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