v16i051: Terminal emulator for NeWS window system, Part04/04
Rich Salz
rsalz at uunet.uu.net
Thu Nov 3 01:12:27 AEST 1988
Submitted-by: hoptoad!gnu (John Gilmore)
Posting-number: Volume 16, Issue 51
Archive-name: psterm/part04
: psterm part 4 of 4
: To unbundle, sh this file
echo tcap.cps
cat >tcap.cps <<'@@@ Fin de tcap.cps'
%
% This file is a product of Sun Microsystems, Inc. and is provided for
% unrestricted use provided that this legend is included on all tape
% media and as a part of the software program in whole or part.
% Users may copy, modify or distribute this file at will.
%
% THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
% WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
% PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
%
% This file is provided with no support and without any obligation on the
% part of Sun Microsystems, Inc. to assist in its use, correction,
% modification or enhancement.
%
% SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
% INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS FILE
% OR ANY PART THEREOF.
%
% In no event will Sun Microsystems, Inc. be liable for any lost revenue
% or profits or other special, indirect and consequential damages, even
% if Sun has been advised of the possibility of such damages.
%
% Sun Microsystems, Inc.
% 2550 Garcia Avenue
% Mountain View, California 94043
%
% Modifications to the original Sun Microsystems, Inc. source code
% made by the Grasshopper Group are in the Public Domain.
%
% Extensions to this file by Eric Messick of the Grasshopper Group.
%
% Grasshopper Group
% 212 Clayton St
% San Francisco, CA 94117
%
%
%
% "@(#)tcap.cps 9.5 88/01/19 SMI
% "@(#)$Header: tcap.cps,v 2.2 88/10/04 05:59:57 gnu Release $
%
% Copyright (c) 1985 by Sun Microsystems, Inc.
%/
cdef PSDefs(reload)
systemdict /LoadingPSTerm known {
createevent dup begin
/Name [/PSTimer /PSTermLoaded] def
end expressinterest
createevent dup begin
/Name /PSTimer def
/TimeStamp currenttime .5 add def
end sendevent awaitevent pop
} if pause
systemdict /PSTermDict known not reload 0 ne or {
systemdict /LoadingPSTerm true put
systemdict /PSTermDict undef
(psterm.ps) LoadFile pop
} if pause
cdef PSInitCode(string userinit)
PSTermDict /UserCodeLoaded known not {
(.pstermrc) LoadFile pop
PSTermDict /UserCodeLoaded true put
systemdict /LoadingPSTerm undef
createevent dup begin
/Name /PSTermLoaded def
/TimeStamp currenttime def
end sendevent
} if pause
userdict end PSTermDict begin begin
% PSTermDict begin dictstackexch
PSTermInit
PSTermDict userinit known { userinit cvx exec } if
cdef CreateWindow(x, y, fs, col, lines, string framelabel,
string iconlabel, string initialfont, starticonic, iconx, icony)
x y fs col lines
framelabel iconlabel initialfont starticonic iconx icony
createwindow
cdef StartInput() startinput
cdef ReInitialize() resetscale
cdef CursorUp(x,y,cstring c) c x y CU
cdef CursorDown(x,y,cstring c) c x y CD
cdef PaintUnderRev(cstring s) s UR
cdef PaintUnderNor(cstring s) s UN
cdef PaintRev(cstring s) s PR
cdef PaintNor(cstring s) s PN
cdef MoveTo(x, y) x y MT
cdef ClearToEndOfLine() CE
cdef CopyLines(yfrom, yby, w, nl) yby w yfrom nl CL
cdef BeginRepair() BRP
cdef EndRepair() ERP
cdef EndRefresh() EOR
cdef SetFrameLabel(string str) str SL
cdef SetSelContents(r, s, l, cstring str) str s l r setselcontents
cdef RingBell() VB % no audible bell as yet
cdef VisibleBell() VB
cdef SetPageMode(onoff) onoff PM
cdef SetAutoMargins(onoff) onoff AM
cdef StartHiLighting(strokeit) strokeit [
cdef HiLightLine(length) length
cdef EndHiLighting(endcol, startcol, startrow) endcol ] startcol startrow HL
cdef ClearSelectionPath() clearselectionpath
cdef RePaintHiLight() PaintHiLight
cdef StrHiLightLine(cstring s) s
cdef StrEndHiLighting(cstring ends, cstring starts,
startrow) ends ] starts startrow HL
cdef TakeDownOutline() takedownoutline
cdef StartSavingSelection() startselset
cdef SaveSelectionPiece(cstring s) s extsel
cdef FinishSavingSelection() finishselset
cdef HiLightRect(startcol, startrow, endcol, endrow, strokeit)
strokeit startcol startrow endcol endrow HiLightRect
cdef ToggleScrollBar(len) len TSB
cdef SetScrollBarValue(len, pos) len pos SSBV
cdef PopMsg(string str)
gsave framebuffer setcanvas currentcursorlocation str popmsg grestore
@@@ Fin de tcap.cps
echo tcap_ops.c
cat >tcap_ops.c <<'@@@ Fin de tcap_ops.c'
/*
* This file is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part.
* Users may copy, modify or distribute this file at will.
*
* THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* This file is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS FILE
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even
* if Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*
* Modifications to the original Sun Microsystems, Inc. source code
* made by the Grasshopper Group are in the Public Domain.
*
* Extensions to this file by Eric Messick of the Grasshopper Group.
*
* Grasshopper Group
* 212 Clayton St
* San Francisco, CA 94117
*
*/
#ifndef lint
static char sccsid[] = "@(#)tcap_ops.c 9.6 88/01/19 Copyright 1985 Sun Micro";
static char RCSid[] =
"@(#)$Header: tcap_ops.c,v 2.3 88/10/04 05:59:59 gnu Release $";
#endif
/*
* Copyright (c) 1985 by Sun Microsystems, Inc.
*/
/*-
tcap_ops.c
tcap_ops.c, Mon Mar 24 11:52:31 1986
David Rosenthal,
Sun Microsystems
*/
#include <stdio.h>
#include <sys/types.h>
#ifdef REF
#include <ref/config.h>
#endif
#include "termcap.h"
#include "tcap.h"
/*
* Termcap operations module.
*
* The external interface of this module is the array T[] and its
* number of elements Ts, plus the initialization routine:
* tc_init_ops()
*/
#include "screen.h"
extern int CharsPerLine;
extern int LinesPerScreen;
extern struct pair Dot;
extern struct tcap T[];
extern int Ts;
extern char *malloc();
#ifndef bcopy
extern void bcopy();
#endif
#ifndef bzero
extern void bzero();
#endif
extern char *strncpy();
static struct tcap *tc_lookup();
static u_short TopLineOfScrollRegion, BottomLineOfScrollRegion;
static struct pair SavedCursor;
static u_short ScrollNLKludge = 0;
struct tcap *CheckCR = 0;
struct tcap *CheckNL = 0;
struct tcap *CheckBS = 0;
struct tcap *CheckTAB = 0;
static unsigned int PermanentModes = 0, TemporaryModes = 0;
static char *FrameLabel;
static u_short FLindex;
static int (*prevInput)();
struct tcap interruptedOp = { 0 };
struct line *lastInputLine;
int PageFull = 0;
static int PrevPageMode = -1;
extern int PageMode;
extern int userLinesPerScreen;
extern int userCharsPerLine;
static int al_op(), clear_body(), ce_op(), cm_in(), cs_op();
static int dc_op(), dl_op(), ic_op(), nl_op(), sf_op();
tc_init_ops()
{
struct tcap *me, *tc;
if (userLinesPerScreen > 0)
LinesPerScreen = userLinesPerScreen;
if (userCharsPerLine > 0)
CharsPerLine = userCharsPerLine;
Dot.x = 0 ;
Dot.y = LinesPerScreen - 1 ;
TopLineOfScrollRegion = 0;
BottomLineOfScrollRegion = LinesPerScreen - 1;
FrameLabel = malloc((unsigned)CharsPerLine+1);
/*
* Beware of termcap entries that define ue and/or se identical
* to me (turn off ALL attributes). Since we just pattern
* match, it's likely we won't get me_op in normal operation,
* so force the entries here. (known for vt100)
*/
me = tc_lookup("me");
if (me) {
tc = tc_lookup("ue");
if (tc && tc->t_size == me->t_size &&
bcmp(me->t_text, tc->t_text, (int)tc->t_size) == 0)
tc->t_op = me->t_op;
tc = tc_lookup("se");
if (tc && tc->t_size == me->t_size &&
bcmp(me->t_text, tc->t_text, (int)tc->t_size) == 0)
tc->t_op = me->t_op;
}
/*
* Check for sf == \n, if so we must kludge things so that
* sf_op will call nl_op as needed (exists on bitgraph).
*/
tc = tc_lookup("sf");
if (tc && tc->t_size == 1 && tc->t_text[0] == '\n')
ScrollNLKludge = 1;
/*
* To minimize the number of times the regular text processing
* is stopped to invoke the pattern matcher we check the most
* strings CR, NL, BS, and TAB to see if they are \r, \n, \b,,
* and \t, respectively. If any are, a quick check on the character
* is made before the pattern matching machinery is invoked.
*/
tc = tc_lookup("cr");
if (tc && tc->t_size == 1 && tc->t_text[0] == '\r')
CheckCR = tc;
tc = tc_lookup("nl");
if (tc && tc->t_size == 1 && tc->t_text[0] == '\n')
CheckNL = tc;
tc = tc_lookup("bc");
if (tc && tc->t_size == 1 && tc->t_text[0] == '\b')
CheckBS = tc;
tc = tc_lookup("ta");
if (tc && tc->t_size == 1 && tc->t_text[0] == '\t')
CheckTAB = tc;
}
tc_initmodemenu()
{
/*
* Insure menu items properly reflect initial settings.
*/
SetPageMode(PageMode);
SetAutoMargins(PermanentModes & AutoMarginMode);
}
static struct tcap *
tc_lookup(key)
char *key;
{
register struct tcap *tp;
for (tp = T; *tp->t_key; tp++)
if (strcmp(tp->t_key, key) == 0)
return (tp);
return ((struct tcap *)0);
}
/*
* scrollreset is called whenever keyboard input is seen, in order to
* do deferred scrolling and remember the last line on which the user
* typed something.
*/
scrollreset(l)
int l;
{
int n = PageFull;
PageFull = 0;
lastInputLine = (l == 1) ? screen[1] : 0;
while (n-- > 0 && !PageFull)
sf_op((struct tcap *) 0);
if (lastInputLine == 0)
lastInputLine = screen[Dot.y];
}
toggleautomargins()
{
PermanentModes ^= (unsigned int) AutoMarginMode;
SetAutoMargins(PermanentModes & AutoMarginMode);
FlushPostScript();
}
togglepagemode()
{
SetPageMode(PageMode = !PageMode);
FlushPostScript();
}
resetscreensize(row, col)
int row, col;
{
struct tcap t;
int dotx, doty;
dotx = Dot.x ;
if (dotx >= col) dotx = col - 1;
doty = Dot.y - LinesPerScreen + row ;
if (doty >= row) doty = row - 1;
if (doty < 0) doty = 0 ;
if (PageMode) {
/* no scroll stop line */
lastInputLine = screen[doty - row + LinesPerScreen];
}
CharsPerLine = col ;
LinesPerScreen = row ;
t.t_x = LinesPerScreen - 1 ;
t.t_y = 0 ;
cs_op(&t); /* change scrolling region to full screen */
/* if it wasn't full screen before, then it's the
* program's responsibility to change it after
* getting the sigwinch
* note that this trashes Dot, so we save it.
*/
Dot.x = dotx ;
Dot.y = doty ;
}
#ifdef notdef
static
trace(s, t)
register char *s;
register struct tcap *t;
{
register char *q = t->t_text;
fprintf(stderr, "%s: ", s);
fprintf(stderr, "[%s,", t->t_key);
if (q == NULL)
fprintf(stderr, "(nil)");
else while (*q) {
if (*q < ' ') {
fprintf(stderr, "^%c", *q + '@');
} else {
fprintf(stderr, "%c", *q);
}
q++;
}
fprintf(stderr, ",%d,(%d,%d)]\n", t->t_index, t->t_x, t->t_y);
}
#endif
#ifndef notdef
#define trace(X, Y) (void)(X, Y)
#endif
#define ChangeScreen()
#define MoveCursor()
#ifdef notdef
static
PrintScreen()
{
register int y;
for (y = 0; y < LinesPerScreen; y++) {
register struct line *l = screen[y];
register int x;
if (l == NULL)
fprintf(stderr, "(nil)");
else for (x = 0; x < l->length; x++) {
if (x == Dot.x && y == Dot.y)
fprintf(stderr, "+");
else if (x == l->changeposition)
fprintf(stderr, "|");
else
fprintf(stderr, "%c", (l->body[x] == ' ' ? '.' : l->body[x]));
}
fprintf(stderr, "\n");
}
fprintf(stderr, "\n");
}
#endif
showc(t)
struct tcap *t;
{
register char *cp = t->t_text;
register struct line *l;
register int dotx, c;
register unsigned Modes = PermanentModes | TemporaryModes;
int n = t->t_size;
register char *bp;
register u_char *pp;
trace("==", t);
TemporaryModes = 0;
dotx = Dot.x;
while (n > 0 && !PageFull) {
l = screen[Dot.y];
if (l->changeposition > dotx)
l->changeposition = dotx;
if (l->length < dotx)
l->length = dotx;
bp = &l->body[dotx] ;
pp = &l->prop[dotx] ;
if (Modes & InsertMode && l->length > dotx) {
n-- ;
c = *cp++;
if (c < ' ' || c >= 0177)
continue;
if (l->length < CharsPerLine)
l->length++;
bcopy((char *)pp, (char *)pp+1,(int)(l->length-dotx-1));
bcopy( bp, bp+1,(int)(l->length-dotx-1));
l->end_of_changes = CharsPerLine + 1 ;
*bp = c;
*pp = (Modes & Attributes);
if (++dotx >= CharsPerLine) {
if (Modes & AutoMarginMode) {
trace("cr", t);
l->end_of_changes = CharsPerLine + 1 ;
l->flags |= LINE_WRAPPED ;
if (l->length < dotx)
l->length = dotx ;
dotx = 0;
MoveCursor();
nl_op(t);
TemporaryModes |= WrapJustHappenedMode;
}
else dotx = CharsPerLine - 1;
}
}
else {
while (n-- > 0 && !PageFull) {
c = *cp++;
if (c < ' ' || c >= 0177)
continue;
*bp++ = c;
*pp++ = (Modes & Attributes);
if (++dotx >= CharsPerLine) {
if (Modes & AutoMarginMode) {
trace("cr", t);
l->end_of_changes =
CharsPerLine + 1 ;
l->flags |= LINE_WRAPPED ;
if (l->length < dotx)
l->length = dotx ;
dotx = 0;
MoveCursor();
nl_op(t);
TemporaryModes |=
WrapJustHappenedMode;
break;
}
else dotx = CharsPerLine - 1;
}
}
}
if (l->length < dotx)
l->length = dotx ;
if (l->end_of_changes < dotx)
l->end_of_changes = dotx;
}
Dot.x = dotx;
ChangeScreen();
/*
* If we were interrupted by nl_op setting PageFull, set up
* interruptedOp with a tcap that can be used to finish this later.
*/
if (PageFull && ++n > 0) {
interruptedOp = *t;
interruptedOp.t_text += (t->t_size - n);
interruptedOp.t_size = n;
}
else interruptedOp.t_op = 0;
}
static int
AL_op(t) /* add multiple blank lines */
struct tcap *t;
{
trace("AL", t);
/* cheat for now */
while (t->t_y-- > 0)
al_op(t);
ChangeScreen();
}
static int
DC_op(t)
struct tcap *t;
{
trace("DC", t);
/* cheat for now */
while (t->t_y-- > 0)
dc_op(t);
ChangeScreen();
}
static int
DL_op(t) /* delete multiple lines */
struct tcap *t;
{
trace("DL", t);
/* cheat for now */
while (t->t_y-- > 0)
dl_op(t);
ChangeScreen();
}
static int
DO_in(t) /* move cursor down n lines */
struct tcap *t;
{
trace("DO", t);
return (cm_in(t)); /* Neat! It might even work */
}
static int
DO_op(t) /* move cursor down n lines */
register struct tcap *t;
{
trace("DO", t);
if (t->t_y >= 0 && (Dot.y + t->t_y) < LinesPerScreen)
Dot.y += t->t_y;
MoveCursor();
}
static int
IC_op(t)
struct tcap *t;
{
trace("IC", t);
/* cheat for now */
while (t->t_y-- > 0)
ic_op(t);
ChangeScreen();
}
static int
LE_in(t) /* move cursor left n characters */
struct tcap *t;
{
trace("LE", t);
return (cm_in(t)); /* Neat! It might even work */
}
static int
LE_op(t) /* move cursor left n characters */
register struct tcap *t;
{
trace("LE", t);
if ((Dot.x - t->t_y) >= 0)
Dot.x -= t->t_y;
MoveCursor();
}
static int
RI_in(t) /* move cursor right n characters */
struct tcap *t;
{
trace("RI", t);
return (cm_in(t)); /* Neat! It might even work */
}
static int
RI_op(t) /* move cursor right n characters */
register struct tcap *t;
{
trace("RI", t);
if (t->t_y >= 0 && (Dot.x + t->t_y) <= CharsPerLine)
Dot.x += t->t_y;
MoveCursor();
}
static int
UP_in(t) /* move cursor up n lines */
struct tcap *t;
{
trace("UP", t);
return (cm_in(t)); /* Neat! It might even work */
}
static int
UP_op(t) /* move cursor up n lines */
register struct tcap *t;
{
trace("UP", t);
if ((Dot.y - t->t_y) >= 0)
Dot.y -= t->t_y;
MoveCursor();
}
static int
al_op(t) /* Add new blank line */
struct tcap *t;
{
register struct line **p, **current;
register struct line *old;
trace("al", t);
current = &screen[Dot.y];
p = &screen[BottomLineOfScrollRegion];
old = *p;
for (; p > current; p--)
*p = *(p-1);
*p = old;
clear_body(old, 0);
old->length = 0;
old->changeposition = 0;
old->end_of_changes = CharsPerLine;
old->usedtobe = LinesPerScreen;
ChangeScreen();
}
static int
am_in(t) /* Has auto-margins */
struct tcap *t;
{
trace("am", t);
if (t->t_x) PermanentModes |= AutoMarginMode;
return (0);
}
static int
bc_op(t) /* back-character */
struct tcap *t;
{
trace("bc", t);
if (Dot.x > 0)
Dot.x--;
MoveCursor();
}
static int
bl_op(t) /* Bell character */
struct tcap *t;
{
trace("bl", t);
RingBell();
}
/*
* Clearing the whole line body for the clear ops may be excessive
* but nothing short of it seems to work for programs which do a lot
* of cursor manipulation, such as rogue or hack.
*/
static int
clear_body(l, x)
struct line *l;
int x;
{
register int len = l->buffer_length - x;
register char *cp;
bzero((char *)&l->prop[x], len);
l->flags = 0 ;
for (cp = &l->body[x]; len-- > 0;)
*cp++ = ' ';
}
static int
cd_op(t) /* Clear to end of display */
struct tcap *t;
{
register struct line **p, **last;
register struct line *l;
trace("cd", t);
ce_op(t);
last = &screen[LinesPerScreen];
for (p = &screen[Dot.y+1]; p < last; p++) {
(l = *p)->length = 0;
l->changeposition = 0;
l->end_of_changes = CharsPerLine ;
clear_body(l, 0);
}
ChangeScreen();
}
static int
ce_op(t) /* Clear to end of line */
struct tcap *t;
{
register struct line *l = screen[Dot.y];
trace("ce", t);
l->length = Dot.x;
if (l->changeposition > Dot.x)
l->changeposition = Dot.x;
l->end_of_changes = CharsPerLine ;
clear_body(l, (int)l->length);
ChangeScreen();
}
static int
cl_op(t) /* Clear screen */
struct tcap *t;
{
register struct line **p, **last;
register struct line *l;
trace("cl", t);
Dot.x = Dot.y = 0;
last = &screen[LinesPerScreen];
for (p = &screen[0]; p < last; p++) {
(l = *p)->length = 0;
l->changeposition = 0;
l->end_of_changes = CharsPerLine ;
clear_body(l, 0);
}
ChangeScreen();
if (PageMode)
lastInputLine = screen[Dot.y]; /* no scroll stop line */
}
#ifdef HAVE_TERMCAP
static int
cm_in(t) /* Cursor motion */
register struct tcap *t;
{
register u_char c;
char buf[128];
register char *cp = t->t_text, *bp = buf;
trace("cm", t);
if (cp == NULL)
return(0);
/* Pre-process out parts of the % escapes */
while ((c = *cp++) != '\0') {
if (c == '%') {
register u_char c2 = *cp++;
switch (c2) {
case '+': /* Subtract next then %. */
switch (t->t_2nd + t->t_pc_r) {
case 0:
case 2:
t->t_yi = *cp++;
break;
case 1:
t->t_xi = *cp++;
break;
}
c2 = '.';
goto percent_dot;
case '>':
switch (t->t_2nd + t->t_pc_r) {
case 1:
t->t_xilim = *cp++;
t->t_xi = *cp++;
t->t_xilim += t->t_xi + 1;
break;
case 0:
case 2:
t->t_yilim = *cp++;
t->t_yi = *cp++;
t->t_yilim += t->t_yi + 1;
break;
}
t->t_2nd = !t->t_2nd;
break;
case 'r':
t->t_pc_r = 1;
break;
case 'i':
t->t_xi++;
t->t_yi++;
break;
case 'n':
t->t_pc_n = 1;
break;
case 'B':
t->t_pc_B = 1;
break;
case 'D':
t->t_pc_D = 1;
break;
/* The following ones will be interpreted on the fly */
case 'd': /* series of decimal digits */
case '2': /* two decimal digits */
case '3': /* three decimal digits */
case '.': /* binary character */
percent_dot:
case '%':
*bp++ = c;
*bp++ = c2;
t->t_2nd = !t->t_2nd;
break;
default: /* Bad % escape */
return (1);
}
}
else {
*bp++ = c;
}
}
*bp++ = '\0';
if (bp-buf > 1) {
if ((t->t_text = malloc((unsigned)(bp-buf+1))) == NULL)
return (2);
strncpy(t->t_text, buf, bp-buf);
t->t_size = bp-buf - 1;
} else {
t->t_text = NULL;
}
t->t_2nd = 0;
return (0);
}
#else /* !HAVE_TERMCAP */
static int
cm_in(t) /* Cursor motion */
register struct tcap *t;
{
register u_char c;
char buf[128];
register char *cp = t->t_text, *bp = buf;
trace("cm", t);
if (cp == NULL)
return(0);
/* Pre-process out parts of the % escapes */
while ((c = *cp++) != '\0') {
static int seen1 = 0;
if (c == '%') {
register u_char c2 = *cp++;
switch (c2) {
case 'p':
switch (*cp++) {
case '1':
seen1++;
t->t_2nd = 0;
break;
case '2':
if (!seen1)
t->t_pc_r = 1;
t->t_2nd = 1;
break;
/*
* This capability is not available in termcap so we will
* assume that it is not present in terminfo either. This
* means that terminal that send more than two pieces of
* variable data with the "cm" directive will not work.
* Currently for "cm" only two variables are defined.
*/
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
return(1);
}
break;
case '\'': /* store constant for future operator */
switch (t->t_2nd + t->t_pc_r) {
case 0:
case 2:
t->t_yi = *cp++;
break;
case 1:
t->t_xi = *cp++;
break;
}
if (*cp == '\'')
cp++; /* blow past the trailing '\'' */
else
return(1);
break;
case '{': /* store decimal constant for future operator */
switch (t->t_2nd + t->t_pc_r) {
case 0:
case 2:
t->t_yi = ((*cp++) * 10) + (*cp++);
break;
case 1:
t->t_xi = ((*cp++) * 10) + (*cp++);
break;
}
if (*cp == '}')
cp++; /* blow past trailing '}' */
else
return(1);
break;
/* the following will not work do to the simplifications here */
case '?': /* if */
case 't': /* then */
case 'e': /* else */
return(1); /* lets not delude ourselves, the data
* structures were set up to deal with termcap
* not the complexities of terminfo.
*/
case 'i':
t->t_xi++;
t->t_yi++;
break;
case '+':
if (*cp++ != '%')
return(1);
if (*cp++ != 'c')
return(1);
*bp++ = '%'; /* make it look like termcap */
*bp++ = '.';
break;
/* use the simpified model of termcap so some of this
* stuff is not valid
*/
case '\b': /* flags in format string */
case ':': /* needed for '-' and '+' flags */
case '#': /* flags in format string */
case '.': /* if only fract part of precision */
return(1);
/* just leave a 'd' */
case '0': /* numeric part of precision */
case '1': /* numeric part of precision */
case '4': /* numeric part of precision */
case '5': /* numeric part of precision */
case '6': /* numeric part of precision */
case '7': /* numeric part of precision */
case '8': /* numeric part of precision */
case '9': /* numeric part of precision */
/* skip past the end of this definition, leave %d in its place*/
while (*cp != 'd' && *cp != 'o' && *cp != 'x'
&& *cp != 'X' && *cp != 's')
cp++;
/* don't support anything but 'd' */
if (*cp != 'd')
return(1);
*bp++ = c; /* '%' */
*bp++ = *cp++; /* 'd' */
/* The following ones will be interpreted on the fly. */
case '2': /* numeric part of precision */
case '3': /* numeric part of precision */
/* remove %[23]->[doxXs], put %[23] in bp */
*bp++ = c;
*bp++ = c2;
/* skip any factional part of the precision */
while (*cp != 'd' && *cp != 'o' && *cp != 'x'
&& *cp != 'X' && *cp != 's')
cp++;
/* don't support anything but 'd' */
if (*cp != 'd')
return(1);
*cp++; /* get rid of the 'd' */
break;
/* not suported by termcap, so not supported here */
case 'o': /* octal: no other formating is present */
case 'x': /* hex: no other formating is present */
case 'X': /* HEX: no other formating is present */
case 's': /* String: no other formating is present */
case 'c': /* binary character */
case 'l': /* strlen() operator */
case '=': /* equal operator */
case '>': /* greater than operator */
case '<': /* less than operator */
case '-': /* subtract operator */
case '*': /* multiply operator */
case '/': /* divide operator */
case 'm': /* modula operator */
case '&': /* bitwise and operator */
case '|': /* bitwise or operator */
case '^': /* bitwise xor operator */
case '~': /* bitwise not operator */
case 'A': /* logical and operator */
case 'O': /* logical or operator */
case '!': /* logical not operator */
return(1);
/* include the string "%A" where A = one of the following cases */
case 'd': /* decimal: no other formating is present */
case '%':
*bp++ = c;
*bp++ = c2;
break;
default: /* Bad % escape */
return (1);
}
}
else {
*bp++ = c;
}
}
*bp++ = '\0';
if (bp-buf > 1) {
if ((t->t_text = malloc(bp-buf+1)) == NULL)
return (2);
strncpy(t->t_text, buf, bp-buf);
t->t_size = bp-buf - 1;
} else {
t->t_text = NULL;
}
t->t_2nd = 0;
return (0);
}
#endif /* !HAVE_TERMCAP */
static int
cm_op(t) /* Cursor motion */
register struct tcap *t;
{
trace("cm", t);
lastInputLine = 0; /* no scroll stop line */
if (t->t_x >= 0 && t->t_x < CharsPerLine)
Dot.x = t->t_x;
if (t->t_y >= 0 && t->t_y < LinesPerScreen)
Dot.y = t->t_y;
MoveCursor();
}
static int
co_in(t) /* number of columns */
struct tcap *t;
{
trace("co", t);
if (userCharsPerLine < 1)
CharsPerLine = t->t_x;
return (0);
}
static int
cr_op(t) /* carriage return */
struct tcap *t;
{
trace("cr", t);
Dot.x = 0;
MoveCursor();
}
static int
cs_in(t) /* change scroll region */
struct tcap *t;
{
trace("cs", t);
return (cm_in(t)); /* Neat! It might even work */
}
static int
cs_op(t) /* change scroll region */
register struct tcap *t;
{
trace("cs", t);
if (t->t_y >= t->t_x || t->t_x >= LinesPerScreen)
return;
Dot.x = 0;
Dot.y = t->t_y;
TopLineOfScrollRegion = t->t_y;
BottomLineOfScrollRegion = t->t_x;
lastInputLine = 0; /* no scroll stop line */
MoveCursor();
}
static int
dc_op(t) /* delete character */
struct tcap *t;
{
register struct line *l = screen[Dot.y];
register int dotx = Dot.x;
int len;
trace("dc", t);
if (l->changeposition > dotx)
l->changeposition = dotx;
if (dotx < l->length) {
l->length--;
len = l->length - dotx;
bcopy((char *)&l->prop[dotx+1], (char *)&l->prop[dotx], len);
l->prop[l->length] = 0 ;
bcopy(&l->body[dotx+1], &l->body[dotx], len);
l->body[l->length] = ' ' ;
}
l->end_of_changes = CharsPerLine ;
ChangeScreen();
}
static int
dl_op(t) /* delete line */
struct tcap *t;
{
register struct line **p, **bottom;
register struct line *old = screen[Dot.y];
trace("dl", t);
lastInputLine = 0; /* no scroll stop line */
bottom = &screen[BottomLineOfScrollRegion];
for (p = &screen[Dot.y]; p < bottom; p++)
*p = *(p+1);
*p = old;
clear_body(old, 0);
old->length = 0;
old->changeposition = 0;
old->end_of_changes = CharsPerLine ;
old->usedtobe = LinesPerScreen ;
ChangeScreen();
}
static int
do_op(t) /* down one line */
struct tcap *t;
{
trace("do", t);
if (PermanentModes & IgnoreNewlineAfterWrapMode) {
if (TemporaryModes & WrapJustHappenedMode) {
TemporaryModes &= ~WrapJustHappenedMode;
return;
}
}
if (Dot.y < LinesPerScreen - 1)
Dot.y++;
else {
sf_op(t);
}
MoveCursor();
}
static int
ei_op(t) /* end insert mode */
struct tcap *t;
{
trace("ei", t);
PermanentModes &= ~InsertMode;
}
static int
el_op(t) /* end frame label definition mode */
struct tcap *t;
{
if (FrameLabel) {
FrameLabel[FLindex] = '\0';
SetFrameLabel(FrameLabel);
}
t = T+Ts;
t->t_op = prevInput;
}
static int
ke_op(t) /* leave keyboard transmit mode */
struct tcap *t;
{
trace("ke", t);
}
static int
ks_op(t) /* enter keyboard transmit mode */
struct tcap *t;
{
trace("ks", t);
}
static int
ho_op(t) /* home cursor */
struct tcap *t;
{
trace("ho", t);
lastInputLine = 0; /* no scroll stop line */
Dot.x = Dot.y = 0;
MoveCursor();
}
static int
ic_op(t) /* insert character */
struct tcap *t;
{
trace("ic", t);
TemporaryModes |= InsertMode;
}
static int
im_op(t) /* enter insert mode */
struct tcap *t;
{
trace("im", t);
PermanentModes |= InsertMode;
}
static int
le_op(t) /* cursor left */
struct tcap *t;
{
trace("le", t);
if (Dot.x > 0)
Dot.x--;
MoveCursor();
}
static int
li_in(t) /* number of lines */
struct tcap *t;
{
trace("li", t);
if (userLinesPerScreen < 1)
LinesPerScreen = t->t_x;
return (0);
}
static int
ll_op(t) /* last line first column */
struct tcap *t;
{
trace("ll", t);
Dot.x = 0;
Dot.y = LinesPerScreen - 1;
MoveCursor();
}
static int
lm_op(t) /* label mode input */
register struct tcap *t;
{
trace("lm", t);
if (FLindex + t->t_size >= CharsPerLine)
t->t_size = CharsPerLine - FLindex;
if (t->t_size > 0) {
if (FrameLabel)
strncpy(&FrameLabel[FLindex], t->t_text, (int)t->t_size);
FLindex += t->t_size;
}
}
static int
mb_op(t) /* enable blink */
struct tcap *t;
{
trace("mb", t);
PermanentModes |= BlinkMode;
}
static int
md_op(t) /* enter bold mode */
struct tcap *t;
{
trace("md", t);
PermanentModes |= BoldMode;
}
static int
me_op(t) /* turn off attributes */
struct tcap *t;
{
trace("me", t);
PermanentModes &= ~(Attributes);
}
static int
mr_op(t) /* enter reverse video */
struct tcap *t;
{
trace("mr", t);
PermanentModes |= ReverseVideoMode;
}
static int
nd_op(t) /* cursor right */
struct tcap *t;
{
trace("nd", t);
if (Dot.x < (CharsPerLine - 1))
Dot.x++;
MoveCursor();
}
static int
nl_op(t) /* newline */
struct tcap *t;
{
trace("nl", t);
if (PermanentModes & IgnoreNewlineAfterWrapMode) {
if (TemporaryModes & WrapJustHappenedMode) {
TemporaryModes &= ~WrapJustHappenedMode;
return;
}
}
if (Dot.y < LinesPerScreen - 1)
Dot.y++;
else {
sf_op(t);
}
MoveCursor();
}
static int
rc_op(t) /* restore cursor */
struct tcap *t;
{
trace("rc", t);
Dot = SavedCursor;
MoveCursor();
}
static int
sc_op(t) /* save cursor */
struct tcap *t;
{
trace("sc", t);
SavedCursor = Dot;
MoveCursor();
}
static int
se_op(t) /* leave stand-out */
struct tcap *t;
{
trace("se", t);
PermanentModes &= ~StandOutMode;
}
static int
so_op(t) /* enter stand-out */
struct tcap *t;
{
trace("so", t);
PermanentModes |= StandOutMode;
}
static int
sf_op(t) /* scroll forwards */
struct tcap *t;
{
register struct line **p, **bottom;
register struct line *old;
static int SFrecur = 0;
trace("sf", t);
/*
* When sf is "\n", nl_op won't be called, so we emulate
* it's actions here (beware of recursion).
*/
if (ScrollNLKludge && !SFrecur) {
SFrecur++; nl_op(t); SFrecur--;
return (1); /* XXX */
}
p = &screen[TopLineOfScrollRegion];
if (PageMode && *p == lastInputLine) {
PageFull++; /* can't scroll this line */
return (0);
}
ScrollSaveLine(*p);
bottom = &screen[BottomLineOfScrollRegion];
p = &screen[TopLineOfScrollRegion];
old = *p;
for (; p < bottom; p++)
*p = *(p+1);
*p = old;
clear_body(old, 0);
old->length = 0;
old->changeposition = 0;
old->end_of_changes = CharsPerLine ;
old->usedtobe = LinesPerScreen;
ChangeScreen();
return (1);
}
static int
sl_op(t) /* start defining new frame label */
register struct tcap *t;
{
trace("sl", t);
FLindex = 0;
t = T+Ts;
prevInput = t->t_op;
t->t_op = lm_op;
}
static int
sr_op(t) /* scroll reverse */
struct tcap *t;
{
register struct line **p, **top;
register struct line *old;
trace("sr", t);
lastInputLine = 0; /* no scroll stop line */
top = &screen[TopLineOfScrollRegion];
p = &screen[BottomLineOfScrollRegion];
old = *p;
for (; p > top; p--)
*p = *(p-1);
*p = old;
clear_body(old, 0);
old->length = 0;
old->changeposition = 0;
old->end_of_changes = CharsPerLine ;
old->usedtobe = LinesPerScreen;
ChangeScreen();
}
static int
ta_op(t) /* tab */
struct tcap *t;
{
trace("ta", t);
Dot.x = (Dot.x & ~07) + 010;
if (Dot.x >= CharsPerLine - 1)
Dot.x = CharsPerLine - 1;
MoveCursor();
}
static int
te_op(t) /* end use of termcap */
struct tcap *t;
{
trace("te", t);
if (PrevPageMode != -1) {
PageMode = PrevPageMode;
PrevPageMode = -1;
}
}
static int
ti_op(t) /* begin use of termcap */
{
trace("ti", t);
/*
* Turn off page mode when using termcap.
*/
if (PrevPageMode == -1) {
PrevPageMode = PageMode;
PageMode = 0;
}
}
static int
ue_op(t) /* end underline */
struct tcap *t;
{
trace("ue", t);
PermanentModes &= ~UnderlineMode;
}
static int
up_op(t) /* cursor up */
struct tcap *t;
{
trace("up", t);
if (Dot.y > 0)
Dot.y--;
else /* vi will never do this, but some ll caps may */
Dot.y = LinesPerScreen - 1;
MoveCursor();
}
static int
us_op(t) /* start underline */
struct tcap *t;
{
trace("us", t);
PermanentModes |= UnderlineMode;
}
static int
vb_op(t) /* visibile bell */
struct tcap *t;
{
trace("bl", t);
VisibleBell();
}
static int
xn_in(t)
struct tcap *t;
{
trace("xn", t);
if (t->t_x) PermanentModes |= IgnoreNewlineAfterWrapMode;
return (0);
}
/* These capabilities are numeric or boolean - they dont have ops */
#define am_op NULL
#define bs_op NULL
#define co_op NULL
#define li_op NULL
#define pc_op NULL
#define xn_op NULL
/* These capabilities are strings that dont need initialization */
#define al_in NULL
#define bc_in NULL
#define bl_in NULL
#define cd_in NULL
#define ce_in NULL
#define cl_in NULL
#define cr_in NULL
#define dc_in NULL
#define dl_in NULL
#define do_in NULL
#define ei_in NULL
#define ke_in NULL
#define ks_in NULL
#define ho_in NULL
#define ic_in NULL
#define im_in NULL
#define le_in NULL
#define ll_in NULL
#define mb_in NULL
#define md_in NULL
#define me_in NULL
#define mr_in NULL
#define nd_in NULL
#define nl_in NULL
#define pc_in NULL
#define rc_in NULL
#define sc_in NULL
#define se_in NULL
#define sf_in NULL
#define so_in NULL
#define sr_in NULL
#define ta_in NULL
#define ue_in NULL
#define up_in NULL
#define us_in NULL
#define s string
#define n num
#define b bool
struct tcap T[] = {
/*
* key ty op in text deftx sz in tmp tf
* x xi xl y yi yl r n B D 2
*/
{"AL", s, AL_op, cs_in, NULL, NULL, 0, 0, NULL, 0},
{"DL", s, DL_op, cs_in, NULL, NULL, 0, 0, NULL, 0},
{"DC", s, DC_op, cs_in, NULL, NULL, 0, 0, NULL, 0},
{"DO", s, DO_op, DO_in, NULL, NULL, 0, 0, NULL, 0},
{"IC", s, IC_op, cs_in, NULL, NULL, 0, 0, NULL, 0},
{"LE", s, LE_op, LE_in, NULL, NULL, 0, 0, NULL, 0},
{"RI", s, RI_op, RI_in, NULL, NULL, 0, 0, NULL, 0},
{"UP", s, UP_op, UP_in, NULL, NULL, 0, 0, NULL, 0},
{"al", s, al_op, al_in, NULL, NULL, 0, 0, NULL, 0},
{"am", b, am_op, am_in, NULL, NULL, 0, 0, NULL, 0},
{"bc", s, bc_op, bc_in, NULL, "\10", 0, 0, NULL, 0},
{"bl", s, bl_op, bl_in, NULL, "\7", 0, 0, NULL, 0},
{"cd", s, cd_op, cd_in, NULL, NULL, 0, 0, NULL, 0},
{"ce", s, ce_op, ce_in, NULL, NULL, 0, 0, NULL, 0},
{"cl", s, cl_op, cl_in, NULL, NULL, 0, 0, NULL, 0},
{"cm", s, cm_op, cm_in, NULL, NULL, 0, 0, NULL, 0},
{"co", n, co_op, co_in, NULL, NULL, 0, 0, NULL, 0},
{"cr", s, cr_op, cr_in, NULL, "\015", 0, 0, NULL, 0},
{"cs", s, cs_op, cs_in, NULL, NULL, 0, 0, NULL, 0},
{"dc", s, dc_op, dc_in, NULL, NULL, 0, 0, NULL, 0},
{"dl", s, dl_op, dl_in, NULL, NULL, 0, 0, NULL, 0},
{"do", s, do_op, do_in, NULL, NULL, 0, 0, NULL, 0},
{"ei", s, ei_op, ei_in, NULL, NULL, 0, 0, NULL, 0},
{"el", s, el_op, NULL, NULL,"\033\\",0, 0, NULL, 0}, /* end label */
{"ke", s, ke_op, ke_in, NULL, NULL, 0, 0, NULL, 0},
{"ks", s, ks_op, ks_in, NULL, NULL, 0, 0, NULL, 0},
{"ho", s, ho_op, ho_in, NULL, NULL, 0, 0, NULL, 0},
{"ic", s, ic_op, ic_in, NULL, NULL, 0, 0, NULL, 0},
{"im", s, im_op, im_in, NULL, NULL, 0, 0, NULL, 0},
{"le", s, le_op, le_in, NULL, NULL, 0, 0, NULL, 0},
{"li", n, li_op, li_in, NULL, NULL, 0, 0, NULL, 0},
{"ll", s, ll_op, ll_in, NULL, NULL, 0, 0, NULL, 0},
{"lm", s, lm_op, NULL, NULL, NULL, 0, 0, NULL, 0}, /* label mode input */
{"mb", s, mb_op, mb_in, NULL, NULL, 0, 0, NULL, 0},
{"md", s, md_op, md_in, NULL, NULL, 0, 0, NULL, 0},
{"me", s, me_op, me_in, NULL, NULL, 0, 0, NULL, 0},
{"mr", s, mr_op, mr_in, NULL, NULL, 0, 0, NULL, 0},
{"nd", s, nd_op, nd_in, NULL, NULL, 0, 0, NULL, 0},
{"nl", s, nl_op, nl_in, NULL, "\012", 0, 0, NULL, 0},
{"pc", s, pc_op, pc_in, NULL, "\200", 0, 0, NULL, 0},
{"rc", s, rc_op, rc_in, NULL, NULL, 0, 0, NULL, 0},
{"sc", s, sc_op, sc_in, NULL, NULL, 0, 0, NULL, 0},
{"se", s, se_op, se_in, NULL, NULL, 0, 0, NULL, 0},
{"sf", s, sf_op, sf_in, NULL, NULL, 0, 0, NULL, 0},
{"sl", s, sl_op, NULL, NULL,"\033]l",0, 0, NULL, 0}, /* start label */
{"so", s, so_op, so_in, NULL, NULL, 0, 0, NULL, 0},
{"sr", s, sr_op, sr_in, NULL, NULL, 0, 0, NULL, 0},
{"ta", s, ta_op, ta_in, NULL, "\011", 0, 0, NULL, 0}, /* XXX */
{"te", s, te_op, NULL, NULL, NULL, 0, 0, NULL, 0},
{"ti", s, ti_op, NULL, NULL, NULL, 0, 0, NULL, 0},
{"ue", s, ue_op, ue_in, NULL, NULL, 0, 0, NULL, 0},
{"up", s, up_op, up_in, NULL, NULL, 0, 0, NULL, 0},
{"us", s, us_op, us_in, NULL, NULL, 0, 0, NULL, 0},
{"vb", s, vb_op, NULL, NULL, NULL, 0, 0, NULL, 0},
{"xn", b, xn_op, xn_in, NULL, NULL, 0, 0, NULL, 0},
{"", s, showc, NULL, NULL, NULL, 0, 0, NULL, 0},
};
/* T[Ts] is a special case - its the display-character operation */
int Ts = (sizeof T)/(sizeof T[0]) - 1;
@@@ Fin de tcap_ops.c
echo tcap_parse.c
cat >tcap_parse.c <<'@@@ Fin de tcap_parse.c'
/*
* This file is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part.
* Users may copy, modify or distribute this file at will.
*
* THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* This file is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS FILE
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even
* if Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*
* Modifications to the original Sun Microsystems, Inc. source code
* made by the Grasshopper Group are in the Public Domain.
*
* Extensions to this file by Eric Messick of the Grasshopper Group.
*
* Grasshopper Group
* 212 Clayton St
* San Francisco, CA 94117
*
*/
#ifndef lint
static char sccsid[] =
"@(#)tcap_parse.c 9.5 88/01/19 Copyright 1985 Sun Micro";
static char RCSid[] =
"@(#)$Header: tcap_parse.c,v 2.3 88/10/04 06:00:03 gnu Release $";
#endif
/*
* Copyright (c) 1985 by Sun Microsystems, Inc.
*/
/*-
tcap_parse.c: Parse termcap output based on termcap entry.
tcap_parse.c, Mon Mar 24 11:25:44 1986
David Rosenthal,
Sun Microsystems
*/
/* XXX - remember longest outstanding partial match? */
/* XXX - overlapping partial matches? */
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#ifdef REF
#include <ref/config.h>
#endif
#include "termcap.h"
extern char *malloc();
#ifndef bcopy
extern void bcopy();
#endif
static int TerminalIsBraindamaged = 0;
/* Import these from tcap_ops.c */
extern struct tcap T[];
extern int Ts;
extern struct tcap *CheckCR;
extern struct tcap *CheckNL;
extern struct tcap *CheckTAB;
extern struct tcap *CheckBS;
extern int PageFull;
extern int PageMode;
static char *unpad();
static int tc_init_stacks();
/*
* Initialize the display system from the TERMCAP entry.
* We parse the entry and build the tcap structures
* describing the operations supported by this type of
* terminal. These descriptions are then used by tc_display()
* in interpreting the data stream generated by the
* application
*/
int
tc_initialize(term)
char *term;
{
#ifdef SUNTGETENT
static void tc_fix_tcap_ent();
#endif
static char tcapbuf[1024], tcaparea[1024];
char *areap = tcaparea;
extern int tgetent(), tgetnum(), tgetflag();
extern char *tgetstr();
register struct tcap *tp;
if (tgetent(tcapbuf, term) != 1) { /* unknown terminal type? */
fprintf(stderr, "tgetent failed\n");
return (1);
}
#ifdef SUNTGETENT
tc_fix_tcap_ent(tcapbuf);
#endif
set_environment_var("TERMCAP", tcapbuf);
for (tp = T; tp < T+Ts; tp++) {
switch (tp->t_type) {
case string:
tp->t_text = unpad(tgetstr(tp->t_key, &areap));
if (tp->t_text == NULL)
tp->t_text = tp->t_deftext;
if (tp->t_text) {
tp->t_size = strlen(tp->t_text);
if (isprint(tp->t_text[0]))
TerminalIsBraindamaged = 1;
} else
tp->t_size = 0;
break;
case num:
tp->t_x = tgetnum(tp->t_key);
break;
case bool:
tp->t_x = tgetflag(tp->t_key);
break;
}
/* invoke any initialize routine */
if (tp->t_in && (*tp->t_in)(tp)) {
fprintf(stderr, "termcap init failed for %s\n", tp->t_key);
return (1);
}
}
tc_init_ops();
return tc_init_stacks();
}
#ifdef HAVE_TERMCAP
static char *
unpad(s)
register char *s;
{
if (s) {
register pad = 0;
while (isdigit(*s))
pad++, s++;
if (pad && *s == '*')
s++;
}
return (s);
}
#else /* !HAVE_TERMCAP, ie next code is for TERMINFO */
/*
* Remove the substring of the form "$<x^>" where x = number, and ^ = characters
* in the set [* /]. This is the terminfo way of specifying delays or padding.
*/
static char *
unpad(s)
register char *s;
{
if (s) {
register char *spt = s;
register char *spt1, *spt2;
char *strchr();
while (spt1 = strchr(spt, '$')) {
if (*(spt1 + 1) == '<') { /* found the '$<' pair */
if (spt2 = strchr(spt1, '>')) {
strcpy(spt1, ++spt2); /* found end '>' */
spt = spt1; /* copy tail of */
continue; /* string over */
/* '$<..', look */
/* for more */
} else
break; /* no match for '$<' so quit */
} else {
spt = spt1 + 1; /* found '$' but no '<', */
continue; /* look for more */
}
}
}
return (s);
}
#endif /* !HAVE_TERMCAP */
#ifdef SUNTGETENT
#define TCAPBUFSIZE 1024
#define SPECIALSIZE 2
static struct {
char *last;
char str[3];
} tcapSpecials[SPECIALSIZE] = {
NULL, "co",
NULL, "li"
};
/*
* Stomp on the first "co" and "li" entries in the termcap entry
* to avoid braindamage in the Sun version of the termcap library.
* Apparently the Sun version of tgetent() looks at the terminal
* state and uses this to prepend extra line+column spec's that
* reflect the terminal's current state. This is not what we want,
* so our only recourse is to undo the this braindamage here.
*/
static void
tc_fix_tcap_ent(buf)
char *buf;
{
char *bp = buf;
#ifndef SYSVREF
char *index();
#else
#define index(s, c) (char *)strchr(s, c)
#endif
int i;
/* for each item in buf ... */
for (bp = index(bp, ':'); bp && *(bp+1); bp = index(bp, ':')) {
++bp;
/* for each special tcap code ... */
for (i = 0; i < SPECIALSIZE; i++) {
if (strncmp(tcapSpecials[i].str, bp, 2) == 0) {
if (tcapSpecials[i].last)
strncpy(tcapSpecials[i].last, "xx", 2);
tcapSpecials[i].last = bp;
break;
}
}
}
}
#endif /* SUNTGETENT */
/*
* Matching is performed with a push-down automata implemented
* with dual stacks. An initial stack is loaded with all the
* potential matches from the termcap structure. Matching then
* takes place by popping each potential match off the ``current
* stack'' and, if a successful match for the current character
* occurs, pushing the match on the ``other stack''. When the
* ``current stack'' is empty (all elements have been examined),
* the stacks are swapped and the process restarted. This continues
* until a completed match or the stack of potential matches has
* been exhausted.
*/
static struct tcap **curstack, **cursp; /* ``potential match'' stack */
static struct tcap **otherstack, **othersp; /* ``match this pass'' stack */
static struct tcap **resetstack; /* prototype curstack */
static int stacksize; /* # of potential matches */
static int MatchInProgress; /* for fast check */
#define PushMatch(tp) (*--othersp = tp)
#define PopMatch() (*cursp++)
#define PopMatched() (*othersp++)
#define SwapStacks() { \
struct tcap **t; \
t = curstack, curstack = otherstack, otherstack = t; \
cursp = othersp, othersp = otherstack + stacksize; \
MatchInProgress = 1; \
}
#define ResetMatchStack() { \
bcopy((char *)resetstack, (char *)curstack, \
stacksize*sizeof (struct tcap *)); \
cursp = curstack; \
MatchInProgress = 0; \
}
#define FlushStack(sp, stack) { \
while (sp < stack+stacksize) { \
tp = *sp++; \
tp->t_index = 0; \
tp->t_param = 0 ; \
tp->t_matched = 0; \
tp->t_2nd = 0; \
} \
}
#define FlushMatchStack() FlushStack(cursp, curstack)
#define FlushMatchedStack() FlushStack(othersp, otherstack);
#define MatchStackEmpty() (cursp >= curstack+stacksize)
#define MatchedStackEmpty() (othersp >= otherstack+stacksize)
/*
* Reset the pattern matching stack and load
* it with all the potential matching entries.
*/
static int
tc_init_stacks()
{
register struct tcap *tp;
for (tp = T; tp < T+Ts; tp++)
if (tp->t_text != NULL)
stacksize++;
curstack = (struct tcap **)malloc((unsigned)
(3*sizeof(struct tcap *) * stacksize));
if (!curstack)
return 1;
otherstack = curstack+stacksize;
resetstack = otherstack+stacksize;
othersp = resetstack+stacksize;
for (tp = T; tp < T+Ts; tp++)
if (tp->t_text != NULL)
PushMatch(tp);
othersp = otherstack+stacksize;
ResetMatchStack();
return 0;
}
extern struct tcap interruptedOp;
/*
* Interpret data from the application. We match data against
* the ``escape sequences'' expected for this termcap description
* and, if successful, invoke the routines used to emulate the
* capabilities on the window.
*/
tc_display(cp, n)
u_char *cp;
register int n;
{
register int c, j;
register struct tcap *tp;
static char dbuf[256], *dp = dbuf;
int restart, lim;
/*
* If we're blocked with a page full, indicate
* nothing was sent to the screen. We should
* never be called when already blocked, but
* just in case, turn scrolling on again so we
* don't lost any data.
*/
if (PageFull) {
if (interruptedOp.t_key == 0)
return (n);
scrollreset(0); /* XXX */
}
/*
* If we have previous output, process it first.
* Check on completion to see if we filled the screen.
*/
if (interruptedOp.t_key) {
(*interruptedOp.t_op)(&interruptedOp);
if (PageFull)
return (n);
interruptedOp.t_key = 0;
}
/*
* For each input character, look for potential
* matches in the tcap structure. For each possible
* match, construct the resultant output buffer.
* On first match process the operation (e.g. invoke
* internal routine) and flush extraneous matches.
* If input doesn't match any capability, send it to
* the window.
*/
while (n > 0 && !PageFull) {
/*
* If we're not in the middle of a match, then
* try and bypass the pattern matcher by performing
* special checks on the most common input.
*/
if (!MatchInProgress) {
while (n > 0 && !PageFull) {
/*
* If terminal has only non-printing escape sequences,
* then process printable characters w/o matching against
* the termcap strings.
*/
if (!TerminalIsBraindamaged) {
for (dp = (char *)cp; n > 0 && isprint((int)*cp); n--)
cp++;
if ((char *)cp > dp) {
tp = T+Ts;
tp->t_text = dp; /* use original storage */
tp->t_size = (char *)cp - dp;
(*tp->t_op)(tp);
if (PageFull)
return (n);
continue;
}
}
/*
* Make quick checks for standard NL, CR, BS, and TAB
* characters. This speeds up scrolling for most
* terminal types.
*/
c = *cp;
if (CheckNL && c == '\n')
tp = CheckNL;
else if (CheckCR && c == '\r')
tp = CheckCR;
else if (CheckTAB && c == '\t')
tp = CheckTAB;
else if (CheckBS && c == '\b')
tp = CheckBS;
else
break;
cp++, n--;
(*tp->t_op)(tp);
if (PageFull)
return (n);
}
dp = dbuf;
if (n == 0)
break;
}
c = *dp++ = *cp++, n--;
while (!MatchStackEmpty()) {
tp = PopMatch();
again:
j = tp->t_index;
restart = 0;
/*
* Check match against numeric %[d23] specification.
*/
if (tp->t_text[j] == '%') {
switch (tp->t_text[j+1]) {
case 'd': /* series of decimal digits */
lim = 127;
goto digit;
case '2': /* two decimal digits */
lim = 2;
goto digit;
case '3': /* three decimal digits */
lim = 3;
/* fall thru.. */
digit:
if (isdigit(c) && tp->t_matched < lim) {
tp->t_matched++;
tp->t_param = tp->t_param*10 + (c-'0');
goto plainmatch;
} else {
if (tp->t_matched == 0)
tp->t_param = 1 ;
tp->t_matched = 0;
restart = !isdigit(c);
goto gotvalue;
}
/*NOTREACHED*/
break;
case '.': /* binary character */
tp->t_param = c;
gotvalue:
switch (tp->t_2nd + tp->t_pc_r) {
case 0:
case 2:
if ((tp->t_y = tp->t_param) >= tp->t_yilim)
tp->t_y -= tp->t_yi;
break;
case 1:
if ((tp->t_x = tp->t_param) >= tp->t_xilim)
tp->t_x -= tp->t_xi;
break;
}
tp->t_2nd = !tp->t_2nd;
tp->t_index += 2;
tp->t_param = 0 ;
goto plainmatch;
case '%':
if ((c & 0177) == '%') {
tp->t_index += 2;
goto plainmatch;
} else
goto nomatch;
default:
abort(); /* XXX */
/* NOTREACHED */
}
} else if ((c & 0177) == (tp->t_text[j] & 0177)) {
tp->t_index++;
plainmatch: /* plain match */
if (tp->t_index >= tp->t_size) {/* match completed */
if (tp->t_op)
(*tp->t_op)(tp);
dp = dbuf;
tp->t_index = 0;
tp->t_matched = 0;
tp->t_param = 0 ;
tp->t_2nd = 0;
goto done;
}
/*
* The end of a %d match is the only case where a
* character must be pushed-back and re-parsed.
*/
if (restart)
goto again;
PushMatch(tp); /* push partial match */
} else {
nomatch: /* failed match */
tp->t_index = 0;
tp->t_param = 0 ;
tp->t_matched = 0;
tp->t_2nd = 0;
}
}
if (!MatchedStackEmpty()) {
SwapStacks();
continue;
}
done:
/*
* Come here either because no partial matches were
* found in the table, or because a match completed.
* In the first case we send the input data off
* immediately. In the second case we reset the
* state machines and go on to the next character.
*/
if (dp - dbuf) { /* flush output */
tp = T+Ts;
tp->t_text = dbuf;
tp->t_size = dp - dbuf;
(*tp->t_op)(tp);
dp = dbuf;
}
FlushMatchedStack(); /* reset partial matches */
FlushMatchStack(); /* reset unchecked partials */
ResetMatchStack(); /* re-init match stack */
}
return (n); /* return number of chars processed */
}
@@@ Fin de tcap_parse.c
echo termcap.h
cat >termcap.h <<'@@@ Fin de termcap.h'
/*
* This file is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part.
* Users may copy, modify or distribute this file at will.
*
* THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* This file is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS FILE
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even
* if Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*
* Modifications to the original Sun Microsystems, Inc. source code
* made by the Grasshopper Group are in the Public Domain.
*
* Extensions to this file by Eric Messick of the Grasshopper Group.
*
* Grasshopper Group
* 212 Clayton St
* San Francisco, CA 94117
*
*/
/*
* "@(#)termcap.h 9.4 88/01/19 SMI
* "@(#)$Header: termcap.h,v 2.0 88/09/16 00:19:39 eric Release $
*
* Copyright (c) 1985 by Sun Microsystems, Inc.
*/
enum tct { string, num, bool};
struct tcap {
char * t_key; /* Capability name */
enum tct t_type; /* Capability type */
int (*t_op)(/* struct tcap * */);
int (*t_in)(/* struct tcap * */);
char * t_text; /* Capability text */
char * t_deftext; /* Default text */
u_short t_size; /* Length of t_text */
u_short t_index; /* Posn. in t_text */
int t_param; /* parameter value for %match */
u_short t_matched; /* Length of matched string */
u_short t_x; /* Coordinate for cm= etc. */
u_short t_xi; /* Offset to subtract from t_x */
u_short t_xilim; /* If t_x >= t_xilim subtract t_xi */
u_short t_y;
u_short t_yi;
u_short t_yilim;
unsigned t_pc_r : 1; /* %r present */
unsigned t_pc_n : 1; /* %n present */
unsigned t_pc_B : 1; /* %B present */
unsigned t_pc_D : 1; /* %D present */
unsigned t_2nd : 1; /* On second coord */
};
@@@ Fin de termcap.h
exit 0
--
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
More information about the Comp.sources.unix
mailing list