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