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