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