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