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

通讯/手机编程

开发平台:

DOS

  1. // ******************************************************************** //
  2. //                                                                      //
  3. //      UTILITY.CPP                                                     //
  4. //      Copyright (c) 1993, Michael Holmes and Bob Flanders             //
  5. //      C++ Communication Utilities                                     //
  6. //                                                                      //
  7. //      Chapter 7: Receiving a FAX                                      //
  8. //      Last changed in chapter 7                                       //
  9. //                                                                      //
  10. //      This file contains the following miscellaneous routines.        //
  11. //          status_line()       update the status line                  //
  12. //          build_comm()        build comm instance                     //
  13. //          terminal_handler()  handle special terminal keys            //
  14. //          terminal_display()  display comm input stream               //
  15. //          first_nonblank()    find first non-blank character          //
  16. //          ascii_encode()      encode string w/control characters      //
  17. //          quit_with()         give an error message, then rtn to DOS  //
  18. //          get_time()          retrieve time of day in ticks           //
  19. //          elapsed_time()      calculate elapsed time in ticks         //
  20. //          time_out()          check for a timeout situation           //
  21. //          wait()              wait for a given number timer ticks     //
  22. //          wait_ms()           wait in milliseconds                    //
  23. //          malloc_chk()        allocate memory with error checks       //
  24. //          field_edit()        edit a field in a window                //
  25. //          delete_file()       delete file any way possible            //
  26. //          pad()               pad a string to a length                //
  27. //          touppers()          translate string to uppercase           //
  28. //          control_break()     control break intercept routine         //
  29. //          critical_rtn()      DOS critical error handler              //
  30. //                                                                      //
  31. // ******************************************************************** //
  32. #define TICKS_DAY 1573040L                  // number of ticks per day
  33. /* ******************************************************************** *
  34.  *
  35.  *  status_line() -- update the status line
  36.  *
  37.  * ******************************************************************** */
  38. void    status_line(void)
  39. {
  40. char    msr;                                // modem status register
  41. window(1, 25, 80, 25);                      // set up status window
  42. _wscroll = 0;                               // disable scrolling
  43. textcolor(FG(stat_cn));                     // set up foreground
  44. textbackground(BG(stat_cn));                // ..and background colors
  45. msr = comm->Modem();                        // get modem status register
  46. cprintf(stat_format,                        // write current status line
  47.     com_ports[comport].name,                // ..including selected port
  48.     line[SPEED].lp->parm,                   // ..selected baud rate
  49.     line[DATA].lp->parm,                    // ..data bits
  50.     line[PARITY].lp->parm,                  // ..parity
  51.     line[STOP].lp->parm,                    // ..and stop bits
  52.     msr & MSR_CD  ? "CD" : "  ",            // ..carrier detect
  53.     msr & MSR_CTS ? "CTS" : "   ",          // ..clear to send
  54.     comm->IFlow() ? "   " : "RTS");         // ..request to send
  55. last_window = 0;                            // clear last window accessed
  56. window(1, 1, 80, 25);                       // ..and reset for full screen
  57. }
  58. /* ******************************************************************** *
  59.  *
  60.  *  build_comm() -- build comm instance with current parameters
  61.  *
  62.  * ******************************************************************** */
  63. void    build_comm()
  64. {
  65. if (comm)                                   // q. using a port already?
  66.     comm->~Comm();                          // a. yes .. close it down
  67. comm = new Comm(                            // build a Comm instance
  68.     com_ports[comport].port,                // ..with base port address
  69.     com_ports[comport].irq,                 // ..and interrupt number
  70.     line[SPEED].lp->value,                  // ..baud rate divisor
  71.     line[PARITY].lp->value |                // ..line control values
  72.     line[DATA].lp->value |                  // ..including parity,
  73.     line[STOP].lp->value,                   // ..data and stop bits
  74.     flowctl, 4096, 512);                    // ..and flow control flag
  75. comm->Write(CMD_EXECUTE);                   // execute previous command
  76. wait_ms(250);                               // .. let it execute
  77. comm->Write(CMD_EXECUTE);                   // .. and.. kill it.
  78. comm->Write(CMD_INIT);                      // send modem init string
  79. comm->Write(CMD_EXECUTE);                   // .. execute init command
  80. }
  81. /* ******************************************************************** *
  82.  *
  83.  *  terminal_handler() -- handle terminal input
  84.  *
  85.  * ******************************************************************** */
  86. void    terminal_handler(void)
  87. {
  88. int     key;                                // extended keyboard character
  89. if (comm->ModemChanged())                   // q. time to update status?
  90.     {
  91.     status_line();                          // a. yes .. do a status update
  92.     term->MakeCurrent();                    // ..and reposition cursor
  93.     }
  94. if ((key = get_key(ALLOW_ALT)) == 0)        // q. get a valid key?
  95.     return;                                 // a. no .. just return
  96. if (key >= 0x100)                           // q. alt or function key?
  97.     {                                       // a. yes .. check validity
  98.     if (main_menu.ValidateKey(key))         // q. valid for main menu?
  99.         {
  100.         main_menu.Display(key);             // a. yes .. display menu
  101.         term->MakeCurrent();                // reposition cursor
  102.         return;                             // ..then return to caller
  103.         }
  104.     }
  105. switch (key)                                // handle special keys
  106.     {
  107.     case F1:                                // clear screen request
  108.         term->Clear();                      // clear terminal window
  109.         break;                              // ..and continue
  110.     default:
  111.         if (key >= 0x100)                   // q. special key?
  112.             {
  113.             printf(BELL);                   // a. yes .. give error beep
  114.             break;                          // ..and continue
  115.             }
  116.         comm->Write(key);                   // else .. send out com port
  117.     }
  118. }
  119. /* ******************************************************************** *
  120.  *
  121.  *  terminal_display() -- display comm input stream
  122.  *
  123.  * ******************************************************************** */
  124. void    terminal_display(void)
  125. {
  126. int     i;                                  // loop counter
  127. char    c,                                  // input character
  128.         msr,                                // modem status register
  129.         lsr,                                // line status register
  130.         buf[40];                            // work buffer
  131. if ((i = comm->Read(&c, &msr, &lsr)) == -1) // q. get a comm character?
  132.     return;                                 // a. no .. just return
  133. if (i)                                      // q. buffer overflow?
  134.     {
  135.     sprintf(buf, overflow_msg, i);          // a. yes .. prepare msg
  136.     term->DisplayReverse(buf);              // ..and give to user
  137.     return;                                 // ..then return to caller
  138.     }
  139. if ((lsr &= LSR_ERROR) != 0)                // q. any errors?
  140.     for (i = 0, lsr >>= 1; lsr;             // a. yes .. loop thru and
  141.             i++, lsr >>= 1)                 // ..display error messages
  142.         if (lsr & 1)                        // q. recognize this error?
  143.             term->DisplayReverse(           // a. yes .. display error msg
  144.                     line_error[i]);         // ..from message table
  145. if (c)                                      // q. null character?
  146.     term->Display(c);                       // a. no .. display character
  147. }
  148. /* ******************************************************************** *
  149.  *
  150.  *  first_nonblank() -- find first non-blank character
  151.  *
  152.  * ******************************************************************** */
  153. char    *first_nonblank(char *s)            // string to look through
  154. {
  155. for (; *s; s++)                             // loop thru string
  156.     if (NOT isspace(*s))                    // q. find a non-blank char?
  157.         return(s);                          // a. yes .. return w/address
  158. return(0);                                  // else .. string is blank
  159. }
  160. /* ******************************************************************** *
  161.  *
  162.  *  ascii_encode() -- encode string w/control characters
  163.  *
  164.  * ******************************************************************** */
  165. char    *ascii_encode(char *s)              // string to encode
  166. {
  167. char    *p, *q;                             // work pointers
  168. for (p = q = s;                             // work across input string
  169.              *s == ' ' || *s == '='; s++)   // ..skipping leading blanks
  170.     ;                                       // ..and delimiting equals
  171. for (; *s; s++)                             // work across rest of the
  172.     {                                       // ..input string
  173.     if (*s == ';')                          // q. hit start of comment?
  174.         break;                              // a. yes .. exit loop
  175.     if (*s != '^')                          // q. control character?
  176.         {
  177.         *p++ = *s;                          // a. no .. just copy
  178.         continue;                           // ..and process next one
  179.         }
  180.     s++;                                    // move on to next input char
  181.     if (*s == '^' || *s == ';')             // q. special characters?
  182.         {
  183.         *p++ = *s;                          // a. yes .. just copy
  184.         continue;                           // ..and process next one
  185.         }
  186.     *p++ = *s & 0x1f;                       // make into control char
  187.     }
  188. *p = '';                                  // terminate encoded string
  189. return(q);                                  // ..and return string addr
  190. }
  191. /* ******************************************************************** *
  192.  *
  193.  *  quit_with() -- give an error message, then return to DOS
  194.  *
  195.  * ******************************************************************** */
  196. void    quit_with(char *msg, ...)           // quit with an error message
  197. {
  198. va_list list;                               // variable list
  199. if (full_screen)                            // q. in full screen mode?
  200.     {
  201.     term->Close();                          // a. yes .. close term window
  202.     window(1, 1, 80, max_lines);            // set up termination screen
  203.     textcolor(FG(mono_1));                  // ..with foreground
  204.     textbackground(BG(mono_1));             // ..and background colors
  205.     clrscr();                               // ..and clear screen
  206.     CURSOR();                               // ..and set cursor to normal
  207.     printf(copyright);                      // display program banner
  208.     }
  209. if (comm)                                   // q. comm object created?
  210.     comm->~Comm();                          // a. yes .. call destructor
  211. _dos_setvect(0x1b, old_break);              // restore old ^break handler
  212. va_start(list, msg);                        // set up variable list
  213. vprintf(msg, list);                         // give error message ..
  214. exit(rc);                                   // ..and then quit
  215. }
  216. /* ******************************************************************** *
  217.  *
  218.  *  time_out() -- check for a timeout event
  219.  *
  220.  * ******************************************************************** */
  221. int     time_out(long *n)                   // time to wait in ticks
  222. {
  223. static  unsigned
  224. long    far *timer = (unsigned long far *)  // BIOS timer tick counter
  225.                         MK_FP(0x40, 0x6c),  // ..down in low memory
  226.         last,                               // last accessed time
  227.         work;                               // work variable
  228. work = *timer;                              // get current time
  229. if (*n > 0)                                 // q. first time call?
  230.     {
  231.     *n = -*n;                               // a. yes .. change sign
  232.     last = work;                            // ..and initialize counters
  233.     }
  234. if (work != last)                           // q. time pass?
  235.     {                                       // a. yes .. see how much
  236.     if (work <= last)                       // q. clock go past midnite?
  237.         (*n)++;                             // a. yes .. count as 1 tick
  238.      else
  239.         *n += (UINT)(work - last);          // else .. count everything
  240.     last = work;                            // start again w/curr time
  241.     }
  242. return(*n >= 0L);                           // return TRUE at timeout time
  243. }
  244. /* ******************************************************************** *
  245.  *
  246.  *  get_time() -- retrieve the time in ticks
  247.  *
  248.  * ******************************************************************** */
  249. ULONG   get_time(void)                      // retrieve time in ticks
  250. {
  251. static
  252. ULONG   far *timer = (unsigned long far *)  // BIOS timer tick counter
  253.                         MK_FP(0x40, 0x6c);  // ..down in low memory
  254. return(*timer);                             // return current value
  255. }
  256. /* ******************************************************************** *
  257.  *
  258.  *  elapsed_time() -- return elapsed time in ticks
  259.  *
  260.  * ******************************************************************** */
  261. ULONG   elapsed_time(ULONG st)              // start time in ticks
  262. {
  263. static
  264. ULONG   far *timer = (unsigned long far *)  // BIOS timer tick counter
  265.                         MK_FP(0x40, 0x6c);  // ..down in low memory
  266. if (st > *timer)                            // q. start time greater?
  267.    return((TICKS_DAY - st) + *timer);       // a. yes .. add in rollover;
  268. else
  269.    return(*timer - st);                     // return elapsed ticks
  270. }
  271. /* ******************************************************************** *
  272.  *
  273.  *  wait() -- wait for a given number of timer ticks
  274.  *
  275.  * ******************************************************************** */
  276. void    wait(long n)                        // time to wait in ticks
  277. {
  278. long    far *timer = (long far *)           // BIOS timer tick counter
  279.                         MK_FP(0x40, 0x6c),  // ..down in low memory
  280.         start, work;                        // start tick count
  281. start = *timer;                             // get current time
  282. while (n > 0)                               // loop 'til n ticks past
  283.     {
  284.     if ((work = *timer) != start)           // q. time pass?
  285.         {                                   // a. yes .. see how much
  286.         if (work < start)                   // q. clock go past midnite?
  287.             n--;                            // a. yes .. count as 1 tick
  288.          else
  289.             n -= (UINT)(work - start);      // else .. count everything
  290.         start = work;                       // start again w/curr time
  291.         }
  292.      else
  293.         kbhit();                            // else .. check keyboard
  294.     }
  295. }
  296. /* ******************************************************************** *
  297.  *
  298.  *  wait_ms() -- wait in milliseconds
  299.  *
  300.  * ******************************************************************** */
  301. void    wait_ms(long ms)                    // milliseconds to wait
  302. {
  303. wait((ms + 54) / 55);                       // convert then wait in ticks
  304. }
  305. /* ******************************************************************** *
  306.  *
  307.  *  malloc_chk() -- allocate memory with error processing
  308.  *
  309.  * ******************************************************************** */
  310. void    *malloc_chk(int s)                  // size to allocate
  311. {
  312. void    *p;                                 // work pointer
  313. if ((p = malloc(s)) == 0)                   // q. out of memory?
  314.     quit_with(no_memory, s);                // a. yes .. give error msg
  315. return(p);                                  // finally rtn with pointer
  316. }
  317. /* ******************************************************************** *
  318.  *
  319.  *  field_edit() -- edit a string field in a window
  320.  *
  321.  * ******************************************************************** */
  322. int     field_edit(Window *win,             // window to work in
  323.                    int  c, int r,           // initial column and row
  324.                    char **s,                // initial field data
  325.                    int  m)                  // maximum field length
  326. {
  327. int     i,                                  // string index
  328.         k,                                  // keyboard input
  329.         x,                                  // current column
  330.         ins;                                // insert flag
  331. char   *org,                                // original string pointer
  332.        *w,                                  // work string pointer
  333.         b[80];                              // work buffer
  334. org = *s;                                   // get initial field data
  335. w = (char *) malloc_chk(m + 1);             // allocate work string
  336. memset(w, ' ', m);                          // clear to blanks
  337. w[m] = 0;                                   // ..and make a string
  338. ins = 0;                                    // clear insert flag
  339. if (org)                                    // q. orig data available?
  340.     strncpy(w, org, strlen(org));           // a. yes .. copy to work
  341. CURSOR();                                   // turn cursor on
  342. win->AtSayReverse(c, r, w);                 // ..display field
  343. win->GotoXY(x = c, r);                      // locate start of field
  344. for(;;)                                     // loop till user quits
  345.     {
  346.     while (NOT (k = get_key(NO_ALT)))       // wait for a key
  347.         ;                                   // ..before continuing
  348.     switch (k)                              // handle user's input
  349.         {
  350.         case LEFT:                          // left key
  351.             if (--x < c)                    // q. past left margin?
  352.                 x = c;                      // a. yes .. reset
  353.             break;                          // ..then get next key
  354.         case RIGHT:                         // right key
  355.             if (++x >= (m + c - 1))         // q. past right margin?
  356.                 x = m + c - 1;              // a. yes .. reset
  357.             break;                          // ..then get next key
  358.         case BACKSPACE:                     // backspace
  359.             if (x == c)                     // q. at top of window?
  360.                 {
  361.                 printf(BELL);               // a. yes .. give warning
  362.                 break;                      // ..and wait for another..
  363.                 }
  364.             x--;                            // move left one character
  365.                                             // ..and fall into delete key
  366.         case DELETE:                        // delete key
  367.             i = x - c;                      // set up string index
  368.             strcpy(&w[i], &w[i + 1]);       // simulate delete
  369.             w[m - 1] = ' ';                 // ..and put a blank at end
  370.             sprintf(b, "%s", &w[i]);        // make into string
  371.             win->AtSayReverse(x, r, b);     // ..display remainder
  372.             break;                          // ..and wait for next key
  373.         case HOME:                          // home key
  374.             x = c;                          // reset pointer to start
  375.             break;                          // ..and wait for next key
  376.         case END:                           // end key
  377.             x = c + m - 1;                  // reset pointer to end
  378.             break;                          // ..and wait for next key
  379.         case CR:                            // carriage return
  380.         case UP:                            // up arrow key
  381.         case DOWN:                          // down arrow key
  382.             NOCURSOR();                     // turn cursor off
  383.             free(org);                      // release original data
  384.             *s = w;                         // store addr of new data
  385.             win->AtSay(c, r, w);            // ..display field normally
  386.             return(DOWN);                   // ..then return to caller
  387.         case ESC:                           // escape key
  388.             NOCURSOR();                     // turn cursor off
  389.             win->AtSay(c, r, w);            // ..display field normally
  390.             free(w);                        // release work copy
  391.             return(0);                      // ..then return to caller
  392.         case INSERT:                        // insert toggle
  393.             if (ins)                        // q. insert mode active?
  394.                 {
  395.                 ins = 0;                    // a. yes .. turn it off
  396.                 CURSOR();                   // ..and use proper cursor
  397.                 }
  398.              else
  399.                 {
  400.                 ins = 1;                    // else .. set on insert
  401.                 BIGCURSOR();                // ..and show insert cursor
  402.                 }
  403.             break;                          // then wait for next key
  404.         default:                            // error case
  405.             if (k & 0xff00 ||               // q. function key..
  406.                         k < ' ')            // ..or less than a blank?
  407.                 {
  408.                 printf(BELL);               // a. yes .. ring the bell
  409.                 break;                      // ..and wait for next key
  410.                 }
  411.             i = x - c;                      // get string index
  412.             if (ins)                        // q. insert mode active?
  413.                 {
  414.                 memmove(&w[i + 1], &w[i],   // a. yes .. move everything
  415.                         m - i);             // ..for the remainder over
  416.                 w[m] = 0;                   // ..and overlay the overflow
  417.                 w[i] = (char) k;            // put new char its place
  418.                 sprintf(b, "%s", &w[i]);    // make into a displayable
  419.                 }
  420.              else
  421.                 {
  422.                 w[i] = (char) k;            // save character in string
  423.                 sprintf(b, "%c", k);        // make into a string
  424.                 }
  425.             win->AtSayReverse(x, r, b);     // display new char/string
  426.             if (i < (m - 1))                // q. up to right margin?
  427.                 x++;                        // a. no .. advance one
  428.             break;                          // ..then get next key
  429.         }
  430.     win->GotoXY(x, r);                      // ..then go there
  431.     }
  432. }
  433. /* ******************************************************************** *
  434.  *
  435.  *  delete_file() -- delete file any way necessary
  436.  *
  437.  * ******************************************************************** */
  438. int     delete_file(char *s)                // filename to delete
  439. {
  440. int     rc;                                 // return code, 0=ok
  441. if ((rc = unlink(s)) != 0)                  // q. regular unlink work?
  442.     {                                       // a. no .. change attributes
  443.     if (NOT (rc = chmod(s, S_IWRITE)))      // q. change work?
  444.         rc = unlink(s);                     // a. yes .. try delete again
  445.     }
  446. return(rc);                                 // return with final status
  447. }
  448. /* ******************************************************************** *
  449.  *
  450.  *  pad() -- pad a string to a length
  451.  *
  452.  * ******************************************************************** */
  453. void    pad(char *s,                        // target string
  454.             int len)                        // final length
  455. {
  456. int     i;                                  // calculated pad length
  457. i = strlen(s);                              // get current length
  458. if (i < len)                                // q. need padding?
  459.     {
  460.     len -= i;                               // a. yes .. get pad length
  461.     memset(&s[i], ' ', len);                // ..blank out rest
  462.     }
  463. s[len] = 0;                                 // ..and terminate string
  464. }
  465. /* ******************************************************************** *
  466.  *
  467.  *  touppers() -- translate all characters to uppercase
  468.  *
  469.  * ******************************************************************** */
  470. void    touppers(char *s)                   // string to translate
  471. {
  472. while (*s)                                  // for each char in string
  473.       {
  474.       *s = toupper(*s);                     // .. translate to uppercase
  475.       s++;                                  // .. and go to next char
  476.       }
  477. }
  478. /* ******************************************************************** *
  479.  *
  480.  *  control_break() -- control break intercept routine
  481.  *
  482.  * ******************************************************************** */
  483. #pragma option -O2-b-e                      // no global reg allocation
  484.                                             // ..or dead code elimination
  485. void    interrupt control_break(...)
  486. {
  487.  asm    mov al, 20                          // al = end of interrupt cmd
  488.  asm    out 20, al                          // clear kb interrupt on 8259
  489. }
  490. /* ******************************************************************** *
  491.  *
  492.  *  critical_rtn() -- DOS critical error handler
  493.  *
  494.  * ******************************************************************** */
  495. #pragma option -O2-b-e                      // no global reg allocation
  496.                                             // ..or dead code elimination
  497. void    interrupt critical_routine(...)
  498. {
  499. if (_AX & 0x800)                            // q. fail allowed?
  500.     _AX = (_AX & 0xff00) | 3;               // a. yes .. show failed
  501.  else
  502.     _AX = (_AX & 0xff00) | 2;               // else .. abort
  503. }