1 /*
2  |	new_curse.c
3  |
4  |	A subset of curses developed for use with ae.
5  |
6  |	written by Hugh Mahon
7  |
8  |	THIS MATERIAL IS PROVIDED "AS IS".  THERE ARE
9  |	NO WARRANTIES OF ANY KIND WITH REGARD TO THIS
10  |	MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE
11  |	IMPLIED WARRANTIES OF MERCHANTABILITY AND
12  |	FITNESS FOR A PARTICULAR PURPOSE.  Neither
13  |	Hewlett-Packard nor Hugh Mahon shall be liable
14  |	for errors contained herein, nor for
15  |	incidental or consequential damages in
16  |	connection with the furnishing, performance or
17  |	use of this material.  Neither Hewlett-Packard
18  |	nor Hugh Mahon assumes any responsibility for
19  |	the use or reliability of this software or
20  |	documentation.  This software and
21  |	documentation is totally UNSUPPORTED.  There
22  |	is no support contract available.  Hewlett-
23  |	Packard has done NO Quality Assurance on ANY
24  |	of the program or documentation.  You may find
25  |	the quality of the materials inferior to
26  |	supported materials.
27  |
28  |	This software is not a product of Hewlett-Packard, Co., or any
29  |	other company.  No support is implied or offered with this software.
30  |	You've got the source, and you're on your own.
31  |
32  |	This software may be distributed under the terms of Larry Wall's
33  |	Artistic license, a copy of which is included in this distribution.
34  |
35  |	This notice must be included with this software and any derivatives.
36  |
37  |	Copyright (c) 1986, 1987, 1988, 1991, 1992, 1993, 1994, 1995 Hugh Mahon
38  |	All are rights reserved.
39  |
40  |	$Header: /home/hugh/sources/old_ae/RCS/new_curse.c,v 1.54 2002/09/21 00:47:14 hugh Exp $
41  |
42  */
43 
44 char *copyright_message[] = { "Copyright (c) 1986, 1987, 1988, 1991, 1992, 1993, 1994, 1995 Hugh Mahon",
45 				"All rights are reserved."};
46 
47 char * new_curse_name= "@(#) new_curse.c $Revision: 1.54 $";
48 
49 #include "new_curse.h"
50 #include <signal.h>
51 #include <fcntl.h>
52 
53 #ifdef SYS5
54 #include <string.h>
55 #else
56 #include <strings.h>
57 #endif
58 
59 #ifdef BSD_SELECT
60 #include <sys/types.h>
61 #include <sys/time.h>
62 
63 #ifdef SLCT_HDR
64 #include <sys/select.h>  /* on AIX */
65 #endif /* SLCT_HDR */
66 
67 #endif /* BSD_SELECT */
68 
69 #ifdef HAS_STDLIB
70 #include <stdlib.h>
71 #endif
72 
73 #if defined(__STDC__)
74 #include <stdarg.h>
75 #else
76 #include <varargs.h>
77 #endif
78 
79 #ifdef HAS_UNISTD
80 #include <unistd.h>
81 #endif
82 
83 #ifdef HAS_SYS_IOCTL
84 #include <sys/ioctl.h>
85 #endif
86 
87 
88 WINDOW *curscr;
89 static WINDOW *virtual_scr;
90 WINDOW *stdscr;
91 WINDOW *last_window_refreshed;
92 
93 #ifdef TIOCGWINSZ
94 	struct winsize ws;
95 #endif
96 
97 #define min(a, b)	(a < b ? a : b)
98 #define highbitset(a)	((a) & 0x80)
99 
100 #ifndef CAP
101 #define String_Out(table, stack, place) Info_Out(table, stack, place)
102 #else
103 #define String_Out(table, stack, place) Cap_Out(table, stack, place)
104 #endif
105 
106 #define bw__ 0	/* booleans	*/
107 #define am__ 1
108 #define xb__ 2
109 #define xs__ 3	/* hp glitch (standout not erased by overwrite)	*/
110 #define xn__ 4
111 #define eo__ 5
112 #define gn__ 6	/* generic type terminal	*/
113 #define hc__ 7	/* hardcopy terminal		*/
114 #define km__ 8
115 #define hs__ 9
116 #define in__ 10
117 #define da__ 11
118 #define db__ 12
119 #define mi__ 13	/* safe to move during insert mode	*/
120 #define ms__ 14	/* safe to move during standout mode	*/
121 #define os__ 15
122 #define es__ 16
123 #define xt__ 17
124 #define hz__ 18	/* hazeltine glitch	*/
125 #define ul__ 19
126 #define xo__ 20
127 #define chts__ 21
128 #define nxon__ 22
129 #define nrrmc__ 23
130 #define npc__ 24
131 #define mc5i__ 25
132 
133 #define co__ 0	/* number of columns	*/	/* numbers		*/
134 #define it__ 1	/* spaces per tab	*/
135 #define li__ 2	/* number of lines	*/
136 #define lm__ 3
137 #define sg__ 4	/* magic cookie glitch	*/
138 #define pb__ 5
139 #define vt__ 6
140 #define ws__ 7
141 
142 #define cols__ 0
143 #define lines__ 2
144 #define xmc__ 4
145 #define vt__ 6
146 #define wsl__ 7
147 #define nlab__ 8
148 #define lh__ 9
149 #define lw__ 10
150 
151 #define bt__ 0	/* back tab		*/	/* strings	*/
152 #define bl__ 1	/* bell			*/
153 #define cr__ 2	/* carriage return	*/
154 #define cs__ 3	/* change scroll region	*/
155 #define ct__ 4	/* clear all tab stops	*/
156 #define cl__ 5	/* clear screen and home cursor	*/
157 #define ce__ 6	/* clear to end of line	*/
158 #define cd__ 7	/* clear to end of display	*/
159 #define ch__ 8	/* set cursor column	*/
160 #define CC__ 9	/* term, settable cmd char in 	*/
161 #define cm__ 10	/* screen rel cursor motion, row, column	*/
162 #define do__ 11	/* down one line	*/
163 #define ho__ 12	/* home cursor	*/
164 #define vi__ 13	/* make cursor invisible	*/
165 #define le__ 14	/* move cursor left one space	*/
166 #define CM__ 15	/* memory rel cursor addressing	*/
167 #define ve__ 16	/* make cursor appear normal	*/
168 #define nd__ 17	/* non-destructive space (cursor right)	*/
169 #define ll__ 18	/* last line, first col	*/
170 #define up__ 19	/* cursor up		*/
171 #define vs__ 20
172 #define dc__ 21	/* delete character	*/
173 #define dl__ 22	/* delete line		*/
174 #define ds__ 23
175 #define hd__ 24
176 #define as__ 25
177 #define mb__ 26
178 #define md__ 27	/* turn on bold		*/
179 #define ti__ 28
180 #define dm__ 29	/* turn on delete mode	*/
181 #define mh__ 30	/* half bright mode	*/
182 #define im__ 31	/* insert mode		*/
183 #define mk__ 32
184 #define mp__ 33
185 #define mr__ 34
186 #define so__ 35	/* enter standout mode	*/
187 #define us__ 36
188 #define ec__ 37
189 #define ae__ 38
190 #define me__ 39
191 #define te__ 40
192 #define ed__ 41
193 #define ei__ 42	/* exit insert mode	*/
194 #define se__ 43	/* exit standout mode	*/
195 #define ue__ 44
196 #define vb__ 45
197 #define ff__ 46
198 #define fs__ 47
199 #define i1__ 48
200 #define i2__ 49
201 #define i3__ 50
202 #define if__ 51
203 #define ic__ 52
204 #define al__ 53
205 #define ip__ 54
206 #define kb__ 55		/* backspace key	*/
207 #define ka__ 56
208 #define kC__ 57
209 #define kt__ 58
210 #define kD__ 59
211 #define kL__ 60
212 #define kd__ 61
213 #define kM__ 62
214 #define kE__ 63
215 #define kS__ 64
216 #define k0__ 65
217 #define k1__ 66
218 #define kf10__ 67
219 #define k2__ 68
220 #define k3__ 69
221 #define k4__ 70
222 #define k5__ 71
223 #define k6__ 72
224 #define k7__ 73
225 #define k8__ 74
226 #define k9__ 75
227 #define kh__ 76
228 #define kI__ 77
229 #define kA__ 78
230 #define kl__ 79
231 #define kH__ 80
232 #define kN__ 81
233 #define kP__ 82
234 #define kr__ 83
235 #define kF__ 84
236 #define kR__ 85
237 #define kT__ 86
238 #define ku__ 87	/* key up	*/
239 #define ke__ 88
240 #define ks__ 89
241 #define l0__ 90
242 #define l1__ 91
243 #define la__ 92
244 #define l2__ 93
245 #define l3__ 94
246 #define l4__ 95
247 #define l5__ 96
248 #define l6__ 97
249 #define l7__ 98
250 #define l8__ 99
251 #define l9__ 100
252 #define mo__ 101
253 #define mm__ 102
254 #define nw__ 103
255 #define pc__ 104
256 #define DC__ 105
257 #define DL__ 106
258 #define DO__ 107
259 #define IC__ 118
260 #define SF__ 109
261 #define AL__ 110
262 #define LE__ 111
263 #define RI__ 112
264 #define SR__ 113
265 #define UP__ 114
266 #define pk__ 115
267 #define pl__ 116
268 #define px__ 117
269 #define ps__ 118
270 #define pf__ 119
271 #define po__ 120
272 #define rp__ 121
273 #define r1__ 122
274 #define r2__ 123
275 #define r3__ 124
276 #define rf__ 125
277 #define rc__ 126
278 #define cv__ 127
279 #define sc__ 128
280 #define sf__ 129
281 #define sr__ 130
282 #define sa__ 131	/* sgr	*/
283 #define st__ 132
284 #define wi__ 133
285 #define ta__ 134
286 #define ts__ 135
287 #define uc__ 136
288 #define hu__ 137
289 #define iP__ 138
290 #define K1__ 139
291 #define K2__ 140
292 #define K3__ 141
293 #define K4__ 142
294 #define K5__ 143
295 #define pO__ 144
296 #define ml__ 145
297 #define mu__ 146
298 #define rmp__ 145
299 #define acsc__ 146
300 #define pln__ 147
301 #define kcbt__ 148
302 #define smxon__ 149
303 #define rmxon__ 150
304 #define smam__ 151
305 #define rmam__ 152
306 #define xonc__ 153
307 #define xoffc__ 154
308 #define enacs__ 155
309 #define smln__ 156
310 #define rmln__ 157
311 #define kbeg__ 158
312 #define kcan__ 159
313 #define kclo__ 160
314 #define kcmd__ 161
315 #define kcpy__ 162
316 #define kcrt__ 163
317 #define kend__ 164
318 #define kent__ 165
319 #define kext__ 166
320 #define kfnd__ 167
321 #define khlp__ 168
322 #define kmrk__ 169
323 #define kmsg__ 170
324 #define kmov__ 171
325 #define knxt__ 172
326 #define kopn__ 173
327 #define kopt__ 174
328 #define kprv__ 175
329 #define kprt__ 176
330 #define krdo__ 177
331 #define kref__ 178
332 #define krfr__ 179
333 #define krpl__ 180
334 #define krst__ 181
335 #define kres__ 182
336 #define ksav__ 183
337 #define kspd__ 184
338 #define kund__ 185
339 #define kBEG__ 186
340 #define kCAN__ 187
341 #define kCMD__ 188
342 #define kCPY__ 189
343 #define kCRT__ 190
344 #define kDC__ 191
345 #define kDL__ 192
346 #define kslt__ 193
347 #define kEND__ 194
348 #define kEOL__ 195
349 #define kEXT__ 196
350 #define kFND__ 197
351 #define kHLP__ 198
352 #define kHOM__ 199
353 #define kIC__ 200
354 #define kLFT__ 201
355 #define kMSG__ 202
356 #define kMOV__ 203
357 #define kNXT__ 204
358 #define kOPT__ 205
359 #define kPRV__ 206
360 #define kPRT__ 207
361 #define kRDO__ 208
362 #define kRPL__ 209
363 #define kRIT__ 210
364 #define kRES__ 211
365 #define kSAV__ 212
366 #define kSPD__ 213
367 #define kUND__ 214
368 #define rfi__ 215
369 #define kf11__ 216
370 #define kf12__ 217
371 #define kf13__ 218
372 #define kf14__ 219
373 #define kf15__ 220
374 #define kf16__ 221
375 #define kf17__ 222
376 #define kf18__ 223
377 #define kf19__ 224
378 #define kf20__ 225
379 #define kf21__ 226
380 #define kf22__ 227
381 #define kf23__ 228
382 #define kf24__ 229
383 #define kf25__ 230
384 #define kf26__ 231
385 #define kf27__ 232
386 #define kf28__ 233
387 #define kf29__ 234
388 #define kf30__ 235
389 #define kf31__ 236
390 #define kf32__ 237
391 #define kf33__ 238
392 #define kf34__ 239
393 #define kf35__ 240
394 #define kf36__ 241
395 #define kf37__ 242
396 #define kf38__ 243
397 #define kf39__ 244
398 #define kf40__ 245
399 #define kf41__ 246
400 #define kf42__ 247
401 #define kf43__ 248
402 #define kf44__ 249
403 #define kf45__ 250
404 #define kf46__ 251
405 #define kf47__ 252
406 #define kf48__ 253
407 #define kf49__ 254
408 #define kf50__ 255
409 #define kf51__ 256
410 #define kf52__ 257
411 #define kf53__ 258
412 #define kf54__ 259
413 #define kf55__ 260
414 #define kf56__ 261
415 #define kf57__ 262
416 #define kf58__ 263
417 #define kf59__ 264
418 #define kf60__ 265
419 #define kf61__ 266
420 #define kf62__ 267
421 #define kf63__ 268
422 #define el1__ 269
423 #define mgc__ 270
424 #define smgl__ 271
425 #define smgr__ 272
426 
427 #ifdef CAP
428 char *Boolean_names[] = {
429 "bw", "am", "xb", "xs", "xn", "eo", "gn", "hc", "km", "hs", "in", "da", "db",
430 "mi", "ms", "os", "es", "xt", "hz", "ul", "xo", "HC", "nx", "NR", "NP", "5i"
431 };
432 
433 char *Number_names[] = {
434 "co#", "it#", "li#", "lm#", "sg#", "pb#", "vt#", "ws#", "Nl#", "lh#", "lw#"
435 };
436 
437 char *String_names[] = {
438 "bt=", "bl=", "cr=", "cs=", "ct=", "cl=", "ce=", "cd=", "ch=", "CC=", "cm=",
439 "do=", "ho=", "vi=", "le=", "CM=", "ve=", "nd=", "ll=", "up=", "vs=", "dc=",
440 "dl=", "ds=", "hd=", "as=", "mb=", "md=", "ti=", "dm=", "mh=", "im=", "mk=",
441 "mp=", "mr=", "so=", "us=", "ec=", "ae=", "me=", "te=", "ed=", "ei=", "se=",
442 "ue=", "vb=", "ff=", "fs=", "i1=", "i2=", "i3=", "if=", "ic=", "al=", "ip=",
443 "kb=", "ka=", "kC=", "kt=", "kD=", "kL=", "kd=", "kM=", "kE=", "kS=", "k0=",
444 "k1=", "k;=", "k2=", "k3=", "k4=", "k5=", "k6=", "k7=", "k8=", "k9=", "kh=",
445 "kI=", "kA=", "kl=", "kH=", "kN=", "kP=", "kr=", "kF=", "kR=", "kT=", "ku=",
446 "ke=", "ks=", "l0=", "l1=", "la=", "l2=", "l3=", "l4=", "l5=", "l6=", "l7=",
447 "l8=", "l9=", "mo=", "mm=", "nw=", "pc=", "DC=", "DL=", "DO=", "IC=", "SF=",
448 "AL=", "LE=", "RI=", "SR=", "UP=", "pk=", "pl=", "px=", "ps=", "pf=", "po=",
449 "rp=", "r1=", "r2=", "r3=", "rf=", "rc=", "cv=", "sc=", "sf=", "sr=", "sa=",
450 "st=", "wi=", "ta=", "ts=", "uc=", "hu=", "iP=", "K1=", "K3=", "K2=", "K4=",
451 "K5=", "pO=", "rP=", "ac=", "pn=", "kB=", "SX=", "RX=", "SA=", "RA=", "XN=",
452 "XF=", "eA=", "LO=", "LF=", "@1=", "@2=", "@3=", "@4=", "@5=", "@6=", "@7=",
453 "@8=", "@9=", "@0=", "%1=", "%2=", "%3=", "%4=", "%5=", "%6=", "%7=", "%8=",
454 "%9=", "%0=", "&1=", "&2=", "&3=", "&4=", "&5=", "&6=", "&7=", "&8=", "&9=",
455 "&0=", "*1=", "*2=", "*3=", "*4=", "*5=", "*6=", "*7=", "*8=", "*9=", "*0=",
456 "#1=", "#2=", "#3=", "#4=", "%a=", "%b=", "%c=", "%d=", "%e=", "%f=", "%g=",
457 "%h=", "%i=", "%j=", "!1=", "!2=", "!3=", "RF=", "F1=", "F2=", "F3=", "F4=",
458 "F5=", "F6=", "F7=", "F8=", "F9=", "FA=", "FB=", "FC=", "FD=", "FE=", "FF=",
459 "FG=", "FH=", "FI=", "FJ=", "FK=", "FL=", "FM=", "FN=", "FO=", "FP=", "FQ=",
460 "FR=", "FS=", "FT=", "FU=", "FV=", "FW=", "FX=", "FY=", "FZ=", "Fa=", "Fb=",
461 "Fc=", "Fd=", "Fe=", "Ff=", "Fg=", "Fh=", "Fi=", "Fj=", "Fk=", "Fl=", "Fm=",
462 "Fn=", "Fo=", "Fp=", "Fq=", "Fr=", "cb=", "MC=", "ML=", "MR="
463 };
464 #endif
465 
466 char *new_curse = "October 1987";
467 
468 char in_buff[100];	/* buffer for ungetch			*/
469 int bufp;		/* next free position in in_buff	*/
470 
471 char *TERMINAL_TYPE = NULL; /* terminal type to be gotten from environment	*/
472 int CFOUND = FALSE;
473 int Data_Line_len = 0;
474 int Max_Key_len;	/* max length of a sequence sent by a key	*/
475 char *Data_Line = NULL;
476 char *TERM_PATH = NULL;
477 char *TERM_data_ptr = NULL;
478 char *Term_File_name = NULL;	/* name of file containing terminal description	*/
479 FILE *TFP;		/* file pointer to file with terminal des.	*/
480 int Fildes;		/* file descriptor for terminfo file		*/
481 int STAND = FALSE;	/* is standout mode activated?			*/
482 int TERM_INFO = FALSE;	/* is terminfo being used (TRUE), or termcap (FALSE) */
483 int Time_Out;	/* set when time elapsed while trying to read function key */
484 int Curr_x;		/* current x position on screen			*/
485 int Curr_y;		/* current y position on the screen		*/
486 int LINES;
487 int COLS;
488 int Move_It;		/* flag to move cursor if magic cookie glitch	*/
489 int initialized = FALSE;	/* tells whether new_curse is initialized	*/
490 float speed;
491 float chars_per_millisecond;
492 int Repaint_screen;	/* if an operation to change screen impossible, repaint screen	*/
493 int Intr;		/* storeage for interrupt character		*/
494 int Parity;		/* 0 = no parity, 1 = odd parity, 2 = even parity */
495 int Noblock;		/* for BSD systems				*/
496 int Num_bits;	/* number of bits per character	*/
497 int Flip_Bytes;	/* some systems have byte order reversed	*/
498 int interrupt_flag = FALSE;	/* set true if SIGWINCH received	*/
499 
500 #ifndef CAP
501 char *Strings;
502 #endif
503 
504 #if !defined(TERMCAP)
505 #define TERMCAP "/etc/termcap"
506 #endif
507 
508 struct KEYS {
509 	int length;	/* length of string sent by key			*/
510 	char *string;	/* string sent by key				*/
511 	int value;	/* CURSES value of key (9-bit)			*/
512 	};
513 
514 struct KEY_STACK {
515 	struct KEYS *element;
516 	struct KEY_STACK *next;
517 	};
518 
519 struct KEY_STACK *KEY_TOS = NULL;
520 struct KEY_STACK *KEY_POINT;
521 
522 /*
523  |
524  |	Not all systems have good terminal information, so we will define
525  |	keyboard information here for the most widely used terminal type,
526  |	the VT100.
527  |
528  */
529 
530 struct KEYS vt100[] =
531 	{
532 		{ 3, "\033[A", 0403 },	/* key up 	*/
533 		{ 3, "\033[C", 0405 },	/* key right	*/
534 		{ 3, "\033[D", 0404 },	/* key left	*/
535 
536 		{ 4, "\033[6~", 0522 },	/* key next page	*/
537 		{ 4, "\033[5~", 0523 },	/* key prev page	*/
538 		{ 3, "\033[[", 0550 },	/* key end	*/
539 		{ 3, "\033[@", 0406 },	/* key home	*/
540 		{ 4, "\033[2~", 0513 },	/* key insert char	*/
541 
542 		{ 3, "\033[y", 0410 },	/* key F0	*/
543 		{ 3, "\033[P", 0411 },	/* key F1	*/
544 		{ 3, "\033[Q", 0412 },	/* key F2	*/
545 		{ 3, "\033[R", 0413 },	/* key F3	*/
546 		{ 3, "\033[S", 0414 },	/* key F4	*/
547 		{ 3, "\033[t", 0415 },	/* key F5	*/
548 		{ 3, "\033[u", 0416 },	/* key F6	*/
549 		{ 3, "\033[v", 0417 },	/* key F7	*/
550 		{ 3, "\033[l", 0420 },	/* key F8	*/
551 		{ 3, "\033[w", 0421 },	/* key F9	*/
552 		{ 3, "\033[x", 0422 },	/* key F10	*/
553 
554 		{ 5, "\033[10~", 0410 },	/* key F0	*/
555 		{ 5, "\033[11~", 0411 },	/* key F1	*/
556 		{ 5, "\033[12~", 0412 },	/* key F2	*/
557 		{ 5, "\033[13~", 0413 },	/* key F3	*/
558 		{ 5, "\033[14~", 0414 },	/* key F4	*/
559 		{ 5, "\033[15~", 0415 },	/* key F5	*/
560 		{ 5, "\033[17~", 0416 },	/* key F6	*/
561 		{ 5, "\033[18~", 0417 },	/* key F7	*/
562 		{ 5, "\033[19~", 0420 },	/* key F8	*/
563 		{ 5, "\033[20~", 0421 },	/* key F9	*/
564 		{ 5, "\033[21~", 0422 },	/* key F10	*/
565 		{ 5, "\033[23~", 0423 },	/* key F11	*/
566 		{ 5, "\033[24~", 0424 },	/* key F12	*/
567 		{ 3, "\033[q", 0534 },	/* ka1 upper-left of keypad	*/
568 		{ 3, "\033[s", 0535 },	/* ka3 upper-right of keypad	*/
569 		{ 3, "\033[r", 0536 },	/* kb2 center of keypad	*/
570  		{ 3, "\033[p", 0537 },	/* kc1 lower-left of keypad	*/
571 		{ 3, "\033[n", 0540 },	/* kc3 lower-right of keypad	*/
572 
573 		/*
574 		 |	The following are the same keys as above, but with
575 		 |	a different character following the escape char.
576 		 */
577 
578 		{ 3, "\033OA", 0403 },	/* key up 	*/
579 		{ 3, "\033OC", 0405 },	/* key right	*/
580 		{ 3, "\033OD", 0404 },	/* key left	*/
581 		{ 3, "\033OB", 0402 },	/* key down	*/
582 		{ 4, "\033O6~", 0522 },	/* key next page	*/
583 		{ 4, "\033O5~", 0523 },	/* key prev page	*/
584 		{ 3, "\033O[", 0550 },	/* key end	*/
585 		{ 3, "\033O@", 0406 },	/* key home	*/
586 		{ 4, "\033O2~", 0513 },	/* key insert char	*/
587 
588 		{ 3, "\033Oy", 0410 },	/* key F0	*/
589 		{ 3, "\033OP", 0411 },	/* key F1	*/
590 		{ 3, "\033OQ", 0412 },	/* key F2	*/
591 		{ 3, "\033OR", 0413 },	/* key F3	*/
592 		{ 3, "\033OS", 0414 },	/* key F4	*/
593 		{ 3, "\033Ot", 0415 },	/* key F5	*/
594 		{ 3, "\033Ou", 0416 },	/* key F6	*/
595 		{ 3, "\033Ov", 0417 },	/* key F7	*/
596 		{ 3, "\033Ol", 0420 },	/* key F8	*/
597 		{ 3, "\033Ow", 0421 },	/* key F9	*/
598 		{ 3, "\033Ox", 0422 },	/* key F10	*/
599 
600 		{ 5, "\033O10~", 0410 },	/* key F0	*/
601 		{ 5, "\033O11~", 0411 },	/* key F1	*/
602 		{ 5, "\033O12~", 0412 },	/* key F2	*/
603 		{ 5, "\033O13~", 0413 },	/* key F3	*/
604 		{ 5, "\033O14~", 0414 },	/* key F4	*/
605 		{ 5, "\033O15~", 0415 },	/* key F5	*/
606 		{ 5, "\033O17~", 0416 },	/* key F6	*/
607 		{ 5, "\033O18~", 0417 },	/* key F7	*/
608 		{ 5, "\033O19~", 0420 },	/* key F8	*/
609 		{ 5, "\033O20~", 0421 },	/* key F9	*/
610 		{ 5, "\033O21~", 0422 },	/* key F10	*/
611 		{ 5, "\033O23~", 0423 },	/* key F11	*/
612 		{ 5, "\033O24~", 0424 },	/* key F12	*/
613 		{ 3, "\033Oq", 0534 },	/* ka1 upper-left of keypad	*/
614 		{ 3, "\033Os", 0535 },	/* ka3 upper-right of keypad	*/
615 		{ 3, "\033Or", 0536 },	/* kb2 center of keypad	*/
616  		{ 3, "\033Op", 0537 },	/* kc1 lower-left of keypad	*/
617 		{ 3, "\033On", 0540 },	/* kc3 lower-right of keypad	*/
618 
619 		{ 0, "", 0 }	/* end	*/
620 	};
621 
622 struct Parameters {
623 	int value;
624 	struct Parameters *next;
625 	};
626 
627 int Key_vals[] = {
628 	0407, 0526, 0515, 0525, 0512, 0510, 0402, 0514, 0517, 0516, 0410, 0411,
629 	0422, 0412, 0413, 0414, 0415, 0416, 0417, 0420, 0421, 0406, 0513, 0511,
630 	0404, 0533, 0522, 0523, 0405, 0520, 0521, 0524, 0403,
631 	0534, 0535, 0536, 0537, 0540, 0541, 0542, 0543, 0544, 0545, 0546, 0547,
632 	0550, 0527, 0551, 0552, 0553, 0554, 0555, 0556, 0557, 0560, 0561, 0562,
633 	0532, 0563, 0564, 0565, 0566, 0567, 0570, 0571, 0627, 0630, 0572, 0573,
634 	0574, 0575, 0576, 0577, 0600, 0601, 0602, 0603, 0604, 0605, 0606, 0607,
635 	0610, 0611, 0612, 0613, 0614, 0615, 0616, 0617, 0620, 0621, 0622, 0623,
636 	0624, 0625, 0626, 0423, 0424, 0425, 0426, 0427, 0430, 0431,
637 	0432, 0433, 0434, 0435, 0436, 0437, 0440, 0441, 0442, 0443, 0444, 0445,
638 	0446, 0447, 0450, 0451, 0452, 0453, 0454, 0455, 0456, 0457, 0460, 0461,
639 	0462, 0463, 0464, 0465, 0466, 0467, 0470, 0471, 0472, 0473, 0474, 0475,
640 	0476, 0477, 0500, 0501, 0502, 0503, 0504, 0505, 0506, 0507
641 };
642 
643 int attributes_set[9];
644 
645 static int nc_attributes = 0;	/* global attributes for new_curse to observe */
646 
647 #ifdef SYS5
648 struct termio Terminal;
649 struct termio Saved_tty;
650 #else
651 struct sgttyb Terminal;
652 struct sgttyb Saved_tty;
653 #endif
654 
655 char *tc_;
656 
657 int Booleans[128];
658 int Numbers[128];
659 char *String_table[1024];
660 
661 int *virtual_lines;
662 
663 static char nc_scrolling_ability = FALSE;
664 
665 char *terminfo_path[] = {
666         "/lib/terminfo",
667         "/usr/lib/terminfo",
668         "/usr/share/lib/terminfo",
669         "/usr/share/terminfo",
670         NULL
671         };
672 
673 #ifdef CAP
674 
675 #if defined(__STDC__) || defined(__cplusplus)
676 #define P_(s) s
677 #else
678 #define P_(s) ()
679 #endif /* __STDC__ */
680 
681 int tc_Get_int P_((int));
682 void CAP_PARSE P_((void));
683 void Find_term P_((void));
684 
685 #undef P_
686 
687 #endif /* CAP */
688 
689 
690 #ifndef __STDC__
691 #ifndef HAS_STDLIB
692 extern char *fgets();
693 extern char *malloc();
694 extern char *getenv();
695 FILE *fopen();			/* declaration for open function	*/
696 #endif /* HAS_STDLIB */
697 #endif /* __STDC__ */
698 
699 #ifdef SIGWINCH
700 
701 /*
702  |	Copy the contents of one window to another.
703  */
704 
705 void
copy_window(origin,destination)706 copy_window(origin, destination)
707 WINDOW *origin, *destination;
708 {
709 	int row, column;
710 	struct _line *orig, *dest;
711 
712 	orig = origin->first_line;
713 	dest = destination->first_line;
714 
715 	for (row = 0;
716 		row < (min(origin->Num_lines, destination->Num_lines));
717 			row++)
718 	{
719 		for (column = 0;
720 		    column < (min(origin->Num_cols, destination->Num_cols));
721 			column++)
722 		{
723 			dest->row[column] = orig->row[column];
724 			dest->attributes[column] = orig->attributes[column];
725 		}
726 		dest->changed = orig->changed;
727 		dest->scroll = orig->scroll;
728 		dest->last_char = min(orig->last_char, destination->Num_cols);
729 		orig = orig->next_screen;
730 		dest = dest->next_screen;
731 	}
732 	destination->LX = min((destination->Num_cols - 1), origin->LX);
733 	destination->LY = min((destination->Num_lines - 1), origin->LY);
734 	destination->Attrib = origin->Attrib;
735 	destination->scroll_up = origin->scroll_up;
736 	destination->scroll_down = origin->scroll_down;
737 	destination->SCROLL_CLEAR = origin->SCROLL_CLEAR;
738 }
739 
740 void
reinitscr(foo)741 reinitscr(foo)
742 int foo;
743 {
744 	WINDOW *local_virt;
745 	WINDOW *local_std;
746 	WINDOW *local_cur;
747 
748 	signal(SIGWINCH, reinitscr);
749 #ifdef TIOCGWINSZ
750 	if (ioctl(0, TIOCGWINSZ, &ws) >= 0)
751 	{
752 		if (ws.ws_row == LINES && ws.ws_col == COLS)
753 			return;
754 		if (ws.ws_row > 0)
755 			LINES = ws.ws_row;
756 		if (ws.ws_col > 0)
757 			COLS = ws.ws_col;
758 	}
759 #endif /* TIOCGWINSZ */
760 	local_virt = newwin(LINES, COLS, 0, 0);
761 	local_std = newwin(LINES, COLS, 0, 0);
762 	local_cur = newwin(LINES, COLS, 0, 0);
763 	copy_window(virtual_scr, local_virt);
764 	copy_window(stdscr, local_std);
765 	copy_window(curscr, local_cur);
766 	delwin(virtual_scr);
767 	delwin(stdscr);
768 	delwin(curscr);
769 	virtual_scr = local_virt;
770 	stdscr = local_std;
771 	curscr = local_cur;
772 	free(virtual_lines);
773 	virtual_lines = (int *) malloc(LINES * (sizeof(int)));
774 	interrupt_flag = TRUE;
775 }
776 #endif /* SIGWINCH */
777 
778 void
initscr()779 initscr()		/* initialize terminal for operations	*/
780 {
781 	int value;
782 	int counter;
783 	char *lines_string;
784 	char *columns_string;
785 #ifdef CAP
786 	char *pointer;
787 #endif /* CAP */
788 
789 #ifdef DIAG
790 printf("starting initscr \n");fflush(stdout);
791 #endif
792 	if (initialized)
793 		return;
794 #ifdef BSD_SELECT
795 	setbuf(stdin, NULL);
796 #endif /* BSD_SELECT */
797 	Flip_Bytes = FALSE;
798 	Parity = 0;
799 	Time_Out = FALSE;
800 	bufp = 0;
801 	Move_It = FALSE;
802 	Noblock = FALSE;
803 #ifdef SYS5
804 	value = ioctl(0, TCGETA, &Terminal);
805 	if (Terminal.c_cflag & PARENB)
806 	{
807 		if (Terminal.c_cflag & PARENB)
808 			Parity = 1;
809 		else
810 			Parity = 2;
811 	}
812 	if ((Terminal.c_cflag & CS8) == CS8)
813 	{
814 		Num_bits = 8;
815 	}
816 	else if ((Terminal.c_cflag & CS7) == CS7)
817 		Num_bits = 7;
818 	else if ((Terminal.c_cflag & CS6) == CS6)
819 		Num_bits = 6;
820 	else
821 		Num_bits = 5;
822 	value = Terminal.c_cflag & 037;
823 	switch (value) {
824 	case 01:	speed = 50.0;
825 		break;
826 	case 02:	speed = 75.0;
827 		break;
828 	case 03:	speed = 110.0;
829 		break;
830 	case 04:	speed = 134.5;
831 		break;
832 	case 05:	speed = 150.0;
833 		break;
834 	case 06:	speed = 200.0;
835 		break;
836 	case 07:	speed = 300.0;
837 		break;
838 	case 010:	speed = 600.0;
839 		break;
840 	case 011:	speed = 900.0;
841 		break;
842 	case 012:	speed = 1200.0;
843 		break;
844 	case 013:	speed = 1800.0;
845 		break;
846 	case 014:	speed = 2400.0;
847 		break;
848 	case 015:	speed = 3600.0;
849 		break;
850 	case 016:	speed = 4800.0;
851 		break;
852 	case 017:	speed = 7200.0;
853 		break;
854 	case 020:	speed = 9600.0;
855 		break;
856 	case 021:	speed = 19200.0;
857 		break;
858 	case 022:	speed = 38400.0;
859 		break;
860 	default:	speed = 0.0;
861 	}
862 #else
863 	value = ioctl(0, TIOCGETP, &Terminal);
864 	if (Terminal.sg_flags & EVENP)
865 		Parity = 2;
866 	else if (Terminal.sg_flags & ODDP)
867 		Parity = 1;
868 	value = Terminal.sg_ospeed;
869 	switch (value) {
870 	case 01:	speed = 50.0;
871 		break;
872 	case 02:	speed = 75.0;
873 		break;
874 	case 03:	speed = 110.0;
875 		break;
876 	case 04:	speed = 134.5;
877 		break;
878 	case 05:	speed = 150.0;
879 		break;
880 	case 06:	speed = 200.0;
881 		break;
882 	case 07:	speed = 300.0;
883 		break;
884 	case 010:	speed = 600.0;
885 		break;
886 	case 011:	speed = 1200.0;
887 		break;
888 	case 012:	speed = 1800.0;
889 		break;
890 	case 013:	speed = 2400.0;
891 		break;
892 	case 014:	speed = 4800.0;
893 		break;
894 	case 015:	speed = 9600.0;
895 		break;
896 	default:	speed = 0.0;
897 	}
898 #endif
899 	chars_per_millisecond = (0.001 * speed) / 8.0;
900 	TERMINAL_TYPE = getenv("TERM");
901 	if (TERMINAL_TYPE == NULL)
902 	{
903 		printf("unknown terminal type\n");
904 		exit(0);
905 	}
906 #ifndef CAP
907 	Fildes = -1;
908 	TERM_PATH = getenv("TERMINFO");
909 	if (TERM_PATH != NULL)
910 	{
911 		Data_Line_len = 23 + strlen(TERM_PATH) + strlen(TERMINAL_TYPE);
912 		Term_File_name = malloc(Data_Line_len);
913 		sprintf(Term_File_name, "%s/%c/%s", TERM_PATH, *TERMINAL_TYPE, TERMINAL_TYPE);
914 		Fildes = open(Term_File_name, O_RDONLY);
915 		if (Fildes == -1)
916 		{
917         		sprintf(Term_File_name, "%s/%x/%s", TERM_PATH, *TERMINAL_TYPE, TERMINAL_TYPE);
918         		Fildes = open(Term_File_name, O_RDONLY);
919 		}
920 	}
921 	counter = 0;
922 	while ((Fildes == -1) && (terminfo_path[counter] != NULL))
923 	{
924 		TERM_PATH = terminfo_path[counter];
925 		Data_Line_len = 23 + strlen(TERM_PATH) + strlen(TERMINAL_TYPE);
926 		Term_File_name = malloc(Data_Line_len);
927 		sprintf(Term_File_name, "%s/%c/%s", TERM_PATH, *TERMINAL_TYPE, TERMINAL_TYPE);
928 		Fildes = open(Term_File_name, O_RDONLY);
929 		if (Fildes == -1)
930 		{
931         		sprintf(Term_File_name, "%s/%x/%s", TERM_PATH, *TERMINAL_TYPE, TERMINAL_TYPE);
932         		Fildes = open(Term_File_name, O_RDONLY);
933 		}
934 		counter++;
935 	}
936 	if (Fildes == -1)
937 	{
938 		free(Term_File_name);
939 		Term_File_name = NULL;
940 	}
941 	else
942 		TERM_INFO = INFO_PARSE();
943 #else
944 	/*
945 	 |	termcap information can be in the TERMCAP env variable, if so
946 	 |	use that, otherwise check the /etc/termcap file
947 	 */
948 	if ((pointer = Term_File_name = getenv("TERMCAP")) != NULL)
949 	{
950 		if (*Term_File_name != '/')
951 			Term_File_name = TERMCAP;
952 	}
953 	else
954 	{
955 		Term_File_name = TERMCAP;
956 	}
957 	if ((TFP = fopen(Term_File_name, "r")) == NULL)
958 	{
959 		printf("unable to open %s file \n", TERMCAP);
960 		exit(0);
961 	}
962  	for (value = 0; value < 1024; value++)
963 		String_table[value] = NULL;
964 	for (value = 0; value < 128; value++)
965 		Booleans[value] = 0;
966 	for (value = 0; value < 128; value++)
967 		Numbers[value] = 0;
968 	Data_Line = malloc(512);
969 	if (pointer && *pointer != '/')
970 	{
971 		TERM_data_ptr = pointer;
972 		CAP_PARSE();
973 	}
974 	else
975 	{
976 		Find_term();
977 		CAP_PARSE();
978 	}
979 #endif
980 	if (String_table[pc__] == NULL)
981 		String_table[pc__] = "\0";
982 	if ((String_table[cm__] == NULL) || (Booleans[hc__]))
983 	{
984 		fprintf(stderr, "sorry, unable to use this terminal type for screen editing\n");
985 		exit(0);
986 	}
987 	Key_Get();
988 	keys_vt100();
989 	LINES = Numbers[li__];
990 	COLS = Numbers[co__];
991 	if ((lines_string = getenv("LINES")) != NULL)
992 	{
993 		value = atoi(lines_string);
994 		if (value > 0)
995 			LINES = value;
996 	}
997 	if ((columns_string = getenv("COLUMNS")) != NULL)
998 	{
999 		value = atoi(columns_string);
1000 		if (value > 0)
1001 			COLS = value;
1002 	}
1003 #ifdef TIOCGWINSZ
1004 	/*
1005 	 |	get the window size
1006 	 */
1007 	if (ioctl(0, TIOCGWINSZ, &ws) >= 0)
1008 	{
1009 		if (ws.ws_row > 0)
1010 			LINES = ws.ws_row;
1011 		if (ws.ws_col > 0)
1012 			COLS = ws.ws_col;
1013 	}
1014 #endif
1015 	virtual_scr = newwin(LINES, COLS, 0, 0);
1016 	stdscr = newwin(LINES, COLS, 0, 0);
1017 	curscr = newwin(LINES, COLS, 0, 0);
1018 	wmove(stdscr, 0, 0);
1019 	werase(stdscr);
1020 	Repaint_screen = TRUE;
1021 	initialized = TRUE;
1022 	virtual_lines = (int *) malloc(LINES * (sizeof(int)));
1023 
1024 #ifdef SIGWINCH
1025 	/*
1026 	 |	reset size of windows and LINES and COLS if term window
1027 	 |	changes size
1028 	 */
1029 	signal(SIGWINCH, reinitscr);
1030 #endif /* SIGWINCH */
1031 
1032 	/*
1033 	 |	check if scrolling is available
1034 	 */
1035 
1036 	nc_scrolling_ability = ((String_table[al__] != NULL) &&
1037 				(String_table[dl__])) || ((String_table[cs__])
1038 				&& (String_table[sr__]));
1039 
1040 }
1041 
1042 #ifndef CAP
1043 int
Get_int()1044 Get_int()		/* get a two-byte integer from the terminfo file */
1045 {
1046 	int High_byte;
1047 	int Low_byte;
1048 	int temp;
1049 
1050 	Low_byte = *((unsigned char *) TERM_data_ptr++);
1051 	High_byte = *((unsigned char *) TERM_data_ptr++);
1052 	if (Flip_Bytes)
1053 	{
1054 		temp = Low_byte;
1055 		Low_byte = High_byte;
1056 		High_byte = temp;
1057 	}
1058 	if ((High_byte == 255) && (Low_byte == 255))
1059 		return (-1);
1060 	else
1061 		return(Low_byte + (High_byte * 256));
1062 }
1063 
1064 int
INFO_PARSE()1065 INFO_PARSE()		/* parse off the data in the terminfo data file	*/
1066 {
1067 	int offset;
1068 	int magic_number = 0;
1069 	int counter = 0;
1070 	int Num_names = 0;
1071 	int Num_bools = 0;
1072 	int Num_ints = 0;
1073 	int Num_strings = 0;
1074 	int string_table_len = 0;
1075 	char *temp_ptr;
1076 
1077 	TERM_data_ptr = Data_Line = malloc((10240 * (sizeof(char))));
1078 	Data_Line_len = read(Fildes, Data_Line, 10240);
1079 	if ((Data_Line_len >= 10240) || (Data_Line_len < 0))
1080 		return(0);
1081 	/*
1082 	 |	get magic number
1083 	 */
1084 	magic_number = Get_int();
1085 	/*
1086 	 |	if magic number not right, reverse byte order and check again
1087 	 */
1088 	if (magic_number != 282)
1089 	{
1090 		Flip_Bytes = TRUE;
1091 		TERM_data_ptr--;
1092 		TERM_data_ptr--;
1093 		magic_number = Get_int();
1094 		if (magic_number != 282)
1095 			return(0);
1096 	}
1097 	/*
1098 	 |	get the number of each type in the terminfo data file
1099 	 */
1100 	Num_names = Get_int();
1101 	Num_bools = Get_int();
1102 	Num_ints = Get_int();
1103 	Num_strings = Get_int();
1104 	string_table_len = Get_int();
1105 	Strings = malloc(string_table_len);
1106 	while (Num_names > 0)
1107 	{
1108 		TERM_data_ptr++;
1109 		Num_names--;
1110 	}
1111 	counter = 0;
1112 	while (Num_bools)
1113 	{
1114 		Num_bools--;
1115 		Booleans[counter++] = *TERM_data_ptr++;
1116 	}
1117 	if ((unsigned long)(TERM_data_ptr) & 1)	/* force alignment	*/
1118 		TERM_data_ptr++;
1119 	counter = 0;
1120 	while (Num_ints)
1121 	{
1122 		Num_ints--;
1123 		Numbers[counter] = Get_int();
1124 		counter++;
1125 	}
1126 	temp_ptr = TERM_data_ptr + Num_strings + Num_strings;
1127 	memcpy(Strings, temp_ptr, string_table_len);
1128 	counter = bt__;
1129 	while (Num_strings)
1130 	{
1131 		Num_strings--;
1132 		if ((offset=Get_int()) != -1)
1133 		{
1134 			if (String_table[counter] == NULL)
1135 				String_table[counter] = Strings + offset;
1136 		}
1137 		else
1138 			String_table[counter] = NULL;
1139 		counter++;
1140 	}
1141 	close(Fildes);
1142 	free(Data_Line);
1143 	return(TRUE);
1144 }
1145 #endif		/* ifndef CAP	*/
1146 
1147 int
AtoI()1148 AtoI()		/* convert ascii text to integers	*/
1149 {
1150 	int Temp;
1151 
1152 	Temp = 0;
1153 	while ((*TERM_data_ptr >= '0') && (*TERM_data_ptr <= '9'))
1154 	{
1155 		Temp = (Temp * 10) + (*TERM_data_ptr - '0');
1156 		TERM_data_ptr++;
1157 	}
1158 	return(Temp);
1159 }
1160 
1161 void
Key_Get()1162 Key_Get()		/* create linked list with all key sequences obtained from terminal database	*/
1163 {
1164 	int Counter;
1165 	int Klen;
1166 	int key_def;
1167 	struct KEY_STACK *Spoint;
1168 
1169 	Max_Key_len = 0;
1170 	Counter = 0;
1171 	key_def = kb__;
1172 	while (key_def <= kf63__)
1173 	{
1174 		if (key_def == ke__)
1175 			key_def = K1__;
1176 		else if (key_def == (K5__ + 1))
1177 			key_def = kcbt__;
1178 		else if (key_def == (kcbt__ + 1))
1179 			key_def = kbeg__;
1180 		else if (key_def == (kUND__ + 1))
1181 			key_def = kf11__;
1182 		if (String_table[key_def] != NULL)
1183 		{
1184 			if (KEY_TOS == NULL)
1185 				Spoint = KEY_TOS = (struct KEY_STACK *) malloc(sizeof(struct KEY_STACK));
1186 			else
1187 			{
1188 				Spoint = KEY_TOS;
1189 				while (Spoint->next != NULL)
1190 					Spoint = Spoint->next;
1191 				Spoint->next = (struct KEY_STACK *) malloc(sizeof(struct KEY_STACK));
1192 				Spoint = Spoint->next;
1193 			}
1194 			Spoint->next = NULL;
1195 			Spoint->element = (struct KEYS *) malloc(sizeof(struct KEYS));
1196 			Spoint->element->string = String_table[key_def];
1197 			Spoint->element->length = strlen(String_table[key_def]);
1198 			Spoint->element->value = Key_vals[Counter];
1199 			Klen = strlen(Spoint->element->string);
1200 			if (Klen > Max_Key_len)
1201 				Max_Key_len = Klen;
1202 			/*
1203 			 |  Some terminal types accept keystrokes of the form
1204 			 |  \E[A and \EOA, substituting '[' for 'O'.  Make a
1205 			 |  duplicate of such key strings (since the
1206 			 |  database will only have one version) so new_curse
1207 			 |  can understand both.
1208 			 */
1209 			if ((Spoint->element->length > 1) &&
1210 			    ((String_table[key_def][1] == '[') ||
1211 			     (String_table[key_def][1] == 'O')))
1212 			{
1213 				Spoint->next = (struct KEY_STACK *) malloc(sizeof(struct KEY_STACK));
1214 				Spoint = Spoint->next;
1215 				Spoint->next = NULL;
1216 				Spoint->element = (struct KEYS *) malloc(sizeof(struct KEYS));
1217 				Spoint->element->length = strlen(String_table[key_def]);
1218 				Spoint->element->string = malloc(Spoint->element->length + 1);
1219 				strcpy(Spoint->element->string, String_table[key_def]);
1220 				Spoint->element->value = Key_vals[Counter];
1221 				Klen = strlen(Spoint->element->string);
1222 				if (Klen > Max_Key_len)
1223 					Max_Key_len = Klen;
1224 
1225 				if (String_table[key_def][1] == '[')
1226 					Spoint->element->string[1] = 'O';
1227 				else
1228 					Spoint->element->string[1] = '[';
1229 			}
1230 		}
1231 		key_def++;
1232 		Counter++;
1233 	}
1234 }
1235 
1236 /*
1237  |	insert information about keys for a vt100 terminal
1238  */
1239 
1240 void
keys_vt100()1241 keys_vt100()
1242 {
1243 	int counter;
1244 	int Klen;
1245 	struct KEY_STACK *Spoint;
1246 
1247 	Spoint = KEY_TOS;
1248 	while (Spoint->next != NULL)
1249 		Spoint = Spoint->next;
1250 	for (counter = 0; vt100[counter].length != 0; counter++)
1251 	{
1252 		Spoint->next = (struct KEY_STACK *) malloc(sizeof(struct KEY_STACK));
1253 		Spoint = Spoint->next;
1254 		Spoint->next = NULL;
1255 		Spoint->element = &vt100[counter];
1256 		Klen = strlen(Spoint->element->string);
1257 		if (Klen > Max_Key_len)
1258 			Max_Key_len = Klen;
1259 	}
1260 }
1261 
1262 #ifdef CAP
1263 char *
String_Get(param)1264 String_Get(param)		/* read the string */
1265 char *param;
1266 {
1267 	char *String;
1268 	char *Temp;
1269 	int Counter;
1270 
1271 	if (param == NULL)
1272 	{
1273 		while (*TERM_data_ptr != '=')
1274 			TERM_data_ptr++;
1275 		Temp = ++TERM_data_ptr;
1276 		Counter = 1;
1277 		while ((*Temp != ':') && (*Temp != (char)NULL))
1278 		{
1279 			Counter++;
1280 			Temp++;
1281 		}
1282 		if (Counter == 1)	/* no data */
1283 			return(NULL);
1284 		String = Temp = malloc(Counter);
1285 		while ((*TERM_data_ptr != ':') && (*TERM_data_ptr != (char)NULL))
1286 		{
1287 			if (*TERM_data_ptr == '\\')
1288 			{
1289 				TERM_data_ptr++;
1290 				if (*TERM_data_ptr == 'n')
1291 					*Temp = '\n';
1292 				else if (*TERM_data_ptr == 't')
1293 					*Temp = '\t';
1294 				else if (*TERM_data_ptr == 'b')
1295 					*Temp = '\b';
1296 				else if (*TERM_data_ptr == 'r')
1297 					*Temp = '\r';
1298 				else if (*TERM_data_ptr == 'f')
1299 					*Temp = '\f';
1300 				else if ((*TERM_data_ptr == 'e') || (*TERM_data_ptr == 'E'))
1301 					*Temp = '\033';		/* escape */
1302 				else if (*TERM_data_ptr == '\\')
1303 					*Temp = '\\';
1304 				else if (*TERM_data_ptr == '\'')
1305 					*Temp = '\'';
1306 				else if ((*TERM_data_ptr >= '0') && (*TERM_data_ptr <= '9'))
1307 				{
1308 					Counter = 0;
1309 					while ((*TERM_data_ptr >= '0') && (*TERM_data_ptr <= '9'))
1310 					{
1311 						Counter = (8 * Counter) + (*TERM_data_ptr - '0');
1312 						TERM_data_ptr++;  /* ? */
1313 					}
1314 					*Temp = Counter;
1315 					TERM_data_ptr--;
1316 				}
1317 				TERM_data_ptr++;
1318 				Temp++;
1319 			}
1320 			else if (*TERM_data_ptr == '^')
1321 			{
1322 				TERM_data_ptr++;
1323 				if ((*TERM_data_ptr >= '@') && (*TERM_data_ptr <= '_'))
1324 					*Temp = *TERM_data_ptr - '@';
1325 				else if (*TERM_data_ptr == '?')
1326 					*Temp = 127;
1327 				TERM_data_ptr++;
1328 				Temp++;
1329 			}
1330 			else
1331 				*Temp++ = *TERM_data_ptr++;
1332 		}
1333 		*Temp = (char)NULL;
1334 		param = String;
1335 	}
1336 	else
1337 	{
1338 		while ((*TERM_data_ptr != (char)NULL) && (*TERM_data_ptr != ':'))
1339 			TERM_data_ptr++;
1340 	}
1341 	return(param);
1342 }
1343 
1344 int
tc_Get_int(param)1345 tc_Get_int(param)		/* read the integer			*/
1346 int param;
1347 {
1348 	int Itemp;
1349 
1350 	if (param == 0)
1351 	{
1352 		while ((*TERM_data_ptr != (char)NULL) && (*TERM_data_ptr != '#'))
1353 			TERM_data_ptr++;
1354 		TERM_data_ptr++;
1355 		Itemp = AtoI();
1356 		param = Itemp;
1357 	}
1358 	else
1359 	{
1360 		while (*TERM_data_ptr != ':')
1361 			TERM_data_ptr++;
1362 	}
1363 	return(param);
1364 }
1365 
1366 void
Find_term()1367 Find_term()		/* find terminal description in termcap file	*/
1368 {
1369 	char *Name;
1370 	char *Ftemp;
1371 
1372 	Ftemp = Name = malloc(strlen(TERMINAL_TYPE) + 2);
1373 	strcpy(Name, TERMINAL_TYPE);
1374 	while (*Ftemp != (char)NULL)
1375 		Ftemp++;
1376 	*Ftemp++ = '|';
1377 	*Ftemp = (char)NULL;
1378 	CFOUND = FALSE;
1379 	Data_Line_len = strlen(TERMINAL_TYPE) + 1;
1380 	while ((!CFOUND) && ((TERM_data_ptr=fgets(Data_Line, 512, TFP)) != NULL))
1381 	{
1382 		if ((*TERM_data_ptr != ' ') && (*TERM_data_ptr != '\t') && (*TERM_data_ptr != '#'))
1383 		{
1384 			while ((!CFOUND) && (*TERM_data_ptr != (char)NULL))
1385 			{
1386 				CFOUND = !strncmp(TERM_data_ptr, Name, Data_Line_len);
1387 				while ((*TERM_data_ptr != (char)NULL) && (*TERM_data_ptr != '|') && (*TERM_data_ptr != '#') && (*TERM_data_ptr != ':'))
1388 					TERM_data_ptr++;
1389 				if (*TERM_data_ptr == '|')
1390 					TERM_data_ptr++;
1391 				else if (!CFOUND)
1392 					*TERM_data_ptr = (char)NULL;
1393 			}
1394 		}
1395 	}
1396 	if (!CFOUND)
1397 	{
1398 		printf("terminal type %s not found\n", TERMINAL_TYPE);
1399 		exit(0);
1400 	}
1401 }
1402 
1403 void
CAP_PARSE()1404 CAP_PARSE()		/* parse off the data in the termcap data file	*/
1405 {
1406 	int offset;
1407 	int found;
1408 
1409 	do
1410 	{
1411 		while (*TERM_data_ptr != (char)NULL)
1412 		{
1413 			for (found = FALSE, offset = 0; (!found) && (offset < 26); offset++)
1414 			{
1415 				if (!strncmp(TERM_data_ptr, Boolean_names[offset], 2))
1416 				{
1417 					found = TRUE;
1418 					Booleans[offset] = TRUE;
1419 				}
1420 			}
1421 			if (!found)
1422 			{
1423 				for (found = FALSE, offset = 0; (!found) && (offset < lw__); offset++)
1424 				{
1425 					if (!strncmp(TERM_data_ptr, Number_names[offset], 3))
1426 					{
1427 						found = TRUE;
1428 						Numbers[offset] = tc_Get_int(Numbers[offset]);
1429 					}
1430 				}
1431 			}
1432 			if (!found)
1433 			{
1434 				for (found = FALSE, offset = 0; (!found) && (offset < smgr__); offset++)
1435 				{
1436 					if (!strncmp(TERM_data_ptr, String_names[offset], 3))
1437 					{
1438 						found = TRUE;
1439 						String_table[offset] = String_Get(String_table[offset]);
1440 					}
1441 				}
1442 			}
1443 
1444 			if (!strncmp(TERM_data_ptr, "tc=", 3))
1445 				tc_ = String_Get(NULL);
1446 			while ((*TERM_data_ptr != ':') && (*TERM_data_ptr != (char)NULL))
1447 				TERM_data_ptr++;
1448 			if (*TERM_data_ptr == ':')
1449 				TERM_data_ptr++;
1450 		}
1451 	} while (((TERM_data_ptr = fgets(Data_Line, 512, TFP)) != NULL) && ((*TERM_data_ptr == ' ') || (*TERM_data_ptr == '\t')));
1452 	if (tc_ != NULL)
1453 	{
1454 		TERMINAL_TYPE = tc_;
1455 		rewind(TFP);
1456 		Find_term();
1457 		tc_ = NULL;
1458 		CAP_PARSE();
1459 	}
1460 	else
1461 		fclose(TFP);
1462 }
1463 #endif		/* ifdef CAP	*/
1464 
1465 struct _line *
Screenalloc(columns)1466 Screenalloc(columns)
1467 int columns;
1468 {
1469 	int i;
1470 	struct _line *tmp;
1471 
1472 	tmp = (struct _line *) malloc(sizeof (struct _line));
1473 	tmp->row = malloc(columns + 1);
1474 	tmp->attributes = malloc(columns + 1);
1475 	tmp->prev_screen = NULL;
1476 	tmp->next_screen = NULL;
1477 	for (i = 0; i < columns; i++)
1478 	{
1479 		tmp->row[i] = ' ';
1480 		tmp->attributes[i] = '\0';
1481 	}
1482 	tmp->scroll = tmp->changed = FALSE;
1483 	tmp->row[0] = '\0';
1484 	tmp->attributes[0] = '\0';
1485 	tmp->row[columns] = '\0';
1486 	tmp->attributes[columns] = '\0';
1487 	tmp->last_char = 0;
1488 	return(tmp);
1489 }
1490 
newwin(lines,cols,start_l,start_c)1491 WINDOW *newwin(lines, cols, start_l, start_c)
1492 int lines, cols;	/* number of lines and columns to be in window	*/
1493 int start_l, start_c;	/* starting line and column to be inwindow	*/
1494 {
1495 	WINDOW *Ntemp;
1496 	struct _line *temp_screen;
1497 	int i;
1498 
1499 	Ntemp = (WINDOW *) malloc(sizeof(WINDOW));
1500 	Ntemp->SR = start_l;
1501 	Ntemp->SC = start_c;
1502 	Ntemp->Num_lines = lines;
1503 	Ntemp->Num_cols = cols;
1504 	Ntemp->LX = 0;
1505 	Ntemp->LY = 0;
1506 	Ntemp->scroll_down = Ntemp->scroll_up = 0;
1507 	Ntemp->SCROLL_CLEAR = FALSE;
1508 	Ntemp->Attrib = FALSE;
1509 	Ntemp->first_line = temp_screen = Screenalloc(cols);
1510 	Ntemp->first_line->number = 0;
1511 	Ntemp->line_array = (struct _line **) malloc(LINES * sizeof(struct _line *));
1512 
1513 	Ntemp->line_array[0] = Ntemp->first_line;
1514 
1515 	for (i = 1; i < lines; i++)
1516 	{
1517 		temp_screen->next_screen = Screenalloc(cols);
1518 		temp_screen->next_screen->number = i;
1519 		temp_screen->next_screen->prev_screen = temp_screen;
1520 		temp_screen = temp_screen->next_screen;
1521 		Ntemp->line_array[i] = temp_screen;
1522 	}
1523 	Ntemp->first_line->prev_screen = NULL;
1524 	temp_screen->next_screen = NULL;
1525 	return(Ntemp);
1526 }
1527 
1528 #ifdef CAP
1529 void
Cap_Out(string,p_list,place)1530 Cap_Out(string, p_list, place)	/* interpret the output string if necessary */
1531 char *string;
1532 int p_list[];			/* stack of values	*/
1533 int place;			/* place keeper of top of stack	*/
1534 {
1535 	char *Otemp;		/* temporary string pointer to parse output */
1536 	int delay;
1537 	int p1, p2, temp;
1538 	float chars;
1539 
1540 	if (string == NULL)
1541 		return;
1542 
1543 	if (p_list != NULL)
1544 	{
1545 		p1 = p_list[--place];
1546 		p2 = p_list[--place];
1547 	}
1548 	delay = 0;
1549 	Otemp = string;
1550 	if ((*Otemp >= '0') && (*Otemp <= '9'))
1551 	{
1552 		delay = atoi(Otemp);
1553 		while ((*Otemp >= '0') && (*Otemp <= '9'))
1554 			Otemp++;
1555 		if (*Otemp == '*')
1556 			Otemp++;
1557 	}
1558 	while (*Otemp != (char)NULL)
1559 	{
1560 		if (*Otemp == '%')
1561 		{
1562 			Otemp++;
1563 			if ((*Otemp == 'd') || (*Otemp == '2') || (*Otemp == '3') || (*Otemp == '.') || (*Otemp == '+'))
1564 			{
1565 				if (*Otemp == 'd')
1566 				 	printf("%d", p1);
1567 				else if (*Otemp == '2')
1568 					printf("%02d", p1);
1569 				else if (*Otemp == '3')
1570 					printf("%03d", p1);
1571 				else if (*Otemp == '+')
1572 				{
1573 					Otemp++;
1574 					p1 += *Otemp;
1575 					putchar(p1);
1576 				}
1577 				else if (*Otemp == '.')
1578 					putchar(p1);
1579 				p1 = p2;
1580 				p2 = 0;
1581 			}
1582 			else if (*Otemp == '>')
1583 			{
1584 				Otemp++;
1585 				if (p1 > *Otemp)
1586 				{
1587 					Otemp++;
1588 					p1 += *Otemp;
1589 				}
1590 				else
1591 					Otemp++;
1592 			}
1593 			else if (*Otemp == 'r')
1594 			{
1595 				temp = p1;
1596 				p1 = p2;
1597 				p2 = temp;
1598 			}
1599 			else if (*Otemp == 'i')
1600 			{
1601 				p1++;
1602 				p2++;
1603 			}
1604 			else if (*Otemp == '%')
1605 				putchar(*Otemp);
1606 			else if (*Otemp == 'n')
1607 			{
1608 				p1 ^= 0140;
1609 				p2 ^= 0140;
1610 			}
1611 			else if (*Otemp == 'B')
1612 			{
1613 				p1 = (16 * (p1/10)) + (p1 % 10);
1614 				p2 = (16 * (p2/10)) + (p2 % 10);
1615 			}
1616 			else if (*Otemp == 'D')
1617 			{
1618 				p1 = (p1 - 2 * (p1 % 16));
1619 				p2 = (p2 - 2 * (p2 % 16));
1620 			}
1621 		}
1622 		else
1623 			putchar (*Otemp);
1624 		Otemp++;
1625 	}
1626 	if (delay != 0)
1627 	{
1628 		chars = delay * chars_per_millisecond;
1629 		delay = chars;
1630 		if ((chars - delay) > 0.0)
1631 			delay++;
1632 		for (; delay > 0; delay--)
1633 			putchar(*String_table[pc__]);
1634 	}
1635 	fflush(stdout);
1636 }
1637 
1638 #else
1639 
1640 	char *Otemp;		/* temporary string pointer to parse output */
1641 	float chars;
1642 	int p[10];
1643 	int variable[27];
1644 
1645 int
Operation(Temp_Stack,place)1646 Operation(Temp_Stack, place)	/* handle conditional operations	*/
1647 int Temp_Stack[];
1648 int place;
1649 {
1650 	int temp;
1651 
1652 	if (*Otemp == 'd')
1653 	{
1654 		Otemp++;
1655 		temp = Temp_Stack[--place];
1656 	 	printf("%d", temp);
1657 	}
1658 	else if (!strncmp(Otemp, "2d", 2))
1659 	{
1660 		temp = Temp_Stack[--place];
1661 		printf("%2d", temp);
1662 		Otemp++;
1663 		Otemp++;
1664 	}
1665 	else if (!strncmp(Otemp, "3d", 2))
1666 	{
1667 		temp = Temp_Stack[--place];
1668 		printf("%0d", temp);
1669 		Otemp++;
1670 		Otemp++;
1671 	}
1672 	else if (!strncmp(Otemp, "02d", 3))
1673 	{
1674 		temp = Temp_Stack[--place];
1675 		printf("%02d", temp);
1676 		Otemp++;
1677 		Otemp++;
1678 		Otemp++;
1679 	}
1680 	else if (!strncmp(Otemp, "03d", 3))
1681 	{
1682 		temp = Temp_Stack[--place];
1683 		printf("%03d", temp);
1684 		Otemp++;
1685 		Otemp++;
1686 		Otemp++;
1687 	}
1688 	else if (*Otemp == '+')
1689 	{
1690 		Otemp++;
1691 		temp = Temp_Stack[--place];
1692 		temp += Temp_Stack[--place];
1693 		Temp_Stack[place++] = temp;
1694 	}
1695 	else if (*Otemp == '-')
1696 	{
1697 		Otemp++;
1698 		temp = Temp_Stack[--place];
1699 		temp -= Temp_Stack[--place];
1700 		Temp_Stack[place++] = temp;
1701 	}
1702 	else if (*Otemp == '*')
1703 	{
1704 		Otemp++;
1705 		temp = Temp_Stack[--place];
1706 		temp *= Temp_Stack[--place];
1707 		Temp_Stack[place++] = temp;
1708 	}
1709 	else if (*Otemp == '/')
1710 	{
1711 		Otemp++;
1712 		temp = Temp_Stack[--place];
1713 		temp /= Temp_Stack[--place];
1714 		Temp_Stack[place++] = temp;
1715 	}
1716 	else if (*Otemp == 'm')
1717 	{
1718 		Otemp++;
1719 		temp = Temp_Stack[--place];
1720 		temp %= Temp_Stack[--place];
1721 		Temp_Stack[place++] = temp;
1722 	}
1723 	else if (*Otemp == '&')
1724 	{
1725 		Otemp++;
1726 		temp = Temp_Stack[--place];
1727 		temp &= Temp_Stack[--place];
1728 		Temp_Stack[place++] = temp;
1729 	}
1730 	else if (*Otemp == '|')
1731 	{
1732 		Otemp++;
1733 		temp = Temp_Stack[--place];
1734 		temp |= Temp_Stack[--place];
1735 		Temp_Stack[place++] = temp;
1736 	}
1737 	else if (*Otemp == '^')
1738 	{
1739 		Otemp++;
1740 		temp = Temp_Stack[--place];
1741 		temp ^= Temp_Stack[--place];
1742 		Temp_Stack[place++] = temp;
1743 	}
1744 	else if (*Otemp == '=')
1745 	{
1746 		Otemp++;
1747 		temp = Temp_Stack[--place];
1748 		temp = (temp == Temp_Stack[--place]);
1749 		Temp_Stack[place++] = temp;
1750 	}
1751 	else if (*Otemp == '>')
1752 	{
1753 		Otemp++;
1754 		temp = Temp_Stack[--place];
1755 		temp = temp > Temp_Stack[--place];
1756 		Temp_Stack[place++] = temp;
1757 	}
1758 	else if (*Otemp == '<')
1759 	{
1760 		Otemp++;
1761 		temp = Temp_Stack[--place];
1762 		temp = temp < Temp_Stack[--place];
1763 		Temp_Stack[place++] = temp;
1764 	}
1765 	else if (*Otemp == 'c')
1766 	{
1767 		Otemp++;
1768 		putchar(Temp_Stack[--place]);
1769 	}
1770 	else if (*Otemp == 'i')
1771 	{
1772 		Otemp++;
1773 		p[1]++;
1774 		p[2]++;
1775 	}
1776 	else if (*Otemp == '%')
1777 	{
1778 		putchar(*Otemp);
1779 		Otemp++;
1780 	}
1781 	else if (*Otemp == '!')
1782 	{
1783 		temp = ! Temp_Stack[--place];
1784 		Temp_Stack[place++] = temp;
1785 		Otemp++;
1786 	}
1787 	else if (*Otemp == '~')
1788 	{
1789 		temp = ~Temp_Stack[--place];
1790 		Temp_Stack[place++] = temp;
1791 		Otemp++;
1792 	}
1793 	else if (*Otemp == 'p')
1794 	{
1795 		Otemp++;
1796 		Temp_Stack[place++] = p[*Otemp - '0'];
1797 		Otemp++;
1798 	}
1799 	else if (*Otemp == 'P')
1800 	{
1801 		Otemp++;
1802 		Temp_Stack[place++] = variable[*Otemp - 'a'];
1803 		Otemp++;
1804 	}
1805 	else if (*Otemp == 'g')
1806 	{
1807 		Otemp++;
1808 		variable[*Otemp - 'a'] = Temp_Stack[--place];
1809 		Otemp++;
1810 	}
1811 	else if (*Otemp == '\'')
1812 	{
1813 		Otemp++;
1814 		Temp_Stack[place++] = *Otemp;
1815 		Otemp++;
1816 		Otemp++;
1817 	}
1818 	else if (*Otemp == '{')
1819 	{
1820 		Otemp++;
1821 		temp = atoi(Otemp);
1822 		Temp_Stack[place++] = temp;
1823 		while (*Otemp != '}')
1824 			Otemp++;
1825 		Otemp++;
1826 	}
1827 	return(place);
1828 }
1829 
1830 void
Info_Out(string,p_list,place)1831 Info_Out(string, p_list, place)	/* interpret the output string if necessary */
1832 char *string;
1833 int p_list[];
1834 int place;
1835 {
1836 	char *tchar;
1837 	int delay;
1838 	int temp;
1839 	int Cond_FLAG;
1840 	int EVAL;
1841 	int Cond_Stack[128];
1842 	int Cond_place;
1843 	int Stack[128];
1844 	int Top_of_stack;
1845 
1846 	if (string == NULL)
1847 		return;
1848 
1849 	Cond_FLAG = FALSE;
1850 	Cond_place = 0;
1851 	Top_of_stack = 0;
1852 	p[0] = 0;
1853 	p[1] = 0;
1854 	p[2] = 0;
1855 	p[3] = 0;
1856 	p[4] = 0;
1857 	p[5] = 0;
1858 	p[6] = 0;
1859 	p[7] = 0;
1860 	p[8] = 0;
1861 	p[9] = 0;
1862 	if (p_list != NULL)
1863 	{
1864 		for (temp = 1; (place != 0); temp++)
1865 		{
1866 			p[temp] = p_list[--place];
1867 		}
1868 	}
1869 	delay = 0;
1870 	Otemp = string;
1871 	while (*Otemp != '\0')
1872 	{
1873 		if (*Otemp == '%')
1874 		{
1875 			Otemp++;
1876 			if ((*Otemp == '?') || (*Otemp == 't') || (*Otemp == 'e') || (*Otemp == ';'))
1877 			{
1878 				if (*Otemp == '?')
1879 				{
1880 					Otemp++;
1881 					Cond_FLAG = TRUE;
1882 					EVAL = TRUE;
1883 					while (EVAL)
1884 					{
1885 						/*
1886 						 |  find the end of the
1887 						 |  conditional statement
1888 						 */
1889 						while ((strncmp(Otemp, "%t", 2)) && (*Otemp != '\0'))
1890 						{
1891 							/*
1892 							 |  move past '%'
1893 							 */
1894 							Otemp++;
1895 							Cond_place = Operation(Cond_Stack, Cond_place);
1896 						}
1897 
1898 						/*
1899 						 |  if condition is true
1900 						 */
1901 						if ((Cond_place > 0) && (Cond_Stack[Cond_place-1]))
1902 						{
1903 							/*
1904 							 |  end conditional
1905 							 |  parsing
1906 							 */
1907 							EVAL = FALSE;
1908 							Otemp++;
1909 							Otemp++;
1910 						}
1911 						else	/* condition is false */
1912 						{
1913 							/*
1914 							 |  find 'else' or end
1915 							 |  of if statement
1916 							 */
1917 							while ((strncmp(Otemp, "%e", 2)) && (strncmp(Otemp, "%;", 2)) && (*Otemp != '\0'))
1918 								Otemp++;
1919 							/*
1920 							 |  if an 'else' found
1921 							 */
1922 							if ((*Otemp != '\0') && (!strncmp(Otemp, "%e", 2)))
1923 							{
1924 								Otemp++;
1925 								Otemp++;
1926 								tchar = Otemp;
1927 								/*
1928 								 |  check for 'then' part
1929 								 */
1930 								while ((*tchar != '\0') && (strncmp(tchar, "%t", 2)) && (strncmp(tchar, "%;", 2)))
1931 									tchar++;
1932 								/*
1933 								 |  if end of string
1934 								 */
1935 								if (*tchar == '\0')
1936 								{
1937 									EVAL = FALSE;
1938 									Cond_FLAG = FALSE;
1939 									Otemp = tchar;
1940 								}
1941 								/*
1942 								 |  if end of if found,
1943 								 |  set up to parse
1944 								 |  info
1945 								 */
1946 								else if (!strncmp(tchar, "%;", 2))
1947 									EVAL = FALSE;
1948 								/*
1949 								 |  otherwise, check
1950 								 |  conditional in
1951 								 |  'else'
1952 								 */
1953 							}
1954 							/*
1955 							 |  if end of if found,
1956 							 |  get out of if
1957 							 |  statement
1958 							 */
1959 							else if ((*Otemp != '\0') && (!strncmp(Otemp, "%;", 2)))
1960 							{
1961 								EVAL = FALSE;
1962 								Otemp++;
1963 								Otemp++;
1964 							}
1965 							else /* Otemp == NULL */
1966 							{
1967 								EVAL = FALSE;
1968 								Cond_FLAG = FALSE;
1969 							}
1970 						}
1971 					}
1972 				}
1973 				else
1974 				{
1975 					Otemp++;
1976 					Cond_FLAG = FALSE;
1977 					if (*Otemp != ';')
1978 					{
1979 						while ((*Otemp != '\0') && (strncmp(Otemp, "%;", 2)))
1980 							Otemp++;
1981 						if (*Otemp != '\0')
1982 						{
1983 							Otemp++;
1984 							Otemp++;
1985 						}
1986 					}
1987 					else
1988 						Otemp++;
1989 				}
1990 			}
1991 			else
1992 			{
1993 				Top_of_stack = Operation(Stack, Top_of_stack);
1994 			}
1995 		}
1996 		else if (!strncmp(Otemp, "$<", 2))
1997 		{
1998 			Otemp++;
1999 			Otemp++;
2000 			delay = atoi(Otemp);
2001 			while (*Otemp != '>')
2002 				Otemp++;
2003 			Otemp++;
2004 			chars = delay * chars_per_millisecond;
2005 			delay = chars;
2006 			if ((chars - delay) > 0.0)
2007 				delay++;
2008 			if (String_table[pc__] == NULL)
2009 				temp = 0;
2010 			else
2011 				temp = *String_table[pc__];
2012 			for (; delay > 0; delay--)
2013 				putc(temp, stdout);
2014 		}
2015 		else
2016 		{
2017 			putchar(*Otemp);
2018 			Otemp++;
2019 		}
2020 	}
2021 	fflush(stdout);
2022 }
2023 #endif
2024 
2025 void
wmove(window,row,column)2026 wmove(window, row, column)	/* move cursor to indicated position in window */
2027 WINDOW *window;
2028 int row, column;
2029 {
2030 	if ((row < window->Num_lines) && (column < window->Num_cols))
2031 	{
2032 		window->LX = column;
2033 		window->LY = row;
2034 	}
2035 }
2036 
2037 void
clear_line(line,column,cols)2038 clear_line(line, column, cols)
2039 struct _line *line;
2040 int column;
2041 int cols;
2042 {
2043 	int j;
2044 
2045 	if (column > line->last_char)
2046 	{
2047 		for (j = line->last_char; j < column; j++)
2048 		{
2049 			line->row[j] = ' ';
2050 			line->attributes[j] = '\0';
2051 		}
2052 	}
2053 	line->last_char = column;
2054 	line->row[column] = '\0';
2055 	line->attributes[column] = '\0';
2056 	line->changed = TRUE;
2057 }
2058 
2059 void
werase(window)2060 werase(window)			/* clear the specified window		*/
2061 WINDOW *window;
2062 {
2063 	int i;
2064 	struct _line *tmp;
2065 
2066 	window->SCROLL_CLEAR = CLEAR;
2067 	window->scroll_up = window->scroll_down = 0;
2068 	for (i = 0, tmp = window->first_line; i < window->Num_lines; i++, tmp = tmp->next_screen)
2069 		clear_line(tmp, 0, window->Num_cols);
2070 }
2071 
2072 void
wclrtoeol(window)2073 wclrtoeol(window)	/* erase from current cursor position to end of line */
2074 WINDOW *window;
2075 {
2076 	int column, row;
2077 	struct _line *tmp;
2078 
2079 	window->SCROLL_CLEAR = CHANGE;
2080 	column = window->LX;
2081 	row = window->LY;
2082 	for (row = 0, tmp = window->first_line; row < window->LY; row++)
2083 		tmp = tmp->next_screen;
2084 	clear_line(tmp, column, window->Num_cols);
2085 }
2086 
2087 void
wrefresh(window)2088 wrefresh(window)		/* flush all previous output		*/
2089 WINDOW *window;
2090 {
2091 	wnoutrefresh(window);
2092 #ifdef DIAG
2093 {
2094 	struct _line *temp;
2095 	int value;
2096 	fprintf(stderr, "columns=%d, lines=%d, SC=%d, SR=%d\n",window->Num_cols, window->Num_lines, window->SC, window->SR);
2097 	for (value = 0, temp = window->first_line; value < window->Num_lines; value++, temp = temp->next_screen)
2098 	{
2099 		if (temp->number == -1)
2100 			fprintf(stderr, "line moved ");
2101 		if (temp->scroll)
2102 			fprintf(stderr, "scroll_x is set:  ");
2103 		fprintf(stderr, "lc%d=%s|\n", temp->last_char, temp->row);
2104 	}
2105 	fprintf(stderr, "+-------------------- virtual screen ----------------------------------------+\n");
2106 	fprintf(stderr, "columns=%d, lines=%d \n",virtual_scr->Num_cols, virtual_scr->Num_lines);
2107 	for (value = 0, temp = virtual_scr->first_line; value < virtual_scr->Num_lines; value++, temp = temp->next_screen)
2108 	{
2109 		if (temp->number == -1)
2110 			fprintf(stderr, "line moved ");
2111 		if (temp->scroll)
2112 			fprintf(stderr, "scroll_x is set:  ");
2113 		fprintf(stderr, "lc%d=%s|\n", temp->last_char, temp->row);
2114 	}
2115 	fprintf(stderr, "columns=%d, lines=%d \n",curscr->Num_cols, curscr->Num_lines);
2116 	for (value = 0, temp = curscr->first_line; value < curscr->Num_lines; value++, temp = temp->next_screen)
2117 		fprintf(stderr, "line=%s|\n", temp->row);
2118 }
2119 #endif
2120 	doupdate();
2121 	virtual_scr->SCROLL_CLEAR = FALSE;
2122 	virtual_scr->scroll_down = virtual_scr->scroll_up = 0;
2123 	fflush(stdout);
2124 }
2125 
2126 void
touchwin(window)2127 touchwin(window)
2128 WINDOW *window;
2129 {
2130 	struct _line *user_line;
2131 	int line_counter = 0;
2132 
2133 	for (line_counter = 0, user_line = window->first_line;
2134 		line_counter < window->Num_lines; line_counter++)
2135 	{
2136 		user_line->changed = TRUE;
2137 	}
2138 	window->SCROLL_CLEAR = TRUE;
2139 }
2140 
2141 void
wnoutrefresh(window)2142 wnoutrefresh(window)
2143 WINDOW *window;
2144 {
2145 	struct _line *user_line;
2146 	struct _line *virtual_line;
2147 	int line_counter = 0;
2148 	int user_col = 0;
2149 	int virt_col = 0;
2150 
2151 	if (window->SR >= virtual_scr->Num_lines)
2152 		return;
2153 	user_line = window->first_line;
2154 	virtual_line = virtual_scr->first_line;
2155 	virtual_scr->SCROLL_CLEAR = window->SCROLL_CLEAR;
2156 	virtual_scr->LX = window->LX + window->SC;
2157 	virtual_scr->LY = window->LY + window->SR;
2158 	virtual_scr->scroll_up = window->scroll_up;
2159 	virtual_scr->scroll_down = window->scroll_down;
2160 	if ((last_window_refreshed == window) && (!window->SCROLL_CLEAR))
2161 		return;
2162 	for (line_counter = 0; line_counter < window->SR; line_counter++)
2163 	{
2164 		virtual_line = virtual_line->next_screen;
2165 	}
2166 	for (line_counter = 0; (line_counter < window->Num_lines)
2167 		&& ((line_counter + window->SR) < virtual_scr->Num_lines);
2168 			line_counter++)
2169 	{
2170 		if ((last_window_refreshed != window) || (user_line->changed) || ((SCROLL | CLEAR) & window->SCROLL_CLEAR))
2171 		{
2172 			for (user_col = 0, virt_col = window->SC;
2173 				(virt_col < virtual_scr->Num_cols)
2174 				  && (user_col < user_line->last_char);
2175 				  	virt_col++, user_col++)
2176 			{
2177 				virtual_line->row[virt_col] = user_line->row[user_col];
2178 				virtual_line->attributes[virt_col] = user_line->attributes[user_col];
2179 			}
2180 			for (user_col = user_line->last_char,
2181 			     virt_col = window->SC + user_line->last_char;
2182 				(virt_col < virtual_scr->Num_cols)
2183 				  && (user_col < window->Num_cols);
2184 				  	virt_col++, user_col++)
2185 			{
2186 				virtual_line->row[virt_col] = ' ';
2187 				virtual_line->attributes[virt_col] = '\0';
2188 			}
2189 		}
2190 		if (virtual_scr->Num_cols != window->Num_cols)
2191 		{
2192 			if (virtual_line->last_char < (user_line->last_char + window->SC))
2193 			{
2194 				if (virtual_line->row[virtual_line->last_char] == '\0')
2195 					virtual_line->row[virtual_line->last_char] = ' ';
2196 				virtual_line->last_char =
2197 					min(virtual_scr->Num_cols,
2198 					  (user_line->last_char + window->SC));
2199 			}
2200 		}
2201 		else
2202 			virtual_line->last_char = user_line->last_char;
2203 		virtual_line->row[virtual_line->last_char] = '\0';
2204 		virtual_line->changed = user_line->changed;
2205 		virtual_line = virtual_line->next_screen;
2206 		user_line = user_line->next_screen;
2207 	}
2208 	window->SCROLL_CLEAR = FALSE;
2209 	window->scroll_up = window->scroll_down = 0;
2210 	last_window_refreshed = window;
2211 }
2212 
2213 void
flushinp()2214 flushinp()			/* flush input				*/
2215 {
2216 }
2217 
2218 void
ungetch(c)2219 ungetch(c)			/* push a character back on input	*/
2220 int c;
2221 {
2222 	if (bufp < 100)
2223 		in_buff[bufp++] = c;
2224 }
2225 
2226 #ifdef BSD_SELECT
2227 int
timed_getchar()2228 timed_getchar()
2229 {
2230 	struct timeval tv;
2231 	fd_set fds;
2232 	int ret_val;
2233 	int nfds = 1;
2234 	char temp;
2235 
2236 	FD_ZERO(&fds);
2237 	tv.tv_sec = 0;
2238 	tv.tv_usec = 500000;  /* half a second */
2239 	FD_SET(0, &fds);
2240 	Time_Out = FALSE; /* just in case */
2241 
2242 	ret_val = select(nfds, &fds, 0, 0, &tv);
2243 
2244 	/*
2245 	 |	if ret_val is less than zero, there was no input
2246 	 |	otherwise, get a character and return it
2247 	 */
2248 
2249 	if (ret_val <= 0)
2250 	{
2251 		Time_Out = TRUE;
2252 		return(-1);
2253 	}
2254 
2255 	return(read(0, &temp, 1)? temp : -1);
2256 }
2257 #endif
2258 
2259 int
wgetch(window)2260 wgetch(window)			/* get character from specified window	*/
2261 WINDOW *window;
2262 {
2263 	int in_value;
2264 	char temp;
2265 #ifndef SYS5
2266 	int old_arg;
2267 #endif /* SYS5 */
2268 
2269 #ifdef BSD_SELECT
2270 	if (Noblock)
2271 		in_value = ((bufp > 0) ? in_buff[--bufp] : timed_getchar());
2272 	else
2273 		in_value = ((bufp > 0) ? in_buff[--bufp] : read(0, &temp, 1)? temp : -1);
2274 #else /* BSD_SELECT */
2275 #ifdef SYS5
2276 	in_value = ((bufp > 0) ? in_buff[--bufp] :
2277 					(read(0, &temp, 1)> 0) ? temp : -1);
2278 #else /* SYS5 */
2279 	if (Noblock)
2280 	{
2281 		Time_Out = FALSE;
2282 		old_arg = fcntl(0, F_GETFL, 0);
2283 		in_value = fcntl(0, F_SETFL, old_arg | FNDELAY);
2284 	}
2285 	in_value = ((bufp > 0) ? in_buff[--bufp] : read(0, &temp, 1)? temp : -1);
2286 	if (Noblock)
2287 	{
2288 		fcntl(0, F_SETFL, old_arg);
2289 		if (Time_Out)
2290 			in_value = -1;
2291 	}
2292 #endif /* SYS5 */
2293 #endif /* BSD_SELECT */
2294 
2295 	if (in_value != -1)
2296 	{
2297 		in_value &= 0xff;
2298 		if ((Parity) && (Num_bits < 8))
2299 				/* strip eighth bit if parity in use */
2300 		in_value &= 0177;
2301 	}
2302 	else if (interrupt_flag)
2303 	{
2304 		interrupt_flag = FALSE;
2305 		in_value = wgetch(window);
2306 	}
2307 
2308 	if ((in_value == '\033') || (in_value == '\037'))/* escape character */
2309 		in_value = Get_key(in_value);
2310 	return(in_value);
2311 }
2312 
2313 #ifndef BSD_SELECT
2314 void
Clear(arg)2315 Clear(arg)		/* notify that time out has occurred	*/
2316 int arg;
2317 {
2318 	Time_Out = TRUE;
2319 #ifdef DEBUG
2320 fprintf(stderr, "inside Clear()\n");
2321 fflush(stderr);
2322 #endif /* DEBUG */
2323 }
2324 #endif /* BSD_SELECT */
2325 
2326 int
Get_key(first_char)2327 Get_key(first_char)			/* try to decode key sequence	*/
2328 int first_char;				/* first character of sequence	*/
2329 {
2330 	int in_char;
2331 	int Count;
2332 	char string[128];
2333 	char *Gtemp;
2334 	int Found;
2335 #ifdef SYS5
2336 	struct termio Gterminal;
2337 #else
2338 	struct sgttyb Gterminal;
2339 #endif
2340 	struct KEY_STACK *St_point;
2341 #if (!defined( BSD_SELECT)) || (!defined(SYS5))
2342 	int value;
2343 #endif /* BSD_SELECT */
2344 
2345 	Count = 0;
2346 	Gtemp = string;
2347 	string[Count++] = first_char;
2348 	string[Count] = '\0';
2349 	Time_Out = FALSE;
2350 #ifndef BSD_SELECT
2351 	signal(SIGALRM, Clear);
2352 	value = alarm(1);
2353 #endif /* BSD_SELECT */
2354 	Noblock = TRUE;
2355 #ifdef SYS5
2356 	Gterminal.c_cc[VTIME] = 0;		/* timeout value	*/
2357 	Gterminal.c_lflag &= ~ICANON;	/* disable canonical operation	*/
2358 	Gterminal.c_lflag &= ~ECHO;		/* disable echo		*/
2359 #endif
2360 	Count = 1;
2361 	Found = FALSE;
2362 	while ((Count < Max_Key_len) && (!Time_Out) && (!Found))
2363 	{
2364 		in_char = wgetch(stdscr);
2365 #ifdef DEBUG
2366 fprintf(stderr, "back in GetKey()\n");
2367 fflush(stderr);
2368 #endif /* DEBUG */
2369 		if (in_char != -1)
2370 		{
2371 			string[Count++] = in_char;
2372 			string[Count] = '\0';
2373 			St_point = KEY_TOS;
2374 			while ((St_point != NULL) && (!Found))
2375 			{
2376 				if (!strcmp(string, St_point->element->string))
2377 					Found = TRUE;
2378 				else
2379 					St_point = St_point->next;
2380 			}
2381 		}
2382 	}
2383 #ifndef BSD_SELECT
2384 	if (!Time_Out)
2385 		value = alarm(0);
2386 #endif /* BSD_SELECT */
2387 #ifdef SYS5
2388 /*	value = ioctl(0, TCSETA, &Terminal);*/
2389 #else
2390 	value = ioctl(0, TIOCSETP, &Terminal);
2391 /*	value = fcntl(0, F_SETFL, old_arg);*/
2392 #endif
2393 	Noblock = FALSE;
2394 	if (Found)
2395 	{
2396 		return(St_point->element->value);
2397 	}
2398 	else
2399 	{
2400 		while (Count > 1)
2401 		{
2402 			if ((string[--Count] != -1) &&
2403 					((unsigned char) (string[Count]) != 255))
2404 			{
2405 #ifdef DIAG
2406 fprintf(stderr, "ungetting character %d\n", string[Count]);fflush(stdout);
2407 #endif
2408 				ungetch(string[Count]);
2409 			}
2410 		}
2411 		return(first_char);
2412 	}
2413 }
2414 
2415 void
waddch(window,c)2416 waddch(window, c)	/* output the character in the specified window	*/
2417 WINDOW *window;
2418 int c;
2419 {
2420 	int column, j;
2421 	int shift;	/* number of spaces to shift if a tab		*/
2422 	struct _line *tmpline;
2423 
2424 #ifdef DIAG
2425 /*printf("starting waddch \n");fflush(stdout);*/
2426 #endif
2427 	column = window->LX;
2428 	if (c == '\t')
2429 	{
2430 		shift = (column + 1) % 8;
2431 		if (shift == 0)
2432 			shift++;
2433 		else
2434 			shift = 9 - shift;
2435 		while (shift > 0)
2436 		{
2437 			shift--;
2438 			waddch(window, ' ');
2439 		}
2440 	}
2441 	else if ((column < window->Num_cols) && (window->LY < window->Num_lines))
2442 	{
2443 		if ((c == '~') && (Booleans[hz__]))
2444 			c = '@';
2445 
2446 		if (( c != '\b') && (c != '\n') && (c != '\r'))
2447 		{
2448 			tmpline = window->line_array[window->LY];
2449 			tmpline->row[column] = c;
2450 			tmpline->attributes[column] = window->Attrib;
2451 			tmpline->changed = TRUE;
2452 			if (column >= tmpline->last_char)
2453 			{
2454 				if (column > tmpline->last_char)
2455 					for (j = tmpline->last_char; j < column; j++)
2456 					{
2457 						tmpline->row[j] = ' ';
2458 						tmpline->attributes[j] = '\0';
2459 					}
2460 				tmpline->row[column + 1] = '\0';
2461 				tmpline->attributes[column + 1] = '\0';
2462 				tmpline->last_char = column + 1;
2463 			}
2464 		}
2465 		if (c == '\n')
2466 		{
2467 			wclrtoeol(window);
2468 			window->LX = window->Num_cols;
2469 		}
2470 		else if (c == '\r')
2471 			window->LX = 0;
2472 		else if (c == '\b')
2473 			window->LX--;
2474 		else
2475 			window->LX++;
2476 	}
2477 	if (window->LX >= window->Num_cols)
2478 	{
2479 		window->LX = 0;
2480 		window->LY++;
2481 		if (window->LY >= window->Num_lines)
2482 		{
2483 			window->LY = window->Num_lines - 1;
2484 /*			window->LY = row;
2485 			wmove(window, 0, 0);
2486 			wdeleteln(window);
2487 			wmove(window, row, 0);*/
2488 		}
2489 	}
2490 	window->SCROLL_CLEAR = CHANGE;
2491 }
2492 
2493 void
winsertln(window)2494 winsertln(window)	/* insert a blank line into the specified window */
2495 WINDOW *window;
2496 {
2497 	int row, column;
2498 	struct _line *tmp;
2499 	struct _line *tmp1;
2500 
2501 	window->scroll_down += 1;
2502 	window->SCROLL_CLEAR = SCROLL;
2503 	column = window->LX;
2504 	row = window->LY;
2505 	for (row = 0, tmp = window->first_line; (row < window->Num_lines) && (tmp->next_screen != NULL); row++)
2506 		tmp = tmp->next_screen;
2507 	if (tmp->prev_screen != NULL)
2508 		tmp->prev_screen->next_screen = NULL;
2509 	tmp1 = tmp;
2510 	clear_line(tmp1, 0, window->Num_cols);
2511 	tmp1->number = -1;
2512 	for (row = 0, tmp = window->first_line; (row < window->LY) && (tmp->next_screen != NULL); row++)
2513 		tmp = tmp->next_screen;
2514 	if ((window->LY == (window->Num_lines - 1)) && (window->Num_lines > 1))
2515 	{
2516 		tmp1->next_screen = tmp->next_screen;
2517 		tmp->next_screen = tmp1;
2518 		tmp->changed = TRUE;
2519 		tmp->next_screen->prev_screen = tmp;
2520 	}
2521 	else if (window->Num_lines > 1)
2522 	{
2523 		if (tmp->prev_screen != NULL)
2524 			tmp->prev_screen->next_screen = tmp1;
2525 		tmp1->prev_screen = tmp->prev_screen;
2526 		tmp->prev_screen = tmp1;
2527 		tmp1->next_screen = tmp;
2528 		tmp->changed = TRUE;
2529 		tmp->scroll = DOWN;
2530 	}
2531 	if (window->LY == 0)
2532 		window->first_line = tmp1;
2533 
2534 	for (row = 0, tmp1 = window->first_line;
2535 		row < window->Num_lines; row++)
2536 	{
2537 		window->line_array[row] = tmp1;
2538 		tmp1 = tmp1->next_screen;
2539 	}
2540 }
2541 
2542 void
wdeleteln(window)2543 wdeleteln(window)	/* delete a line in the specified window */
2544 WINDOW *window;
2545 {
2546 	int row, column;
2547 	struct _line *tmp;
2548 	struct _line  *tmpline;
2549 
2550 	if (window->Num_lines > 1)
2551 	{
2552 		window->scroll_up += 1;
2553 		window->SCROLL_CLEAR = SCROLL;
2554 		column = window->LX;
2555 		row = window->LY;
2556 		for (row = 0, tmp = window->first_line; row < window->LY; row++)
2557 			tmp = tmp->next_screen;
2558 		if (window->LY == 0)
2559 			window->first_line = tmp->next_screen;
2560 		if (tmp->prev_screen != NULL)
2561 			tmp->prev_screen->next_screen = tmp->next_screen;
2562 		if (tmp->next_screen != NULL)
2563 		{
2564 			tmp->next_screen->changed = TRUE;
2565 			tmp->next_screen->scroll = UP;
2566 			tmp->next_screen->prev_screen = tmp->prev_screen;
2567 		}
2568 		tmpline = tmp;
2569 		clear_line(tmpline, 0, window->Num_cols);
2570 		tmpline->number = -1;
2571 		for (row = 0, tmp = window->first_line; tmp->next_screen != NULL; row++)
2572 			tmp = tmp->next_screen;
2573 		if (tmp != NULL)
2574 		{
2575 			tmp->next_screen = tmpline;
2576 			tmp->next_screen->prev_screen = tmp;
2577 			tmp->changed = TRUE;
2578 			tmp = tmp->next_screen;
2579 		}
2580 		else
2581 			tmp = tmpline;
2582 		tmp->next_screen = NULL;
2583 
2584 		for (row = 0, tmp = window->first_line; row < window->Num_lines; row++)
2585 		{
2586 			window->line_array[row] = tmp;
2587 			tmp = tmp->next_screen;
2588 		}
2589 	}
2590 	else
2591 	{
2592 		clear_line(window->first_line, 0, window->Num_cols);
2593 	}
2594 }
2595 
2596 void
wclrtobot(window)2597 wclrtobot(window)	/* delete from current position to end of the window */
2598 WINDOW *window;
2599 {
2600 	int row, column;
2601 	struct _line *tmp;
2602 
2603 	window->SCROLL_CLEAR |= CLEAR;
2604 	column = window->LX;
2605 	row = window->LY;
2606 	for (row = 0, tmp = window->first_line; row < window->LY; row++)
2607 		tmp = tmp->next_screen;
2608 	clear_line(tmp, column, window->Num_cols);
2609 	for (row = (window->LY + 1); row < window->Num_lines; row++)
2610 	{
2611 		tmp = tmp->next_screen;
2612 		clear_line(tmp, 0, window->Num_cols);
2613 	}
2614 	wmove(window, row, column);
2615 }
2616 
2617 void
wstandout(window)2618 wstandout(window)	/* begin standout mode in window	*/
2619 WINDOW *window;
2620 {
2621 	if (Numbers[sg__] < 1)	/* if not magic cookie glitch	*/
2622 		window->Attrib |= A_STANDOUT;
2623 }
2624 
2625 void
wstandend(window)2626 wstandend(window)	/* end standout mode in window	*/
2627 WINDOW *window;
2628 {
2629 	window->Attrib &= ~A_STANDOUT;
2630 }
2631 
2632 void
waddstr(window,string)2633 waddstr(window, string)	/* write 'string' in window	*/
2634 WINDOW *window;
2635 char *string;
2636 {
2637 	char *wstring;
2638 
2639 	for (wstring = string; *wstring != '\0'; wstring++)
2640 		waddch(window, *wstring);
2641 }
2642 
2643 void
clearok(window,flag)2644 clearok(window, flag)	/* erase screen and redraw at next refresh	*/
2645 WINDOW *window;
2646 int flag;
2647 {
2648 	Repaint_screen = TRUE;
2649 }
2650 
2651 
2652 void
echo()2653 echo()			/* turn on echoing				*/
2654 {
2655 	int value;
2656 
2657 #ifdef SYS5
2658 	Terminal.c_lflag |= ECHO;		/* enable echo		*/
2659 	value = ioctl(0, TCSETA, &Terminal);	/* set characteristics	*/
2660 #else
2661 	Terminal.sg_flags |= ECHO;		/* enable echo		*/
2662 	value = ioctl(0, TIOCSETP, &Terminal);	/* set characteristics	*/
2663 #endif
2664 }
2665 
2666 void
noecho()2667 noecho()		/* turn off echoing				*/
2668 {
2669 	int value;
2670 
2671 #ifdef SYS5
2672 	Terminal.c_lflag &= ~ECHO;		/* disable echo		*/
2673 	value = ioctl(0, TCSETA, &Terminal);	/* set characteristics	*/
2674 #else
2675 	Terminal.sg_flags &= ~ECHO;		/* disable echo		*/
2676 	value = ioctl(0, TIOCSETP, &Terminal);	/* set characteristics	*/
2677 #endif
2678 }
2679 
2680 void
raw()2681 raw()			/* set to read characters immediately		*/
2682 {
2683 	int value;
2684 
2685 #ifdef SYS5
2686 	Intr = Terminal.c_cc[VINTR];	/* get the interrupt character	*/
2687 	Terminal.c_lflag &= ~ICANON;	/* disable canonical operation	*/
2688 	Terminal.c_lflag &= ~ISIG;	/* disable signal checking	*/
2689 #ifdef FLUSHO
2690 	Terminal.c_lflag &= ~FLUSHO;
2691 #endif
2692 #ifdef PENDIN
2693 	Terminal.c_lflag &= ~PENDIN;
2694 #endif
2695 #ifdef IEXTEN
2696 	Terminal.c_lflag &= ~IEXTEN;
2697 #endif
2698 	Terminal.c_cc[VMIN] = 1;		/* minimum of one character */
2699 	Terminal.c_cc[VTIME] = 0;		/* timeout value	*/
2700 	Terminal.c_cc[VINTR] = 0;		/* eliminate interrupt	*/
2701 	value = ioctl(0, TCSETA, &Terminal);	/* set characteristics	*/
2702 #else
2703 	Terminal.sg_flags |= RAW;	/* enable raw mode		*/
2704 	value = ioctl(0, TIOCSETP, &Terminal);	/* set characteristics	*/
2705 #endif
2706 }
2707 
2708 void
noraw()2709 noraw()			/* set to normal character read mode		*/
2710 {
2711 	int value;
2712 
2713 #ifdef SYS5
2714 	Terminal.c_lflag |= ICANON;	/* enable canonical operation	*/
2715 	Terminal.c_lflag |= ISIG;	/* enable signal checking	*/
2716 	Terminal.c_cc[VEOF] = 4;		/* EOF character = 4	*/
2717 	Terminal.c_cc[VEOL] = '\0';	/* EOL = 0		*/
2718 	Terminal.c_cc[VINTR] = Intr;		/* reset interrupt char	*/
2719 	value = ioctl(0, TCSETA, &Terminal);	/* set characteristics	*/
2720 #else
2721 	Terminal.sg_flags &= ~RAW;	/* disable raw mode		*/
2722 	value = ioctl(0, TIOCSETP, &Terminal);	/* set characteristics	*/
2723 /*	old_arg = fcntl(0, F_GETFL, 0);
2724 	value = fcntl(0, F_SETFL, old_arg & ~FNDELAY);*/
2725 #endif
2726 }
2727 
2728 void
nl()2729 nl()
2730 {
2731 	int value;
2732 
2733 #ifdef SYS5
2734 	Terminal.c_iflag |= ICRNL;	/* enable carriage-return to line-feed mapping	*/
2735 	value = ioctl(0, TCSETA, &Terminal);	/* set characteristics	*/
2736 #endif
2737 }
2738 
2739 void
nonl()2740 nonl()
2741 {
2742 	int value;
2743 
2744 #ifdef SYS5
2745 	Terminal.c_iflag &= ~ICRNL;	/* disable carriage-return to line-feed mapping	*/
2746 	Terminal.c_iflag &= ~IGNCR;	/* do not ignore carriage-return	*/
2747 	value = ioctl(0, TCSETA, &Terminal);	/* set characteristics	*/
2748 #endif
2749 }
2750 
2751 void
saveterm()2752 saveterm()
2753 {
2754 }
2755 
2756 void
fixterm()2757 fixterm()
2758 {
2759 }
2760 
2761 void
resetterm()2762 resetterm()
2763 {
2764 }
2765 
2766 void
nodelay(window,flag)2767 nodelay(window, flag)
2768 WINDOW *window;
2769 int flag;
2770 {
2771 }
2772 
2773 void
idlok(window,flag)2774 idlok(window, flag)
2775 WINDOW *window;
2776 int flag;
2777 {
2778 }
2779 
2780 void
keypad(window,flag)2781 keypad(window, flag)
2782 WINDOW *window;
2783 int flag;
2784 {
2785 	if (flag)
2786 		String_Out(String_table[ks__], NULL, 0);
2787 	else
2788 		String_Out(String_table[ke__], NULL, 0);
2789 }
2790 
2791 void
savetty()2792 savetty()		/* save current tty stats			*/
2793 {
2794 	int value;
2795 
2796 #ifdef SYS5
2797 	value = ioctl(0, TCGETA, &Saved_tty);	/* set characteristics	*/
2798 #else
2799 	value = ioctl(0, TIOCGETP, &Saved_tty);	/* set characteristics	*/
2800 #endif
2801 }
2802 
2803 void
resetty()2804 resetty()		/* restore previous tty stats			*/
2805 {
2806 	int value;
2807 
2808 #ifdef SYS5
2809 	value = ioctl(0, TCSETA, &Saved_tty);	/* set characteristics	*/
2810 #else
2811 	value = ioctl(0, TIOCSETP, &Saved_tty);	/* set characteristics	*/
2812 #endif
2813 }
2814 
2815 void
endwin()2816 endwin()		/* end windows					*/
2817 {
2818 	keypad(stdscr, FALSE);
2819 	initialized = FALSE;
2820 	delwin(curscr);
2821 	delwin(virtual_scr);
2822 	delwin(stdscr);
2823 #ifndef SYS5
2824 {
2825 	int old_arg, value;
2826 /*	old_arg = fcntl(0, F_GETFL, 0);
2827 	value = fcntl(0, F_SETFL, old_arg & ~FNDELAY);*/
2828 }
2829 #endif
2830 }
2831 
2832 void
delwin(window)2833 delwin(window)		/* delete the window structure			*/
2834 WINDOW *window;
2835 {
2836 	int i;
2837 
2838 	for (i = 1; (i < window->Num_lines) && (window->first_line->next_screen != NULL); i++)
2839 	{
2840 		window->first_line = window->first_line->next_screen;
2841 		free(window->first_line->prev_screen->row);
2842 		free(window->first_line->prev_screen->attributes);
2843 		free(window->first_line->prev_screen);
2844 	}
2845 	if (window == last_window_refreshed)
2846 		last_window_refreshed = 0;
2847 	if (window->first_line != NULL)
2848 	{
2849 		free(window->first_line->row);
2850 		free(window->first_line->attributes);
2851 		free(window->first_line);
2852 		free(window);
2853 	}
2854 }
2855 
2856 #ifndef __STDC__
2857 void
wprintw(va_alist)2858 wprintw(va_alist)
2859 va_dcl
2860 #else /* __STDC__ */
2861 void
2862 wprintw(WINDOW *window, const char *format, ...)
2863 #endif /* __STDC__ */
2864 {
2865 #ifndef __STDC__
2866 	WINDOW *window;
2867 	char *format;
2868 	va_list ap;
2869 #else
2870 	va_list ap;
2871 #endif
2872 	int value;
2873 	char *fpoint;
2874 	char *wtemp;
2875 
2876 #ifndef __STDC__
2877 	va_start(ap);
2878 	window = va_arg(ap, WINDOW *);
2879 	format = va_arg(ap, char *);
2880 #else /* __STDC__ */
2881 	va_start(ap, format);
2882 #endif /* __STDC__ */
2883 
2884 	fpoint = (char *) format;
2885 	while (*fpoint != '\0')
2886 	{
2887 		if (*fpoint == '%')
2888 		{
2889 			fpoint++;
2890 			if (*fpoint == 'd')
2891 			{
2892 				value = va_arg(ap, int);
2893 				iout(window, value);
2894 			}
2895 			else if (*fpoint == 'c')
2896 			{
2897 				value = va_arg(ap, int);
2898 				waddch(window, value);
2899 			}
2900 			else if (*fpoint == 's')
2901 			{
2902 				wtemp = va_arg(ap, char *);
2903 					waddstr(window, wtemp);
2904 			}
2905 			fpoint++;
2906 		}
2907 		else if (*fpoint == '\\')
2908 		{
2909 			fpoint++;
2910 			if (*fpoint == 'n')
2911 				waddch(window, '\n');
2912 			else if ((*fpoint >= '0') && (*fpoint <= '9'))
2913 			{
2914 				value = 0;
2915 				while ((*fpoint >= '0') && (*fpoint <= '9'))
2916 				{
2917 					value = (value * 8) + (*fpoint - '0');
2918 					fpoint++;
2919 				}
2920 				waddch(window, value);
2921 			}
2922 			fpoint++;
2923 		}
2924 		else
2925 			waddch(window, *fpoint++);
2926 	}
2927 #ifdef __STDC__
2928 	va_end(ap);
2929 #endif /* __STDC__ */
2930 }
2931 
2932 void
iout(window,value)2933 iout(window, value)	/* output characters		*/
2934 WINDOW *window;
2935 int value;
2936 {
2937 	int i;
2938 
2939 	if ((i = value / 10) != 0)
2940 		iout(window, i);
2941 	waddch(window, ((value % 10) + '0'));
2942 }
2943 
2944 int
Comp_line(line1,line2)2945 Comp_line(line1, line2)		/* compare lines	*/
2946 struct _line *line1;
2947 struct _line *line2;
2948 {
2949 	int count1;
2950 	int i;
2951 	char *att1, *att2;
2952 	char *c1, *c2;
2953 
2954 	if (line1->last_char != line2->last_char)
2955 		return(2);
2956 
2957 	c1 = line1->row;
2958 	c2 = line2->row;
2959 	att1 = line1->attributes;
2960 	att2 = line2->attributes;
2961 	i = 0;
2962 	while ((c1[i] != '\0') && (c2[i] != '\0') && (c1[i] == c2[i]) && (att1[i] == att2[i]))
2963 		i++;
2964 	count1 = i + 1;
2965 	if ((count1 == 1) && (c1[i] == '\0') && (c2[i] == '\0'))
2966 		count1 = 0;			/* both lines blank	*/
2967 	else if ((c1[i] == '\0') && (c2[i] == '\0'))
2968 		count1 = -1;			/* equal		*/
2969 	else
2970 		count1 = 1;			/* lines unequal	*/
2971 	return(count1);
2972 }
2973 
2974 struct _line *
Insert_line(row,end_row,window)2975 Insert_line(row, end_row, window)	/* insert line into screen */
2976 int row;
2977 int end_row;
2978 WINDOW *window;
2979 {
2980 	int i;
2981 	struct _line *tmp;
2982 	struct _line *tmp1;
2983 
2984 	for (i = 0, tmp = curscr->first_line; i < window->SR; i++)
2985 		tmp = tmp->next_screen;
2986 	if ((end_row + window->SR) == 0)
2987 		curscr->first_line = curscr->first_line->next_screen;
2988 	top_of_win = tmp;
2989 	/*
2990 	 |	find bottom line to delete
2991 	 */
2992 	for (i = 0, tmp = top_of_win; (tmp->next_screen != NULL) && (i < end_row); i++)
2993 		tmp = tmp->next_screen;
2994 	if (tmp->prev_screen != NULL)
2995 		tmp->prev_screen->next_screen = tmp->next_screen;
2996 	if (tmp->next_screen != NULL)
2997 		tmp->next_screen->prev_screen = tmp->prev_screen;
2998 	tmp1 = tmp;
2999 	/*
3000 	 |	clear deleted line
3001 	 */
3002 	clear_line(tmp, 0, window->Num_cols);
3003 	tmp1->number = -1;
3004 	for (i = 0, tmp = curscr->first_line; (tmp->next_screen != NULL) && (i < window->SR); i++)
3005 		tmp = tmp->next_screen;
3006 	top_of_win = tmp;
3007 	for (i = 0, tmp = top_of_win; i < row; i++)
3008 		tmp = tmp->next_screen;
3009 	if ((tmp->prev_screen != NULL) && (window->Num_lines > 0))
3010 		tmp->prev_screen->next_screen = tmp1;
3011 	tmp1->prev_screen = tmp->prev_screen;
3012 	tmp->prev_screen = tmp1;
3013 	tmp1->next_screen = tmp;
3014 	if ((row + window->SR) == 0)
3015 		curscr->first_line = tmp1;
3016 	if (tmp1->next_screen != NULL)
3017 		tmp1 = tmp1->next_screen;
3018 
3019 	if ((!String_table[cs__]) && (end_row < window->Num_lines))
3020 	{
3021 		Position(window, (window->SR + end_row), 0);
3022 		String_Out(String_table[dl__], NULL, 0);
3023 	}
3024 	Position(window, (window->SR + row), 0);
3025 	if (String_table[al__] != NULL)
3026 		String_Out(String_table[al__], NULL, 0);
3027 	else
3028 		String_Out(String_table[sr__], NULL, 0);
3029 
3030 	for (i = 0, top_of_win = curscr->first_line; (top_of_win->next_screen != NULL) && (i < window->SR); i++)
3031 		top_of_win = top_of_win->next_screen;
3032 	return(tmp1);
3033 }
3034 
3035 
3036 struct _line *
Delete_line(row,end_row,window)3037 Delete_line(row, end_row, window)	/* delete a line on screen */
3038 int row;
3039 int end_row;
3040 WINDOW *window;
3041 {
3042 	int i;
3043 	struct _line *tmp;
3044 	struct _line *tmp1;
3045 	struct _line *tmp2;
3046 
3047 	i = 0;
3048 	tmp = curscr->first_line;
3049 	while (i < window->SR)
3050 	{
3051 		i++;
3052 		tmp = tmp->next_screen;
3053 	}
3054 	/*
3055 	 |	find line to delete
3056 	 */
3057 	top_of_win = tmp;
3058 	if ((row + window->SR) == 0)
3059 		curscr->first_line = top_of_win->next_screen;
3060 	for (i = 0, tmp = top_of_win; i < row; i++)
3061 		tmp = tmp->next_screen;
3062 	if (tmp->prev_screen != NULL)
3063 		tmp->prev_screen->next_screen = tmp->next_screen;
3064 	if (tmp->next_screen != NULL)
3065 		tmp->next_screen->prev_screen = tmp->prev_screen;
3066 	tmp2 = tmp->next_screen;
3067 	tmp1 = tmp;
3068 	/*
3069 	 |	clear deleted line
3070 	 */
3071 	clear_line(tmp1, 0, window->Num_cols);
3072 	tmp1->number = -1;
3073 	/*
3074 	 |	find location to insert deleted line
3075 	 */
3076 	for (i = 0, tmp = curscr->first_line; (tmp->next_screen != NULL) && (i < window->SR); i++)
3077 		tmp = tmp->next_screen;
3078 	top_of_win = tmp;
3079 	for (i = 0, tmp = top_of_win; (i < end_row) && (tmp->next_screen != NULL); i++)
3080 		tmp = tmp->next_screen;
3081 	tmp1->next_screen = tmp;
3082 	tmp1->prev_screen = tmp->prev_screen;
3083 	if (tmp1->prev_screen != NULL)
3084 		tmp1->prev_screen->next_screen = tmp1;
3085 	tmp->prev_screen = tmp1;
3086 
3087 	Position(window, (window->SR + row), 0);
3088 	String_Out(String_table[dl__], NULL, 0);
3089 	if ((!String_table[cs__]) && (end_row < window->Num_lines))
3090 	{
3091 		Position(window, (window->SR + end_row), 0);
3092 		String_Out(String_table[al__], NULL, 0);
3093 	}
3094 	else if ((String_table[cs__] != NULL) && (String_table[dl__] == NULL))
3095 	{
3096 		Position(window, (window->SR + end_row), 0);
3097 		putchar('\n');
3098 	}
3099 
3100 	if (row == (window->Num_lines-1))
3101 		tmp2 = tmp1;
3102 	if ((row + window->SR) == 0)
3103 		curscr->first_line = top_of_win = tmp2;
3104 	return(tmp2);
3105 }
3106 
3107 void
CLEAR_TO_EOL(window,row,column)3108 CLEAR_TO_EOL(window, row, column)
3109 WINDOW *window;
3110 int row, column;
3111 {
3112 	int x, y;
3113 	struct _line *tmp1;
3114 
3115 	for (y = 0, tmp1 = curscr->first_line; (y < (window->SR+row)) && (tmp1->next_screen != NULL); y++)
3116 		tmp1 = tmp1->next_screen;
3117 	for (x = column; x<window->Num_cols; x++)
3118 	{
3119 		tmp1->row[x] = ' ';
3120 		tmp1->attributes[x] = '\0';
3121 	}
3122 	tmp1->row[column] = '\0';
3123 	tmp1->last_char = column;
3124 	if (column < COLS)
3125 	{
3126 		if (STAND)
3127 		{
3128 			STAND = FALSE;
3129 			Position(window, row, column);
3130 			attribute_off();
3131 		}
3132 		if (String_table[ce__] != NULL)
3133 			String_Out(String_table[ce__], NULL, 0);
3134 		else
3135 		{
3136 			for (x = column; x < window->Num_cols; x++)
3137 				putchar(' ');
3138 			Curr_x = x;
3139 		}
3140 	}
3141 }
3142 
3143 int
check_delete(window,line,offset,pointer_new,pointer_old)3144 check_delete(window, line, offset, pointer_new, pointer_old)
3145 WINDOW *window;
3146 int line, offset;
3147 struct _line *pointer_new, *pointer_old;
3148 {
3149 	int end_old;
3150 	int end_new;
3151 	int k;
3152 	int changed;
3153 	char *old_lin;
3154 	char *new_lin;
3155 	char *old_att;
3156 	char *new_att;
3157 
3158 	changed = FALSE;
3159 	new_lin = pointer_new->row;
3160 	new_att = pointer_new->attributes;
3161 	old_lin = pointer_old->row;
3162 	old_att = pointer_old->attributes;
3163 	end_old = end_new = offset;
3164 	while (((new_lin[end_new] != old_lin[end_old]) || (new_att[end_new] != old_att[end_old])) && (old_lin[end_old] != '\0') && (new_lin[end_old] != '\0'))
3165 		end_old++;
3166 	if (old_lin[end_old] != '\0')
3167 	{
3168 		k = 0;
3169 		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] != '\0') && (old_lin[end_old+k] != '\0') && (k < 10))
3170 			k++;
3171 		if ((k > 8) || ((new_lin[end_new+k] == '\0') && (k != 0)))
3172 		{
3173 			if (new_lin[end_new+k] == '\0')
3174 			{
3175 				Position(window, line, (end_new+k));
3176 				CLEAR_TO_EOL(window, line, (end_new+k));
3177 			}
3178 			Position(window, line, offset);
3179 			for (k = offset; k < end_old; k++)
3180 				Char_del(old_lin, old_att, offset, window->Num_cols);
3181 			while ((old_lin[offset] != '\0') && (offset < COLS))
3182 				offset++;
3183 			pointer_old->last_char = offset;
3184 			changed = TRUE;
3185 		}
3186 	}
3187 	return(changed);
3188 }
3189 
3190 /*
3191  |	Check if characters were inserted in the middle of a line, and if
3192  |	so, insert them.
3193  */
3194 
3195 int
check_insert(window,line,offset,pointer_new,pointer_old)3196 check_insert(window, line, offset, pointer_new, pointer_old)
3197 WINDOW *window;
3198 int line, offset;
3199 struct _line *pointer_new, *pointer_old;
3200 {
3201 	int changed;
3202 	int end_old, end_new;
3203 	int k;
3204 	int same = FALSE;
3205 	int old_off;
3206 	int insert;
3207 	char *old_lin;
3208 	char *new_lin;
3209 	char *old_att;
3210 	char *new_att;
3211 
3212 	changed = FALSE;
3213 	new_lin = pointer_new->row;
3214 	new_att = pointer_new->attributes;
3215 	old_lin = pointer_old->row;
3216 	old_att = pointer_old->attributes;
3217 	end_old = end_new = offset;
3218 	while (((new_lin[end_new] != old_lin[end_old]) || (new_att[end_new] != old_att[end_old])) && (new_lin[end_new] != '\0') && (old_lin[end_new] != '\0'))
3219 		end_new++;
3220 	if (new_lin[end_new] != '\0')
3221 	{
3222 		k = 0;
3223 		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] != '\0') && (old_lin[end_old+k] != '\0') && (k < 10))
3224 			k++;
3225 		/*
3226 		 |  check for commonality between rest of lines (are the old
3227 		 |  and new lines the same, except for a chunk in the middle?)
3228 		 |  if the rest of the lines are common, do not insert text
3229 		 */
3230 		old_off = end_new;
3231 		while ((old_lin[old_off] != '\0') && (new_lin[old_off] != '\0') && (old_lin[old_off] == new_lin[old_off]) && (old_att[old_off] == new_att[old_off]))
3232 			old_off++;
3233 		if ((old_lin[old_off] == new_lin[old_off]) && (old_att[old_off] == new_att[old_off]))
3234 			same = TRUE;
3235 		if ((!same) && ((k > 8) || ((new_lin[end_new+k] == '\0') && (k != 0))))
3236 		{
3237 			Position(window, line, offset);
3238 			insert = FALSE;
3239 			if (String_table[ic__] == NULL)
3240 			{
3241 				String_Out(String_table[im__], NULL, 0);
3242 				insert = TRUE;
3243 			}
3244 			for (k = offset; k < end_new; k++)
3245 			{
3246 				if (!insert)
3247 					String_Out(String_table[ic__], NULL, 0);
3248 				Char_ins(old_lin, old_att, new_lin[k], new_att[k], k, window->Num_cols);
3249 			}
3250 			if (insert)
3251 				String_Out(String_table[ei__], NULL, 0);
3252 			while ((old_lin[offset] != '\0') && (offset < COLS))
3253 				offset++;
3254 			pointer_old->last_char = offset;
3255 			changed = TRUE;
3256 		}
3257 	}
3258 	return(changed);
3259 }
3260 
3261 void
doupdate()3262 doupdate()
3263 {
3264 	WINDOW *window;
3265 	int similar;
3266 	int diff;
3267 	int begin_old, begin_new;
3268 	int end_old, end_new;
3269 	int count1, j;
3270 	int from_top, tmp_ft, offset;
3271 	int changed;
3272 	int first_time;
3273 	int first_same;
3274 	int last_same;
3275 	int list[10];
3276 	int bottom;
3277 
3278 	struct _line *curr;
3279 	struct _line *virt;
3280 	struct _line *old;
3281 
3282 	struct _line *new;
3283 
3284 	struct _line *old1, *new1;
3285 
3286 	char *cur_lin;
3287 	char *vrt_lin;
3288 	char *cur_att;
3289 	char *vrt_att;
3290 	char *att1, *att2;
3291 	char *c1, *c2;
3292 
3293 	char NC_chinese = FALSE;	/* flag to indicate handling Chinese */
3294 
3295 	window = virtual_scr;
3296 
3297 	if ((nc_attributes & A_NC_BIG5) != 0)
3298 		NC_chinese = TRUE;
3299 
3300 	if (Repaint_screen)
3301 	{
3302 		if (String_table[cl__])
3303 			String_Out(String_table[cl__], NULL, 0);
3304 		else
3305 		{
3306 			from_top = 0;
3307 			while (from_top < LINES)
3308 			{
3309 				Position(curscr, from_top, 0);
3310 				if (String_table[ce__] != NULL)
3311 					String_Out(String_table[ce__], NULL, 0);
3312 				else
3313 				{
3314 					for (j = 0; j < window->Num_cols; j++)
3315 						putchar(' ');
3316 				}
3317 				from_top++;
3318 			}
3319 		}
3320 		for (from_top = 0, curr = curscr->first_line; from_top < curscr->Num_lines; from_top++, curr = curr->next_screen)
3321 		{
3322 			Position(curscr, from_top, 0);
3323 			for (j = 0; (curr->row[j] != '\0') && (j < curscr->Num_cols); j++)
3324 			{
3325 				Char_out(curr->row[j], curr->attributes[j], curr->row, curr->attributes, j);
3326 			}
3327 			if (STAND)
3328 			{
3329 				STAND = FALSE;
3330 				Position(curscr, from_top, j);
3331 				attribute_off();
3332 			}
3333 		}
3334 		Repaint_screen = FALSE;
3335 	}
3336 
3337 	similar = 0;
3338 	diff = FALSE;
3339 	top_of_win = curscr->first_line;
3340 
3341 	for (from_top = 0, curr = top_of_win, virt = window->first_line;
3342 			from_top < window->Num_lines; from_top++)
3343 	{
3344 		virtual_lines[from_top] = TRUE;
3345 		if ((similar = Comp_line(curr, virt)) > 0)
3346 		{
3347 			virtual_lines[from_top] = FALSE;
3348 			diff = TRUE;
3349 		}
3350 		curr = curr->next_screen;
3351 		virt = virt->next_screen;
3352 	}
3353 
3354 	from_top = 0;
3355 	virt = window->first_line;
3356 	curr = top_of_win;
3357 	similar = 0;
3358 	/*
3359 	 |  if the window has lines that are different, check for scrolling
3360 	 */
3361 	if (diff)
3362 	{
3363 		last_same = -1;
3364 		changed = FALSE;
3365 		for (first_same = window->Num_lines;
3366 		    (first_same > from_top) && (virtual_lines[first_same - 1]);
3367 		     first_same--)
3368 			;
3369 		for (last_same = 0;
3370 		    (last_same < window->Num_lines) && (virtual_lines[last_same]== FALSE);
3371 		     last_same++)
3372 			;
3373 		while ((from_top < first_same) && nc_scrolling_ability)
3374 					/* check entire lines for diffs	*/
3375 		{
3376 
3377 			if (from_top >= last_same)
3378 			{
3379 				for (last_same = from_top;
3380 				     (last_same < window->Num_lines) &&
3381 				     (virtual_lines[last_same] == FALSE);
3382 				      last_same++)
3383 					;
3384 			}
3385 			if (!virtual_lines[from_top])
3386 			{
3387 				diff = TRUE;
3388 				/*
3389 				 |	check for lines deleted (scroll up)
3390 				 */
3391 				for (tmp_ft = from_top+1, old = curr->next_screen;
3392 					((window->scroll_up) && (diff) &&
3393 					(tmp_ft < last_same) &&
3394 					(!virtual_lines[tmp_ft]));
3395 						tmp_ft++)
3396 				{
3397 					if ((Comp_line(old, virt) == -1) && (!virtual_lines[from_top]))
3398 					{
3399 						/*
3400 						 |	Find the bottom of the
3401 						 |	area that should be
3402 						 |	scrolled.
3403 						 */
3404 						for (bottom = tmp_ft, old1 = old,
3405 						     new1 = virt, count1 = 0;
3406 							(bottom < window->Num_lines) &&
3407 								(Comp_line(old1, new1) <= 0);
3408 								bottom++, old1 = old1->next_screen,
3409 								new1 = new1->next_screen,
3410 								count1++)
3411 							;
3412 						if (count1 > 3)
3413 						{
3414 							if (String_table[cs__]) /* scrolling region */
3415 							{
3416 								list[1] = from_top;
3417 								list[0] = min((bottom - 1), (window->Num_lines - 1));
3418 								String_Out(String_table[cs__], list, 2);
3419 								Curr_y = Curr_x = -1;
3420 							}
3421 
3422 							for (offset = (tmp_ft - from_top); (offset > 0); offset--)
3423 							{
3424 								old = Delete_line(from_top, min((bottom - 1), (window->Num_lines - 1)), window);
3425 								diff = FALSE;
3426 							}
3427 
3428 							if (String_table[cs__]) /* scrolling region */
3429 							{
3430 								list[1] = 0;
3431 								list[0] = LINES - 1;
3432 								String_Out(String_table[cs__], list, 2);
3433 								Curr_y = Curr_x = -1;
3434 							}
3435 
3436 							top_of_win = curscr->first_line;
3437 							curr = top_of_win;
3438 							for (offset = 0; offset < from_top; offset++)
3439 								curr = curr->next_screen;
3440 							for (offset = from_top, old=curr, new=virt;
3441 							   offset < window->Num_lines;
3442 							   old=old->next_screen, new=new->next_screen,
3443 							   offset++)
3444 							{
3445 								similar = Comp_line(old, new);
3446 								virtual_lines[offset] = (similar > 0 ? FALSE : TRUE);
3447 							}
3448 						}
3449 					}
3450 					else
3451 						old = old->next_screen;
3452 				}
3453 				/*
3454 				 |	check for lines inserted (scroll down)
3455 				 */
3456 				for (tmp_ft = from_top-1, old = curr->prev_screen;
3457 					((window->scroll_down) && (tmp_ft >= 0) &&
3458 					(diff) &&
3459 					(!virtual_lines[tmp_ft]));
3460 					  tmp_ft--)
3461 				{
3462 					if (Comp_line(old, virt) == -1)
3463 					{
3464 						/*
3465 						 |	Find the bottom of the
3466 						 |	area that should be
3467 						 |	scrolled.
3468 						 */
3469 						for (bottom = from_top, old1 = old,
3470 						     new1 = virt, count1 = 0;
3471 							(bottom < window->Num_lines) &&
3472 								(Comp_line(old1, new1) <= 0);
3473 								bottom++, old1 = old1->next_screen,
3474 								new1 = new1->next_screen,
3475 								count1++)
3476 							;
3477 						if (count1 > 3)
3478 						{
3479 							if (String_table[cs__]) /* scrolling region */
3480 							{
3481 								list[1] = tmp_ft;
3482 								list[0] = min((bottom - 1), (window->Num_lines - 1));
3483 								String_Out(String_table[cs__], list, 2);
3484 								Curr_y = Curr_x = -1;
3485 							}
3486 
3487 							for (offset = (from_top - tmp_ft); (offset > 0); offset--)
3488 							{
3489 								old = Insert_line(tmp_ft, min((bottom - 1), (window->Num_lines -1)), window);
3490 								diff = FALSE;
3491 							}
3492 
3493 							if (String_table[cs__]) /* scrolling region */
3494 							{
3495 								list[1] = 0;
3496 								list[0] = LINES - 1;
3497 								String_Out(String_table[cs__], list, 2);
3498 								Curr_y = Curr_x = -1;
3499 							}
3500 
3501 							top_of_win = curscr->first_line;
3502 							curr = top_of_win;
3503 							for (offset = 0; offset < from_top; offset++)
3504 								curr = curr->next_screen;
3505 							for (offset = from_top, old=curr, new=virt;
3506 							   offset < window->Num_lines;
3507 							   old=old->next_screen, new=new->next_screen,
3508 							   offset++)
3509 							{
3510 								similar = Comp_line(old, new);
3511 								virtual_lines[offset] = (similar > 0 ? FALSE : TRUE);
3512 							}
3513 						}
3514 					}
3515 					else
3516 						old = old->prev_screen;
3517 				}
3518 			}
3519 			from_top++;
3520 			curr = curr->next_screen;
3521 			virt = virt->next_screen;
3522 		}
3523 	}
3524 
3525 
3526 	/*
3527 	 |	Scrolling done, now need to insert, delete, or modify text
3528 	 |	within lines.
3529 	 */
3530 
3531 	for (from_top = 0, curr = curscr->first_line; from_top < window->SR; from_top++)
3532 		curr = curr->next_screen;
3533 	top_of_win = curr;
3534 	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)
3535 	{
3536 
3537 		/*
3538 		 |	If either 'insert mode' or 'insert char' are
3539 		 |	available, enter the following 'if' statement,
3540 		 |	else, need to simply rewrite the contents of the line
3541 		 |	at the point where the contents of the line change.
3542 		 */
3543 
3544 		if (((String_table[ic__]) || (String_table[im__])) &&
3545 		    (String_table[dc__]) && (curr->row[0] != '\0') &&
3546 		    (!NC_chinese))
3547 		{
3548 			j = 0;
3549 			first_time = TRUE;
3550 			vrt_lin = virt->row;
3551 			vrt_att = virt->attributes;
3552 			cur_lin = curr->row;
3553 			cur_att = curr->attributes;
3554 			while ((vrt_lin[j] != '\0') && (j < window->Num_cols))
3555 			{
3556 				if ((STAND) && (Booleans[xs__]))
3557 				{
3558 					while ((vrt_lin[j] == cur_lin[j]) && (vrt_att[j] == cur_att[j]) && (vrt_lin[j] != '\0') && (vrt_att[j]))
3559 						j++;
3560 					if ((STAND) && (!vrt_att[j]))
3561 					{
3562 						STAND = FALSE;
3563 						Position(window, from_top, j);
3564 						attribute_off();
3565 						attribute_off();
3566 					}
3567 				}
3568 				else
3569 				{
3570 					while ((vrt_lin[j] == cur_lin[j]) && (vrt_att[j] == cur_att[j]) && (vrt_lin[j] != '\0'))
3571 						j++;
3572 				}
3573 				if ((vrt_att[j] != cur_att[j]) && (cur_att[j]) && (Booleans[xs__]))
3574 				{
3575 					Position(window, from_top, j);
3576 /*					CLEAR_TO_EOL(window, from_top, j);*/
3577 					attribute_off();
3578 					attribute_off();
3579 				}
3580 				if (vrt_lin[j] != '\0')
3581 				{
3582 					begin_new = j;
3583 					begin_old = j;
3584 					end_old = j;
3585 					end_new = j;
3586 					if ((first_time) && (virt->changed))
3587 					{
3588 						if (curr->last_char <= virt->last_char)
3589 							changed = check_insert(window, from_top, j, virt, curr);
3590 					}
3591 					changed = check_delete(window, from_top, j, virt, curr);
3592 					first_time = FALSE;
3593 					virt->changed = FALSE;
3594 					if (!changed)
3595 						changed = check_insert(window, from_top, j, virt, curr);
3596 					if (((!changed) || (cur_lin[j] != vrt_lin[j]) || (cur_att[j] != vrt_att[j])) && (j < window->Num_cols))
3597 					{
3598 						if ((vrt_lin[j] == ' ') && (cur_lin[j] == '\0') && (vrt_att[j] == cur_att[j]))
3599 							cur_lin[j] = ' ';
3600 						else
3601 						{
3602 							Position(window, from_top, j);
3603 							Char_out(vrt_lin[j], vrt_att[j], cur_lin, cur_att, j);
3604 						}
3605 					}
3606 					if ((vrt_lin[j] != '\0'))
3607 						j++;
3608 				}
3609 				if ((STAND) && (!vrt_att[j]))
3610 				{
3611 					STAND = FALSE;
3612 					Position(window, from_top, j);
3613 					attribute_off();
3614 				}
3615 			}
3616 			if ((vrt_lin[j] == '\0') && (cur_lin[j] != '\0'))
3617 			{
3618 				Position(window, from_top, j);
3619 				CLEAR_TO_EOL(window, from_top, j);
3620 			}
3621 		}
3622 		else /*if ((similar != -1) && (similar != 0))*/
3623 		{
3624 			j = 0;
3625 			c1 = curr->row;
3626 			att1 = curr->attributes;
3627 			c2 = virt->row;
3628 			att2 = virt->attributes;
3629 			while ((j < window->Num_cols) && (c2[j] != '\0'))
3630 			{
3631 				while ((c1[j] == c2[j]) && (att1[j] == att2[j]) && (j < window->Num_cols) && (c2[j] != '\0'))
3632 					j++;
3633 
3634 				/*
3635 				 |	if previous character is an eight bit
3636 				 |	char, start redraw from that character
3637 				 */
3638 
3639 				if ((NC_chinese) && (highbitset(c1[j - 1])))
3640 					j--;
3641 				begin_old = j;
3642 				begin_new = j;
3643 				if ((j < window->Num_cols) && (c2[j] != '\0'))
3644 				{
3645 					Position(window, from_top, begin_old);
3646 					CLEAR_TO_EOL(window, from_top, j);
3647 					Position(window, from_top, begin_old);
3648 					for (j = begin_old; (c2[j] != '\0') && (j < window->Num_cols); j++)
3649 						Char_out(c2[j], att2[j], c1, att1, j);
3650 				}
3651 			}
3652 			if ((c2[j] == '\0') && (c1[j] != '\0'))
3653 			{
3654 				Position(window, from_top, j);
3655 				CLEAR_TO_EOL(window, from_top, j);
3656 			}
3657 		}
3658 		if (STAND)
3659 		{
3660 			STAND = FALSE;
3661 			Position(window, from_top, j);
3662 			attribute_off();
3663 		}
3664 		virt->number = from_top;
3665 	}
3666 	Position(window, window->LY, window->LX);
3667 }
3668 
3669 void
Position(window,row,col)3670 Position(window, row, col)	/* position the cursor for output on the screen	*/
3671 WINDOW *window;
3672 int row;
3673 int col;
3674 {
3675 	int list[10];
3676 	int place;
3677 
3678 	int pos_row;
3679 	int pos_column;
3680 
3681 	pos_row = row + window->SR;
3682 	pos_column = col + window->SC;
3683 	if ((pos_row != Curr_y) || (pos_column != Curr_x))
3684 	{
3685 		if (String_table[cm__] != NULL) /* && (row < window->Num_lines) && (column < window->Num_cols))*/
3686 		{
3687 			place = 0;
3688 			list[place++] = pos_column;
3689 			list[place++] = pos_row;
3690 			String_Out(String_table[cm__], list, place);
3691 			if ((STAND) && (!Booleans[ms__]))
3692 				attribute_on();
3693 		}
3694 		Curr_x = pos_column;
3695 		Curr_y = pos_row;
3696 	}
3697 }
3698 
3699 void
Char_del(line,attrib,offset,maxlen)3700 Char_del(line, attrib, offset, maxlen)	/* delete chars from line	*/
3701 char *line;
3702 char *attrib;
3703 int offset;
3704 int maxlen;
3705 {
3706 	int one, two;
3707 
3708 	for (one = offset, two = offset+1; (line[one] != '\0') && (one < maxlen); one++, two++)
3709 	{
3710 		line[one] = line[two];
3711 		attrib[one] = attrib[two];
3712 	}
3713 	String_Out(String_table[dc__], NULL, 0);
3714 }
3715 
3716 void
Char_ins(line,attrib,newc,newatt,offset,maxlen)3717 Char_ins(line, attrib, newc, newatt, offset, maxlen)	/* insert chars in line	*/
3718 char *line;
3719 char *attrib;
3720 char newc;
3721 char newatt;
3722 int offset;
3723 int maxlen;
3724 {
3725 	int one, two;
3726 
3727 	one = 0;
3728 	while ((line[one] != '\0') && (one < (maxlen - 2)))
3729 		one++;
3730 	for (two = one + 1; (two > offset); one--, two--)
3731 	{
3732 		line[two] = line[one];
3733 		attrib[two] = attrib[one];
3734 	}
3735 	line[offset] = newc;
3736 	attrib[offset] = newatt;
3737 	Char_out(newc, newatt, line, attrib, offset);
3738 }
3739 
3740 void
attribute_on()3741 attribute_on()
3742 {
3743 	if (String_table[sa__])
3744 	{
3745 		attributes_set[0] = 1;
3746 		String_Out(String_table[sa__], attributes_set, 1);
3747 	}
3748 	else if (String_table[so__])
3749 		String_Out(String_table[so__], NULL, 0);
3750 }
3751 
3752 void
attribute_off()3753 attribute_off()
3754 {
3755 	if (String_table[me__])
3756 		String_Out(String_table[me__], NULL, 0);
3757 	else if (String_table[sa__])
3758 	{
3759 		attributes_set[0] = 0;
3760 		String_Out(String_table[sa__], attributes_set, 1);
3761 	}
3762 	else if (String_table[se__])
3763 		String_Out(String_table[se__], NULL, 0);
3764 }
3765 
3766 void
Char_out(newc,newatt,line,attrib,offset)3767 Char_out(newc, newatt, line, attrib, offset)	/* output character with proper attribute	*/
3768 char newc;
3769 char newatt;
3770 char *line;
3771 char *attrib;
3772 int offset;
3773 {
3774 
3775 
3776 	if ((newatt) && (!STAND))
3777 	{
3778 		STAND = TRUE;
3779 		attribute_on();
3780 	}
3781 	else if ((STAND) && (!newatt))
3782 	{
3783 		STAND = FALSE;
3784 		attribute_off();
3785 	}
3786 
3787 	if ((newatt) && (STAND) && (Booleans[xs__]))
3788 	{
3789 		attribute_on();
3790 	}
3791 
3792 	if (!((Curr_y >= (LINES - 1)) && (Curr_x >= (COLS - 1))))
3793 	{
3794 		putchar(newc);
3795 		line[offset] = newc;
3796 		attrib[offset] = newatt;
3797 	}
3798 	Curr_x++;
3799 }
3800 
3801 /*
3802  |
3803  |	The two routines that follow, nc_setattrib(), nc_clearattrib(), are
3804  |	hacks that notify new_curse to handle characters that have the high
3805  |	bit set as the first of two bytes of a multi-byte string.
3806  |
3807  */
3808 
3809 void
nc_setattrib(flag)3810 nc_setattrib(flag)
3811 int flag;
3812 {
3813 	nc_attributes |= flag;
3814 }
3815 
3816 void
nc_clearattrib(flag)3817 nc_clearattrib(flag)
3818 int flag;
3819 {
3820 	nc_attributes &= ~flag;
3821 }
3822 
3823