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