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