1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-19 10:53:58 +00:00
freebsd/usr.bin/ee/new_curse.c
2001-08-13 14:06:34 +00:00

3772 lines
85 KiB
C

/*
| new_curse.c
|
| A subset of curses developed for use with ae.
|
| written by Hugh Mahon
|
| THIS MATERIAL IS PROVIDED "AS IS". THERE ARE
| NO WARRANTIES OF ANY KIND WITH REGARD TO THIS
| MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE
| IMPLIED WARRANTIES OF MERCHANTABILITY AND
| FITNESS FOR A PARTICULAR PURPOSE. Neither
| Hewlett-Packard nor Hugh Mahon shall be liable
| for errors contained herein, nor for
| incidental or consequential damages in
| connection with the furnishing, performance or
| use of this material. Neither Hewlett-Packard
| nor Hugh Mahon assumes any responsibility for
| the use or reliability of this software or
| documentation. This software and
| documentation is totally UNSUPPORTED. There
| is no support contract available. Hewlett-
| Packard has done NO Quality Assurance on ANY
| of the program or documentation. You may find
| the quality of the materials inferior to
| supported materials.
|
| This software is not a product of Hewlett-Packard, Co., or any
| other company. No support is implied or offered with this software.
| You've got the source, and you're on your own.
|
| This software may be distributed under the terms of Larry Wall's
| Artistic license, a copy of which is included in this distribution.
|
| This notice must be included with this software and any derivatives.
|
| Copyright (c) 1986, 1987, 1988, 1991, 1992, 1993, 1994, 1995 Hugh Mahon
| All are rights reserved.
|
| $Header: /home/hugh/sources/old_ae/RCS/new_curse.c,v 1.49 1998/12/21 02:25:59 hugh Exp hugh $
|
*/
char *copyright_message[] = { "Copyright (c) 1986, 1987, 1988, 1991, 1992, 1993, 1994, 1995 Hugh Mahon",
"All rights are reserved."};
#ifndef lint
statis const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include "new_curse.h"
#include <signal.h>
#include <fcntl.h>
#ifdef SYS5
#include <string.h>
#else
#include <strings.h>
#endif
#ifdef BSD_SELECT
#include <sys/types.h>
#include <sys/time.h>
#ifdef SLCT_HDR
#include <sys/select.h> /* on AIX */
#endif /* SLCT_HDR */
#endif /* BSD_SELECT */
#ifdef HAS_STDLIB
#include <stdlib.h>
#endif
#if defined(__STDC__)
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#ifdef HAS_UNISTD
#include <unistd.h>
#endif
#ifdef HAS_SYS_IOCTL
#include <sys/ioctl.h>
#endif
WINDOW *curscr;
static WINDOW *virtual_scr;
WINDOW *stdscr;
WINDOW *last_window_refreshed;
#ifdef TIOCGWINSZ
struct winsize ws;
#endif
#define min(a, b) (a < b ? a : b)
#define highbitset(a) ((a) & 0x80)
#ifndef CAP
#define String_Out(table, stack, place) Info_Out(table, stack, place)
#else
#define String_Out(table, stack, place) Cap_Out(table, stack, place)
#endif
#define bw__ 0 /* booleans */
#define am__ 1
#define xb__ 2
#define xs__ 3 /* hp glitch (standout not erased by overwrite) */
#define xn__ 4
#define eo__ 5
#define gn__ 6 /* generic type terminal */
#define hc__ 7 /* hardcopy terminal */
#define km__ 8
#define hs__ 9
#define in__ 10
#define da__ 11
#define db__ 12
#define mi__ 13 /* safe to move during insert mode */
#define ms__ 14 /* safe to move during standout mode */
#define os__ 15
#define es__ 16
#define xt__ 17
#define hz__ 18 /* hazeltine glitch */
#define ul__ 19
#define xo__ 20
#define chts__ 21
#define nxon__ 22
#define nrrmc__ 23
#define npc__ 24
#define mc5i__ 25
#define co__ 0 /* number of columns */ /* numbers */
#define it__ 1 /* spaces per tab */
#define li__ 2 /* number of lines */
#define lm__ 3
#define sg__ 4 /* magic cookie glitch */
#define pb__ 5
#define vt__ 6
#define ws__ 7
#define cols__ 0
#define lines__ 2
#define xmc__ 4
#define vt__ 6
#define wsl__ 7
#define nlab__ 8
#define lh__ 9
#define lw__ 10
#define bt__ 0 /* back tab */ /* strings */
#define bl__ 1 /* bell */
#define cr__ 2 /* carriage return */
#define cs__ 3 /* change scroll region */
#define ct__ 4 /* clear all tab stops */
#define cl__ 5 /* clear screen and home cursor */
#define ce__ 6 /* clear to end of line */
#define cd__ 7 /* clear to end of display */
#define ch__ 8 /* set cursor column */
#define CC__ 9 /* term, settable cmd char in */
#define cm__ 10 /* screen rel cursor motion, row, column */
#define do__ 11 /* down one line */
#define ho__ 12 /* home cursor */
#define vi__ 13 /* make cursor invisible */
#define le__ 14 /* move cursor left one space */
#define CM__ 15 /* memory rel cursor addressing */
#define ve__ 16 /* make cursor appear normal */
#define nd__ 17 /* non-destructive space (cursor right) */
#define ll__ 18 /* last line, first col */
#define up__ 19 /* cursor up */
#define vs__ 20
#define dc__ 21 /* delete character */
#define dl__ 22 /* delete line */
#define ds__ 23
#define hd__ 24
#define as__ 25
#define mb__ 26
#define md__ 27 /* turn on bold */
#define ti__ 28
#define dm__ 29 /* turn on delete mode */
#define mh__ 30 /* half bright mode */
#define im__ 31 /* insert mode */
#define mk__ 32
#define mp__ 33
#define mr__ 34
#define so__ 35 /* enter standout mode */
#define us__ 36
#define ec__ 37
#define ae__ 38
#define me__ 39
#define te__ 40
#define ed__ 41
#define ei__ 42 /* exit insert mode */
#define se__ 43 /* exit standout mode */
#define ue__ 44
#define vb__ 45
#define ff__ 46
#define fs__ 47
#define i1__ 48
#define i2__ 49
#define i3__ 50
#define if__ 51
#define ic__ 52
#define al__ 53
#define ip__ 54
#define kb__ 55 /* backspace key */
#define ka__ 56
#define kC__ 57
#define kt__ 58
#define kD__ 59
#define kL__ 60
#define kd__ 61
#define kM__ 62
#define kE__ 63
#define kS__ 64
#define k0__ 65
#define k1__ 66
#define kf10__ 67
#define k2__ 68
#define k3__ 69
#define k4__ 70
#define k5__ 71
#define k6__ 72
#define k7__ 73
#define k8__ 74
#define k9__ 75
#define kh__ 76
#define kI__ 77
#define kA__ 78
#define kl__ 79
#define kH__ 80
#define kN__ 81
#define kP__ 82
#define kr__ 83
#define kF__ 84
#define kR__ 85
#define kT__ 86
#define ku__ 87 /* key up */
#define ke__ 88
#define ks__ 89
#define l0__ 90
#define l1__ 91
#define la__ 92
#define l2__ 93
#define l3__ 94
#define l4__ 95
#define l5__ 96
#define l6__ 97
#define l7__ 98
#define l8__ 99
#define l9__ 100
#define mo__ 101
#define mm__ 102
#define nw__ 103
#define pc__ 104
#define DC__ 105
#define DL__ 106
#define DO__ 107
#define IC__ 118
#define SF__ 109
#define AL__ 110
#define LE__ 111
#define RI__ 112
#define SR__ 113
#define UP__ 114
#define pk__ 115
#define pl__ 116
#define px__ 117
#define ps__ 118
#define pf__ 119
#define po__ 120
#define rp__ 121
#define r1__ 122
#define r2__ 123
#define r3__ 124
#define rf__ 125
#define rc__ 126
#define cv__ 127
#define sc__ 128
#define sf__ 129
#define sr__ 130
#define sa__ 131 /* sgr */
#define st__ 132
#define wi__ 133
#define ta__ 134
#define ts__ 135
#define uc__ 136
#define hu__ 137
#define iP__ 138
#define K1__ 139
#define K2__ 140
#define K3__ 141
#define K4__ 142
#define K5__ 143
#define pO__ 144
#define ml__ 145
#define mu__ 146
#define rmp__ 145
#define acsc__ 146
#define pln__ 147
#define kcbt__ 148
#define smxon__ 149
#define rmxon__ 150
#define smam__ 151
#define rmam__ 152
#define xonc__ 153
#define xoffc__ 154
#define enacs__ 155
#define smln__ 156
#define rmln__ 157
#define kbeg__ 158
#define kcan__ 159
#define kclo__ 160
#define kcmd__ 161
#define kcpy__ 162
#define kcrt__ 163
#define kend__ 164
#define kent__ 165
#define kext__ 166
#define kfnd__ 167
#define khlp__ 168
#define kmrk__ 169
#define kmsg__ 170
#define kmov__ 171
#define knxt__ 172
#define kopn__ 173
#define kopt__ 174
#define kprv__ 175
#define kprt__ 176
#define krdo__ 177
#define kref__ 178
#define krfr__ 179
#define krpl__ 180
#define krst__ 181
#define kres__ 182
#define ksav__ 183
#define kspd__ 184
#define kund__ 185
#define kBEG__ 186
#define kCAN__ 187
#define kCMD__ 188
#define kCPY__ 189
#define kCRT__ 190
#define kDC__ 191
#define kDL__ 192
#define kslt__ 193
#define kEND__ 194
#define kEOL__ 195
#define kEXT__ 196
#define kFND__ 197
#define kHLP__ 198
#define kHOM__ 199
#define kIC__ 200
#define kLFT__ 201
#define kMSG__ 202
#define kMOV__ 203
#define kNXT__ 204
#define kOPT__ 205
#define kPRV__ 206
#define kPRT__ 207
#define kRDO__ 208
#define kRPL__ 209
#define kRIT__ 210
#define kRES__ 211
#define kSAV__ 212
#define kSPD__ 213
#define kUND__ 214
#define rfi__ 215
#define kf11__ 216
#define kf12__ 217
#define kf13__ 218
#define kf14__ 219
#define kf15__ 220
#define kf16__ 221
#define kf17__ 222
#define kf18__ 223
#define kf19__ 224
#define kf20__ 225
#define kf21__ 226
#define kf22__ 227
#define kf23__ 228
#define kf24__ 229
#define kf25__ 230
#define kf26__ 231
#define kf27__ 232
#define kf28__ 233
#define kf29__ 234
#define kf30__ 235
#define kf31__ 236
#define kf32__ 237
#define kf33__ 238
#define kf34__ 239
#define kf35__ 240
#define kf36__ 241
#define kf37__ 242
#define kf38__ 243
#define kf39__ 244
#define kf40__ 245
#define kf41__ 246
#define kf42__ 247
#define kf43__ 248
#define kf44__ 249
#define kf45__ 250
#define kf46__ 251
#define kf47__ 252
#define kf48__ 253
#define kf49__ 254
#define kf50__ 255
#define kf51__ 256
#define kf52__ 257
#define kf53__ 258
#define kf54__ 259
#define kf55__ 260
#define kf56__ 261
#define kf57__ 262
#define kf58__ 263
#define kf59__ 264
#define kf60__ 265
#define kf61__ 266
#define kf62__ 267
#define kf63__ 268
#define el1__ 269
#define mgc__ 270
#define smgl__ 271
#define smgr__ 272
#ifdef CAP
char *Boolean_names[] = {
"bw", "am", "xb", "xs", "xn", "eo", "gn", "hc", "km", "hs", "in", "da", "db",
"mi", "ms", "os", "es", "xt", "hz", "ul", "xo", "HC", "nx", "NR", "NP", "5i"
};
char *Number_names[] = {
"co#", "it#", "li#", "lm#", "sg#", "pb#", "vt#", "ws#", "Nl#", "lh#", "lw#"
};
char *String_names[] = {
"bt=", "bl=", "cr=", "cs=", "ct=", "cl=", "ce=", "cd=", "ch=", "CC=", "cm=",
"do=", "ho=", "vi=", "le=", "CM=", "ve=", "nd=", "ll=", "up=", "vs=", "dc=",
"dl=", "ds=", "hd=", "as=", "mb=", "md=", "ti=", "dm=", "mh=", "im=", "mk=",
"mp=", "mr=", "so=", "us=", "ec=", "ae=", "me=", "te=", "ed=", "ei=", "se=",
"ue=", "vb=", "ff=", "fs=", "i1=", "i2=", "i3=", "if=", "ic=", "al=", "ip=",
"kb=", "ka=", "kC=", "kt=", "kD=", "kL=", "kd=", "kM=", "kE=", "kS=", "k0=",
"k1=", "k;=", "k2=", "k3=", "k4=", "k5=", "k6=", "k7=", "k8=", "k9=", "kh=",
"kI=", "kA=", "kl=", "kH=", "kN=", "kP=", "kr=", "kF=", "kR=", "kT=", "ku=",
"ke=", "ks=", "l0=", "l1=", "la=", "l2=", "l3=", "l4=", "l5=", "l6=", "l7=",
"l8=", "l9=", "mo=", "mm=", "nw=", "pc=", "DC=", "DL=", "DO=", "IC=", "SF=",
"AL=", "LE=", "RI=", "SR=", "UP=", "pk=", "pl=", "px=", "ps=", "pf=", "po=",
"rp=", "r1=", "r2=", "r3=", "rf=", "rc=", "cv=", "sc=", "sf=", "sr=", "sa=",
"st=", "wi=", "ta=", "ts=", "uc=", "hu=", "iP=", "K1=", "K3=", "K2=", "K4=",
"K5=", "pO=", "rP=", "ac=", "pn=", "kB=", "SX=", "RX=", "SA=", "RA=", "XN=",
"XF=", "eA=", "LO=", "LF=", "@1=", "@2=", "@3=", "@4=", "@5=", "@6=", "@7=",
"@8=", "@9=", "@0=", "%1=", "%2=", "%3=", "%4=", "%5=", "%6=", "%7=", "%8=",
"%9=", "%0=", "&1=", "&2=", "&3=", "&4=", "&5=", "&6=", "&7=", "&8=", "&9=",
"&0=", "*1=", "*2=", "*3=", "*4=", "*5=", "*6=", "*7=", "*8=", "*9=", "*0=",
"#1=", "#2=", "#3=", "#4=", "%a=", "%b=", "%c=", "%d=", "%e=", "%f=", "%g=",
"%h=", "%i=", "%j=", "!1=", "!2=", "!3=", "RF=", "F1=", "F2=", "F3=", "F4=",
"F5=", "F6=", "F7=", "F8=", "F9=", "FA=", "FB=", "FC=", "FD=", "FE=", "FF=",
"FG=", "FH=", "FI=", "FJ=", "FK=", "FL=", "FM=", "FN=", "FO=", "FP=", "FQ=",
"FR=", "FS=", "FT=", "FU=", "FV=", "FW=", "FX=", "FY=", "FZ=", "Fa=", "Fb=",
"Fc=", "Fd=", "Fe=", "Ff=", "Fg=", "Fh=", "Fi=", "Fj=", "Fk=", "Fl=", "Fm=",
"Fn=", "Fo=", "Fp=", "Fq=", "Fr=", "cb=", "MC=", "ML=", "MR="
};
#endif
char *new_curse = "October 1987";
char in_buff[100]; /* buffer for ungetch */
int bufp; /* next free position in in_buff */
char *TERMINAL_TYPE = NULL; /* terminal type to be gotten from environment */
int CFOUND = FALSE;
int Data_Line_len = 0;
int Max_Key_len; /* max length of a sequence sent by a key */
char *Data_Line = NULL;
char *TERM_PATH = NULL;
char *TERM_data_ptr = NULL;
char *Term_File_name = NULL; /* name of file containing terminal description */
FILE *TFP; /* file pointer to file with terminal des. */
int Fildes; /* file descriptor for terminfo file */
int STAND = FALSE; /* is standout mode activated? */
int TERM_INFO = FALSE; /* is terminfo being used (TRUE), or termcap (FALSE) */
int Time_Out; /* set when time elapsed while trying to read function key */
int Curr_x; /* current x position on screen */
int Curr_y; /* current y position on the screen */
int LINES;
int COLS;
int Move_It; /* flag to move cursor if magic cookie glitch */
int initialized = FALSE; /* tells whether new_curse is initialized */
float speed;
float chars_per_millisecond;
int Repaint_screen; /* if an operation to change screen impossible, repaint screen */
int Intr; /* storeage for interrupt character */
int Parity; /* 0 = no parity, 1 = odd parity, 2 = even parity */
int Noblock; /* for BSD systems */
int Num_bits; /* number of bits per character */
int Flip_Bytes; /* some systems have byte order reversed */
int interrupt_flag = FALSE; /* set true if SIGWINCH received */
#ifndef CAP
char *Strings;
#endif
struct KEYS {
int length; /* length of string sent by key */
char *string; /* string sent by key */
int value; /* CURSES value of key (9-bit) */
};
struct KEY_STACK {
struct KEYS *element;
struct KEY_STACK *next;
};
struct KEY_STACK *KEY_TOS = NULL;
struct KEY_STACK *KEY_POINT;
/*
|
| Not all systems have good terminal information, so we will define
| keyboard information here for the most widely used terminal type,
| the VT100.
|
*/
struct KEYS vt100[] =
{
{ 3, "\033[A", 0403 }, /* key up */
{ 3, "\033[C", 0405 }, /* key right */
{ 3, "\033[D", 0404 }, /* key left */
{ 4, "\033[6~", 0522 }, /* key next page */
{ 4, "\033[5~", 0523 }, /* key prev page */
{ 3, "\033[[", 0550 }, /* key end */
{ 3, "\033[@", 0406 }, /* key home */
{ 4, "\033[2~", 0513 }, /* key insert char */
{ 3, "\033[y", 0410 }, /* key F0 */
{ 3, "\033[P", 0411 }, /* key F1 */
{ 3, "\033[Q", 0412 }, /* key F2 */
{ 3, "\033[R", 0413 }, /* key F3 */
{ 3, "\033[S", 0414 }, /* key F4 */
{ 3, "\033[t", 0415 }, /* key F5 */
{ 3, "\033[u", 0416 }, /* key F6 */
{ 3, "\033[v", 0417 }, /* key F7 */
{ 3, "\033[l", 0420 }, /* key F8 */
{ 3, "\033[w", 0421 }, /* key F9 */
{ 3, "\033[x", 0422 }, /* key F10 */
{ 5, "\033[10~", 0410 }, /* key F0 */
{ 5, "\033[11~", 0411 }, /* key F1 */
{ 5, "\033[12~", 0412 }, /* key F2 */
{ 5, "\033[13~", 0413 }, /* key F3 */
{ 5, "\033[14~", 0414 }, /* key F4 */
{ 5, "\033[15~", 0415 }, /* key F5 */
{ 5, "\033[17~", 0416 }, /* key F6 */
{ 5, "\033[18~", 0417 }, /* key F7 */
{ 5, "\033[19~", 0420 }, /* key F8 */
{ 5, "\033[20~", 0421 }, /* key F9 */
{ 5, "\033[21~", 0422 }, /* key F10 */
{ 5, "\033[23~", 0423 }, /* key F11 */
{ 5, "\033[24~", 0424 }, /* key F12 */
{ 3, "\033[q", 0534 }, /* ka1 upper-left of keypad */
{ 3, "\033[s", 0535 }, /* ka3 upper-right of keypad */
{ 3, "\033[r", 0536 }, /* kb2 center of keypad */
{ 3, "\033[p", 0537 }, /* kc1 lower-left of keypad */
{ 3, "\033[n", 0540 }, /* kc3 lower-right of keypad */
/*
| The following are the same keys as above, but with
| a different character following the escape char.
*/
{ 3, "\033OA", 0403 }, /* key up */
{ 3, "\033OC", 0405 }, /* key right */
{ 3, "\033OD", 0404 }, /* key left */
{ 3, "\033OB", 0402 }, /* key down */
{ 4, "\033O6~", 0522 }, /* key next page */
{ 4, "\033O5~", 0523 }, /* key prev page */
{ 3, "\033O[", 0550 }, /* key end */
{ 3, "\033O@", 0406 }, /* key home */
{ 4, "\033O2~", 0513 }, /* key insert char */
{ 3, "\033Oy", 0410 }, /* key F0 */
{ 3, "\033OP", 0411 }, /* key F1 */
{ 3, "\033OQ", 0412 }, /* key F2 */
{ 3, "\033OR", 0413 }, /* key F3 */
{ 3, "\033OS", 0414 }, /* key F4 */
{ 3, "\033Ot", 0415 }, /* key F5 */
{ 3, "\033Ou", 0416 }, /* key F6 */
{ 3, "\033Ov", 0417 }, /* key F7 */
{ 3, "\033Ol", 0420 }, /* key F8 */
{ 3, "\033Ow", 0421 }, /* key F9 */
{ 3, "\033Ox", 0422 }, /* key F10 */
{ 5, "\033O10~", 0410 }, /* key F0 */
{ 5, "\033O11~", 0411 }, /* key F1 */
{ 5, "\033O12~", 0412 }, /* key F2 */
{ 5, "\033O13~", 0413 }, /* key F3 */
{ 5, "\033O14~", 0414 }, /* key F4 */
{ 5, "\033O15~", 0415 }, /* key F5 */
{ 5, "\033O17~", 0416 }, /* key F6 */
{ 5, "\033O18~", 0417 }, /* key F7 */
{ 5, "\033O19~", 0420 }, /* key F8 */
{ 5, "\033O20~", 0421 }, /* key F9 */
{ 5, "\033O21~", 0422 }, /* key F10 */
{ 5, "\033O23~", 0423 }, /* key F11 */
{ 5, "\033O24~", 0424 }, /* key F12 */
{ 3, "\033Oq", 0534 }, /* ka1 upper-left of keypad */
{ 3, "\033Os", 0535 }, /* ka3 upper-right of keypad */
{ 3, "\033Or", 0536 }, /* kb2 center of keypad */
{ 3, "\033Op", 0537 }, /* kc1 lower-left of keypad */
{ 3, "\033On", 0540 }, /* kc3 lower-right of keypad */
{ 0, "", 0 } /* end */
};
struct Parameters {
int value;
struct Parameters *next;
};
int Key_vals[] = {
0407, 0526, 0515, 0525, 0512, 0510, 0402, 0514, 0517, 0516, 0410, 0411,
0422, 0412, 0413, 0414, 0415, 0416, 0417, 0420, 0421, 0406, 0513, 0511,
0404, 0533, 0522, 0523, 0405, 0520, 0521, 0524, 0403,
0534, 0535, 0536, 0537, 0540, 0541, 0542, 0543, 0544, 0545, 0546, 0547,
0550, 0527, 0551, 0552, 0553, 0554, 0555, 0556, 0557, 0560, 0561, 0562,
0532, 0563, 0564, 0565, 0566, 0567, 0570, 0571, 0627, 0630, 0572, 0573,
0574, 0575, 0576, 0577, 0600, 0601, 0602, 0603, 0604, 0605, 0606, 0607,
0610, 0611, 0612, 0613, 0614, 0615, 0616, 0617, 0620, 0621, 0622, 0623,
0624, 0625, 0626, 0423, 0424, 0425, 0426, 0427, 0430, 0431,
0432, 0433, 0434, 0435, 0436, 0437, 0440, 0441, 0442, 0443, 0444, 0445,
0446, 0447, 0450, 0451, 0452, 0453, 0454, 0455, 0456, 0457, 0460, 0461,
0462, 0463, 0464, 0465, 0466, 0467, 0470, 0471, 0472, 0473, 0474, 0475,
0476, 0477, 0500, 0501, 0502, 0503, 0504, 0505, 0506, 0507
};
int attributes_set[9];
static int nc_attributes = 0; /* global attributes for new_curse to observe */
#ifdef SYS5
struct termio Terminal;
struct termio Saved_tty;
#else
struct sgttyb Terminal;
struct sgttyb Saved_tty;
#endif
char *tc_;
int Booleans[128];
int Numbers[128];
char *String_table[1024];
int *virtual_lines;
static char nc_scrolling_ability = FALSE;
#ifdef CAP
#if __STDC__ || defined(__cplusplus)
#define P_(s) s
#else
#define P_(s) ()
#endif /* __STDC__ */
int tc_Get_int P_((int));
void CAP_PARSE P_((void));
void Find_term P_((void));
#undef P_
#endif /* CAP */
#ifndef __STDC__
#ifndef HAS_STDLIB
extern char *fgets();
extern char *malloc();
extern char *getenv();
FILE *fopen(); /* declaration for open function */
#endif /* HAS_STDLIB */
#endif /* __STDC__ */
#ifdef SIGWINCH
/*
| Copy the contents of one window to another.
*/
void
copy_window(origin, destination)
WINDOW *origin, *destination;
{
int row, column;
struct _line *orig, *dest;
orig = origin->first_line;
dest = destination->first_line;
for (row = 0;
row < (min(origin->Num_lines, destination->Num_lines));
row++)
{
for (column = 0;
column < (min(origin->Num_cols, destination->Num_cols));
column++)
{
dest->row[column] = orig->row[column];
dest->attributes[column] = orig->attributes[column];
}
dest->changed = orig->changed;
dest->scroll = orig->scroll;
dest->last_char = min(orig->last_char, destination->Num_cols);
orig = orig->next_screen;
dest = dest->next_screen;
}
destination->LX = min((destination->Num_cols - 1), origin->LX);
destination->LY = min((destination->Num_lines - 1), origin->LY);
destination->Attrib = origin->Attrib;
destination->scroll_up = origin->scroll_up;
destination->scroll_down = origin->scroll_down;
destination->SCROLL_CLEAR = origin->SCROLL_CLEAR;
}
void
reinitscr(foo)
int foo;
{
WINDOW *local_virt;
WINDOW *local_std;
WINDOW *local_cur;
signal(SIGWINCH, reinitscr);
#ifdef TIOCGWINSZ
if (ioctl(0, TIOCGWINSZ, &ws) >= 0)
{
if (ws.ws_row == LINES && ws.ws_col == COLS)
return;
if (ws.ws_row > 0)
LINES = ws.ws_row;
if (ws.ws_col > 0)
COLS = ws.ws_col;
}
#endif /* TIOCGWINSZ */
local_virt = newwin(LINES, COLS, 0, 0);
local_std = newwin(LINES, COLS, 0, 0);
local_cur = newwin(LINES, COLS, 0, 0);
copy_window(virtual_scr, local_virt);
copy_window(stdscr, local_std);
copy_window(curscr, local_cur);
delwin(virtual_scr);
delwin(stdscr);
delwin(curscr);
virtual_scr = local_virt;
stdscr = local_std;
curscr = local_cur;
free(virtual_lines);
virtual_lines = (int *) malloc(LINES * (sizeof(int)));
interrupt_flag = TRUE;
}
#endif /* SIGWINCH */
void
initscr() /* initialize terminal for operations */
{
int value;
char *lines_string;
char *columns_string;
#ifdef CAP
char *pointer;
#endif /* CAP */
#ifdef DIAG
printf("starting initscr \n");fflush(stdout);
#endif
if (initialized)
return;
#ifdef BSD_SELECT
setbuf(stdin, NULL);
#endif /* BSD_SELECT */
Flip_Bytes = FALSE;
Parity = 0;
Time_Out = FALSE;
bufp = 0;
Move_It = FALSE;
Noblock = FALSE;
#ifdef SYS5
value = ioctl(0, TCGETA, &Terminal);
if (Terminal.c_cflag & PARENB)
{
if (Terminal.c_cflag & PARENB)
Parity = 1;
else
Parity = 2;
}
if ((Terminal.c_cflag & CS8) == CS8)
{
Num_bits = 8;
}
else if ((Terminal.c_cflag & CS7) == CS7)
Num_bits = 7;
else if ((Terminal.c_cflag & CS6) == CS6)
Num_bits = 6;
else
Num_bits = 5;
value = Terminal.c_cflag & 037;
switch (value) {
case 01: speed = 50.0;
break;
case 02: speed = 75.0;
break;
case 03: speed = 110.0;
break;
case 04: speed = 134.5;
break;
case 05: speed = 150.0;
break;
case 06: speed = 200.0;
break;
case 07: speed = 300.0;
break;
case 010: speed = 600.0;
break;
case 011: speed = 900.0;
break;
case 012: speed = 1200.0;
break;
case 013: speed = 1800.0;
break;
case 014: speed = 2400.0;
break;
case 015: speed = 3600.0;
break;
case 016: speed = 4800.0;
break;
case 017: speed = 7200.0;
break;
case 020: speed = 9600.0;
break;
case 021: speed = 19200.0;
break;
case 022: speed = 38400.0;
break;
default: speed = 0.0;
}
#else
value = ioctl(0, TIOCGETP, &Terminal);
if (Terminal.sg_flags & EVENP)
Parity = 2;
else if (Terminal.sg_flags & ODDP)
Parity = 1;
value = Terminal.sg_ospeed;
switch (value) {
case 01: speed = 50.0;
break;
case 02: speed = 75.0;
break;
case 03: speed = 110.0;
break;
case 04: speed = 134.5;
break;
case 05: speed = 150.0;
break;
case 06: speed = 200.0;
break;
case 07: speed = 300.0;
break;
case 010: speed = 600.0;
break;
case 011: speed = 1200.0;
break;
case 012: speed = 1800.0;
break;
case 013: speed = 2400.0;
break;
case 014: speed = 4800.0;
break;
case 015: speed = 9600.0;
break;
default: speed = 0.0;
}
#endif
chars_per_millisecond = (0.001 * speed) / 8.0;
TERMINAL_TYPE = getenv("TERM");
if (TERMINAL_TYPE == NULL)
{
printf("unknown terminal type\n");
exit(0);
}
#ifndef CAP
Fildes = -1;
TERM_PATH = getenv("TERMINFO");
if (TERM_PATH != NULL)
{
Data_Line_len = 23 + strlen(TERM_PATH) + strlen(TERMINAL_TYPE);
Term_File_name = malloc(Data_Line_len);
sprintf(Term_File_name, "%s/%c/%s", TERM_PATH, *TERMINAL_TYPE, TERMINAL_TYPE);
Fildes = open(Term_File_name, O_RDONLY);
}
if (Fildes == -1)
{
TERM_PATH = "/usr/lib/terminfo";
Data_Line_len = 23 + strlen(TERM_PATH) + strlen(TERMINAL_TYPE);
Term_File_name = malloc(Data_Line_len);
sprintf(Term_File_name, "%s/%c/%s", TERM_PATH, *TERMINAL_TYPE, TERMINAL_TYPE);
Fildes = open(Term_File_name, O_RDONLY);
}
if (Fildes == -1)
{
TERM_PATH = "/usr/share/lib/terminfo";
Data_Line_len = 23 + strlen(TERM_PATH) + strlen(TERMINAL_TYPE);
Term_File_name = malloc(Data_Line_len);
sprintf(Term_File_name, "%s/%c/%s", TERM_PATH, *TERMINAL_TYPE, TERMINAL_TYPE);
Fildes = open(Term_File_name, O_RDONLY);
}
if (Fildes == -1)
{
TERM_PATH = "/usr/share/terminfo";
Data_Line_len = 23 + strlen(TERM_PATH) + strlen(TERMINAL_TYPE);
Term_File_name = malloc(Data_Line_len);
sprintf(Term_File_name, "%s/%c/%s", TERM_PATH, *TERMINAL_TYPE, TERMINAL_TYPE);
Fildes = open(Term_File_name, O_RDONLY);
}
if (Fildes == -1)
{
free(Term_File_name);
Term_File_name = NULL;
}
else
TERM_INFO = INFO_PARSE();
#else
/*
| termcap information can be in the TERMCAP env variable, if so
| use that, otherwise check the /etc/termcap file
*/
if ((pointer = Term_File_name = getenv("TERMCAP")) != NULL)
{
if (*Term_File_name != '/')
Term_File_name = "/etc/termcap";
}
else
{
Term_File_name = "/etc/termcap";
}
if ((TFP = fopen(Term_File_name, "r")) == NULL)
{
printf("unable to open /etc/termcap file \n");
exit(0);
}
for (value = 0; value < 1024; value++)
String_table[value] = NULL;
for (value = 0; value < 128; value++)
Booleans[value] = 0;
for (value = 0; value < 128; value++)
Numbers[value] = 0;
Data_Line = malloc(512);
if (pointer && *pointer != '/')
{
TERM_data_ptr = pointer;
CAP_PARSE();
}
else
{
Find_term();
CAP_PARSE();
}
#endif
if (String_table[pc__] == NULL)
String_table[pc__] = "\0";
if ((String_table[cm__] == NULL) || (Booleans[hc__]))
{
fprintf(stderr, "sorry, unable to use this terminal type for screen editing\n");
exit(0);
}
Key_Get();
keys_vt100();
LINES = Numbers[li__];
COLS = Numbers[co__];
if ((lines_string = getenv("LINES")) != NULL)
{
value = atoi(lines_string);
if (value > 0)
LINES = value;
}
if ((columns_string = getenv("COLUMNS")) != NULL)
{
value = atoi(columns_string);
if (value > 0)
COLS = value;
}
#ifdef TIOCGWINSZ
/*
| get the window size
*/
if (ioctl(0, TIOCGWINSZ, &ws) >= 0)
{
if (ws.ws_row > 0)
LINES = ws.ws_row;
if (ws.ws_col > 0)
COLS = ws.ws_col;
}
#endif
virtual_scr = newwin(LINES, COLS, 0, 0);
stdscr = newwin(LINES, COLS, 0, 0);
curscr = newwin(LINES, COLS, 0, 0);
wmove(stdscr, 0, 0);
werase(stdscr);
Repaint_screen = TRUE;
initialized = TRUE;
virtual_lines = (int *) malloc(LINES * (sizeof(int)));
#ifdef SIGWINCH
/*
| reset size of windows and LINES and COLS if term window
| changes size
*/
signal(SIGWINCH, reinitscr);
#endif /* SIGWINCH */
/*
| check if scrolling is available
*/
nc_scrolling_ability = ((String_table[al__] != NULL) &&
(String_table[dl__])) || ((String_table[cs__])
&& (String_table[sr__]));
}
#ifndef CAP
int
Get_int() /* get a two-byte integer from the terminfo file */
{
int High_byte;
int Low_byte;
int temp;
Low_byte = *((unsigned char *) TERM_data_ptr++);
High_byte = *((unsigned char *) TERM_data_ptr++);
if (Flip_Bytes)
{
temp = Low_byte;
Low_byte = High_byte;
High_byte = temp;
}
if ((High_byte == 255) && (Low_byte == 255))
return (-1);
else
return(Low_byte + (High_byte * 256));
}
int
INFO_PARSE() /* parse off the data in the terminfo data file */
{
int offset;
int magic_number = 0;
int counter = 0;
int Num_names = 0;
int Num_bools = 0;
int Num_ints = 0;
int Num_strings = 0;
int string_table_len = 0;
char *temp_ptr;
TERM_data_ptr = Data_Line = malloc((10240 * (sizeof(char))));
Data_Line_len = read(Fildes, Data_Line, 10240);
if ((Data_Line_len >= 10240) || (Data_Line_len < 0))
return(0);
/*
| get magic number
*/
magic_number = Get_int();
/*
| if magic number not right, reverse byte order and check again
*/
if (magic_number != 282)
{
Flip_Bytes = TRUE;
TERM_data_ptr--;
TERM_data_ptr--;
magic_number = Get_int();
if (magic_number != 282)
return(0);
}
/*
| get the number of each type in the terminfo data file
*/
Num_names = Get_int();
Num_bools = Get_int();
Num_ints = Get_int();
Num_strings = Get_int();
string_table_len = Get_int();
Strings = malloc(string_table_len);
while (Num_names > 0)
{
TERM_data_ptr++;
Num_names--;
}
counter = 0;
while (Num_bools)
{
Num_bools--;
Booleans[counter++] = *TERM_data_ptr++;
}
if (((unsigned int) TERM_data_ptr) & 1) /* force alignment */
TERM_data_ptr++;
counter = 0;
while (Num_ints)
{
Num_ints--;
Numbers[counter] = Get_int();
counter++;
}
temp_ptr = TERM_data_ptr + Num_strings + Num_strings;
memcpy(Strings, temp_ptr, string_table_len);
counter = bt__;
while (Num_strings)
{
Num_strings--;
if ((offset=Get_int()) != -1)
{
if (String_table[counter] == NULL)
String_table[counter] = Strings + offset;
}
else
String_table[counter] = NULL;
counter++;
}
close(Fildes);
free(Data_Line);
return(TRUE);
}
#endif /* ifndef CAP */
int
AtoI() /* convert ascii text to integers */
{
int Temp;
Temp = 0;
while ((*TERM_data_ptr >= '0') && (*TERM_data_ptr <= '9'))
{
Temp = (Temp * 10) + (*TERM_data_ptr - '0');
TERM_data_ptr++;
}
return(Temp);
}
void
Key_Get() /* create linked list with all key sequences obtained from terminal database */
{
int Counter;
int Klen;
int key_def;
struct KEY_STACK *Spoint;
Max_Key_len = 0;
Counter = 0;
key_def = kb__;
while (key_def <= kf63__)
{
if (key_def == ke__)
key_def = K1__;
else if (key_def == (K5__ + 1))
key_def = kcbt__;
else if (key_def == (kcbt__ + 1))
key_def = kbeg__;
else if (key_def == (kUND__ + 1))
key_def = kf11__;
if (String_table[key_def] != NULL)
{
if (KEY_TOS == NULL)
Spoint = KEY_TOS = (struct KEY_STACK *) malloc(sizeof(struct KEY_STACK));
else
{
Spoint = KEY_TOS;
while (Spoint->next != NULL)
Spoint = Spoint->next;
Spoint->next = (struct KEY_STACK *) malloc(sizeof(struct KEY_STACK));
Spoint = Spoint->next;
}
Spoint->next = NULL;
Spoint->element = (struct KEYS *) malloc(sizeof(struct KEYS));
Spoint->element->string = String_table[key_def];
Spoint->element->length = strlen(String_table[key_def]);
Spoint->element->value = Key_vals[Counter];
Klen = strlen(Spoint->element->string);
if (Klen > Max_Key_len)
Max_Key_len = Klen;
/*
| Some terminal types accept keystrokes of the form
| \E[A and \EOA, substituting '[' for 'O'. Make a
| duplicate of such key strings (since the
| database will only have one version) so new_curse
| can understand both.
*/
if ((Spoint->element->length > 1) &&
((String_table[key_def][1] == '[') ||
(String_table[key_def][1] == 'O')))
{
Spoint->next = (struct KEY_STACK *) malloc(sizeof(struct KEY_STACK));
Spoint = Spoint->next;
Spoint->next = NULL;
Spoint->element = (struct KEYS *) malloc(sizeof(struct KEYS));
Spoint->element->length = strlen(String_table[key_def]);
Spoint->element->string = malloc(Spoint->element->length + 1);
strcpy(Spoint->element->string, String_table[key_def]);
Spoint->element->value = Key_vals[Counter];
Klen = strlen(Spoint->element->string);
if (Klen > Max_Key_len)
Max_Key_len = Klen;
if (String_table[key_def][1] == '[')
Spoint->element->string[1] = 'O';
else
Spoint->element->string[1] = '[';
}
}
key_def++;
Counter++;
}
}
/*
| insert information about keys for a vt100 terminal
*/
void
keys_vt100()
{
int counter;
int Klen;
struct KEY_STACK *Spoint;
Spoint = KEY_TOS;
while (Spoint->next != NULL)
Spoint = Spoint->next;
for (counter = 0; vt100[counter].length != 0; counter++)
{
Spoint->next = (struct KEY_STACK *) malloc(sizeof(struct KEY_STACK));
Spoint = Spoint->next;
Spoint->next = NULL;
Spoint->element = &vt100[counter];
Klen = strlen(Spoint->element->string);
if (Klen > Max_Key_len)
Max_Key_len = Klen;
}
}
#ifdef CAP
char *
String_Get(param) /* read the string */
char *param;
{
char *String;
char *Temp;
int Counter;
if (param == NULL)
{
while (*TERM_data_ptr != '=')
TERM_data_ptr++;
Temp = ++TERM_data_ptr;
Counter = 1;
while ((*Temp != ':') && (*Temp != (char)NULL))
{
Counter++;
Temp++;
}
if (Counter == 1) /* no data */
return(NULL);
String = Temp = malloc(Counter);
while ((*TERM_data_ptr != ':') && (*TERM_data_ptr != (char)NULL))
{
if (*TERM_data_ptr == '\\')
{
TERM_data_ptr++;
if (*TERM_data_ptr == 'n')
*Temp = '\n';
else if (*TERM_data_ptr == 't')
*Temp = '\t';
else if (*TERM_data_ptr == 'b')
*Temp = '\b';
else if (*TERM_data_ptr == 'r')
*Temp = '\r';
else if (*TERM_data_ptr == 'f')
*Temp = '\f';
else if ((*TERM_data_ptr == 'e') || (*TERM_data_ptr == 'E'))
*Temp = '\033'; /* escape */
else if (*TERM_data_ptr == '\\')
*Temp = '\\';
else if (*TERM_data_ptr == '\'')
*Temp = '\'';
else if ((*TERM_data_ptr >= '0') && (*TERM_data_ptr <= '9'))
{
Counter = 0;
while ((*TERM_data_ptr >= '0') && (*TERM_data_ptr <= '9'))
{
Counter = (8 * Counter) + (*TERM_data_ptr - '0');
TERM_data_ptr++; /* ? */
}
*Temp = Counter;
TERM_data_ptr--;
}
TERM_data_ptr++;
Temp++;
}
else if (*TERM_data_ptr == '^')
{
TERM_data_ptr++;
if ((*TERM_data_ptr >= '@') && (*TERM_data_ptr <= '_'))
*Temp = *TERM_data_ptr - '@';
else if (*TERM_data_ptr == '?')
*Temp = 127;
TERM_data_ptr++;
Temp++;
}
else
*Temp++ = *TERM_data_ptr++;
}
*Temp = (char)NULL;
param = String;
}
else
{
while ((*TERM_data_ptr != (char)NULL) && (*TERM_data_ptr != ':'))
TERM_data_ptr++;
}
return(param);
}
int
tc_Get_int(param) /* read the integer */
int param;
{
int Itemp;
if (param == 0)
{
while ((*TERM_data_ptr != (char)NULL) && (*TERM_data_ptr != '#'))
TERM_data_ptr++;
TERM_data_ptr++;
Itemp = AtoI();
param = Itemp;
}
else
{
while (*TERM_data_ptr != ':')
TERM_data_ptr++;
}
return(param);
}
void
Find_term() /* find terminal description in termcap file */
{
char *Name;
char *Ftemp;
Ftemp = Name = malloc(strlen(TERMINAL_TYPE + 1) + 1);
strcpy(Name, TERMINAL_TYPE);
while (*Ftemp != (char)NULL)
Ftemp++;
*Ftemp++ = '|';
*Ftemp = (char)NULL;
CFOUND = FALSE;
Data_Line_len = strlen(TERMINAL_TYPE) + 1;
while ((!CFOUND) && ((TERM_data_ptr=fgets(Data_Line, 512, TFP)) != NULL))
{
if ((*TERM_data_ptr != ' ') && (*TERM_data_ptr != '\t') && (*TERM_data_ptr != '#'))
{
while ((!CFOUND) && (*TERM_data_ptr != (char)NULL))
{
CFOUND = !strncmp(TERM_data_ptr, Name, Data_Line_len);
while ((*TERM_data_ptr != (char)NULL) && (*TERM_data_ptr != '|') && (*TERM_data_ptr != '#') && (*TERM_data_ptr != ':'))
TERM_data_ptr++;
if (*TERM_data_ptr == '|')
TERM_data_ptr++;
else if (!CFOUND)
*TERM_data_ptr = (char)NULL;
}
}
}
if (!CFOUND)
{
printf("terminal type %s not found\n", TERMINAL_TYPE);
exit(0);
}
}
void
CAP_PARSE() /* parse off the data in the termcap data file */
{
int offset;
int found;
do
{
while (*TERM_data_ptr != (char)NULL)
{
for (found = FALSE, offset = 0; (!found) && (offset < 26); offset++)
{
if (!strncmp(TERM_data_ptr, Boolean_names[offset], 2))
{
found = TRUE;
Booleans[offset] = TRUE;
}
}
if (!found)
{
for (found = FALSE, offset = 0; (!found) && (offset < lw__); offset++)
{
if (!strncmp(TERM_data_ptr, Number_names[offset], 3))
{
found = TRUE;
Numbers[offset] = tc_Get_int(Numbers[offset]);
}
}
}
if (!found)
{
for (found = FALSE, offset = 0; (!found) && (offset < smgr__); offset++)
{
if (!strncmp(TERM_data_ptr, String_names[offset], 3))
{
found = TRUE;
String_table[offset] = String_Get(String_table[offset]);
}
}
}
if (!strncmp(TERM_data_ptr, "tc=", 3))
tc_ = String_Get(NULL);
while ((*TERM_data_ptr != ':') && (*TERM_data_ptr != (char)NULL))
TERM_data_ptr++;
if (*TERM_data_ptr == ':')
TERM_data_ptr++;
}
} while (((TERM_data_ptr = fgets(Data_Line, 512, TFP)) != NULL) && ((*TERM_data_ptr == ' ') || (*TERM_data_ptr == '\t')));
if (tc_ != NULL)
{
TERMINAL_TYPE = tc_;
rewind(TFP);
Find_term();
free(tc_);
tc_ = NULL;
CAP_PARSE();
}
else
fclose(TFP);
}
#endif /* ifdef CAP */
struct _line *
Screenalloc(columns)
int columns;
{
int i;
struct _line *tmp;
tmp = (struct _line *) malloc(sizeof (struct _line));
tmp->row = malloc(columns + 1);
tmp->attributes = malloc(columns + 1);
tmp->prev_screen = NULL;
tmp->next_screen = NULL;
for (i = 0; i < columns; i++)
{
tmp->row[i] = ' ';
tmp->attributes[i] = (char) NULL;
}
tmp->scroll = tmp->changed = FALSE;
tmp->row[0] = (char) NULL;
tmp->attributes[0] = (char) NULL;
tmp->row[columns] = (char) NULL;
tmp->attributes[columns] = (char) NULL;
tmp->last_char = 0;
return(tmp);
}
WINDOW *newwin(lines, cols, start_l, start_c)
int lines, cols; /* number of lines and columns to be in window */
int start_l, start_c; /* starting line and column to be inwindow */
{
WINDOW *Ntemp;
struct _line *temp_screen;
int i;
Ntemp = (WINDOW *) malloc(sizeof(WINDOW));
Ntemp->SR = start_l;
Ntemp->SC = start_c;
Ntemp->Num_lines = lines;
Ntemp->Num_cols = cols;
Ntemp->LX = 0;
Ntemp->LY = 0;
Ntemp->scroll_down = Ntemp->scroll_up = 0;
Ntemp->SCROLL_CLEAR = FALSE;
Ntemp->Attrib = FALSE;
Ntemp->first_line = temp_screen = Screenalloc(cols);
Ntemp->first_line->number = 0;
for (i = 1; i < lines; i++)
{
temp_screen->next_screen = Screenalloc(cols);
temp_screen->next_screen->number = i;
temp_screen->next_screen->prev_screen = temp_screen;
temp_screen = temp_screen->next_screen;
}
Ntemp->first_line->prev_screen = NULL;
temp_screen->next_screen = NULL;
return(Ntemp);
}
#ifdef CAP
void
Cap_Out(string, p_list, place) /* interpret the output string if necessary */
char *string;
int p_list[]; /* stack of values */
int place; /* place keeper of top of stack */
{
char *Otemp; /* temporary string pointer to parse output */
int delay;
int p1, p2, temp;
float chars;
if (string == NULL)
return;
if (p_list != NULL)
{
p1 = p_list[--place];
p2 = p_list[--place];
}
delay = 0;
Otemp = string;
if ((*Otemp >= '0') && (*Otemp <= '9'))
{
delay = atoi(Otemp);
while ((*Otemp >= '0') && (*Otemp <= '9'))
Otemp++;
if (*Otemp == '*')
Otemp++;
}
while (*Otemp != (char)NULL)
{
if (*Otemp == '%')
{
Otemp++;
if ((*Otemp == 'd') || (*Otemp == '2') || (*Otemp == '3') || (*Otemp == '.') || (*Otemp == '+'))
{
if (*Otemp == 'd')
printf("%d", p1);
else if (*Otemp == '2')
printf("%02d", p1);
else if (*Otemp == '3')
printf("%03d", p1);
else if (*Otemp == '+')
{
Otemp++;
p1 += *Otemp;
putchar(p1);
}
else if (*Otemp == '.')
putchar(p1);
p1 = p2;
p2 = 0;
}
else if (*Otemp == '>')
{
Otemp++;
if (p1 > *Otemp)
{
Otemp++;
p1 += *Otemp;
}
else
Otemp++;
}
else if (*Otemp == 'r')
{
temp = p1;
p1 = p2;
p2 = temp;
}
else if (*Otemp == 'i')
{
p1++;
p2++;
}
else if (*Otemp == '%')
putchar(*Otemp);
else if (*Otemp == 'n')
{
p1 ^= 0140;
p2 ^= 0140;
}
else if (*Otemp == 'B')
{
p1 = (16 * (p1/10)) + (p1 % 10);
p2 = (16 * (p2/10)) + (p2 % 10);
}
else if (*Otemp == 'D')
{
p1 = (p1 - 2 * (p1 % 16));
p2 = (p2 - 2 * (p2 % 16));
}
}
else
putchar (*Otemp);
Otemp++;
}
if (delay != 0)
{
chars = delay * chars_per_millisecond;
delay = chars;
if ((chars - delay) > 0.0)
delay++;
for (; delay > 0; delay--)
putchar(*String_table[pc__]);
}
fflush(stdout);
}
#else
char *Otemp; /* temporary string pointer to parse output */
float chars;
int p[10];
int variable[27];
int
Operation(Temp_Stack, place) /* handle conditional operations */
int Temp_Stack[];
int place;
{
int temp;
if (*Otemp == 'd')
{
Otemp++;
temp = Temp_Stack[--place];
printf("%d", temp);
}
else if (!strncmp(Otemp, "2d", 2))
{
temp = Temp_Stack[--place];
printf("%2d", temp);
Otemp++;
Otemp++;
}
else if (!strncmp(Otemp, "3d", 2))
{
temp = Temp_Stack[--place];
printf("%0d", temp);
Otemp++;
Otemp++;
}
else if (!strncmp(Otemp, "02d", 3))
{
temp = Temp_Stack[--place];
printf("%02d", temp);
Otemp++;
Otemp++;
Otemp++;
}
else if (!strncmp(Otemp, "03d", 3))
{
temp = Temp_Stack[--place];
printf("%03d", temp);
Otemp++;
Otemp++;
Otemp++;
}
else if (*Otemp == '+')
{
Otemp++;
temp = Temp_Stack[--place];
temp += Temp_Stack[--place];
Temp_Stack[place++] = temp;
}
else if (*Otemp == '-')
{
Otemp++;
temp = Temp_Stack[--place];
temp -= Temp_Stack[--place];
Temp_Stack[place++] = temp;
}
else if (*Otemp == '*')
{
Otemp++;
temp = Temp_Stack[--place];
temp *= Temp_Stack[--place];
Temp_Stack[place++] = temp;
}
else if (*Otemp == '/')
{
Otemp++;
temp = Temp_Stack[--place];
temp /= Temp_Stack[--place];
Temp_Stack[place++] = temp;
}
else if (*Otemp == 'm')
{
Otemp++;
temp = Temp_Stack[--place];
temp %= Temp_Stack[--place];
Temp_Stack[place++] = temp;
}
else if (*Otemp == '&')
{
Otemp++;
temp = Temp_Stack[--place];
temp &= Temp_Stack[--place];
Temp_Stack[place++] = temp;
}
else if (*Otemp == '|')
{
Otemp++;
temp = Temp_Stack[--place];
temp |= Temp_Stack[--place];
Temp_Stack[place++] = temp;
}
else if (*Otemp == '^')
{
Otemp++;
temp = Temp_Stack[--place];
temp ^= Temp_Stack[--place];
Temp_Stack[place++] = temp;
}
else if (*Otemp == '=')
{
Otemp++;
temp = Temp_Stack[--place];
temp = (temp == Temp_Stack[--place]);
Temp_Stack[place++] = temp;
}
else if (*Otemp == '>')
{
Otemp++;
temp = Temp_Stack[--place];
temp = temp > Temp_Stack[--place];
Temp_Stack[place++] = temp;
}
else if (*Otemp == '<')
{
Otemp++;
temp = Temp_Stack[--place];
temp = temp < Temp_Stack[--place];
Temp_Stack[place++] = temp;
}
else if (*Otemp == 'c')
{
Otemp++;
putchar(Temp_Stack[--place]);
}
else if (*Otemp == 'i')
{
Otemp++;
p[1]++;
p[2]++;
}
else if (*Otemp == '%')
{
putchar(*Otemp);
Otemp++;
}
else if (*Otemp == '!')
{
temp = ! Temp_Stack[--place];
Temp_Stack[place++] = temp;
Otemp++;
}
else if (*Otemp == '~')
{
temp = ~Temp_Stack[--place];
Temp_Stack[place++] = temp;
Otemp++;
}
else if (*Otemp == 'p')
{
Otemp++;
Temp_Stack[place++] = p[*Otemp - '0'];
Otemp++;
}
else if (*Otemp == 'P')
{
Otemp++;
Temp_Stack[place++] = variable[*Otemp - 'a'];
Otemp++;
}
else if (*Otemp == 'g')
{
Otemp++;
variable[*Otemp - 'a'] = Temp_Stack[--place];
Otemp++;
}
else if (*Otemp == '\'')
{
Otemp++;
Temp_Stack[place++] = *Otemp;
Otemp++;
Otemp++;
}
else if (*Otemp == '{')
{
Otemp++;
temp = atoi(Otemp);
Temp_Stack[place++] = temp;
while (*Otemp != '}')
Otemp++;
Otemp++;
}
return(place);
}
void
Info_Out(string, p_list, place) /* interpret the output string if necessary */
char *string;
int p_list[];
int place;
{
char *tchar;
int delay;
int temp;
int Cond_FLAG;
int EVAL;
int Cond_Stack[128];
int Cond_place;
int Stack[128];
int Top_of_stack;
if (string == NULL)
return;
Cond_FLAG = FALSE;
Cond_place = 0;
Top_of_stack = 0;
p[0] = 0;
p[1] = 0;
p[2] = 0;
p[3] = 0;
p[4] = 0;
p[5] = 0;
p[6] = 0;
p[7] = 0;
p[8] = 0;
p[9] = 0;
if (p_list != NULL)
{
for (temp = 1; (place != 0); temp++)
{
p[temp] = p_list[--place];
}
}
delay = 0;
Otemp = string;
while (*Otemp != (char) NULL)
{
if (*Otemp == '%')
{
Otemp++;
if ((*Otemp == '?') || (*Otemp == 't') || (*Otemp == 'e') || (*Otemp == ';'))
{
if (*Otemp == '?')
{
Otemp++;
Cond_FLAG = TRUE;
EVAL = TRUE;
while (EVAL)
{
/*
| find the end of the
| conditional statement
*/
while ((strncmp(Otemp, "%t", 2)) && (*Otemp != (char) NULL))
{
/*
| move past '%'
*/
Otemp++;
Cond_place = Operation(Cond_Stack, Cond_place);
}
/*
| if condition is true
*/
if ((Cond_place > 0) && (Cond_Stack[Cond_place-1]))
{
/*
| end conditional
| parsing
*/
EVAL = FALSE;
Otemp++;
Otemp++;
}
else /* condition is false */
{
/*
| find 'else' or end
| of if statement
*/
while ((strncmp(Otemp, "%e", 2)) && (strncmp(Otemp, "%;", 2)) && (*Otemp != (char) NULL))
Otemp++;
/*
| if an 'else' found
*/
if ((*Otemp != (char) NULL) && (!strncmp(Otemp, "%e", 2)))
{
Otemp++;
Otemp++;
tchar = Otemp;
/*
| check for 'then' part
*/
while ((*tchar != (char) NULL) && (strncmp(tchar, "%t", 2)) && (strncmp(tchar, "%;", 2)))
tchar++;
/*
| if end of string
*/
if (*tchar == (char) NULL)
{
EVAL = FALSE;
Cond_FLAG = FALSE;
Otemp = tchar;
}
/*
| if end of if found,
| set up to parse
| info
*/
else if (!strncmp(tchar, "%;", 2))
EVAL = FALSE;
/*
| otherwise, check
| conditional in
| 'else'
*/
}
/*
| if end of if found,
| get out of if
| statement
*/
else if ((*Otemp != (char) NULL) && (!strncmp(Otemp, "%;", 2)))
{
EVAL = FALSE;
Otemp++;
Otemp++;
}
else /* Otemp == NULL */
{
EVAL = FALSE;
Cond_FLAG = FALSE;
}
}
}
}
else
{
Otemp++;
Cond_FLAG = FALSE;
if (*Otemp != ';')
{
while ((*Otemp != (char) NULL) && (strncmp(Otemp, "%;", 2)))
Otemp++;
if (*Otemp != (char) NULL)
{
Otemp++;
Otemp++;
}
}
else
Otemp++;
}
}
else
{
Top_of_stack = Operation(Stack, Top_of_stack);
}
}
else if (!strncmp(Otemp, "$<", 2))
{
Otemp++;
Otemp++;
delay = atoi(Otemp);
while (*Otemp != '>')
Otemp++;
Otemp++;
chars = delay * chars_per_millisecond;
delay = chars;
if ((chars - delay) > 0.0)
delay++;
if (String_table[pc__] == NULL)
temp = 0;
else
temp = *String_table[pc__];
for (; delay > 0; delay--)
putc(temp, stdout);
}
else
{
putchar(*Otemp);
Otemp++;
}
}
fflush(stdout);
}
#endif
void
wmove(window, row, column) /* move cursor to indicated position in window */
WINDOW *window;
int row, column;
{
if ((row < window->Num_lines) && (column < window->Num_cols))
{
window->LX = column;
window->LY = row;
}
}
void
clear_line(line, column, cols)
struct _line *line;
int column;
int cols;
{
int j;
if (column > line->last_char)
line->row[line->last_char] = ' ';
line->last_char = column;
line->row[column] = (char) NULL;
line->attributes[column] = (char) NULL;
line->changed = TRUE;
for (j = column + 1; j < cols; j++)
{
line->row[j] = ' ';
line->attributes[j] = (char) NULL;
}
}
void
werase(window) /* clear the specified window */
WINDOW *window;
{
int i;
struct _line *tmp;
window->SCROLL_CLEAR = CLEAR;
window->scroll_up = window->scroll_down = 0;
for (i = 0, tmp = window->first_line; i < window->Num_lines; i++, tmp = tmp->next_screen)
clear_line(tmp, 0, window->Num_cols);
}
void
wclrtoeol(window) /* erase from current cursor position to end of line */
WINDOW *window;
{
int column, row;
struct _line *tmp;
window->SCROLL_CLEAR = CHANGE;
column = window->LX;
row = window->LY;
for (row = 0, tmp = window->first_line; row < window->LY; row++)
tmp = tmp->next_screen;
clear_line(tmp, column, window->Num_cols);
}
void
wrefresh(window) /* flush all previous output */
WINDOW *window;
{
wnoutrefresh(window);
#ifdef DIAG
{
struct _line *temp;
int value;
fprintf(stderr, "columns=%d, lines=%d, SC=%d, SR=%d\n",window->Num_cols, window->Num_lines, window->SC, window->SR);
for (value = 0, temp = window->first_line; value < window->Num_lines; value++, temp = temp->next_screen)
{
if (temp->number == -1)
fprintf(stderr, "line moved ");
if (temp->scroll)
fprintf(stderr, "scroll_x is set: ");
fprintf(stderr, "lc%d=%s|\n", temp->last_char, temp->row);
}
fprintf(stderr, "+-------------------- virtual screen ----------------------------------------+\n");
fprintf(stderr, "columns=%d, lines=%d \n",virtual_scr->Num_cols, virtual_scr->Num_lines);
for (value = 0, temp = virtual_scr->first_line; value < virtual_scr->Num_lines; value++, temp = temp->next_screen)
{
if (temp->number == -1)
fprintf(stderr, "line moved ");
if (temp->scroll)
fprintf(stderr, "scroll_x is set: ");
fprintf(stderr, "lc%d=%s|\n", temp->last_char, temp->row);
}
fprintf(stderr, "columns=%d, lines=%d \n",curscr->Num_cols, curscr->Num_lines);
for (value = 0, temp = curscr->first_line; value < curscr->Num_lines; value++, temp = temp->next_screen)
fprintf(stderr, "line=%s|\n", temp->row);
}
#endif
doupdate();
virtual_scr->SCROLL_CLEAR = FALSE;
virtual_scr->scroll_down = virtual_scr->scroll_up = 0;
fflush(stdout);
}
void
touchwin(window)
WINDOW *window;
{
struct _line *user_line;
int line_counter = 0;
for (line_counter = 0, user_line = window->first_line;
line_counter < window->Num_lines; line_counter++)
{
user_line->changed = TRUE;
}
window->SCROLL_CLEAR = TRUE;
}
void
wnoutrefresh(window)
WINDOW *window;
{
struct _line *user_line;
struct _line *virtual_line;
int line_counter = 0;
int user_col = 0;
int virt_col = 0;
if (window->SR >= virtual_scr->Num_lines)
return;
user_line = window->first_line;
virtual_line = virtual_scr->first_line;
virtual_scr->SCROLL_CLEAR = window->SCROLL_CLEAR;
virtual_scr->LX = window->LX + window->SC;
virtual_scr->LY = window->LY + window->SR;
virtual_scr->scroll_up = window->scroll_up;
virtual_scr->scroll_down = window->scroll_down;
if ((last_window_refreshed == window) && (!window->SCROLL_CLEAR))
return;
for (line_counter = 0; line_counter < window->SR; line_counter++)
{
virtual_line = virtual_line->next_screen;
}
for (line_counter = 0; (line_counter < window->Num_lines)
&& ((line_counter + window->SR) < virtual_scr->Num_lines);
line_counter++)
{
if ((last_window_refreshed != window) || (user_line->changed) || ((SCROLL | CLEAR) & window->SCROLL_CLEAR))
{
for (user_col = 0, virt_col = window->SC;
(virt_col < virtual_scr->Num_cols)
&& (user_col < window->Num_cols);
virt_col++, user_col++)
{
virtual_line->row[virt_col] = user_line->row[user_col];
virtual_line->attributes[virt_col] = user_line->attributes[user_col];
}
}
if (virtual_scr->Num_cols != window->Num_cols)
{
if (virtual_line->last_char < (user_line->last_char + window->SC))
{
if (virtual_line->row[virtual_line->last_char] == (char) NULL)
virtual_line->row[virtual_line->last_char] = ' ';
virtual_line->last_char =
min(virtual_scr->Num_cols,
(user_line->last_char + window->SC));
}
else if (virtual_line->last_char > (user_line->last_char + window->SC))
{
virtual_line->row[min(virtual_scr->Num_cols,
(user_line->last_char + window->SC))] = ' ';
}
}
else
virtual_line->last_char = user_line->last_char;
virtual_line->row[virtual_line->last_char] = (char) NULL;
virtual_line->changed = user_line->changed;
virtual_line = virtual_line->next_screen;
user_line = user_line->next_screen;
}
window->SCROLL_CLEAR = FALSE;
window->scroll_up = window->scroll_down = 0;
last_window_refreshed = window;
}
void
flushinp() /* flush input */
{
}
void
ungetch(c) /* push a character back on input */
int c;
{
if (bufp < 100)
in_buff[bufp++] = c;
}
#ifdef BSD_SELECT
int
timed_getchar()
{
struct timeval tv;
fd_set fds;
int ret_val;
int nfds = 1;
char temp;
FD_ZERO(&fds);
tv.tv_sec = 0;
tv.tv_usec = 500000; /* half a second */
FD_SET(0, &fds);
Time_Out = FALSE; /* just in case */
ret_val = select(nfds, &fds, 0, 0, &tv);
/*
| if ret_val is less than zero, there was no input
| otherwise, get a character and return it
*/
if (ret_val <= 0)
{
Time_Out = TRUE;
return(-1);
}
return(read(STDIN_FILENO, &temp, 1)? temp : -1);
}
#endif
int
wgetch(window) /* get character from specified window */
WINDOW *window;
{
int in_value;
char temp;
#ifndef SYS5
int old_arg;
#endif /* SYS5 */
#ifdef BSD_SELECT
if (Noblock)
in_value = ((bufp > 0) ? in_buff[--bufp] : timed_getchar());
else
in_value = ((bufp > 0) ? in_buff[--bufp] : read(STDIN_FILENO, &temp, 1)? temp : -1);
#else /* BSD_SELECT */
#ifdef SYS5
in_value = ((bufp > 0) ? in_buff[--bufp] :
(read(STDIN_FILENO, &temp, 1)> 0) ? temp : -1);
#else /* SYS5 */
if (Noblock)
{
Time_Out = FALSE;
old_arg = fcntl(0, F_GETFL, 0);
in_value = fcntl(0, F_SETFL, old_arg | FNDELAY);
}
in_value = ((bufp > 0) ? in_buff[--bufp] : read(STDIN_FILENO, &temp, 1)? temp : -1);
if (Noblock)
{
fcntl(0, F_SETFL, old_arg);
if (Time_Out)
in_value = -1;
}
#endif /* SYS5 */
#endif /* BSD_SELECT */
if (in_value != -1)
{
in_value &= 0xff;
if ((Parity) && (Num_bits < 8))
/* strip eighth bit if parity in use */
in_value &= 0177;
}
else if (interrupt_flag)
{
interrupt_flag = FALSE;
in_value = wgetch(window);
}
if ((in_value == '\033') || (in_value == '\037'))/* escape character */
in_value = Get_key(in_value);
return(in_value);
}
#ifndef BSD_SELECT
void
Clear(arg) /* notify that time out has occurred */
int arg;
{
Time_Out = TRUE;
#ifdef DEBUG
fprintf(stderr, "inside Clear()\n");
fflush(stderr);
#endif /* DEBUG */
}
#endif /* BSD_SELECT */
int
Get_key(first_char) /* try to decode key sequence */
int first_char; /* first character of sequence */
{
int in_char;
int Count;
char string[128];
char *Gtemp;
int Found;
#ifdef SYS5
struct termio Gterminal;
#else
struct sgttyb Gterminal;
#endif
struct KEY_STACK *St_point;
#if (!defined( BSD_SELECT)) || (!defined(SYS5))
int value;
#endif /* BSD_SELECT */
Count = 0;
Gtemp = string;
string[Count++] = first_char;
string[Count] = (char) NULL;
Time_Out = FALSE;
#ifndef BSD_SELECT
signal(SIGALRM, Clear);
value = alarm(1);
#endif /* BSD_SELECT */
Noblock = TRUE;
#ifdef SYS5
Gterminal.c_cc[VTIME] = 0; /* timeout value */
Gterminal.c_lflag &= ~ICANON; /* disable canonical operation */
Gterminal.c_lflag &= ~ECHO; /* disable echo */
#endif
Count = 1;
Found = FALSE;
while ((Count < Max_Key_len) && (!Time_Out) && (!Found))
{
in_char = wgetch(stdscr);
#ifdef DEBUG
fprintf(stderr, "back in GetKey()\n");
fflush(stderr);
#endif /* DEBUG */
if (in_char != -1)
{
string[Count++] = in_char;
string[Count] = (char) NULL;
St_point = KEY_TOS;
while ((St_point != NULL) && (!Found))
{
if (!strcmp(string, St_point->element->string))
Found = TRUE;
else
St_point = St_point->next;
}
}
}
#ifndef BSD_SELECT
if (!Time_Out)
value = alarm(0);
#endif /* BSD_SELECT */
#ifdef SYS5
/* value = ioctl(0, TCSETA, &Terminal);*/
#else
value = ioctl(0, TIOCSETP, &Terminal);
/* value = fcntl(0, F_SETFL, old_arg);*/
#endif
Noblock = FALSE;
if (Found)
{
return(St_point->element->value);
}
else
{
while (Count > 1)
{
if ((string[--Count] != -1) &&
((unsigned char) (string[Count]) != 255))
{
#ifdef DIAG
fprintf(stderr, "ungetting character %d\n", string[Count]);fflush(stdout);
#endif
ungetch(string[Count]);
}
}
return(first_char);
}
}
void
waddch(window, c) /* output the character in the specified window */
WINDOW *window;
int c;
{
int row, column;
int shift; /* number of spaces to shift if a tab */
struct _line *tmpline;
#ifdef DIAG
/*printf("starting waddch \n");fflush(stdout);*/
#endif
row = window->LY;
column = window->LX;
if (c == '\t')
{
shift = (column + 1) % 8;
if (shift == 0)
shift++;
else
shift = 9 - shift;
while (shift > 0)
{
shift--;
waddch(window, ' ');
}
}
else if ((column < window->Num_cols) && (row < window->Num_lines))
{
if ((c == '~') && (Booleans[hz__]))
c = '@';
if (( c != '\b') && (c != '\n') && (c != '\r'))
{
row = 0;
tmpline = window->first_line;
while (row < window->LY)
{
row++;
tmpline = tmpline->next_screen;
}
tmpline->row[column] = c;
tmpline->attributes[column] = window->Attrib;
tmpline->changed = TRUE;
if (column >= tmpline->last_char)
{
if (column > tmpline->last_char)
tmpline->row[tmpline->last_char] = ' ';
tmpline->row[column + 1] = (char) NULL;
tmpline->attributes[column + 1] = (char) NULL;
tmpline->last_char = column + 1;
}
}
if (c == '\n')
{
wclrtoeol(window);
window->LX = window->Num_cols;
}
else if (c == '\r')
window->LX = 0;
else if (c == '\b')
window->LX--;
else
window->LX++;
}
if (window->LX >= window->Num_cols)
{
window->LX = 0;
window->LY++;
if (window->LY >= window->Num_lines)
{
window->LY = window->Num_lines - 1;
/* window->LY = row;
wmove(window, 0, 0);
wdeleteln(window);
wmove(window, row, 0);*/
}
}
window->SCROLL_CLEAR = CHANGE;
}
void
winsertln(window) /* insert a blank line into the specified window */
WINDOW *window;
{
int row, column;
struct _line *tmp;
struct _line *tmp1;
window->scroll_down += 1;
window->SCROLL_CLEAR = SCROLL;
column = window->LX;
row = window->LY;
for (row = 0, tmp = window->first_line; (row < window->Num_lines) && (tmp->next_screen != NULL); row++)
tmp = tmp->next_screen;
if (tmp->prev_screen != NULL)
tmp->prev_screen->next_screen = NULL;
tmp1 = tmp;
clear_line(tmp1, 0, window->Num_cols);
tmp1->number = -1;
for (row = 0, tmp = window->first_line; (row < window->LY) && (tmp->next_screen != NULL); row++)
tmp = tmp->next_screen;
if ((window->LY == (window->Num_lines - 1)) && (window->Num_lines > 1))
{
tmp1->next_screen = tmp->next_screen;
tmp->next_screen = tmp1;
tmp->changed = TRUE;
tmp->next_screen->prev_screen = tmp;
}
else if (window->Num_lines > 1)
{
if (tmp->prev_screen != NULL)
tmp->prev_screen->next_screen = tmp1;
tmp1->prev_screen = tmp->prev_screen;
tmp->prev_screen = tmp1;
tmp1->next_screen = tmp;
tmp->changed = TRUE;
tmp->scroll = DOWN;
}
if (window->LY == 0)
window->first_line = tmp1;
}
void
wdeleteln(window) /* delete a line in the specified window */
WINDOW *window;
{
int row, column;
struct _line *tmp;
struct _line *tmpline;
if (window->Num_lines > 1)
{
window->scroll_up += 1;
window->SCROLL_CLEAR = SCROLL;
column = window->LX;
row = window->LY;
for (row = 0, tmp = window->first_line; row < window->LY; row++)
tmp = tmp->next_screen;
if (window->LY == 0)
window->first_line = tmp->next_screen;
if (tmp->prev_screen != NULL)
tmp->prev_screen->next_screen = tmp->next_screen;
if (tmp->next_screen != NULL)
{
tmp->next_screen->changed = TRUE;
tmp->next_screen->scroll = UP;
tmp->next_screen->prev_screen = tmp->prev_screen;
}
tmpline = tmp;
clear_line(tmpline, 0, window->Num_cols);
tmpline->number = -1;
for (row = 0, tmp = window->first_line; tmp->next_screen != NULL; row++)
tmp = tmp->next_screen;
if (tmp != NULL)
{
tmp->next_screen = tmpline;
tmp->next_screen->prev_screen = tmp;
tmp->changed = TRUE;
tmp = tmp->next_screen;
}
else
tmp = tmpline;
tmp->next_screen = NULL;
}
else
{
clear_line(window->first_line, 0, window->Num_cols);
}
}
void
wclrtobot(window) /* delete from current position to end of the window */
WINDOW *window;
{
int row, column;
struct _line *tmp;
window->SCROLL_CLEAR |= CLEAR;
column = window->LX;
row = window->LY;
for (row = 0, tmp = window->first_line; row < window->LY; row++)
tmp = tmp->next_screen;
clear_line(tmp, column, window->Num_cols);
for (row = (window->LY + 1); row < window->Num_lines; row++)
{
tmp = tmp->next_screen;
clear_line(tmp, 0, window->Num_cols);
}
wmove(window, row, column);
}
void
wstandout(window) /* begin standout mode in window */
WINDOW *window;
{
if (Numbers[sg__] < 1) /* if not magic cookie glitch */
window->Attrib |= A_STANDOUT;
}
void
wstandend(window) /* end standout mode in window */
WINDOW *window;
{
window->Attrib &= ~A_STANDOUT;
}
void
waddstr(window, string) /* write 'string' in window */
WINDOW *window;
char *string;
{
char *wstring;
for (wstring = string; *wstring != (char) NULL; wstring++)
waddch(window, *wstring);
}
void
clearok(window, flag) /* erase screen and redraw at next refresh */
WINDOW *window;
int flag;
{
Repaint_screen = TRUE;
}
void
echo() /* turn on echoing */
{
int value;
#ifdef SYS5
Terminal.c_lflag |= ECHO; /* enable echo */
value = ioctl(0, TCSETA, &Terminal); /* set characteristics */
#else
Terminal.sg_flags |= ECHO; /* enable echo */
value = ioctl(0, TIOCSETP, &Terminal); /* set characteristics */
#endif
}
void
noecho() /* turn off echoing */
{
int value;
#ifdef SYS5
Terminal.c_lflag &= ~ECHO; /* disable echo */
value = ioctl(0, TCSETA, &Terminal); /* set characteristics */
#else
Terminal.sg_flags &= ~ECHO; /* disable echo */
value = ioctl(0, TIOCSETP, &Terminal); /* set characteristics */
#endif
}
void
raw() /* set to read characters immediately */
{
int value;
#ifdef SYS5
Intr = Terminal.c_cc[VINTR]; /* get the interrupt character */
Terminal.c_lflag &= ~ICANON; /* disable canonical operation */
Terminal.c_lflag &= ~ISIG; /* disable signal checking */
#ifdef FLUSHO
Terminal.c_lflag &= ~FLUSHO;
#endif
#ifdef PENDIN
Terminal.c_lflag &= ~PENDIN;
#endif
#ifdef IEXTEN
Terminal.c_lflag &= ~IEXTEN;
#endif
Terminal.c_cc[VMIN] = 1; /* minimum of one character */
Terminal.c_cc[VTIME] = 255; /* timeout value */
Terminal.c_cc[VINTR] = 0; /* eliminate interrupt */
value = ioctl(0, TCSETA, &Terminal); /* set characteristics */
#else
Terminal.sg_flags |= RAW; /* enable raw mode */
value = ioctl(0, TIOCSETP, &Terminal); /* set characteristics */
#endif
}
void
noraw() /* set to normal character read mode */
{
int value;
#ifdef SYS5
Terminal.c_lflag |= ICANON; /* enable canonical operation */
Terminal.c_lflag |= ISIG; /* enable signal checking */
Terminal.c_cc[VEOF] = 4; /* EOF character = 4 */
Terminal.c_cc[VEOL] = (char) NULL; /* EOL = 0 */
Terminal.c_cc[VINTR] = Intr; /* reset interrupt char */
value = ioctl(0, TCSETA, &Terminal); /* set characteristics */
#else
Terminal.sg_flags &= ~RAW; /* disable raw mode */
value = ioctl(0, TIOCSETP, &Terminal); /* set characteristics */
/* old_arg = fcntl(0, F_GETFL, 0);
value = fcntl(0, F_SETFL, old_arg & ~FNDELAY);*/
#endif
}
void
nl()
{
int value;
#ifdef SYS5
Terminal.c_iflag |= ICRNL; /* enable carriage-return to line-feed mapping */
value = ioctl(0, TCSETA, &Terminal); /* set characteristics */
#endif
}
void
nonl()
{
int value;
#ifdef SYS5
Terminal.c_iflag &= ~ICRNL; /* disable carriage-return to line-feed mapping */
Terminal.c_iflag &= ~IGNCR; /* do not ignore carriage-return */
value = ioctl(0, TCSETA, &Terminal); /* set characteristics */
#endif
}
void
saveterm()
{
}
void
fixterm()
{
}
void
resetterm()
{
}
void
nodelay(window, flag)
WINDOW *window;
int flag;
{
}
void
idlok(window, flag)
WINDOW *window;
int flag;
{
}
void
keypad(window, flag)
WINDOW *window;
int flag;
{
if (flag)
String_Out(String_table[ks__], NULL, 0);
else
String_Out(String_table[ke__], NULL, 0);
}
void
savetty() /* save current tty stats */
{
int value;
#ifdef SYS5
value = ioctl(0, TCGETA, &Saved_tty); /* set characteristics */
#else
value = ioctl(0, TIOCGETP, &Saved_tty); /* set characteristics */
#endif
}
void
resetty() /* restore previous tty stats */
{
int value;
#ifdef SYS5
value = ioctl(0, TCSETA, &Saved_tty); /* set characteristics */
#else
value = ioctl(0, TIOCSETP, &Saved_tty); /* set characteristics */
#endif
}
void
endwin() /* end windows */
{
keypad(stdscr, FALSE);
initialized = FALSE;
delwin(curscr);
delwin(virtual_scr);
delwin(stdscr);
#ifndef SYS5
{
int old_arg, value;
/* old_arg = fcntl(0, F_GETFL, 0);
value = fcntl(0, F_SETFL, old_arg & ~FNDELAY);*/
}
#endif
}
void
delwin(window) /* delete the window structure */
WINDOW *window;
{
int i;
for (i = 1; (i < window->Num_lines) && (window->first_line->next_screen != NULL); i++)
{
window->first_line = window->first_line->next_screen;
free(window->first_line->prev_screen->row);
free(window->first_line->prev_screen->attributes);
free(window->first_line->prev_screen);
}
if (window == last_window_refreshed)
last_window_refreshed = 0;
if (window->first_line != NULL)
{
free(window->first_line->row);
free(window->first_line->attributes);
free(window->first_line);
free(window);
}
}
#ifndef __STDC__
void
wprintw(va_alist)
va_dcl
#else /* __STDC__ */
void
wprintw(WINDOW *window, const char *format, ...)
#endif /* __STDC__ */
{
#ifndef __STDC__
WINDOW *window;
char *format;
va_list ap;
#else
va_list ap;
#endif
int value;
char *fpoint;
char *wtemp;
#ifndef __STDC__
va_start(ap);
window = va_arg(ap, WINDOW *);
format = va_arg(ap, char *);
#else /* __STDC__ */
va_start(ap, format);
#endif /* __STDC__ */
fpoint = (char *) format;
while (*fpoint != (char) NULL)
{
if (*fpoint == '%')
{
fpoint++;
if (*fpoint == 'd')
{
value = va_arg(ap, int);
iout(window, value);
}
else if (*fpoint == 'c')
{
value = va_arg(ap, int);
waddch(window, value);
}
else if (*fpoint == 's')
{
wtemp = va_arg(ap, char *);
waddstr(window, wtemp);
}
fpoint++;
}
else if (*fpoint == '\\')
{
fpoint++;
if (*fpoint == 'n')
waddch(window, '\n');
else if ((*fpoint >= '0') && (*fpoint <= '9'))
{
value = 0;
while ((*fpoint >= '0') && (*fpoint <= '9'))
{
value = (value * 8) + (*fpoint - '0');
fpoint++;
}
waddch(window, value);
}
fpoint++;
}
else
waddch(window, *fpoint++);
}
#ifdef __STDC__
va_end(ap);
#endif /* __STDC__ */
}
void
iout(window, value) /* output characters */
WINDOW *window;
int value;
{
int i;
if ((i = value / 10) != 0)
iout(window, i);
waddch(window, ((value % 10) + '0'));
}
int
Comp_line(line1, line2) /* compare lines */
struct _line *line1;
struct _line *line2;
{
int count1, count2;
int i;
char *att1, *att2;
char *c1, *c2;
c1 = line1->row;
c2 = line2->row;
att1 = line1->attributes;
att2 = line2->attributes;
count2 = strlen(c1) + 1;
count1 = strlen(c2) + 1;
if (count1 > count2)
{
i = count2;
count2 = count1;
count1 = i;
}
if (count2 > (count1 + count1))
return(2);
i = 0;
while ((c1[i] != (char) NULL) && (c2[i] != (char) NULL) && (c1[i] == c2[i]) && (att1[i] == att2[i]))
i++;
count1 = i + 1;
if ((count1 == 1) && (count2 == 1))
count1 = 0; /* both lines blank */
else if (count2 == count1)
count1 = -1; /* equal */
else
count1 = count2 / count1; /* lines unequal */
return(count1);
}
struct _line *
Insert_line(row, end_row, window) /* insert line into screen */
int row;
int end_row;
WINDOW *window;
{
int i;
struct _line *tmp;
struct _line *tmp1;
for (i = 0, tmp = curscr->first_line; i < window->SR; i++)
tmp = tmp->next_screen;
if ((end_row + window->SR) == 0)
curscr->first_line = curscr->first_line->next_screen;
top_of_win = tmp;
/*
| find bottom line to delete
*/
for (i = 0, tmp = top_of_win; (tmp->next_screen != NULL) && (i < end_row); i++)
tmp = tmp->next_screen;
if (tmp->prev_screen != NULL)
tmp->prev_screen->next_screen = tmp->next_screen;
if (tmp->next_screen != NULL)
tmp->next_screen->prev_screen = tmp->prev_screen;
tmp1 = tmp;
/*
| clear deleted line
*/
clear_line(tmp, 0, window->Num_cols);
tmp1->number = -1;
for (i = 0, tmp = curscr->first_line; (tmp->next_screen != NULL) && (i < window->SR); i++)
tmp = tmp->next_screen;
top_of_win = tmp;
for (i = 0, tmp = top_of_win; i < row; i++)
tmp = tmp->next_screen;
if ((tmp->prev_screen != NULL) && (window->Num_lines > 0))
tmp->prev_screen->next_screen = tmp1;
tmp1->prev_screen = tmp->prev_screen;
tmp->prev_screen = tmp1;
tmp1->next_screen = tmp;
if ((row + window->SR) == 0)
curscr->first_line = tmp1;
if (tmp1->next_screen != NULL)
tmp1 = tmp1->next_screen;
if ((!String_table[cs__]) && (end_row < window->Num_lines))
{
Position(window, (window->SR + end_row), 0);
String_Out(String_table[dl__], NULL, 0);
}
Position(window, (window->SR + row), 0);
if (String_table[al__] != NULL)
String_Out(String_table[al__], NULL, 0);
else
String_Out(String_table[sr__], NULL, 0);
for (i = 0, top_of_win = curscr->first_line; (top_of_win->next_screen != NULL) && (i < window->SR); i++)
top_of_win = top_of_win->next_screen;
return(tmp1);
}
struct _line *
Delete_line(row, end_row, window) /* delete a line on screen */
int row;
int end_row;
WINDOW *window;
{
int i;
struct _line *tmp;
struct _line *tmp1;
struct _line *tmp2;
i = 0;
tmp = curscr->first_line;
while (i < window->SR)
{
i++;
tmp = tmp->next_screen;
}
/*
| find line to delete
*/
top_of_win = tmp;
if ((row + window->SR) == 0)
curscr->first_line = top_of_win->next_screen;
for (i = 0, tmp = top_of_win; i < row; i++)
tmp = tmp->next_screen;
if (tmp->prev_screen != NULL)
tmp->prev_screen->next_screen = tmp->next_screen;
if (tmp->next_screen != NULL)
tmp->next_screen->prev_screen = tmp->prev_screen;
tmp2 = tmp->next_screen;
tmp1 = tmp;
/*
| clear deleted line
*/
clear_line(tmp1, 0, window->Num_cols);
tmp1->number = -1;
/*
| find location to insert deleted line
*/
for (i = 0, tmp = curscr->first_line; (tmp->next_screen != NULL) && (i < window->SR); i++)
tmp = tmp->next_screen;
top_of_win = tmp;
for (i = 0, tmp = top_of_win; (i < end_row) && (tmp->next_screen != NULL); i++)
tmp = tmp->next_screen;
tmp1->next_screen = tmp;
tmp1->prev_screen = tmp->prev_screen;
if (tmp1->prev_screen != NULL)
tmp1->prev_screen->next_screen = tmp1;
tmp->prev_screen = tmp1;
Position(window, (window->SR + row), 0);
String_Out(String_table[dl__], NULL, 0);
if ((!String_table[cs__]) && (end_row < window->Num_lines))
{
Position(window, (window->SR + end_row), 0);
String_Out(String_table[al__], NULL, 0);
}
else if ((String_table[cs__] != NULL) && (String_table[dl__] == NULL))
{
Position(window, (window->SR + end_row), 0);
putchar('\n');
}
if (row == (window->Num_lines-1))
tmp2 = tmp1;
if ((row + window->SR) == 0)
curscr->first_line = top_of_win = tmp2;
return(tmp2);
}
void
CLEAR_TO_EOL(window, row, column)
WINDOW *window;
int row, column;
{
int x, y;
struct _line *tmp1;
for (y = 0, tmp1 = curscr->first_line; (y < (window->SR+row)) && (tmp1->next_screen != NULL); y++)
tmp1 = tmp1->next_screen;
for (x = column; x<window->Num_cols; x++)
{
tmp1->row[x] = ' ';
tmp1->attributes[x] = (char) NULL;
}
tmp1->row[column] = (char) NULL;
tmp1->last_char = column;
if (column < COLS)
{
if (STAND)
{
STAND = FALSE;
Position(window, row, column);
attribute_off();
}
if (String_table[ce__] != NULL)
String_Out(String_table[ce__], NULL, 0);
else
{
for (x = column; x < window->Num_cols; x++)
putchar(' ');
Curr_x = x;
}
}
}
int
check_delete(window, line, offset, pointer_new, pointer_old)
WINDOW *window;
int line, offset;
struct _line *pointer_new, *pointer_old;
{
int end_old;
int end_new;
int k;
int changed;
char *old_lin;
char *new_lin;
char *old_att;
char *new_att;
changed = FALSE;
new_lin = pointer_new->row;
new_att = pointer_new->attributes;
old_lin = pointer_old->row;
old_att = pointer_old->attributes;
end_old = end_new = offset;
while (((new_lin[end_new] != old_lin[end_old]) || (new_att[end_new] != old_att[end_old])) && (old_lin[end_old] != (char) NULL) && (new_lin[end_old] != (char) NULL))
end_old++;
if (old_lin[end_old] != (char) NULL)
{
k = 0;
while ((old_lin[end_old+k] == new_lin[end_new+k]) && (new_att[end_new+k] == old_att[end_old+k]) && (new_lin[end_new+k] != (char) NULL) && (old_lin[end_old+k] != (char) NULL) && (k < 10))
k++;
if ((k > 8) || ((new_lin[end_new+k] == (char) NULL) && (k != 0)))
{
if (new_lin[end_new+k] == (char) NULL)
{
Position(window, line, (end_new+k));
CLEAR_TO_EOL(window, line, (end_new+k));
}
Position(window, line, offset);
for (k = offset; k < end_old; k++)
Char_del(old_lin, old_att, offset, window->Num_cols);
while ((old_lin[offset] != (char) NULL) && (offset < COLS))
offset++;
pointer_old->last_char = offset;
changed = TRUE;
}
}
return(changed);
}
/*
| Check if characters were inserted in the middle of a line, and if
| so, insert them.
*/
int
check_insert(window, line, offset, pointer_new, pointer_old)
WINDOW *window;
int line, offset;
struct _line *pointer_new, *pointer_old;
{
int changed;
int end_old, end_new;
int k;
int same = FALSE;
int old_off;
int insert;
char *old_lin;
char *new_lin;
char *old_att;
char *new_att;
changed = FALSE;
new_lin = pointer_new->row;
new_att = pointer_new->attributes;
old_lin = pointer_old->row;
old_att = pointer_old->attributes;
end_old = end_new = offset;
while (((new_lin[end_new] != old_lin[end_old]) || (new_att[end_new] != old_att[end_old])) && (new_lin[end_new] != (char) NULL) && (old_lin[end_new] != (char) NULL))
end_new++;
if (new_lin[end_new] != (char) NULL)
{
k = 0;
while ((old_lin[end_old+k] == new_lin[end_new+k]) && (old_att[end_old+k] == new_att[end_new+k]) && (new_lin[end_new+k] != (char) NULL) && (old_lin[end_old+k] != (char) NULL) && (k < 10))
k++;
/*
| check for commonality between rest of lines (are the old
| and new lines the same, except for a chunk in the middle?)
| if the rest of the lines are common, do not insert text
*/
old_off = end_new;
while ((old_lin[old_off] != (char) NULL) && (new_lin[old_off] != (char) NULL) && (old_lin[old_off] == new_lin[old_off]) && (old_att[old_off] == new_att[old_off]))
old_off++;
if ((old_lin[old_off] == new_lin[old_off]) && (old_att[old_off] == new_att[old_off]))
same = TRUE;
if ((!same) && ((k > 8) || ((new_lin[end_new+k] == (char) NULL) && (k != 0))))
{
Position(window, line, offset);
insert = FALSE;
if (String_table[ic__] == NULL)
{
String_Out(String_table[im__], NULL, 0);
insert = TRUE;
}
for (k = offset; k < end_new; k++)
{
if (!insert)
String_Out(String_table[ic__], NULL, 0);
Char_ins(old_lin, old_att, new_lin[k], new_att[k], k, window->Num_cols);
}
if (insert)
String_Out(String_table[ei__], NULL, 0);
while ((old_lin[offset] != (char) NULL) && (offset < COLS))
offset++;
pointer_old->last_char = offset;
changed = TRUE;
}
}
return(changed);
}
void
doupdate()
{
WINDOW *window;
int similar;
int diff;
int begin_old, begin_new;
int end_old, end_new;
int count1, j;
int from_top, tmp_ft, offset;
int changed;
int first_time;
int first_same;
int last_same;
int list[10];
struct _line *curr;
struct _line *virt;
struct _line *old;
struct _line *new;
char *cur_lin;
char *vrt_lin;
char *cur_att;
char *vrt_att;
char *att1, *att2;
char *c1, *c2;
char NC_chinese = FALSE; /* flag to indicate handling Chinese */
window = virtual_scr;
if ((nc_attributes & A_NC_BIG5) != 0)
NC_chinese = TRUE;
if (Repaint_screen)
{
if (String_table[cl__])
String_Out(String_table[cl__], NULL, 0);
else
{
from_top = 0;
while (from_top < LINES)
{
Position(curscr, from_top, 0);
if (String_table[ce__] != NULL)
String_Out(String_table[ce__], NULL, 0);
else
{
for (j = 0; j < window->Num_cols; j++)
putchar(' ');
}
from_top++;
}
}
for (from_top = 0, curr = curscr->first_line; from_top < curscr->Num_lines; from_top++, curr = curr->next_screen)
{
Position(curscr, from_top, 0);
for (j = 0; (curr->row[j] != (char) NULL) && (j < curscr->Num_cols); j++)
{
Char_out(curr->row[j], curr->attributes[j], curr->row, curr->attributes, j);
}
if (STAND)
{
STAND = FALSE;
Position(curscr, from_top, j);
attribute_off();
}
}
Repaint_screen = FALSE;
}
similar = 0;
diff = FALSE;
top_of_win = curscr->first_line;
for (from_top = 0, curr = top_of_win, virt = window->first_line;
from_top < window->Num_lines; from_top++)
{
virtual_lines[from_top] = TRUE;
if ((similar = Comp_line(curr, virt)) > 0)
{
virtual_lines[from_top] = FALSE;
diff = TRUE;
}
curr = curr->next_screen;
virt = virt->next_screen;
}
from_top = 0;
virt = window->first_line;
curr = top_of_win;
similar = 0;
/*
| if the window has lines that are different, check for scrolling
*/
if (diff)
{
last_same = -1;
changed = FALSE;
for (first_same = window->Num_lines;
(first_same > from_top) && (virtual_lines[first_same - 1]);
first_same--)
;
count1 = first_same - 1;
for (last_same = 0;
(last_same < window->Num_lines) && (virtual_lines[last_same]== FALSE);
last_same++)
;
while ((from_top < first_same) && nc_scrolling_ability)
/* check entire lines for diffs */
{
if (from_top >= last_same)
{
for (last_same = from_top;
(last_same < window->Num_lines) &&
(virtual_lines[last_same] == FALSE);
last_same++)
;
}
if (!virtual_lines[from_top])
{
diff = TRUE;
/*
| check for lines deleted (scroll up)
*/
for (tmp_ft = from_top+1, old = curr->next_screen;
((window->scroll_up) && (diff) &&
(tmp_ft < last_same) &&
(!virtual_lines[tmp_ft]));
tmp_ft++)
{
if ((Comp_line(old, virt) == -1) && (!virtual_lines[from_top]))
{
if (String_table[cs__]) /* scrolling region */
{
list[1] = from_top;
list[0] = min((last_same - 1), (window->Num_lines - 1));
String_Out(String_table[cs__], list, 2);
Curr_y = Curr_x = -1;
}
for (offset = (tmp_ft - from_top); (offset > 0); offset--)
{
old = Delete_line(from_top, min((last_same - 1), (window->Num_lines - 1)), window);
diff = FALSE;
}
if (String_table[cs__]) /* scrolling region */
{
list[1] = 0;
list[0] = LINES - 1;
String_Out(String_table[cs__], list, 2);
Curr_y = Curr_x = -1;
}
top_of_win = curscr->first_line;
curr = top_of_win;
for (offset = 0; offset < from_top; offset++)
curr = curr->next_screen;
for (offset = from_top, old=curr, new=virt;
offset < window->Num_lines;
old=old->next_screen, new=new->next_screen,
offset++)
{
similar = Comp_line(old, new);
virtual_lines[offset] = (similar > 0 ? FALSE : TRUE);
}
}
else
old = old->next_screen;
}
/*
| check for lines inserted (scroll down)
*/
for (tmp_ft = from_top-1, old = curr->prev_screen;
((window->scroll_down) && (tmp_ft >= 0) &&
(diff) &&
(!virtual_lines[tmp_ft]));
tmp_ft--)
{
if (Comp_line(old, virt) == -1)
{
if (String_table[cs__]) /* scrolling region */
{
list[1] = tmp_ft;
list[0] = min((last_same - 1), (window->Num_lines - 1));
String_Out(String_table[cs__], list, 2);
Curr_y = Curr_x = -1;
}
for (offset = (from_top - tmp_ft); (offset > 0); offset--)
{
old = Insert_line(tmp_ft, min((last_same - 1), (window->Num_lines -1)), window);
diff = FALSE;
}
if (String_table[cs__]) /* scrolling region */
{
list[1] = 0;
list[0] = LINES - 1;
String_Out(String_table[cs__], list, 2);
Curr_y = Curr_x = -1;
}
top_of_win = curscr->first_line;
curr = top_of_win;
for (offset = 0; offset < from_top; offset++)
curr = curr->next_screen;
for (offset = from_top, old=curr, new=virt;
offset < window->Num_lines;
old=old->next_screen, new=new->next_screen,
offset++)
{
similar = Comp_line(old, new);
virtual_lines[offset] = (similar > 0 ? FALSE : TRUE);
}
}
else
old = old->prev_screen;
}
}
from_top++;
curr = curr->next_screen;
virt = virt->next_screen;
}
}
/*
| Scrolling done, now need to insert, delete, or modify text
| within lines.
*/
for (from_top = 0, curr = curscr->first_line; from_top < window->SR; from_top++)
curr = curr->next_screen;
top_of_win = curr;
for (from_top = 0, curr = top_of_win, virt = window->first_line; from_top < window->Num_lines; from_top++, curr = curr->next_screen, virt = virt->next_screen)
{
/*
| If either 'insert mode' or 'insert char' are
| available, enter the following 'if' statement,
| else, need to simply rewrite the contents of the line
| at the point where the contents of the line change.
*/
if (((String_table[ic__]) || (String_table[im__])) &&
(String_table[dc__]) && (curr->row[0] != (char) NULL) &&
(!NC_chinese))
{
j = 0;
first_time = TRUE;
vrt_lin = virt->row;
vrt_att = virt->attributes;
cur_lin = curr->row;
cur_att = curr->attributes;
while ((vrt_lin[j] != (char) NULL) && (j < window->Num_cols))
{
if ((STAND) && (Booleans[xs__]))
{
while ((vrt_lin[j] == cur_lin[j]) && (vrt_att[j] == cur_att[j]) && (vrt_lin[j] != (char) NULL) && (vrt_att[j]))
j++;
if ((STAND) && (!vrt_att[j]))
{
STAND = FALSE;
Position(window, from_top, j);
attribute_off();
attribute_off();
}
}
else
{
while ((vrt_lin[j] == cur_lin[j]) && (vrt_att[j] == cur_att[j]) && (vrt_lin[j] != (char) NULL))
j++;
}
if ((vrt_att[j] != cur_att[j]) && (cur_att[j]) && (Booleans[xs__]))
{
Position(window, from_top, j);
/* CLEAR_TO_EOL(window, from_top, j);*/
attribute_off();
attribute_off();
}
if (vrt_lin[j] != (char) NULL)
{
begin_new = j;
begin_old = j;
end_old = j;
end_new = j;
if ((first_time) && (virt->changed))
{
if (curr->last_char <= virt->last_char)
changed = check_insert(window, from_top, j, virt, curr);
}
changed = check_delete(window, from_top, j, virt, curr);
first_time = FALSE;
virt->changed = FALSE;
if (!changed)
changed = check_insert(window, from_top, j, virt, curr);
if (((!changed) || (cur_lin[j] != vrt_lin[j]) || (cur_att[j] != vrt_att[j])) && (j < window->Num_cols))
{
if ((vrt_lin[j] == ' ') && (cur_lin[j] == (char) NULL) && (vrt_att[j] == cur_att[j]))
cur_lin[j] = ' ';
else
{
Position(window, from_top, j);
Char_out(vrt_lin[j], vrt_att[j], cur_lin, cur_att, j);
}
}
if ((vrt_lin[j] != (char) NULL))
j++;
}
if ((STAND) && (!vrt_att[j]))
{
STAND = FALSE;
Position(window, from_top, j);
attribute_off();
}
}
if ((vrt_lin[j] == (char) NULL) && (cur_lin[j] != (char) NULL))
{
Position(window, from_top, j);
CLEAR_TO_EOL(window, from_top, j);
}
}
else /*if ((similar != -1) && (similar != 0))*/
{
j = 0;
c1 = curr->row;
att1 = curr->attributes;
c2 = virt->row;
att2 = virt->attributes;
while ((j < window->Num_cols) && (c2[j] != (char) NULL))
{
while ((c1[j] == c2[j]) && (att1[j] == att2[j]) && (j < window->Num_cols) && (c2[j] != (char) NULL))
j++;
/*
| if previous character is an eight bit
| char, start redraw from that character
*/
if ((NC_chinese) && (highbitset(c1[j - 1])))
j--;
begin_old = j;
begin_new = j;
if ((j < window->Num_cols) && (c2[j] != (char) NULL))
{
Position(window, from_top, begin_old);
CLEAR_TO_EOL(window, from_top, j);
Position(window, from_top, begin_old);
for (j = begin_old; (c2[j] != (char) NULL) && (j < window->Num_cols); j++)
Char_out(c2[j], att2[j], c1, att1, j);
}
}
if ((c2[j] == (char) NULL) && (c1[j] != (char) NULL))
{
Position(window, from_top, j);
CLEAR_TO_EOL(window, from_top, j);
}
}
if (STAND)
{
STAND = FALSE;
Position(window, from_top, j);
attribute_off();
}
virt->number = from_top;
}
Position(window, window->LY, window->LX);
}
void
Position(window, row, col) /* position the cursor for output on the screen */
WINDOW *window;
int row;
int col;
{
int list[10];
int place;
int pos_row;
int pos_column;
pos_row = row + window->SR;
pos_column = col + window->SC;
if ((pos_row != Curr_y) || (pos_column != Curr_x))
{
if (String_table[cm__] != NULL) /* && (row < window->Num_lines) && (column < window->Num_cols))*/
{
place = 0;
list[place++] = pos_column;
list[place++] = pos_row;
String_Out(String_table[cm__], list, place);
if ((STAND) && (!Booleans[ms__]))
attribute_on();
}
Curr_x = pos_column;
Curr_y = pos_row;
}
}
void
Char_del(line, attrib, offset, maxlen) /* delete chars from line */
char *line;
char *attrib;
int offset;
int maxlen;
{
int one, two;
for (one = offset, two = offset+1; (line[one] != (char) NULL) && (one < maxlen); one++, two++)
{
line[one] = line[two];
attrib[one] = attrib[two];
}
String_Out(String_table[dc__], NULL, 0);
}
void
Char_ins(line, attrib, newc, newatt, offset, maxlen) /* insert chars in line */
char *line;
char *attrib;
char newc;
char newatt;
int offset;
int maxlen;
{
int one, two;
one = 0;
while ((line[one] != (char) NULL) && (one < (maxlen - 2)))
one++;
for (two = one + 1; (two > offset); one--, two--)
{
line[two] = line[one];
attrib[two] = attrib[one];
}
line[offset] = newc;
attrib[offset] = newatt;
Char_out(newc, newatt, line, attrib, offset);
}
void
attribute_on()
{
if (String_table[sa__])
{
attributes_set[0] = 1;
String_Out(String_table[sa__], attributes_set, 1);
}
else if (String_table[so__])
String_Out(String_table[so__], NULL, 0);
}
void
attribute_off()
{
if (String_table[me__])
String_Out(String_table[me__], NULL, 0);
else if (String_table[sa__])
{
attributes_set[0] = 0;
String_Out(String_table[sa__], attributes_set, 1);
}
else if (String_table[se__])
String_Out(String_table[se__], NULL, 0);
}
void
Char_out(newc, newatt, line, attrib, offset) /* output character with proper attribute */
char newc;
char newatt;
char *line;
char *attrib;
int offset;
{
if ((newatt) && (!STAND))
{
STAND = TRUE;
attribute_on();
}
else if ((STAND) && (!newatt))
{
STAND = FALSE;
attribute_off();
}
if ((newatt) && (STAND) && (Booleans[xs__]))
{
attribute_on();
}
if (!((Curr_y >= (LINES - 1)) && (Curr_x >= (COLS - 1))))
{
putchar(newc);
line[offset] = newc;
attrib[offset] = newatt;
}
Curr_x++;
}
/*
|
| The two routines that follow, nc_setattrib(), nc_clearattrib(), are
| hacks that notify new_curse to handle characters that have the high
| bit set as the first of two bytes of a multi-byte string.
|
*/
void
nc_setattrib(flag)
int flag;
{
nc_attributes |= flag;
}
void
nc_clearattrib(flag)
int flag;
{
nc_attributes &= ~flag;
}