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: 
    } 
}