home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / old / ckermit4f / ckmco2.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  57KB  |  2,070 lines

  1. /*
  2.  * FILE ckmco2.c
  3.  *
  4.  * Module of mackermit: contains code for dealing with the Mac side
  5.  * of terminal emulation.
  6.  */
  7.  
  8. #include "ckcdeb.h"
  9.  
  10. #define    __SEG__    ckmcon
  11. #include <quickdraw.h>
  12. #include <controls.h>
  13. #include <devices.h>
  14. #include <serial.h>
  15. #include <files.h>
  16. #include <events.h>
  17. #include <windows.h>
  18. #include <dialogs.h>
  19. #include <menus.h>
  20. #include <toolutils.h>
  21. #include <osutils.h>
  22. #include <resources.h>
  23. #include <ctype.h>
  24. #include <Script.h>
  25. #include <Memory.h>
  26.  
  27. #include "ckmdef.h"
  28. #include "ckmasm.h"        /* Assembler code */
  29. #include "ckmres.h"        /* kermit resources */
  30.  
  31. #include "ckmcon.h"        /* defines, etc. for terminal emulator */
  32.  
  33. extern WindowPtr terminalWindow;    /* the terminal window */
  34. Rect ScreenRect;
  35. ControlHandle t_vscroll;
  36.  
  37.  /*
  38.   * (UoR) don't need scrollrect any more (use scroll_up and scroll_down), use
  39.   * ScreenRect for mouse check
  40.   */
  41.  
  42. /* Screen book keeping variables */
  43. extern int screensize,        /* variable number of lines on screen */
  44.     topmargin,            /* Edges of adjustable window */
  45.     bottommargin,
  46.     graphicsinset[4],        /* (UoR) current character sets */
  47.     Gl_set,             /* (UoR) current chosen set */
  48.     Gr_set,            /* (PWP) current chosen upper set */
  49.     screeninvert,        /* (UoR) inverted screen flag */
  50.     insert,
  51.     newline,            /* (UoR) linefeed mode by default */
  52.     autowrap,            /* Autowrap on by default */
  53.     relorigin,            /* (UoR) relative origin off */
  54.     autorepeat,            /* (UoR) auto repeat flag */
  55.     appl_mode,            /* (PWP) application mode */
  56.     curskey_mode,        /* (PWP) cursor key application mode */
  57.     smoothscroll,        /* do smooth scrolling (PWP: or not) */
  58.     transparent,        /* do not show control characters */
  59.     blockcursor,        /* show block or underline cursor */
  60.     cursor_shown,        /* (PWP) show the cursor */
  61.     mouse_arrows,        /* mouse down in screen does arrow keys */
  62.     visible_bell,        /* true if we do blink instead of bell */
  63.     eightbit_disp,        /* do 8 bit wide to the screen */
  64.     blinkcursor;        /* true if we make the cursor blink */
  65.  
  66. extern ucharptr *scr, *scr_attrs;        /* virtual screen pointer */
  67. extern ucharptr real_scr[MAX_SCREENSIZE];    /* The real screen, including scrollback */
  68. extern ucharptr real_attrs[MAX_SCREENSIZE];    /* the attributes of each character */
  69.  
  70. int display_topline;        /* top line actually displayed */
  71. int display_totlines;        /* number of real lines in screen + scrollback */
  72. extern int curlin, curcol;    /* Cursor position */
  73. extern int savcol, savlin;        /* Cursor save variables */
  74. extern int savsty, savfnt, savgrf, savmod, savset[2];    /* (UoR) cursor save
  75.                          * variables */
  76. extern int savund;            /* PWP for saved underlining */
  77. extern int scrtop, scrbot;        /* Absolute scrolling region bounds */
  78.  
  79. int textstyle = 0;        /* (UoR) current style */
  80. int current_style = 0;
  81. int draw_sing_chars = FALSE;
  82.  
  83. int oldlin = -1;
  84. int oldcol = 0;            /* (UoR) for last mouse position */
  85.  
  86. /* (PWP) variables for controling the selected text */
  87. int from_lin = -1;
  88. int from_col = 0;
  89. int to_lin;
  90. int to_col;
  91. Boolean have_selection = 0;
  92.  
  93. #define ABS(a)    ((a) < 0 ? -(a) : (a))
  94.  
  95. int cursor_invert = FALSE,    /* (UoR) for flashing cursor */
  96.     cur_drawn = FALSE;
  97. long last_flash = 0;
  98.  
  99. char **myclip_h;        /* internal clipboard */
  100. int myclip_size;        /* size of above */
  101.  
  102. static int mousecurs_drawn = FALSE;    /* (PWP) is the mouse cursor drawn? */
  103.  
  104. static int in_front = 0;    /* PWP: true when we are the front window */
  105.  
  106. extern Boolean usingRAMdriver,
  107.            have_128roms;    /* true if we are a Plus or better */
  108.  
  109. RgnHandle dummyRgn;        /* dummy region for ScrollRect */
  110.                 /* Initialized in mac_init */
  111.  
  112. long MyCaretTime;        /* (UoR) ticks between flashes */
  113.  
  114. extern Cursor *textcurs, *normcurs, *watchcurs;    /* mouse cursor shapes */
  115.  
  116. extern    int        to_printer;        /*JAO*/
  117. extern    int        to_screen;        /*JAO*/
  118. extern    int        printer_is_on_line_num;    /*JAO*/
  119. extern    Handle    hPrintBuffer;            /*JAO*/
  120. extern    long    lPrintBufferSize;        /*JAO*/
  121. extern    long    lPrintBufferChars;        /*JAO*/
  122. extern    long    lPrintBufferAt;            /*JAO*/
  123.  
  124. extern    DialogPtr    bufferingDialog;    /*JAO*/
  125. extern    DialogPtr    overflowingDialog;    /*JAO*/
  126.  
  127. extern    MenuHandle menus[];    /* handle on our menus */  /*JAO*/
  128.  
  129. /* keyboard handling stuff */
  130.  
  131. extern char keytable[512];    /* the key redefintion flag table */
  132. extern modrec modtable[NUMOFMODS];    /* modifier records */
  133.  
  134. #define myKeyCodeMask    0x7F00
  135. #define keyModifierMask    0x1F00
  136. #define ctrlCodeMask    0x1F
  137. #define metaOrBits    0x80
  138.  
  139. #define UnmodMask    0x80        /* action bits */
  140. #define CapsMask    0x40
  141. #define CtrlMask    0x20
  142. #define MetaMask    0x10
  143.  
  144.  
  145. Boolean have_scriptmgr = FALSE;
  146.  
  147. long old_KCHR, old_SICN;    /* pointers to current system key script, icon */
  148. long cur_KCHR;
  149.  
  150. /***** forward decls ********/
  151.  
  152. void cursor_draw(), cursor_erase();
  153.  
  154. /****************************************************************************/
  155. /****************************************************************************/
  156. /****************************************************************************/
  157. /* keyboard event handling routines                                         */
  158. /****************************************************************************/
  159.  
  160.  
  161. InitKeyStuff()
  162. {
  163.     have_scriptmgr = NGetTrapAddress(num_UnknownTrap, 1) !=
  164.              NGetTrapAddress(num_ScriptTrap, 1);
  165.              
  166.     if (have_scriptmgr) {
  167.     old_KCHR = GetScript( smRoman, smScriptKeys);
  168.     old_SICN = GetScript( smRoman, smScriptIcon);
  169.     }
  170.     cur_KCHR = old_KCHR;
  171.  
  172.     UpdateOptKey(1);    /* get things set right initially */
  173. }
  174.  
  175. UpdateOptKey(enable)
  176. int enable;
  177. {
  178.     int i;
  179.     int futzit = 0;
  180.     
  181.     if (enable) {
  182.     for (i = 0; i < NUMOFMODS; i++) {
  183.     /* shift what to look for into high byte */
  184.         if ((modtable[i].modbits) & (optionKey >> 4))    /* if Option is selected */
  185.             futzit = 1;
  186.     }
  187.     } else {    /* allways turn off when disabling window */
  188.         futzit = 0;
  189.     }
  190.     
  191.     (void) FutzOptKey(futzit);
  192. }
  193.  
  194. FutzOptKey(enable)
  195. int enable;
  196. {
  197.     int err;
  198.     
  199.     if (have_scriptmgr) {        /* if we are system 4.1 or later... */
  200.     if (enable) {    /* no deadkeys */
  201.         if (cur_KCHR != old_KCHR)
  202.         return (1);    /* we are allready fine */
  203.         if (GetEnvirons(smKeyScript) == smRoman) {  /* only if in roman script */
  204.         /* set the key map */
  205.         err = SetScript (smRoman, smScriptKeys, NODEAD_KCHR);
  206.         if (err != noErr) {
  207.             printerr ("Trouble setting custom keymap (KCHR):", err);
  208.             return (0);
  209.         }
  210.         /* set the icon */
  211.         err = SetScript (smRoman, smScriptIcon, NODEAD_SICN);
  212.         if (err != noErr) {
  213.             printerr ("Trouble setting custom keymap icon (SICN):", err);
  214.             return (0);
  215.         }
  216.         KeyScript (smRoman);
  217.         cur_KCHR = NODEAD_KCHR;
  218.         return (1);    /* success! */
  219.         } else {
  220.             printerr("Can't disable Option key -- you have a non-US keyboard",0);
  221.             return (0);
  222.         }
  223.     } else {    /* back to normal */
  224.         if (cur_KCHR == old_KCHR)
  225.         return (1);    /* we are allready fine */
  226.         /* set the key map */
  227.         err = SetScript (smRoman, smScriptKeys, old_KCHR);
  228.         if (err != noErr) {
  229.         printerr ("Trouble resetting default keymap (KCHR):", err);
  230.         return (0);
  231.         }
  232.         /* set the icon */
  233.         err = SetScript (smRoman, smScriptIcon, old_SICN);
  234.         if (err != noErr) {
  235.         printerr ("Trouble resetting default keymap icon (SICN):", err);
  236.         return (0);
  237.         }
  238.         KeyScript (smRoman);
  239.         cur_KCHR = old_KCHR;
  240.         return (1);        /* success! */
  241.     }
  242.     } else {
  243.     /* do something or other to do the old way */
  244.     /* printerr("Kermit can't disable Option on old systems",0); */
  245.     }
  246.     return (0);
  247. }
  248.  
  249.  
  250. /****************************************************************************/
  251. /* return the ASCII character which is generated by the keyCode specified */
  252. /* with no modifiers pressed */
  253. /****************************************************************************/
  254. unsigned char
  255. DeModifyChar (keyCode, modifiers)
  256. long keyCode, modifiers;
  257. {
  258.     long c;
  259.     long mystate, retval;
  260.     short s_keycode;
  261.     Handle kchr_h;
  262.     THz curZone;
  263.  
  264. #ifdef COMMENT
  265.     ProcHandle KeyTrans;
  266.  
  267.     if (keyCode > 64)
  268.     KeyTrans = (ProcHandle) 0x2A2;    /* keypad decode */
  269.     else
  270.     KeyTrans = (ProcHandle) 0x29E;    /* keyboard decode */
  271.  
  272.     SaveRegs ();        /* save all registers */
  273.     AllRegs ();
  274.  
  275.     /* setup regs for procedure call */
  276.     /* loadD1 ((long) modifiers); */        /* no modifiers */
  277.     loadD1 ((long) 0);        /* no modifiers */
  278.     loadD2 ((long) keyCode);    /* set the keycode */
  279.     loadA0 (*KeyTrans);        /* load the content of Key1Trans to A0 */
  280.  
  281.     /* run the translation routine */
  282.     execute ();            /* call the Key1Trans procedure */
  283.  
  284.     /* move the result from reg D0 to c */
  285.     loadA0 (&c);        /* set destination address */
  286.     pushD0 ();            /* move register D0 to stack */
  287.     poptoA0 ();            /* load the stacktop to (A0) */
  288.  
  289.     RestoreRegs ();        /* restore all registers */
  290.     AllRegs ();
  291.  
  292. #endif /* COMMENT */
  293.  
  294.     if (have_scriptmgr) {        /* if we are system 4.1 or later... */
  295.         mystate = 0;
  296.     
  297.     kchr_h = GetResource('KCHR', cur_KCHR);
  298.     if (kchr_h == NIL) {
  299.         printerr("DeModifyChar: couldn't get KCHR address",0);
  300.         return(0);
  301.     }
  302.     LoadResource(kchr_h);
  303.     HLock(kchr_h);
  304.     
  305.     s_keycode = (modifiers & 0xff00) | (keyCode & 0xff);
  306.  
  307.     c = KeyTrans(*kchr_h, s_keycode, &mystate);
  308.     HUnlock(kchr_h);
  309.     curZone = GetZone();        /* as per John Norstad's (Disinfectant) */
  310.     SetZone(HandleZone(kchr_h));    /* "Toolbox Gotchas" */
  311.     ReleaseResource(kchr_h);
  312.     SetZone(curZone);
  313.     }    
  314.     return (c);
  315. }                /* DeModifyChar */
  316.  
  317.  
  318.  
  319. unsigned char obuf[2] = {1, 0};    /* single char output buffer */
  320.  
  321. /****************************************************************************/
  322. /* send a character to the line if it is in ASCII range. Do local echo if */
  323. /* necessary */
  324. /****************************************************************************/
  325. OutputChar (c)
  326. unsigned char c;
  327. {
  328.  
  329.     /*
  330.      * PWP: NO 7 bit masking!!!  If we do this, then I can't use Emacs, and
  331.      * the European users will be VERY unhappy, 'cause they won't be able to
  332.      * send all of their characters.
  333.      */
  334.  
  335.     obuf[1] = c;        /* store character */
  336.     writeps (obuf);        /* and write it out */
  337.  
  338.     if (duplex != 0) {
  339.     cursor_erase ();    /* remove from screen */
  340.     printit ((char) c);    /* Echo the char to the screen */
  341.     flushbuf ();        /* flush the character */
  342.     cursor_draw ();        /* put it back */
  343.     }
  344. }                /* OutputChar */
  345.  
  346. #ifdef COMMENT
  347. /****************************************************************************/
  348. /* Bittest returns the setting of an element in a Pascal PACKED ARRAY [0..n]
  349.    OF Boolean such as the KeyMap argument returned by GetKey
  350. /****************************************************************************/
  351. Boolean
  352. bittest (bitmap, bitnum)
  353. char bitmap[];
  354. int bitnum;
  355. {
  356.     return (0x01 & (bitmap[bitnum / 8] >> (bitnum % 8)));
  357. }                /* bittest */
  358.  
  359. /* PWP: or, as a macro, */
  360. #define bittest(bitmap,bitnum)    (0x01 & (bitmap[bitnum / 8] >> (bitnum % 8)))
  361.  
  362. #endif /* COMMENT */
  363.  
  364.  
  365. /****************************************************************************/
  366. /* Process a character received from the keyboard */
  367. /****************************************************************************/
  368. handle_char (evt)
  369. EventRecord *evt;
  370. {
  371.     short i;
  372.     short len;
  373.     short theCode;
  374.     short modCode;
  375.     short theModBits;
  376.     char flags;
  377.     char tmpstr[256];
  378.     unsigned char c;
  379.  
  380.     /* (UoR) check for auto repeated keys */
  381.     if ((autorepeat == FALSE) && (evt->what == autoKey))
  382.     return;
  383.  
  384.     ObscureCursor ();        /* PWP: hide the cursor until next move */
  385.  
  386.     modCode = evt->modifiers & keyModifierMask;
  387.     theCode = ((evt->message & myKeyCodeMask) >> 8) + (modCode >> 1);
  388.     
  389.     /* check for a special code for this key */
  390.     if (BitTst (keytable, theCode)) {
  391.     GetMacro (theCode, &flags, tmpstr);    /* get the macrostring */
  392.  
  393.     if (flags) {        /* check special flags */
  394.         switch (flags) {
  395.           case shortBreak:
  396.         sendbreak (5);
  397.         return;
  398.  
  399.           case longBreak:
  400.         sendbreak (70);
  401.         return;
  402.  
  403.           case leftArrowKey:
  404.         do_arrow (leftARROW);
  405.         return;
  406.  
  407.           case rightArrowKey:
  408.         do_arrow (rightARROW);
  409.         return;
  410.  
  411.           case upArrowKey:
  412.         do_arrow (UPARROW);
  413.         return;
  414.  
  415.           case downArrowKey:
  416.         do_arrow (DOWNARROW);
  417.         return;
  418.         
  419.           case keycomma:
  420.           case keyminus:
  421.           case keyperiod:
  422.           /* there is no keyslash */
  423.           case key0:
  424.           case key1:
  425.           case key2:
  426.           case key3:
  427.           case key4:
  428.           case key5:
  429.           case key6:
  430.           case key7:
  431.           case key8:
  432.           case key9:
  433.         do_keypad(flags - keycomma);
  434.         return;
  435.         
  436.           case keypf1:
  437.           case keypf2:
  438.           case keypf3:
  439.           case keypf4:
  440.         do_pfkey(flags - keypf1);
  441.         return;
  442.         
  443.           case keyenter:
  444.         do_keyenter();
  445.         return;        
  446.         }
  447.     }
  448.     /* send key macro string */
  449.  
  450.     /*
  451.      * PWP: note, we DON'T have to convert it to a Pascal string, 'cause
  452.      * the macros are now stored as Pascal strings
  453.      */
  454.     writeps (tmpstr);    /* send it to the line */
  455.     if (duplex != 0)
  456.         printps (tmpstr);    /* echo it locally */
  457.     return;
  458.     }
  459.     for (i = 0; i < NUMOFMODS; i++) {
  460.     /* shift what to look for into high byte */
  461.     theModBits = modtable[i].modbits << 4;
  462.     len = strlen (modtable[i].prefix);
  463.  
  464.     if ((theModBits || len) &&
  465.         ((theModBits & modCode) == (theModBits & keyModifierMask))) {
  466.         /* send prefix if there is one */
  467.         if (len) {
  468.         /* PWP: these are saved as Pascal strings now */
  469.         BlockMove (modtable[i].prefix, tmpstr, (modtable[i].prefix[0] + 1));
  470.         writeps (tmpstr);    /* send it to the line */
  471.         if (duplex != 0)
  472.             printps (tmpstr);    /* echo it locally */
  473.         }
  474.  
  475.         /*
  476.          * get the unmodified ASCII code if the unmodify action bit is
  477.          * active
  478.          */
  479.         if (theModBits & UnmodMask)
  480.         c = DeModifyChar ((long) ((evt->message & myKeyCodeMask) >> 8),
  481.                   (long) (modCode & shiftKey));
  482.              /* PWP: we pass through the shiftedness of this key */
  483.         else
  484.         c = evt->message & charCodeMask;    /* otherwise get the
  485.                              * standard char */
  486.  
  487.         /* make an uppercase character if the caps action bit is active */
  488.         if ((theModBits & CapsMask) && islower (c))
  489.         c = _toupper (c);
  490.  
  491.         /* make a control character if the control action bit is active */
  492.         if (theModBits & CtrlMask)
  493.         c &= ctrlCodeMask;
  494.  
  495.         /* PWP: for Meta characters (yes, I use Emacs) */
  496.         if (theModBits & MetaMask)
  497.         c |= metaOrBits;
  498.  
  499.         OutputChar (c);
  500.         return;
  501.     }            /* if */
  502.     }                /* for */
  503.  
  504.     /* get the ASCII code and send it */
  505.     OutputChar (evt->message & charCodeMask);
  506. }                /* handle_char */
  507.  
  508. /****************************************************************************/
  509. /****************************************************************************/
  510. /****************************************************************************/
  511. /* general rectangle routines                                               */
  512. /****************************************************************************/
  513.  
  514.  
  515.  
  516. /****************************************************************************/
  517. /*
  518.  * Routine makerect
  519.  *
  520.  * Make a rectangle in r starting on line lin and column col extending
  521.  * numlin lines and numcol characters.
  522.  *
  523.  */
  524. /****************************************************************************/
  525. makerect (r, lin, col, numlin, numcol)
  526. Rect *r;
  527. int lin;
  528. int col;
  529. int numlin;
  530. int numcol;
  531. {
  532.     r->top = lin * LINEHEIGHT + TOPMARGIN;
  533.     r->left = col * CHARWIDTH + LEFTMARGIN;
  534.     r->bottom = r->top + numlin * LINEHEIGHT;
  535.     r->right = r->left + numcol * CHARWIDTH;
  536. }                /* makerect */
  537.  
  538. /* (PWP) do what makerect does, then invert the rect */
  539. invertchars (lin, col, numlin, numcol)
  540. int lin;
  541. int col;
  542. int numlin;
  543. int numcol;
  544. {
  545.     Rect r;
  546.     r.top = lin * LINEHEIGHT + TOPMARGIN;
  547.     r.left = col * CHARWIDTH + LEFTMARGIN;
  548.     r.bottom = r.top + numlin * LINEHEIGHT;
  549.     r.right = r.left + numcol * CHARWIDTH;
  550.     InvertRect (&r);
  551. }
  552.  
  553. /* Make rect r (made by makerect()) into the right shape
  554.      for underlining */
  555. makertou (r)
  556. Rect *r;
  557. {
  558.     r->top = r->bottom - 1;
  559. }
  560.  
  561. /****************************************************************************/
  562. /* Connect support routines */
  563. /****************************************************************************/
  564. consetup ()
  565. {
  566.     PenMode (srcCopy);        /* (PWP) was patXor */
  567.     flushio ();            /* Get rid of pending characters */
  568.  
  569.     init_term ();        /* Set up some terminal variables */
  570.     TextFont (VT100FONT);    /* (UoR) Set initial font to VT100 */
  571.     TextMode (srcXor);        /* (UoR) use XOR mode (for inverse) */
  572.     TextFace (0);        /* PWP: be safe.  We allways stay like this */
  573.     clear_screen ();        /* Clear the screen */
  574.     home_cursor ();        /* Go to the upper left */
  575.     cursor_save ();        /* Save this position */
  576.     cursor_draw ();        /* (UoR) be sure to draw it */
  577. }                /* consetup */
  578.  
  579. void
  580. term_reset ()
  581. {
  582.     PenMode (srcCopy);        /* (PWP) was patXor */
  583.     flushio ();            /* Get rid of pending characters */
  584.     screen_to_bottom ();    /* slide the visible region to active area */
  585.  
  586.     graphicsinset[0] = ASCII_SET;
  587.     graphicsinset[1] = GRAF_SET;
  588.     norm_char();
  589.     Gl_set = 0;
  590.     Gr_set = 1;
  591.     textstyle = 0;
  592.     current_style = 0;
  593.     draw_sing_chars = 0;
  594.     screeninvert = FALSE;    /* (UoR) inverted screen flag */
  595.     insert = FALSE;
  596.     newline = FALSE;        /* (UoR) linefeed mode by default */
  597.     autowrap = TRUE;        /* Autowrap on by default */
  598.     relorigin = FALSE;        /* (UoR) relative origin off */
  599.     autorepeat = TRUE;        /* (UoR) auto repeat flag */
  600.     appl_mode = FALSE;        /* (PWP) keypad application mode */
  601.     curskey_mode = FALSE;    /* (PWP) cursor key application mode */
  602.     smoothscroll = FALSE;    /* do smooth scrolling (PWP: or not) */
  603.     transparent = TRUE;        /* do not show control characters */
  604.     blockcursor = TRUE;        /* show block or underline cursor */
  605.     cursor_shown = TRUE;    /* (PWP) show the cursor */
  606.     mouse_arrows = FALSE;    /* mouse down in screen does arrow keys */
  607.     visible_bell = FALSE;    /* true if we do blink instead of bell */
  608.     eightbit_disp = FALSE;    /* default to 7 bits */
  609.     blinkcursor = TRUE;        /* true if we make the cursor blink */
  610.  
  611.     have_selection = FALSE;    /* (PWP) we have no selected text */
  612.     
  613.     TextFont (VT100FONT);    /* (UoR) Set initial font to VT100 */
  614.     TextMode (srcXor);        /* (UoR) use XOR mode (for inverse) */
  615.     TextFace (0);        /* PWP: be safe.  We allways stay like this */
  616.     clear_screen ();        /* Clear the screen */
  617.     home_cursor ();        /* Go to the upper left */
  618.     cursor_save ();        /* Save this position */
  619.     cursor_draw ();        /* (UoR) be sure to draw it */
  620. }                /* consetup */
  621.  
  622. /****************************************************************************/
  623. /****************************************************************************/
  624.  
  625. /****************************************************************************/
  626. /*
  627.  *   Flushio:
  628.  *      Initialize some communications constants, and clear screen and
  629.  *      character buffers. */
  630. /****************************************************************************/
  631. flushio ()
  632. {
  633.     int err;
  634.  
  635.     err = KillIO (innum);
  636.     if (err)
  637.     printerr ("Bad input clear", err);
  638.     err = KillIO (outnum);
  639.     if (err)
  640.     printerr ("Bad ouput clear", err);
  641. }                /* flushio */
  642.  
  643.  
  644.  
  645. /****************************************************************************/
  646. /* sendbreak - sends a break across the communictions line.
  647.  *
  648.  * The argument is in units of approximately 0.05 seconds (or 50
  649.  * milliseconds).  To send a break of duration 250 milliseconds the
  650.  * argument would be 5; a break of duration 3.5 seconds would be (umm,
  651.  * lets see now) 70.
  652.  *
  653.  */
  654. /****************************************************************************/
  655. sendbreak (msunit)
  656. int msunit;
  657. {
  658.     long finalticks;
  659.  
  660. /* delay wants 1/60th units.  We have 3/60 (50 ms.) units, convert */
  661.  
  662.     msunit = msunit * 3;
  663.  
  664.     SerSetBrk (outnum);        /* start breaking */
  665.     Delay ((long) msunit, &finalticks);    /* delay */
  666.     SerClrBrk (outnum);        /* stop breaking */
  667. }                /* sendbreak */
  668.  
  669. /****************************************************************************/
  670. /* toggledtr - Turn DTR off, wait a bit, turn it back on.
  671.  *
  672.  * the argument is in the same units as sendbreak (see above).
  673.  */
  674. /****************************************************************************/
  675. toggle_dtr (msunit)
  676. int msunit;
  677. {
  678.     long finalticks;
  679.     CntrlParam cpb;
  680.     int err;
  681.  
  682.     if (usingRAMdriver) {
  683.     /* delay wants 1/60th units.  We have 3/60 (50 ms.) units, convert */
  684.  
  685.     msunit = msunit * 3;
  686.  
  687.     cpb.csCode = 18;        /* lower DTR */
  688.     cpb.ioCRefNum = outnum;
  689.     err = PBControl (&cpb, FALSE);
  690.     if (err != noErr)
  691.         printerr ("toggle_dtr() trouble lowering DTR: ", err);
  692.  
  693.         Delay ((long) msunit, &finalticks);    /* delay */
  694.  
  695.     cpb.csCode = 17;        /* raise DTR */
  696.     cpb.ioCRefNum = outnum;
  697.     err = PBControl (&cpb, FALSE);
  698.     if (err != noErr)
  699.         printerr ("toggle_dtr() trouble raising DTR: ", err);
  700.    }
  701. }                /* sendbreak */
  702.  
  703. /****************************************************************************/
  704. /* do_xon - xon the output port and send an xon (control-Q) character        */
  705. /****************************************************************************/
  706. do_xon ()
  707. {
  708.     CntrlParam cpb;
  709.     int err;
  710.  
  711.     if (usingRAMdriver) {
  712.     cpb.csCode = 22;        /* clear XOFF for my output */
  713.     cpb.ioCRefNum = outnum;
  714.     err = PBControl (&cpb, FALSE);
  715.     if (err != noErr)
  716.         printerr ("do_xon() trouble unblocking output port: ", err);
  717.  
  718.     cpb.csCode = 24;        /* unconditionally send XON */
  719.     cpb.ioCRefNum = outnum;
  720.     err = PBControl (&cpb, FALSE);
  721.     if (err != noErr)
  722.         printerr ("do_xon() trouble sending XON: ", err);
  723.    } else {
  724.        OutputChar ('\021');    /* XON */
  725.    }
  726. }                /* sendbreak */
  727.  
  728. /*************************************************/
  729. /* cursor drawing stuff                          */
  730. /*************************************************/
  731.  
  732. Boolean
  733. cursor_rect (line, col, r)
  734. Rect *r;
  735. {
  736.     if (line - display_topline >= screensize)    /* if cursor not on screen */
  737.         return FALSE;
  738.     
  739.     makerect (r, line - display_topline, col, 1, 1);    /* Get character rectangle */
  740.     if (!blockcursor)
  741.     r->top = r->bottom - 1;
  742.     return TRUE;
  743. }                /* cursor_rect */
  744.  
  745. void
  746. cursor_draw ()
  747. {
  748.     /*    Line(CHARWIDTH,0);*//* Draw cursor */
  749.  
  750.     Rect r;
  751.  
  752.     /* if (cur_drawn) return; */
  753.     if (!cursor_shown) return;        /* (PWP) not if we are hiding cursor */
  754.     
  755.     if (!cursor_invert) {
  756.     if (cursor_rect (curlin, curcol, &r)) {
  757.         if (in_front) {
  758.         InvertRect (&r);
  759.         } else {
  760.         PenMode (patXor);
  761.         FrameRect (&r);
  762.         PenMode (patCopy);
  763.         }
  764.     }
  765.     }
  766.  
  767.     if ((oldlin >= 0) && (!mousecurs_drawn)) {    /* (UoR) replace mouse cursor */
  768.     makerect (&r, oldlin, oldcol, 1, 1);
  769.     PenMode (patXor);
  770.     FrameRect (&r);
  771.     PenMode (patCopy);
  772.     mousecurs_drawn = TRUE;
  773.     }
  774.     
  775.     cursor_invert = TRUE;
  776.     cur_drawn = TRUE;
  777. }                /* cursor_draw */
  778.  
  779.  
  780. void
  781. cursor_erase ()
  782. {
  783.     /*    Line(-CHARWIDTH,0);*//* Erase cursor */
  784.  
  785.     Rect r;
  786.  
  787.     /* if (!cur_drawn) return; */
  788.  
  789.     if (cursor_invert) {
  790.     if (cursor_rect (curlin, curcol, &r)) {
  791.         if (in_front) {
  792.         InvertRect (&r);
  793.         } else {
  794.         PenMode (patXor);
  795.         FrameRect (&r);
  796.         PenMode (patCopy);
  797.         }
  798.     }
  799.     }
  800.     
  801.     if ((oldlin >= 0) && (mousecurs_drawn)) {    /* (UoR) remove mouse cursor */
  802.     makerect (&r, oldlin, oldcol, 1, 1);
  803.     PenMode (patXor);
  804.     FrameRect (&r);
  805.     PenMode (patCopy);
  806.      mousecurs_drawn = FALSE;
  807.    }
  808.  
  809.     cursor_invert = FALSE;
  810.     cur_drawn = FALSE;
  811. }                /* cursor_erase */
  812.  
  813. void
  814. flash_cursor (theWindow)
  815. WindowPtr theWindow;
  816. {
  817.     register long tc;
  818.     Rect r;
  819.  
  820.     if (theWindow == (WindowPtr) NIL) {
  821.     last_flash = TickCount ();
  822.     return;
  823.     }
  824.  
  825.     tc = TickCount ();
  826.     if (((tc - last_flash) > MyCaretTime) ||
  827.     (tc - last_flash) < 0L) {
  828.     last_flash = tc;
  829.  
  830.     if (cur_drawn) {
  831.         if (cursor_rect (curlin, curcol, &r)) {
  832.         if (blinkcursor && in_front) {    /* PWP: only blink if asked for */
  833.             InvertRect (&r);
  834.             cursor_invert = !cursor_invert;
  835.         } else if (!cursor_invert) {    /* make sure that the cursor
  836.                          * shows up */
  837.             if (in_front) {
  838.             InvertRect (&r);
  839.             } else {
  840.             PenMode (patXor);
  841.             FrameRect (&r);
  842.             PenMode (patCopy);
  843.             }
  844.             cursor_invert = TRUE;
  845.         }
  846.         }
  847.     }
  848.     }
  849. }                /* flash_cursor */
  850.  
  851.  
  852. /****************************************************************************/
  853. /* PWP -- like waitasec(), but don't get any characters.  Used for 
  854.    visable bell. */
  855. /****************************************************************************/
  856. waitnoinput ()
  857. {
  858.     long ticks = 2, end_time;
  859.  
  860.     Delay (ticks, &end_time);    /* pause for 1/30th second */
  861. }                /* waitnoinput */
  862.  
  863.  
  864. /****************************************************************************/
  865. /* (UoR) get any characters, and pause for a while */
  866. /****************************************************************************/
  867. waitasec ()
  868. {
  869.     waitnoinput();
  870.     inpchars ();
  871. }                /* waitasec */
  872.  
  873.  
  874. /****************************************************************************/
  875. /* updateCursor -- taken from NCSA Telnet for the Macintosh, v 2.2   */
  876. /****************************************************************************/
  877. void
  878. updateCursor(force, myfrontwindow)
  879. int force;
  880. WindowPeek myfrontwindow;
  881. {
  882.     static Point lastPoint;
  883.     static int optwasdown = 0;
  884.     static Cursor *lastCursor=0L;    /* what we set the cursor to last */
  885.     Cursor *thisCursor;
  886.     int optDown;
  887.     char allthekeys[16];    /* Someplace to put the keymap */
  888.     int newlin, newcol;
  889.     Point MousePt;
  890.     Rect r;
  891.  
  892.     /* SetPort(myfrontwindow); */
  893.     GetMouse(&MousePt);
  894.  
  895.  
  896.     if ( (!force) && (MousePt == lastPoint) && (optDown == optwasdown))
  897.     return;
  898.  
  899.     if (force)
  900.     lastCursor=0L;
  901.     
  902.     if (protocmd != 0) {    /* if doing a transfer */
  903.     thisCursor = watchcurs;
  904.     } else if (((myfrontwindow == terminalWindow) ||
  905.         ((myfrontwindow == NIL) &&
  906.          (FrontWindow() == terminalWindow))) &&
  907.        PtInRect (&MousePt, &ScreenRect)) {
  908.  
  909.     GetKeys(allthekeys);
  910.     optDown = allthekeys[7] & 4;    /* should be symbolic */
  911.  
  912.     if (mouse_arrows || optDown) {
  913.         newlin = (MousePt.v - TOPMARGIN) / LINEHEIGHT;
  914.         newcol = (MousePt.h - LEFTMARGIN + CHARWIDTH/2) / CHARWIDTH;
  915.  
  916.         if ((oldlin != newlin) || (oldcol != newcol)) {
  917.         PenMode (patXor);    /* For FrameRect calls */
  918.         if (oldlin >= 0) {    /* if old rectangle */
  919.             if (mousecurs_drawn) {
  920.             makerect (&r, oldlin, oldcol, 1, 1);
  921.             FrameRect (&r);
  922.             }
  923.         } else {        /* else if drawing for the first time */
  924.             HideCursor ();
  925.         }
  926.         
  927.         makerect (&r, newlin, newcol, 1, 1);
  928.         FrameRect (&r);
  929.         PenMode (patCopy);    /* reset to normal pen mode */
  930.  
  931.         oldlin = newlin;
  932.         oldcol = newcol;
  933.          mousecurs_drawn = TRUE;
  934.         }
  935.         lastPoint=MousePt;
  936.         optwasdown=optDown;
  937.         
  938.         return;
  939.     } else {            
  940.         thisCursor = textcurs;
  941.     }
  942.     } else {
  943.     thisCursor  = normcurs;        /* default cursor shape */
  944.     }
  945.     
  946.     if  (lastCursor!= thisCursor) {
  947.     SetCursor(thisCursor);
  948.     lastCursor = thisCursor;
  949.     }
  950.     lastPoint=MousePt;
  951.     optwasdown=optDown;
  952.  
  953.     if (oldlin >= 0) {        /* if we hade drawn a movement outline */
  954.     if (mousecurs_drawn) {
  955.         PenMode (patXor);    /* For FrameRect calls */
  956.         makerect (&r, oldlin, oldcol, 1, 1);
  957.         FrameRect (&r);
  958.     }
  959.     
  960.     oldlin = -1;
  961.      mousecurs_drawn = FALSE;
  962.     ShowCursor ();
  963.     PenMode (patCopy);    /* reset to normal pen mode */
  964.     }
  965. }
  966.  
  967.  
  968. /****************************************************************************/
  969. /* Put characters onto the actual screen                                    */
  970. /****************************************************************************/
  971.  
  972. char outbuf[MAXCOL + 1];
  973. int outcnt = 0, outcol;
  974.  
  975. static int to_mac_style[] = {
  976.     normal,    underline, italic, underline|italic,
  977.     bold, bold|underline, bold|italic, bold|underline|italic
  978. };
  979.  
  980. /****************************************************************************/
  981. /* flushbuf() -- draw all the buffered characters on the screen */
  982. /****************************************************************************/
  983. flushbuf ()
  984. {
  985.     register int i;
  986.     Rect r;
  987.  
  988.     if (outcnt == 0)
  989.     return;            /* Nothing to flush */
  990.  
  991.     if (to_printer) {                    /*JAO*/
  992.     for (i = 0; i < outcnt; i++) {
  993.         (*hPrintBuffer)[lPrintBufferAt++] = outbuf[i];
  994.         if (lPrintBufferAt == lPrintBufferSize)
  995.         lPrintBufferAt = 0L;
  996.         lPrintBufferChars++;
  997.         if (lPrintBufferChars == lPrintBufferSize) {
  998.         overflowingDialog = GetNewDialog(OVERFLOWINGBOXID, NILPTR, (WindowPtr) - 1);
  999.         DrawDialog(overflowingDialog);
  1000.         }
  1001.     }
  1002.     }
  1003.  
  1004.     if (!to_screen) return;                                                    /*JAO*/
  1005.  
  1006.     makerect (&r, curlin, outcol, 1, outcnt);
  1007.     EraseRect (&r);
  1008.  
  1009.     if (draw_sing_chars) {
  1010.     for (i = 0; i < outcnt; i++) {
  1011.         MOVETOCHAR(outcol + i, curlin - display_topline);
  1012.         DrawChar(outbuf[i] & 0377);
  1013.     }
  1014.     } else {    /* non-blinking */
  1015.     MOVETOCHAR(outcol, curlin - display_topline);
  1016.     DrawText (outbuf, 0, outcnt);    /* Output the string */
  1017.     }
  1018.     
  1019.     if (textstyle & VT_INVERT) {
  1020.     InvertRect (&r);
  1021.     }
  1022.  
  1023.     outcnt = 0;            /* Say no more chars to output */
  1024. }                /* flushbuf */
  1025.  
  1026. /****************************************************************************/
  1027. /* set_style(style) - set the correct stuff for displaying chars in style   */
  1028. /****************************************************************************/
  1029. int
  1030. set_style(style)
  1031. int style;
  1032. {
  1033.     int m_sty, m_font;
  1034.     static int o_sty = 0, o_font = 0;
  1035.     Handle theRsrc;
  1036.     
  1037.     if (style == current_style) return;
  1038.     current_style = style;
  1039.     
  1040.     m_sty = to_mac_style[style & STY_MSTY];
  1041.     m_font = ((style & STY_FONT) >> 3) + VT100FONT;
  1042.     draw_sing_chars = style & VT_BLINK;
  1043.     
  1044.     if (!have_128roms && (m_sty & bold)) {    /* if on an old mac and bolding */
  1045.     if (m_font = VT100FONT) {
  1046.         m_font = VT100BOLD;
  1047.         m_sty &= ~bold;
  1048.     } else {
  1049.         draw_sing_chars = 1;
  1050.     }
  1051.     }
  1052.  
  1053.     if (m_font != o_font) {
  1054.     TextFont (m_font);        /* new font */
  1055.     o_font = m_font;
  1056.     }
  1057.     if (m_sty != o_sty) {
  1058.     TextFace (m_sty);        /* new text face */
  1059.     o_sty = m_sty;
  1060.     }
  1061. }
  1062.  
  1063. /****************************************************************************/
  1064. /****************************************************************************/
  1065. void
  1066. draw_line_attrs(lin, v)
  1067. register int lin, v;
  1068. {
  1069.     register int o, i, sty, j;
  1070.     Rect r;
  1071.     
  1072.     if ((v < 0) || (v > screensize))
  1073.     printerr("draw_line_attrs, v out of range:", v);
  1074.  
  1075.     sty = scr_attrs[lin][0];
  1076.     o = 0;
  1077.     i = 0;
  1078.     do {
  1079.         if ((scr_attrs[lin][i] != sty) || (i == MAXCOL)) {    /* if this style != current style */
  1080.         makerect (&r, v, o, 1, i-o);
  1081.         EraseRect (&r);
  1082.  
  1083.         set_style(sty);
  1084.         if (draw_sing_chars) {
  1085.         for (j = o; j < i; j++) {
  1086.             MOVETOCHAR(j, v);
  1087.             DrawChar(scr[lin][j] & 0377);
  1088.         }
  1089.         } else {    /* non-blinking */
  1090.         MOVETOCHAR(o, v);
  1091.         DrawText (scr[lin], o, i-o);    /* Output this part */
  1092.         }
  1093.         if (sty & VT_INVERT) {
  1094.         InvertRect (&r);
  1095.         }
  1096.         o = i;    /* now left extent == current */
  1097.         sty = scr_attrs[lin][i];    /* new current style */
  1098.     }
  1099.     i++;
  1100.     } while (i <= MAXCOL);
  1101. }
  1102.  
  1103. /****************************************************************************/
  1104. /****************************************************************************/
  1105. void
  1106. scroll_term()
  1107. {
  1108.     register int new_topline, delta, lin, i;
  1109.     int fl, fc, tl, tc;
  1110.     Rect r;            /* cannot be register */
  1111.  
  1112.     new_topline = screensize - display_totlines + GetCtlValue (t_vscroll);
  1113.     if ((new_topline > 0) || (new_topline <  screensize - MAX_SCREENSIZE)) {
  1114.         printerr("BUG: in scroll_term(), new_topline out of range:", new_topline);
  1115.     return;
  1116.     }
  1117.     if ((delta = (display_topline - new_topline)) == 0)
  1118.     return;        /* we didn't move */
  1119.  
  1120.     makerect (&r, 0, 0, screensize, MAXCOL);
  1121.     
  1122.     if ((delta >= screensize) || (-delta >= screensize)) {   /* if whole screen */
  1123.         EraseRect(&r);
  1124.     
  1125.         lin = new_topline;            /* new top line */
  1126.     for (i = 0; i < screensize; i++) {
  1127.         draw_line_attrs(lin, i);
  1128.         lin++;
  1129.     }
  1130.     display_topline = new_topline;
  1131.  
  1132.     if (have_selection)
  1133.         invert_text(from_lin, from_col, to_lin, to_col);
  1134.         
  1135.     return;    /* we are done */
  1136.     }
  1137.  
  1138.     /* if we get here, we are not doing the whole screen */
  1139.     ScrollRect (&r, 0, delta * LINEHEIGHT, dummyRgn);
  1140.  
  1141.     if (delta > 0) {    /* scrolling down (pushing top arrow) */
  1142.         lin = new_topline;            /* new top line */
  1143.     for (i = 0; (i < delta) && (i < screensize); i++) {
  1144.         draw_line_attrs(lin, i);
  1145.         lin++;
  1146.     }
  1147.     display_topline = new_topline;
  1148.  
  1149.     if (have_selection &&
  1150.         (from_lin < display_topline + delta) &&
  1151.         (to_lin >= display_topline)) {
  1152.         if (from_lin < display_topline) {
  1153.         fl = display_topline;
  1154.         fc = 0;
  1155.         } else {
  1156.         fl = from_lin;
  1157.         fc = from_col;
  1158.         }
  1159.         if (to_lin >= display_topline + delta) {
  1160.         tl = display_topline + delta - 1;
  1161.         tc = MAXCOL;
  1162.         } else {
  1163.         tl = to_lin;
  1164.         tc = to_col;
  1165.         }
  1166.         invert_text(fl, fc, tl, tc);
  1167.     }
  1168.     } else {        /* scrolling up (pushing bottom arrow) */
  1169.         lin = display_topline + screensize;    /* one past old bottom line */
  1170.     /*********** PWP: delta is negative here ****************/
  1171.     i = screensize + delta;
  1172.     if (i < 0) i = 0;    /* bounds */
  1173.     while (i < screensize)
  1174.         draw_line_attrs(lin++, i++);
  1175.     display_topline = new_topline;
  1176.  
  1177.     if (have_selection &&
  1178.         (from_lin < (display_topline + screensize)) &&
  1179.         (to_lin >= (display_topline + screensize + delta))) {
  1180.         if (from_lin < display_topline + screensize + delta) {
  1181.         fl = display_topline + screensize + delta;
  1182.         fc = 0;
  1183.         } else {
  1184.         fl = from_lin;
  1185.         fc = from_col;
  1186.         }
  1187.         if (to_lin >= display_topline + screensize) {
  1188.         tl = display_topline + screensize - 1;
  1189.         tc = MAXCOL;
  1190.         } else {
  1191.         tl = to_lin;
  1192.         tc = to_col;
  1193.         }
  1194.         invert_text(fl, fc, tl, tc);
  1195.     }
  1196.     }
  1197. }
  1198.  
  1199. void pascal
  1200. doscroll (WHICHCONTROL, THECODE)
  1201. ControlHandle WHICHCONTROL;
  1202. short THECODE;
  1203. {
  1204.     register int amount = 0, val, max;
  1205.  
  1206.     if (THECODE == inUpButton)
  1207.     amount = -1;
  1208.     if (THECODE == inDownButton)
  1209.     amount = 1;
  1210.     if (amount == 0)
  1211.     return;
  1212.     val = GetCtlValue (WHICHCONTROL) + amount;
  1213.     max = GetCtlMax (WHICHCONTROL);
  1214.     if ((val < 0) || (val > max))
  1215.     return;
  1216.     SetCtlValue (WHICHCONTROL, val);
  1217.     scroll_term ();
  1218. }                /* doscroll */
  1219.  
  1220.  
  1221. /****************************************************************************/
  1222. /* we move the displayed region to the bottom when we recieve characters */
  1223. /****************************************************************************/
  1224.  
  1225. screen_to_bottom()
  1226. {
  1227.     if (display_topline != toplin) {
  1228.     SetCtlValue (t_vscroll, display_totlines - screensize);
  1229.     scroll_term ();
  1230.     }
  1231. }
  1232.  
  1233. /****************************************************************************/
  1234. /* update_vscroll - adjust the scaling of the vertical scroll bar, or  */
  1235. /*                      disable it if we havn't saved anything back yet */
  1236. /****************************************************************************/
  1237. update_vscroll ()
  1238. {
  1239.     if (in_front && display_totlines > screensize) {
  1240.     SetCtlMax (t_vscroll, display_totlines - screensize);
  1241.     SetCtlValue (t_vscroll, display_totlines - screensize);
  1242.     HiliteControl (t_vscroll, 0);
  1243.     } else {
  1244.     HiliteControl (t_vscroll, 255);
  1245.     }
  1246. }                /* sizescrollbars */
  1247.  
  1248. /****************************************************************************/
  1249. /****************************************************************************/
  1250. t_pagescroll (code, amount, ctrlh)
  1251. ControlHandle ctrlh;
  1252. {
  1253.     Point myPt;
  1254.     register int val, max;
  1255.  
  1256.     max = GetCtlMax (ctrlh);
  1257.     val = GetCtlValue (ctrlh);
  1258.     
  1259.     do {
  1260.     GetMouse (&myPt);
  1261.     if (TestControl (ctrlh, &myPt) != code)
  1262.         continue;
  1263.     
  1264.     val += amount;
  1265.     if (val < 0)
  1266.         val = 0;
  1267.     if (val > max)
  1268.         val = max;
  1269.     SetCtlValue (ctrlh,  val);
  1270.     scroll_term ();
  1271.     } while (StillDown ());
  1272. }                /* pagescroll */
  1273.  
  1274.  
  1275. termmouse(evt)
  1276. EventRecord *evt;
  1277. {
  1278.     int actrlcode;
  1279.     long ticks;
  1280.     ControlHandle acontrol;
  1281.     GrafPtr savePort;
  1282.     
  1283.     GetPort (&savePort);    /* save the current port */
  1284.     SetPort (terminalWindow);
  1285.  
  1286.     GlobalToLocal (&evt->where);/* convert to local */
  1287.     if (mouse_arrows || (evt->modifiers & optionKey)) {
  1288.     if (PtInRect (&evt->where, &ScreenRect)) {    /* In terminal content? */
  1289.         mouse_cursor_move(evt);        
  1290.         SetPort (savePort);        /* restore previous port */
  1291.         return;            /* yes, do mouse stuff */
  1292.     }
  1293.     }
  1294.     cursor_erase();
  1295.     actrlcode = FindControl (&evt->where, terminalWindow, &acontrol);
  1296.     switch (actrlcode) {    
  1297.       case inUpButton:
  1298.       case inDownButton:
  1299.     (void) TrackControl (acontrol, &evt->where, doscroll);
  1300.     break;
  1301.  
  1302.       case inPageUp:
  1303.     t_pagescroll (actrlcode, -(screensize/2), acontrol);
  1304.     break;
  1305.  
  1306.       case inPageDown:
  1307.     t_pagescroll (actrlcode, (screensize/2), acontrol);
  1308.     break;
  1309.  
  1310.       case inThumb:
  1311.     (void) TrackControl (acontrol, &evt->where, (ProcPtr) NIL);
  1312.     scroll_term ();
  1313.     break;
  1314.     
  1315.       case 0:        /* in the window content itself */
  1316.     mouse_region_select(evt);
  1317.     break;
  1318.     }
  1319.     /* MOVETOCHAR(curcol, curlin - display_topline); */
  1320.     cursor_draw();
  1321.     SetPort (savePort);        /* restore previous port */
  1322. }
  1323.  
  1324. do_arrow(dir)    /* dir is 'A' (up), 'B' (down), 'C' (right), or 'D' (left) */
  1325. unsigned char dir;
  1326. {
  1327.     OutputChar('\033');        /* ESC */
  1328.     if (curskey_mode)
  1329.         OutputChar('O');    /* SS3 */
  1330.     else
  1331.         OutputChar('[');    /* CSI */
  1332.     OutputChar(dir);
  1333. }
  1334.  
  1335. do_keypad (n)    /* char to send is n + ',' */
  1336. int n;
  1337. {
  1338.     if (appl_mode) {
  1339.         OutputChar('\033');        /* ESC */
  1340.         OutputChar('O');    /* SS3 */
  1341.     OutputChar((unsigned char) n + 'l');
  1342.     } else {
  1343.         OutputChar((unsigned char) n + ',');    /* normal digit or glyph */
  1344.     }
  1345. }
  1346.  
  1347. do_pfkey(n)    /* pf1 == 0 ... pf4 == 3 */
  1348. int n;
  1349. {
  1350.     OutputChar('\033');        /* ESC */
  1351.     OutputChar('O');    /* SS3 */
  1352.     OutputChar((unsigned char) n + 'P');
  1353. }
  1354.  
  1355. do_keyenter()
  1356. {
  1357.     if (appl_mode) {
  1358.         OutputChar('\033');        /* ESC */
  1359.         OutputChar('O');    /* SS3 */
  1360.     OutputChar('M');
  1361.     } else {
  1362.         OutputChar('\015');
  1363.     }
  1364. }
  1365.  
  1366. mouse_cursor_move (evt)
  1367. EventRecord *evt;
  1368. {
  1369.     int mouselin;
  1370.     int mousecol;
  1371.     int tempcol;
  1372.     int templin;
  1373.     int i;
  1374.     Point MousePt;
  1375.  
  1376.     MousePt = evt->where;
  1377.     mouselin = (MousePt.v - TOPMARGIN) / LINEHEIGHT;
  1378.     mousecol = (MousePt.h - LEFTMARGIN + CHARWIDTH/2) / CHARWIDTH;
  1379.     tempcol = curcol;
  1380.     templin = curlin;
  1381.  
  1382.     if (mousecol < tempcol)
  1383.     for (i = tempcol; i > mousecol; i--) {
  1384.         do_arrow (leftARROW);
  1385.         waitasec ();
  1386.         /* If tabs are used, we may go too far, so end loop */
  1387.         if (curcol <= mousecol)
  1388.         i = mousecol;
  1389.     }
  1390.  
  1391.     if (mouselin < templin)
  1392.     for (i = templin; i > mouselin; i--) {
  1393.         do_arrow (UPARROW);
  1394.         waitasec ();
  1395.     }
  1396.  
  1397.     else if (mouselin > templin)
  1398.     for (i = templin; i < mouselin; i++) {
  1399.         do_arrow (DOWNARROW);
  1400.         waitasec ();
  1401.     }
  1402.  
  1403.     if (curlin == mouselin)
  1404.     tempcol = curcol;    /* for short lines */
  1405.  
  1406.     if (tempcol < mousecol)
  1407.     for (i = tempcol; i < mousecol; i++) {
  1408.         do_arrow (rightARROW);
  1409.         waitasec ();
  1410.         /* If tabs are used, we may go too far, so end loop */
  1411.         if (curcol >= mousecol)
  1412.         i = mousecol;
  1413.     }
  1414. }                /* mouse_cursor_move */
  1415.  
  1416. invert_text(from_lin, from_col, to_lin, to_col)
  1417. {
  1418.     Rect r;
  1419.     int t;
  1420.     
  1421.     if (from_lin > to_lin) {        /* make from < to */
  1422.         t = to_lin;
  1423.     to_lin = from_lin;
  1424.     from_lin = t;
  1425.         t = to_col;
  1426.     to_col = from_col;
  1427.     from_col = t;
  1428.     }
  1429.     
  1430.     from_lin -= display_topline;    /* convert to screen coords */
  1431.     if (from_lin < 0) {
  1432.     from_lin = 0;
  1433.     from_col = 0;
  1434.     }
  1435.     if (from_lin >= screensize)
  1436.     return;
  1437.     to_lin -= display_topline;        /* convert to screen coords */
  1438.     if (to_lin < 0)
  1439.     return;
  1440.     if (to_lin >= screensize) {
  1441.     to_lin = screensize-1;
  1442.     to_col = MAXCOL;
  1443.     }
  1444.  
  1445.     if (from_lin == to_lin) {    /* if only one line */
  1446.     if (from_col > to_col) {
  1447.             t = to_col;
  1448.         to_col = from_col;
  1449.         from_col = t;
  1450.     }
  1451.     if (from_col != to_col)    /* then invert the characters in between */
  1452.         invertchars(from_lin, from_col, 1, to_col - from_col);
  1453.     } else {
  1454.     if (from_col < MAXCOL)
  1455.         invertchars(from_lin, from_col, 1, MAXCOL - from_col);
  1456.     t = to_lin - from_lin - 1;
  1457.     if (t > 0)
  1458.         invertchars(from_lin+1, 0, t, MAXCOL);
  1459.     if (to_col > 0)
  1460.         invertchars(to_lin, 0, 1, to_col);
  1461.     }
  1462. }
  1463.     
  1464. mouse_region_select (evt)
  1465. EventRecord *evt;
  1466. {
  1467.     int mouselin;
  1468.     int mousecol;
  1469.     int i, shift, sval, smax;
  1470.     Point MousePt;
  1471.  
  1472.     /* if no selection, then a shift drag is just a drag */
  1473.     if (have_selection)
  1474.     shift = (evt->modifiers) & shiftKey;
  1475.     else
  1476.     shift = 0;
  1477.     
  1478.     /* if not adding to region, remove old one */
  1479.     if (!shift && have_selection)
  1480.         invert_text(from_lin, from_col, to_lin, to_col);
  1481.  
  1482.     MousePt = evt->where;
  1483.     mouselin = (MousePt.v - TOPMARGIN) / LINEHEIGHT + display_topline;
  1484.     if (mouselin < display_topline)
  1485.     mouselin = display_topline;
  1486.     if (mouselin >= display_topline + screensize)
  1487.     mouselin = display_topline + screensize-1;
  1488.     mousecol = (MousePt.h - LEFTMARGIN + CHARWIDTH/2) / CHARWIDTH;
  1489.     if (mousecol < 0) mousecol = 0;
  1490.     if (mousecol > MAXCOL) mousecol = MAXCOL;
  1491.     
  1492.     if (shift) {
  1493.     /* swap from_* and to_* if closer to from */
  1494.     if (ABS((MAXCOL * from_lin + from_col) - (MAXCOL * mouselin + mousecol)) <
  1495.         ABS((MAXCOL * to_lin + to_col) - (MAXCOL * mouselin + mousecol))) {
  1496.             i = to_lin;
  1497.         to_lin = from_lin;
  1498.         from_lin = i;
  1499.             i = to_col;
  1500.         to_col = from_col;
  1501.         from_col = i;
  1502.     }
  1503.     } else {
  1504.     from_lin = mouselin;
  1505.     from_col = mousecol;
  1506.     to_lin = mouselin;
  1507.     to_col = mousecol;
  1508.     }
  1509.     
  1510.     while (StillDown()) {
  1511.     GetMouse(&MousePt);
  1512.     mouselin = (MousePt.v - TOPMARGIN) / LINEHEIGHT + display_topline;
  1513.     mousecol = (MousePt.h - LEFTMARGIN + CHARWIDTH/2) / CHARWIDTH;
  1514.     if (mouselin < display_topline) {
  1515.         sval = GetCtlValue (t_vscroll) - 1;
  1516.         smax = GetCtlMax (t_vscroll);
  1517.         if ((sval >= 0) && (sval <= smax)) {
  1518.         SetCtlValue (t_vscroll, sval);
  1519.         scroll_term ();
  1520.         }
  1521.         mouselin = display_topline;
  1522.         mousecol = 0;
  1523.     } else if (mouselin >= display_topline + screensize) {
  1524.         sval = GetCtlValue (t_vscroll) + 1;
  1525.         smax = GetCtlMax (t_vscroll);
  1526.         if ((sval >= 0) && (sval <= smax)) {
  1527.         SetCtlValue (t_vscroll, sval);
  1528.         scroll_term ();
  1529.         }
  1530.         mouselin = display_topline + screensize-1;
  1531.         mousecol = MAXCOL;
  1532.     } else if (mousecol < 0) {
  1533.         mousecol = 0;
  1534.     } else if (mousecol > MAXCOL) {
  1535.         mousecol = MAXCOL;
  1536.     }
  1537.     if ((mousecol != to_col) || (mouselin != to_lin)) {
  1538.         invert_text(to_lin, to_col, mouselin, mousecol);
  1539.         to_lin = mouselin;
  1540.         to_col = mousecol;
  1541.     }
  1542.     }
  1543.     
  1544.     if (from_lin > to_lin) {        /* make from < to */
  1545.     int t;
  1546.     
  1547.         t = to_lin;
  1548.     to_lin = from_lin;
  1549.     from_lin = t;
  1550.         t = to_col;
  1551.     to_col = from_col;
  1552.     from_col = t;
  1553.     } else if (from_lin == to_lin) {
  1554.         if (from_col > to_col) {
  1555.         int t;
  1556.         
  1557.         t = to_col;
  1558.         to_col = from_col;
  1559.         from_col = t;
  1560.     }
  1561.     }
  1562.     
  1563.     if ((from_lin != to_lin) || (from_col != to_col))
  1564.     have_selection = TRUE;
  1565.     else
  1566.     have_selection = FALSE;
  1567. }
  1568.  
  1569. /* (PWP) if the selection is within [tlin,blin], then remove it */
  1570.  
  1571. maybe_nuke_selection(tlin, blin)
  1572. int tlin, blin;
  1573. {
  1574.     if (have_selection &&
  1575.     ((from_lin < tlin) || (to_lin > blin)) &&
  1576.         ((to_lin > tlin)   || (from_lin < blin))) {
  1577.     have_selection = FALSE;
  1578.     invert_text(from_lin, from_col, to_lin, to_col);
  1579.     }
  1580. }
  1581.  
  1582. /* copy the current selction to the (internal) clipboard */
  1583. scr_copy()
  1584. {
  1585.     int lin, i, rcol;
  1586.     long sz;
  1587.     char *dp;
  1588.     
  1589.     if (myclip_h == NIL) {
  1590.     printerr("scr_copy: clip handle not allocated", 0);
  1591.     return;
  1592.     }
  1593.     
  1594.     if (have_selection) {
  1595.     /****** find out how big the text to copy is ******/
  1596.         if (from_lin == to_lin) {
  1597.         sz = to_col - from_col + 1;
  1598.     } else {
  1599.         for (rcol = MAXCOL; rcol > from_col; rcol--)    /* first */
  1600.             if (scr[from_lin][rcol-1] != ' ')
  1601.             break;
  1602.         sz = rcol - from_col + 1;    /* chars plus one for the newline */
  1603.         for (lin = from_lin+1; lin < to_lin; lin++) {    /* in between */
  1604.         for (rcol = MAXCOL; rcol > 0; rcol--)
  1605.             if (scr[lin][rcol-1] != ' ')
  1606.             break;
  1607.         sz += rcol + 1;    /* chars plus one for the newline */
  1608.         }
  1609.         for (rcol = to_col; rcol > 0; rcol--)        /* last */
  1610.             if (scr[to_lin][rcol-1] != ' ')
  1611.             break;
  1612.         sz += rcol;        /* chars */
  1613.         if (to_col >= MAXCOL)
  1614.             sz++;
  1615.     }
  1616.  
  1617.     /****** allocate and lock a buffer for the text ******/
  1618.     if (sz > GetHandleSize ((Handle) myclip_h)) {
  1619.         HUnlock((Handle) myclip_h);
  1620.         SetHandleSize((Handle) myclip_h, sz);
  1621.     }
  1622.     HLock((Handle) myclip_h);
  1623.     dp = *myclip_h;
  1624.     
  1625.     /****** copy the characters over to the clip ******/
  1626.         if (from_lin == to_lin) {
  1627.         for (i = from_col; i < to_col; i++)
  1628.             *dp++ = scr[from_lin][i];
  1629.     } else {
  1630.         /* trim off spaces */
  1631.         for (rcol = MAXCOL; rcol > from_col; rcol--)    /* first */
  1632.         if (scr[from_lin][rcol-1] != ' ')
  1633.             break;
  1634.         for (i = from_col; i < rcol; i++)
  1635.         *dp++ = scr[from_lin][i];
  1636.         *dp++ = '\r';
  1637.         for (lin = from_lin+1; lin < to_lin; lin++) {    /* in between */
  1638.         for (rcol = MAXCOL; rcol > 0; rcol--)
  1639.             if (scr[lin][rcol-1] != ' ')
  1640.             break;
  1641.         for (i = 0; i < rcol; i++)
  1642.             *dp++ = scr[lin][i];
  1643.         *dp++ = '\r';
  1644.         }
  1645.         for (rcol = to_col; rcol > 0; rcol--)        /* last */
  1646.         if (scr[to_lin][rcol-1] != ' ')
  1647.             break;
  1648.         for (i = 0; i < rcol; i++)
  1649.         *dp++ = scr[to_lin][i];
  1650.         if (to_col >= MAXCOL)
  1651.         *dp++ = '\r';
  1652.     }
  1653.     myclip_size = (dp - *myclip_h);
  1654.  
  1655.     /****** check to make sure we didn't overflow the clipboard ******/
  1656.     if (myclip_size > sz)
  1657.         fatal ("Overflow! myclip_size - sz ==", myclip_size - sz);
  1658.  
  1659.     /****** We are done.  Unlock the handle ******/
  1660.     HUnlock((Handle) myclip_h);
  1661.     } else {
  1662.     SysBeep(3);
  1663.     }
  1664. }
  1665.  
  1666. /* paste the clipboard into the terminal, by "typing" it in */
  1667. scr_paste()
  1668. {
  1669.     char *cp, *endp;
  1670.     
  1671.     if (myclip_size > 0) {
  1672.     HLock((Handle) myclip_h);
  1673.     cp = *myclip_h;
  1674.     endp = cp + myclip_size;
  1675.     for (; cp < endp; cp++) {
  1676.         OutputChar(*cp);
  1677.         if (*cp == '\r')
  1678.         waitasec ();
  1679.     }
  1680.     } else {
  1681.     SysBeep(3);
  1682.     }
  1683. }
  1684.  
  1685.  
  1686. /****************************************************************************/
  1687. /****************************************************************************/
  1688.  
  1689. #ifdef COMMENT
  1690. show_inval_rgn(w)
  1691. WindowPeek w;
  1692. {
  1693.     RgnHandle r = NewRgn();
  1694.  
  1695.     CopyRgn (w->updateRgn, r);
  1696.     OffsetRgn(r,            /* convert to local grafport coords */
  1697.           (((w->port).portBits).bounds).left,
  1698.           (((w->port).portBits).bounds).top);
  1699.     FillRgn(r, qd.black);
  1700.     DisposeRgn(r);
  1701. }
  1702. #endif /* COMMENT */
  1703.  
  1704. /****************************************************************************/
  1705. /*
  1706.  * (UoR)
  1707.  *
  1708.  * Scroll lines within the scroll region upwards from line tlin
  1709.  * to line blin (lines are assumed to be in the region)
  1710.  *
  1711.  * (PWP) scroll_screen is the combination of scroll_up and scroll_down.
  1712.  *       dir is the number of lines to scroll, <0 if up, >0 if down.
  1713.  *     (actually, right now only -1 and 1 are handled.)
  1714.  */
  1715. /****************************************************************************/
  1716. void
  1717. scroll_screen (tlin, blin, dir)        /* these are in scr[][] cordinates */
  1718. register int tlin;
  1719. register int blin;
  1720. register int dir;
  1721. {
  1722.     register int i, now;
  1723.     int abstop, absbot;
  1724.     char *savedline, *savedattr;  /* temporary to hold screen line pointer */
  1725.     Rect r, opened_r;        /* cannot be register */
  1726.     Point save_pt;
  1727.     GrafPtr currWindow;        /* cannot be register */
  1728.     RgnHandle newupdateRgn;
  1729.  
  1730.     abstop = tlin;    /* really tlin - display_topline, but we are at bottom */
  1731.     absbot = blin;    /* so display_topline == 0 */
  1732.     makerect (&r, abstop, 0, absbot - abstop + 1, MAXCOL);
  1733.     if (dir < 0)
  1734.     makerect (&opened_r, absbot, 0, 1, MAXCOL);
  1735.     else
  1736.     makerect (&opened_r, abstop, 0, 1, MAXCOL);
  1737.  
  1738.     /* (PWP) if our selected region overlaps, but is not enclosed by the region
  1739.        we want to scroll, then remove it, because the region no longer contains
  1740.        what the user thought it did. */
  1741.     if (have_selection && (tlin != toplin) && (blin != botlin) &&
  1742.     ((from_lin < tlin) || (to_lin > blin)) &&
  1743.         ((to_lin > tlin)   || (from_lin < blin))) {
  1744.     have_selection = FALSE;
  1745.     invert_text(from_lin, from_col, to_lin, to_col);
  1746.     }
  1747.     if (!in_front) {
  1748.     /* compensate update region for scrolling */
  1749.     GetPort (&currWindow);
  1750.     /* scroll the old updateRgn */
  1751.     OffsetRgn (((WindowPeek) currWindow)->updateRgn, 0, -LINEHEIGHT);
  1752.     }
  1753.     
  1754.     /* do the scrolling */
  1755.     newupdateRgn = NewRgn();
  1756.     if (smoothscroll && in_front) {
  1757.     for (i = 1; i <= LINEHEIGHT; i += 1) {
  1758.         /* PWP: wait for a vertical reblank (in a sneaky way) */
  1759.         now = TickCount ();
  1760.         while (TickCount () == now)
  1761.         /* wait... */ ;
  1762.         if (dir < 0)
  1763.         ScrollRect (&r, 0, -1, newupdateRgn);
  1764.         else
  1765.         ScrollRect (&r, 0, 1, newupdateRgn);
  1766.     }
  1767.     } else {
  1768.     ScrollRect (&r, 0, dir * LINEHEIGHT, newupdateRgn);
  1769.     if (!in_front) {
  1770.         InvalRgn(newupdateRgn);
  1771.         ValidRect(&opened_r);
  1772.     }
  1773.     }
  1774.     DisposeRgn(newupdateRgn);
  1775.     
  1776.     if (dir < 0) {
  1777.     /* adjust the internal character buffers */
  1778.     if ((tlin == toplin) && (blin == botlin)) {    /* if whole screen */
  1779.         display_totlines++;
  1780.         if (display_totlines > MAX_SCREENSIZE)
  1781.         display_totlines = MAX_SCREENSIZE;    /* bounds */
  1782.             tlin = screensize - display_totlines;    /* top of saved buffer */
  1783.     }
  1784.      savedline = scr[tlin];
  1785.     savedattr = scr_attrs[tlin];
  1786.     for (i = tlin+1; i <= blin; i++) {
  1787.             scr[i-1] = scr[i];
  1788.             scr_attrs[i-1] = scr_attrs[i];
  1789.     }
  1790.     scr[blin] = savedline;
  1791.     scr_attrs[blin] = savedattr;
  1792.     
  1793.     zeroline (blin);        /* clear the line */
  1794.  
  1795.     /* adjust selection */
  1796.     if (have_selection && (from_lin >= tlin) && (to_lin <= blin)) {
  1797.         from_lin--;
  1798.         to_lin--;
  1799.     }
  1800.     } else {
  1801.         /* adjust the internal buffers */
  1802.     savedline = scr[blin];
  1803.     savedattr = scr_attrs[blin];
  1804.     for (i = blin-1; i >= tlin; i--) {
  1805.             scr[i+1] = scr[i];
  1806.             scr_attrs[i+1] = scr_attrs[i];
  1807.     }
  1808.     scr[tlin] = savedline;
  1809.     scr_attrs[tlin] = savedattr;
  1810.  
  1811.     zeroline (tlin);
  1812.  
  1813.     /* adjust selection */
  1814.     if (have_selection && (from_lin >= tlin) && (to_lin <= blin)) {
  1815.         from_lin++;
  1816.         to_lin++;
  1817.     }
  1818.     }
  1819. }                /* scroll_up */
  1820.  
  1821. /****************************************************************************/
  1822. /* redraw the terminal screen (we got a redraw event) */
  1823. /****************************************************************************/
  1824. term_redraw ()
  1825. {
  1826.     int i, lin;
  1827.     Rect r;
  1828.  
  1829.     BackPat(qd.white);
  1830.     PenPat(qd.black);
  1831.  
  1832.     r = terminalWindow->portRect;    /* copy the window size */
  1833.     /* r.right -= 15;    */        /* subtract control */
  1834.     /* makerect (&r, 0, 0, screensize, MAXCOL); */   /* PWP: clear the screen first */
  1835.     EraseRect (&r);
  1836.  
  1837.     DrawGrowIcon (terminalWindow);
  1838.     DrawControls (terminalWindow);
  1839.     /* erase the bottom scroll line */
  1840.     PenMode(patBic);
  1841.     MoveTo(0, (terminalWindow->portRect).bottom - 15);
  1842.     LineTo((terminalWindow->portRect).right - 16,
  1843.         (terminalWindow->portRect).bottom - 15);
  1844.     PenNormal();
  1845.  
  1846.     /* update_vscroll(); */
  1847.     /* SetCtlValue (t_vscroll, GetCtlValue (t_vscroll)); */
  1848.  
  1849.     lin = display_topline;
  1850.     for (i = 0; i < screensize; i++) {
  1851.     draw_line_attrs(lin, i);
  1852.     lin++;
  1853.     }
  1854.  
  1855.     if (have_selection)
  1856.         invert_text(from_lin, from_col, to_lin, to_col);
  1857.  
  1858.     if (cur_drawn && cursor_invert) {    /* (UoR) only if cursor is showing */
  1859.     cursor_invert = FALSE;    /* (UoR) make sure we draw it */
  1860.     cursor_draw ();        /* redraw cursor */
  1861.     last_flash = TickCount ();    /* (UoR) reset timer */
  1862.     }
  1863.  
  1864. }                /* term_redraw */
  1865.  
  1866. term_activate(hilite)
  1867. int hilite;
  1868. {
  1869.     cursor_erase ();        /* remove cursor from screen */
  1870.     in_front = hilite;
  1871.     if (in_front) {
  1872.     HiliteControl (t_vscroll, 0);
  1873.     UpdateOptKey(1);
  1874.     } else {
  1875.     HiliteControl (t_vscroll, 255);
  1876.     UpdateOptKey(0);
  1877.     }
  1878.     cursor_draw ();
  1879. }
  1880.  
  1881.  
  1882. /****************************************************************************/
  1883. /* initalize the terminal emulator. */
  1884. /****************************************************************************/
  1885. init_term ()
  1886. {
  1887.     register int i, j;
  1888.     char *cp;
  1889.     
  1890.     topmargin = TOPMARGIN;    /* Edges of adjustable window */
  1891.     bottommargin = bottomMARGIN;
  1892.     
  1893.     if ((cp = (char *)NewPtr(((long)(MAXCOL+1) * (long) MAX_SCREENSIZE))) == NIL)
  1894.     fatal("Could not allocate screen buffer", 0);
  1895.     
  1896.     for (i = 0; i < MAX_SCREENSIZE; i++) {
  1897.         real_scr[i] = cp + (i * (MAXCOL+1));    /* divvy up screen buffer */
  1898.  
  1899.     for (j = 0; j < MAXCOL; j++)
  1900.         real_scr[i][j] = ' ';
  1901.     real_scr[i][MAXCOL] = '\0';    /* Terminate the lines as strings */
  1902.  
  1903.         if ((real_attrs[i] = (char *)NewPtr((long)(MAXCOL+1))) == NIL)
  1904.         fatal("Could not allocate screen attribute line", i);
  1905.  
  1906.     for (j = 0; j < MAXCOL; j++)
  1907.         real_attrs[i][j] = 0;
  1908.     real_attrs[i][MAXCOL] = '\0';    /* Terminate the lines as strings */
  1909.     }
  1910.     scr = &real_scr[MAX_SCREENSIZE - screensize];
  1911.     if (scr[0] == NIL)
  1912.     fatal("init_term: scr assignment botched for [0]", 0);
  1913.     if (scr[screensize-1] == NIL)
  1914.     fatal("init_term: scr assignment botched for [screensize-1]", 0);
  1915.  
  1916.     scr_attrs = &real_attrs[MAX_SCREENSIZE - screensize];
  1917.     if (scr_attrs[0] == NIL)
  1918.     fatal("init_term: scr assignment botched for [0]", 0);
  1919.     if (scr_attrs[screensize-1] == NIL)
  1920.     fatal("init_term: scr assignment botched for [screensize-1]", 0);
  1921.     
  1922.     scrtop = toplin;        /* Scrolling region equals all */
  1923.     scrbot = botlin;
  1924.     display_topline = toplin;    /* init display w/elevator at bottom */
  1925.     display_totlines = screensize;
  1926.     makerect (&ScreenRect, 0, 0, screensize, MAXCOL);
  1927.     /* (UoR) full screen rectangle */
  1928.     
  1929.     SizeWindow(terminalWindow,
  1930.         rightMARGIN + 1 + 16,     /* add extra to side for asthetics */
  1931.     bottomMARGIN + TOPMARGIN,     /* add extra to bottom for asthetics */
  1932.     FALSE);
  1933.     /* PWP: make the window match it's real size */
  1934.     
  1935.     DrawGrowIcon (terminalWindow);
  1936.     
  1937.     /* erase the bottom scroll line */
  1938.     PenMode(patBic);
  1939.     MoveTo(0, (terminalWindow->portRect).bottom - 15);
  1940.     LineTo((terminalWindow->portRect).right - 16,
  1941.         (terminalWindow->portRect).bottom - 15);
  1942.     PenNormal();
  1943.     
  1944.     t_vscroll = GetNewControl (RCMDVSCROLL, terminalWindow);
  1945.     sizevscroll();
  1946.  
  1947.     InitKeyStuff();        /* find the original KCHR keymaps */
  1948.  
  1949.     /* ClipRect(&ScreenRect); */
  1950. }                /* init_term */
  1951.  
  1952. /****************************************************************************/
  1953. /* sizevscroll - called when window is created and after a window grow */
  1954. /*                      sequence to resize the scroll window's bars. */
  1955. /****************************************************************************/
  1956. sizevscroll ()
  1957. {
  1958.     register Rect *r;
  1959.  
  1960.     r = &terminalWindow->portRect;/* window size */
  1961.     HideControl (t_vscroll);
  1962.  
  1963.     MoveControl (t_vscroll, r->right - 15, r->top - 1);
  1964.     SizeControl (t_vscroll, 16, r->bottom - r->top - 13);
  1965.  
  1966.     SetCtlMin (t_vscroll, 0);
  1967.     update_vscroll();
  1968.     ShowControl (t_vscroll);
  1969. }                /* sizescrollbars */
  1970.  
  1971. /****************************************************************************/
  1972. /* grow_term_to(size) -- change the size of the terminal window to size.
  1973.    this is called by growterm() (see below) and the terminal settings dialog
  1974.    handler (termsetdialog()).
  1975. /****************************************************************************/
  1976. grow_term_to (size)
  1977. int size;
  1978. {
  1979.     long gr;
  1980.     int height;
  1981.     int width;
  1982.     char *savedline;
  1983.     int i, j, d;
  1984.     GrafPtr savePort;
  1985.  
  1986.     if ((size < 1) || (size > MAX_SCREENSIZE))
  1987.        size = 24;    /* the default case */
  1988.     
  1989.     if (size > display_totlines) {    /* if getting bigger than we were */
  1990.         for (i = screensize - display_totlines, j = screensize - size;
  1991.          i < screensize; i++, j++) {
  1992.         savedline = scr[i];        /* save used line */
  1993.         scr[i] = scr[j];        /* copy empty line to old line */
  1994.         scr[j] = savedline;        /* copy old line to new line */
  1995.         savedline = scr_attrs[i];    /* do the same for attribute lines */
  1996.         scr_attrs[i] = scr_attrs[j];
  1997.         scr_attrs[j] = savedline;
  1998.     }
  1999.     display_totlines = size;
  2000.     } else {
  2001.     curlin += size - screensize;    /* adjust cursor row to match stretch */
  2002.     if (curlin < 0)
  2003.         curlin = 0;
  2004.     if (curlin > size-1)
  2005.         curlin = size-1;
  2006.     }
  2007.     
  2008.     screensize = size;
  2009.     if (screensize > MAX_SCREENSIZE)
  2010.         screensize = MAX_SCREENSIZE;        /* bounds check */
  2011.  
  2012.     scr = &real_scr[MAX_SCREENSIZE - screensize];
  2013.     scr_attrs = &real_attrs[MAX_SCREENSIZE - screensize];
  2014.     
  2015.     bottommargin = bottomMARGIN;    /* this changes */
  2016.     
  2017.     scrtop = toplin;        /* Scrolling region equals all */
  2018.     scrbot = botlin;
  2019.     display_topline = 0;    /* re-init display w/elevator at bottom */
  2020.     makerect (&ScreenRect, 0, 0, screensize, MAXCOL);
  2021.     /* (UoR) full screen rectangle */
  2022.     
  2023.     SizeWindow(terminalWindow,
  2024.         rightMARGIN + 1 + 16,     /* add extra to side for asthetics */
  2025.     bottomMARGIN + TOPMARGIN,     /* add extra to bottom for asthetics */
  2026.     FALSE);
  2027.     /* PWP: make the window match it's real size */
  2028.     sizevscroll ();    /* size the scroll bars */
  2029.  
  2030.     /* ClipRect(&ScreenRect); */
  2031.  
  2032.     GetPort (&savePort);
  2033.     SetPort (terminalWindow);
  2034.     InvalRect (&terminalWindow->portRect);    /* invalidate whole window rectangle */
  2035.     SetPort (savePort);
  2036. }                /* growwindow */
  2037.  
  2038. /****************************************************************************/
  2039. /****************************************************************************/
  2040. growterm (p)
  2041. Point *p;
  2042. {
  2043.     long gr;
  2044.     int height;
  2045.     int width;
  2046.     int size;
  2047.     Rect growRect;
  2048.     GrafPtr savePort;
  2049.  
  2050.     growRect = qd.screenBits.bounds;
  2051.     growRect.top = 50;        /* minimal horizontal size */
  2052.     growRect.left = rightMARGIN + 18;    /* minimal vertical size */
  2053.     growRect.right = rightMARGIN + 18;    /* minimal vertical size */
  2054.  
  2055.     gr = GrowWindow (terminalWindow, p, &growRect);
  2056.  
  2057.     if (gr == 0)
  2058.     return;
  2059.     height = HiWord (gr);
  2060.     width = LoWord (gr);
  2061.  
  2062.     size = (height - (2 * TOPMARGIN)) / LINEHEIGHT;
  2063.     if (size > MAX_SCREENSIZE)
  2064.         screensize = MAX_SCREENSIZE;        /* bounds check */
  2065.     if (size < 1)
  2066.         size = 1;
  2067.  
  2068.     grow_term_to(size);
  2069. }                /* growterm */
  2070.