home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
ckc072.zip
/
ckmcon.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-08-16
|
58KB
|
2,292 lines
/* Paul Placeway, Ohio State -- added option to flashing cursor, made */
/* key macros use Pascal strings, so that a NUL (0x00) can be sent */
/* Enhanced by Clayton M. Elwell, Ohio State University 24 Nov 1987 -- */
/* added insert character */
/* Matthias Aebi, ECOFIN Research and Consulting, Ltd., Oct 1987 -- */
/* ported to MPW, changed the way keys work */
/* Version 0.8(35) - Jim Noble at Planning Research Corporation, June 1987. */
/* Ported to Megamax native Macintosh C compiler. */
/* From: DPVC@UORDBV.BITNET */
/* DPVC at U of R, Oct 1, add blinking cursor and mouse cursor movement */
/* DPVC at U of R, Sept. 26, fixed book-keeping for scrolling and inserting */
/* characters and lines */
/* DPVC at U of R, Sept. 25, to fix cursor positioning off the screen, and */
/* a few other, minor VT100 incompatibilities */
/* DPVC at the University of Rochester, Sept. 9, to add Block Cursor and */
/* ability to do VT100 graphics characters */
/* By CAM2 and DPVC at the University of Rochester on Sept 6, */
/* changed bolding from using TextStyle attributes to using a separate bold */
/* font */
/* By Frank on June 20 - Add parity to all outbound chars using software */
/* Also, ignore DEL (0177) characters on input. */
/* By Bill on May 29 - Add Key set translation */
/* By WBC3 on Apr 24 - Add ^^, ^@ and ^_. Also use Pascal strings for */
/* output in the terminal emulator */
/* By WBC3 on Apr 23 - Add query terminal and be more fastidious about */
/* ignoring sequences we don't know about */
/* By WBC3 on Apr 22 - Fix tab stops to conform to the rest of the world! */
/* By Bill on Apr 21 - Fix immediate echo problems. */
/* do less cursor_erase, cursor_draw stuff */
/*
* FILE ckmcon.c
*
* Module of mackermit: contains code for the terminal simulation
* routine.
*/
#include "ckcdeb.h"
#define __SEG__ ckmcon
#include <quickdraw.h>
#include <files.h>
#include <events.h>
#include <windows.h>
#include <toolutils.h>
#include <osutils.h>
#include <ctype.h>
#include "ckmdef.h"
#include "ckmasm.h" /* Assembler code */
#define MAXLIN 24
#define MAXCOL 80
#define LINEHEIGHT 12
#define CHARWIDTH 6
#define TOPMARGIN 3 /* Terminal display constants */
#define bottomMARGIN (LINEHEIGHT * MAXLIN + TOPMARGIN)
#define LEFTMARGIN 3
#define rightMARGIN (CHARWIDTH * MAXCOL + LEFTMARGIN)
#define LINEADJ 3 /* Amount of char below base line */
/* Font Numbers (UoR Mod) to fix bolding problems */
/* These should be placed in the RESOURCE FORK of the executable */
#define VT100FONT 128 /* VT100 Terminal Font (not-bold) */
#define VT100BOLD 129 /* VT100 Bold Font */
/* Tab settings */
/*
#define NUMTABS 9
short tabstops[NUMTABS] = {8,16,24,32,40,48,56,64,72};
*//* (UoR) remove old method of tab stops */
/* (UoR) do tapstops via an array: 0 means no tab, 1 means tab at that column */
short tabstops[MAXCOL + 1] = {
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1
};
#define USA_SET 0 /* (UoR) VT100 character set numbers */
#define UK_SET 1
#define GRAF_SET 2
int topmargin = TOPMARGIN, /* Edges of adjustable window */
bottommargin = bottomMARGIN,
textstyle = 0,
currentfont = VT100FONT, /* (UoR) currently active font */
graphicsinset[2] = {USA_SET, USA_SET}, /* (UoR) current character sets */
current_set = 0, /* (UoR) current chosen set */
doinvert = FALSE, /* Flag for inverted terminal mode */
dounder = FALSE, /* Flag for underlining (PWP) */
screeninvert = FALSE, /* (UoR) inverted screen flag */
insert = FALSE,
newline = FALSE, /* (UoR) linefeed mode by default */
autowrap = TRUE, /* Autowrap on by default */
relorigin = FALSE, /* (UoR) relative origin off */
autorepeat = TRUE, /* (UoR) auto repeat flag */
smoothscroll = FALSE, /* do smooth scrolling (PWP: or not) */
transparent = TRUE, /* do not show control characters */
blockcursor = TRUE, /* show block or underline cursor */
mouse_arrows = FALSE, /* mouse down in screen does arrow keys */
visible_bell = FALSE, /* true if we do blink instead of bell */
nat_chars = FALSE, /* half transparent -- show undef. control
* chars */
blinkcursor = TRUE; /* true if we make the cursor blink */
char *querystring = "\033[?1;2c"; /* Answer we are a VT100 with AVO */
/* (UoR) used to be VT102 */
char *reportstring = "\033[0n"; /* (UoR) report that we're OK */
char *noprinter = "\033[?13n"; /* (UoR) report no printer */
Rect ScreenRect;
/*
* (UoR) don't need scrollrect any more (use scroll_up and scroll_down), use
* ScreenRect for mouse check
*/
/* Screen book keeping variables */
char scr[MAXLIN][MAXCOL + 1]; /* Characters on the screen */
short nxtlin[MAXLIN], toplin, botlin; /* Linked list of lines */
int curlin, curcol, abslin; /* Cursor position */
int savcol, savlin; /* Cursor save variables */
int savsty, savfnt, savgrf, savmod, savset[2]; /* (UoR) cursor save
* variables */
int savund; /* PWP for saved underlining */
int scrtop, scrbot; /* Absolute scrolling region bounds */
int cursor_invert = FALSE, /* (UoR) for flashing cursor */
cur_drawn = FALSE;
long last_flash = 0;
int oldlin = -1;
int oldcol = 0; /* (UoR) for last mouse position */
RgnHandle dummyRgn; /* dummy region for ScrollRect */
/* Initialized in mac_init */
# define CARETTIME 20 /* (UoR) ticks between flashes */
/* Stuff for escape character processing */
#define CF_OUTC 0 /* Just output the char */
#define CF_SESC 1 /* In a single char escape seq */
#define CF_MESC 2 /* In a multi char '[' escape seq */
#define CF_TOSS 3 /* Toss this char */
#define CF_GRF0 4 /* (UoR) for graphics sequence 0 */
#define CF_GRF1 5 /* (UoR) for graphics sequence 1 */
char prvchr, numone[6], numtwo[6], *numptr;
int num1, num2, charflg = CF_OUTC;
/* extern CSParam controlparam; */
extern unsigned char dopar ();
typedef int (*PFI) ();
/* Terminal function declarations. */
int
tab (), back_space (), carriage_return (), line_feed (), bell (),
escape_seq (), text_mode (), clear_line (), erase_display (),
cursor_position (), cursor_up (), cursor_down (), cursor_right (),
cursor_left (), cursor_save (), cursor_restore (), set_scroll_region (),
reverse_line_feed (), dummy (), delete_char (), insert_mode (),
end_insert_mode (), insert_line (), delete_line (), query_terminal (),
multi_char (), toss_char (), insert_chars (),
/* (UoR) for VT100 graphic character set */
graphic_G0 (), graphic_G1 (), control_N (), control_O (),
/* (UoR) for other VT100 functions */
new_line (), request_report (), set_tab (), clear_tab ();
/* (UoR) constansts that point to the function definitions for arrow keys */
/* Used by mouse cursor positioning function (Pascal strings) */
# define UPARROW "\003\033OA"
# define DOWNARROW "\003\033OB"
# define leftARROW "\003\033OD"
# define rightARROW "\003\033OC"
/* Terminal control character function command table. */
#define MINSINGCMDS 000
#define MAXSINGCMDS 037
PFI controltable[MAXSINGCMDS - MINSINGCMDS + 1] =
{
dummy, /* 0 */
dummy, /* 1 */
dummy, /* 2 */
dummy, /* 3 */
dummy, /* 4 */
dummy, /* 5 */
dummy, /* 6 */
bell, /* 7 */
back_space, /* 10 */
tab, /* 11 */
line_feed, /* 12 */
line_feed, /* 13 (Vertical tab) */
line_feed, /* 14 (Form feed) */
carriage_return, /* 15 */
control_N, /* 16 (graphic set 1) *//* (UoR) */
control_O, /* 17 (graphic set 0) *//* (UoR) */
dummy, /* 20 */
dummy, /* 21 */
dummy, /* 22 */
dummy, /* 23 */
dummy, /* 24 */
dummy, /* 25 */
dummy, /* 26 */
dummy, /* 27 */
dummy, /* 30 */
dummy, /* 31 */
dummy, /* 32 */
escape_seq, /* 33 (Escape) */
dummy, /* 34 */
dummy, /* 35 */
dummy, /* 36 */
dummy /* 37 */
};
#define MINSINGESCS 0040
#define MAXSINGESCS 0137
PFI singescapetable[MAXSINGESCS - MINSINGESCS + 1] =
{
dummy, /* 40 */
dummy, /* 41 */
dummy, /* 42 */
toss_char, /* 43 '#' */
dummy, /* 44 */
dummy, /* 45 */
dummy, /* 46 */
dummy, /* 47 */
graphic_G0, /* 50 '(' *//* (UoR) */
graphic_G1, /* 51 ')' *//* (UoR) */
dummy, /* 52 */
dummy, /* 53 */
dummy, /* 54 */
dummy, /* 55 */
dummy, /* 56 */
dummy, /* 57 */
dummy, /* 60 */
dummy, /* 61 */
dummy, /* 62 */
dummy, /* 63 */
dummy, /* 64 */
dummy, /* 65 */
dummy, /* 66 */
cursor_save, /* 67 '7' */
cursor_restore, /* 70 '8' */
dummy, /* 71 */
dummy, /* 72 */
dummy, /* 73 */
dummy, /* 74 '<' */
dummy, /* 75 '=' */
dummy, /* 76 '>' */
dummy, /* 77 */
dummy, /* 100 */
dummy, /* 101 */
dummy, /* 102 */
dummy, /* 103 */
line_feed, /* 104 'D' */
new_line, /* 105 'E' *//* (UoR) */
dummy, /* 106 */
dummy, /* 107 */
set_tab, /* 110 'H' *//* (UoR) */
dummy, /* 111 */
dummy, /* 112 */
dummy, /* 113 */
dummy, /* 114 */
reverse_line_feed, /* 115 'M' */
toss_char, /* 116 'N' *//* CME */
toss_char, /* 117 'O' *//* (UoR) ignore these */
dummy, /* 120 */
dummy, /* 121 */
dummy, /* 122 */
dummy, /* 123 */
dummy, /* 124 */
dummy, /* 125 */
dummy, /* 126 */
dummy, /* 127 */
dummy, /* 130 */
dummy, /* 131 */
query_terminal, /* 132 'Z' */
multi_char, /* 133 '[' */
dummy, /* 134 */
dummy, /* 135 */
dummy, /* 136 */
dummy /* 137 */
};
/* Terminal escape sequence function command table */
#define MINMULTESCS 0100
#define MAXMULTESCS 0177
PFI escapetable[MAXMULTESCS - MINMULTESCS + 1] =
{
insert_chars, /* 100 *//* CME */
cursor_up, /* 101 'A' */
cursor_down, /* 102 'B' */
cursor_right, /* 103 'C' */
cursor_left, /* 104 'D' */
dummy, /* 105 */
dummy, /* 106 */
dummy, /* 107 */
cursor_position, /* 110 'H' */
dummy, /* 111 */
erase_display, /* 112 'J' */
clear_line, /* 113 'K' */
insert_line, /* 114 'L' */
delete_line, /* 115 'M' */
dummy, /* 116 */
dummy, /* 117 */
delete_char, /* 120 'P' */
dummy, /* 121 */
dummy, /* 122 */
dummy, /* 123 */
dummy, /* 124 */
dummy, /* 125 */
dummy, /* 126 */
dummy, /* 127 */
dummy, /* 130 */
dummy, /* 131 */
dummy, /* 132 */
dummy, /* 133 */
dummy, /* 134 */
dummy, /* 135 */
dummy, /* 136 */
dummy, /* 137 */
dummy, /* 140 */
dummy, /* 141 */
dummy, /* 142 */
query_terminal, /* 143 'c' */
dummy, /* 144 */
dummy, /* 145 */
cursor_position, /* 146 'f' */
clear_tab, /* 147 'g' *//* (UoR) */
insert_mode, /* 150 'h' */
dummy, /* 151 */
dummy, /* 152 */
dummy, /* 153 */
end_insert_mode, /* 154 'l' */
text_mode, /* 155 'm' */
request_report, /* 156 'n' *//* (UoR) */
dummy, /* 157 */
dummy, /* 160 */
dummy, /* 161 */
set_scroll_region, /* 162 'r' */
dummy, /* 163 */
dummy, /* 164 */
dummy, /* 165 */
dummy, /* 166 */
dummy, /* 167 */
dummy, /* 170 */
dummy, /* 171 */
dummy, /* 172 */
dummy, /* 173 */
dummy, /* 174 */
dummy, /* 175 */
dummy, /* 176 */
dummy /* 177 */
};
/****************************************************************************/
/* Connect support routines */
/****************************************************************************/
consetup ()
{
PenMode (patXor);
flushio (); /* Get rid of pending characters */
init_term (); /* Set up some terminal variables */
TextFont (VT100FONT); /* (UoR) Set initial font to VT100 */
TextMode (srcXor); /* (UoR) use XOR mode (for inverse) */
TextFace (0); /* PWP: be safe. We allways stay like this */
clear_screen (); /* Clear the screen */
home_cursor (); /* Go to the upper left */
cursor_save (); /* Save this position */
cursor_draw (); /* (UoR) be sure to draw it */
} /* consetup */
/****************************************************************************/
/* Input and process all the characters pending on the tty line */
/****************************************************************************/
inpchars ()
{
int rdcnt;
if ((rdcnt = ttchk ()) == 0)/* How many chars there? */
return; /* Ret if 0 */
cursor_erase (); /* remove cursor from screen */
while (rdcnt-- > 0) /* Output all those characters */
printit (ttinc (0));
flushbuf (); /* Flush any remaining characters */
cursor_draw (); /* put it back */
} /* inpchars */
/****************************************************************************/
/* writeps - write a pascal form string to the serial port.
*
*/
/****************************************************************************/
writeps (s)
char *s;
{
long wcnt, w2;
int err;
char *s2;
w2 = wcnt = *s++; /* get count */
for (s2 = s; w2 > 0; w2--, s2++) /* add parity */
*s2 = dopar (*s2);
err = FSWrite (outnum, &wcnt, s); /* write the characters */
if (err != noErr)
printerr ("Bad FSWrite in writeps: ", err);
return;
} /* writeps */
/****************************************************************************/
/*
* (UoR)
*
* Print a string to the screen (used to echo function and meta strings
* in duplex mode).
*
*/
/****************************************************************************/
printps (s)
char *s;
{
long w2;
char *s2;
cursor_erase ();
w2 = *s++; /* get count */
for (s2 = s; w2 > 0; w2--, s2++)
printit (*s2); /* print it out, and perform special
* functions */
flushbuf ();
cursor_draw ();
return;
} /* printps */
/****************************************************************************/
/* return the ASCII character which is generated by the keyCode specified */
/* with no modifiers pressed */
/****************************************************************************/
unsigned char
DeModifyChar (keyCode)
short keyCode;
{
ProcHandle KeyTrans;
long c;
if (keyCode > 64)
KeyTrans = 0x2A2; /* keypad decode */
else
KeyTrans = 0x29E; /* keyboard decode */
SaveRegs (); /* save all registers */
AllRegs ();
/* setup regs for procedure call */
loadD1 ((long) 0); /* no modifiers */
loadD2 ((long) keyCode); /* set the keycode */
loadA0 (*KeyTrans); /* load the content of Key1Trans to A0 */
/* run the translation routine */
execute (); /* call the Key1Trans procedure */
/* move the result from reg D0 to c */
loadA0 (&c); /* set destination address */
pushD0 (); /* move register D0 to stack */
poptoA0 (); /* load the stacktop to (A0) */
RestoreRegs (); /* restore all registers */
AllRegs ();
return (c);
} /* DeModifyChar */
unsigned char obuf[2] = {1, 0}; /* single char output buffer */
/****************************************************************************/
/* send a character to the line if it is in ASCII range. Do local echo if */
/* necessary */
/****************************************************************************/
OutputChar (c)
unsigned char c;
{
/*
* PWP: NO 7 bit masking!!! If we do this, then I can't use Emacs, and
* the European users will be VERY unhappy, 'cause they won't be able to
* send all of their characters.
*/
#ifdef COMMENT_OUT
if (c > 127) { /* reject non-ASCII characters */
SysBeep (1);
return;
}
#endif /* COMMENT_OUT */
obuf[1] = c; /* store character */
writeps (obuf); /* and write it out */
if (duplex != 0) {
cursor_erase (); /* remove from screen */
printit ((char) c); /* Echo the char to the screen */
flushbuf (); /* flush the character */
cursor_draw (); /* put it back */
}
} /* OutputChar */
extern char keytable[512]; /* the key redefintion flag table */
extern modrec modtable[NUMOFMODS]; /* modifier records */
#define myKeyCodeMask 0x7F00
#define keyModifierMask 0x1F00
#define ctrlCodeMask 0x1F
#define metaOrBits 0x80
#define UnmodMask 0x80 /* action bits */
#define CapsMask 0x40
#define CtrlMask 0x20
#define MetaMask 0x10
/****************************************************************************/
/* Process a character received from the keyboard */
/****************************************************************************/
handle_char (evt)
EventRecord *evt;
{
short i;
short len;
short theCode;
short modCode;
short theModBits;
char flags;
char tmpstr[256];
unsigned char c;
/* (UoR) check for auto repeated keys */
if ((autorepeat == FALSE) && (evt->what == autoKey))
return;
ObscureCursor (); /* PWP: hide the cursor until next move */
modCode = evt->modifiers & keyModifierMask;
theCode = ((evt->message & myKeyCodeMask) >> 8) + (modCode >> 1);
/* check for a special code for this key */
if (BitTst (&keytable, theCode)) {
GetMacro (theCode, &flags, tmpstr); /* get the macrostring */
if (flags) { /* check special flags */
if (flags & shortBreak) { /* short break ? */
sendbreak (5);
return;
}
if (flags & longBreak) { /* long break ? */
sendbreak (70);
return;
}
}
/* send key macro string */
/*
* PWP: note, we DON'T have to convert it to a Pascal string, 'cause
* the macros are now stored as Pascal strings
*/
writeps (tmpstr); /* send it to the line */
if (duplex != 0)
printps (tmpstr); /* echo it locally */
return;
}
for (i = 0; i < NUMOFMODS; i++) {
/* shift what to look for into high byte */
theModBits = modtable[i].modbits << 4;
len = strlen (modtable[i].prefix);
if ((theModBits || len) &&
((theModBits & modCode) == (theModBits & keyModifierMask))) {
/* send prefix if there is one */
if (len) {
/* PWP: these are saved as Pascal strings now */
BlockMove (modtable[i].prefix, tmpstr, (modtable[i].prefix[0] + 1));
writeps (tmpstr); /* send it to the line */
if (duplex != 0)
printps (tmpstr); /* echo it locally */
}
/*
* get the unmodified ASCII code if the unmodify action bit is
* active
*/
if (theModBits & UnmodMask)
c = DeModifyChar ((evt->message & myKeyCodeMask) >> 8);
else
c = evt->message & charCodeMask; /* otherwise get the
* standard char */
/* make an uppercase character if the caps action bit is active */
if ((theModBits & CapsMask) && islower (c))
c = _toupper (c);
/* make a control character if the control action bit is active */
if (theModBits & CtrlMask)
c &= ctrlCodeMask;
/* PWP: for Meta characters (yes, I use Emacs) */
if (theModBits & MetaMask)
c |= metaOrBits;
OutputChar (c);
return;
} /* if */
} /* for */
/* get the ASCII code and send it */
OutputChar (evt->message & charCodeMask);
} /* handle_char */
char outbuf[MAXCOL + 1];
int outcnt = 0, outcol;
/****************************************************************************/
/* flushbuf() -- draw all the buffered characters on the screen */
/****************************************************************************/
flushbuf ()
{
Rect r;
if (outcnt == 0)
return; /* Nothing to flush */
/* Erase a hole large enough for outcnt chars */
makerect (&r, abslin, outcol, 1, outcnt);
EraseRect (&r); /* (UoR) Use InvertRect instead of fillRect */
DrawText (outbuf, 0, outcnt); /* Output the string */
if (doinvert) /* PWP: moved this... */
InvertRect (&r);
if (dounder) { /* PWP: do underlining */
makertou (&r); /* make into an underline */
InvertRect (&r);
}
outcnt = 0; /* Say no more chars to output */
} /* flushbuf */
/****************************************************************************/
/* save a character in the buffer */
/****************************************************************************/
buf_char (c)
char c;
{
if (outcnt == 0)
outcol = curcol; /* No chars in buffer, init column */
outbuf[outcnt++] = c; /* Put in the buffer to output later */
} /* buf_char */
/****************************************************************************/
/*
* Printit:
* Draws character and updates buffer
*/
/****************************************************************************/
printit (c)
char c;
{
PFI funp, lookup ();
long lnum1, lnum2;
c &= 0177;
if (c != 0) { /* (UoR) ignore null characters */
switch (charflg) {
case CF_OUTC: /* Just output the char */
MDrawChar (c);
break;
case CF_SESC: /* In a single char escape seq */
charflg = CF_OUTC; /* Reset flag to simple outputting */
if (funp = lookup (c, singescapetable, MINSINGESCS, MAXSINGESCS))
(*funp) (); /* Do escape sequence function */
break;
case CF_GRF0: /* (UoR) process graphic characters */
case CF_GRF1:
switch (c) {
case 'A':
graphicsinset[charflg - CF_GRF0] = UK_SET;
break;
case 'B':
case '1':
graphicsinset[charflg - CF_GRF0] = USA_SET;
break;
case '0':
case '2':
graphicsinset[charflg - CF_GRF0] = GRAF_SET;
break;
}
charflg = CF_OUTC; /* Reset flag for next character */
break;
case CF_MESC: /* Multichar escape sequence */
if (c >= 0x20 && c < 0x40) { /* Deal with the modifiers */
if (c >= '<' && c <= '?') {
prvchr = c; /* Handle priv char */
} else if ((numptr == numone || numptr == numtwo) &&
(c == '0' || c == '-' || c == '+')) {
/* if at start of sequence */
if (c == '-') /* then we only record leading - */
*numptr++ = c;
} else if (c >= '0' && c <= '9') { /* PWP: was also '+' or '-' */
*numptr++ = c; /* Add the char to the num */
} else if (c == ';') {
*numptr = '\0'; /* Terminate the string */
numptr = numtwo; /* Go to next number */
} else {
charflg = CF_OUTC; /* (UoR) */
}
} else if (c >= 0x40) { /* End of sequence */
/* PWP: according to VTTEST, we ignore control characters here */
if (funp = lookup (c, escapetable, MINMULTESCS, MAXMULTESCS)) {
*numptr = '\0'; /* Terminate the string */
StringToNum (numone, &lnum1); /* Translate the numbers */
StringToNum (numtwo, &lnum2);
num1 = (int) lnum1;
num2 = (int) lnum2;
(*funp) (); /* Do the escape sequence function */
}
charflg = CF_OUTC; /* Back to simple outputting */
}
break;
case CF_TOSS: /* Ignore this char */
charflg = CF_OUTC; /* Reset flag */
break;
}
}
} /* printit */
/****************************************************************************/
/*
* Routine makerect
*
* Make a rectangle in r starting on line lin and column col extending
* numlin lines and numcol characters.
*
*/
/****************************************************************************/
makerect (r, lin, col, numlin, numcol)
Rect *r;
int lin;
int col;
int numlin;
int numcol;
{
r->top = lin * LINEHEIGHT + TOPMARGIN;
r->left = col * CHARWIDTH + LEFTMARGIN;
r->bottom = r->top + numlin * LINEHEIGHT;
r->right = r->left + numcol * CHARWIDTH;
} /* makerect */
/* Make rect r (made by makerect()) into the right shape
for underlining */
makertou (r)
Rect *r;
{
r->top = r->bottom - 1;
}
/****************************************************************************/
/*
* Lookup:
* Lookup a given character in the apropriate character table, and
* return a pointer to the appropriate function, if it exists.
*/
/****************************************************************************/
PFI
lookup (index, table, min, max)
char index;
PFI table[];
int min;
int max;
{
if (index > max || index < min)
return ((PFI) NULL); /* Don't index out of range */
return (table[index - min]);
} /* lookup */
/****************************************************************************/
/*
* Flushio:
* Initialize some communications constants, and clear screen and
* character buffers. */
/****************************************************************************/
flushio ()
{
int err;
err = KillIO (-6);
if (err)
printerr ("Bad input clear", err);
err = KillIO (-7);
if (err)
printerr ("Bad ouput clear", err);
} /* flushio */
/****************************************************************************/
/* sendbreak - sends a break across the communictions line.
*
* The argument is in units of approximately 0.05 seconds (or 50
* milliseconds). To send a break of duration 250 milliseconds the
* argument would be 5; a break of duration 3.5 seconds would be (umm,
* lets see now) 70.
*
*/
/****************************************************************************/
sendbreak (msunit)
{
long finalticks;
/* delay wants 1/60th units. We have 3/60 (50 ms.) units, convert */
msunit = msunit * 3;
SerSetBrk (outnum); /* start breaking */
Delay ((long) msunit, &finalticks); /* delay */
SerClrBrk (outnum); /* stop breaking */
} /* sendbreak */
/****************************************************************************/
/* draw a characer on the screen (or buffer it) */
/****************************************************************************/
MDrawChar (chr)
char chr;
{
PFI funp;
/* If it's a control char, do the apropriate function. */
if ((chr < ' ') && (transparent)) { /* Is it a control character */
flushbuf ();
if (funp = lookup (chr, controltable, MINSINGCMDS, MAXSINGCMDS)) {
if (funp != dummy) {/* PWP */
(*funp) ();
return;
}
}
if (!nat_chars) /* PWP: half transparent -- show undefd
* controls */
return;
if (chr == '\0') /* PWP: never show nulls */
return;
}
if (chr < 0177) { /* Don't do Mac graphic characters */
switch (graphicsinset[current_set]) {
case GRAF_SET: /* Do VT100 graphics (offset to character in
* VT100 font) */
if ((chr >= '_') && (chr <= '~'))
chr += 128;
break;
case UK_SET: /* Use pound symbol from VT100 font */
if (chr == '#')
chr = 0375; /* VT100 pound symbol = 0375 */
break;
}
if (curcol >= MAXCOL) { /* Are we about to wrap around? */
if (autowrap) { /* If autowrap indicated wrap */
flushbuf ();
if (newline == FALSE)
carriage_return ();
line_feed ();
} else {
flushbuf (); /* (UoR) make sure last char is shown */
back_space (); /* Otherwise just overwrite */
}
}
if (insert) { /* Insert mode? */
insert_char (); /* Open hole for char if requested */
erase_char (); /* Erase the old char */
DrawChar (chr);
} else
buf_char (chr); /* Otherwise just buffer the char */
scr[curlin][curcol++] = chr;
}
} /* MDrawChar */
/****************************************************************************/
/*
* Control character functions:
* Each of the following allow the mac to simulate
* the behavior of a terminal when given the proper
* control character.
*/
/****************************************************************************/
back_space ()
{
if (curcol > 0)
relmove (-1, 0);
} /* back_space */
erase_char ()
{
Rect r;
scr[curlin][curcol] = ' '; /* Erase char for update */
makerect (&r, abslin, curcol, 1, 1); /* One char by one line */
EraseRect (&r); /* (UoR) use InvertRect instead of FillRect */
if (doinvert)
InvertRect (&r);
} /* erase_char */
tab ()
{
int i;
/* for (i=0; i<NUMTABS; i++)
{
if (tabstops[i] > curcol)
{
absmove(tabstops[i],abslin);
return;
}
* }*/
/* (UoR) remove old method of tabbing */
/* (UoR) find next tabstop */
for (i = curcol + 1; (i < MAXCOL) && (tabstops[i] == 0); i++);
absmove (i, abslin);
} /* tab */
line_feed ()
{
if (newline)
absmove (0, abslin); /* (UoR) perform newline function */
if (curlin == scrbot)
scroll_up (scrtop, curlin); /* (UoR) scroll lines up */
else
relmove (0, 1);
} /* line_feed */
reverse_line_feed ()
{
if (curlin == scrtop)
scroll_down (curlin, scrbot); /* (UoR) scroll down in region */
else
relmove (0, -1);
} /* reverse_line_feed */
carriage_return ()
{
if (newline)
line_feed (); /* (UoR) perform newline function */
else
absmove (0, abslin);
} /* carriage_return */
new_line ()
{
carriage_return ();
line_feed ();
} /* new_line */
clear_screen ()
{
register int i;
Rect r;
makerect (&r, 0, 0, MAXLIN, MAXCOL); /* The whole screen */
EraseRect (&r);
for (i = 0; i < MAXLIN; i++)
zeroline (i); /* Clear up the update records */
} /* clear_screen */
home_cursor ()
{
if (relorigin)
absmove (0, fndabs (scrtop));
else
absmove (0, 0); /* (UoR) correct for relative origin */
} /* home_cursor */
/****************************************************************************/
/* PWP -- like waitasec(), but don't get any characters. Used for
visable bell. */
/****************************************************************************/
waitnoinput ()
{
long end_time;
end_time = TickCount () + 2;/* pause for 1/30th second */
while (TickCount () < end_time);
} /* waitnoinput */
bell ()
{
Rect r;
if (visible_bell) {
makerect (&r, 0, 0, MAXLIN, MAXCOL); /* The whole screen */
InvertRect (&r);
waitnoinput (); /* sleep for a bit (1/30 sec) */
InvertRect (&r);
} else {
SysBeep (3);
}
} /* bell */
escape_seq ()
{
charflg = CF_SESC; /* Say we are in an escape sequence */
} /* escape_seq */
graphic_G0 () /* (UoR) do VT100 graphic characters */
{
charflg = CF_GRF0;
} /* graphic_G0 */
graphic_G1 ()
{
charflg = CF_GRF1;
} /* graphic_G1 */
control_N ()
{
current_set = 1; /* set to graphics set 1 */
} /* control_N */
control_O ()
{
current_set = 0; /* set to graphics set 0 */
} /* control_O */
clear_line ()
{
int i;
Rect r;
switch (num1) {
case 0: /* Clear: here to the right */
makerect (&r, abslin, curcol, 1, MAXCOL - curcol);
for (i = curcol; i < MAXCOL; i++)
scr[curlin][i] = ' ';
break;
case 1: /* Clear: left to here */
makerect (&r, abslin, 0, 1, curcol + 1);
for (i = 0; i <= curcol; i++)
scr[curlin][i] = ' ';
break;
case 2: /* Clear: entire line */
makerect (&r, abslin, 0, 1, MAXCOL);
zeroline (curlin);
break;
}
EraseRect (&r);
} /* clear_line */
erase_display ()
{
int i;
Rect r;
switch (num1) {
case 0:
clear_line (); /* Same num1 causes correct clear */
makerect (&r, abslin + 1, 0, MAXLIN - abslin - 1, MAXCOL);
/* (UoR) -1 added */
EraseRect (&r);
for (i = abslin + 1; i < MAXLIN; i++)
zeroline (fndrel (i));
break;
case 1:
clear_line (); /* Same num1 causes correct clear */
makerect (&r, 0, 0, abslin, MAXCOL);
EraseRect (&r);
for (i = 0; i < abslin; i++)
zeroline (fndrel (i));
break;
case 2:
clear_screen ();
break;
}
} /* erase_display */
/****************************************************************************/
/**** All cursor moves need to check that they don't go beyond the margins */
/****************************************************************************/
cursor_right ()
{
if (num1 == 0)
num1 = 1;
relmove (num1, 0);
} /* cursor_right */
cursor_left ()
{
if (num1 == 0)
num1 = 1;
relmove (-num1, 0);
} /* cursor_left */
cursor_up ()
{
int abstop; /* (UoR) check that we don't pass scrtop */
abstop = fndabs (scrtop);
if (num1 == 0)
num1 = 1;
if ((abslin >= abstop) && (abslin - num1 < abstop))
absmove (curcol, abstop);
else
relmove (0, -num1);
} /* cursor_up */
cursor_down ()
{
int absbot; /* (UoR) check that we don't pass scrbot */
absbot = fndabs (scrbot);
if (num1 == 0)
num1 = 1;
if ((abslin <= absbot) && (abslin + num1 > absbot))
absmove (curcol, absbot);
else
relmove (0, num1);
} /* cursor_down */
cursor_position ()
{
/* if (--num1 < 0) num1 = 0;
* if (--num2 < 0) num2 = 0; *//* This is taken care of by absmove */
if (relorigin)
absmove (--num2, fndabs (scrtop) + num1 - 1); /* (UoR) */
else
absmove (--num2, --num1); /* (UoR) moved "--" here from prev
* lines */
} /* cursor_position */
cursor_save ()
{
savcol = curcol; /* Save the current line and column */
savlin = abslin;
/* savsty = textstyle; *//* (UoR) additions */
savfnt = currentfont;
savmod = doinvert;
savund = dounder; /* PWP */
savgrf = current_set;
savset[0] = graphicsinset[0];
savset[1] = graphicsinset[1];
} /* cursor_save */
cursor_restore ()
{
absmove (savcol, savlin); /* Move to the old cursor position */
textstyle = savsty; /* (UoR) additions */
currentfont = savfnt;
doinvert = savmod;
TextFont (currentfont);
/* TextFace(textstyle); */
dounder = savund; /* PWP */
current_set = savgrf;
graphicsinset[0] = savset[0];
graphicsinset[1] = savset[1];
} /* cursor_restore */
cursor_rect (line, col, r)
Rect *r;
{
makerect (r, line, col, 1, 1); /* Get character rectangle */
if (blockcursor) {
/* r->left--; *//* make r a little wider (PWP: or not) */
/* r->top--; */
} else
r->top = r->bottom - 1;
} /* cursor_rect */
cursor_draw ()
{
/* Line(CHARWIDTH,0);*//* Draw cursor */
Rect r;
if (cursor_invert == FALSE) {
cursor_rect (abslin, curcol, &r);
InvertRect (&r);
}
if (oldlin >= 0) { /* (UoR) replace mouse cursor */
cursor_rect (oldlin, oldcol, &r);
PenMode (patXor);
FrameRect (&r);
PenMode (patCopy);
}
cursor_invert = TRUE;
cur_drawn = TRUE;
} /* cursor_draw */
cursor_erase ()
{
/* Line(-CHARWIDTH,0);*//* Erase cursor */
Rect r;
if (cursor_invert) {
cursor_rect (abslin, curcol, &r);
InvertRect (&r);
}
if (oldlin >= 0) { /* (UoR) remove mouse cursor */
makerect (&r, oldlin, oldcol, 1, 1);
cursor_rect (oldlin, oldcol, &r);
PenMode (patXor);
FrameRect (&r);
PenMode (patCopy);
}
cursor_invert = FALSE;
cur_drawn = FALSE;
} /* cursor_erase */
flash_cursor (theWindow)
WindowPtr theWindow;
{
register long tc;
Rect r;
if (theWindow == (WindowPtr) NIL) {
last_flash = TickCount ();
return;
}
#ifdef COMMENT /* PWP: this eats up gobbs of time */
if (FrontWindow () != theWindow) {
last_flash = TickCount ();
return;
}
#endif
tc = TickCount ();
if (((tc - last_flash) > CARETTIME) ||
(tc - last_flash) < 0) {
last_flash = tc;
if (cur_drawn) {
cursor_rect (abslin, curcol, &r);
if (blinkcursor) { /* PWP: only blink if asked for */
InvertRect (&r);
if (cursor_invert)
cursor_invert = FALSE;
else
cursor_invert = TRUE;
} else if (!cursor_invert) { /* make sure that the cursor
* shows up */
InvertRect (&r);
cursor_invert = TRUE;
}
}
}
} /* flash_cursor */
/****************************************************************************/
/* Bittest returns the setting of an element in a Pascal PACKED ARRAY [0..n]
OF Boolean such as the KeyMap argument returned by GetKeys(). */
/****************************************************************************/
Boolean
bittest (bitmap, bitnum)
char bitmap[];
int bitnum;
{
return (0x01 & (bitmap[bitnum / 8] >> (bitnum % 8)));
} /* bittest */
/****************************************************************************/
/* check to see if the cursor is in the window and is going to send a mouse-
arrow keys combination */
/****************************************************************************/
check_pointer (theWindow)
WindowPtr theWindow;
{
Boolean mouse_in_window;
int newlin;
int newcol;
Point MousePt;
Rect r;
/*
* PWP: NOTE!!! since the common case is to do nothing, we do NOT want to
* have the PenMode() calls outside of the tests. We will be only doing
* one or the other anyway, so it won't slow us down any.
*/
GetMouse (&MousePt);
mouse_in_window = PtInRect (&MousePt, &ScreenRect);
newlin = (MousePt.v - TOPMARGIN) / LINEHEIGHT;
newcol = (MousePt.h - LEFTMARGIN) / CHARWIDTH;
if ((FrontWindow () == theWindow) && (mouse_in_window) &&
(cur_drawn) && (mouse_arrows) && Button ()) {
PenMode (patXor); /* For FrameRect calls */
if ((oldlin != newlin) || (oldcol != newcol)) {
if (oldlin >= 0) {
cursor_rect (oldlin, oldcol, &r);
FrameRect (&r);
} else
HideCursor ();
cursor_rect (newlin, newcol, &r);
FrameRect (&r);
oldlin = newlin;
oldcol = newcol;
}
PenMode (patCopy); /* reset to normal pen mode */
}
if (oldlin >= 0) { /* optomize: easy tests first */
if ((FrontWindow () != theWindow) || (!mouse_in_window) ||
(!cur_drawn) || (!mouse_arrows) || (!Button ())) {
PenMode (patXor); /* For FrameRect calls */
cursor_rect (oldlin, oldcol, &r);
FrameRect (&r);
oldlin = -1;
InitCursor (); /* show the arrow cursor immediately */
/* (reset crsr level) */
PenMode (patCopy); /* reset to normal pen mode */
}
}
} /* check_pointer */
mouse_cursor_move (evt)
EventRecord *evt;
{
int mouselin;
int mousecol;
int tempcol;
int templin;
int i;
Point MousePt;
if (!mouse_arrows) /* PWP: make this an option */
return;
MousePt = evt->where;
GlobalToLocal (&MousePt);
mouselin = (MousePt.v - TOPMARGIN) / LINEHEIGHT;
mousecol = (MousePt.h - LEFTMARGIN) / CHARWIDTH;
tempcol = curcol;
templin = abslin;
if (mousecol < tempcol)
for (i = tempcol; i > mousecol; i--) {
writeps (leftARROW);
waitasec ();
/* If tabs are used, we may go too far, so end loop */
if (curcol <= mousecol)
i = mousecol;
}
if (mouselin < templin)
for (i = templin; i > mouselin; i--) {
writeps (UPARROW);
waitasec ();
}
else if (mouselin > templin)
for (i = templin; i < mouselin; i++) {
writeps (DOWNARROW);
waitasec ();
}
if (abslin == mouselin)
tempcol = curcol; /* for short lines */
if (tempcol < mousecol)
for (i = tempcol; i < mousecol; i++) {
writeps (rightARROW);
waitasec ();
/* If tabs are used, we may go too far, so end loop */
if (curcol >= mousecol)
i = mousecol;
}
} /* mouse_cursor_move */
/****************************************************************************/
/* (UoR) get any characters, and pause for a while */
/****************************************************************************/
waitasec ()
{
long end_time;
end_time = TickCount () + 2;/* pause for 1/30th second */
while (TickCount () < end_time);
inpchars ();
} /* waitasec */
set_scroll_region ()
{
if (--num1 < 0)
num1 = 0; /* Make top of line (prev line) */
if (num2 == 0)
num2 = 24; /* Zero means entire screen */
if (num1 < num2 - 1) { /* (UoR) make sure region is legal */
topmargin = (num1 * LINEHEIGHT) + TOPMARGIN;
bottommargin = (num2 * LINEHEIGHT) + TOPMARGIN;
scrtop = fndrel (num1);
scrbot = fndrel (num2 - 1);
home_cursor (); /* We're supposed to home it! */
}
} /* set_scroll_region */
/****************************************************************************/
/* aka Select Graphic Rendition */
/****************************************************************************/
text_mode ()
{
another:
switch (num1) {
case 0: /* primary rendition */
doinvert = FALSE;
TextFont (VT100FONT); /* (Uor) Use plain font */
currentfont = VT100FONT;
dounder = FALSE; /* textstyle=0; TextFace(0); */
break;
case 1: /* bold or increased intensity */
TextFont (VT100BOLD); /* use bold font instead */
currentfont = VT100BOLD;
break;
case 2: /* faint or decreased intensity or secondary
* color */
case 3: /* italic */
case 4: /* underscore */
/* textstyle+=underline; *//* use = not += (avoid roll-over) */
/* textstyle = underline; /* (UoR) */
/* TextFace(textstyle); */
dounder = TRUE;
break;
case 5: /* slow blink (< 150/sec); (UoR) blink is
* inverse */
case 6: /* fast blink (>= 150/sec) */
case 7: /* reverse image */
doinvert = TRUE;
break;
case 21:
case 22:
TextFont (VT100FONT); /* reset to plain font */
currentfont = VT100FONT;
break;
case 24:
/* TextFace(0); /* just reset to plain style */
/* since bolding is done via a separate font */
/* textstyle = 0; */
dounder = FALSE;
break;
case 25:
case 27:
doinvert = FALSE;
break;
}
if (num2 != 0) { /* Check for funny VAXTPU syntax. */
num1 = num2;
num2 = 0;
goto another;
}
} /* text_mode */
/****************************************************************************/
/*
* (UoR)
*
* Insert and Delete lines (replacements for originals, which have
* which have been deleted)
*
*/
/****************************************************************************/
insert_line ()
{
int i, absbot;
absbot = fndabs (scrbot);
if ((abslin >= fndabs (scrtop)) && (abslin <= absbot)) {
if (num1 == 0)
num1 = 1;
if (num1 > absbot - abslin + 1)
num1 = absbot - abslin + 1;
for (i = 0; i < num1; i++)
scroll_down (curlin, scrbot);
}
} /* insert_line */
delete_line ()
{
int i, absbot;
absbot = fndabs (scrbot);
if ((abslin >= fndabs (scrtop)) && (abslin <= absbot)) {
if (num1 == 0)
num1 = 1;
if (num1 > absbot - abslin + 1)
num1 = absbot - abslin + 1;
for (i = 0; i < num1; i++)
scroll_up (curlin, scrbot);
}
} /* delete_line */
delete_char ()
{
int i;
Rect r;
if (num1 == 0)
num1 = 1;
makerect (&r, abslin, curcol, 1, MAXCOL - curcol);
if (num1 > MAXCOL - curcol - 1)
num1 = MAXCOL - curcol - 1;
/* Scroll them out */
ScrollRect (&r, -CHARWIDTH * num1, 0, dummyRgn);
/* Shift them down *//* (UoR) used to assign using abscol */
for (i = curcol; i < MAXCOL - num1; i++)
scr[curlin][i] = scr[curlin][i + num1];
/* Fill in holes with spaces */
while (i < MAXCOL)
scr[curlin][i++] = ' ';
} /* delete_char */
/****************************************************************************/
/* CME */
/****************************************************************************/
insert_chars ()
{
int i;
Rect r;
if (num1 == 0)
num1 = 1;
makerect (&r, abslin, curcol, 1, MAXCOL - curcol);
if (num1 > MAXCOL - curcol - 1)
num1 = MAXCOL - curcol - 1;
/* Scroll them out */
ScrollRect (&r, CHARWIDTH * num1, 0, dummyRgn);
/* Shift them up *//* (UoR) used to assign using abscol */
for (i = MAXCOL - 1; i >= curcol + num1; i--)
scr[curlin][i] = scr[curlin][i - num1];
/* Fill in holes with spaces */
while (i > curcol)
scr[curlin][--i] = ' ';
} /* delete_char */
insert_char ()
{
int i;
Rect r;
makerect (&r, abslin, curcol, 1, MAXCOL - curcol);
ScrollRect (&r, CHARWIDTH, 0, dummyRgn);
/* Shift em up *//* (UoR) used to assign ...[i-1]=...[i] */
/* (UoR) used to assign using abscol */
for (i = MAXCOL - 1; i > curcol; i--)
scr[curlin][i] = scr[curlin][i - 1];
scr[curlin][curcol] = ' ';
} /* insert_char */
insert_mode ()
{
if (prvchr == '?')
set_mode (); /* (UoR) do some of these calls */
switch (num1) {
case 20:
newline = TRUE;
break;
case 4:
insert = TRUE;
break;
}
} /* insert_mode */
end_insert_mode ()
{
if (prvchr == '?')
reset_mode (); /* (UoR) do some of these calls */
switch (num1) {
case 20:
newline = FALSE;
break;
case 4:
insert = FALSE;
break;
}
} /* end_insert_mode */
invert_term ()
{
num1 = 5;
if (screeninvert)
reset_mode ();
else
set_mode ();
} /* invert_term */
set_mode ()
{
Rect r;
switch (num1) {
case 5:
if (screeninvert == FALSE) {
BackPat (qd.black); /* (UoR) use black background */
makerect (&r, 0, 0, MAXLIN, MAXCOL);
InvertRect (&r);
screeninvert = TRUE;
}
break;
case 6:
relorigin = TRUE;
home_cursor ();
break;
case 7:
autowrap = TRUE;
break;
case 8:
autorepeat = TRUE;
break;
}
} /* set_mode */
reset_mode ()
{
Rect r;
switch (num1) {
case 5:
if (screeninvert) {
BackPat (qd.white);
makerect (&r, 0, 0, MAXLIN, MAXCOL);
InvertRect (&r);
screeninvert = FALSE;
}
break;
case 6:
relorigin = FALSE;
home_cursor ();
break;
case 7:
autowrap = FALSE;
break;
case 8:
autorepeat = FALSE;
break;
}
} /* reset_mode */
set_tab ()
{
tabstops[curcol] = 1;
} /* set_tab */
clear_tab ()
{
int i;
switch (num1) {
case 0:
tabstops[curcol] = 0;
break;
case 3:
for (i = 0; i < MAXCOL; i++)
tabstops[i] = 0;
break;
}
} /* clear_tab */
/****************************************************************************/
/* (UoR) use for respoding to information requests */
/****************************************************************************/
writereply (s)
char *s;
{
long wrcnt, w2;
int err;
char *s2;
w2 = wrcnt = strlen (s); /* How long is the string? */
for (s2 = s; w2 > 0; w2--, s2++) /* add parity */
*s2 = dopar (*s2);
err = FSWrite (outnum, &wrcnt, s); /* Respond to the query */
if (err)
printerr ("Bad Writeout:", err);
} /* writereply */
query_terminal ()
{
writereply (querystring);
} /* query_terminal */
/****************************************************************************/
/* (UoR) reports */
/****************************************************************************/
request_report ()
{
switch (num1) {
case 5: /* (UoR) report that we're OK */
writereply (reportstring);
break;
case 6: /* (UoR) reprt the cursor position */
position_report ();
break;
case 15: /* (UoR) report printer status */
if (prvchr == '?')
writereply (noprinter);
break;
}
} /* request_report */
position_report ()
{
int i;
char buf[9];
char *report;
i = 0;
buf[i++] = '\033';
buf[i++] = '[';
if (abslin > 9)
buf[i++] = '0' + (abslin + 1) / 10;
buf[i++] = '0' + (abslin + 1) % 10;
buf[i++] = ';';
if (curcol > 9)
buf[i++] = '0' + (curcol + 1) / 10;
buf[i++] = '0' + (curcol + 1) % 10;
buf[i++] = 'R';
buf[i] = '\0';
report = buf;
writereply (report);
} /* position_report */
/****************************************************************************/
/* does nothing. */
/****************************************************************************/
dummy ()
{
} /* dummy */
multi_char ()
{
numone[0] = numtwo[0] = '0';/* Initialize the numbers to zero */
numone[1] = numtwo[1] = '\0';
numptr = numone; /* Place to put the next number */
prvchr = '\0'; /* No priv char yet */
charflg = CF_MESC; /* Say we are in a ESC [ swequence */
} /* multi_char */
toss_char ()
{
charflg = CF_TOSS;
} /* toss_char */
/****************************************************************************/
/* Routine zeroline
*
* Zero (set to space) all the characters in relative line lin.
*
*/
/****************************************************************************/
zeroline (lin)
int lin;
{
register int i;
Rect r;
for (i = 0; i < MAXCOL; i++)
scr[lin][i] = ' ';
} /* zeroline */
/****************************************************************************/
/* Move a relative number of lines and chars. Both can be negative. */
/****************************************************************************/
relmove (hor, ver)
{
absmove (curcol + hor, abslin + ver); /* (UoR) use absmove, which
* checks */
/* for cursor moving off screen */
} /* relmove */
/****************************************************************************/
/* Move to absolute position hor char and ver line. */
/****************************************************************************/
absmove (hor, ver)
{
if (hor > MAXCOL - 1)
hor = MAXCOL - 1; /* (UoR) make sure its on the screen */
if (hor < 0)
hor = 0;
if (ver > MAXLIN - 1)
ver = MAXLIN - 1;
if (ver < 0)
ver = 0;
if (relorigin) {
if (ver < fndabs (scrtop))
ver = fndabs (scrtop);
if (ver > fndabs (scrbot))
ver = fndabs (scrbot);
}
MoveTo (hor * CHARWIDTH + LEFTMARGIN, (ver + 1) * LINEHEIGHT + TOPMARGIN - LINEADJ);
curcol = hor;
abslin = ver;
curlin = fndrel (ver);
} /* absmove */
/****************************************************************************/
/* dump the whole screen to the session log file */
/****************************************************************************/
scrtolog ()
{
int lin, i;
lin = toplin;
for (i = 0; i < MAXLIN; i++) {
slog (scr[lin], MAXCOL);/* write this line to session log */
lin = nxtlin[lin];
}
} /* scrtolog */
/****************************************************************************/
/*
* (UoR)
*
* Scroll lines within the scroll region upwards from line tlin
* to line blin (lines are assumed to be in the region)
*
*/
/****************************************************************************/
scroll_up (tlin, blin)
int tlin;
int blin;
{
register int i, now;
int newtop;
int abstop;
Rect r;
GrafPtr currWindow;
abstop = fndabs (tlin);
makerect (&r, abstop, 0, fndabs (blin) - abstop + 1, MAXCOL);
ObscureCursor ();
/* compensate update region for scrolling */
GetPort (&currWindow);
OffsetRgn ((WindowPeek) currWindow->updateRgn, 0, -LINEHEIGHT);
/* do the scrolling */
if (smoothscroll) {
for (i = 1; i <= LINEHEIGHT; i += 2) {
/* PWP: wait for a vertical reblank (in a sneaky way) */
now = TickCount ();
while (TickCount () == now)
/* wait... */ ;
ScrollRect (&r, 0, -2, dummyRgn);
}
} else {
ScrollRect (&r, 0, -LINEHEIGHT, dummyRgn);
}
if (tlin == blin) { /* if only one line, just clear it */
zeroline (blin);
return;
}
newtop = nxtlin[tlin]; /* new top line */
if (tlin == scrtop)
scrtop = newtop; /* reset scrtop, if needed */
if (tlin == toplin)
toplin = newtop; /* reset toplin, if needed */
else
nxtlin[fndprv (tlin)] = newtop; /* else de-link tlin line */
nxtlin[tlin] = nxtlin[blin];/* link tlin in after blin */
nxtlin[blin] = tlin;
if (blin == scrbot) { /* reset pointers to bottom of regions */
if (blin == botlin)
botlin = tlin;
scrbot = tlin;
}
if (seslog) /* if logging is active then */
slog (scr[tlin], MAXCOL); /* write line to session log */
zeroline (tlin); /* clear the line */
curlin = fndrel (abslin);
} /* scroll_up */
/****************************************************************************/
/* (UoR) Scroll lines in scroll region down from line tlin to */
/* line blin (lines are assumed to be within the scroll region) */
/****************************************************************************/
scroll_down (tlin, blin)
int tlin;
int blin;
{
int i;
int abstop;
int newbot;
Rect r;
GrafPtr currWindow;
abstop = fndabs (tlin);
makerect (&r, abstop, 0, fndabs (blin) - abstop + 1, MAXCOL);
ObscureCursor ();
/* compensate update region for scrolling */
GetPort (&currWindow);
OffsetRgn ((WindowPeek) currWindow->updateRgn, 0, LINEHEIGHT);
/* do the scrolling */
if (smoothscroll)
for (i = 1; i <= LINEHEIGHT; i += 2)
ScrollRect (&r, 0, 2, dummyRgn);
else
ScrollRect (&r, 0, LINEHEIGHT, dummyRgn);
if (tlin == blin) { /* if only one line, just clear it */
zeroline (tlin);
return;
}
newbot = fndprv (blin); /* new bottom line */
if (tlin == scrtop)
scrtop = blin; /* reset scrtop, if needed */
if (tlin == toplin)
toplin = blin; /* reset toplin, if needed */
else
nxtlin[fndprv (tlin)] = blin; /* else de-link top line */
nxtlin[newbot] = nxtlin[blin]; /* link blin above tlin */
nxtlin[blin] = tlin;
if (blin == scrbot) { /* reset bottom of region pointers */
if (blin == botlin)
botlin = newbot;
scrbot = newbot;
}
zeroline (blin);
curlin = fndrel (abslin);
} /* scroll_down */
/****************************************************************************/
/*
* Find the relative line number given the absolute one.
*
*/
/****************************************************************************/
fndrel (linum)
int linum;
{
register int i, lin;
lin = toplin;
for (i = 0; i < linum; i++)
lin = nxtlin[lin];
return (lin);
} /* fndrel */
/****************************************************************************/
/*
* Find the absolute line number given the relative one.
*
*/
/****************************************************************************/
fndabs (linum)
int linum;
{
int i, lin;
lin = toplin;
i = 0;
while (lin != linum) {
i++;
lin = nxtlin[lin];
}
return (i);
} /* fndabs */
/****************************************************************************/
/*
* Find the previous relative line number from relative line linum.
*
*/
/****************************************************************************/
fndprv (linum)
int linum;
{
int lin;
lin = toplin;
while (nxtlin[lin] != linum)
lin = nxtlin[lin];
return (lin);
} /* fndprv */
/****************************************************************************/
/* redraw the terminal screen (we got a redraw event) */
/****************************************************************************/
term_redraw ()
{
int i, lin;
Rect r;
makerect (&r, 0, 0, MAXLIN, MAXCOL); /* PWP: clear the screen first */
EraseRect (&r);
lin = toplin;
for (i = 0; i < MAXLIN; i++) {
MoveTo (LEFTMARGIN, (i + 1) * LINEHEIGHT + TOPMARGIN - LINEADJ);
DrawString (scr[lin]);
#ifdef COMMENT
if (screeninvert) { /* (UoR) refresh screen in invert mode */
makerect (&r, i, 0, 1, MAXCOL);
InvertRect (&r); /* PWP: was Erase, but that does no good */
}
#endif
lin = nxtlin[lin];
}
MoveTo (curcol * CHARWIDTH + LEFTMARGIN,
(abslin + 1) * LINEHEIGHT + TOPMARGIN - LINEADJ);
if (cur_drawn && cursor_invert) { /* (UoR) only if cursor is showing */
cursor_invert = FALSE; /* (UoR) make sure we draw it */
cursor_draw (); /* redraw cursor */
last_flash = TickCount (); /* (UoR) reset timer */
}
} /* term_redraw */
/****************************************************************************/
/* initalize the terminal emulator. */
/****************************************************************************/
init_term ()
{
int i;
for (i = 0; i < MAXLIN; i++) {
nxtlin[i] = i + 1; /* Tie together the linked list */
scr[i][MAXCOL] = '\0'; /* Terminate the lines as strings */
}
toplin = 0; /* Initialize the top and bottom ptr */
botlin = MAXLIN - 1;
scrtop = toplin; /* Scrolling region equals all */
scrbot = botlin;
nxtlin[botlin] = -1; /* Indicate this is the end */
makerect (&ScreenRect, 0, 0, MAXLIN, MAXCOL);
/* (UoR) full screen rectangle */
} /* init_term */