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