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