www.pudn.com > commutil.zip > FUTILITY.CPP
// ******************************************************************** //
// //
// FUTILITY.CPP //
// Copyright (c) 1993, Michael Holmes and Bob Flanders //
// C++ Communication Utilities //
// //
// This file contains the following miscellaneous routines. //
// quit_with() give an error message, then return to DOS //
// status_line() display status line //
// malloc_chk() allocate memory with error checks //
// clear_memory() clear a large block of memory //
// wait() wait for a give number timer ticks //
// wait_ms() wait in milliseconds //
// first_nonblank() find first non-blank character //
// field_edit() edit a field in a window //
// set_bits() set on a string of bits //
// get_bit() get a bit from a string of bits //
// get_bits() get a bunch of bits from a string of bits //
// reverse_scan() scan a area backwards //
// trim() trim trailing blanks //
// control_break() control break intercept routine //
// critical_rtn() DOS critical error handler //
// //
// ******************************************************************** //
/* ******************************************************************** *
*
* quit_with() -- give an error message, then return to DOS
*
* ******************************************************************** */
void quit_with(char *msg, ...) // quit with an error message
{
va_list list; // variable list
if (full_screen) // q. in full screen mode?
{
term->Close(); // a. yes .. close term window
window(1, 1, 80, max_lines); // set up termination screen
textcolor(FG(mono_1)); // ..with foreground
textbackground(BG(mono_1)); // ..and background colors
clrscr(); // ..and clear screen
CURSOR(); // ..and set cursor to normal
printf(copyright); // display program banner
}
_dos_setvect(0x1b, old_break); // restore old ^break handler
va_start(list, msg); // set up variable list
vprintf(msg, list); // give error message ..
exit(rc); // ..and then quit
}
/* ******************************************************************** *
*
* status_line() -- update the status line
*
* ******************************************************************** */
void status_line(char *msg, ...) // message to format/display
{
char buf[100]; // string buffer
va_list list; // variable list
window(1, 25, 80, 25); // set up status window
_wrapon(_GWRAPOFF); // disable scrolling
textcolor(FG(stat_cn)); // set up foreground
textbackground(BG(stat_cn)); // ..and background colors
va_start(list, msg); // set up variable list
vsprintf(buf, msg, list); // ..format buffer
cprintf(buf); // ..then display message
last_window = 0; // clear last window accessed
window(1, 1, 80, 25); // ..and reset for full screen
}
/* ******************************************************************** *
*
* malloc_chk() -- allocate memory with error processing
*
* ******************************************************************** */
void *malloc_chk(long n) // size of block
{
void *p; // temporary pointer
if (n > 65535L) // q. big area?
p = (void *) _halloc((n + 1) / 2, 2); // a. yes .. get big memory
else
p = (void *) _fmalloc(n); // else .. get regular memory
if (NOT p) // q. enough memory?
quit_with(no_memory); // a. no .. give error msg
return(p); // else .. return w/address
}
/* ******************************************************************** *
*
* clear_memory() -- clear a big block of memory
*
* ******************************************************************** */
void clear_memory(char *s, // area to clear
char c, // character to clear to
long size) // length to clear
{
char huge *p; // huge work pointer
UINT clr_size = 0; // working size
for (p = s; size; size -= clr_size) // clear in big chunks
{
if (size > (65536L - 16)) // q. more than 64k to do?
clr_size = (UINT) 65536L - 16; // a. yes .. just do some
else
clr_size = (UINT) size; // else .. do what's left
memset((char *) p, c, (UINT) clr_size); // clear to block to null
p += clr_size; // point to next block
}
}
/* ******************************************************************** *
*
* wait() -- wait for a given number of timer ticks
*
* ******************************************************************** */
void wait(long n) // time to wait in ticks
{
long far *timer = (long far *) // BIOS timer tick counter
MK_FP(0x40, 0x6c), // ..down in low memory
start, work; // start tick count
start = *timer; // get current time
while (n > 0) // loop 'til n ticks past
{
if ((work = *timer) != start) // q. time pass?
{ // a. yes .. see how much
if (work < start) // q. clock go past midnite?
n--; // a. yes .. count as 1 tick
else
n -= (UINT)(work - start); // else .. count everything
start = work; // start again w/curr time
}
else
kbhit(); // else .. check keyboard
}
}
/* ******************************************************************** *
*
* wait_ms() -- wait in milliseconds
*
* ******************************************************************** */
void wait_ms(long ms) // milliseconds to wait
{
wait((ms + 54) / 55); // convert then wait in ticks
}
/* ******************************************************************** *
*
* first_nonblank() -- find first non-blank character
*
* ******************************************************************** */
char *first_nonblank(char *s) // string to look through
{
for (; *s; s++) // loop thru string
if (NOT isspace(*s)) // q. find a non-blank char?
return(s); // a. yes .. return w/address
return(0); // else .. string is blank
}
/* ******************************************************************** *
*
* field_edit() -- edit a string field in a window
*
* ******************************************************************** */
int field_edit(Window *win, // window to work in
int c, int r, // initial column and row
char **s, // initial field data
int m) // maximum field length
{
int i, // string index
k, // keyboard input
x, // current column
ins; // insert flag
char *org, // original string pointer
*w, // work string pointer
b[80]; // work buffer
org = *s; // get initial field data
w = (char *) malloc_chk(m + 1); // allocate work string
memset(w, ' ', m); // clear to blanks
w[m] = 0; // ..and make a string
ins = 0; // clear insert flag
if (org) // q. orig data available?
strncpy(w, org, strlen(org)); // a. yes .. copy to work
CURSOR(); // turn cursor on
win->AtSayReverse(c, r, w); // ..display field
win->GotoXY(x = c, r); // locate start of field
while (1) // loop till user quits
{
while (NOT (k = get_key(NO_ALT))) // wait for a key
; // ..before continuing
switch (k) // handle user's input
{
case LEFT: // left key
if (--x < c) // q. past left margin?
x = c; // a. yes .. reset
break; // ..then get next key
case RIGHT: // right key
if (++x >= (m + c - 1)) // q. past right margin?
x = m + c - 1; // a. yes .. reset
break; // ..then get next key
case BACKSPACE: // backspace
if (x == c) // q. at top of window?
{
printf(BELL); // a. yes .. give warning
break; // ..and wait for another..
}
x--; // move left one character
// ..and fall into delete key
case DELETE: // delete key
i = x - c; // set up string index
strcpy(&w[i], &w[i + 1]); // simulate delete
w[m - 1] = ' '; // ..and put a blank at end
sprintf(b, "%s", &w[i]); // make into string
win->AtSayReverse(x, r, b); // ..display remainder
break; // ..and wait for next key
case HOME: // home key
x = c; // reset pointer to start
break; // ..and wait for next key
case END: // end key
x = c + m - 1; // reset pointer to end
break; // ..and wait for next key
case CR: // carriage return
case UP: // up arrow key
case DOWN: // down arrow key
NOCURSOR(); // turn cursor off
free(org); // release original data
*s = w; // store addr of new data
win->AtSay(c, r, w); // ..display field normally
return(DOWN); // ..then return to caller
case ESC: // escape key
NOCURSOR(); // turn cursor off
win->AtSay(c, r, w); // ..display field normally
free(w); // release work copy
return(0); // ..then return to caller
case INSERT: // insert toggle
if (ins) // q. insert mode active?
{
ins = 0; // a. yes .. turn it off
CURSOR(); // ..and use proper cursor
}
else
{
ins = 1; // else .. set on insert
BIGCURSOR(); // ..and show insert cursor
}
break; // then wait for next key
default: // error case
if (k & 0xff00 || // q. function key..
k < ' ') // ..or less than a blank?
{
printf(BELL); // a. yes .. ring the bell
break; // ..and wait for next key
}
i = x - c; // get string index
if (ins) // q. insert mode active?
{
memmove(&w[i + 1], &w[i], // a. yes .. move everything
m - i); // ..for the remainder over
w[m] = 0; // ..and overlay the overflow
w[i] = (char) k; // put new char its place
sprintf(b, "%s", &w[i]); // make into a displayable
}
else
{
w[i] = (char) k; // save character in string
sprintf(b, "%c", k); // make into a string
}
win->AtSayReverse(x, r, b); // display new char/string
if (i < (m - 1)) // q. upto right margin?
x++; // a. no .. advance one
break; // ..then get next key
}
win->GotoXY(x, r); // ..then go there
}
return(0); // keep MSC C/C++ happy
}
/* ******************************************************************** *
*
* set_bits() -- set on a string of bits
*
* ******************************************************************** */
void set_bits(char huge *s, // target string
int n, // starting bit nbr (0 based)
int l) // length of bits
{
char mask; // work mask
int f; // first bit number
if (NOT l) // q. zero length?
return; // a. yes .. then just return
s += n / 8; // get to 1st target byte
f = n % 8; // bit within byte
mask = 0xff >> f; // initial mask
f = 8 - f; // remaining bits after 1st
if (f >= l) // q. too many already?
{
mask &= (0xff00 >> ((n % 8) + l)); // a. yes .. clear off extras
*s |= mask; // ..set the bits on
return; // ..and return to caller
}
else
*s++ |= mask; // else .. set on first group
for (l -= f; l >= 8; l -= 8) // for each group of 8 bits
*s++ = 0xff; // ..mark all of them on
if (l) // q. any straglers?
*s |= 0xff00 >> l; // a. yes .. turn them on too
}
/* ******************************************************************** *
*
* get_bit() -- get a bit from a string of bits
*
* ******************************************************************** */
UINT get_bit(unsigned char huge *s, // target string
int n) // starting bit nbr (0 based)
{
return((s[n / 8] >> (7 - (n % 8))) & 1); // return with requested bit
}
/* ******************************************************************** *
*
* get_bits() -- get a string of bits
*
* ******************************************************************** */
UINT get_bits(unsigned char huge *s, // target string
int n, // starting bit nbr (0 based)
int l) // length of bits
{
UINT x; // bits from bit string
if (NOT l || l > 16) // q. too much or too little?
return(0); // a. yes .. then just return
for (x = 0; l--; n++) // while there is work to do
x = (x << 1) | get_bit(s, n); // ..get another bit
return(x); // finally, return to caller
}
/* ******************************************************************** *
*
* reverse_scan() -- backscan for dissimilar character
*
* ******************************************************************** */
char *reverse_scan(char *p, // starting point
char c, // character to scan against
int len) // length of search
{
for (p += len - 1; len--; p--) // loop thru memory
if (*p != c) // q. find last one?
return(p); // a. yes .. return w/address
return(0); // else .. return empty handed
}
/* ******************************************************************** *
*
* trim() -- trim trailing blanks
*
* ******************************************************************** */
char *trim(char *s) // source and target string
{
char *p; // work pointer
for (p = s + strlen(s) - 1; // starting at the end..
*p == ' ' && p > s; p--) // ..work backwards
;
*(++p) = 0; // set in new terminator
return(s); // ..and return w/source
}
/* ******************************************************************** *
*
* control_break() -- control break intercept routine
*
* ******************************************************************** */
void interrupt far control_break(void)
{
_asm mov al, 20 // al = end of interrupt cmd
_asm out 20, al // clear kb interrupt on 8259
}
/* ******************************************************************** *
*
* critical_rtn() -- DOS critical error handler
*
* ******************************************************************** */
void interrupt far critical_routine(void)
{
_asm
{
mov al, 0x03 // al = fail request rtn code
test ah, 0x80 // q. fail allowed?
jnz Done // a. yes .. just return
mov al, 0x02 // al = abort request rtn code
Done:
}
}