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