FUTILITY.CPP
上传用户:xr_qian
上传日期:2007-01-05
资源大小:443k
文件大小:20k
源码类别:

通讯/手机编程

开发平台:

DOS

  1. // ******************************************************************** //
  2. //                                                                      //
  3. //      FUTILITY.CPP                                                    //
  4. //      Copyright (c) 1993, Michael Holmes and Bob Flanders             //
  5. //      C++ Communication Utilities                                     //
  6. //                                                                      //
  7. //      This file contains the following miscellaneous routines.        //
  8. //          quit_with()      give an error message, then return to DOS  //
  9. //          status_line()    display status line                        //
  10. //          malloc_chk()     allocate memory with error checks          //
  11. //          clear_memory()   clear a large block of memory              //
  12. //          wait()           wait for a give number timer ticks         //
  13. //          wait_ms()        wait in milliseconds                       //
  14. //          first_nonblank() find first non-blank character             //
  15. //          field_edit()     edit a field in a window                   //
  16. //          set_bits()       set on a string of bits                    //
  17. //          get_bit()        get a bit from a string of bits            //
  18. //          get_bits()       get a bunch of bits from a string of bits  //
  19. //          reverse_scan()   scan a area backwards                      //
  20. //          trim()           trim trailing blanks                       //
  21. //          control_break()  control break intercept routine            //
  22. //          critical_rtn()   DOS critical error handler                 //
  23. //                                                                      //
  24. // ******************************************************************** //
  25. /* ******************************************************************** *
  26.  *
  27.  *  quit_with() -- give an error message, then return to DOS
  28.  *
  29.  * ******************************************************************** */
  30. void    quit_with(char *msg, ...)           // quit with an error message
  31. {
  32. va_list list;                               // variable list
  33. if (full_screen)                            // q. in full screen mode?
  34.     {
  35.     term->Close();                          // a. yes .. close term window
  36.     window(1, 1, 80, max_lines);            // set up termination screen
  37.     textcolor(FG(mono_1));                  // ..with foreground
  38.     textbackground(BG(mono_1));             // ..and background colors
  39.     clrscr();                               // ..and clear screen
  40.     CURSOR();                               // ..and set cursor to normal
  41.     printf(copyright);                      // display program banner
  42.     }
  43. _dos_setvect(0x1b, old_break);              // restore old ^break handler
  44. va_start(list, msg);                        // set up variable list
  45. vprintf(msg, list);                         // give error message ..
  46. exit(rc);                                   // ..and then quit
  47. }
  48. /* ******************************************************************** *
  49.  *
  50.  *  status_line() -- update the status line
  51.  *
  52.  * ******************************************************************** */
  53. void    status_line(char *msg, ...)         // message to format/display
  54. {
  55. char    buf[100];                           // string buffer
  56. va_list list;                               // variable list
  57. window(1, 25, 80, 25);                      // set up status window
  58. _wscroll = 0;                               // disable scrolling
  59. textcolor(FG(stat_cn));                     // set up foreground
  60. textbackground(BG(stat_cn));                // ..and background colors
  61. va_start(list, msg);                        // set up variable list
  62. vsprintf(buf, msg, list);                   // ..format buffer
  63. cprintf(buf);                               // ..then display message
  64. last_window = 0;                            // clear last window accessed
  65. window(1, 1, 80, 25);                       // ..and reset for full screen
  66. }
  67. /* ******************************************************************** *
  68.  *
  69.  *  malloc_chk() -- allocate memory with error processing
  70.  *
  71.  * ******************************************************************** */
  72. void   *malloc_chk(long n)                  // size of block
  73. {
  74. void    *p;                                 // temporary pointer
  75. if (NOT (p = (void *) _fmalloc(n)))         // q. enough memory?
  76.     quit_with(no_memory);                   // a. no .. give error msg
  77. return(p);                                  // else .. return w/address
  78. }
  79. /* ******************************************************************** *
  80.  *
  81.  *  clear_memory() -- clear a big block of memory
  82.  *
  83.  * ******************************************************************** */
  84. void    clear_memory(char *s,               // area to clear
  85.                      char c,                // character to clear to
  86.                      long size)             // length to clear
  87. {
  88. char    huge *p;                            // huge work pointer
  89. UINT    clr_size = 0;                       // working size
  90. for (p = s; size; size -= clr_size)         // clear in big chunks
  91.     {
  92.     if (size > (65536L - 16))               // q. more than 64k to do?
  93.         clr_size = (UINT) 65536L - 16;      // a. yes .. just do some
  94.      else
  95.         clr_size = (UINT) size;             // else .. do what's left
  96.     memset((char *) p, c, (UINT) clr_size); // clear to block to null
  97.     p += clr_size;                          // point to next block
  98.     }
  99. }
  100. /* ******************************************************************** *
  101.  *
  102.  *  wait() -- wait for a given number of timer ticks
  103.  *
  104.  * ******************************************************************** */
  105. void    wait(long n)                        // time to wait in ticks
  106. {
  107. long    far *timer = (long far *)           // BIOS timer tick counter
  108.                         MK_FP(0x40, 0x6c),  // ..down in low memory
  109.         start, work;                        // start tick count
  110. start = *timer;                             // get current time
  111. while (n > 0)                               // loop 'til n ticks past
  112.     {
  113.     if ((work = *timer) != start)           // q. time pass?
  114.         {                                   // a. yes .. see how much
  115.         if (work < start)                   // q. clock go past midnite?
  116.             n--;                            // a. yes .. count as 1 tick
  117.          else
  118.             n -= (UINT)(work - start);      // else .. count everything
  119.         start = work;                       // start again w/curr time
  120.         }
  121.      else
  122.         kbhit();                            // else .. check keyboard
  123.     }
  124. }
  125. /* ******************************************************************** *
  126.  *
  127.  *  wait_ms() -- wait in milliseconds
  128.  *
  129.  * ******************************************************************** */
  130. void    wait_ms(long ms)                    // milliseconds to wait
  131. {
  132. wait((ms + 54) / 55);                       // convert then wait in ticks
  133. }
  134. /* ******************************************************************** *
  135.  *
  136.  *  first_nonblank() -- find first non-blank character
  137.  *
  138.  * ******************************************************************** */
  139. char    *first_nonblank(char *s)            // string to look through
  140. {
  141. for (; *s; s++)                             // loop thru string
  142.     if (NOT isspace(*s))                    // q. find a non-blank char?
  143.         return(s);                          // a. yes .. return w/address
  144. return(0);                                  // else .. string is blank
  145. }
  146. /* ******************************************************************** *
  147.  *
  148.  *  field_edit() -- edit a string field in a window
  149.  *
  150.  * ******************************************************************** */
  151. int     field_edit(Window *win,             // window to work in
  152.                    int  c, int r,           // initial column and row
  153.                    char **s,                // initial field data
  154.                    int  m)                  // maximum field length
  155. {
  156. int     i,                                  // string index
  157.         k,                                  // keyboard input
  158.         x,                                  // current column
  159.         ins;                                // insert flag
  160. char   *org,                                // original string pointer
  161.        *w,                                  // work string pointer
  162.         b[80];                              // work buffer
  163. org = *s;                                   // get initial field data
  164. w = (char *) malloc_chk(m + 1);             // allocate work string
  165. memset(w, ' ', m);                          // clear to blanks
  166. w[m] = 0;                                   // ..and make a string
  167. ins = 0;                                    // clear insert flag
  168. if (org)                                    // q. orig data available?
  169.     strncpy(w, org, strlen(org));           // a. yes .. copy to work
  170. CURSOR();                                   // turn cursor on
  171. win->AtSayReverse(c, r, w);                 // ..display field
  172. win->GotoXY(x = c, r);                      // locate start of field
  173. while (1)                                   // loop till user quits
  174.     {
  175.     while (NOT (k = get_key(NO_ALT)))       // wait for a key
  176.         ;                                   // ..before continuing
  177.     switch (k)                              // handle user's input
  178.         {
  179.         case LEFT:                          // left key
  180.             if (--x < c)                    // q. past left margin?
  181.                 x = c;                      // a. yes .. reset
  182.             break;                          // ..then get next key
  183.         case RIGHT:                         // right key
  184.             if (++x >= (m + c - 1))         // q. past right margin?
  185.                 x = m + c - 1;              // a. yes .. reset
  186.             break;                          // ..then get next key
  187.         case BACKSPACE:                     // backspace
  188.             if (x == c)                     // q. at top of window?
  189.                 {
  190.                 printf(BELL);               // a. yes .. give warning
  191.                 break;                      // ..and wait for another..
  192.                 }
  193.             x--;                            // move left one character
  194.                                             // ..and fall into delete key
  195.         case DELETE:                        // delete key
  196.             i = x - c;                      // set up string index
  197.             strcpy(&w[i], &w[i + 1]);       // simulate delete
  198.             w[m - 1] = ' ';                 // ..and put a blank at end
  199.             sprintf(b, "%s", &w[i]);        // make into string
  200.             win->AtSayReverse(x, r, b);     // ..display remainder
  201.             break;                          // ..and wait for next key
  202.         case HOME:                          // home key
  203.             x = c;                          // reset pointer to start
  204.             break;                          // ..and wait for next key
  205.         case END:                           // end key
  206.             x = c + m - 1;                  // reset pointer to end
  207.             break;                          // ..and wait for next key
  208.         case CR:                            // carriage return
  209.         case UP:                            // up arrow key
  210.         case DOWN:                          // down arrow key
  211.             NOCURSOR();                     // turn cursor off
  212.             free(org);                      // release original data
  213.             *s = w;                         // store addr of new data
  214.             win->AtSay(c, r, w);            // ..display field normally
  215.             return(DOWN);                   // ..then return to caller
  216.         case ESC:                           // escape key
  217.             NOCURSOR();                     // turn cursor off
  218.             win->AtSay(c, r, w);            // ..display field normally
  219.             free(w);                        // release work copy
  220.             return(0);                      // ..then return to caller
  221.         case INSERT:                        // insert toggle
  222.             if (ins)                        // q. insert mode active?
  223.                 {
  224.                 ins = 0;                    // a. yes .. turn it off
  225.                 CURSOR();                   // ..and use proper cursor
  226.                 }
  227.              else
  228.                 {
  229.                 ins = 1;                    // else .. set on insert
  230.                 BIGCURSOR();                // ..and show insert cursor
  231.                 }
  232.             break;                          // then wait for next key
  233.         default:                            // error case
  234.             if (k & 0xff00 ||               // q. function key..
  235.                         k < ' ')            // ..or less than a blank?
  236.                 {
  237.                 printf(BELL);               // a. yes .. ring the bell
  238.                 break;                      // ..and wait for next key
  239.                 }
  240.             i = x - c;                      // get string index
  241.             if (ins)                        // q. insert mode active?
  242.                 {
  243.                 memmove(&w[i + 1], &w[i],   // a. yes .. move everything
  244.                         m - i);             // ..for the remainder over
  245.                 w[m] = 0;                   // ..and overlay the overflow
  246.                 w[i] = (char) k;            // put new char its place
  247.                 sprintf(b, "%s", &w[i]);    // make into a displayable
  248.                 }
  249.              else
  250.                 {
  251.                 w[i] = (char) k;            // save character in string
  252.                 sprintf(b, "%c", k);        // make into a string
  253.                 }
  254.             win->AtSayReverse(x, r, b);     // display new char/string
  255.             if (i < (m - 1))                // q. upto right margin?
  256.                 x++;                        // a. no .. advance one
  257.             break;                          // ..then get next key
  258.         }
  259.     win->GotoXY(x, r);                      // ..then go there
  260.     }
  261. }
  262. /* ******************************************************************** *
  263.  *
  264.  *  set_bits() -- set on a string of bits
  265.  *
  266.  * ******************************************************************** */
  267. void    set_bits(char *s,                   // target string
  268.                  int   n,                   // starting bit nbr (0 based)
  269.                  int   l)                   // length of bits
  270. {
  271. char    mask;                               // work mask
  272. int     f;                                  // first bit number
  273. if (NOT l)                                  // q. zero length?
  274.     return;                                 // a. yes .. then just return
  275. s += n / 8;                                 // get to 1st target byte
  276. f = n % 8;                                  // bit within byte
  277. mask = 0xff >> f;                           // initial mask
  278. f = 8 - f;                                  // remaining bits after 1st
  279. if (f >= l)                                 // q. too many already?
  280.     {
  281.     mask &= (0xff00 >> ((n % 8) + l));      // a. yes .. clear off extras
  282.     *s |= mask;                             // ..set the bits on
  283.     return;                                 // ..and return to caller
  284.     }
  285.  else
  286.     *s++ |= mask;                           // else .. set on first group
  287. for (l -= f; l >= 8; l -= 8)                // for each group of 8 bits
  288.     *s++ = 0xff;                            // ..mark all of them on
  289. if (l)                                      // q. any straglers?
  290.     *s |= 0xff00 >> l;                      // a. yes .. turn them on too
  291. }
  292. /* ******************************************************************** *
  293.  *
  294.  *  get_bit() -- get a bit from a string of bits
  295.  *
  296.  * ******************************************************************** */
  297. UINT    get_bit(unsigned char *s,           // target string
  298.                 int   n)                    // starting bit nbr (0 based)
  299. {
  300. return((s[n / 8] >> (7 - (n % 8))) & 1);    // return with requested bit
  301. }
  302. /* ******************************************************************** *
  303.  *
  304.  *  get_bits() -- get a string of bits
  305.  *
  306.  * ******************************************************************** */
  307. UINT    get_bits(unsigned char *s,          // target string
  308.                  int   n,                   // starting bit nbr (0 based)
  309.                  int   l)                   // length of bits
  310. {
  311. UINT    x;                                  // bits from bit string
  312. if (NOT l || l > 16)                        // q. too much or too little?
  313.     return(0);                              // a. yes .. then just return
  314. for (x = 0; l--; n++)                       // while there is work to do
  315.     x = (x << 1) | get_bit(s, n);           // ..get another bit
  316. return(x);                                  // finally, return to caller
  317. }
  318. /* ******************************************************************** *
  319.  *
  320.  *  reverse_scan() -- backscan for dissimilar character
  321.  *
  322.  * ******************************************************************** */
  323. char   *reverse_scan(char *p,               // starting point
  324.                      char c,                // character to scan against
  325.                      int  len)              // length of search
  326. {
  327. for (p += len - 1; len--; p--)              // loop thru memory
  328.     if (*p != c)                            // q. find last one?
  329.         return(p);                          // a. yes .. return w/address
  330. return(0);                                  // else .. return empty handed
  331. }
  332. /* ******************************************************************** *
  333.  *
  334.  *  trim() -- trim trailing blanks
  335.  *
  336.  * ******************************************************************** */
  337. char   *trim(char *s)                       // source and target string
  338. {
  339. char   *p;                                  // work pointer
  340. for (p = s + strlen(s) - 1;                 // starting at the end..
  341.             *p == ' ' && p > s; p--)        // ..work backwards
  342.     ;
  343. *(++p) = 0;                                 // set in new terminator
  344. return(s);                                  // ..and return w/source
  345. }
  346. /* ******************************************************************** *
  347.  *
  348.  *  control_break() -- control break intercept routine
  349.  *
  350.  * ******************************************************************** */
  351. #pragma option -O2-b-e                      // no global reg allocation
  352.                                             // ..or dead code elimination
  353. void    interrupt control_break(...)
  354. {
  355.  asm    mov al, 20                          // al = end of interrupt cmd
  356.  asm    out 20, al                          // clear kb interrupt on 8259
  357. }
  358. /* ******************************************************************** *
  359.  *
  360.  *  critical_rtn() -- DOS critical error handler
  361.  *
  362.  * ******************************************************************** */
  363. #pragma option -O2-b-e                      // no global reg allocation
  364.                                             // ..or dead code elimination
  365. void    interrupt critical_routine(...)
  366. {
  367. if (_AX & 0x800)                            // q. fail allowed?
  368.     _AX = (_AX & 0xff00) | 3;               // a. yes .. show failed
  369.  else
  370.     _AX = (_AX & 0xff00) | 2;               // else .. abort
  371. }