xref: /freebsd/contrib/ee/new_curse.c (revision 72fcea8cb7f1eb4a5e673d5c5d0586d8d28425cc)
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.50 2001/01/19 02:53:40 hugh Exp hugh $
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.50 $";
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 struct KEYS {
505 	int length;	/* length of string sent by key			*/
506 	char *string;	/* string sent by key				*/
507 	int value;	/* CURSES value of key (9-bit)			*/
508 	};
509 
510 struct KEY_STACK {
511 	struct KEYS *element;
512 	struct KEY_STACK *next;
513 	};
514 
515 struct KEY_STACK *KEY_TOS = NULL;
516 struct KEY_STACK *KEY_POINT;
517 
518 /*
519  |
520  |	Not all systems have good terminal information, so we will define
521  |	keyboard information here for the most widely used terminal type,
522  |	the VT100.
523  |
524  */
525 
526 struct KEYS vt100[] =
527 	{
528 		{ 3, "\033[A", 0403 },	/* key up 	*/
529 		{ 3, "\033[C", 0405 },	/* key right	*/
530 		{ 3, "\033[D", 0404 },	/* key left	*/
531 
532 		{ 4, "\033[6~", 0522 },	/* key next page	*/
533 		{ 4, "\033[5~", 0523 },	/* key prev page	*/
534 		{ 3, "\033[[", 0550 },	/* key end	*/
535 		{ 3, "\033[@", 0406 },	/* key home	*/
536 		{ 4, "\033[2~", 0513 },	/* key insert char	*/
537 
538 		{ 3, "\033[y", 0410 },	/* key F0	*/
539 		{ 3, "\033[P", 0411 },	/* key F1	*/
540 		{ 3, "\033[Q", 0412 },	/* key F2	*/
541 		{ 3, "\033[R", 0413 },	/* key F3	*/
542 		{ 3, "\033[S", 0414 },	/* key F4	*/
543 		{ 3, "\033[t", 0415 },	/* key F5	*/
544 		{ 3, "\033[u", 0416 },	/* key F6	*/
545 		{ 3, "\033[v", 0417 },	/* key F7	*/
546 		{ 3, "\033[l", 0420 },	/* key F8	*/
547 		{ 3, "\033[w", 0421 },	/* key F9	*/
548 		{ 3, "\033[x", 0422 },	/* key F10	*/
549 
550 		{ 5, "\033[10~", 0410 },	/* key F0	*/
551 		{ 5, "\033[11~", 0411 },	/* key F1	*/
552 		{ 5, "\033[12~", 0412 },	/* key F2	*/
553 		{ 5, "\033[13~", 0413 },	/* key F3	*/
554 		{ 5, "\033[14~", 0414 },	/* key F4	*/
555 		{ 5, "\033[15~", 0415 },	/* key F5	*/
556 		{ 5, "\033[17~", 0416 },	/* key F6	*/
557 		{ 5, "\033[18~", 0417 },	/* key F7	*/
558 		{ 5, "\033[19~", 0420 },	/* key F8	*/
559 		{ 5, "\033[20~", 0421 },	/* key F9	*/
560 		{ 5, "\033[21~", 0422 },	/* key F10	*/
561 		{ 5, "\033[23~", 0423 },	/* key F11	*/
562 		{ 5, "\033[24~", 0424 },	/* key F12	*/
563 		{ 3, "\033[q", 0534 },	/* ka1 upper-left of keypad	*/
564 		{ 3, "\033[s", 0535 },	/* ka3 upper-right of keypad	*/
565 		{ 3, "\033[r", 0536 },	/* kb2 center of keypad	*/
566  		{ 3, "\033[p", 0537 },	/* kc1 lower-left of keypad	*/
567 		{ 3, "\033[n", 0540 },	/* kc3 lower-right of keypad	*/
568 
569 		/*
570 		 |	The following are the same keys as above, but with
571 		 |	a different character following the escape char.
572 		 */
573 
574 		{ 3, "\033OA", 0403 },	/* key up 	*/
575 		{ 3, "\033OC", 0405 },	/* key right	*/
576 		{ 3, "\033OD", 0404 },	/* key left	*/
577 		{ 3, "\033OB", 0402 },	/* key down	*/
578 		{ 4, "\033O6~", 0522 },	/* key next page	*/
579 		{ 4, "\033O5~", 0523 },	/* key prev page	*/
580 		{ 3, "\033O[", 0550 },	/* key end	*/
581 		{ 3, "\033O@", 0406 },	/* key home	*/
582 		{ 4, "\033O2~", 0513 },	/* key insert char	*/
583 
584 		{ 3, "\033Oy", 0410 },	/* key F0	*/
585 		{ 3, "\033OP", 0411 },	/* key F1	*/
586 		{ 3, "\033OQ", 0412 },	/* key F2	*/
587 		{ 3, "\033OR", 0413 },	/* key F3	*/
588 		{ 3, "\033OS", 0414 },	/* key F4	*/
589 		{ 3, "\033Ot", 0415 },	/* key F5	*/
590 		{ 3, "\033Ou", 0416 },	/* key F6	*/
591 		{ 3, "\033Ov", 0417 },	/* key F7	*/
592 		{ 3, "\033Ol", 0420 },	/* key F8	*/
593 		{ 3, "\033Ow", 0421 },	/* key F9	*/
594 		{ 3, "\033Ox", 0422 },	/* key F10	*/
595 
596 		{ 5, "\033O10~", 0410 },	/* key F0	*/
597 		{ 5, "\033O11~", 0411 },	/* key F1	*/
598 		{ 5, "\033O12~", 0412 },	/* key F2	*/
599 		{ 5, "\033O13~", 0413 },	/* key F3	*/
600 		{ 5, "\033O14~", 0414 },	/* key F4	*/
601 		{ 5, "\033O15~", 0415 },	/* key F5	*/
602 		{ 5, "\033O17~", 0416 },	/* key F6	*/
603 		{ 5, "\033O18~", 0417 },	/* key F7	*/
604 		{ 5, "\033O19~", 0420 },	/* key F8	*/
605 		{ 5, "\033O20~", 0421 },	/* key F9	*/
606 		{ 5, "\033O21~", 0422 },	/* key F10	*/
607 		{ 5, "\033O23~", 0423 },	/* key F11	*/
608 		{ 5, "\033O24~", 0424 },	/* key F12	*/
609 		{ 3, "\033Oq", 0534 },	/* ka1 upper-left of keypad	*/
610 		{ 3, "\033Os", 0535 },	/* ka3 upper-right of keypad	*/
611 		{ 3, "\033Or", 0536 },	/* kb2 center of keypad	*/
612  		{ 3, "\033Op", 0537 },	/* kc1 lower-left of keypad	*/
613 		{ 3, "\033On", 0540 },	/* kc3 lower-right of keypad	*/
614 
615 		{ 0, "", 0 }	/* end	*/
616 	};
617 
618 struct Parameters {
619 	int value;
620 	struct Parameters *next;
621 	};
622 
623 int Key_vals[] = {
624 	0407, 0526, 0515, 0525, 0512, 0510, 0402, 0514, 0517, 0516, 0410, 0411,
625 	0422, 0412, 0413, 0414, 0415, 0416, 0417, 0420, 0421, 0406, 0513, 0511,
626 	0404, 0533, 0522, 0523, 0405, 0520, 0521, 0524, 0403,
627 	0534, 0535, 0536, 0537, 0540, 0541, 0542, 0543, 0544, 0545, 0546, 0547,
628 	0550, 0527, 0551, 0552, 0553, 0554, 0555, 0556, 0557, 0560, 0561, 0562,
629 	0532, 0563, 0564, 0565, 0566, 0567, 0570, 0571, 0627, 0630, 0572, 0573,
630 	0574, 0575, 0576, 0577, 0600, 0601, 0602, 0603, 0604, 0605, 0606, 0607,
631 	0610, 0611, 0612, 0613, 0614, 0615, 0616, 0617, 0620, 0621, 0622, 0623,
632 	0624, 0625, 0626, 0423, 0424, 0425, 0426, 0427, 0430, 0431,
633 	0432, 0433, 0434, 0435, 0436, 0437, 0440, 0441, 0442, 0443, 0444, 0445,
634 	0446, 0447, 0450, 0451, 0452, 0453, 0454, 0455, 0456, 0457, 0460, 0461,
635 	0462, 0463, 0464, 0465, 0466, 0467, 0470, 0471, 0472, 0473, 0474, 0475,
636 	0476, 0477, 0500, 0501, 0502, 0503, 0504, 0505, 0506, 0507
637 };
638 
639 int attributes_set[9];
640 
641 static int nc_attributes = 0;	/* global attributes for new_curse to observe */
642 
643 #ifdef SYS5
644 struct termio Terminal;
645 struct termio Saved_tty;
646 #else
647 struct sgttyb Terminal;
648 struct sgttyb Saved_tty;
649 #endif
650 
651 char *tc_;
652 
653 int Booleans[128];
654 int Numbers[128];
655 char *String_table[1024];
656 
657 int *virtual_lines;
658 
659 static char nc_scrolling_ability = FALSE;
660 
661 #ifdef CAP
662 
663 #if defined(__STDC__) || defined(__cplusplus)
664 #define P_(s) s
665 #else
666 #define P_(s) ()
667 #endif /* __STDC__ */
668 
669 int tc_Get_int P_((int));
670 void CAP_PARSE P_((void));
671 void Find_term P_((void));
672 
673 #undef P_
674 
675 #endif /* CAP */
676 
677 
678 #ifndef __STDC__
679 #ifndef HAS_STDLIB
680 extern char *fgets();
681 extern char *malloc();
682 extern char *getenv();
683 FILE *fopen();			/* declaration for open function	*/
684 #endif /* HAS_STDLIB */
685 #endif /* __STDC__ */
686 
687 #ifdef SIGWINCH
688 
689 /*
690  |	Copy the contents of one window to another.
691  */
692 
693 void
694 copy_window(origin, destination)
695 WINDOW *origin, *destination;
696 {
697 	int row, column;
698 	struct _line *orig, *dest;
699 
700 	orig = origin->first_line;
701 	dest = destination->first_line;
702 
703 	for (row = 0;
704 		row < (min(origin->Num_lines, destination->Num_lines));
705 			row++)
706 	{
707 		for (column = 0;
708 		    column < (min(origin->Num_cols, destination->Num_cols));
709 			column++)
710 		{
711 			dest->row[column] = orig->row[column];
712 			dest->attributes[column] = orig->attributes[column];
713 		}
714 		dest->changed = orig->changed;
715 		dest->scroll = orig->scroll;
716 		dest->last_char = min(orig->last_char, destination->Num_cols);
717 		orig = orig->next_screen;
718 		dest = dest->next_screen;
719 	}
720 	destination->LX = min((destination->Num_cols - 1), origin->LX);
721 	destination->LY = min((destination->Num_lines - 1), origin->LY);
722 	destination->Attrib = origin->Attrib;
723 	destination->scroll_up = origin->scroll_up;
724 	destination->scroll_down = origin->scroll_down;
725 	destination->SCROLL_CLEAR = origin->SCROLL_CLEAR;
726 }
727 
728 void
729 reinitscr(foo)
730 int foo;
731 {
732 	WINDOW *local_virt;
733 	WINDOW *local_std;
734 	WINDOW *local_cur;
735 
736 	signal(SIGWINCH, reinitscr);
737 #ifdef TIOCGWINSZ
738 	if (ioctl(0, TIOCGWINSZ, &ws) >= 0)
739 	{
740 		if (ws.ws_row == LINES && ws.ws_col == COLS)
741 			return;
742 		if (ws.ws_row > 0)
743 			LINES = ws.ws_row;
744 		if (ws.ws_col > 0)
745 			COLS = ws.ws_col;
746 	}
747 #endif /* TIOCGWINSZ */
748 	local_virt = newwin(LINES, COLS, 0, 0);
749 	local_std = newwin(LINES, COLS, 0, 0);
750 	local_cur = newwin(LINES, COLS, 0, 0);
751 	copy_window(virtual_scr, local_virt);
752 	copy_window(stdscr, local_std);
753 	copy_window(curscr, local_cur);
754 	delwin(virtual_scr);
755 	delwin(stdscr);
756 	delwin(curscr);
757 	virtual_scr = local_virt;
758 	stdscr = local_std;
759 	curscr = local_cur;
760 	free(virtual_lines);
761 	virtual_lines = (int *) malloc(LINES * (sizeof(int)));
762 	interrupt_flag = TRUE;
763 }
764 #endif /* SIGWINCH */
765 
766 void
767 initscr()		/* initialize terminal for operations	*/
768 {
769 	int value;
770 	char *lines_string;
771 	char *columns_string;
772 #ifdef CAP
773 	char *pointer;
774 #endif /* CAP */
775 
776 #ifdef DIAG
777 printf("starting initscr \n");fflush(stdout);
778 #endif
779 	if (initialized)
780 		return;
781 #ifdef BSD_SELECT
782 	setbuf(stdin, NULL);
783 #endif /* BSD_SELECT */
784 	Flip_Bytes = FALSE;
785 	Parity = 0;
786 	Time_Out = FALSE;
787 	bufp = 0;
788 	Move_It = FALSE;
789 	Noblock = FALSE;
790 #ifdef SYS5
791 	value = ioctl(0, TCGETA, &Terminal);
792 	if (Terminal.c_cflag & PARENB)
793 	{
794 		if (Terminal.c_cflag & PARENB)
795 			Parity = 1;
796 		else
797 			Parity = 2;
798 	}
799 	if ((Terminal.c_cflag & CS8) == CS8)
800 	{
801 		Num_bits = 8;
802 	}
803 	else if ((Terminal.c_cflag & CS7) == CS7)
804 		Num_bits = 7;
805 	else if ((Terminal.c_cflag & CS6) == CS6)
806 		Num_bits = 6;
807 	else
808 		Num_bits = 5;
809 	value = Terminal.c_cflag & 037;
810 	switch (value) {
811 	case 01:	speed = 50.0;
812 		break;
813 	case 02:	speed = 75.0;
814 		break;
815 	case 03:	speed = 110.0;
816 		break;
817 	case 04:	speed = 134.5;
818 		break;
819 	case 05:	speed = 150.0;
820 		break;
821 	case 06:	speed = 200.0;
822 		break;
823 	case 07:	speed = 300.0;
824 		break;
825 	case 010:	speed = 600.0;
826 		break;
827 	case 011:	speed = 900.0;
828 		break;
829 	case 012:	speed = 1200.0;
830 		break;
831 	case 013:	speed = 1800.0;
832 		break;
833 	case 014:	speed = 2400.0;
834 		break;
835 	case 015:	speed = 3600.0;
836 		break;
837 	case 016:	speed = 4800.0;
838 		break;
839 	case 017:	speed = 7200.0;
840 		break;
841 	case 020:	speed = 9600.0;
842 		break;
843 	case 021:	speed = 19200.0;
844 		break;
845 	case 022:	speed = 38400.0;
846 		break;
847 	default:	speed = 0.0;
848 	}
849 #else
850 	value = ioctl(0, TIOCGETP, &Terminal);
851 	if (Terminal.sg_flags & EVENP)
852 		Parity = 2;
853 	else if (Terminal.sg_flags & ODDP)
854 		Parity = 1;
855 	value = Terminal.sg_ospeed;
856 	switch (value) {
857 	case 01:	speed = 50.0;
858 		break;
859 	case 02:	speed = 75.0;
860 		break;
861 	case 03:	speed = 110.0;
862 		break;
863 	case 04:	speed = 134.5;
864 		break;
865 	case 05:	speed = 150.0;
866 		break;
867 	case 06:	speed = 200.0;
868 		break;
869 	case 07:	speed = 300.0;
870 		break;
871 	case 010:	speed = 600.0;
872 		break;
873 	case 011:	speed = 1200.0;
874 		break;
875 	case 012:	speed = 1800.0;
876 		break;
877 	case 013:	speed = 2400.0;
878 		break;
879 	case 014:	speed = 4800.0;
880 		break;
881 	case 015:	speed = 9600.0;
882 		break;
883 	default:	speed = 0.0;
884 	}
885 #endif
886 	chars_per_millisecond = (0.001 * speed) / 8.0;
887 	TERMINAL_TYPE = getenv("TERM");
888 	if (TERMINAL_TYPE == NULL)
889 	{
890 		printf("unknown terminal type\n");
891 		exit(0);
892 	}
893 #ifndef CAP
894 	Fildes = -1;
895 	TERM_PATH = getenv("TERMINFO");
896 	if (TERM_PATH != NULL)
897 	{
898 		Data_Line_len = 23 + strlen(TERM_PATH) + strlen(TERMINAL_TYPE);
899 		Term_File_name = malloc(Data_Line_len);
900 		sprintf(Term_File_name, "%s/%c/%s", TERM_PATH, *TERMINAL_TYPE, TERMINAL_TYPE);
901 		Fildes = open(Term_File_name, O_RDONLY);
902 	}
903 	if (Fildes == -1)
904 	{
905 		TERM_PATH = "/usr/lib/terminfo";
906 		Data_Line_len = 23 + strlen(TERM_PATH) + strlen(TERMINAL_TYPE);
907 		Term_File_name = malloc(Data_Line_len);
908 		sprintf(Term_File_name, "%s/%c/%s", TERM_PATH, *TERMINAL_TYPE, TERMINAL_TYPE);
909 		Fildes = open(Term_File_name, O_RDONLY);
910 	}
911 	if (Fildes == -1)
912 	{
913 		TERM_PATH = "/usr/share/lib/terminfo";
914 		Data_Line_len = 23 + strlen(TERM_PATH) + strlen(TERMINAL_TYPE);
915 		Term_File_name = malloc(Data_Line_len);
916 		sprintf(Term_File_name, "%s/%c/%s", TERM_PATH, *TERMINAL_TYPE, TERMINAL_TYPE);
917 		Fildes = open(Term_File_name, O_RDONLY);
918 	}
919 	if (Fildes == -1)
920 	{
921 		TERM_PATH = "/usr/share/terminfo";
922 		Data_Line_len = 23 + strlen(TERM_PATH) + strlen(TERMINAL_TYPE);
923 		Term_File_name = malloc(Data_Line_len);
924 		sprintf(Term_File_name, "%s/%c/%s", TERM_PATH, *TERMINAL_TYPE, TERMINAL_TYPE);
925 		Fildes = open(Term_File_name, O_RDONLY);
926 	}
927 	if (Fildes == -1)
928 	{
929 		free(Term_File_name);
930 		Term_File_name = NULL;
931 	}
932 	else
933 		TERM_INFO = INFO_PARSE();
934 #else
935 	/*
936 	 |	termcap information can be in the TERMCAP env variable, if so
937 	 |	use that, otherwise check the /etc/termcap file
938 	 */
939 	if ((pointer = Term_File_name = getenv("TERMCAP")) != NULL)
940 	{
941 		if (*Term_File_name != '/')
942 			Term_File_name = "/etc/termcap";
943 	}
944 	else
945 	{
946 		Term_File_name = "/etc/termcap";
947 	}
948 	if ((TFP = fopen(Term_File_name, "r")) == NULL)
949 	{
950 		printf("unable to open /etc/termcap file \n");
951 		exit(0);
952 	}
953  	for (value = 0; value < 1024; value++)
954 		String_table[value] = NULL;
955 	for (value = 0; value < 128; value++)
956 		Booleans[value] = 0;
957 	for (value = 0; value < 128; value++)
958 		Numbers[value] = 0;
959 	Data_Line = malloc(512);
960 	if (pointer && *pointer != '/')
961 	{
962 		TERM_data_ptr = pointer;
963 		CAP_PARSE();
964 	}
965 	else
966 	{
967 		Find_term();
968 		CAP_PARSE();
969 	}
970 #endif
971 	if (String_table[pc__] == NULL)
972 		String_table[pc__] = "\0";
973 	if ((String_table[cm__] == NULL) || (Booleans[hc__]))
974 	{
975 		fprintf(stderr, "sorry, unable to use this terminal type for screen editing\n");
976 		exit(0);
977 	}
978 	Key_Get();
979 	keys_vt100();
980 	LINES = Numbers[li__];
981 	COLS = Numbers[co__];
982 	if ((lines_string = getenv("LINES")) != NULL)
983 	{
984 		value = atoi(lines_string);
985 		if (value > 0)
986 			LINES = value;
987 	}
988 	if ((columns_string = getenv("COLUMNS")) != NULL)
989 	{
990 		value = atoi(columns_string);
991 		if (value > 0)
992 			COLS = value;
993 	}
994 #ifdef TIOCGWINSZ
995 	/*
996 	 |	get the window size
997 	 */
998 	if (ioctl(0, TIOCGWINSZ, &ws) >= 0)
999 	{
1000 		if (ws.ws_row > 0)
1001 			LINES = ws.ws_row;
1002 		if (ws.ws_col > 0)
1003 			COLS = ws.ws_col;
1004 	}
1005 #endif
1006 	virtual_scr = newwin(LINES, COLS, 0, 0);
1007 	stdscr = newwin(LINES, COLS, 0, 0);
1008 	curscr = newwin(LINES, COLS, 0, 0);
1009 	wmove(stdscr, 0, 0);
1010 	werase(stdscr);
1011 	Repaint_screen = TRUE;
1012 	initialized = TRUE;
1013 	virtual_lines = (int *) malloc(LINES * (sizeof(int)));
1014 
1015 #ifdef SIGWINCH
1016 	/*
1017 	 |	reset size of windows and LINES and COLS if term window
1018 	 |	changes size
1019 	 */
1020 	signal(SIGWINCH, reinitscr);
1021 #endif /* SIGWINCH */
1022 
1023 	/*
1024 	 |	check if scrolling is available
1025 	 */
1026 
1027 	nc_scrolling_ability = ((String_table[al__] != NULL) &&
1028 				(String_table[dl__])) || ((String_table[cs__])
1029 				&& (String_table[sr__]));
1030 
1031 }
1032 
1033 #ifndef CAP
1034 int
1035 Get_int()		/* get a two-byte integer from the terminfo file */
1036 {
1037 	int High_byte;
1038 	int Low_byte;
1039 	int temp;
1040 
1041 	Low_byte = *((unsigned char *) TERM_data_ptr++);
1042 	High_byte = *((unsigned char *) TERM_data_ptr++);
1043 	if (Flip_Bytes)
1044 	{
1045 		temp = Low_byte;
1046 		Low_byte = High_byte;
1047 		High_byte = temp;
1048 	}
1049 	if ((High_byte == 255) && (Low_byte == 255))
1050 		return (-1);
1051 	else
1052 		return(Low_byte + (High_byte * 256));
1053 }
1054 
1055 int
1056 INFO_PARSE()		/* parse off the data in the terminfo data file	*/
1057 {
1058 	int offset;
1059 	int magic_number = 0;
1060 	int counter = 0;
1061 	int Num_names = 0;
1062 	int Num_bools = 0;
1063 	int Num_ints = 0;
1064 	int Num_strings = 0;
1065 	int string_table_len = 0;
1066 	char *temp_ptr;
1067 
1068 	TERM_data_ptr = Data_Line = malloc((10240 * (sizeof(char))));
1069 	Data_Line_len = read(Fildes, Data_Line, 10240);
1070 	if ((Data_Line_len >= 10240) || (Data_Line_len < 0))
1071 		return(0);
1072 	/*
1073 	 |	get magic number
1074 	 */
1075 	magic_number = Get_int();
1076 	/*
1077 	 |	if magic number not right, reverse byte order and check again
1078 	 */
1079 	if (magic_number != 282)
1080 	{
1081 		Flip_Bytes = TRUE;
1082 		TERM_data_ptr--;
1083 		TERM_data_ptr--;
1084 		magic_number = Get_int();
1085 		if (magic_number != 282)
1086 			return(0);
1087 	}
1088 	/*
1089 	 |	get the number of each type in the terminfo data file
1090 	 */
1091 	Num_names = Get_int();
1092 	Num_bools = Get_int();
1093 	Num_ints = Get_int();
1094 	Num_strings = Get_int();
1095 	string_table_len = Get_int();
1096 	Strings = malloc(string_table_len);
1097 	while (Num_names > 0)
1098 	{
1099 		TERM_data_ptr++;
1100 		Num_names--;
1101 	}
1102 	counter = 0;
1103 	while (Num_bools)
1104 	{
1105 		Num_bools--;
1106 		Booleans[counter++] = *TERM_data_ptr++;
1107 	}
1108 	if (((unsigned int) TERM_data_ptr) & 1)	/* force alignment	*/
1109 		TERM_data_ptr++;
1110 	counter = 0;
1111 	while (Num_ints)
1112 	{
1113 		Num_ints--;
1114 		Numbers[counter] = Get_int();
1115 		counter++;
1116 	}
1117 	temp_ptr = TERM_data_ptr + Num_strings + Num_strings;
1118 	memcpy(Strings, temp_ptr, string_table_len);
1119 	counter = bt__;
1120 	while (Num_strings)
1121 	{
1122 		Num_strings--;
1123 		if ((offset=Get_int()) != -1)
1124 		{
1125 			if (String_table[counter] == NULL)
1126 				String_table[counter] = Strings + offset;
1127 		}
1128 		else
1129 			String_table[counter] = NULL;
1130 		counter++;
1131 	}
1132 	close(Fildes);
1133 	free(Data_Line);
1134 	return(TRUE);
1135 }
1136 #endif		/* ifndef CAP	*/
1137 
1138 int
1139 AtoI()		/* convert ascii text to integers	*/
1140 {
1141 	int Temp;
1142 
1143 	Temp = 0;
1144 	while ((*TERM_data_ptr >= '0') && (*TERM_data_ptr <= '9'))
1145 	{
1146 		Temp = (Temp * 10) + (*TERM_data_ptr - '0');
1147 		TERM_data_ptr++;
1148 	}
1149 	return(Temp);
1150 }
1151 
1152 void
1153 Key_Get()		/* create linked list with all key sequences obtained from terminal database	*/
1154 {
1155 	int Counter;
1156 	int Klen;
1157 	int key_def;
1158 	struct KEY_STACK *Spoint;
1159 
1160 	Max_Key_len = 0;
1161 	Counter = 0;
1162 	key_def = kb__;
1163 	while (key_def <= kf63__)
1164 	{
1165 		if (key_def == ke__)
1166 			key_def = K1__;
1167 		else if (key_def == (K5__ + 1))
1168 			key_def = kcbt__;
1169 		else if (key_def == (kcbt__ + 1))
1170 			key_def = kbeg__;
1171 		else if (key_def == (kUND__ + 1))
1172 			key_def = kf11__;
1173 		if (String_table[key_def] != NULL)
1174 		{
1175 			if (KEY_TOS == NULL)
1176 				Spoint = KEY_TOS = (struct KEY_STACK *) malloc(sizeof(struct KEY_STACK));
1177 			else
1178 			{
1179 				Spoint = KEY_TOS;
1180 				while (Spoint->next != NULL)
1181 					Spoint = Spoint->next;
1182 				Spoint->next = (struct KEY_STACK *) malloc(sizeof(struct KEY_STACK));
1183 				Spoint = Spoint->next;
1184 			}
1185 			Spoint->next = NULL;
1186 			Spoint->element = (struct KEYS *) malloc(sizeof(struct KEYS));
1187 			Spoint->element->string = String_table[key_def];
1188 			Spoint->element->length = strlen(String_table[key_def]);
1189 			Spoint->element->value = Key_vals[Counter];
1190 			Klen = strlen(Spoint->element->string);
1191 			if (Klen > Max_Key_len)
1192 				Max_Key_len = Klen;
1193 			/*
1194 			 |  Some terminal types accept keystrokes of the form
1195 			 |  \E[A and \EOA, substituting '[' for 'O'.  Make a
1196 			 |  duplicate of such key strings (since the
1197 			 |  database will only have one version) so new_curse
1198 			 |  can understand both.
1199 			 */
1200 			if ((Spoint->element->length > 1) &&
1201 			    ((String_table[key_def][1] == '[') ||
1202 			     (String_table[key_def][1] == 'O')))
1203 			{
1204 				Spoint->next = (struct KEY_STACK *) malloc(sizeof(struct KEY_STACK));
1205 				Spoint = Spoint->next;
1206 				Spoint->next = NULL;
1207 				Spoint->element = (struct KEYS *) malloc(sizeof(struct KEYS));
1208 				Spoint->element->length = strlen(String_table[key_def]);
1209 				Spoint->element->string = malloc(Spoint->element->length + 1);
1210 				strcpy(Spoint->element->string, String_table[key_def]);
1211 				Spoint->element->value = Key_vals[Counter];
1212 				Klen = strlen(Spoint->element->string);
1213 				if (Klen > Max_Key_len)
1214 					Max_Key_len = Klen;
1215 
1216 				if (String_table[key_def][1] == '[')
1217 					Spoint->element->string[1] = 'O';
1218 				else
1219 					Spoint->element->string[1] = '[';
1220 			}
1221 		}
1222 		key_def++;
1223 		Counter++;
1224 	}
1225 }
1226 
1227 /*
1228  |	insert information about keys for a vt100 terminal
1229  */
1230 
1231 void
1232 keys_vt100()
1233 {
1234 	int counter;
1235 	int Klen;
1236 	struct KEY_STACK *Spoint;
1237 
1238 	Spoint = KEY_TOS;
1239 	while (Spoint->next != NULL)
1240 		Spoint = Spoint->next;
1241 	for (counter = 0; vt100[counter].length != 0; counter++)
1242 	{
1243 		Spoint->next = (struct KEY_STACK *) malloc(sizeof(struct KEY_STACK));
1244 		Spoint = Spoint->next;
1245 		Spoint->next = NULL;
1246 		Spoint->element = &vt100[counter];
1247 		Klen = strlen(Spoint->element->string);
1248 		if (Klen > Max_Key_len)
1249 			Max_Key_len = Klen;
1250 	}
1251 }
1252 
1253 #ifdef CAP
1254 char *
1255 String_Get(param)		/* read the string */
1256 char *param;
1257 {
1258 	char *String;
1259 	char *Temp;
1260 	int Counter;
1261 
1262 	if (param == NULL)
1263 	{
1264 		while (*TERM_data_ptr != '=')
1265 			TERM_data_ptr++;
1266 		Temp = ++TERM_data_ptr;
1267 		Counter = 1;
1268 		while ((*Temp != ':') && (*Temp != (char)NULL))
1269 		{
1270 			Counter++;
1271 			Temp++;
1272 		}
1273 		if (Counter == 1)	/* no data */
1274 			return(NULL);
1275 		String = Temp = malloc(Counter);
1276 		while ((*TERM_data_ptr != ':') && (*TERM_data_ptr != (char)NULL))
1277 		{
1278 			if (*TERM_data_ptr == '\\')
1279 			{
1280 				TERM_data_ptr++;
1281 				if (*TERM_data_ptr == 'n')
1282 					*Temp = '\n';
1283 				else if (*TERM_data_ptr == 't')
1284 					*Temp = '\t';
1285 				else if (*TERM_data_ptr == 'b')
1286 					*Temp = '\b';
1287 				else if (*TERM_data_ptr == 'r')
1288 					*Temp = '\r';
1289 				else if (*TERM_data_ptr == 'f')
1290 					*Temp = '\f';
1291 				else if ((*TERM_data_ptr == 'e') || (*TERM_data_ptr == 'E'))
1292 					*Temp = '\033';		/* escape */
1293 				else if (*TERM_data_ptr == '\\')
1294 					*Temp = '\\';
1295 				else if (*TERM_data_ptr == '\'')
1296 					*Temp = '\'';
1297 				else if ((*TERM_data_ptr >= '0') && (*TERM_data_ptr <= '9'))
1298 				{
1299 					Counter = 0;
1300 					while ((*TERM_data_ptr >= '0') && (*TERM_data_ptr <= '9'))
1301 					{
1302 						Counter = (8 * Counter) + (*TERM_data_ptr - '0');
1303 						TERM_data_ptr++;  /* ? */
1304 					}
1305 					*Temp = Counter;
1306 					TERM_data_ptr--;
1307 				}
1308 				TERM_data_ptr++;
1309 				Temp++;
1310 			}
1311 			else if (*TERM_data_ptr == '^')
1312 			{
1313 				TERM_data_ptr++;
1314 				if ((*TERM_data_ptr >= '@') && (*TERM_data_ptr <= '_'))
1315 					*Temp = *TERM_data_ptr - '@';
1316 				else if (*TERM_data_ptr == '?')
1317 					*Temp = 127;
1318 				TERM_data_ptr++;
1319 				Temp++;
1320 			}
1321 			else
1322 				*Temp++ = *TERM_data_ptr++;
1323 		}
1324 		*Temp = (char)NULL;
1325 		param = String;
1326 	}
1327 	else
1328 	{
1329 		while ((*TERM_data_ptr != (char)NULL) && (*TERM_data_ptr != ':'))
1330 			TERM_data_ptr++;
1331 	}
1332 	return(param);
1333 }
1334 
1335 int
1336 tc_Get_int(param)		/* read the integer			*/
1337 int param;
1338 {
1339 	int Itemp;
1340 
1341 	if (param == 0)
1342 	{
1343 		while ((*TERM_data_ptr != (char)NULL) && (*TERM_data_ptr != '#'))
1344 			TERM_data_ptr++;
1345 		TERM_data_ptr++;
1346 		Itemp = AtoI();
1347 		param = Itemp;
1348 	}
1349 	else
1350 	{
1351 		while (*TERM_data_ptr != ':')
1352 			TERM_data_ptr++;
1353 	}
1354 	return(param);
1355 }
1356 
1357 void
1358 Find_term()		/* find terminal description in termcap file	*/
1359 {
1360 	char *Name;
1361 	char *Ftemp;
1362 
1363 	Ftemp = Name = malloc(strlen(TERMINAL_TYPE + 1) + 1);
1364 	strcpy(Name, TERMINAL_TYPE);
1365 	while (*Ftemp != (char)NULL)
1366 		Ftemp++;
1367 	*Ftemp++ = '|';
1368 	*Ftemp = (char)NULL;
1369 	CFOUND = FALSE;
1370 	Data_Line_len = strlen(TERMINAL_TYPE) + 1;
1371 	while ((!CFOUND) && ((TERM_data_ptr=fgets(Data_Line, 512, TFP)) != NULL))
1372 	{
1373 		if ((*TERM_data_ptr != ' ') && (*TERM_data_ptr != '\t') && (*TERM_data_ptr != '#'))
1374 		{
1375 			while ((!CFOUND) && (*TERM_data_ptr != (char)NULL))
1376 			{
1377 				CFOUND = !strncmp(TERM_data_ptr, Name, Data_Line_len);
1378 				while ((*TERM_data_ptr != (char)NULL) && (*TERM_data_ptr != '|') && (*TERM_data_ptr != '#') && (*TERM_data_ptr != ':'))
1379 					TERM_data_ptr++;
1380 				if (*TERM_data_ptr == '|')
1381 					TERM_data_ptr++;
1382 				else if (!CFOUND)
1383 					*TERM_data_ptr = (char)NULL;
1384 			}
1385 		}
1386 	}
1387 	if (!CFOUND)
1388 	{
1389 		printf("terminal type %s not found\n", TERMINAL_TYPE);
1390 		exit(0);
1391 	}
1392 }
1393 
1394 void
1395 CAP_PARSE()		/* parse off the data in the termcap data file	*/
1396 {
1397 	int offset;
1398 	int found;
1399 
1400 	do
1401 	{
1402 		while (*TERM_data_ptr != (char)NULL)
1403 		{
1404 			for (found = FALSE, offset = 0; (!found) && (offset < 26); offset++)
1405 			{
1406 				if (!strncmp(TERM_data_ptr, Boolean_names[offset], 2))
1407 				{
1408 					found = TRUE;
1409 					Booleans[offset] = TRUE;
1410 				}
1411 			}
1412 			if (!found)
1413 			{
1414 				for (found = FALSE, offset = 0; (!found) && (offset < lw__); offset++)
1415 				{
1416 					if (!strncmp(TERM_data_ptr, Number_names[offset], 3))
1417 					{
1418 						found = TRUE;
1419 						Numbers[offset] = tc_Get_int(Numbers[offset]);
1420 					}
1421 				}
1422 			}
1423 			if (!found)
1424 			{
1425 				for (found = FALSE, offset = 0; (!found) && (offset < smgr__); offset++)
1426 				{
1427 					if (!strncmp(TERM_data_ptr, String_names[offset], 3))
1428 					{
1429 						found = TRUE;
1430 						String_table[offset] = String_Get(String_table[offset]);
1431 					}
1432 				}
1433 			}
1434 
1435 			if (!strncmp(TERM_data_ptr, "tc=", 3))
1436 				tc_ = String_Get(NULL);
1437 			while ((*TERM_data_ptr != ':') && (*TERM_data_ptr != (char)NULL))
1438 				TERM_data_ptr++;
1439 			if (*TERM_data_ptr == ':')
1440 				TERM_data_ptr++;
1441 		}
1442 	} while (((TERM_data_ptr = fgets(Data_Line, 512, TFP)) != NULL) && ((*TERM_data_ptr == ' ') || (*TERM_data_ptr == '\t')));
1443 	if (tc_ != NULL)
1444 	{
1445 		TERMINAL_TYPE = tc_;
1446 		rewind(TFP);
1447 		Find_term();
1448 		tc_ = NULL;
1449 		CAP_PARSE();
1450 	}
1451 	else
1452 		fclose(TFP);
1453 }
1454 #endif		/* ifdef CAP	*/
1455 
1456 struct _line *
1457 Screenalloc(columns)
1458 int columns;
1459 {
1460 	int i;
1461 	struct _line *tmp;
1462 
1463 	tmp = (struct _line *) malloc(sizeof (struct _line));
1464 	tmp->row = malloc(columns + 1);
1465 	tmp->attributes = malloc(columns + 1);
1466 	tmp->prev_screen = NULL;
1467 	tmp->next_screen = NULL;
1468 	for (i = 0; i < columns; i++)
1469 	{
1470 		tmp->row[i] = ' ';
1471 		tmp->attributes[i] = (char) NULL;
1472 	}
1473 	tmp->scroll = tmp->changed = FALSE;
1474 	tmp->row[0] = (char) NULL;
1475 	tmp->attributes[0] = (char) NULL;
1476 	tmp->row[columns] = (char) NULL;
1477 	tmp->attributes[columns] = (char) NULL;
1478 	tmp->last_char = 0;
1479 	return(tmp);
1480 }
1481 
1482 WINDOW *newwin(lines, cols, start_l, start_c)
1483 int lines, cols;	/* number of lines and columns to be in window	*/
1484 int start_l, start_c;	/* starting line and column to be inwindow	*/
1485 {
1486 	WINDOW *Ntemp;
1487 	struct _line *temp_screen;
1488 	int i;
1489 
1490 	Ntemp = (WINDOW *) malloc(sizeof(WINDOW));
1491 	Ntemp->SR = start_l;
1492 	Ntemp->SC = start_c;
1493 	Ntemp->Num_lines = lines;
1494 	Ntemp->Num_cols = cols;
1495 	Ntemp->LX = 0;
1496 	Ntemp->LY = 0;
1497 	Ntemp->scroll_down = Ntemp->scroll_up = 0;
1498 	Ntemp->SCROLL_CLEAR = FALSE;
1499 	Ntemp->Attrib = FALSE;
1500 	Ntemp->first_line = temp_screen = Screenalloc(cols);
1501 	Ntemp->first_line->number = 0;
1502 	Ntemp->line_array = (struct _line **) malloc(LINES * sizeof(struct _line *));
1503 
1504 	Ntemp->line_array[0] = Ntemp->first_line;
1505 
1506 	for (i = 1; i < lines; i++)
1507 	{
1508 		temp_screen->next_screen = Screenalloc(cols);
1509 		temp_screen->next_screen->number = i;
1510 		temp_screen->next_screen->prev_screen = temp_screen;
1511 		temp_screen = temp_screen->next_screen;
1512 		Ntemp->line_array[i] = temp_screen;
1513 	}
1514 	Ntemp->first_line->prev_screen = NULL;
1515 	temp_screen->next_screen = NULL;
1516 	return(Ntemp);
1517 }
1518 
1519 #ifdef CAP
1520 void
1521 Cap_Out(string, p_list, place)	/* interpret the output string if necessary */
1522 char *string;
1523 int p_list[];			/* stack of values	*/
1524 int place;			/* place keeper of top of stack	*/
1525 {
1526 	char *Otemp;		/* temporary string pointer to parse output */
1527 	int delay;
1528 	int p1, p2, temp;
1529 	float chars;
1530 
1531 	if (string == NULL)
1532 		return;
1533 
1534 	if (p_list != NULL)
1535 	{
1536 		p1 = p_list[--place];
1537 		p2 = p_list[--place];
1538 	}
1539 	delay = 0;
1540 	Otemp = string;
1541 	if ((*Otemp >= '0') && (*Otemp <= '9'))
1542 	{
1543 		delay = atoi(Otemp);
1544 		while ((*Otemp >= '0') && (*Otemp <= '9'))
1545 			Otemp++;
1546 		if (*Otemp == '*')
1547 			Otemp++;
1548 	}
1549 	while (*Otemp != (char)NULL)
1550 	{
1551 		if (*Otemp == '%')
1552 		{
1553 			Otemp++;
1554 			if ((*Otemp == 'd') || (*Otemp == '2') || (*Otemp == '3') || (*Otemp == '.') || (*Otemp == '+'))
1555 			{
1556 				if (*Otemp == 'd')
1557 				 	printf("%d", p1);
1558 				else if (*Otemp == '2')
1559 					printf("%02d", p1);
1560 				else if (*Otemp == '3')
1561 					printf("%03d", p1);
1562 				else if (*Otemp == '+')
1563 				{
1564 					Otemp++;
1565 					p1 += *Otemp;
1566 					putchar(p1);
1567 				}
1568 				else if (*Otemp == '.')
1569 					putchar(p1);
1570 				p1 = p2;
1571 				p2 = 0;
1572 			}
1573 			else if (*Otemp == '>')
1574 			{
1575 				Otemp++;
1576 				if (p1 > *Otemp)
1577 				{
1578 					Otemp++;
1579 					p1 += *Otemp;
1580 				}
1581 				else
1582 					Otemp++;
1583 			}
1584 			else if (*Otemp == 'r')
1585 			{
1586 				temp = p1;
1587 				p1 = p2;
1588 				p2 = temp;
1589 			}
1590 			else if (*Otemp == 'i')
1591 			{
1592 				p1++;
1593 				p2++;
1594 			}
1595 			else if (*Otemp == '%')
1596 				putchar(*Otemp);
1597 			else if (*Otemp == 'n')
1598 			{
1599 				p1 ^= 0140;
1600 				p2 ^= 0140;
1601 			}
1602 			else if (*Otemp == 'B')
1603 			{
1604 				p1 = (16 * (p1/10)) + (p1 % 10);
1605 				p2 = (16 * (p2/10)) + (p2 % 10);
1606 			}
1607 			else if (*Otemp == 'D')
1608 			{
1609 				p1 = (p1 - 2 * (p1 % 16));
1610 				p2 = (p2 - 2 * (p2 % 16));
1611 			}
1612 		}
1613 		else
1614 			putchar (*Otemp);
1615 		Otemp++;
1616 	}
1617 	if (delay != 0)
1618 	{
1619 		chars = delay * chars_per_millisecond;
1620 		delay = chars;
1621 		if ((chars - delay) > 0.0)
1622 			delay++;
1623 		for (; delay > 0; delay--)
1624 			putchar(*String_table[pc__]);
1625 	}
1626 	fflush(stdout);
1627 }
1628 
1629 #else
1630 
1631 	char *Otemp;		/* temporary string pointer to parse output */
1632 	float chars;
1633 	int p[10];
1634 	int variable[27];
1635 
1636 int
1637 Operation(Temp_Stack, place)	/* handle conditional operations	*/
1638 int Temp_Stack[];
1639 int place;
1640 {
1641 	int temp;
1642 
1643 	if (*Otemp == 'd')
1644 	{
1645 		Otemp++;
1646 		temp = Temp_Stack[--place];
1647 	 	printf("%d", temp);
1648 	}
1649 	else if (!strncmp(Otemp, "2d", 2))
1650 	{
1651 		temp = Temp_Stack[--place];
1652 		printf("%2d", temp);
1653 		Otemp++;
1654 		Otemp++;
1655 	}
1656 	else if (!strncmp(Otemp, "3d", 2))
1657 	{
1658 		temp = Temp_Stack[--place];
1659 		printf("%0d", temp);
1660 		Otemp++;
1661 		Otemp++;
1662 	}
1663 	else if (!strncmp(Otemp, "02d", 3))
1664 	{
1665 		temp = Temp_Stack[--place];
1666 		printf("%02d", temp);
1667 		Otemp++;
1668 		Otemp++;
1669 		Otemp++;
1670 	}
1671 	else if (!strncmp(Otemp, "03d", 3))
1672 	{
1673 		temp = Temp_Stack[--place];
1674 		printf("%03d", temp);
1675 		Otemp++;
1676 		Otemp++;
1677 		Otemp++;
1678 	}
1679 	else if (*Otemp == '+')
1680 	{
1681 		Otemp++;
1682 		temp = Temp_Stack[--place];
1683 		temp += Temp_Stack[--place];
1684 		Temp_Stack[place++] = temp;
1685 	}
1686 	else if (*Otemp == '-')
1687 	{
1688 		Otemp++;
1689 		temp = Temp_Stack[--place];
1690 		temp -= Temp_Stack[--place];
1691 		Temp_Stack[place++] = temp;
1692 	}
1693 	else if (*Otemp == '*')
1694 	{
1695 		Otemp++;
1696 		temp = Temp_Stack[--place];
1697 		temp *= Temp_Stack[--place];
1698 		Temp_Stack[place++] = temp;
1699 	}
1700 	else if (*Otemp == '/')
1701 	{
1702 		Otemp++;
1703 		temp = Temp_Stack[--place];
1704 		temp /= Temp_Stack[--place];
1705 		Temp_Stack[place++] = temp;
1706 	}
1707 	else if (*Otemp == 'm')
1708 	{
1709 		Otemp++;
1710 		temp = Temp_Stack[--place];
1711 		temp %= Temp_Stack[--place];
1712 		Temp_Stack[place++] = temp;
1713 	}
1714 	else if (*Otemp == '&')
1715 	{
1716 		Otemp++;
1717 		temp = Temp_Stack[--place];
1718 		temp &= Temp_Stack[--place];
1719 		Temp_Stack[place++] = temp;
1720 	}
1721 	else if (*Otemp == '|')
1722 	{
1723 		Otemp++;
1724 		temp = Temp_Stack[--place];
1725 		temp |= Temp_Stack[--place];
1726 		Temp_Stack[place++] = temp;
1727 	}
1728 	else if (*Otemp == '^')
1729 	{
1730 		Otemp++;
1731 		temp = Temp_Stack[--place];
1732 		temp ^= Temp_Stack[--place];
1733 		Temp_Stack[place++] = temp;
1734 	}
1735 	else if (*Otemp == '=')
1736 	{
1737 		Otemp++;
1738 		temp = Temp_Stack[--place];
1739 		temp = (temp == Temp_Stack[--place]);
1740 		Temp_Stack[place++] = temp;
1741 	}
1742 	else if (*Otemp == '>')
1743 	{
1744 		Otemp++;
1745 		temp = Temp_Stack[--place];
1746 		temp = temp > Temp_Stack[--place];
1747 		Temp_Stack[place++] = temp;
1748 	}
1749 	else if (*Otemp == '<')
1750 	{
1751 		Otemp++;
1752 		temp = Temp_Stack[--place];
1753 		temp = temp < Temp_Stack[--place];
1754 		Temp_Stack[place++] = temp;
1755 	}
1756 	else if (*Otemp == 'c')
1757 	{
1758 		Otemp++;
1759 		putchar(Temp_Stack[--place]);
1760 	}
1761 	else if (*Otemp == 'i')
1762 	{
1763 		Otemp++;
1764 		p[1]++;
1765 		p[2]++;
1766 	}
1767 	else if (*Otemp == '%')
1768 	{
1769 		putchar(*Otemp);
1770 		Otemp++;
1771 	}
1772 	else if (*Otemp == '!')
1773 	{
1774 		temp = ! Temp_Stack[--place];
1775 		Temp_Stack[place++] = temp;
1776 		Otemp++;
1777 	}
1778 	else if (*Otemp == '~')
1779 	{
1780 		temp = ~Temp_Stack[--place];
1781 		Temp_Stack[place++] = temp;
1782 		Otemp++;
1783 	}
1784 	else if (*Otemp == 'p')
1785 	{
1786 		Otemp++;
1787 		Temp_Stack[place++] = p[*Otemp - '0'];
1788 		Otemp++;
1789 	}
1790 	else if (*Otemp == 'P')
1791 	{
1792 		Otemp++;
1793 		Temp_Stack[place++] = variable[*Otemp - 'a'];
1794 		Otemp++;
1795 	}
1796 	else if (*Otemp == 'g')
1797 	{
1798 		Otemp++;
1799 		variable[*Otemp - 'a'] = Temp_Stack[--place];
1800 		Otemp++;
1801 	}
1802 	else if (*Otemp == '\'')
1803 	{
1804 		Otemp++;
1805 		Temp_Stack[place++] = *Otemp;
1806 		Otemp++;
1807 		Otemp++;
1808 	}
1809 	else if (*Otemp == '{')
1810 	{
1811 		Otemp++;
1812 		temp = atoi(Otemp);
1813 		Temp_Stack[place++] = temp;
1814 		while (*Otemp != '}')
1815 			Otemp++;
1816 		Otemp++;
1817 	}
1818 	return(place);
1819 }
1820 
1821 void
1822 Info_Out(string, p_list, place)	/* interpret the output string if necessary */
1823 char *string;
1824 int p_list[];
1825 int place;
1826 {
1827 	char *tchar;
1828 	int delay;
1829 	int temp;
1830 	int Cond_FLAG;
1831 	int EVAL;
1832 	int Cond_Stack[128];
1833 	int Cond_place;
1834 	int Stack[128];
1835 	int Top_of_stack;
1836 
1837 	if (string == NULL)
1838 		return;
1839 
1840 	Cond_FLAG = FALSE;
1841 	Cond_place = 0;
1842 	Top_of_stack = 0;
1843 	p[0] = 0;
1844 	p[1] = 0;
1845 	p[2] = 0;
1846 	p[3] = 0;
1847 	p[4] = 0;
1848 	p[5] = 0;
1849 	p[6] = 0;
1850 	p[7] = 0;
1851 	p[8] = 0;
1852 	p[9] = 0;
1853 	if (p_list != NULL)
1854 	{
1855 		for (temp = 1; (place != 0); temp++)
1856 		{
1857 			p[temp] = p_list[--place];
1858 		}
1859 	}
1860 	delay = 0;
1861 	Otemp = string;
1862 	while (*Otemp != (char) NULL)
1863 	{
1864 		if (*Otemp == '%')
1865 		{
1866 			Otemp++;
1867 			if ((*Otemp == '?') || (*Otemp == 't') || (*Otemp == 'e') || (*Otemp == ';'))
1868 			{
1869 				if (*Otemp == '?')
1870 				{
1871 					Otemp++;
1872 					Cond_FLAG = TRUE;
1873 					EVAL = TRUE;
1874 					while (EVAL)
1875 					{
1876 						/*
1877 						 |  find the end of the
1878 						 |  conditional statement
1879 						 */
1880 						while ((strncmp(Otemp, "%t", 2)) && (*Otemp != (char) NULL))
1881 						{
1882 							/*
1883 							 |  move past '%'
1884 							 */
1885 							Otemp++;
1886 							Cond_place = Operation(Cond_Stack, Cond_place);
1887 						}
1888 
1889 						/*
1890 						 |  if condition is true
1891 						 */
1892 						if ((Cond_place > 0) && (Cond_Stack[Cond_place-1]))
1893 						{
1894 							/*
1895 							 |  end conditional
1896 							 |  parsing
1897 							 */
1898 							EVAL = FALSE;
1899 							Otemp++;
1900 							Otemp++;
1901 						}
1902 						else	/* condition is false */
1903 						{
1904 							/*
1905 							 |  find 'else' or end
1906 							 |  of if statement
1907 							 */
1908 							while ((strncmp(Otemp, "%e", 2)) && (strncmp(Otemp, "%;", 2)) && (*Otemp != (char) NULL))
1909 								Otemp++;
1910 							/*
1911 							 |  if an 'else' found
1912 							 */
1913 							if ((*Otemp != (char) NULL) && (!strncmp(Otemp, "%e", 2)))
1914 							{
1915 								Otemp++;
1916 								Otemp++;
1917 								tchar = Otemp;
1918 								/*
1919 								 |  check for 'then' part
1920 								 */
1921 								while ((*tchar != (char) NULL) && (strncmp(tchar, "%t", 2)) && (strncmp(tchar, "%;", 2)))
1922 									tchar++;
1923 								/*
1924 								 |  if end of string
1925 								 */
1926 								if (*tchar == (char) NULL)
1927 								{
1928 									EVAL = FALSE;
1929 									Cond_FLAG = FALSE;
1930 									Otemp = tchar;
1931 								}
1932 								/*
1933 								 |  if end of if found,
1934 								 |  set up to parse
1935 								 |  info
1936 								 */
1937 								else if (!strncmp(tchar, "%;", 2))
1938 									EVAL = FALSE;
1939 								/*
1940 								 |  otherwise, check
1941 								 |  conditional in
1942 								 |  'else'
1943 								 */
1944 							}
1945 							/*
1946 							 |  if end of if found,
1947 							 |  get out of if
1948 							 |  statement
1949 							 */
1950 							else if ((*Otemp != (char) NULL) && (!strncmp(Otemp, "%;", 2)))
1951 							{
1952 								EVAL = FALSE;
1953 								Otemp++;
1954 								Otemp++;
1955 							}
1956 							else /* Otemp == NULL */
1957 							{
1958 								EVAL = FALSE;
1959 								Cond_FLAG = FALSE;
1960 							}
1961 						}
1962 					}
1963 				}
1964 				else
1965 				{
1966 					Otemp++;
1967 					Cond_FLAG = FALSE;
1968 					if (*Otemp != ';')
1969 					{
1970 						while ((*Otemp != (char) NULL) && (strncmp(Otemp, "%;", 2)))
1971 							Otemp++;
1972 						if (*Otemp != (char) NULL)
1973 						{
1974 							Otemp++;
1975 							Otemp++;
1976 						}
1977 					}
1978 					else
1979 						Otemp++;
1980 				}
1981 			}
1982 			else
1983 			{
1984 				Top_of_stack = Operation(Stack, Top_of_stack);
1985 			}
1986 		}
1987 		else if (!strncmp(Otemp, "$<", 2))
1988 		{
1989 			Otemp++;
1990 			Otemp++;
1991 			delay = atoi(Otemp);
1992 			while (*Otemp != '>')
1993 				Otemp++;
1994 			Otemp++;
1995 			chars = delay * chars_per_millisecond;
1996 			delay = chars;
1997 			if ((chars - delay) > 0.0)
1998 				delay++;
1999 			if (String_table[pc__] == NULL)
2000 				temp = 0;
2001 			else
2002 				temp = *String_table[pc__];
2003 			for (; delay > 0; delay--)
2004 				putc(temp, stdout);
2005 		}
2006 		else
2007 		{
2008 			putchar(*Otemp);
2009 			Otemp++;
2010 		}
2011 	}
2012 	fflush(stdout);
2013 }
2014 #endif
2015 
2016 void
2017 wmove(window, row, column)	/* move cursor to indicated position in window */
2018 WINDOW *window;
2019 int row, column;
2020 {
2021 	if ((row < window->Num_lines) && (column < window->Num_cols))
2022 	{
2023 		window->LX = column;
2024 		window->LY = row;
2025 	}
2026 }
2027 
2028 void
2029 clear_line(line, column, cols)
2030 struct _line *line;
2031 int column;
2032 int cols;
2033 {
2034 	int j;
2035 
2036 	if (column > line->last_char)
2037 	{
2038 		for (j = line->last_char; j < column; j++)
2039 		{
2040 			line->row[j] = ' ';
2041 			line->attributes[j] = (char) NULL;
2042 		}
2043 	}
2044 	line->last_char = column;
2045 	line->row[column] = (char) NULL;
2046 	line->attributes[column] = (char) NULL;
2047 	line->changed = TRUE;
2048 }
2049 
2050 void
2051 werase(window)			/* clear the specified window		*/
2052 WINDOW *window;
2053 {
2054 	int i;
2055 	struct _line *tmp;
2056 
2057 	window->SCROLL_CLEAR = CLEAR;
2058 	window->scroll_up = window->scroll_down = 0;
2059 	for (i = 0, tmp = window->first_line; i < window->Num_lines; i++, tmp = tmp->next_screen)
2060 		clear_line(tmp, 0, window->Num_cols);
2061 }
2062 
2063 void
2064 wclrtoeol(window)	/* erase from current cursor position to end of line */
2065 WINDOW *window;
2066 {
2067 	int column, row;
2068 	struct _line *tmp;
2069 
2070 	window->SCROLL_CLEAR = CHANGE;
2071 	column = window->LX;
2072 	row = window->LY;
2073 	for (row = 0, tmp = window->first_line; row < window->LY; row++)
2074 		tmp = tmp->next_screen;
2075 	clear_line(tmp, column, window->Num_cols);
2076 }
2077 
2078 void
2079 wrefresh(window)		/* flush all previous output		*/
2080 WINDOW *window;
2081 {
2082 	wnoutrefresh(window);
2083 #ifdef DIAG
2084 {
2085 	struct _line *temp;
2086 	int value;
2087 	fprintf(stderr, "columns=%d, lines=%d, SC=%d, SR=%d\n",window->Num_cols, window->Num_lines, window->SC, window->SR);
2088 	for (value = 0, temp = window->first_line; value < window->Num_lines; value++, temp = temp->next_screen)
2089 	{
2090 		if (temp->number == -1)
2091 			fprintf(stderr, "line moved ");
2092 		if (temp->scroll)
2093 			fprintf(stderr, "scroll_x is set:  ");
2094 		fprintf(stderr, "lc%d=%s|\n", temp->last_char, temp->row);
2095 	}
2096 	fprintf(stderr, "+-------------------- virtual screen ----------------------------------------+\n");
2097 	fprintf(stderr, "columns=%d, lines=%d \n",virtual_scr->Num_cols, virtual_scr->Num_lines);
2098 	for (value = 0, temp = virtual_scr->first_line; value < virtual_scr->Num_lines; value++, temp = temp->next_screen)
2099 	{
2100 		if (temp->number == -1)
2101 			fprintf(stderr, "line moved ");
2102 		if (temp->scroll)
2103 			fprintf(stderr, "scroll_x is set:  ");
2104 		fprintf(stderr, "lc%d=%s|\n", temp->last_char, temp->row);
2105 	}
2106 	fprintf(stderr, "columns=%d, lines=%d \n",curscr->Num_cols, curscr->Num_lines);
2107 	for (value = 0, temp = curscr->first_line; value < curscr->Num_lines; value++, temp = temp->next_screen)
2108 		fprintf(stderr, "line=%s|\n", temp->row);
2109 }
2110 #endif
2111 	doupdate();
2112 	virtual_scr->SCROLL_CLEAR = FALSE;
2113 	virtual_scr->scroll_down = virtual_scr->scroll_up = 0;
2114 	fflush(stdout);
2115 }
2116 
2117 void
2118 touchwin(window)
2119 WINDOW *window;
2120 {
2121 	struct _line *user_line;
2122 	int line_counter = 0;
2123 
2124 	for (line_counter = 0, user_line = window->first_line;
2125 		line_counter < window->Num_lines; line_counter++)
2126 	{
2127 		user_line->changed = TRUE;
2128 	}
2129 	window->SCROLL_CLEAR = TRUE;
2130 }
2131 
2132 void
2133 wnoutrefresh(window)
2134 WINDOW *window;
2135 {
2136 	struct _line *user_line;
2137 	struct _line *virtual_line;
2138 	int line_counter = 0;
2139 	int user_col = 0;
2140 	int virt_col = 0;
2141 
2142 	if (window->SR >= virtual_scr->Num_lines)
2143 		return;
2144 	user_line = window->first_line;
2145 	virtual_line = virtual_scr->first_line;
2146 	virtual_scr->SCROLL_CLEAR = window->SCROLL_CLEAR;
2147 	virtual_scr->LX = window->LX + window->SC;
2148 	virtual_scr->LY = window->LY + window->SR;
2149 	virtual_scr->scroll_up = window->scroll_up;
2150 	virtual_scr->scroll_down = window->scroll_down;
2151 	if ((last_window_refreshed == window) && (!window->SCROLL_CLEAR))
2152 		return;
2153 	for (line_counter = 0; line_counter < window->SR; line_counter++)
2154 	{
2155 		virtual_line = virtual_line->next_screen;
2156 	}
2157 	for (line_counter = 0; (line_counter < window->Num_lines)
2158 		&& ((line_counter + window->SR) < virtual_scr->Num_lines);
2159 			line_counter++)
2160 	{
2161 		if ((last_window_refreshed != window) || (user_line->changed) || ((SCROLL | CLEAR) & window->SCROLL_CLEAR))
2162 		{
2163 			for (user_col = 0, virt_col = window->SC;
2164 				(virt_col < virtual_scr->Num_cols)
2165 				  && (user_col < user_line->last_char);
2166 				  	virt_col++, user_col++)
2167 			{
2168 				virtual_line->row[virt_col] = user_line->row[user_col];
2169 				virtual_line->attributes[virt_col] = user_line->attributes[user_col];
2170 			}
2171 			for (user_col = user_line->last_char,
2172 			     virt_col = window->SC + user_line->last_char;
2173 				(virt_col < virtual_scr->Num_cols)
2174 				  && (user_col < window->Num_cols);
2175 				  	virt_col++, user_col++)
2176 			{
2177 				virtual_line->row[virt_col] = ' ';
2178 				virtual_line->attributes[virt_col] = (char) NULL;
2179 			}
2180 		}
2181 		if (virtual_scr->Num_cols != window->Num_cols)
2182 		{
2183 			if (virtual_line->last_char < (user_line->last_char + window->SC))
2184 			{
2185 				if (virtual_line->row[virtual_line->last_char] == (char) NULL)
2186 					virtual_line->row[virtual_line->last_char] = ' ';
2187 				virtual_line->last_char =
2188 					min(virtual_scr->Num_cols,
2189 					  (user_line->last_char + window->SC));
2190 			}
2191 		}
2192 		else
2193 			virtual_line->last_char = user_line->last_char;
2194 		virtual_line->row[virtual_line->last_char] = (char) NULL;
2195 		virtual_line->changed = user_line->changed;
2196 		virtual_line = virtual_line->next_screen;
2197 		user_line = user_line->next_screen;
2198 	}
2199 	window->SCROLL_CLEAR = FALSE;
2200 	window->scroll_up = window->scroll_down = 0;
2201 	last_window_refreshed = window;
2202 }
2203 
2204 void
2205 flushinp()			/* flush input				*/
2206 {
2207 }
2208 
2209 void
2210 ungetch(c)			/* push a character back on input	*/
2211 int c;
2212 {
2213 	if (bufp < 100)
2214 		in_buff[bufp++] = c;
2215 }
2216 
2217 #ifdef BSD_SELECT
2218 int
2219 timed_getchar()
2220 {
2221 	struct timeval tv;
2222 	fd_set fds;
2223 	int ret_val;
2224 	int nfds = 1;
2225 	char temp;
2226 
2227 	FD_ZERO(&fds);
2228 	tv.tv_sec = 0;
2229 	tv.tv_usec = 500000;  /* half a second */
2230 	FD_SET(0, &fds);
2231 	Time_Out = FALSE; /* just in case */
2232 
2233 	ret_val = select(nfds, &fds, 0, 0, &tv);
2234 
2235 	/*
2236 	 |	if ret_val is less than zero, there was no input
2237 	 |	otherwise, get a character and return it
2238 	 */
2239 
2240 	if (ret_val <= 0)
2241 	{
2242 		Time_Out = TRUE;
2243 		return(-1);
2244 	}
2245 
2246 	return(read(0, &temp, 1)? temp : -1);
2247 }
2248 #endif
2249 
2250 int
2251 wgetch(window)			/* get character from specified window	*/
2252 WINDOW *window;
2253 {
2254 	int in_value;
2255 	char temp;
2256 #ifndef SYS5
2257 	int old_arg;
2258 #endif /* SYS5 */
2259 
2260 #ifdef BSD_SELECT
2261 	if (Noblock)
2262 		in_value = ((bufp > 0) ? in_buff[--bufp] : timed_getchar());
2263 	else
2264 		in_value = ((bufp > 0) ? in_buff[--bufp] : read(0, &temp, 1)? temp : -1);
2265 #else /* BSD_SELECT */
2266 #ifdef SYS5
2267 	in_value = ((bufp > 0) ? in_buff[--bufp] :
2268 					(read(0, &temp, 1)> 0) ? temp : -1);
2269 #else /* SYS5 */
2270 	if (Noblock)
2271 	{
2272 		Time_Out = FALSE;
2273 		old_arg = fcntl(0, F_GETFL, 0);
2274 		in_value = fcntl(0, F_SETFL, old_arg | FNDELAY);
2275 	}
2276 	in_value = ((bufp > 0) ? in_buff[--bufp] : read(0, &temp, 1)? temp : -1);
2277 	if (Noblock)
2278 	{
2279 		fcntl(0, F_SETFL, old_arg);
2280 		if (Time_Out)
2281 			in_value = -1;
2282 	}
2283 #endif /* SYS5 */
2284 #endif /* BSD_SELECT */
2285 
2286 	if (in_value != -1)
2287 	{
2288 		in_value &= 0xff;
2289 		if ((Parity) && (Num_bits < 8))
2290 				/* strip eighth bit if parity in use */
2291 		in_value &= 0177;
2292 	}
2293 	else if (interrupt_flag)
2294 	{
2295 		interrupt_flag = FALSE;
2296 		in_value = wgetch(window);
2297 	}
2298 
2299 	if ((in_value == '\033') || (in_value == '\037'))/* escape character */
2300 		in_value = Get_key(in_value);
2301 	return(in_value);
2302 }
2303 
2304 #ifndef BSD_SELECT
2305 void
2306 Clear(arg)		/* notify that time out has occurred	*/
2307 int arg;
2308 {
2309 	Time_Out = TRUE;
2310 #ifdef DEBUG
2311 fprintf(stderr, "inside Clear()\n");
2312 fflush(stderr);
2313 #endif /* DEBUG */
2314 }
2315 #endif /* BSD_SELECT */
2316 
2317 int
2318 Get_key(first_char)			/* try to decode key sequence	*/
2319 int first_char;				/* first character of sequence	*/
2320 {
2321 	int in_char;
2322 	int Count;
2323 	char string[128];
2324 	char *Gtemp;
2325 	int Found;
2326 #ifdef SYS5
2327 	struct termio Gterminal;
2328 #else
2329 	struct sgttyb Gterminal;
2330 #endif
2331 	struct KEY_STACK *St_point;
2332 #if (!defined( BSD_SELECT)) || (!defined(SYS5))
2333 	int value;
2334 #endif /* BSD_SELECT */
2335 
2336 	Count = 0;
2337 	Gtemp = string;
2338 	string[Count++] = first_char;
2339 	string[Count] = (char) NULL;
2340 	Time_Out = FALSE;
2341 #ifndef BSD_SELECT
2342 	signal(SIGALRM, Clear);
2343 	value = alarm(1);
2344 #endif /* BSD_SELECT */
2345 	Noblock = TRUE;
2346 #ifdef SYS5
2347 	Gterminal.c_cc[VTIME] = 0;		/* timeout value	*/
2348 	Gterminal.c_lflag &= ~ICANON;	/* disable canonical operation	*/
2349 	Gterminal.c_lflag &= ~ECHO;		/* disable echo		*/
2350 #endif
2351 	Count = 1;
2352 	Found = FALSE;
2353 	while ((Count < Max_Key_len) && (!Time_Out) && (!Found))
2354 	{
2355 		in_char = wgetch(stdscr);
2356 #ifdef DEBUG
2357 fprintf(stderr, "back in GetKey()\n");
2358 fflush(stderr);
2359 #endif /* DEBUG */
2360 		if (in_char != -1)
2361 		{
2362 			string[Count++] = in_char;
2363 			string[Count] = (char) NULL;
2364 			St_point = KEY_TOS;
2365 			while ((St_point != NULL) && (!Found))
2366 			{
2367 				if (!strcmp(string, St_point->element->string))
2368 					Found = TRUE;
2369 				else
2370 					St_point = St_point->next;
2371 			}
2372 		}
2373 	}
2374 #ifndef BSD_SELECT
2375 	if (!Time_Out)
2376 		value = alarm(0);
2377 #endif /* BSD_SELECT */
2378 #ifdef SYS5
2379 /*	value = ioctl(0, TCSETA, &Terminal);*/
2380 #else
2381 	value = ioctl(0, TIOCSETP, &Terminal);
2382 /*	value = fcntl(0, F_SETFL, old_arg);*/
2383 #endif
2384 	Noblock = FALSE;
2385 	if (Found)
2386 	{
2387 		return(St_point->element->value);
2388 	}
2389 	else
2390 	{
2391 		while (Count > 1)
2392 		{
2393 			if ((string[--Count] != -1) &&
2394 					((unsigned char) (string[Count]) != 255))
2395 			{
2396 #ifdef DIAG
2397 fprintf(stderr, "ungetting character %d\n", string[Count]);fflush(stdout);
2398 #endif
2399 				ungetch(string[Count]);
2400 			}
2401 		}
2402 		return(first_char);
2403 	}
2404 }
2405 
2406 void
2407 waddch(window, c)	/* output the character in the specified window	*/
2408 WINDOW *window;
2409 int c;
2410 {
2411 	int column, j;
2412 	int shift;	/* number of spaces to shift if a tab		*/
2413 	struct _line *tmpline;
2414 
2415 #ifdef DIAG
2416 /*printf("starting waddch \n");fflush(stdout);*/
2417 #endif
2418 	column = window->LX;
2419 	if (c == '\t')
2420 	{
2421 		shift = (column + 1) % 8;
2422 		if (shift == 0)
2423 			shift++;
2424 		else
2425 			shift = 9 - shift;
2426 		while (shift > 0)
2427 		{
2428 			shift--;
2429 			waddch(window, ' ');
2430 		}
2431 	}
2432 	else if ((column < window->Num_cols) && (window->LY < window->Num_lines))
2433 	{
2434 		if ((c == '~') && (Booleans[hz__]))
2435 			c = '@';
2436 
2437 		if (( c != '\b') && (c != '\n') && (c != '\r'))
2438 		{
2439 			tmpline = window->line_array[window->LY];
2440 			tmpline->row[column] = c;
2441 			tmpline->attributes[column] = window->Attrib;
2442 			tmpline->changed = TRUE;
2443 			if (column >= tmpline->last_char)
2444 			{
2445 				if (column > tmpline->last_char)
2446 					for (j = tmpline->last_char; j < column; j++)
2447 					{
2448 						tmpline->row[j] = ' ';
2449 						tmpline->attributes[j] = (char) NULL;
2450 					}
2451 				tmpline->row[column + 1] = (char) NULL;
2452 				tmpline->attributes[column + 1] = (char) NULL;
2453 				tmpline->last_char = column + 1;
2454 			}
2455 		}
2456 		if (c == '\n')
2457 		{
2458 			wclrtoeol(window);
2459 			window->LX = window->Num_cols;
2460 		}
2461 		else if (c == '\r')
2462 			window->LX = 0;
2463 		else if (c == '\b')
2464 			window->LX--;
2465 		else
2466 			window->LX++;
2467 	}
2468 	if (window->LX >= window->Num_cols)
2469 	{
2470 		window->LX = 0;
2471 		window->LY++;
2472 		if (window->LY >= window->Num_lines)
2473 		{
2474 			window->LY = window->Num_lines - 1;
2475 /*			window->LY = row;
2476 			wmove(window, 0, 0);
2477 			wdeleteln(window);
2478 			wmove(window, row, 0);*/
2479 		}
2480 	}
2481 	window->SCROLL_CLEAR = CHANGE;
2482 }
2483 
2484 void
2485 winsertln(window)	/* insert a blank line into the specified window */
2486 WINDOW *window;
2487 {
2488 	int row, column;
2489 	struct _line *tmp;
2490 	struct _line *tmp1;
2491 
2492 	window->scroll_down += 1;
2493 	window->SCROLL_CLEAR = SCROLL;
2494 	column = window->LX;
2495 	row = window->LY;
2496 	for (row = 0, tmp = window->first_line; (row < window->Num_lines) && (tmp->next_screen != NULL); row++)
2497 		tmp = tmp->next_screen;
2498 	if (tmp->prev_screen != NULL)
2499 		tmp->prev_screen->next_screen = NULL;
2500 	tmp1 = tmp;
2501 	clear_line(tmp1, 0, window->Num_cols);
2502 	tmp1->number = -1;
2503 	for (row = 0, tmp = window->first_line; (row < window->LY) && (tmp->next_screen != NULL); row++)
2504 		tmp = tmp->next_screen;
2505 	if ((window->LY == (window->Num_lines - 1)) && (window->Num_lines > 1))
2506 	{
2507 		tmp1->next_screen = tmp->next_screen;
2508 		tmp->next_screen = tmp1;
2509 		tmp->changed = TRUE;
2510 		tmp->next_screen->prev_screen = tmp;
2511 	}
2512 	else if (window->Num_lines > 1)
2513 	{
2514 		if (tmp->prev_screen != NULL)
2515 			tmp->prev_screen->next_screen = tmp1;
2516 		tmp1->prev_screen = tmp->prev_screen;
2517 		tmp->prev_screen = tmp1;
2518 		tmp1->next_screen = tmp;
2519 		tmp->changed = TRUE;
2520 		tmp->scroll = DOWN;
2521 	}
2522 	if (window->LY == 0)
2523 		window->first_line = tmp1;
2524 
2525 	for (row = 0, tmp1 = window->first_line;
2526 		row < window->Num_lines; row++)
2527 	{
2528 		window->line_array[row] = tmp1;
2529 		tmp1 = tmp1->next_screen;
2530 	}
2531 }
2532 
2533 void
2534 wdeleteln(window)	/* delete a line in the specified window */
2535 WINDOW *window;
2536 {
2537 	int row, column;
2538 	struct _line *tmp;
2539 	struct _line  *tmpline;
2540 
2541 	if (window->Num_lines > 1)
2542 	{
2543 		window->scroll_up += 1;
2544 		window->SCROLL_CLEAR = SCROLL;
2545 		column = window->LX;
2546 		row = window->LY;
2547 		for (row = 0, tmp = window->first_line; row < window->LY; row++)
2548 			tmp = tmp->next_screen;
2549 		if (window->LY == 0)
2550 			window->first_line = tmp->next_screen;
2551 		if (tmp->prev_screen != NULL)
2552 			tmp->prev_screen->next_screen = tmp->next_screen;
2553 		if (tmp->next_screen != NULL)
2554 		{
2555 			tmp->next_screen->changed = TRUE;
2556 			tmp->next_screen->scroll = UP;
2557 			tmp->next_screen->prev_screen = tmp->prev_screen;
2558 		}
2559 		tmpline = tmp;
2560 		clear_line(tmpline, 0, window->Num_cols);
2561 		tmpline->number = -1;
2562 		for (row = 0, tmp = window->first_line; tmp->next_screen != NULL; row++)
2563 			tmp = tmp->next_screen;
2564 		if (tmp != NULL)
2565 		{
2566 			tmp->next_screen = tmpline;
2567 			tmp->next_screen->prev_screen = tmp;
2568 			tmp->changed = TRUE;
2569 			tmp = tmp->next_screen;
2570 		}
2571 		else
2572 			tmp = tmpline;
2573 		tmp->next_screen = NULL;
2574 
2575 		for (row = 0, tmp = window->first_line; row < window->Num_lines; row++)
2576 		{
2577 			window->line_array[row] = tmp;
2578 			tmp = tmp->next_screen;
2579 		}
2580 	}
2581 	else
2582 	{
2583 		clear_line(window->first_line, 0, window->Num_cols);
2584 	}
2585 }
2586 
2587 void
2588 wclrtobot(window)	/* delete from current position to end of the window */
2589 WINDOW *window;
2590 {
2591 	int row, column;
2592 	struct _line *tmp;
2593 
2594 	window->SCROLL_CLEAR |= CLEAR;
2595 	column = window->LX;
2596 	row = window->LY;
2597 	for (row = 0, tmp = window->first_line; row < window->LY; row++)
2598 		tmp = tmp->next_screen;
2599 	clear_line(tmp, column, window->Num_cols);
2600 	for (row = (window->LY + 1); row < window->Num_lines; row++)
2601 	{
2602 		tmp = tmp->next_screen;
2603 		clear_line(tmp, 0, window->Num_cols);
2604 	}
2605 	wmove(window, row, column);
2606 }
2607 
2608 void
2609 wstandout(window)	/* begin standout mode in window	*/
2610 WINDOW *window;
2611 {
2612 	if (Numbers[sg__] < 1)	/* if not magic cookie glitch	*/
2613 		window->Attrib |= A_STANDOUT;
2614 }
2615 
2616 void
2617 wstandend(window)	/* end standout mode in window	*/
2618 WINDOW *window;
2619 {
2620 	window->Attrib &= ~A_STANDOUT;
2621 }
2622 
2623 void
2624 waddstr(window, string)	/* write 'string' in window	*/
2625 WINDOW *window;
2626 char *string;
2627 {
2628 	char *wstring;
2629 
2630 	for (wstring = string; *wstring != (char) NULL; wstring++)
2631 		waddch(window, *wstring);
2632 }
2633 
2634 void
2635 clearok(window, flag)	/* erase screen and redraw at next refresh	*/
2636 WINDOW *window;
2637 int flag;
2638 {
2639 	Repaint_screen = TRUE;
2640 }
2641 
2642 
2643 void
2644 echo()			/* turn on echoing				*/
2645 {
2646 	int value;
2647 
2648 #ifdef SYS5
2649 	Terminal.c_lflag |= ECHO;		/* enable echo		*/
2650 	value = ioctl(0, TCSETA, &Terminal);	/* set characteristics	*/
2651 #else
2652 	Terminal.sg_flags |= ECHO;		/* enable echo		*/
2653 	value = ioctl(0, TIOCSETP, &Terminal);	/* set characteristics	*/
2654 #endif
2655 }
2656 
2657 void
2658 noecho()		/* turn off echoing				*/
2659 {
2660 	int value;
2661 
2662 #ifdef SYS5
2663 	Terminal.c_lflag &= ~ECHO;		/* disable echo		*/
2664 	value = ioctl(0, TCSETA, &Terminal);	/* set characteristics	*/
2665 #else
2666 	Terminal.sg_flags &= ~ECHO;		/* disable echo		*/
2667 	value = ioctl(0, TIOCSETP, &Terminal);	/* set characteristics	*/
2668 #endif
2669 }
2670 
2671 void
2672 raw()			/* set to read characters immediately		*/
2673 {
2674 	int value;
2675 
2676 #ifdef SYS5
2677 	Intr = Terminal.c_cc[VINTR];	/* get the interrupt character	*/
2678 	Terminal.c_lflag &= ~ICANON;	/* disable canonical operation	*/
2679 	Terminal.c_lflag &= ~ISIG;	/* disable signal checking	*/
2680 #ifdef FLUSHO
2681 	Terminal.c_lflag &= ~FLUSHO;
2682 #endif
2683 #ifdef PENDIN
2684 	Terminal.c_lflag &= ~PENDIN;
2685 #endif
2686 #ifdef IEXTEN
2687 	Terminal.c_lflag &= ~IEXTEN;
2688 #endif
2689 	Terminal.c_cc[VMIN] = 1;		/* minimum of one character */
2690 	Terminal.c_cc[VTIME] = 0;		/* timeout value	*/
2691 	Terminal.c_cc[VINTR] = 0;		/* eliminate interrupt	*/
2692 	value = ioctl(0, TCSETA, &Terminal);	/* set characteristics	*/
2693 #else
2694 	Terminal.sg_flags |= RAW;	/* enable raw mode		*/
2695 	value = ioctl(0, TIOCSETP, &Terminal);	/* set characteristics	*/
2696 #endif
2697 }
2698 
2699 void
2700 noraw()			/* set to normal character read mode		*/
2701 {
2702 	int value;
2703 
2704 #ifdef SYS5
2705 	Terminal.c_lflag |= ICANON;	/* enable canonical operation	*/
2706 	Terminal.c_lflag |= ISIG;	/* enable signal checking	*/
2707 	Terminal.c_cc[VEOF] = 4;		/* EOF character = 4	*/
2708 	Terminal.c_cc[VEOL] = (char) NULL;	/* EOL = 0		*/
2709 	Terminal.c_cc[VINTR] = Intr;		/* reset interrupt char	*/
2710 	value = ioctl(0, TCSETA, &Terminal);	/* set characteristics	*/
2711 #else
2712 	Terminal.sg_flags &= ~RAW;	/* disable raw mode		*/
2713 	value = ioctl(0, TIOCSETP, &Terminal);	/* set characteristics	*/
2714 /*	old_arg = fcntl(0, F_GETFL, 0);
2715 	value = fcntl(0, F_SETFL, old_arg & ~FNDELAY);*/
2716 #endif
2717 }
2718 
2719 void
2720 nl()
2721 {
2722 	int value;
2723 
2724 #ifdef SYS5
2725 	Terminal.c_iflag |= ICRNL;	/* enable carriage-return to line-feed mapping	*/
2726 	value = ioctl(0, TCSETA, &Terminal);	/* set characteristics	*/
2727 #endif
2728 }
2729 
2730 void
2731 nonl()
2732 {
2733 	int value;
2734 
2735 #ifdef SYS5
2736 	Terminal.c_iflag &= ~ICRNL;	/* disable carriage-return to line-feed mapping	*/
2737 	Terminal.c_iflag &= ~IGNCR;	/* do not ignore carriage-return	*/
2738 	value = ioctl(0, TCSETA, &Terminal);	/* set characteristics	*/
2739 #endif
2740 }
2741 
2742 void
2743 saveterm()
2744 {
2745 }
2746 
2747 void
2748 fixterm()
2749 {
2750 }
2751 
2752 void
2753 resetterm()
2754 {
2755 }
2756 
2757 void
2758 nodelay(window, flag)
2759 WINDOW *window;
2760 int flag;
2761 {
2762 }
2763 
2764 void
2765 idlok(window, flag)
2766 WINDOW *window;
2767 int flag;
2768 {
2769 }
2770 
2771 void
2772 keypad(window, flag)
2773 WINDOW *window;
2774 int flag;
2775 {
2776 	if (flag)
2777 		String_Out(String_table[ks__], NULL, 0);
2778 	else
2779 		String_Out(String_table[ke__], NULL, 0);
2780 }
2781 
2782 void
2783 savetty()		/* save current tty stats			*/
2784 {
2785 	int value;
2786 
2787 #ifdef SYS5
2788 	value = ioctl(0, TCGETA, &Saved_tty);	/* set characteristics	*/
2789 #else
2790 	value = ioctl(0, TIOCGETP, &Saved_tty);	/* set characteristics	*/
2791 #endif
2792 }
2793 
2794 void
2795 resetty()		/* restore previous tty stats			*/
2796 {
2797 	int value;
2798 
2799 #ifdef SYS5
2800 	value = ioctl(0, TCSETA, &Saved_tty);	/* set characteristics	*/
2801 #else
2802 	value = ioctl(0, TIOCSETP, &Saved_tty);	/* set characteristics	*/
2803 #endif
2804 }
2805 
2806 void
2807 endwin()		/* end windows					*/
2808 {
2809 	keypad(stdscr, FALSE);
2810 	initialized = FALSE;
2811 	delwin(curscr);
2812 	delwin(virtual_scr);
2813 	delwin(stdscr);
2814 #ifndef SYS5
2815 {
2816 	int old_arg, value;
2817 /*	old_arg = fcntl(0, F_GETFL, 0);
2818 	value = fcntl(0, F_SETFL, old_arg & ~FNDELAY);*/
2819 }
2820 #endif
2821 }
2822 
2823 void
2824 delwin(window)		/* delete the window structure			*/
2825 WINDOW *window;
2826 {
2827 	int i;
2828 
2829 	for (i = 1; (i < window->Num_lines) && (window->first_line->next_screen != NULL); i++)
2830 	{
2831 		window->first_line = window->first_line->next_screen;
2832 		free(window->first_line->prev_screen->row);
2833 		free(window->first_line->prev_screen->attributes);
2834 		free(window->first_line->prev_screen);
2835 	}
2836 	if (window == last_window_refreshed)
2837 		last_window_refreshed = 0;
2838 	if (window->first_line != NULL)
2839 	{
2840 		free(window->first_line->row);
2841 		free(window->first_line->attributes);
2842 		free(window->first_line);
2843 		free(window);
2844 	}
2845 }
2846 
2847 #ifndef __STDC__
2848 void
2849 wprintw(va_alist)
2850 va_dcl
2851 #else /* __STDC__ */
2852 void
2853 wprintw(WINDOW *window, const char *format, ...)
2854 #endif /* __STDC__ */
2855 {
2856 #ifndef __STDC__
2857 	WINDOW *window;
2858 	char *format;
2859 	va_list ap;
2860 #else
2861 	va_list ap;
2862 #endif
2863 	int value;
2864 	char *fpoint;
2865 	char *wtemp;
2866 
2867 #ifndef __STDC__
2868 	va_start(ap);
2869 	window = va_arg(ap, WINDOW *);
2870 	format = va_arg(ap, char *);
2871 #else /* __STDC__ */
2872 	va_start(ap, format);
2873 #endif /* __STDC__ */
2874 
2875 	fpoint = (char *) format;
2876 	while (*fpoint != (char) NULL)
2877 	{
2878 		if (*fpoint == '%')
2879 		{
2880 			fpoint++;
2881 			if (*fpoint == 'd')
2882 			{
2883 				value = va_arg(ap, int);
2884 				iout(window, value);
2885 			}
2886 			else if (*fpoint == 'c')
2887 			{
2888 				value = va_arg(ap, int);
2889 				waddch(window, value);
2890 			}
2891 			else if (*fpoint == 's')
2892 			{
2893 				wtemp = va_arg(ap, char *);
2894 					waddstr(window, wtemp);
2895 			}
2896 			fpoint++;
2897 		}
2898 		else if (*fpoint == '\\')
2899 		{
2900 			fpoint++;
2901 			if (*fpoint == 'n')
2902 				waddch(window, '\n');
2903 			else if ((*fpoint >= '0') && (*fpoint <= '9'))
2904 			{
2905 				value = 0;
2906 				while ((*fpoint >= '0') && (*fpoint <= '9'))
2907 				{
2908 					value = (value * 8) + (*fpoint - '0');
2909 					fpoint++;
2910 				}
2911 				waddch(window, value);
2912 			}
2913 			fpoint++;
2914 		}
2915 		else
2916 			waddch(window, *fpoint++);
2917 	}
2918 #ifdef __STDC__
2919 	va_end(ap);
2920 #endif /* __STDC__ */
2921 }
2922 
2923 void
2924 iout(window, value)	/* output characters		*/
2925 WINDOW *window;
2926 int value;
2927 {
2928 	int i;
2929 
2930 	if ((i = value / 10) != 0)
2931 		iout(window, i);
2932 	waddch(window, ((value % 10) + '0'));
2933 }
2934 
2935 int
2936 Comp_line(line1, line2)		/* compare lines	*/
2937 struct _line *line1;
2938 struct _line *line2;
2939 {
2940 	int count1;
2941 	int i;
2942 	char *att1, *att2;
2943 	char *c1, *c2;
2944 
2945 	if (line1->last_char != line2->last_char)
2946 		return(2);
2947 
2948 	c1 = line1->row;
2949 	c2 = line2->row;
2950 	att1 = line1->attributes;
2951 	att2 = line2->attributes;
2952 	i = 0;
2953 	while ((c1[i] != (char) NULL) && (c2[i] != (char) NULL) && (c1[i] == c2[i]) && (att1[i] == att2[i]))
2954 		i++;
2955 	count1 = i + 1;
2956 	if ((count1 == 1) && (c1[i] == (char) NULL) && (c2[i] == (char) NULL))
2957 		count1 = 0;			/* both lines blank	*/
2958 	else if ((c1[i] == (char) NULL) && (c2[i] == (char) NULL))
2959 		count1 = -1;			/* equal		*/
2960 	else
2961 		count1 = 1;			/* lines unequal	*/
2962 	return(count1);
2963 }
2964 
2965 struct _line *
2966 Insert_line(row, end_row, window)	/* insert line into screen */
2967 int row;
2968 int end_row;
2969 WINDOW *window;
2970 {
2971 	int i;
2972 	struct _line *tmp;
2973 	struct _line *tmp1;
2974 
2975 	for (i = 0, tmp = curscr->first_line; i < window->SR; i++)
2976 		tmp = tmp->next_screen;
2977 	if ((end_row + window->SR) == 0)
2978 		curscr->first_line = curscr->first_line->next_screen;
2979 	top_of_win = tmp;
2980 	/*
2981 	 |	find bottom line to delete
2982 	 */
2983 	for (i = 0, tmp = top_of_win; (tmp->next_screen != NULL) && (i < end_row); i++)
2984 		tmp = tmp->next_screen;
2985 	if (tmp->prev_screen != NULL)
2986 		tmp->prev_screen->next_screen = tmp->next_screen;
2987 	if (tmp->next_screen != NULL)
2988 		tmp->next_screen->prev_screen = tmp->prev_screen;
2989 	tmp1 = tmp;
2990 	/*
2991 	 |	clear deleted line
2992 	 */
2993 	clear_line(tmp, 0, window->Num_cols);
2994 	tmp1->number = -1;
2995 	for (i = 0, tmp = curscr->first_line; (tmp->next_screen != NULL) && (i < window->SR); i++)
2996 		tmp = tmp->next_screen;
2997 	top_of_win = tmp;
2998 	for (i = 0, tmp = top_of_win; i < row; i++)
2999 		tmp = tmp->next_screen;
3000 	if ((tmp->prev_screen != NULL) && (window->Num_lines > 0))
3001 		tmp->prev_screen->next_screen = tmp1;
3002 	tmp1->prev_screen = tmp->prev_screen;
3003 	tmp->prev_screen = tmp1;
3004 	tmp1->next_screen = tmp;
3005 	if ((row + window->SR) == 0)
3006 		curscr->first_line = tmp1;
3007 	if (tmp1->next_screen != NULL)
3008 		tmp1 = tmp1->next_screen;
3009 
3010 	if ((!String_table[cs__]) && (end_row < window->Num_lines))
3011 	{
3012 		Position(window, (window->SR + end_row), 0);
3013 		String_Out(String_table[dl__], NULL, 0);
3014 	}
3015 	Position(window, (window->SR + row), 0);
3016 	if (String_table[al__] != NULL)
3017 		String_Out(String_table[al__], NULL, 0);
3018 	else
3019 		String_Out(String_table[sr__], NULL, 0);
3020 
3021 	for (i = 0, top_of_win = curscr->first_line; (top_of_win->next_screen != NULL) && (i < window->SR); i++)
3022 		top_of_win = top_of_win->next_screen;
3023 	return(tmp1);
3024 }
3025 
3026 
3027 struct _line *
3028 Delete_line(row, end_row, window)	/* delete a line on screen */
3029 int row;
3030 int end_row;
3031 WINDOW *window;
3032 {
3033 	int i;
3034 	struct _line *tmp;
3035 	struct _line *tmp1;
3036 	struct _line *tmp2;
3037 
3038 	i = 0;
3039 	tmp = curscr->first_line;
3040 	while (i < window->SR)
3041 	{
3042 		i++;
3043 		tmp = tmp->next_screen;
3044 	}
3045 	/*
3046 	 |	find line to delete
3047 	 */
3048 	top_of_win = tmp;
3049 	if ((row + window->SR) == 0)
3050 		curscr->first_line = top_of_win->next_screen;
3051 	for (i = 0, tmp = top_of_win; i < row; i++)
3052 		tmp = tmp->next_screen;
3053 	if (tmp->prev_screen != NULL)
3054 		tmp->prev_screen->next_screen = tmp->next_screen;
3055 	if (tmp->next_screen != NULL)
3056 		tmp->next_screen->prev_screen = tmp->prev_screen;
3057 	tmp2 = tmp->next_screen;
3058 	tmp1 = tmp;
3059 	/*
3060 	 |	clear deleted line
3061 	 */
3062 	clear_line(tmp1, 0, window->Num_cols);
3063 	tmp1->number = -1;
3064 	/*
3065 	 |	find location to insert deleted line
3066 	 */
3067 	for (i = 0, tmp = curscr->first_line; (tmp->next_screen != NULL) && (i < window->SR); i++)
3068 		tmp = tmp->next_screen;
3069 	top_of_win = tmp;
3070 	for (i = 0, tmp = top_of_win; (i < end_row) && (tmp->next_screen != NULL); i++)
3071 		tmp = tmp->next_screen;
3072 	tmp1->next_screen = tmp;
3073 	tmp1->prev_screen = tmp->prev_screen;
3074 	if (tmp1->prev_screen != NULL)
3075 		tmp1->prev_screen->next_screen = tmp1;
3076 	tmp->prev_screen = tmp1;
3077 
3078 	Position(window, (window->SR + row), 0);
3079 	String_Out(String_table[dl__], NULL, 0);
3080 	if ((!String_table[cs__]) && (end_row < window->Num_lines))
3081 	{
3082 		Position(window, (window->SR + end_row), 0);
3083 		String_Out(String_table[al__], NULL, 0);
3084 	}
3085 	else if ((String_table[cs__] != NULL) && (String_table[dl__] == NULL))
3086 	{
3087 		Position(window, (window->SR + end_row), 0);
3088 		putchar('\n');
3089 	}
3090 
3091 	if (row == (window->Num_lines-1))
3092 		tmp2 = tmp1;
3093 	if ((row + window->SR) == 0)
3094 		curscr->first_line = top_of_win = tmp2;
3095 	return(tmp2);
3096 }
3097 
3098 void
3099 CLEAR_TO_EOL(window, row, column)
3100 WINDOW *window;
3101 int row, column;
3102 {
3103 	int x, y;
3104 	struct _line *tmp1;
3105 
3106 	for (y = 0, tmp1 = curscr->first_line; (y < (window->SR+row)) && (tmp1->next_screen != NULL); y++)
3107 		tmp1 = tmp1->next_screen;
3108 	for (x = column; x<window->Num_cols; x++)
3109 	{
3110 		tmp1->row[x] = ' ';
3111 		tmp1->attributes[x] = (char) NULL;
3112 	}
3113 	tmp1->row[column] = (char) NULL;
3114 	tmp1->last_char = column;
3115 	if (column < COLS)
3116 	{
3117 		if (STAND)
3118 		{
3119 			STAND = FALSE;
3120 			Position(window, row, column);
3121 			attribute_off();
3122 		}
3123 		if (String_table[ce__] != NULL)
3124 			String_Out(String_table[ce__], NULL, 0);
3125 		else
3126 		{
3127 			for (x = column; x < window->Num_cols; x++)
3128 				putchar(' ');
3129 			Curr_x = x;
3130 		}
3131 	}
3132 }
3133 
3134 int
3135 check_delete(window, line, offset, pointer_new, pointer_old)
3136 WINDOW *window;
3137 int line, offset;
3138 struct _line *pointer_new, *pointer_old;
3139 {
3140 	int end_old;
3141 	int end_new;
3142 	int k;
3143 	int changed;
3144 	char *old_lin;
3145 	char *new_lin;
3146 	char *old_att;
3147 	char *new_att;
3148 
3149 	changed = FALSE;
3150 	new_lin = pointer_new->row;
3151 	new_att = pointer_new->attributes;
3152 	old_lin = pointer_old->row;
3153 	old_att = pointer_old->attributes;
3154 	end_old = end_new = offset;
3155 	while (((new_lin[end_new] != old_lin[end_old]) || (new_att[end_new] != old_att[end_old])) && (old_lin[end_old] != (char) NULL) && (new_lin[end_old] != (char) NULL))
3156 		end_old++;
3157 	if (old_lin[end_old] != (char) NULL)
3158 	{
3159 		k = 0;
3160 		while ((old_lin[end_old+k] == new_lin[end_new+k]) && (new_att[end_new+k] == old_att[end_old+k]) && (new_lin[end_new+k] != (char) NULL) && (old_lin[end_old+k] != (char) NULL) && (k < 10))
3161 			k++;
3162 		if ((k > 8) || ((new_lin[end_new+k] == (char) NULL) && (k != 0)))
3163 		{
3164 			if (new_lin[end_new+k] == (char) NULL)
3165 			{
3166 				Position(window, line, (end_new+k));
3167 				CLEAR_TO_EOL(window, line, (end_new+k));
3168 			}
3169 			Position(window, line, offset);
3170 			for (k = offset; k < end_old; k++)
3171 				Char_del(old_lin, old_att, offset, window->Num_cols);
3172 			while ((old_lin[offset] != (char) NULL) && (offset < COLS))
3173 				offset++;
3174 			pointer_old->last_char = offset;
3175 			changed = TRUE;
3176 		}
3177 	}
3178 	return(changed);
3179 }
3180 
3181 /*
3182  |	Check if characters were inserted in the middle of a line, and if
3183  |	so, insert them.
3184  */
3185 
3186 int
3187 check_insert(window, line, offset, pointer_new, pointer_old)
3188 WINDOW *window;
3189 int line, offset;
3190 struct _line *pointer_new, *pointer_old;
3191 {
3192 	int changed;
3193 	int end_old, end_new;
3194 	int k;
3195 	int same = FALSE;
3196 	int old_off;
3197 	int insert;
3198 	char *old_lin;
3199 	char *new_lin;
3200 	char *old_att;
3201 	char *new_att;
3202 
3203 	changed = FALSE;
3204 	new_lin = pointer_new->row;
3205 	new_att = pointer_new->attributes;
3206 	old_lin = pointer_old->row;
3207 	old_att = pointer_old->attributes;
3208 	end_old = end_new = offset;
3209 	while (((new_lin[end_new] != old_lin[end_old]) || (new_att[end_new] != old_att[end_old])) && (new_lin[end_new] != (char) NULL) && (old_lin[end_new] != (char) NULL))
3210 		end_new++;
3211 	if (new_lin[end_new] != (char) NULL)
3212 	{
3213 		k = 0;
3214 		while ((old_lin[end_old+k] == new_lin[end_new+k]) && (old_att[end_old+k] == new_att[end_new+k]) && (new_lin[end_new+k] != (char) NULL) && (old_lin[end_old+k] != (char) NULL) && (k < 10))
3215 			k++;
3216 		/*
3217 		 |  check for commonality between rest of lines (are the old
3218 		 |  and new lines the same, except for a chunk in the middle?)
3219 		 |  if the rest of the lines are common, do not insert text
3220 		 */
3221 		old_off = end_new;
3222 		while ((old_lin[old_off] != (char) NULL) && (new_lin[old_off] != (char) NULL) && (old_lin[old_off] == new_lin[old_off]) && (old_att[old_off] == new_att[old_off]))
3223 			old_off++;
3224 		if ((old_lin[old_off] == new_lin[old_off]) && (old_att[old_off] == new_att[old_off]))
3225 			same = TRUE;
3226 		if ((!same) && ((k > 8) || ((new_lin[end_new+k] == (char) NULL) && (k != 0))))
3227 		{
3228 			Position(window, line, offset);
3229 			insert = FALSE;
3230 			if (String_table[ic__] == NULL)
3231 			{
3232 				String_Out(String_table[im__], NULL, 0);
3233 				insert = TRUE;
3234 			}
3235 			for (k = offset; k < end_new; k++)
3236 			{
3237 				if (!insert)
3238 					String_Out(String_table[ic__], NULL, 0);
3239 				Char_ins(old_lin, old_att, new_lin[k], new_att[k], k, window->Num_cols);
3240 			}
3241 			if (insert)
3242 				String_Out(String_table[ei__], NULL, 0);
3243 			while ((old_lin[offset] != (char) NULL) && (offset < COLS))
3244 				offset++;
3245 			pointer_old->last_char = offset;
3246 			changed = TRUE;
3247 		}
3248 	}
3249 	return(changed);
3250 }
3251 
3252 void
3253 doupdate()
3254 {
3255 	WINDOW *window;
3256 	int similar;
3257 	int diff;
3258 	int begin_old, begin_new;
3259 	int end_old, end_new;
3260 	int count1, j;
3261 	int from_top, tmp_ft, offset;
3262 	int changed;
3263 	int first_time;
3264 	int first_same;
3265 	int last_same;
3266 	int list[10];
3267 	int bottom;
3268 
3269 	struct _line *curr;
3270 	struct _line *virt;
3271 	struct _line *old;
3272 
3273 	struct _line *new;
3274 
3275 	struct _line *old1, *new1;
3276 
3277 	char *cur_lin;
3278 	char *vrt_lin;
3279 	char *cur_att;
3280 	char *vrt_att;
3281 	char *att1, *att2;
3282 	char *c1, *c2;
3283 
3284 	char NC_chinese = FALSE;	/* flag to indicate handling Chinese */
3285 
3286 	window = virtual_scr;
3287 
3288 	if ((nc_attributes & A_NC_BIG5) != 0)
3289 		NC_chinese = TRUE;
3290 
3291 	if (Repaint_screen)
3292 	{
3293 		if (String_table[cl__])
3294 			String_Out(String_table[cl__], NULL, 0);
3295 		else
3296 		{
3297 			from_top = 0;
3298 			while (from_top < LINES)
3299 			{
3300 				Position(curscr, from_top, 0);
3301 				if (String_table[ce__] != NULL)
3302 					String_Out(String_table[ce__], NULL, 0);
3303 				else
3304 				{
3305 					for (j = 0; j < window->Num_cols; j++)
3306 						putchar(' ');
3307 				}
3308 				from_top++;
3309 			}
3310 		}
3311 		for (from_top = 0, curr = curscr->first_line; from_top < curscr->Num_lines; from_top++, curr = curr->next_screen)
3312 		{
3313 			Position(curscr, from_top, 0);
3314 			for (j = 0; (curr->row[j] != (char) NULL) && (j < curscr->Num_cols); j++)
3315 			{
3316 				Char_out(curr->row[j], curr->attributes[j], curr->row, curr->attributes, j);
3317 			}
3318 			if (STAND)
3319 			{
3320 				STAND = FALSE;
3321 				Position(curscr, from_top, j);
3322 				attribute_off();
3323 			}
3324 		}
3325 		Repaint_screen = FALSE;
3326 	}
3327 
3328 	similar = 0;
3329 	diff = FALSE;
3330 	top_of_win = curscr->first_line;
3331 
3332 	for (from_top = 0, curr = top_of_win, virt = window->first_line;
3333 			from_top < window->Num_lines; from_top++)
3334 	{
3335 		virtual_lines[from_top] = TRUE;
3336 		if ((similar = Comp_line(curr, virt)) > 0)
3337 		{
3338 			virtual_lines[from_top] = FALSE;
3339 			diff = TRUE;
3340 		}
3341 		curr = curr->next_screen;
3342 		virt = virt->next_screen;
3343 	}
3344 
3345 	from_top = 0;
3346 	virt = window->first_line;
3347 	curr = top_of_win;
3348 	similar = 0;
3349 	/*
3350 	 |  if the window has lines that are different, check for scrolling
3351 	 */
3352 	if (diff)
3353 	{
3354 		last_same = -1;
3355 		changed = FALSE;
3356 		for (first_same = window->Num_lines;
3357 		    (first_same > from_top) && (virtual_lines[first_same - 1]);
3358 		     first_same--)
3359 			;
3360 		for (last_same = 0;
3361 		    (last_same < window->Num_lines) && (virtual_lines[last_same]== FALSE);
3362 		     last_same++)
3363 			;
3364 		while ((from_top < first_same) && nc_scrolling_ability)
3365 					/* check entire lines for diffs	*/
3366 		{
3367 
3368 			if (from_top >= last_same)
3369 			{
3370 				for (last_same = from_top;
3371 				     (last_same < window->Num_lines) &&
3372 				     (virtual_lines[last_same] == FALSE);
3373 				      last_same++)
3374 					;
3375 			}
3376 			if (!virtual_lines[from_top])
3377 			{
3378 				diff = TRUE;
3379 				/*
3380 				 |	check for lines deleted (scroll up)
3381 				 */
3382 				for (tmp_ft = from_top+1, old = curr->next_screen;
3383 					((window->scroll_up) && (diff) &&
3384 					(tmp_ft < last_same) &&
3385 					(!virtual_lines[tmp_ft]));
3386 						tmp_ft++)
3387 				{
3388 					if ((Comp_line(old, virt) == -1) && (!virtual_lines[from_top]))
3389 					{
3390 						/*
3391 						 |	Find the bottom of the
3392 						 |	area that should be
3393 						 |	scrolled.
3394 						 */
3395 						for (bottom = tmp_ft, old1 = old,
3396 						     new1 = virt, count1 = 0;
3397 							(bottom < window->Num_lines) &&
3398 								(Comp_line(old1, new1) <= 0);
3399 								bottom++, old1 = old1->next_screen,
3400 								new1 = new1->next_screen,
3401 								count1++)
3402 							;
3403 						if (count1 > 3)
3404 						{
3405 							if (String_table[cs__]) /* scrolling region */
3406 							{
3407 								list[1] = from_top;
3408 								list[0] = min((bottom - 1), (window->Num_lines - 1));
3409 								String_Out(String_table[cs__], list, 2);
3410 								Curr_y = Curr_x = -1;
3411 							}
3412 
3413 							for (offset = (tmp_ft - from_top); (offset > 0); offset--)
3414 							{
3415 								old = Delete_line(from_top, min((bottom - 1), (window->Num_lines - 1)), window);
3416 								diff = FALSE;
3417 							}
3418 
3419 							if (String_table[cs__]) /* scrolling region */
3420 							{
3421 								list[1] = 0;
3422 								list[0] = LINES - 1;
3423 								String_Out(String_table[cs__], list, 2);
3424 								Curr_y = Curr_x = -1;
3425 							}
3426 
3427 							top_of_win = curscr->first_line;
3428 							curr = top_of_win;
3429 							for (offset = 0; offset < from_top; offset++)
3430 								curr = curr->next_screen;
3431 							for (offset = from_top, old=curr, new=virt;
3432 							   offset < window->Num_lines;
3433 							   old=old->next_screen, new=new->next_screen,
3434 							   offset++)
3435 							{
3436 								similar = Comp_line(old, new);
3437 								virtual_lines[offset] = (similar > 0 ? FALSE : TRUE);
3438 							}
3439 						}
3440 					}
3441 					else
3442 						old = old->next_screen;
3443 				}
3444 				/*
3445 				 |	check for lines inserted (scroll down)
3446 				 */
3447 				for (tmp_ft = from_top-1, old = curr->prev_screen;
3448 					((window->scroll_down) && (tmp_ft >= 0) &&
3449 					(diff) &&
3450 					(!virtual_lines[tmp_ft]));
3451 					  tmp_ft--)
3452 				{
3453 					if (Comp_line(old, virt) == -1)
3454 					{
3455 						/*
3456 						 |	Find the bottom of the
3457 						 |	area that should be
3458 						 |	scrolled.
3459 						 */
3460 						for (bottom = from_top, old1 = old,
3461 						     new1 = virt, count1 = 0;
3462 							(bottom < window->Num_lines) &&
3463 								(Comp_line(old1, new1) <= 0);
3464 								bottom++, old1 = old1->next_screen,
3465 								new1 = new1->next_screen,
3466 								count1++)
3467 							;
3468 						if (count1 > 3)
3469 						{
3470 							if (String_table[cs__]) /* scrolling region */
3471 							{
3472 								list[1] = tmp_ft;
3473 								list[0] = min((bottom - 1), (window->Num_lines - 1));
3474 								String_Out(String_table[cs__], list, 2);
3475 								Curr_y = Curr_x = -1;
3476 							}
3477 
3478 							for (offset = (from_top - tmp_ft); (offset > 0); offset--)
3479 							{
3480 								old = Insert_line(tmp_ft, min((bottom - 1), (window->Num_lines -1)), window);
3481 								diff = FALSE;
3482 							}
3483 
3484 							if (String_table[cs__]) /* scrolling region */
3485 							{
3486 								list[1] = 0;
3487 								list[0] = LINES - 1;
3488 								String_Out(String_table[cs__], list, 2);
3489 								Curr_y = Curr_x = -1;
3490 							}
3491 
3492 							top_of_win = curscr->first_line;
3493 							curr = top_of_win;
3494 							for (offset = 0; offset < from_top; offset++)
3495 								curr = curr->next_screen;
3496 							for (offset = from_top, old=curr, new=virt;
3497 							   offset < window->Num_lines;
3498 							   old=old->next_screen, new=new->next_screen,
3499 							   offset++)
3500 							{
3501 								similar = Comp_line(old, new);
3502 								virtual_lines[offset] = (similar > 0 ? FALSE : TRUE);
3503 							}
3504 						}
3505 					}
3506 					else
3507 						old = old->prev_screen;
3508 				}
3509 			}
3510 			from_top++;
3511 			curr = curr->next_screen;
3512 			virt = virt->next_screen;
3513 		}
3514 	}
3515 
3516 
3517 	/*
3518 	 |	Scrolling done, now need to insert, delete, or modify text
3519 	 |	within lines.
3520 	 */
3521 
3522 	for (from_top = 0, curr = curscr->first_line; from_top < window->SR; from_top++)
3523 		curr = curr->next_screen;
3524 	top_of_win = curr;
3525 	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)
3526 	{
3527 
3528 		/*
3529 		 |	If either 'insert mode' or 'insert char' are
3530 		 |	available, enter the following 'if' statement,
3531 		 |	else, need to simply rewrite the contents of the line
3532 		 |	at the point where the contents of the line change.
3533 		 */
3534 
3535 		if (((String_table[ic__]) || (String_table[im__])) &&
3536 		    (String_table[dc__]) && (curr->row[0] != (char) NULL) &&
3537 		    (!NC_chinese))
3538 		{
3539 			j = 0;
3540 			first_time = TRUE;
3541 			vrt_lin = virt->row;
3542 			vrt_att = virt->attributes;
3543 			cur_lin = curr->row;
3544 			cur_att = curr->attributes;
3545 			while ((vrt_lin[j] != (char) NULL) && (j < window->Num_cols))
3546 			{
3547 				if ((STAND) && (Booleans[xs__]))
3548 				{
3549 					while ((vrt_lin[j] == cur_lin[j]) && (vrt_att[j] == cur_att[j]) && (vrt_lin[j] != (char) NULL) && (vrt_att[j]))
3550 						j++;
3551 					if ((STAND) && (!vrt_att[j]))
3552 					{
3553 						STAND = FALSE;
3554 						Position(window, from_top, j);
3555 						attribute_off();
3556 						attribute_off();
3557 					}
3558 				}
3559 				else
3560 				{
3561 					while ((vrt_lin[j] == cur_lin[j]) && (vrt_att[j] == cur_att[j]) && (vrt_lin[j] != (char) NULL))
3562 						j++;
3563 				}
3564 				if ((vrt_att[j] != cur_att[j]) && (cur_att[j]) && (Booleans[xs__]))
3565 				{
3566 					Position(window, from_top, j);
3567 /*					CLEAR_TO_EOL(window, from_top, j);*/
3568 					attribute_off();
3569 					attribute_off();
3570 				}
3571 				if (vrt_lin[j] != (char) NULL)
3572 				{
3573 					begin_new = j;
3574 					begin_old = j;
3575 					end_old = j;
3576 					end_new = j;
3577 					if ((first_time) && (virt->changed))
3578 					{
3579 						if (curr->last_char <= virt->last_char)
3580 							changed = check_insert(window, from_top, j, virt, curr);
3581 					}
3582 					changed = check_delete(window, from_top, j, virt, curr);
3583 					first_time = FALSE;
3584 					virt->changed = FALSE;
3585 					if (!changed)
3586 						changed = check_insert(window, from_top, j, virt, curr);
3587 					if (((!changed) || (cur_lin[j] != vrt_lin[j]) || (cur_att[j] != vrt_att[j])) && (j < window->Num_cols))
3588 					{
3589 						if ((vrt_lin[j] == ' ') && (cur_lin[j] == (char) NULL) && (vrt_att[j] == cur_att[j]))
3590 							cur_lin[j] = ' ';
3591 						else
3592 						{
3593 							Position(window, from_top, j);
3594 							Char_out(vrt_lin[j], vrt_att[j], cur_lin, cur_att, j);
3595 						}
3596 					}
3597 					if ((vrt_lin[j] != (char) NULL))
3598 						j++;
3599 				}
3600 				if ((STAND) && (!vrt_att[j]))
3601 				{
3602 					STAND = FALSE;
3603 					Position(window, from_top, j);
3604 					attribute_off();
3605 				}
3606 			}
3607 			if ((vrt_lin[j] == (char) NULL) && (cur_lin[j] != (char) NULL))
3608 			{
3609 				Position(window, from_top, j);
3610 				CLEAR_TO_EOL(window, from_top, j);
3611 			}
3612 		}
3613 		else /*if ((similar != -1) && (similar != 0))*/
3614 		{
3615 			j = 0;
3616 			c1 = curr->row;
3617 			att1 = curr->attributes;
3618 			c2 = virt->row;
3619 			att2 = virt->attributes;
3620 			while ((j < window->Num_cols) && (c2[j] != (char) NULL))
3621 			{
3622 				while ((c1[j] == c2[j]) && (att1[j] == att2[j]) && (j < window->Num_cols) && (c2[j] != (char) NULL))
3623 					j++;
3624 
3625 				/*
3626 				 |	if previous character is an eight bit
3627 				 |	char, start redraw from that character
3628 				 */
3629 
3630 				if ((NC_chinese) && (highbitset(c1[j - 1])))
3631 					j--;
3632 				begin_old = j;
3633 				begin_new = j;
3634 				if ((j < window->Num_cols) && (c2[j] != (char) NULL))
3635 				{
3636 					Position(window, from_top, begin_old);
3637 					CLEAR_TO_EOL(window, from_top, j);
3638 					Position(window, from_top, begin_old);
3639 					for (j = begin_old; (c2[j] != (char) NULL) && (j < window->Num_cols); j++)
3640 						Char_out(c2[j], att2[j], c1, att1, j);
3641 				}
3642 			}
3643 			if ((c2[j] == (char) NULL) && (c1[j] != (char) NULL))
3644 			{
3645 				Position(window, from_top, j);
3646 				CLEAR_TO_EOL(window, from_top, j);
3647 			}
3648 		}
3649 		if (STAND)
3650 		{
3651 			STAND = FALSE;
3652 			Position(window, from_top, j);
3653 			attribute_off();
3654 		}
3655 		virt->number = from_top;
3656 	}
3657 	Position(window, window->LY, window->LX);
3658 }
3659 
3660 void
3661 Position(window, row, col)	/* position the cursor for output on the screen	*/
3662 WINDOW *window;
3663 int row;
3664 int col;
3665 {
3666 	int list[10];
3667 	int place;
3668 
3669 	int pos_row;
3670 	int pos_column;
3671 
3672 	pos_row = row + window->SR;
3673 	pos_column = col + window->SC;
3674 	if ((pos_row != Curr_y) || (pos_column != Curr_x))
3675 	{
3676 		if (String_table[cm__] != NULL) /* && (row < window->Num_lines) && (column < window->Num_cols))*/
3677 		{
3678 			place = 0;
3679 			list[place++] = pos_column;
3680 			list[place++] = pos_row;
3681 			String_Out(String_table[cm__], list, place);
3682 			if ((STAND) && (!Booleans[ms__]))
3683 				attribute_on();
3684 		}
3685 		Curr_x = pos_column;
3686 		Curr_y = pos_row;
3687 	}
3688 }
3689 
3690 void
3691 Char_del(line, attrib, offset, maxlen)	/* delete chars from line	*/
3692 char *line;
3693 char *attrib;
3694 int offset;
3695 int maxlen;
3696 {
3697 	int one, two;
3698 
3699 	for (one = offset, two = offset+1; (line[one] != (char) NULL) && (one < maxlen); one++, two++)
3700 	{
3701 		line[one] = line[two];
3702 		attrib[one] = attrib[two];
3703 	}
3704 	String_Out(String_table[dc__], NULL, 0);
3705 }
3706 
3707 void
3708 Char_ins(line, attrib, newc, newatt, offset, maxlen)	/* insert chars in line	*/
3709 char *line;
3710 char *attrib;
3711 char newc;
3712 char newatt;
3713 int offset;
3714 int maxlen;
3715 {
3716 	int one, two;
3717 
3718 	one = 0;
3719 	while ((line[one] != (char) NULL) && (one < (maxlen - 2)))
3720 		one++;
3721 	for (two = one + 1; (two > offset); one--, two--)
3722 	{
3723 		line[two] = line[one];
3724 		attrib[two] = attrib[one];
3725 	}
3726 	line[offset] = newc;
3727 	attrib[offset] = newatt;
3728 	Char_out(newc, newatt, line, attrib, offset);
3729 }
3730 
3731 void
3732 attribute_on()
3733 {
3734 	if (String_table[sa__])
3735 	{
3736 		attributes_set[0] = 1;
3737 		String_Out(String_table[sa__], attributes_set, 1);
3738 	}
3739 	else if (String_table[so__])
3740 		String_Out(String_table[so__], NULL, 0);
3741 }
3742 
3743 void
3744 attribute_off()
3745 {
3746 	if (String_table[me__])
3747 		String_Out(String_table[me__], NULL, 0);
3748 	else if (String_table[sa__])
3749 	{
3750 		attributes_set[0] = 0;
3751 		String_Out(String_table[sa__], attributes_set, 1);
3752 	}
3753 	else if (String_table[se__])
3754 		String_Out(String_table[se__], NULL, 0);
3755 }
3756 
3757 void
3758 Char_out(newc, newatt, line, attrib, offset)	/* output character with proper attribute	*/
3759 char newc;
3760 char newatt;
3761 char *line;
3762 char *attrib;
3763 int offset;
3764 {
3765 
3766 
3767 	if ((newatt) && (!STAND))
3768 	{
3769 		STAND = TRUE;
3770 		attribute_on();
3771 	}
3772 	else if ((STAND) && (!newatt))
3773 	{
3774 		STAND = FALSE;
3775 		attribute_off();
3776 	}
3777 
3778 	if ((newatt) && (STAND) && (Booleans[xs__]))
3779 	{
3780 		attribute_on();
3781 	}
3782 
3783 	if (!((Curr_y >= (LINES - 1)) && (Curr_x >= (COLS - 1))))
3784 	{
3785 		putchar(newc);
3786 		line[offset] = newc;
3787 		attrib[offset] = newatt;
3788 	}
3789 	Curr_x++;
3790 }
3791 
3792 /*
3793  |
3794  |	The two routines that follow, nc_setattrib(), nc_clearattrib(), are
3795  |	hacks that notify new_curse to handle characters that have the high
3796  |	bit set as the first of two bytes of a multi-byte string.
3797  |
3798  */
3799 
3800 void
3801 nc_setattrib(flag)
3802 int flag;
3803 {
3804 	nc_attributes |= flag;
3805 }
3806 
3807 void
3808 nc_clearattrib(flag)
3809 int flag;
3810 {
3811 	nc_attributes &= ~flag;
3812 }
3813 
3814