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