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