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