home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / ckc072.zip / ckmcon.c < prev    next >
C/C++ Source or Header  |  1988-08-16  |  58KB  |  2,292 lines

  1. /* Paul Placeway, Ohio State -- added option to flashing cursor, made */
  2. /*  key macros use Pascal strings, so that a NUL (0x00) can be sent */
  3. /* Enhanced by Clayton M. Elwell, Ohio State University 24 Nov 1987 -- */
  4. /*  added insert character */
  5. /* Matthias Aebi, ECOFIN Research and Consulting, Ltd., Oct 1987 -- */
  6. /*  ported to MPW, changed the way keys work */
  7. /* Version 0.8(35) - Jim Noble at Planning Research Corporation, June 1987. */
  8. /* Ported to Megamax native Macintosh C compiler. */
  9. /* From: DPVC@UORDBV.BITNET */
  10. /* DPVC at U of R, Oct 1, add blinking cursor and mouse cursor movement */
  11. /* DPVC at U of R, Sept. 26, fixed book-keeping for scrolling and inserting */
  12. /*  characters and lines */
  13. /* DPVC at U of R, Sept. 25, to fix cursor positioning off the screen, and */
  14. /*  a few other, minor VT100 incompatibilities */
  15. /* DPVC at the University of Rochester, Sept. 9, to add Block Cursor and */
  16. /*  ability to do VT100 graphics characters */
  17. /* By CAM2 and DPVC at the University of Rochester on Sept 6, */
  18. /*  changed bolding from using TextStyle attributes to using a separate bold */
  19. /*  font */
  20. /* By Frank on June 20 - Add parity to all outbound chars using software */
  21. /*  Also, ignore DEL (0177) characters on input. */
  22. /* By Bill on May 29 - Add Key set translation */
  23. /* By WBC3 on Apr 24 - Add ^^, ^@ and ^_.  Also use Pascal strings for */
  24. /*  output in the terminal emulator */
  25. /* By WBC3 on Apr 23 - Add query terminal and be more fastidious about */
  26. /*  ignoring sequences we don't know about */
  27. /* By WBC3 on Apr 22 - Fix tab stops to conform to the rest of the world! */
  28. /* By Bill on Apr 21 - Fix immediate echo problems. */
  29. /*  do less cursor_erase, cursor_draw stuff */
  30.  
  31. /*
  32.  * FILE ckmcon.c
  33.  *
  34.  * Module of mackermit: contains code for the terminal simulation
  35.  * routine.
  36.  */
  37.  
  38. #include "ckcdeb.h"
  39.  
  40. #define    __SEG__    ckmcon
  41. #include <quickdraw.h>
  42. #include <files.h>
  43. #include <events.h>
  44. #include <windows.h>
  45. #include <toolutils.h>
  46. #include <osutils.h>
  47. #include <ctype.h>
  48.  
  49. #include "ckmdef.h"
  50. #include "ckmasm.h"        /* Assembler code */
  51.  
  52. #define MAXLIN      24
  53. #define MAXCOL      80
  54. #define LINEHEIGHT  12
  55. #define CHARWIDTH    6
  56. #define TOPMARGIN    3        /* Terminal display constants */
  57. #define bottomMARGIN (LINEHEIGHT * MAXLIN + TOPMARGIN)
  58. #define LEFTMARGIN   3
  59. #define rightMARGIN  (CHARWIDTH * MAXCOL + LEFTMARGIN)
  60. #define LINEADJ      3        /* Amount of char below base line */
  61.  
  62. /* Font Numbers (UoR Mod) to fix bolding problems */
  63. /* These should be placed in the RESOURCE FORK of the executable */
  64.  
  65. #define VT100FONT  128        /* VT100 Terminal Font (not-bold) */
  66. #define VT100BOLD  129        /* VT100 Bold Font */
  67.  
  68. /* Tab settings */
  69.  
  70. /*
  71. #define NUMTABS 9
  72. short tabstops[NUMTABS] = {8,16,24,32,40,48,56,64,72};
  73.   *//* (UoR) remove old method of tab stops */
  74.  
  75. /* (UoR) do tapstops via an array: 0 means no tab, 1 means tab at that column */
  76. short tabstops[MAXCOL + 1] = {
  77.     0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
  78.     0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
  79.     1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
  80.     0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1
  81. };
  82.  
  83. #define USA_SET  0        /* (UoR) VT100 character set numbers */
  84. #define UK_SET   1
  85. #define GRAF_SET 2
  86.  
  87. int topmargin = TOPMARGIN,    /* Edges of adjustable window */
  88.     bottommargin = bottomMARGIN,
  89.     textstyle = 0, 
  90.     currentfont = VT100FONT,    /* (UoR) currently active font */
  91.     graphicsinset[2] = {USA_SET, USA_SET}, /* (UoR) current character sets */
  92.     current_set = 0,        /* (UoR) current chosen set */
  93.     doinvert = FALSE,        /* Flag for inverted terminal mode */
  94.     dounder = FALSE,        /* Flag for underlining (PWP) */
  95.     screeninvert = FALSE,    /* (UoR) inverted screen flag */
  96.     insert = FALSE,
  97.     newline = FALSE,        /* (UoR) linefeed mode by default */
  98.     autowrap = TRUE,        /* Autowrap on by default */
  99.     relorigin = FALSE,        /* (UoR) relative origin off */
  100.     autorepeat = TRUE,        /* (UoR) auto repeat flag */
  101.     smoothscroll = FALSE,    /* do smooth scrolling (PWP: or not) */
  102.     transparent = TRUE,        /* do not show control characters */
  103.     blockcursor = TRUE,        /* show block or underline cursor */
  104.     mouse_arrows = FALSE,    /* mouse down in screen does arrow keys */
  105.     visible_bell = FALSE,    /* true if we do blink instead of bell */
  106.     nat_chars = FALSE,        /* half transparent -- show undef. control
  107.                  * chars */
  108.     blinkcursor = TRUE;        /* true if we make the cursor blink */
  109.  
  110. char *querystring = "\033[?1;2c";    /* Answer we are a VT100 with AVO */
  111.  /* (UoR) used to be VT102 */
  112. char *reportstring = "\033[0n";    /* (UoR) report that we're OK */
  113. char *noprinter = "\033[?13n";    /* (UoR) report no printer */
  114.  
  115. Rect ScreenRect;
  116.  
  117.  /*
  118.   * (UoR) don't need scrollrect any more (use scroll_up and scroll_down), use
  119.   * ScreenRect for mouse check
  120.   */
  121.  
  122. /* Screen book keeping variables */
  123.  
  124. char scr[MAXLIN][MAXCOL + 1];    /* Characters on the screen */
  125. short nxtlin[MAXLIN], toplin, botlin;    /* Linked list of lines */
  126. int curlin, curcol, abslin;    /* Cursor position */
  127. int savcol, savlin;        /* Cursor save variables */
  128. int savsty, savfnt, savgrf, savmod, savset[2];    /* (UoR) cursor save
  129.                          * variables */
  130. int savund;            /* PWP for saved underlining */
  131. int scrtop, scrbot;        /* Absolute scrolling region bounds */
  132. int cursor_invert = FALSE,    /* (UoR) for flashing cursor */
  133.     cur_drawn = FALSE;
  134. long last_flash = 0;
  135. int oldlin = -1;
  136. int oldcol = 0;            /* (UoR) for last mouse position */
  137.  
  138. RgnHandle dummyRgn;        /* dummy region for ScrollRect */
  139.                 /* Initialized in mac_init */
  140.  
  141. # define CARETTIME 20        /* (UoR) ticks between flashes */
  142.  
  143. /* Stuff for escape character processing */
  144.  
  145. #define CF_OUTC 0        /* Just output the char */
  146. #define CF_SESC 1        /* In a single char escape seq */
  147. #define CF_MESC 2        /* In a multi char '[' escape seq */
  148. #define CF_TOSS 3        /* Toss this char */
  149. #define CF_GRF0 4        /* (UoR) for graphics sequence 0 */
  150. #define CF_GRF1 5        /* (UoR) for graphics sequence 1 */
  151.  
  152. char prvchr, numone[6], numtwo[6], *numptr;
  153. int num1, num2, charflg = CF_OUTC;
  154. /* extern CSParam controlparam; */
  155. extern unsigned char dopar ();
  156.  
  157. typedef int (*PFI) ();
  158.  
  159. /* Terminal function declarations. */
  160.  
  161. int 
  162. tab (), back_space (), carriage_return (), line_feed (), bell (),
  163. escape_seq (), text_mode (), clear_line (), erase_display (),
  164. cursor_position (), cursor_up (), cursor_down (), cursor_right (),
  165. cursor_left (), cursor_save (), cursor_restore (), set_scroll_region (),
  166. reverse_line_feed (), dummy (), delete_char (), insert_mode (),
  167. end_insert_mode (), insert_line (), delete_line (), query_terminal (),
  168. multi_char (), toss_char (), insert_chars (),
  169.  
  170.  /* (UoR) for VT100 graphic character set */
  171.  
  172. graphic_G0 (), graphic_G1 (), control_N (), control_O (),
  173.  
  174.  /* (UoR) for other VT100 functions */
  175.  
  176. new_line (), request_report (), set_tab (), clear_tab ();
  177.  
  178.  
  179. /* (UoR) constansts that point to the function definitions for arrow keys */
  180. /*  Used by mouse cursor positioning function (Pascal strings) */
  181.  
  182. # define UPARROW    "\003\033OA"
  183. # define DOWNARROW  "\003\033OB"
  184. # define leftARROW  "\003\033OD"
  185. # define rightARROW "\003\033OC"
  186.  
  187.  
  188. /* Terminal control character function command table. */
  189.  
  190. #define MINSINGCMDS 000
  191. #define MAXSINGCMDS 037
  192.  
  193. PFI controltable[MAXSINGCMDS - MINSINGCMDS + 1] =
  194. {
  195.     dummy,            /* 0 */
  196.     dummy,            /* 1 */
  197.     dummy,            /* 2 */
  198.     dummy,            /* 3 */
  199.     dummy,            /* 4 */
  200.     dummy,            /* 5 */
  201.     dummy,            /* 6 */
  202.     bell,            /* 7 */
  203.     back_space,            /* 10 */
  204.     tab,            /* 11 */
  205.     line_feed,            /* 12 */
  206.     line_feed,            /* 13 (Vertical tab) */
  207.     line_feed,            /* 14 (Form feed) */
  208.     carriage_return,        /* 15 */
  209.     control_N,            /* 16 (graphic set 1) *//* (UoR) */
  210.     control_O,            /* 17 (graphic set 0) *//* (UoR) */
  211.     dummy,            /* 20 */
  212.     dummy,            /* 21 */
  213.     dummy,            /* 22 */
  214.     dummy,            /* 23 */
  215.     dummy,            /* 24 */
  216.     dummy,            /* 25 */
  217.     dummy,            /* 26 */
  218.     dummy,            /* 27 */
  219.     dummy,            /* 30 */
  220.     dummy,            /* 31 */
  221.     dummy,            /* 32 */
  222.     escape_seq,            /* 33 (Escape) */
  223.     dummy,            /* 34 */
  224.     dummy,            /* 35 */
  225.     dummy,            /* 36 */
  226.     dummy            /* 37 */
  227. };
  228.  
  229.  
  230.  
  231. #define MINSINGESCS 0040
  232. #define MAXSINGESCS 0137
  233.  
  234. PFI singescapetable[MAXSINGESCS - MINSINGESCS + 1] =
  235. {
  236.     dummy,            /* 40 */
  237.     dummy,            /* 41 */
  238.     dummy,            /* 42 */
  239.     toss_char,            /* 43 '#' */
  240.     dummy,            /* 44 */
  241.     dummy,            /* 45 */
  242.     dummy,            /* 46 */
  243.     dummy,            /* 47 */
  244.     graphic_G0,            /* 50 '(' *//* (UoR) */
  245.     graphic_G1,            /* 51 ')' *//* (UoR) */
  246.     dummy,            /* 52 */
  247.     dummy,            /* 53 */
  248.     dummy,            /* 54 */
  249.     dummy,            /* 55 */
  250.     dummy,            /* 56 */
  251.     dummy,            /* 57 */
  252.     dummy,            /* 60 */
  253.     dummy,            /* 61 */
  254.     dummy,            /* 62 */
  255.     dummy,            /* 63 */
  256.     dummy,            /* 64 */
  257.     dummy,            /* 65 */
  258.     dummy,            /* 66 */
  259.     cursor_save,        /* 67 '7' */
  260.     cursor_restore,        /* 70 '8' */
  261.     dummy,            /* 71 */
  262.     dummy,            /* 72 */
  263.     dummy,            /* 73 */
  264.     dummy,            /* 74 '<' */
  265.     dummy,            /* 75 '=' */
  266.     dummy,            /* 76 '>' */
  267.     dummy,            /* 77 */
  268.     dummy,            /* 100 */
  269.     dummy,            /* 101 */
  270.     dummy,            /* 102 */
  271.     dummy,            /* 103 */
  272.     line_feed,            /* 104 'D' */
  273.     new_line,            /* 105 'E' *//* (UoR) */
  274.     dummy,            /* 106 */
  275.     dummy,            /* 107 */
  276.     set_tab,            /* 110 'H' *//* (UoR) */
  277.     dummy,            /* 111 */
  278.     dummy,            /* 112 */
  279.     dummy,            /* 113 */
  280.     dummy,            /* 114 */
  281.     reverse_line_feed,        /* 115 'M' */
  282.     toss_char,            /* 116 'N' *//* CME */
  283.     toss_char,            /* 117 'O' *//* (UoR) ignore these */
  284.     dummy,            /* 120 */
  285.     dummy,            /* 121 */
  286.     dummy,            /* 122 */
  287.     dummy,            /* 123 */
  288.     dummy,            /* 124 */
  289.     dummy,            /* 125 */
  290.     dummy,            /* 126 */
  291.     dummy,            /* 127 */
  292.     dummy,            /* 130 */
  293.     dummy,            /* 131 */
  294.     query_terminal,        /* 132 'Z' */
  295.     multi_char,            /* 133 '[' */
  296.     dummy,            /* 134 */
  297.     dummy,            /* 135 */
  298.     dummy,            /* 136 */
  299.     dummy            /* 137 */
  300. };
  301.  
  302.  
  303.  
  304.  
  305. /* Terminal escape sequence function command table */
  306.  
  307. #define MINMULTESCS 0100
  308. #define MAXMULTESCS 0177
  309.  
  310. PFI escapetable[MAXMULTESCS - MINMULTESCS + 1] =
  311. {
  312.     insert_chars,        /* 100 *//* CME */
  313.     cursor_up,            /* 101 'A' */
  314.     cursor_down,        /* 102 'B' */
  315.     cursor_right,        /* 103 'C' */
  316.     cursor_left,        /* 104 'D' */
  317.     dummy,            /* 105 */
  318.     dummy,            /* 106 */
  319.     dummy,            /* 107 */
  320.     cursor_position,        /* 110 'H' */
  321.     dummy,            /* 111 */
  322.     erase_display,        /* 112 'J' */
  323.     clear_line,            /* 113 'K' */
  324.     insert_line,        /* 114 'L' */
  325.     delete_line,        /* 115 'M' */
  326.     dummy,            /* 116 */
  327.     dummy,            /* 117 */
  328.     delete_char,        /* 120 'P' */
  329.     dummy,            /* 121 */
  330.     dummy,            /* 122 */
  331.     dummy,            /* 123 */
  332.     dummy,            /* 124 */
  333.     dummy,            /* 125 */
  334.     dummy,            /* 126 */
  335.     dummy,            /* 127 */
  336.     dummy,            /* 130 */
  337.     dummy,            /* 131 */
  338.     dummy,            /* 132 */
  339.     dummy,            /* 133 */
  340.     dummy,            /* 134 */
  341.     dummy,            /* 135 */
  342.     dummy,            /* 136 */
  343.     dummy,            /* 137 */
  344.     dummy,            /* 140 */
  345.     dummy,            /* 141 */
  346.     dummy,            /* 142 */
  347.     query_terminal,        /* 143 'c' */
  348.     dummy,            /* 144 */
  349.     dummy,            /* 145 */
  350.     cursor_position,        /* 146 'f' */
  351.     clear_tab,            /* 147 'g' *//* (UoR) */
  352.     insert_mode,        /* 150 'h' */
  353.     dummy,            /* 151 */
  354.     dummy,            /* 152 */
  355.     dummy,            /* 153 */
  356.     end_insert_mode,        /* 154 'l' */
  357.     text_mode,            /* 155 'm' */
  358.     request_report,        /* 156 'n' *//* (UoR) */
  359.     dummy,            /* 157 */
  360.     dummy,            /* 160 */
  361.     dummy,            /* 161 */
  362.     set_scroll_region,        /* 162 'r' */
  363.     dummy,            /* 163 */
  364.     dummy,            /* 164 */
  365.     dummy,            /* 165 */
  366.     dummy,            /* 166 */
  367.     dummy,            /* 167 */
  368.     dummy,            /* 170 */
  369.     dummy,            /* 171 */
  370.     dummy,            /* 172 */
  371.     dummy,            /* 173 */
  372.     dummy,            /* 174 */
  373.     dummy,            /* 175 */
  374.     dummy,            /* 176 */
  375.     dummy            /* 177 */
  376. };
  377.  
  378.  
  379.  
  380. /****************************************************************************/
  381. /* Connect support routines */
  382. /****************************************************************************/
  383. consetup ()
  384. {
  385.     PenMode (patXor);
  386.     flushio ();            /* Get rid of pending characters */
  387.  
  388.     init_term ();        /* Set up some terminal variables */
  389.     TextFont (VT100FONT);    /* (UoR) Set initial font to VT100 */
  390.     TextMode (srcXor);        /* (UoR) use XOR mode (for inverse) */
  391.     TextFace (0);        /* PWP: be safe.  We allways stay like this */
  392.     clear_screen ();        /* Clear the screen */
  393.     home_cursor ();        /* Go to the upper left */
  394.     cursor_save ();        /* Save this position */
  395.     cursor_draw ();        /* (UoR) be sure to draw it */
  396. }                /* consetup */
  397.  
  398.  
  399.  
  400. /****************************************************************************/
  401. /* Input and process all the characters pending on the tty line */
  402. /****************************************************************************/
  403. inpchars ()
  404. {
  405.     int rdcnt;
  406.  
  407.     if ((rdcnt = ttchk ()) == 0)/* How many chars there? */
  408.     return;            /* Ret if 0 */
  409.  
  410.     cursor_erase ();        /* remove cursor from screen */
  411.     while (rdcnt-- > 0)        /* Output all those characters */
  412.     printit (ttinc (0));
  413.     flushbuf ();        /* Flush any remaining characters */
  414.     cursor_draw ();        /* put it back */
  415. }                /* inpchars */
  416.  
  417.  
  418.  
  419. /****************************************************************************/
  420. /* writeps - write a pascal form string to the serial port.
  421.  *
  422.  */
  423. /****************************************************************************/
  424. writeps (s)
  425. char *s;
  426. {
  427.     long wcnt, w2;
  428.     int err;
  429.     char *s2;
  430.  
  431.     w2 = wcnt = *s++;        /* get count */
  432.  
  433.     for (s2 = s; w2 > 0; w2--, s2++)    /* add parity */
  434.     *s2 = dopar (*s2);
  435.  
  436.     err = FSWrite (outnum, &wcnt, s);    /* write the characters */
  437.     if (err != noErr)
  438.     printerr ("Bad FSWrite in writeps: ", err);
  439.  
  440.     return;
  441. }                /* writeps */
  442.  
  443.  
  444.  
  445. /****************************************************************************/
  446. /*
  447.  * (UoR)
  448.  *
  449.  * Print a string to the screen (used to echo function and meta strings
  450.  * in duplex mode).
  451.  *
  452.  */
  453. /****************************************************************************/
  454. printps (s)
  455. char *s;
  456. {
  457.     long w2;
  458.     char *s2;
  459.  
  460.     cursor_erase ();
  461.  
  462.     w2 = *s++;            /* get count */
  463.     for (s2 = s; w2 > 0; w2--, s2++)
  464.     printit (*s2);        /* print it out, and perform special
  465.                  * functions */
  466.  
  467.     flushbuf ();
  468.  
  469.     cursor_draw ();
  470.     return;
  471. }                /* printps */
  472.  
  473.  
  474.  
  475. /****************************************************************************/
  476. /* return the ASCII character which is generated by the keyCode specified */
  477. /* with no modifiers pressed */
  478. /****************************************************************************/
  479. unsigned char
  480. DeModifyChar (keyCode)
  481. short keyCode;
  482. {
  483.     ProcHandle KeyTrans;
  484.     long c;
  485.  
  486.     if (keyCode > 64)
  487.     KeyTrans = 0x2A2;    /* keypad decode */
  488.     else
  489.     KeyTrans = 0x29E;    /* keyboard decode */
  490.  
  491.     SaveRegs ();        /* save all registers */
  492.     AllRegs ();
  493.  
  494.     /* setup regs for procedure call */
  495.     loadD1 ((long) 0);        /* no modifiers */
  496.     loadD2 ((long) keyCode);    /* set the keycode */
  497.     loadA0 (*KeyTrans);        /* load the content of Key1Trans to A0 */
  498.  
  499.     /* run the translation routine */
  500.     execute ();            /* call the Key1Trans procedure */
  501.  
  502.     /* move the result from reg D0 to c */
  503.     loadA0 (&c);        /* set destination address */
  504.     pushD0 ();            /* move register D0 to stack */
  505.     poptoA0 ();            /* load the stacktop to (A0) */
  506.  
  507.     RestoreRegs ();        /* restore all registers */
  508.     AllRegs ();
  509.  
  510.     return (c);
  511. }                /* DeModifyChar */
  512.  
  513.  
  514.  
  515. unsigned char obuf[2] = {1, 0};    /* single char output buffer */
  516.  
  517. /****************************************************************************/
  518. /* send a character to the line if it is in ASCII range. Do local echo if */
  519. /* necessary */
  520. /****************************************************************************/
  521. OutputChar (c)
  522. unsigned char c;
  523. {
  524.  
  525.     /*
  526.      * PWP: NO 7 bit masking!!!  If we do this, then I can't use Emacs, and
  527.      * the European users will be VERY unhappy, 'cause they won't be able to
  528.      * send all of their characters.
  529.      */
  530.  
  531. #ifdef COMMENT_OUT
  532.     if (c > 127) {        /* reject non-ASCII characters */
  533.     SysBeep (1);
  534.     return;
  535.     }
  536. #endif                /* COMMENT_OUT */
  537.  
  538.     obuf[1] = c;        /* store character */
  539.     writeps (obuf);        /* and write it out */
  540.  
  541.     if (duplex != 0) {
  542.     cursor_erase ();    /* remove from screen */
  543.     printit ((char) c);    /* Echo the char to the screen */
  544.     flushbuf ();        /* flush the character */
  545.     cursor_draw ();        /* put it back */
  546.     }
  547. }                /* OutputChar */
  548.  
  549.  
  550.  
  551. extern char keytable[512];    /* the key redefintion flag table */
  552. extern modrec modtable[NUMOFMODS];    /* modifier records */
  553.  
  554. #define myKeyCodeMask    0x7F00
  555. #define keyModifierMask    0x1F00
  556. #define ctrlCodeMask    0x1F
  557. #define metaOrBits    0x80
  558.  
  559. #define UnmodMask    0x80        /* action bits */
  560. #define CapsMask    0x40
  561. #define CtrlMask    0x20
  562. #define MetaMask    0x10
  563.  
  564. /****************************************************************************/
  565. /* Process a character received from the keyboard */
  566. /****************************************************************************/
  567. handle_char (evt)
  568. EventRecord *evt;
  569. {
  570.     short i;
  571.     short len;
  572.     short theCode;
  573.     short modCode;
  574.     short theModBits;
  575.     char flags;
  576.     char tmpstr[256];
  577.     unsigned char c;
  578.  
  579.     /* (UoR) check for auto repeated keys */
  580.     if ((autorepeat == FALSE) && (evt->what == autoKey))
  581.     return;
  582.  
  583.     ObscureCursor ();        /* PWP: hide the cursor until next move */
  584.  
  585.     modCode = evt->modifiers & keyModifierMask;
  586.     theCode = ((evt->message & myKeyCodeMask) >> 8) + (modCode >> 1);
  587.     
  588.     /* check for a special code for this key */
  589.     if (BitTst (&keytable, theCode)) {
  590.     GetMacro (theCode, &flags, tmpstr);    /* get the macrostring */
  591.  
  592.     if (flags) {        /* check special flags */
  593.         if (flags & shortBreak) {    /* short break ? */
  594.         sendbreak (5);
  595.         return;
  596.         }
  597.         if (flags & longBreak) {    /* long break ? */
  598.         sendbreak (70);
  599.         return;
  600.         }
  601.     }
  602.     /* send key macro string */
  603.  
  604.     /*
  605.      * PWP: note, we DON'T have to convert it to a Pascal string, 'cause
  606.      * the macros are now stored as Pascal strings
  607.      */
  608.     writeps (tmpstr);    /* send it to the line */
  609.     if (duplex != 0)
  610.         printps (tmpstr);    /* echo it locally */
  611.     return;
  612.     }
  613.     for (i = 0; i < NUMOFMODS; i++) {
  614.     /* shift what to look for into high byte */
  615.     theModBits = modtable[i].modbits << 4;
  616.     len = strlen (modtable[i].prefix);
  617.  
  618.     if ((theModBits || len) &&
  619.         ((theModBits & modCode) == (theModBits & keyModifierMask))) {
  620.         /* send prefix if there is one */
  621.         if (len) {
  622.         /* PWP: these are saved as Pascal strings now */
  623.         BlockMove (modtable[i].prefix, tmpstr, (modtable[i].prefix[0] + 1));
  624.         writeps (tmpstr);    /* send it to the line */
  625.         if (duplex != 0)
  626.             printps (tmpstr);    /* echo it locally */
  627.         }
  628.  
  629.         /*
  630.          * get the unmodified ASCII code if the unmodify action bit is
  631.          * active
  632.          */
  633.         if (theModBits & UnmodMask)
  634.         c = DeModifyChar ((evt->message & myKeyCodeMask) >> 8);
  635.         else
  636.         c = evt->message & charCodeMask;    /* otherwise get the
  637.                              * standard char */
  638.  
  639.         /* make an uppercase character if the caps action bit is active */
  640.         if ((theModBits & CapsMask) && islower (c))
  641.         c = _toupper (c);
  642.  
  643.         /* make a control character if the control action bit is active */
  644.         if (theModBits & CtrlMask)
  645.         c &= ctrlCodeMask;
  646.  
  647.         /* PWP: for Meta characters (yes, I use Emacs) */
  648.         if (theModBits & MetaMask)
  649.         c |= metaOrBits;
  650.  
  651.         OutputChar (c);
  652.         return;
  653.     }            /* if */
  654.     }                /* for */
  655.  
  656.     /* get the ASCII code and send it */
  657.     OutputChar (evt->message & charCodeMask);
  658. }                /* handle_char */
  659.  
  660.  
  661.  
  662. char outbuf[MAXCOL + 1];
  663. int outcnt = 0, outcol;
  664.  
  665. /****************************************************************************/
  666. /* flushbuf() -- draw all the buffered characters on the screen */
  667. /****************************************************************************/
  668. flushbuf ()
  669. {
  670.     Rect r;
  671.  
  672.     if (outcnt == 0)
  673.     return;            /* Nothing to flush */
  674.  
  675.     /* Erase a hole large enough for outcnt chars */
  676.     makerect (&r, abslin, outcol, 1, outcnt);
  677.  
  678.     EraseRect (&r);        /* (UoR) Use InvertRect instead of fillRect */
  679.     DrawText (outbuf, 0, outcnt);    /* Output the string */
  680.  
  681.     if (doinvert)        /* PWP: moved this... */
  682.     InvertRect (&r);
  683.  
  684.     if (dounder) {        /* PWP: do underlining */
  685.     makertou (&r);        /* make into an underline */
  686.     InvertRect (&r);
  687.     }
  688.     outcnt = 0;            /* Say no more chars to output */
  689. }                /* flushbuf */
  690.  
  691.  
  692.  
  693. /****************************************************************************/
  694. /* save a character in the buffer */
  695. /****************************************************************************/
  696. buf_char (c)
  697. char c;
  698. {
  699.     if (outcnt == 0)
  700.     outcol = curcol;    /* No chars in buffer, init column */
  701.     outbuf[outcnt++] = c;    /* Put in the buffer to output later */
  702. }                /* buf_char */
  703.  
  704.  
  705.  
  706. /****************************************************************************/
  707. /*
  708.  *  Printit:
  709.  *      Draws character and updates buffer
  710.  */
  711. /****************************************************************************/
  712. printit (c)
  713. char c;
  714. {
  715.     PFI funp, lookup ();
  716.     long lnum1, lnum2;
  717.  
  718.     c &= 0177;
  719.  
  720.     if (c != 0) {        /* (UoR) ignore null characters */
  721.  
  722.     switch (charflg) {
  723.       case CF_OUTC:    /* Just output the char */
  724.         MDrawChar (c);
  725.         break;
  726.  
  727.       case CF_SESC:    /* In a single char escape seq */
  728.         charflg = CF_OUTC;    /* Reset flag to simple outputting */
  729.         if (funp = lookup (c, singescapetable, MINSINGESCS, MAXSINGESCS))
  730.         (*funp) ();    /* Do escape sequence function */
  731.         break;
  732.  
  733.       case CF_GRF0:    /* (UoR) process graphic characters */
  734.       case CF_GRF1:
  735.         switch (c) {
  736.           case 'A':
  737.         graphicsinset[charflg - CF_GRF0] = UK_SET;
  738.         break;
  739.           case 'B':
  740.           case '1':
  741.         graphicsinset[charflg - CF_GRF0] = USA_SET;
  742.         break;
  743.  
  744.           case '0':
  745.           case '2':
  746.         graphicsinset[charflg - CF_GRF0] = GRAF_SET;
  747.         break;
  748.         }
  749.         charflg = CF_OUTC;    /* Reset flag for next character */
  750.         break;
  751.  
  752.       case CF_MESC:    /* Multichar escape sequence */
  753.         if (c >= 0x20 && c < 0x40) {    /* Deal with the modifiers */
  754.         if (c >= '<' && c <= '?') {
  755.             prvchr = c;    /* Handle priv char */
  756.         } else if ((numptr == numone || numptr == numtwo) &&
  757.              (c == '0' || c == '-' || c == '+')) {
  758.             /* if at start of sequence */
  759.             if (c == '-')    /* then we only record leading - */
  760.                 *numptr++ = c;
  761.         } else if (c >= '0' && c <= '9') {  /* PWP: was also '+' or '-' */
  762.             *numptr++ = c;    /* Add the char to the num */
  763.         } else if (c == ';') {
  764.             *numptr = '\0';    /* Terminate the string */
  765.             numptr = numtwo;    /* Go to next number */
  766.         } else {
  767.             charflg = CF_OUTC;    /* (UoR) */
  768.         }
  769.         } else if (c >= 0x40) {        /* End of sequence */
  770.         /* PWP: according to VTTEST, we ignore control characters here */
  771.         if (funp = lookup (c, escapetable, MINMULTESCS, MAXMULTESCS)) {
  772.             *numptr = '\0';    /* Terminate the string */
  773.             StringToNum (numone, &lnum1);    /* Translate the numbers */
  774.             StringToNum (numtwo, &lnum2);
  775.             num1 = (int) lnum1;
  776.             num2 = (int) lnum2;
  777.             (*funp) ();    /* Do the escape sequence function */
  778.         }
  779.         charflg = CF_OUTC;    /* Back to simple outputting */
  780.         }
  781.         break;
  782.  
  783.       case CF_TOSS:    /* Ignore this char */
  784.         charflg = CF_OUTC;    /* Reset flag */
  785.         break;
  786.     }
  787.     }
  788. }                /* printit */
  789.  
  790.  
  791.  
  792. /****************************************************************************/
  793. /*
  794.  * Routine makerect
  795.  *
  796.  * Make a rectangle in r starting on line lin and column col extending
  797.  * numlin lines and numcol characters.
  798.  *
  799.  */
  800. /****************************************************************************/
  801. makerect (r, lin, col, numlin, numcol)
  802. Rect *r;
  803. int lin;
  804. int col;
  805. int numlin;
  806. int numcol;
  807. {
  808.     r->top = lin * LINEHEIGHT + TOPMARGIN;
  809.     r->left = col * CHARWIDTH + LEFTMARGIN;
  810.     r->bottom = r->top + numlin * LINEHEIGHT;
  811.     r->right = r->left + numcol * CHARWIDTH;
  812. }                /* makerect */
  813.  
  814. /* Make rect r (made by makerect()) into the right shape
  815.      for underlining */
  816. makertou (r)
  817. Rect *r;
  818. {
  819.     r->top = r->bottom - 1;
  820. }
  821.  
  822. /****************************************************************************/
  823. /*
  824.  *   Lookup:
  825.  *      Lookup a given character in the apropriate character table, and
  826.  *      return a pointer to the appropriate function, if it exists.
  827.  */
  828. /****************************************************************************/
  829. PFI
  830. lookup (index, table, min, max)
  831. char index;
  832. PFI table[];
  833. int min;
  834. int max;
  835. {
  836.     if (index > max || index < min)
  837.     return ((PFI) NULL);    /* Don't index out of range */
  838.     return (table[index - min]);
  839. }                /* lookup */
  840.  
  841.  
  842.  
  843. /****************************************************************************/
  844. /*
  845.  *   Flushio:
  846.  *      Initialize some communications constants, and clear screen and
  847.  *      character buffers. */
  848. /****************************************************************************/
  849. flushio ()
  850. {
  851.     int err;
  852.  
  853.     err = KillIO (-6);
  854.     if (err)
  855.     printerr ("Bad input clear", err);
  856.     err = KillIO (-7);
  857.     if (err)
  858.     printerr ("Bad ouput clear", err);
  859. }                /* flushio */
  860.  
  861.  
  862.  
  863. /****************************************************************************/
  864. /* sendbreak - sends a break across the communictions line.
  865.  *
  866.  * The argument is in units of approximately 0.05 seconds (or 50
  867.  * milliseconds).  To send a break of duration 250 milliseconds the
  868.  * argument would be 5; a break of duration 3.5 seconds would be (umm,
  869.  * lets see now) 70.
  870.  *
  871.  */
  872. /****************************************************************************/
  873. sendbreak (msunit)
  874. {
  875.     long finalticks;
  876.  
  877. /* delay wants 1/60th units.  We have 3/60 (50 ms.) units, convert */
  878.  
  879.     msunit = msunit * 3;
  880.  
  881.     SerSetBrk (outnum);        /* start breaking */
  882.     Delay ((long) msunit, &finalticks);    /* delay */
  883.     SerClrBrk (outnum);        /* stop breaking */
  884. }                /* sendbreak */
  885.  
  886.  
  887.  
  888. /****************************************************************************/
  889. /* draw a characer on the screen (or buffer it) */
  890. /****************************************************************************/
  891. MDrawChar (chr)
  892. char chr;
  893. {
  894.     PFI funp;
  895.  
  896.     /* If it's a control char, do the apropriate function. */
  897.  
  898.     if ((chr < ' ') && (transparent)) {    /* Is it a control character */
  899.     flushbuf ();
  900.     if (funp = lookup (chr, controltable, MINSINGCMDS, MAXSINGCMDS)) {
  901.         if (funp != dummy) {/* PWP */
  902.         (*funp) ();
  903.         return;
  904.         }
  905.     }
  906.     if (!nat_chars)        /* PWP: half transparent -- show undefd
  907.                  * controls */
  908.         return;
  909.     if (chr == '\0')    /* PWP: never show nulls */
  910.         return;
  911.     }
  912.     if (chr < 0177) {        /* Don't do Mac graphic characters */
  913.     switch (graphicsinset[current_set]) {
  914.       case GRAF_SET:    /* Do VT100 graphics (offset to character in
  915.                  * VT100 font) */
  916.         if ((chr >= '_') && (chr <= '~'))
  917.         chr += 128;
  918.         break;
  919.  
  920.       case UK_SET:        /* Use pound symbol from VT100 font */
  921.         if (chr == '#')
  922.         chr = 0375;    /* VT100 pound symbol = 0375 */
  923.         break;
  924.     }
  925.  
  926.     if (curcol >= MAXCOL) {    /* Are we about to wrap around? */
  927.         if (autowrap) {    /* If autowrap indicated wrap */
  928.         flushbuf ();
  929.         if (newline == FALSE)
  930.             carriage_return ();
  931.         line_feed ();
  932.         } else {
  933.         flushbuf ();    /* (UoR) make sure last char is shown */
  934.         back_space ();    /* Otherwise just overwrite */
  935.         }
  936.     }
  937.     if (insert) {        /* Insert mode? */
  938.         insert_char ();    /* Open hole for char if requested */
  939.         erase_char ();    /* Erase the old char */
  940.         DrawChar (chr);
  941.     } else
  942.         buf_char (chr);    /* Otherwise just buffer the char */
  943.  
  944.     scr[curlin][curcol++] = chr;
  945.     }
  946. }                /* MDrawChar */
  947.  
  948.  
  949.  
  950. /****************************************************************************/
  951. /*
  952.  *      Control character functions:
  953.  *              Each of the following allow the mac to simulate
  954.  *              the behavior of a terminal when given the proper
  955.  *              control character.
  956.  */
  957. /****************************************************************************/
  958.  
  959.  
  960. back_space ()
  961. {
  962.     if (curcol > 0)
  963.     relmove (-1, 0);
  964. }                /* back_space */
  965.  
  966.  
  967.  
  968. erase_char ()
  969. {
  970.     Rect r;
  971.  
  972.     scr[curlin][curcol] = ' ';    /* Erase char for update */
  973.     makerect (&r, abslin, curcol, 1, 1);    /* One char by one line */
  974.  
  975.     EraseRect (&r);        /* (UoR) use InvertRect instead of FillRect */
  976.     if (doinvert)
  977.     InvertRect (&r);
  978. }                /* erase_char */
  979.  
  980.  
  981.  
  982. tab ()
  983. {
  984.     int i;
  985.  
  986. /*    for (i=0; i<NUMTABS; i++)
  987.     {
  988.         if (tabstops[i] > curcol)
  989.         {
  990.             absmove(tabstops[i],abslin);
  991.             return;
  992.         }
  993.      *  }*/
  994.     /* (UoR) remove old method of tabbing */
  995.  
  996.     /* (UoR) find next tabstop */
  997.     for (i = curcol + 1; (i < MAXCOL) && (tabstops[i] == 0); i++);
  998.     absmove (i, abslin);
  999. }                /* tab */
  1000.  
  1001.  
  1002.  
  1003. line_feed ()
  1004. {
  1005.     if (newline)
  1006.     absmove (0, abslin);    /* (UoR) perform newline function */
  1007.  
  1008.     if (curlin == scrbot)
  1009.     scroll_up (scrtop, curlin);    /* (UoR) scroll lines up */
  1010.     else
  1011.     relmove (0, 1);
  1012. }                /* line_feed */
  1013.  
  1014.  
  1015.  
  1016. reverse_line_feed ()
  1017. {
  1018.     if (curlin == scrtop)
  1019.     scroll_down (curlin, scrbot);    /* (UoR) scroll down in region */
  1020.     else
  1021.     relmove (0, -1);
  1022. }                /* reverse_line_feed */
  1023.  
  1024.  
  1025.  
  1026. carriage_return ()
  1027. {
  1028.     if (newline)
  1029.     line_feed ();        /* (UoR) perform newline function */
  1030.     else
  1031.     absmove (0, abslin);
  1032. }                /* carriage_return */
  1033.  
  1034.  
  1035.  
  1036. new_line ()
  1037. {
  1038.     carriage_return ();
  1039.     line_feed ();
  1040. }                /* new_line */
  1041.  
  1042.  
  1043.  
  1044. clear_screen ()
  1045. {
  1046.     register int i;
  1047.     Rect r;
  1048.  
  1049.     makerect (&r, 0, 0, MAXLIN, MAXCOL);    /* The whole screen */
  1050.     EraseRect (&r);
  1051.  
  1052.     for (i = 0; i < MAXLIN; i++)
  1053.     zeroline (i);        /* Clear up the update records */
  1054. }                /* clear_screen */
  1055.  
  1056.  
  1057.  
  1058. home_cursor ()
  1059. {
  1060.     if (relorigin)
  1061.     absmove (0, fndabs (scrtop));
  1062.     else
  1063.     absmove (0, 0);        /* (UoR) correct for relative origin */
  1064. }                /* home_cursor */
  1065.  
  1066.  
  1067.  
  1068. /****************************************************************************/
  1069. /* PWP -- like waitasec(), but don't get any characters.  Used for 
  1070.    visable bell. */
  1071. /****************************************************************************/
  1072. waitnoinput ()
  1073. {
  1074.     long end_time;
  1075.  
  1076.     end_time = TickCount () + 2;/* pause for 1/30th second */
  1077.     while (TickCount () < end_time);
  1078. }                /* waitnoinput */
  1079.  
  1080.  
  1081.  
  1082. bell ()
  1083. {
  1084.     Rect r;
  1085.  
  1086.     if (visible_bell) {
  1087.     makerect (&r, 0, 0, MAXLIN, MAXCOL);    /* The whole screen */
  1088.     InvertRect (&r);
  1089.     waitnoinput ();        /* sleep for a bit (1/30 sec) */
  1090.     InvertRect (&r);
  1091.     } else {
  1092.     SysBeep (3);
  1093.     }
  1094. }                /* bell */
  1095.  
  1096.  
  1097.  
  1098. escape_seq ()
  1099. {
  1100.     charflg = CF_SESC;        /* Say we are in an escape sequence */
  1101. }                /* escape_seq */
  1102.  
  1103.  
  1104.  
  1105. graphic_G0 ()            /* (UoR) do VT100 graphic characters */
  1106. {
  1107.     charflg = CF_GRF0;
  1108. }                /* graphic_G0 */
  1109.  
  1110.  
  1111.  
  1112. graphic_G1 ()
  1113. {
  1114.     charflg = CF_GRF1;
  1115. }                /* graphic_G1 */
  1116.  
  1117.  
  1118.  
  1119. control_N ()
  1120. {
  1121.     current_set = 1;        /* set to graphics set 1 */
  1122. }                /* control_N */
  1123.  
  1124.  
  1125.  
  1126. control_O ()
  1127. {
  1128.     current_set = 0;        /* set to graphics set 0 */
  1129. }                /* control_O */
  1130.  
  1131.  
  1132.  
  1133. clear_line ()
  1134. {
  1135.     int i;
  1136.     Rect r;
  1137.  
  1138.     switch (num1) {
  1139.       case 0:            /* Clear:  here to the right */
  1140.     makerect (&r, abslin, curcol, 1, MAXCOL - curcol);
  1141.     for (i = curcol; i < MAXCOL; i++)
  1142.         scr[curlin][i] = ' ';
  1143.     break;
  1144.  
  1145.       case 1:            /* Clear:  left to here */
  1146.     makerect (&r, abslin, 0, 1, curcol + 1);
  1147.     for (i = 0; i <= curcol; i++)
  1148.         scr[curlin][i] = ' ';
  1149.     break;
  1150.  
  1151.       case 2:            /* Clear:  entire line */
  1152.     makerect (&r, abslin, 0, 1, MAXCOL);
  1153.     zeroline (curlin);
  1154.     break;
  1155.     }
  1156.     EraseRect (&r);
  1157. }                /* clear_line */
  1158.  
  1159.  
  1160.  
  1161. erase_display ()
  1162. {
  1163.     int i;
  1164.     Rect r;
  1165.  
  1166.     switch (num1) {
  1167.       case 0:
  1168.     clear_line ();        /* Same num1 causes correct clear */
  1169.     makerect (&r, abslin + 1, 0, MAXLIN - abslin - 1, MAXCOL);
  1170.                 /* (UoR) -1 added */
  1171.     EraseRect (&r);
  1172.     for (i = abslin + 1; i < MAXLIN; i++)
  1173.         zeroline (fndrel (i));
  1174.     break;
  1175.  
  1176.       case 1:
  1177.     clear_line ();        /* Same num1 causes correct clear */
  1178.     makerect (&r, 0, 0, abslin, MAXCOL);
  1179.     EraseRect (&r);
  1180.     for (i = 0; i < abslin; i++)
  1181.         zeroline (fndrel (i));
  1182.     break;
  1183.  
  1184.       case 2:
  1185.     clear_screen ();
  1186.     break;
  1187.     }
  1188. }                /* erase_display */
  1189.  
  1190.  
  1191. /****************************************************************************/
  1192. /**** All cursor moves need to check that they don't go beyond the margins */
  1193. /****************************************************************************/
  1194.  
  1195. cursor_right ()
  1196. {
  1197.     if (num1 == 0)
  1198.     num1 = 1;
  1199.     relmove (num1, 0);
  1200. }                /* cursor_right */
  1201.  
  1202.  
  1203.  
  1204. cursor_left ()
  1205. {
  1206.     if (num1 == 0)
  1207.     num1 = 1;
  1208.     relmove (-num1, 0);
  1209. }                /* cursor_left */
  1210.  
  1211.  
  1212.  
  1213. cursor_up ()
  1214. {
  1215.     int abstop;            /* (UoR) check that we don't pass scrtop */
  1216.  
  1217.     abstop = fndabs (scrtop);
  1218.     if (num1 == 0)
  1219.     num1 = 1;
  1220.     if ((abslin >= abstop) && (abslin - num1 < abstop))
  1221.     absmove (curcol, abstop);
  1222.     else
  1223.     relmove (0, -num1);
  1224. }                /* cursor_up */
  1225.  
  1226.  
  1227.  
  1228. cursor_down ()
  1229. {
  1230.     int absbot;            /* (UoR) check that we don't pass scrbot */
  1231.  
  1232.     absbot = fndabs (scrbot);
  1233.     if (num1 == 0)
  1234.     num1 = 1;
  1235.     if ((abslin <= absbot) && (abslin + num1 > absbot))
  1236.     absmove (curcol, absbot);
  1237.     else
  1238.     relmove (0, num1);
  1239. }                /* cursor_down */
  1240.  
  1241.  
  1242.  
  1243. cursor_position ()
  1244. {
  1245. /*    if (--num1 < 0) num1 = 0;
  1246.      *    if (--num2 < 0) num2 = 0;  *//* This is taken care of by absmove */
  1247.  
  1248.     if (relorigin)
  1249.     absmove (--num2, fndabs (scrtop) + num1 - 1);    /* (UoR) */
  1250.     else
  1251.     absmove (--num2, --num1);    /* (UoR) moved "--" here from prev
  1252.                      * lines */
  1253. }                /* cursor_position */
  1254.  
  1255.  
  1256.  
  1257. cursor_save ()
  1258. {
  1259.     savcol = curcol;        /* Save the current line and column */
  1260.     savlin = abslin;
  1261.  
  1262.     /* savsty = textstyle; *//* (UoR) additions */
  1263.     savfnt = currentfont;
  1264.     savmod = doinvert;
  1265.     savund = dounder;        /* PWP */
  1266.     savgrf = current_set;
  1267.     savset[0] = graphicsinset[0];
  1268.     savset[1] = graphicsinset[1];
  1269. }                /* cursor_save */
  1270.  
  1271.  
  1272.  
  1273. cursor_restore ()
  1274. {
  1275.     absmove (savcol, savlin);    /* Move to the old cursor position */
  1276.  
  1277.     textstyle = savsty;        /* (UoR) additions */
  1278.     currentfont = savfnt;
  1279.     doinvert = savmod;
  1280.     TextFont (currentfont);
  1281.     /* TextFace(textstyle); */
  1282.     dounder = savund;        /* PWP */
  1283.     current_set = savgrf;
  1284.     graphicsinset[0] = savset[0];
  1285.     graphicsinset[1] = savset[1];
  1286. }                /* cursor_restore */
  1287.  
  1288.  
  1289.  
  1290. cursor_rect (line, col, r)
  1291. Rect *r;
  1292. {
  1293.     makerect (r, line, col, 1, 1);    /* Get character rectangle */
  1294.     if (blockcursor) {
  1295.     /* r->left--;  *//* make r a little wider (PWP: or not) */
  1296.     /* r->top--;     */
  1297.     } else
  1298.     r->top = r->bottom - 1;
  1299. }                /* cursor_rect */
  1300.  
  1301.  
  1302.  
  1303. cursor_draw ()
  1304. {
  1305.     /*    Line(CHARWIDTH,0);*//* Draw cursor */
  1306.  
  1307.     Rect r;
  1308.  
  1309.     if (cursor_invert == FALSE) {
  1310.     cursor_rect (abslin, curcol, &r);
  1311.     InvertRect (&r);
  1312.     }
  1313.     if (oldlin >= 0) {        /* (UoR) replace mouse cursor */
  1314.     cursor_rect (oldlin, oldcol, &r);
  1315.     PenMode (patXor);
  1316.     FrameRect (&r);
  1317.     PenMode (patCopy);
  1318.     }
  1319.     cursor_invert = TRUE;
  1320.     cur_drawn = TRUE;
  1321. }                /* cursor_draw */
  1322.  
  1323.  
  1324.  
  1325. cursor_erase ()
  1326. {
  1327.     /*    Line(-CHARWIDTH,0);*//* Erase cursor */
  1328.  
  1329.     Rect r;
  1330.  
  1331.     if (cursor_invert) {
  1332.     cursor_rect (abslin, curcol, &r);
  1333.     InvertRect (&r);
  1334.     }
  1335.     if (oldlin >= 0) {        /* (UoR) remove mouse cursor */
  1336.     makerect (&r, oldlin, oldcol, 1, 1);
  1337.     cursor_rect (oldlin, oldcol, &r);
  1338.     PenMode (patXor);
  1339.     FrameRect (&r);
  1340.     PenMode (patCopy);
  1341.     }
  1342.     cursor_invert = FALSE;
  1343.     cur_drawn = FALSE;
  1344. }                /* cursor_erase */
  1345.  
  1346.  
  1347.  
  1348. flash_cursor (theWindow)
  1349. WindowPtr theWindow;
  1350. {
  1351.     register long tc;
  1352.     Rect r;
  1353.  
  1354.     if (theWindow == (WindowPtr) NIL) {
  1355.     last_flash = TickCount ();
  1356.     return;
  1357.     }
  1358.  
  1359. #ifdef COMMENT            /* PWP: this eats up gobbs of time */
  1360.     if (FrontWindow () != theWindow) {
  1361.     last_flash = TickCount ();
  1362.     return;
  1363.     }
  1364. #endif
  1365.  
  1366.     tc = TickCount ();
  1367.     if (((tc - last_flash) > CARETTIME) ||
  1368.     (tc - last_flash) < 0) {
  1369.     last_flash = tc;
  1370.  
  1371.     if (cur_drawn) {
  1372.         cursor_rect (abslin, curcol, &r);
  1373.         if (blinkcursor) {    /* PWP: only blink if asked for */
  1374.         InvertRect (&r);
  1375.         if (cursor_invert)
  1376.             cursor_invert = FALSE;
  1377.         else
  1378.             cursor_invert = TRUE;
  1379.         } else if (!cursor_invert) {    /* make sure that the cursor
  1380.                          * shows up */
  1381.         InvertRect (&r);
  1382.         cursor_invert = TRUE;
  1383.         }
  1384.     }
  1385.     }
  1386. }                /* flash_cursor */
  1387.  
  1388.  
  1389.  
  1390. /****************************************************************************/
  1391. /* Bittest returns the setting of an element in a Pascal PACKED ARRAY [0..n]
  1392.    OF Boolean such as the KeyMap argument returned by GetKeys(). */
  1393. /****************************************************************************/
  1394. Boolean
  1395. bittest (bitmap, bitnum)
  1396. char bitmap[];
  1397. int bitnum;
  1398. {
  1399.     return (0x01 & (bitmap[bitnum / 8] >> (bitnum % 8)));
  1400. }                /* bittest */
  1401.  
  1402.  
  1403.  
  1404. /****************************************************************************/
  1405. /* check to see if the cursor is in the window and is going to send a mouse-
  1406.    arrow keys combination */
  1407. /****************************************************************************/
  1408. check_pointer (theWindow)
  1409. WindowPtr theWindow;
  1410. {
  1411.     Boolean mouse_in_window;
  1412.     int newlin;
  1413.     int newcol;
  1414.     Point MousePt;
  1415.     Rect r;
  1416.  
  1417.     /*
  1418.      * PWP: NOTE!!! since the common case is to do nothing, we do NOT want to
  1419.      * have the PenMode() calls outside of the tests. We will be only doing
  1420.      * one or the other anyway, so it won't slow us down any.
  1421.      */
  1422.  
  1423.     GetMouse (&MousePt);
  1424.     mouse_in_window = PtInRect (&MousePt, &ScreenRect);
  1425.  
  1426.     newlin = (MousePt.v - TOPMARGIN) / LINEHEIGHT;
  1427.     newcol = (MousePt.h - LEFTMARGIN) / CHARWIDTH;
  1428.  
  1429.  
  1430.     if ((FrontWindow () == theWindow) && (mouse_in_window) &&
  1431.     (cur_drawn) && (mouse_arrows) && Button ()) {
  1432.     PenMode (patXor);    /* For FrameRect calls */
  1433.     if ((oldlin != newlin) || (oldcol != newcol)) {
  1434.         if (oldlin >= 0) {
  1435.         cursor_rect (oldlin, oldcol, &r);
  1436.         FrameRect (&r);
  1437.         } else
  1438.         HideCursor ();
  1439.  
  1440.         cursor_rect (newlin, newcol, &r);
  1441.         FrameRect (&r);
  1442.  
  1443.         oldlin = newlin;
  1444.         oldcol = newcol;
  1445.     }
  1446.     PenMode (patCopy);    /* reset to normal pen mode */
  1447.     }
  1448.     if (oldlin >= 0) {        /* optomize: easy tests first */
  1449.     if ((FrontWindow () != theWindow) || (!mouse_in_window) ||
  1450.         (!cur_drawn) || (!mouse_arrows) || (!Button ())) {
  1451.         PenMode (patXor);    /* For FrameRect calls */
  1452.         cursor_rect (oldlin, oldcol, &r);
  1453.         FrameRect (&r);
  1454.  
  1455.         oldlin = -1;
  1456.         InitCursor ();    /* show the arrow cursor immediately */
  1457.         /* (reset crsr level) */
  1458.         PenMode (patCopy);    /* reset to normal pen mode */
  1459.     }
  1460.     }
  1461. }                /* check_pointer */
  1462.  
  1463.  
  1464. mouse_cursor_move (evt)
  1465. EventRecord *evt;
  1466. {
  1467.     int mouselin;
  1468.     int mousecol;
  1469.     int tempcol;
  1470.     int templin;
  1471.     int i;
  1472.     Point MousePt;
  1473.  
  1474.     if (!mouse_arrows)        /* PWP: make this an option */
  1475.     return;
  1476.  
  1477.     MousePt = evt->where;
  1478.     GlobalToLocal (&MousePt);
  1479.     mouselin = (MousePt.v - TOPMARGIN) / LINEHEIGHT;
  1480.     mousecol = (MousePt.h - LEFTMARGIN) / CHARWIDTH;
  1481.     tempcol = curcol;
  1482.     templin = abslin;
  1483.  
  1484.     if (mousecol < tempcol)
  1485.     for (i = tempcol; i > mousecol; i--) {
  1486.         writeps (leftARROW);
  1487.         waitasec ();
  1488.         /* If tabs are used, we may go too far, so end loop */
  1489.         if (curcol <= mousecol)
  1490.         i = mousecol;
  1491.     }
  1492.  
  1493.     if (mouselin < templin)
  1494.     for (i = templin; i > mouselin; i--) {
  1495.         writeps (UPARROW);
  1496.         waitasec ();
  1497.     }
  1498.  
  1499.     else if (mouselin > templin)
  1500.     for (i = templin; i < mouselin; i++) {
  1501.         writeps (DOWNARROW);
  1502.         waitasec ();
  1503.     }
  1504.  
  1505.     if (abslin == mouselin)
  1506.     tempcol = curcol;    /* for short lines */
  1507.  
  1508.     if (tempcol < mousecol)
  1509.     for (i = tempcol; i < mousecol; i++) {
  1510.         writeps (rightARROW);
  1511.         waitasec ();
  1512.         /* If tabs are used, we may go too far, so end loop */
  1513.         if (curcol >= mousecol)
  1514.         i = mousecol;
  1515.     }
  1516. }                /* mouse_cursor_move */
  1517.  
  1518.  
  1519.  
  1520. /****************************************************************************/
  1521. /* (UoR) get any characters, and pause for a while */
  1522. /****************************************************************************/
  1523. waitasec ()
  1524. {
  1525.     long end_time;
  1526.  
  1527.     end_time = TickCount () + 2;/* pause for 1/30th second */
  1528.     while (TickCount () < end_time);
  1529.     inpchars ();
  1530. }                /* waitasec */
  1531.  
  1532.  
  1533.  
  1534. set_scroll_region ()
  1535. {
  1536.     if (--num1 < 0)
  1537.     num1 = 0;        /* Make top of line (prev line) */
  1538.     if (num2 == 0)
  1539.     num2 = 24;        /* Zero means entire screen */
  1540.  
  1541.     if (num1 < num2 - 1) {    /* (UoR) make sure region is legal */
  1542.     topmargin = (num1 * LINEHEIGHT) + TOPMARGIN;
  1543.     bottommargin = (num2 * LINEHEIGHT) + TOPMARGIN;
  1544.  
  1545.     scrtop = fndrel (num1);
  1546.     scrbot = fndrel (num2 - 1);
  1547.  
  1548.     home_cursor ();        /* We're supposed to home it! */
  1549.     }
  1550. }                /* set_scroll_region */
  1551.  
  1552.  
  1553.  
  1554. /****************************************************************************/
  1555. /* aka Select Graphic Rendition */
  1556. /****************************************************************************/
  1557. text_mode ()
  1558. {
  1559. another:
  1560.     switch (num1) {
  1561.       case 0:            /* primary rendition */
  1562.     doinvert = FALSE;
  1563.     TextFont (VT100FONT);    /* (Uor) Use plain font */
  1564.     currentfont = VT100FONT;
  1565.     dounder = FALSE;    /* textstyle=0; TextFace(0); */
  1566.     break;
  1567.  
  1568.       case 1:            /* bold or increased intensity */
  1569.     TextFont (VT100BOLD);    /* use bold font instead */
  1570.     currentfont = VT100BOLD;
  1571.     break;
  1572.  
  1573.       case 2:            /* faint or decreased intensity or secondary
  1574.                  * color */
  1575.       case 3:            /* italic */
  1576.       case 4:            /* underscore */
  1577.     /* textstyle+=underline; *//* use = not += (avoid roll-over) */
  1578.     /* textstyle = underline;    /* (UoR) */
  1579.     /* TextFace(textstyle); */
  1580.     dounder = TRUE;
  1581.     break;
  1582.  
  1583.       case 5:            /* slow blink (< 150/sec); (UoR) blink is
  1584.                  * inverse */
  1585.       case 6:            /* fast blink (>= 150/sec) */
  1586.       case 7:            /* reverse image */
  1587.     doinvert = TRUE;
  1588.     break;
  1589.  
  1590.       case 21:
  1591.       case 22:
  1592.     TextFont (VT100FONT);    /* reset to plain font */
  1593.     currentfont = VT100FONT;
  1594.     break;
  1595.  
  1596.       case 24:
  1597.     /* TextFace(0);        /* just reset to plain style */
  1598.     /* since bolding is done via a separate font */
  1599.     /* textstyle = 0; */
  1600.     dounder = FALSE;
  1601.     break;
  1602.  
  1603.       case 25:
  1604.       case 27:
  1605.     doinvert = FALSE;
  1606.     break;
  1607.     }
  1608.     if (num2 != 0) {        /* Check for funny VAXTPU syntax. */
  1609.     num1 = num2;
  1610.     num2 = 0;
  1611.     goto another;
  1612.     }
  1613. }                /* text_mode */
  1614.  
  1615.  
  1616.  
  1617. /****************************************************************************/
  1618. /*
  1619.  * (UoR)
  1620.  *
  1621.  * Insert and Delete lines (replacements for originals, which have
  1622.  *   which have been deleted)
  1623.  *
  1624.  */
  1625. /****************************************************************************/
  1626. insert_line ()
  1627. {
  1628.     int i, absbot;
  1629.  
  1630.     absbot = fndabs (scrbot);
  1631.  
  1632.     if ((abslin >= fndabs (scrtop)) && (abslin <= absbot)) {
  1633.     if (num1 == 0)
  1634.         num1 = 1;
  1635.     if (num1 > absbot - abslin + 1)
  1636.         num1 = absbot - abslin + 1;
  1637.  
  1638.     for (i = 0; i < num1; i++)
  1639.         scroll_down (curlin, scrbot);
  1640.     }
  1641. }                /* insert_line */
  1642.  
  1643.  
  1644.  
  1645. delete_line ()
  1646. {
  1647.     int i, absbot;
  1648.  
  1649.     absbot = fndabs (scrbot);
  1650.  
  1651.     if ((abslin >= fndabs (scrtop)) && (abslin <= absbot)) {
  1652.     if (num1 == 0)
  1653.         num1 = 1;
  1654.     if (num1 > absbot - abslin + 1)
  1655.         num1 = absbot - abslin + 1;
  1656.  
  1657.     for (i = 0; i < num1; i++)
  1658.         scroll_up (curlin, scrbot);
  1659.     }
  1660. }                /* delete_line */
  1661.  
  1662.  
  1663.  
  1664. delete_char ()
  1665. {
  1666.     int i;
  1667.     Rect r;
  1668.  
  1669.     if (num1 == 0)
  1670.     num1 = 1;
  1671.  
  1672.     makerect (&r, abslin, curcol, 1, MAXCOL - curcol);
  1673.  
  1674.     if (num1 > MAXCOL - curcol - 1)
  1675.     num1 = MAXCOL - curcol - 1;
  1676.  
  1677.     /* Scroll them out */
  1678.     ScrollRect (&r, -CHARWIDTH * num1, 0, dummyRgn);
  1679.  
  1680.     /* Shift them down *//* (UoR) used to assign using abscol */
  1681.     for (i = curcol; i < MAXCOL - num1; i++)
  1682.     scr[curlin][i] = scr[curlin][i + num1];
  1683.  
  1684.     /* Fill in holes with spaces */
  1685.     while (i < MAXCOL)
  1686.     scr[curlin][i++] = ' ';
  1687. }                /* delete_char */
  1688.  
  1689.  
  1690.  
  1691. /****************************************************************************/
  1692. /* CME */
  1693. /****************************************************************************/
  1694. insert_chars ()
  1695. {
  1696.     int i;
  1697.     Rect r;
  1698.  
  1699.     if (num1 == 0)
  1700.     num1 = 1;
  1701.  
  1702.     makerect (&r, abslin, curcol, 1, MAXCOL - curcol);
  1703.  
  1704.     if (num1 > MAXCOL - curcol - 1)
  1705.     num1 = MAXCOL - curcol - 1;
  1706.  
  1707.     /* Scroll them out */
  1708.     ScrollRect (&r, CHARWIDTH * num1, 0, dummyRgn);
  1709.  
  1710.     /* Shift them up *//* (UoR) used to assign using abscol */
  1711.     for (i = MAXCOL - 1; i >= curcol + num1; i--)
  1712.     scr[curlin][i] = scr[curlin][i - num1];
  1713.  
  1714.     /* Fill in holes with spaces */
  1715.     while (i > curcol)
  1716.     scr[curlin][--i] = ' ';
  1717. }                /* delete_char */
  1718.  
  1719.  
  1720.  
  1721. insert_char ()
  1722. {
  1723.     int i;
  1724.     Rect r;
  1725.  
  1726.     makerect (&r, abslin, curcol, 1, MAXCOL - curcol);
  1727.     ScrollRect (&r, CHARWIDTH, 0, dummyRgn);
  1728.  
  1729.     /* Shift em up *//* (UoR) used to assign ...[i-1]=...[i] */
  1730.     /* (UoR) used to assign using abscol */
  1731.  
  1732.     for (i = MAXCOL - 1; i > curcol; i--)
  1733.     scr[curlin][i] = scr[curlin][i - 1];
  1734.  
  1735.     scr[curlin][curcol] = ' ';
  1736. }                /* insert_char */
  1737.  
  1738.  
  1739.  
  1740. insert_mode ()
  1741. {
  1742.     if (prvchr == '?')
  1743.     set_mode ();        /* (UoR) do some of these calls */
  1744.  
  1745.     switch (num1) {
  1746.       case 20:
  1747.     newline = TRUE;
  1748.     break;
  1749.  
  1750.       case 4:
  1751.     insert = TRUE;
  1752.     break;
  1753.     }
  1754. }                /* insert_mode */
  1755.  
  1756.  
  1757.  
  1758. end_insert_mode ()
  1759. {
  1760.     if (prvchr == '?')
  1761.     reset_mode ();        /* (UoR) do some of these calls */
  1762.  
  1763.     switch (num1) {
  1764.       case 20:
  1765.     newline = FALSE;
  1766.     break;
  1767.  
  1768.       case 4:
  1769.     insert = FALSE;
  1770.     break;
  1771.     }
  1772. }                /* end_insert_mode */
  1773.  
  1774.  
  1775.  
  1776. invert_term ()
  1777. {
  1778.     num1 = 5;
  1779.     if (screeninvert)
  1780.     reset_mode ();
  1781.     else
  1782.     set_mode ();
  1783. }                /* invert_term */
  1784.  
  1785.  
  1786.  
  1787. set_mode ()
  1788. {
  1789.     Rect r;
  1790.  
  1791.     switch (num1) {
  1792.       case 5:
  1793.     if (screeninvert == FALSE) {
  1794.         BackPat (qd.black);    /* (UoR) use black background */
  1795.         makerect (&r, 0, 0, MAXLIN, MAXCOL);
  1796.         InvertRect (&r);
  1797.         screeninvert = TRUE;
  1798.     }
  1799.     break;
  1800.  
  1801.       case 6:
  1802.     relorigin = TRUE;
  1803.     home_cursor ();
  1804.     break;
  1805.  
  1806.       case 7:
  1807.     autowrap = TRUE;
  1808.     break;
  1809.  
  1810.       case 8:
  1811.     autorepeat = TRUE;
  1812.     break;
  1813.     }
  1814. }                /* set_mode */
  1815.  
  1816.  
  1817.  
  1818. reset_mode ()
  1819. {
  1820.     Rect r;
  1821.  
  1822.     switch (num1) {
  1823.       case 5:
  1824.     if (screeninvert) {
  1825.         BackPat (qd.white);
  1826.         makerect (&r, 0, 0, MAXLIN, MAXCOL);
  1827.         InvertRect (&r);
  1828.         screeninvert = FALSE;
  1829.     }
  1830.     break;
  1831.  
  1832.       case 6:
  1833.     relorigin = FALSE;
  1834.     home_cursor ();
  1835.     break;
  1836.  
  1837.       case 7:
  1838.     autowrap = FALSE;
  1839.     break;
  1840.  
  1841.       case 8:
  1842.     autorepeat = FALSE;
  1843.     break;
  1844.     }
  1845. }                /* reset_mode */
  1846.  
  1847.  
  1848.  
  1849. set_tab ()
  1850. {
  1851.     tabstops[curcol] = 1;
  1852. }                /* set_tab */
  1853.  
  1854.  
  1855.  
  1856. clear_tab ()
  1857. {
  1858.     int i;
  1859.  
  1860.     switch (num1) {
  1861.       case 0:
  1862.     tabstops[curcol] = 0;
  1863.     break;
  1864.  
  1865.       case 3:
  1866.     for (i = 0; i < MAXCOL; i++)
  1867.         tabstops[i] = 0;
  1868.     break;
  1869.     }
  1870. }                /* clear_tab */
  1871.  
  1872.  
  1873.  
  1874. /****************************************************************************/
  1875. /* (UoR) use for respoding to information requests */
  1876. /****************************************************************************/
  1877. writereply (s)
  1878. char *s;
  1879. {
  1880.     long wrcnt, w2;
  1881.     int err;
  1882.     char *s2;
  1883.  
  1884.     w2 = wrcnt = strlen (s);    /* How long is the string? */
  1885.     for (s2 = s; w2 > 0; w2--, s2++)    /* add parity */
  1886.     *s2 = dopar (*s2);
  1887.     err = FSWrite (outnum, &wrcnt, s);    /* Respond to the query */
  1888.     if (err)
  1889.     printerr ("Bad Writeout:", err);
  1890. }                /* writereply */
  1891.  
  1892.  
  1893.  
  1894. query_terminal ()
  1895. {
  1896.     writereply (querystring);
  1897. }                /* query_terminal */
  1898.  
  1899.  
  1900.  
  1901. /****************************************************************************/
  1902. /* (UoR) reports */
  1903. /****************************************************************************/
  1904. request_report ()
  1905. {
  1906.     switch (num1) {
  1907.       case 5:            /* (UoR) report that we're OK */
  1908.     writereply (reportstring);
  1909.     break;
  1910.  
  1911.       case 6:            /* (UoR) reprt the cursor position */
  1912.     position_report ();
  1913.     break;
  1914.  
  1915.       case 15:            /* (UoR) report printer status */
  1916.     if (prvchr == '?')
  1917.         writereply (noprinter);
  1918.     break;
  1919.     }
  1920. }                /* request_report */
  1921.  
  1922.  
  1923.  
  1924. position_report ()
  1925. {
  1926.     int i;
  1927.     char buf[9];
  1928.     char *report;
  1929.  
  1930.     i = 0;
  1931.     buf[i++] = '\033';
  1932.     buf[i++] = '[';
  1933.     if (abslin > 9)
  1934.     buf[i++] = '0' + (abslin + 1) / 10;
  1935.     buf[i++] = '0' + (abslin + 1) % 10;
  1936.     buf[i++] = ';';
  1937.     if (curcol > 9)
  1938.     buf[i++] = '0' + (curcol + 1) / 10;
  1939.     buf[i++] = '0' + (curcol + 1) % 10;
  1940.     buf[i++] = 'R';
  1941.     buf[i] = '\0';
  1942.     report = buf;
  1943.     writereply (report);
  1944. }                /* position_report */
  1945.  
  1946.  
  1947.  
  1948. /****************************************************************************/
  1949. /* does nothing. */
  1950. /****************************************************************************/
  1951. dummy ()
  1952. {
  1953. }                /* dummy */
  1954.  
  1955.  
  1956.  
  1957. multi_char ()
  1958. {
  1959.     numone[0] = numtwo[0] = '0';/* Initialize the numbers to zero */
  1960.     numone[1] = numtwo[1] = '\0';
  1961.     numptr = numone;        /* Place to put the next number */
  1962.     prvchr = '\0';        /* No priv char yet */
  1963.     charflg = CF_MESC;        /* Say we are in a ESC [ swequence */
  1964. }                /* multi_char */
  1965.  
  1966.  
  1967.  
  1968. toss_char ()
  1969. {
  1970.     charflg = CF_TOSS;
  1971. }                /* toss_char */
  1972.  
  1973.  
  1974.  
  1975. /****************************************************************************/
  1976. /* Routine zeroline
  1977.  *
  1978.  * Zero (set to space) all the characters in relative line lin.
  1979.  *
  1980.  */
  1981. /****************************************************************************/
  1982. zeroline (lin)
  1983. int lin;
  1984. {
  1985.     register int i;
  1986.     Rect r;
  1987.  
  1988.     for (i = 0; i < MAXCOL; i++)
  1989.     scr[lin][i] = ' ';
  1990. }                /* zeroline */
  1991.  
  1992.  
  1993.  
  1994. /****************************************************************************/
  1995. /* Move a relative number of lines and chars.  Both can be negative. */
  1996. /****************************************************************************/
  1997. relmove (hor, ver)
  1998. {
  1999.     absmove (curcol + hor, abslin + ver);    /* (UoR) use absmove, which
  2000.                          * checks */
  2001.     /* for cursor moving off screen */
  2002. }                /* relmove */
  2003.  
  2004.  
  2005.  
  2006. /****************************************************************************/
  2007. /* Move to absolute position hor char and ver line. */
  2008. /****************************************************************************/
  2009. absmove (hor, ver)
  2010. {
  2011.     if (hor > MAXCOL - 1)
  2012.     hor = MAXCOL - 1;    /* (UoR) make sure its on the screen */
  2013.     if (hor < 0)
  2014.     hor = 0;
  2015.     if (ver > MAXLIN - 1)
  2016.     ver = MAXLIN - 1;
  2017.     if (ver < 0)
  2018.     ver = 0;
  2019.     if (relorigin) {
  2020.     if (ver < fndabs (scrtop))
  2021.         ver = fndabs (scrtop);
  2022.     if (ver > fndabs (scrbot))
  2023.         ver = fndabs (scrbot);
  2024.     }
  2025.     MoveTo (hor * CHARWIDTH + LEFTMARGIN, (ver + 1) * LINEHEIGHT + TOPMARGIN - LINEADJ);
  2026.     curcol = hor;
  2027.     abslin = ver;
  2028.     curlin = fndrel (ver);
  2029. }                /* absmove */
  2030.  
  2031.  
  2032.  
  2033. /****************************************************************************/
  2034. /* dump the whole screen to the session log file */
  2035. /****************************************************************************/
  2036. scrtolog ()
  2037. {
  2038.     int lin, i;
  2039.  
  2040.     lin = toplin;
  2041.     for (i = 0; i < MAXLIN; i++) {
  2042.     slog (scr[lin], MAXCOL);/* write this line to session log */
  2043.     lin = nxtlin[lin];
  2044.     }
  2045. }                /* scrtolog */
  2046.  
  2047.  
  2048.  
  2049. /****************************************************************************/
  2050. /*
  2051.  * (UoR)
  2052.  *
  2053.  * Scroll lines within the scroll region upwards from line tlin
  2054.  * to line blin (lines are assumed to be in the region)
  2055.  *
  2056.  */
  2057. /****************************************************************************/
  2058. scroll_up (tlin, blin)
  2059. int tlin;
  2060. int blin;
  2061. {
  2062.     register int i, now;
  2063.     int newtop;
  2064.     int abstop;
  2065.     Rect r;
  2066.     GrafPtr currWindow;
  2067.  
  2068.     abstop = fndabs (tlin);
  2069.     makerect (&r, abstop, 0, fndabs (blin) - abstop + 1, MAXCOL);
  2070.  
  2071.     ObscureCursor ();
  2072.  
  2073.     /* compensate update region for scrolling */
  2074.     GetPort (&currWindow);
  2075.     OffsetRgn ((WindowPeek) currWindow->updateRgn, 0, -LINEHEIGHT);
  2076.  
  2077.     /* do the scrolling */
  2078.     if (smoothscroll) {
  2079.     for (i = 1; i <= LINEHEIGHT; i += 2) {
  2080.         /* PWP: wait for a vertical reblank (in a sneaky way) */
  2081.         now = TickCount ();
  2082.         while (TickCount () == now)
  2083.          /* wait... */ ;
  2084.         ScrollRect (&r, 0, -2, dummyRgn);
  2085.     }
  2086.     } else {
  2087.     ScrollRect (&r, 0, -LINEHEIGHT, dummyRgn);
  2088.     }
  2089.  
  2090.     if (tlin == blin) {        /* if only one line, just clear it */
  2091.     zeroline (blin);
  2092.     return;
  2093.     }
  2094.     newtop = nxtlin[tlin];    /* new top line */
  2095.  
  2096.     if (tlin == scrtop)
  2097.     scrtop = newtop;    /* reset scrtop, if needed */
  2098.     if (tlin == toplin)
  2099.     toplin = newtop;    /* reset toplin, if needed */
  2100.     else
  2101.     nxtlin[fndprv (tlin)] = newtop;    /* else de-link tlin line */
  2102.  
  2103.     nxtlin[tlin] = nxtlin[blin];/* link tlin in after blin */
  2104.     nxtlin[blin] = tlin;
  2105.  
  2106.     if (blin == scrbot) {    /* reset pointers to bottom of regions */
  2107.     if (blin == botlin)
  2108.         botlin = tlin;
  2109.     scrbot = tlin;
  2110.     }
  2111.     if (seslog)            /* if logging is active then */
  2112.     slog (scr[tlin], MAXCOL);    /* write line to session log */
  2113.     zeroline (tlin);        /* clear the line */
  2114.     curlin = fndrel (abslin);
  2115. }                /* scroll_up */
  2116.  
  2117.  
  2118.  
  2119. /****************************************************************************/
  2120. /* (UoR) Scroll lines in scroll region down from line tlin to     */
  2121. /* line blin (lines are assumed to be within the scroll region)    */
  2122. /****************************************************************************/
  2123. scroll_down (tlin, blin)
  2124. int tlin;
  2125. int blin;
  2126. {
  2127.     int i;
  2128.     int abstop;
  2129.     int newbot;
  2130.     Rect r;
  2131.     GrafPtr currWindow;
  2132.  
  2133.     abstop = fndabs (tlin);
  2134.     makerect (&r, abstop, 0, fndabs (blin) - abstop + 1, MAXCOL);
  2135.  
  2136.     ObscureCursor ();
  2137.  
  2138.     /* compensate update region for scrolling */
  2139.     GetPort (&currWindow);
  2140.     OffsetRgn ((WindowPeek) currWindow->updateRgn, 0, LINEHEIGHT);
  2141.  
  2142.     /* do the scrolling */
  2143.  
  2144.     if (smoothscroll)
  2145.     for (i = 1; i <= LINEHEIGHT; i += 2)
  2146.         ScrollRect (&r, 0, 2, dummyRgn);
  2147.     else
  2148.     ScrollRect (&r, 0, LINEHEIGHT, dummyRgn);
  2149.  
  2150.     if (tlin == blin) {        /* if only one line, just clear it */
  2151.     zeroline (tlin);
  2152.     return;
  2153.     }
  2154.     newbot = fndprv (blin);    /* new bottom line */
  2155.  
  2156.     if (tlin == scrtop)
  2157.     scrtop = blin;        /* reset scrtop, if needed */
  2158.     if (tlin == toplin)
  2159.     toplin = blin;        /* reset toplin, if needed */
  2160.     else
  2161.     nxtlin[fndprv (tlin)] = blin;    /* else de-link top line */
  2162.  
  2163.     nxtlin[newbot] = nxtlin[blin];    /* link blin above tlin */
  2164.     nxtlin[blin] = tlin;
  2165.  
  2166.     if (blin == scrbot) {    /* reset bottom of region pointers */
  2167.     if (blin == botlin)
  2168.         botlin = newbot;
  2169.     scrbot = newbot;
  2170.     }
  2171.     zeroline (blin);
  2172.     curlin = fndrel (abslin);
  2173. }                /* scroll_down */
  2174.  
  2175.  
  2176.  
  2177. /****************************************************************************/
  2178. /*
  2179.  * Find the relative line number given the absolute one.
  2180.  *
  2181.  */
  2182. /****************************************************************************/
  2183. fndrel (linum)
  2184. int linum;
  2185. {
  2186.     register int i, lin;
  2187.  
  2188.     lin = toplin;
  2189.     for (i = 0; i < linum; i++)
  2190.     lin = nxtlin[lin];
  2191.     return (lin);
  2192. }                /* fndrel */
  2193.  
  2194.  
  2195.  
  2196. /****************************************************************************/
  2197. /*
  2198.  * Find the absolute line number given the relative one.
  2199.  *
  2200.  */
  2201. /****************************************************************************/
  2202. fndabs (linum)
  2203. int linum;
  2204. {
  2205.     int i, lin;
  2206.  
  2207.     lin = toplin;
  2208.     i = 0;
  2209.     while (lin != linum) {
  2210.     i++;
  2211.     lin = nxtlin[lin];
  2212.     }
  2213.     return (i);
  2214. }                /* fndabs */
  2215.  
  2216.  
  2217.  
  2218. /****************************************************************************/
  2219. /*
  2220.  * Find the previous relative line number from relative line linum.
  2221.  *
  2222.  */
  2223. /****************************************************************************/
  2224. fndprv (linum)
  2225. int linum;
  2226. {
  2227.     int lin;
  2228.  
  2229.     lin = toplin;
  2230.     while (nxtlin[lin] != linum)
  2231.     lin = nxtlin[lin];
  2232.     return (lin);
  2233. }                /* fndprv */
  2234.  
  2235.  
  2236.  
  2237. /****************************************************************************/
  2238. /* redraw the terminal screen (we got a redraw event) */
  2239. /****************************************************************************/
  2240. term_redraw ()
  2241. {
  2242.     int i, lin;
  2243.     Rect r;
  2244.  
  2245.     makerect (&r, 0, 0, MAXLIN, MAXCOL);    /* PWP: clear the screen first */
  2246.     EraseRect (&r);
  2247.  
  2248.     lin = toplin;
  2249.     for (i = 0; i < MAXLIN; i++) {
  2250.     MoveTo (LEFTMARGIN, (i + 1) * LINEHEIGHT + TOPMARGIN - LINEADJ);
  2251.     DrawString (scr[lin]);
  2252. #ifdef COMMENT
  2253.     if (screeninvert) {    /* (UoR) refresh screen in invert mode */
  2254.         makerect (&r, i, 0, 1, MAXCOL);
  2255.         InvertRect (&r);    /* PWP: was Erase, but that does no good */
  2256.     }
  2257. #endif
  2258.     lin = nxtlin[lin];
  2259.     }
  2260.  
  2261.     MoveTo (curcol * CHARWIDTH + LEFTMARGIN,
  2262.         (abslin + 1) * LINEHEIGHT + TOPMARGIN - LINEADJ);
  2263.  
  2264.     if (cur_drawn && cursor_invert) {    /* (UoR) only if cursor is showing */
  2265.     cursor_invert = FALSE;    /* (UoR) make sure we draw it */
  2266.     cursor_draw ();        /* redraw cursor */
  2267.     last_flash = TickCount ();    /* (UoR) reset timer */
  2268.     }
  2269. }                /* term_redraw */
  2270.  
  2271.  
  2272.  
  2273. /****************************************************************************/
  2274. /* initalize the terminal emulator. */
  2275. /****************************************************************************/
  2276. init_term ()
  2277. {
  2278.     int i;
  2279.  
  2280.     for (i = 0; i < MAXLIN; i++) {
  2281.     nxtlin[i] = i + 1;    /* Tie together the linked list */
  2282.     scr[i][MAXCOL] = '\0';    /* Terminate the lines as strings */
  2283.     }
  2284.     toplin = 0;            /* Initialize the top and bottom ptr */
  2285.     botlin = MAXLIN - 1;
  2286.     scrtop = toplin;        /* Scrolling region equals all */
  2287.     scrbot = botlin;
  2288.     nxtlin[botlin] = -1;    /* Indicate this is the end */
  2289.     makerect (&ScreenRect, 0, 0, MAXLIN, MAXCOL);
  2290.     /* (UoR) full screen rectangle */
  2291. }                /* init_term */
  2292.