aboutsummaryrefslogblamecommitdiff
path: root/usr.bin/ee/new_curse.c
blob: 22e1a847f6e01751e1f090c6f2faba4144525745 (plain) (tree)
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012






































                                                                               
                                                                                                     





                                                                                                        

                      
























                                     
                   



















                                       
                                    


































































































































































































































































































































































































































                                                                                          



































































































                                                                           






















                                                                                

                                                                                



















                                         


                     



                









































































































































































































































                                                                                              







                                                                                              

















































                                                                                                
                     






















































































































































































































































                                                                                                          

























                                                                                     

























































































































































































































































                                                                                                                                                       





                                                                    











































































































































































































































































































































































































































































































































                                                                                                                                                         
                                                 



                                               




                                                  




















































































































                                                                                                                            
                                                                    




                                                                                                     










                                                                                              




                                                                                               






















































                                                                          
                                                        
















                                                                            
                                                                                                    


                                                   
                                                                                       






                                                                
                                                                                            





































































































































                                                                                 
                        





                                                                          
                         













                                            
                                                                          





                                                               






                                                               





                                                                     
                                                                               








































































                                                                                                               










































                                                                                        





























































                                                                               
 






































































































































































                                                                                          




































                                                                                              

                                                
 
                   



                     
                             











































                                                                              
                   


















                                                          
                           



                          



                                 









                                       



                                                                                                            
                                           
                                                                          
                                  

                                                                          
                                                                          


























































































































































































































                                                                                                                                                                                                          




                                                                          
















































































                                                                                                                                                                                                          






                           






                          

                                                                               

                             


                                             


























































                                                                                                                                 
                                                                           








                                                                               
                                        







                                                                                          
 





















                                                                                                       
                                                                                              
                                                 




                                                                                                                
 




                                                                                                                                           
 


                                                                                              
                                                                            

                                                                                                
                                                         
 










                                                                                                             















                                                                                   
                                                                                              
                                                 




                                                                                                                
 




                                                                                                                                        
 


                                                                                              
                                                                            


                                                                                                
 










                                                                                                             











                                                                       





                                                                           




                                                                                                                                                                      










                                                                             





















































































                                                                                                                                                       







                                                                              































































































































































                                                                                                                  





















                                                                            
/*
 |	new_curse.c
 |
 |	A subset of curses developed for use with ae.
 |
 |	written by Hugh Mahon
 |
 |	THIS MATERIAL IS PROVIDED "AS IS".  THERE ARE
 |	NO WARRANTIES OF ANY KIND WITH REGARD TO THIS
 |	MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE
 |	IMPLIED WARRANTIES OF MERCHANTABILITY AND
 |	FITNESS FOR A PARTICULAR PURPOSE.  Neither
 |	Hewlett-Packard nor Hugh Mahon shall be liable
 |	for errors contained herein, nor for
 |	incidental or consequential damages in
 |	connection with the furnishing, performance or
 |	use of this material.  Neither Hewlett-Packard
 |	nor Hugh Mahon assumes any responsibility for
 |	the use or reliability of this software or
 |	documentation.  This software and
 |	documentation is totally UNSUPPORTED.  There
 |	is no support contract available.  Hewlett-
 |	Packard has done NO Quality Assurance on ANY
 |	of the program or documentation.  You may find
 |	the quality of the materials inferior to
 |	supported materials.
 |
 |	This software is not a product of Hewlett-Packard, Co., or any 
 |	other company.  No support is implied or offered with this software.
 |	You've got the source, and you're on your own.
 |
 |	This software may be distributed under the terms of Larry Wall's 
 |	Artistic license, a copy of which is included in this distribution. 
 |
 |	This notice must be included with this software and any derivatives.
 |
 |	Copyright (c) 1986, 1987, 1988, 1991, 1992, 1993, 1994, 1995 Hugh Mahon
 |	All are rights reserved.
 |
 |	$Header: /home/hugh/sources/old_ae/RCS/new_curse.c,v 1.49 1998/12/21 02:25:59 hugh Exp hugh $
 |
 */

char *copyright_message[] = { "Copyright (c) 1986, 1987, 1988, 1991, 1992, 1993, 1994, 1995 Hugh Mahon",
				"All rights are reserved."};

#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");

#include "new_curse.h"
#include <signal.h>
#include <fcntl.h>

#ifdef SYS5
#include <string.h>
#else
#include <strings.h>
#endif

#ifdef BSD_SELECT
#include <sys/types.h>
#include <sys/time.h>

#ifdef SLCT_HDR
#include <sys/select.h>  /* on AIX */
#endif /* SLCT_HDR */

#endif /* BSD_SELECT */

#ifdef HAS_STDLIB
#include <stdlib.h>
#endif

#include <stdarg.h>

#ifdef HAS_UNISTD
#include <unistd.h>
#endif

#ifdef HAS_SYS_IOCTL
#include <sys/ioctl.h>
#endif


WINDOW *curscr;
static WINDOW *virtual_scr;
WINDOW *stdscr;
WINDOW *last_window_refreshed;

#ifdef TIOCGWINSZ
	struct winsize ws;
#endif

#define min(a, b)	(a < b ? a : b)
#define highbitset(a)	((a) & 0x80)

#ifndef CAP
#define String_Out(table, stack, place) Info_Out(table, stack, place)
#else
#define String_Out(table, stack, place) Cap_Out(table, stack, place)
#endif

#define bw__ 0	/* booleans	*/
#define am__ 1
#define xb__ 2
#define xs__ 3	/* hp glitch (standout not erased by overwrite)	*/
#define xn__ 4
#define eo__ 5
#define gn__ 6	/* generic type terminal	*/
#define hc__ 7	/* hardcopy terminal		*/
#define km__ 8
#define hs__ 9
#define in__ 10
#define da__ 11
#define db__ 12
#define mi__ 13	/* safe to move during insert mode	*/
#define ms__ 14	/* safe to move during standout mode	*/
#define os__ 15
#define es__ 16
#define xt__ 17
#define hz__ 18	/* hazeltine glitch	*/
#define ul__ 19
#define xo__ 20
#define chts__ 21
#define nxon__ 22
#define nrrmc__ 23
#define npc__ 24
#define mc5i__ 25

#define co__ 0	/* number of columns	*/	/* numbers		*/
#define it__ 1	/* spaces per tab	*/
#define li__ 2	/* number of lines	*/
#define lm__ 3
#define sg__ 4	/* magic cookie glitch	*/
#define pb__ 5
#define vt__ 6
#define ws__ 7

#define cols__ 0
#define lines__ 2
#define xmc__ 4
#define vt__ 6
#define wsl__ 7
#define nlab__ 8
#define lh__ 9
#define lw__ 10

#define bt__ 0	/* back tab		*/	/* strings	*/
#define bl__ 1	/* bell			*/
#define cr__ 2	/* carriage return	*/
#define cs__ 3	/* change scroll region	*/
#define ct__ 4	/* clear all tab stops	*/
#define cl__ 5	/* clear screen and home cursor	*/
#define ce__ 6	/* clear to end of line	*/
#define cd__ 7	/* clear to end of display	*/
#define ch__ 8	/* set cursor column	*/
#define CC__ 9	/* term, settable cmd char in 	*/
#define cm__ 10	/* screen rel cursor motion, row, column	*/
#define do__ 11	/* down one line	*/
#define ho__ 12	/* home cursor	*/
#define vi__ 13	/* make cursor invisible	*/
#define le__ 14	/* move cursor left one space	*/
#define CM__ 15	/* memory rel cursor addressing	*/
#define ve__ 16	/* make cursor appear normal	*/
#define nd__ 17	/* non-destructive space (cursor right)	*/
#define ll__ 18	/* last line, first col	*/
#define up__ 19	/* cursor up		*/
#define vs__ 20
#define dc__ 21	/* delete character	*/
#define dl__ 22	/* delete line		*/
#define ds__ 23
#define hd__ 24
#define as__ 25
#define mb__ 26
#define md__ 27	/* turn on bold		*/
#define ti__ 28
#define dm__ 29	/* turn on delete mode	*/
#define mh__ 30	/* half bright mode	*/
#define im__ 31	/* insert mode		*/
#define mk__ 32
#define mp__ 33
#define mr__ 34
#define so__ 35	/* enter standout mode	*/
#define us__ 36
#define ec__ 37
#define ae__ 38
#define me__ 39
#define te__ 40
#define ed__ 41
#define ei__ 42	/* exit insert mode	*/
#define se__ 43	/* exit standout mode	*/
#define ue__ 44
#define vb__ 45
#define ff__ 46
#define fs__ 47
#define i1__ 48
#define i2__ 49
#define i3__ 50
#define if__ 51
#define ic__ 52
#define al__ 53
#define ip__ 54
#define kb__ 55		/* backspace key	*/
#define ka__ 56
#define kC__ 57
#define kt__ 58
#define kD__ 59
#define kL__ 60
#define kd__ 61
#define kM__ 62
#define kE__ 63
#define kS__ 64
#define k0__ 65
#define k1__ 66
#define kf10__ 67
#define k2__ 68
#define k3__ 69
#define k4__ 70
#define k5__ 71
#define k6__ 72
#define k7__ 73
#define k8__ 74
#define k9__ 75
#define kh__ 76
#define kI__ 77
#define kA__ 78
#define kl__ 79
#define kH__ 80
#define kN__ 81
#define kP__ 82
#define kr__ 83
#define kF__ 84
#define kR__ 85
#define kT__ 86
#define ku__ 87	/* key up	*/
#define ke__ 88
#define ks__ 89
#define l0__ 90
#define l1__ 91
#define la__ 92
#define l2__ 93
#define l3__ 94
#define l4__ 95
#define l5__ 96
#define l6__ 97
#define l7__ 98
#define l8__ 99
#define l9__ 100
#define mo__ 101
#define mm__ 102
#define nw__ 103
#define pc__ 104
#define DC__ 105
#define DL__ 106
#define DO__ 107
#define IC__ 118
#define SF__ 109
#define AL__ 110
#define LE__ 111
#define RI__ 112
#define SR__ 113
#define UP__ 114
#define pk__ 115
#define pl__ 116
#define px__ 117
#define ps__ 118
#define pf__ 119
#define po__ 120
#define rp__ 121
#define r1__ 122
#define r2__ 123
#define r3__ 124
#define rf__ 125
#define rc__ 126
#define cv__ 127
#define sc__ 128
#define sf__ 129
#define sr__ 130
#define sa__ 131	/* sgr	*/
#define st__ 132
#define wi__ 133
#define ta__ 134
#define ts__ 135
#define uc__ 136
#define hu__ 137
#define iP__ 138
#define K1__ 139
#define K2__ 140
#define K3__ 141
#define K4__ 142
#define K5__ 143
#define pO__ 144
#define ml__ 145
#define mu__ 146
#define rmp__ 145
#define acsc__ 146
#define pln__ 147
#define kcbt__ 148
#define smxon__ 149
#define rmxon__ 150
#define smam__ 151
#define rmam__ 152
#define xonc__ 153
#define xoffc__ 154
#define enacs__ 155
#define smln__ 156
#define rmln__ 157
#define kbeg__ 158
#define kcan__ 159
#define kclo__ 160
#define kcmd__ 161
#define kcpy__ 162
#define kcrt__ 163
#define kend__ 164
#define kent__ 165
#define kext__ 166
#define kfnd__ 167
#define khlp__ 168
#define kmrk__ 169
#define kmsg__ 170
#define kmov__ 171
#define knxt__ 172
#define kopn__ 173
#define kopt__ 174
#define kprv__ 175
#define kprt__ 176
#define krdo__ 177
#define kref__ 178
#define krfr__ 179
#define krpl__ 180
#define krst__ 181
#define kres__ 182
#define ksav__ 183
#define kspd__ 184
#define kund__ 185
#define kBEG__ 186
#define kCAN__ 187
#define kCMD__ 188
#define kCPY__ 189
#define kCRT__ 190
#define kDC__ 191
#define kDL__ 192
#define kslt__ 193
#define kEND__ 194
#define kEOL__ 195
#define kEXT__ 196
#define kFND__ 197
#define kHLP__ 198
#define kHOM__ 199
#define kIC__ 200
#define kLFT__ 201
#define kMSG__ 202
#define kMOV__ 203
#define kNXT__ 204
#define kOPT__ 205
#define kPRV__ 206
#define kPRT__ 207
#define kRDO__ 208
#define kRPL__ 209
#define kRIT__ 210
#define kRES__ 211
#define kSAV__ 212
#define kSPD__ 213
#define kUND__ 214
#define rfi__ 215
#define kf11__ 216
#define kf12__ 217
#define kf13__ 218
#define kf14__ 219
#define kf15__ 220
#define kf16__ 221
#define kf17__ 222
#define kf18__ 223
#define kf19__ 224
#define kf20__ 225
#define kf21__ 226
#define kf22__ 227
#define kf23__ 228
#define kf24__ 229
#define kf25__ 230
#define kf26__ 231
#define kf27__ 232
#define kf28__ 233
#define kf29__ 234
#define kf30__ 235
#define kf31__ 236
#define kf32__ 237
#define kf33__ 238
#define kf34__ 239
#define kf35__ 240
#define kf36__ 241
#define kf37__ 242
#define kf38__ 243
#define kf39__ 244
#define kf40__ 245
#define kf41__ 246
#define kf42__ 247
#define kf43__ 248
#define kf44__ 249
#define kf45__ 250
#define kf46__ 251
#define kf47__ 252
#define kf48__ 253
#define kf49__ 254
#define kf50__ 255
#define kf51__ 256
#define kf52__ 257
#define kf53__ 258
#define kf54__ 259
#define kf55__ 260
#define kf56__ 261
#define kf57__ 262
#define kf58__ 263
#define kf59__ 264
#define kf60__ 265
#define kf61__ 266
#define kf62__ 267
#define kf63__ 268
#define el1__ 269
#define mgc__ 270
#define smgl__ 271
#define smgr__ 272

#ifdef CAP
char *Boolean_names[] = {
"bw", "am", "xb", "xs", "xn", "eo", "gn", "hc", "km", "hs", "in", "da", "db", 
"mi", "ms", "os", "es", "xt", "hz", "ul", "xo", "HC", "nx", "NR", "NP", "5i"
}; 

char *Number_names[] = { 
"co#", "it#", "li#", "lm#", "sg#", "pb#", "vt#", "ws#", "Nl#", "lh#", "lw#"
};

char *String_names[] = {
"bt=", "bl=", "cr=", "cs=", "ct=", "cl=", "ce=", "cd=", "ch=", "CC=", "cm=", 
"do=", "ho=", "vi=", "le=", "CM=", "ve=", "nd=", "ll=", "up=", "vs=", "dc=", 
"dl=", "ds=", "hd=", "as=", "mb=", "md=", "ti=", "dm=", "mh=", "im=", "mk=", 
"mp=", "mr=", "so=", "us=", "ec=", "ae=", "me=", "te=", "ed=", "ei=", "se=", 
"ue=", "vb=", "ff=", "fs=", "i1=", "i2=", "i3=", "if=", "ic=", "al=", "ip=", 
"kb=", "ka=", "kC=", "kt=", "kD=", "kL=", "kd=", "kM=", "kE=", "kS=", "k0=", 
"k1=", "k;=", "k2=", "k3=", "k4=", "k5=", "k6=", "k7=", "k8=", "k9=", "kh=", 
"kI=", "kA=", "kl=", "kH=", "kN=", "kP=", "kr=", "kF=", "kR=", "kT=", "ku=", 
"ke=", "ks=", "l0=", "l1=", "la=", "l2=", "l3=", "l4=", "l5=", "l6=", "l7=", 
"l8=", "l9=", "mo=", "mm=", "nw=", "pc=", "DC=", "DL=", "DO=", "IC=", "SF=", 
"AL=", "LE=", "RI=", "SR=", "UP=", "pk=", "pl=", "px=", "ps=", "pf=", "po=", 
"rp=", "r1=", "r2=", "r3=", "rf=", "rc=", "cv=", "sc=", "sf=", "sr=", "sa=", 
"st=", "wi=", "ta=", "ts=", "uc=", "hu=", "iP=", "K1=", "K3=", "K2=", "K4=", 
"K5=", "pO=", "rP=", "ac=", "pn=", "kB=", "SX=", "RX=", "SA=", "RA=", "XN=", 
"XF=", "eA=", "LO=", "LF=", "@1=", "@2=", "@3=", "@4=", "@5=", "@6=", "@7=", 
"@8=", "@9=", "@0=", "%1=", "%2=", "%3=", "%4=", "%5=", "%6=", "%7=", "%8=", 
"%9=", "%0=", "&1=", "&2=", "&3=", "&4=", "&5=", "&6=", "&7=", "&8=", "&9=", 
"&0=", "*1=", "*2=", "*3=", "*4=", "*5=", "*6=", "*7=", "*8=", "*9=", "*0=", 
"#1=", "#2=", "#3=", "#4=", "%a=", "%b=", "%c=", "%d=", "%e=", "%f=", "%g=", 
"%h=", "%i=", "%j=", "!1=", "!2=", "!3=", "RF=", "F1=", "F2=", "F3=", "F4=", 
"F5=", "F6=", "F7=", "F8=", "F9=", "FA=", "FB=", "FC=", "FD=", "FE=", "FF=", 
"FG=", "FH=", "FI=", "FJ=", "FK=", "FL=", "FM=", "FN=", "FO=", "FP=", "FQ=", 
"FR=", "FS=", "FT=", "FU=", "FV=", "FW=", "FX=", "FY=", "FZ=", "Fa=", "Fb=", 
"Fc=", "Fd=", "Fe=", "Ff=", "Fg=", "Fh=", "Fi=", "Fj=", "Fk=", "Fl=", "Fm=", 
"Fn=", "Fo=", "Fp=", "Fq=", "Fr=", "cb=", "MC=", "ML=", "MR="
};
#endif

char *new_curse = "October 1987";

char in_buff[100];	/* buffer for ungetch			*/
int bufp;		/* next free position in in_buff	*/

char *TERMINAL_TYPE = NULL; /* terminal type to be gotten from environment	*/
int CFOUND = FALSE;
int Data_Line_len = 0;
int Max_Key_len;	/* max length of a sequence sent by a key	*/
char *Data_Line = NULL;
char *TERM_PATH = NULL;
char *TERM_data_ptr = NULL;
char *Term_File_name = NULL;	/* name of file containing terminal description	*/
FILE *TFP;		/* file pointer to file with terminal des.	*/
int Fildes;		/* file descriptor for terminfo file		*/
int STAND = FALSE;	/* is standout mode activated?			*/
int TERM_INFO = FALSE;	/* is terminfo being used (TRUE), or termcap (FALSE) */
int Time_Out;	/* set when time elapsed while trying to read function key */
int Curr_x;		/* current x position on screen			*/
int Curr_y;		/* current y position on the screen		*/
int LINES;
int COLS;
int Move_It;		/* flag to move cursor if magic cookie glitch	*/
int initialized = FALSE;	/* tells whether new_curse is initialized	*/
float speed;
float chars_per_millisecond;
int Repaint_screen;	/* if an operation to change screen impossible, repaint screen	*/
int Intr;		/* storeage for interrupt character		*/
int Parity;		/* 0 = no parity, 1 = odd parity, 2 = even parity */
int Noblock;		/* for BSD systems				*/
int Num_bits;	/* number of bits per character	*/
int Flip_Bytes;	/* some systems have byte order reversed	*/
int interrupt_flag = FALSE;	/* set true if SIGWINCH received	*/

#ifndef CAP
char *Strings;
#endif

struct KEYS {
	int length;	/* length of string sent by key			*/
	char *string;	/* string sent by key				*/
	int value;	/* CURSES value of key (9-bit)			*/
	};

struct KEY_STACK {
	struct KEYS *element;
	struct KEY_STACK *next;
	};

struct KEY_STACK *KEY_TOS = NULL;
struct KEY_STACK *KEY_POINT;

/*
 |
 |	Not all systems have good terminal information, so we will define 
 |	keyboard information here for the most widely used terminal type, 
 |	the VT100.
 |
 */

struct KEYS vt100[] = 
	{
		{ 3, "\033[A", 0403 },	/* key up 	*/
		{ 3, "\033[C", 0405 },	/* key right	*/
		{ 3, "\033[D", 0404 },	/* key left	*/

		{ 4, "\033[6~", 0522 },	/* key next page	*/
		{ 4, "\033[5~", 0523 },	/* key prev page	*/
		{ 3, "\033[[", 0550 },	/* key end	*/
		{ 3, "\033[@", 0406 },	/* key home	*/
		{ 4, "\033[2~", 0513 },	/* key insert char	*/

		{ 3, "\033[y", 0410 },	/* key F0	*/
		{ 3, "\033[P", 0411 },	/* key F1	*/
		{ 3, "\033[Q", 0412 },	/* key F2	*/
		{ 3, "\033[R", 0413 },	/* key F3	*/
		{ 3, "\033[S", 0414 },	/* key F4	*/
		{ 3, "\033[t", 0415 },	/* key F5	*/
		{ 3, "\033[u", 0416 },	/* key F6	*/
		{ 3, "\033[v", 0417 },	/* key F7	*/
		{ 3, "\033[l", 0420 },	/* key F8	*/
		{ 3, "\033[w", 0421 },	/* key F9	*/
		{ 3, "\033[x", 0422 },	/* key F10	*/

		{ 5, "\033[10~", 0410 },	/* key F0	*/
		{ 5, "\033[11~", 0411 },	/* key F1	*/
		{ 5, "\033[12~", 0412 },	/* key F2	*/
		{ 5, "\033[13~", 0413 },	/* key F3	*/
		{ 5, "\033[14~", 0414 },	/* key F4	*/
		{ 5, "\033[15~", 0415 },	/* key F5	*/
		{ 5, "\033[17~", 0416 },	/* key F6	*/
		{ 5, "\033[18~", 0417 },	/* key F7	*/
		{ 5, "\033[19~", 0420 },	/* key F8	*/
		{ 5, "\033[20~", 0421 },	/* key F9	*/
		{ 5, "\033[21~", 0422 },	/* key F10	*/
		{ 5, "\033[23~", 0423 },	/* key F11	*/
		{ 5, "\033[24~", 0424 },	/* key F12	*/
		{ 3, "\033[q", 0534 },	/* ka1 upper-left of keypad	*/
		{ 3, "\033[s", 0535 },	/* ka3 upper-right of keypad	*/
		{ 3, "\033[r", 0536 },	/* kb2 center of keypad	*/
 		{ 3, "\033[p", 0537 },	/* kc1 lower-left of keypad	*/
		{ 3, "\033[n", 0540 },	/* kc3 lower-right of keypad	*/

		/*
		 |	The following are the same keys as above, but with 
		 |	a different character following the escape char.
		 */

		{ 3, "\033OA", 0403 },	/* key up 	*/
		{ 3, "\033OC", 0405 },	/* key right	*/
		{ 3, "\033OD", 0404 },	/* key left	*/
		{ 3, "\033OB", 0402 },	/* key down	*/
		{ 4, "\033O6~", 0522 },	/* key next page	*/
		{ 4, "\033O5~", 0523 },	/* key prev page	*/
		{ 3, "\033O[", 0550 },	/* key end	*/
		{ 3, "\033O@", 0406 },	/* key home	*/
		{ 4, "\033O2~", 0513 },	/* key insert char	*/

		{ 3, "\033Oy", 0410 },	/* key F0	*/
		{ 3, "\033OP", 0411 },	/* key F1	*/
		{ 3, "\033OQ", 0412 },	/* key F2	*/
		{ 3, "\033OR", 0413 },	/* key F3	*/
		{ 3, "\033OS", 0414 },	/* key F4	*/
		{ 3, "\033Ot", 0415 },	/* key F5	*/
		{ 3, "\033Ou", 0416 },	/* key F6	*/
		{ 3, "\033Ov", 0417 },	/* key F7	*/
		{ 3, "\033Ol", 0420 },	/* key F8	*/
		{ 3, "\033Ow", 0421 },	/* key F9	*/
		{ 3, "\033Ox", 0422 },	/* key F10	*/

		{ 5, "\033O10~", 0410 },	/* key F0	*/
		{ 5, "\033O11~", 0411 },	/* key F1	*/
		{ 5, "\033O12~", 0412 },	/* key F2	*/
		{ 5, "\033O13~", 0413 },	/* key F3	*/
		{ 5, "\033O14~", 0414 },	/* key F4	*/
		{ 5, "\033O15~", 0415 },	/* key F5	*/
		{ 5, "\033O17~", 0416 },	/* key F6	*/
		{ 5, "\033O18~", 0417 },	/* key F7	*/
		{ 5, "\033O19~", 0420 },	/* key F8	*/
		{ 5, "\033O20~", 0421 },	/* key F9	*/
		{ 5, "\033O21~", 0422 },	/* key F10	*/
		{ 5, "\033O23~", 0423 },	/* key F11	*/
		{ 5, "\033O24~", 0424 },	/* key F12	*/
		{ 3, "\033Oq", 0534 },	/* ka1 upper-left of keypad	*/
		{ 3, "\033Os", 0535 },	/* ka3 upper-right of keypad	*/
		{ 3, "\033Or", 0536 },	/* kb2 center of keypad	*/
 		{ 3, "\033Op", 0537 },	/* kc1 lower-left of keypad	*/
		{ 3, "\033On", 0540 },	/* kc3 lower-right of keypad	*/

		{ 0, "", 0 }	/* end	*/
	};

struct Parameters {
	int value;
	struct Parameters *next;
	};

int Key_vals[] = { 
	0407, 0526, 0515, 0525, 0512, 0510, 0402, 0514, 0517, 0516, 0410, 0411, 
	0422, 0412, 0413, 0414, 0415, 0416, 0417, 0420, 0421, 0406, 0513, 0511, 
	0404, 0533, 0522, 0523, 0405, 0520, 0521, 0524, 0403, 
	0534, 0535, 0536, 0537, 0540, 0541, 0542, 0543, 0544, 0545, 0546, 0547, 
	0550, 0527, 0551, 0552, 0553, 0554, 0555, 0556, 0557, 0560, 0561, 0562, 
	0532, 0563, 0564, 0565, 0566, 0567, 0570, 0571, 0627, 0630, 0572, 0573, 
	0574, 0575, 0576, 0577, 0600, 0601, 0602, 0603, 0604, 0605, 0606, 0607, 
	0610, 0611, 0612, 0613, 0614, 0615, 0616, 0617, 0620, 0621, 0622, 0623, 
	0624, 0625, 0626, 0423, 0424, 0425, 0426, 0427, 0430, 0431, 
	0432, 0433, 0434, 0435, 0436, 0437, 0440, 0441, 0442, 0443, 0444, 0445, 
	0446, 0447, 0450, 0451, 0452, 0453, 0454, 0455, 0456, 0457, 0460, 0461, 
	0462, 0463, 0464, 0465, 0466, 0467, 0470, 0471, 0472, 0473, 0474, 0475, 
	0476, 0477, 0500, 0501, 0502, 0503, 0504, 0505, 0506, 0507
};

int attributes_set[9];

static int nc_attributes = 0;	/* global attributes for new_curse to observe */

#ifdef SYS5
struct termio Terminal;
struct termio Saved_tty;
#else
struct sgttyb Terminal;
struct sgttyb Saved_tty;
#endif

char *tc_;

int Booleans[128];	
int Numbers[128];
char *String_table[1024];

int *virtual_lines;

static char nc_scrolling_ability = FALSE;

#ifdef CAP

int tc_Get_int(int);
void CAP_PARSE(void);
void Find_term(void);

#endif /* CAP */


#ifdef SIGWINCH

/*
 |	Copy the contents of one window to another.
 */

void 
copy_window(origin, destination)
WINDOW *origin, *destination;
{
	int row, column;
	struct _line *orig, *dest;

	orig = origin->first_line;
	dest = destination->first_line;

	for (row = 0; 
		row < (min(origin->Num_lines, destination->Num_lines)); 
			row++)
	{
		for (column = 0; 
		    column < (min(origin->Num_cols, destination->Num_cols)); 
			column++)
		{
			dest->row[column] = orig->row[column];
			dest->attributes[column] = orig->attributes[column];
		}
		dest->changed = orig->changed;
		dest->scroll = orig->scroll;
		dest->last_char = min(orig->last_char, destination->Num_cols);
		orig = orig->next_screen;
		dest = dest->next_screen;
	}
	destination->LX = min((destination->Num_cols - 1), origin->LX);
	destination->LY = min((destination->Num_lines - 1), origin->LY);
	destination->Attrib = origin->Attrib;
	destination->scroll_up = origin->scroll_up;
	destination->scroll_down = origin->scroll_down;
	destination->SCROLL_CLEAR = origin->SCROLL_CLEAR;
}

void 
reinitscr(foo)
int foo; 
{
	WINDOW *local_virt;
	WINDOW *local_std;
	WINDOW *local_cur;

	signal(SIGWINCH, reinitscr);
#ifdef TIOCGWINSZ
	if (ioctl(0, TIOCGWINSZ, &ws) >= 0)
	{
		if (ws.ws_row == LINES && ws.ws_col == COLS) 
			return;
		if (ws.ws_row > 0) 
			LINES = ws.ws_row;
		if (ws.ws_col > 0) 
			COLS = ws.ws_col;
	}
#endif /* TIOCGWINSZ */
	local_virt = newwin(LINES, COLS, 0, 0);
	local_std = newwin(LINES, COLS, 0, 0);
	local_cur = newwin(LINES, COLS, 0, 0);
	copy_window(virtual_scr, local_virt);
	copy_window(stdscr, local_std);
	copy_window(curscr, local_cur);
	delwin(virtual_scr);
	delwin(stdscr);
	delwin(curscr);
	virtual_scr = local_virt;
	stdscr = local_std;
	curscr = local_cur;
	free(virtual_lines);
	virtual_lines = (int *) malloc(LINES * (sizeof(int)));
	interrupt_flag = TRUE;
}
#endif /* SIGWINCH */

void 
initscr()		/* initialize terminal for operations	*/
{
	int value;
	char *lines_string;
	char *columns_string;
#ifdef CAP
	char *pointer;
#endif /* CAP */

#ifdef DIAG
printf("starting initscr \n");fflush(stdout);
#endif
	if (initialized)
		return;
#ifdef BSD_SELECT
	setbuf(stdin, NULL);
#endif /* BSD_SELECT */
	Flip_Bytes = FALSE;
	Parity = 0;
	Time_Out = FALSE;
	bufp = 0;
	Move_It = FALSE;
	Noblock = FALSE;
#ifdef SYS5
	value = ioctl(0, TCGETA, &Terminal);
	if (Terminal.c_cflag & PARENB)
	{
		if (Terminal.c_cflag & PARENB)
			Parity = 1;
		else
			Parity = 2;
	}
	if ((Terminal.c_cflag & CS8) == CS8)
	{
		Num_bits = 8;
	}
	else if ((Terminal.c_cflag & CS7) == CS7)
		Num_bits = 7;
	else if ((Terminal.c_cflag & CS6) == CS6)
		Num_bits = 6;
	else
		Num_bits = 5;
	value = Terminal.c_cflag & 037;
	switch (value) {
	case 01:	speed = 50.0;
		break;
	case 02:	speed = 75.0;
		break;
	case 03:	speed = 110.0;
		break;
	case 04:	speed = 134.5;
		break;
	case 05:	speed = 150.0;
		break;
	case 06:	speed = 200.0;
		break;
	case 07:	speed = 300.0;
		break;
	case 010:	speed = 600.0;
		break;
	case 011:	speed = 900.0;
		break;
	case 012:	speed = 1200.0;
		break;
	case 013:	speed = 1800.0;
		break;
	case 014:	speed = 2400.0;
		break;
	case 015:	speed = 3600.0;
		break;
	case 016:	speed = 4800.0;
		break;
	case 017:	speed = 7200.0;
		break;
	case 020:	speed = 9600.0;
		break;
	case 021:	speed = 19200.0;
		break;
	case 022:	speed = 38400.0;
		break;
	default:	speed = 0.0;
	}
#else
	value = ioctl(0, TIOCGETP, &Terminal);
	if (Terminal.sg_flags & EVENP)
		Parity = 2;
	else if (Terminal.sg_flags & ODDP)
		Parity = 1;
	value = Terminal.sg_ospeed;
	switch (value) {
	case 01:	speed = 50.0;
		break;
	case 02:	speed = 75.0;
		break;
	case 03:	speed = 110.0;
		break;
	case 04:	speed = 134.5;
		break;
	case 05:	speed = 150.0;
		break;
	case 06:	speed = 200.0;
		break;
	case 07:	speed = 300.0;
		break;
	case 010:	speed = 600.0;
		break;
	case 011:	speed = 1200.0;
		break;
	case 012:	speed = 1800.0;
		break;
	case 013:	speed = 2400.0;
		break;
	case 014:	speed = 4800.0;
		break;
	case 015:	speed = 9600.0;
		break;
	default:	speed = 0.0;
	}
#endif
	chars_per_millisecond = (0.001 * speed) / 8.0;
	TERMINAL_TYPE = getenv("TERM");
	if (TERMINAL_TYPE == NULL)
	{
		printf("unknown terminal type\n");
		exit(0);
	}
#ifndef CAP
	Fildes = -1;
	TERM_PATH = getenv("TERMINFO");
	if (TERM_PATH != NULL)
	{
		Data_Line_len = 23 + strlen(TERM_PATH) + strlen(TERMINAL_TYPE);
		Term_File_name = malloc(Data_Line_len);
		sprintf(Term_File_name, "%s/%c/%s", TERM_PATH, *TERMINAL_TYPE, TERMINAL_TYPE);
		Fildes = open(Term_File_name, O_RDONLY);
	}
	if (Fildes == -1)
	{
		TERM_PATH = "/usr/lib/terminfo";
		Data_Line_len = 23 + strlen(TERM_PATH) + strlen(TERMINAL_TYPE);
		Term_File_name = malloc(Data_Line_len);
		sprintf(Term_File_name, "%s/%c/%s", TERM_PATH, *TERMINAL_TYPE, TERMINAL_TYPE);
		Fildes = open(Term_File_name, O_RDONLY);
	}
	if (Fildes == -1)
	{
		TERM_PATH = "/usr/share/lib/terminfo";
		Data_Line_len = 23 + strlen(TERM_PATH) + strlen(TERMINAL_TYPE);
		Term_File_name = malloc(Data_Line_len);
		sprintf(Term_File_name, "%s/%c/%s", TERM_PATH, *TERMINAL_TYPE, TERMINAL_TYPE);
		Fildes = open(Term_File_name, O_RDONLY);
	}
	if (Fildes == -1)
	{
		TERM_PATH = "/usr/share/terminfo";
		Data_Line_len = 23 + strlen(TERM_PATH) + strlen(TERMINAL_TYPE);
		Term_File_name = malloc(Data_Line_len);
		sprintf(Term_File_name, "%s/%c/%s", TERM_PATH, *TERMINAL_TYPE, TERMINAL_TYPE);
		Fildes = open(Term_File_name, O_RDONLY);
	}
	if (Fildes == -1)
	{
		free(Term_File_name);
		Term_File_name = NULL;
	}
	else
		TERM_INFO = INFO_PARSE();
#else
	/*
	 |	termcap information can be in the TERMCAP env variable, if so 
	 |	use that, otherwise check the /etc/termcap file
	 */
	if ((pointer = Term_File_name = getenv("TERMCAP")) != NULL)
	{
		if (*Term_File_name != '/')
			Term_File_name = "/etc/termcap";
	}
	else
	{
		Term_File_name = "/etc/termcap";
	}
	if ((TFP = fopen(Term_File_name, "r")) == NULL)
	{
		printf("unable to open /etc/termcap file \n");
		exit(0);
	}
 	for (value = 0; value < 1024; value++)	
		String_table[value] = NULL;
	for (value = 0; value < 128; value++)	
		Booleans[value] = 0;
	for (value = 0; value < 128; value++)	
		Numbers[value] = 0;
	Data_Line = malloc(512);
	if (pointer && *pointer != '/')
	{
		TERM_data_ptr = pointer;
		CAP_PARSE();
	}
	else
	{
		Find_term();
		CAP_PARSE();
	}
#endif
	if (String_table[pc__] == NULL) 
		String_table[pc__] = "\0";
	if ((String_table[cm__] == NULL) || (Booleans[hc__]))
	{
		fprintf(stderr, "sorry, unable to use this terminal type for screen editing\n");
		exit(0);
	}
	Key_Get();
	keys_vt100();
	LINES = Numbers[li__];
	COLS = Numbers[co__];
	if ((lines_string = getenv("LINES")) != NULL)
	{
		value = atoi(lines_string);
		if (value > 0)
			LINES = value;
	}
	if ((columns_string = getenv("COLUMNS")) != NULL)
	{
		value = atoi(columns_string);
		if (value > 0)
			COLS = value;
	}
#ifdef TIOCGWINSZ
	/*
	 |	get the window size
	 */
	if (ioctl(0, TIOCGWINSZ, &ws) >= 0)
	{
		if (ws.ws_row > 0)
			LINES = ws.ws_row;
		if (ws.ws_col > 0)
			COLS = ws.ws_col;
	}
#endif
	virtual_scr = newwin(LINES, COLS, 0, 0);
	stdscr = newwin(LINES, COLS, 0, 0);
	curscr = newwin(LINES, COLS, 0, 0);
	wmove(stdscr, 0, 0);
	werase(stdscr);
	Repaint_screen = TRUE;
	initialized = TRUE;
	virtual_lines = (int *) malloc(LINES * (sizeof(int)));

#ifdef SIGWINCH
	/*
	 |	reset size of windows and LINES and COLS if term window 
	 |	changes size
	 */
	signal(SIGWINCH, reinitscr);
#endif /* SIGWINCH */

	/*
	 |	check if scrolling is available
	 */

	nc_scrolling_ability = ((String_table[al__] != NULL) && 
				(String_table[dl__])) || ((String_table[cs__]) 
				&& (String_table[sr__]));

}

#ifndef CAP
int 
Get_int()		/* get a two-byte integer from the terminfo file */
{
	int High_byte;
	int Low_byte;
	int temp;

	Low_byte = *((unsigned char *) TERM_data_ptr++);
	High_byte = *((unsigned char *) TERM_data_ptr++);
	if (Flip_Bytes)
	{
		temp = Low_byte;
		Low_byte = High_byte;
		High_byte = temp;
	}
	if ((High_byte == 255) && (Low_byte == 255))
		return (-1);
	else
		return(Low_byte + (High_byte * 256));
}

int 
INFO_PARSE()		/* parse off the data in the terminfo data file	*/
{
	int offset;
	int magic_number = 0;
	int counter = 0;
	int Num_names = 0;
	int Num_bools = 0;
	int Num_ints = 0;
	int Num_strings = 0;
	int string_table_len = 0;
	char *temp_ptr;

	TERM_data_ptr = Data_Line = malloc((10240 * (sizeof(char))));
	Data_Line_len = read(Fildes, Data_Line, 10240);
	if ((Data_Line_len >= 10240) || (Data_Line_len < 0))
		return(0);
	/*
	 |	get magic number
	 */
	magic_number = Get_int();
	/*
	 |	if magic number not right, reverse byte order and check again
	 */
	if (magic_number != 282)
	{
		Flip_Bytes = TRUE;
		TERM_data_ptr--;
		TERM_data_ptr--;
		magic_number = Get_int();
		if (magic_number != 282)
			return(0);
	}
	/*
	 |	get the number of each type in the terminfo data file
	 */
	Num_names = Get_int();
	Num_bools = Get_int();
	Num_ints = Get_int();
	Num_strings = Get_int();
	string_table_len = Get_int();
	Strings = malloc(string_table_len);
	while (Num_names > 0)
	{
		TERM_data_ptr++;
		Num_names--;
	}
	counter = 0;
	while (Num_bools)
	{
		Num_bools--;
		Booleans[counter++] = *TERM_data_ptr++;
	}
	if (((unsigned int) TERM_data_ptr) & 1)	/* force alignment	*/
		TERM_data_ptr++;
	counter = 0;
	while (Num_ints)
	{
		Num_ints--;
		Numbers[counter] = Get_int();
		counter++;
	}
	temp_ptr = TERM_data_ptr + Num_strings + Num_strings;
	memcpy(Strings, temp_ptr, string_table_len);
	counter = bt__;
	while (Num_strings)
	{
		Num_strings--;
		if ((offset=Get_int()) != -1)
		{
			if (String_table[counter] == NULL)
				String_table[counter] = Strings + offset;
		}
		else
			String_table[counter] = NULL;
		counter++;
	}
	close(Fildes);
	free(Data_Line);
	return(TRUE);
}
#endif		/* ifndef CAP	*/

int 
AtoI()		/* convert ascii text to integers	*/
{
	int Temp;

	Temp = 0;
	while ((*TERM_data_ptr >= '0') && (*TERM_data_ptr <= '9'))
	{
		Temp = (Temp * 10) + (*TERM_data_ptr - '0');
		TERM_data_ptr++;
	}
	return(Temp);
}

void 
Key_Get()		/* create linked list with all key sequences obtained from terminal database	*/
{
	int Counter;
	int Klen;
	int key_def;
	struct KEY_STACK *Spoint;

	Max_Key_len = 0;
	Counter = 0;
	key_def = kb__;
	while (key_def <= kf63__)
	{
		if (key_def == ke__)
			key_def = K1__;
		else if (key_def == (K5__ + 1))
			key_def = kcbt__;
		else if (key_def == (kcbt__ + 1))
			key_def = kbeg__;
		else if (key_def == (kUND__ + 1))
			key_def = kf11__;
		if (String_table[key_def] != NULL)
		{
			if (KEY_TOS == NULL)
				Spoint = KEY_TOS = (struct KEY_STACK *) malloc(sizeof(struct KEY_STACK));
			else
			{
				Spoint = KEY_TOS;
				while (Spoint->next != NULL)
					Spoint = Spoint->next;
				Spoint->next = (struct KEY_STACK *) malloc(sizeof(struct KEY_STACK));
				Spoint = Spoint->next;
			}
			Spoint->next = NULL;
			Spoint->element = (struct KEYS *) malloc(sizeof(struct KEYS));
			Spoint->element->string = String_table[key_def];
			Spoint->element->length = strlen(String_table[key_def]);
			Spoint->element->value = Key_vals[Counter];
			Klen = strlen(Spoint->element->string);
			if (Klen > Max_Key_len)
				Max_Key_len = Klen;
			/*
			 |  Some terminal types accept keystrokes of the form
			 |  \E[A and \EOA, substituting '[' for 'O'.  Make a 
			 |  duplicate of such key strings (since the 
			 |  database will only have one version) so new_curse 
			 |  can understand both.
			 */
			if ((Spoint->element->length > 1) && 
			    ((String_table[key_def][1] == '[') || 
			     (String_table[key_def][1] == 'O')))
			{
				Spoint->next = (struct KEY_STACK *) malloc(sizeof(struct KEY_STACK));
				Spoint = Spoint->next;
				Spoint->next = NULL;
				Spoint->element = (struct KEYS *) malloc(sizeof(struct KEYS));
				Spoint->element->length = strlen(String_table[key_def]);
				Spoint->element->string = malloc(Spoint->element->length + 1);
				strcpy(Spoint->element->string, String_table[key_def]);
				Spoint->element->value = Key_vals[Counter];
				Klen = strlen(Spoint->element->string);
				if (Klen > Max_Key_len)
					Max_Key_len = Klen;
			
				if (String_table[key_def][1] == '[')
					Spoint->element->string[1] = 'O';
				else
					Spoint->element->string[1] = '[';
			}
		}
		key_def++;
		Counter++;
	}
}

/*
 |	insert information about keys for a vt100 terminal
 */

void
keys_vt100()
{
	int counter;
	int Klen;
	struct KEY_STACK *Spoint;

	Spoint = KEY_TOS;
	while (Spoint->next != NULL)
		Spoint = Spoint->next;
	for (counter = 0; vt100[counter].length != 0; counter++)
	{
		Spoint->next = (struct KEY_STACK *) malloc(sizeof(struct KEY_STACK));
		Spoint = Spoint->next;
		Spoint->next = NULL;
		Spoint->element = &vt100[counter];
		Klen = strlen(Spoint->element->string);
		if (Klen > Max_Key_len)
			Max_Key_len = Klen;
	}
}

#ifdef CAP
char *
String_Get(param)		/* read the string */
char *param;
{
	char *String;
	char *Temp;
	int Counter;

	if (param == NULL)
	{
		while (*TERM_data_ptr != '=')
			TERM_data_ptr++;
		Temp = ++TERM_data_ptr;
		Counter = 1;
		while ((*Temp != ':') && (*Temp != (char)NULL))
		{
			Counter++;
			Temp++;
		}
		if (Counter == 1)	/* no data */
			return(NULL);
		String = Temp = malloc(Counter);
		while ((*TERM_data_ptr != ':') && (*TERM_data_ptr != (char)NULL))
		{
			if (*TERM_data_ptr == '\\')
			{
				TERM_data_ptr++;
				if (*TERM_data_ptr == 'n')
					*Temp = '\n';
				else if (*TERM_data_ptr == 't')
					*Temp = '\t';
				else if (*TERM_data_ptr == 'b')
					*Temp = '\b';
				else if (*TERM_data_ptr == 'r')
					*Temp = '\r';
				else if (*TERM_data_ptr == 'f')
					*Temp = '\f';
				else if ((*TERM_data_ptr == 'e') || (*TERM_data_ptr == 'E'))
					*Temp = '\033';		/* escape */
				else if (*TERM_data_ptr == '\\')
					*Temp = '\\';
				else if (*TERM_data_ptr == '\'')
					*Temp = '\'';
				else if ((*TERM_data_ptr >= '0') && (*TERM_data_ptr <= '9'))
				{
					Counter = 0;
					while ((*TERM_data_ptr >= '0') && (*TERM_data_ptr <= '9'))
					{
						Counter = (8 * Counter) + (*TERM_data_ptr - '0');
						TERM_data_ptr++;  /* ? */
					}
					*Temp = Counter;
					TERM_data_ptr--;
				}
				TERM_data_ptr++;
				Temp++;
			}
			else if (*TERM_data_ptr == '^')
			{
				TERM_data_ptr++;
				if ((*TERM_data_ptr >= '@') && (*TERM_data_ptr <= '_'))
					*Temp = *TERM_data_ptr - '@';
				else if (*TERM_data_ptr == '?')
					*Temp = 127;
				TERM_data_ptr++;
				Temp++;
			}
			else
				*Temp++ = *TERM_data_ptr++;
		}
		*Temp = (char)NULL;
		param = String;
	}
	else
	{
		while ((*TERM_data_ptr != (char)NULL) && (*TERM_data_ptr != ':'))
			TERM_data_ptr++;
	}
	return(param);
}

int 
tc_Get_int(param)		/* read the integer			*/
int param;
{
	int Itemp;

	if (param == 0)
	{
		while ((*TERM_data_ptr != (char)NULL) && (*TERM_data_ptr != '#'))
			TERM_data_ptr++;
		TERM_data_ptr++;
		Itemp = AtoI();
		param = Itemp;
	}
	else
	{
		while (*TERM_data_ptr != ':')
			TERM_data_ptr++;
	}
	return(param);
}

void 
Find_term()		/* find terminal description in termcap file	*/
{
	char *Name;
	char *Ftemp;

	Ftemp = Name = malloc(strlen(TERMINAL_TYPE + 1) + 1);
	strcpy(Name, TERMINAL_TYPE);
	while (*Ftemp != (char)NULL)
		Ftemp++;
	*Ftemp++ = '|';
	*Ftemp = (char)NULL;
	CFOUND = FALSE;
	Data_Line_len = strlen(TERMINAL_TYPE) + 1;
	while ((!CFOUND) && ((TERM_data_ptr=fgets(Data_Line, 512, TFP)) != NULL))
	{
		if ((*TERM_data_ptr != ' ') && (*TERM_data_ptr != '\t') && (*TERM_data_ptr != '#'))
		{
			while ((!CFOUND) && (*TERM_data_ptr != (char)NULL))
			{
				CFOUND = !strncmp(TERM_data_ptr, Name, Data_Line_len);
				while ((*TERM_data_ptr != (char)NULL) && (*TERM_data_ptr != '|') && (*TERM_data_ptr != '#') && (*TERM_data_ptr != ':'))
					TERM_data_ptr++;
				if (*TERM_data_ptr == '|')
					TERM_data_ptr++;
				else if (!CFOUND)
					*TERM_data_ptr = (char)NULL;
			}
		}
	}
	if (!CFOUND)
	{
		printf("terminal type %s not found\n", TERMINAL_TYPE);
		exit(0);
	}
}

void 
CAP_PARSE()		/* parse off the data in the termcap data file	*/
{
	int offset;
	int found;

	do
	{
		while (*TERM_data_ptr != (char)NULL)
		{
			for (found = FALSE, offset = 0; (!found) && (offset < 26); offset++)
			{
				if (!strncmp(TERM_data_ptr, Boolean_names[offset], 2))
				{
					found = TRUE;
					Booleans[offset] = TRUE;
				}
			}
			if (!found)
			{
				for (found = FALSE, offset = 0; (!found) && (offset < lw__); offset++)
				{
					if (!strncmp(TERM_data_ptr, Number_names[offset], 3))
					{
						found = TRUE;
						Numbers[offset] = tc_Get_int(Numbers[offset]);
					}
				}
			}
			if (!found)
			{
				for (found = FALSE, offset = 0; (!found) && (offset < smgr__); offset++)
				{
					if (!strncmp(TERM_data_ptr, String_names[offset], 3))
					{
						found = TRUE;
						String_table[offset] = String_Get(String_table[offset]);
					}
				}
			}

			if (!strncmp(TERM_data_ptr, "tc=", 3))
				tc_ = String_Get(NULL);
			while ((*TERM_data_ptr != ':') && (*TERM_data_ptr != (char)NULL))
				TERM_data_ptr++;
			if (*TERM_data_ptr == ':')
				TERM_data_ptr++;
		}
	} while (((TERM_data_ptr = fgets(Data_Line, 512, TFP)) != NULL) && ((*TERM_data_ptr == ' ') || (*TERM_data_ptr == '\t')));
	if (tc_ != NULL)
	{
		TERMINAL_TYPE = tc_;
		rewind(TFP);
		Find_term();
		free(tc_);
		tc_ = NULL;
		CAP_PARSE();
	}
	else
		fclose(TFP);
}
#endif		/* ifdef CAP	*/

struct _line *
Screenalloc(columns)
int columns;
{
	int i;
	struct _line *tmp;

	tmp = (struct _line *) malloc(sizeof (struct _line));
	tmp->row = malloc(columns + 1);
	tmp->attributes = malloc(columns + 1);
	tmp->prev_screen = NULL;
	tmp->next_screen = NULL;
	for (i = 0; i < columns; i++)
	{
		tmp->row[i] = ' ';
		tmp->attributes[i] = (char) NULL;
	}
	tmp->scroll = tmp->changed = FALSE;
	tmp->row[0] = (char) NULL;
	tmp->attributes[0] = (char) NULL;
	tmp->row[columns] = (char) NULL;
	tmp->attributes[columns] = (char) NULL;
	tmp->last_char = 0;
	return(tmp);
}

WINDOW *newwin(lines, cols, start_l, start_c)
int lines, cols;	/* number of lines and columns to be in window	*/
int start_l, start_c;	/* starting line and column to be inwindow	*/
{
	WINDOW *Ntemp;
	struct _line *temp_screen;
	int i;

	Ntemp = (WINDOW *) malloc(sizeof(WINDOW));
	Ntemp->SR = start_l;
	Ntemp->SC = start_c;
	Ntemp->Num_lines = lines;
	Ntemp->Num_cols = cols;
	Ntemp->LX = 0;
	Ntemp->LY = 0;
	Ntemp->scroll_down = Ntemp->scroll_up = 0;
	Ntemp->SCROLL_CLEAR = FALSE;
	Ntemp->Attrib = FALSE;
	Ntemp->first_line = temp_screen = Screenalloc(cols);
	Ntemp->first_line->number = 0;
	for (i = 1; i < lines; i++)
	{
		temp_screen->next_screen = Screenalloc(cols);
		temp_screen->next_screen->number = i;
		temp_screen->next_screen->prev_screen = temp_screen;
		temp_screen = temp_screen->next_screen;
	}
	Ntemp->first_line->prev_screen = NULL;
	temp_screen->next_screen = NULL;
	return(Ntemp);
}

#ifdef CAP
void 
Cap_Out(string, p_list, place)	/* interpret the output string if necessary */
char *string;
int p_list[];			/* stack of values	*/
int place;			/* place keeper of top of stack	*/
{
	char *Otemp;		/* temporary string pointer to parse output */
	int delay;
	int p1, p2, temp;
	float chars;

	if (string == NULL)
		return;

	if (p_list != NULL)
	{
		p1 = p_list[--place];
		p2 = p_list[--place];
	}
	delay = 0;
	Otemp = string;
	if ((*Otemp >= '0') && (*Otemp <= '9'))
	{
		delay = atoi(Otemp);
		while ((*Otemp >= '0') && (*Otemp <= '9'))
			Otemp++;
		if (*Otemp == '*')
			Otemp++;
	}
	while (*Otemp != (char)NULL)
	{
		if (*Otemp == '%')
		{
			Otemp++;
			if ((*Otemp == 'd') || (*Otemp == '2') || (*Otemp == '3') || (*Otemp == '.') || (*Otemp == '+')) 
			{
				if (*Otemp == 'd')
				 	printf("%d", p1);
				else if (*Otemp == '2')
					printf("%02d", p1);
				else if (*Otemp == '3')
					printf("%03d", p1);
				else if (*Otemp == '+')
				{
					Otemp++;
					p1 += *Otemp;
					putchar(p1);
				}
				else if (*Otemp == '.')
					putchar(p1);
				p1 = p2;
				p2 = 0;
			}
			else if (*Otemp == '>')
			{
				Otemp++;
				if (p1 > *Otemp)
				{
					Otemp++;
					p1 += *Otemp;
				}
				else
					Otemp++;
			}
			else if (*Otemp == 'r')
			{
				temp = p1;
				p1 = p2;
				p2 = temp;
			}
			else if (*Otemp == 'i')
			{
				p1++;
				p2++;
			}
			else if (*Otemp == '%')
				putchar(*Otemp);
			else if (*Otemp == 'n')
			{
				p1 ^= 0140;
				p2 ^= 0140;
			}
			else if (*Otemp == 'B')
			{
				p1 = (16 * (p1/10)) + (p1 % 10);
				p2 = (16 * (p2/10)) + (p2 % 10);
			}
			else if (*Otemp == 'D')
			{
				p1 = (p1 - 2 * (p1 % 16));
				p2 = (p2 - 2 * (p2 % 16));
			}
		}
		else
			putchar (*Otemp);
		Otemp++;
	}
	if (delay != 0)
	{
		chars = delay * chars_per_millisecond;
		delay = chars;
		if ((chars - delay) > 0.0)
			delay++;
		for (; delay > 0; delay--)
			putchar(*String_table[pc__]);
	}
	fflush(stdout);
}

#else

	char *Otemp;		/* temporary string pointer to parse output */
	float chars;
	int p[10];
	int variable[27];

int 
Operation(Temp_Stack, place)	/* handle conditional operations	*/
int Temp_Stack[];
int place;
{
	int temp;

	if (*Otemp == 'd')
	{
		Otemp++;
		temp = Temp_Stack[--place];
	 	printf("%d", temp);
	}
	else if (!strncmp(Otemp, "2d", 2))
	{
		temp = Temp_Stack[--place];
		printf("%2d", temp);
		Otemp++;
		Otemp++;
	}
	else if (!strncmp(Otemp, "3d", 2))
	{
		temp = Temp_Stack[--place];
		printf("%0d", temp);
		Otemp++;
		Otemp++;
	}
	else if (!strncmp(Otemp, "02d", 3))
	{
		temp = Temp_Stack[--place];
		printf("%02d", temp);
		Otemp++;
		Otemp++;
		Otemp++;
	}
	else if (!strncmp(Otemp, "03d", 3))
	{
		temp = Temp_Stack[--place];
		printf("%03d", temp);
		Otemp++;
		Otemp++;
		Otemp++;
	}
	else if (*Otemp == '+')
	{
		Otemp++;
		temp = Temp_Stack[--place];
		temp += Temp_Stack[--place];
		Temp_Stack[place++] = temp;
	}
	else if (*Otemp == '-')
	{
		Otemp++;
		temp = Temp_Stack[--place];
		temp -= Temp_Stack[--place];
		Temp_Stack[place++] = temp;
	}
	else if (*Otemp == '*')
	{
		Otemp++;
		temp = Temp_Stack[--place];
		temp *= Temp_Stack[--place];
		Temp_Stack[place++] = temp;
	}
	else if (*Otemp == '/')
	{
		Otemp++;
		temp = Temp_Stack[--place];
		temp /= Temp_Stack[--place];
		Temp_Stack[place++] = temp;
	}
	else if (*Otemp == 'm')
	{
		Otemp++;
		temp = Temp_Stack[--place];
		temp %= Temp_Stack[--place];
		Temp_Stack[place++] = temp;
	}
	else if (*Otemp == '&')
	{
		Otemp++;
		temp = Temp_Stack[--place];
		temp &= Temp_Stack[--place];
		Temp_Stack[place++] = temp;
	}
	else if (*Otemp == '|')
	{
		Otemp++;
		temp = Temp_Stack[--place];
		temp |= Temp_Stack[--place];
		Temp_Stack[place++] = temp;
	}
	else if (*Otemp == '^')
	{
		Otemp++;
		temp = Temp_Stack[--place];
		temp ^= Temp_Stack[--place];
		Temp_Stack[place++] = temp;
	}
	else if (*Otemp == '=')
	{
		Otemp++;
		temp = Temp_Stack[--place];
		temp = (temp == Temp_Stack[--place]);
		Temp_Stack[place++] = temp;
	}
	else if (*Otemp == '>')
	{
		Otemp++;
		temp = Temp_Stack[--place];
		temp = temp > Temp_Stack[--place];
		Temp_Stack[place++] = temp;
	}
	else if (*Otemp == '<')
	{
		Otemp++;
		temp = Temp_Stack[--place];
		temp = temp < Temp_Stack[--place];
		Temp_Stack[place++] = temp;
	}
	else if (*Otemp == 'c')
	{
		Otemp++;
		putchar(Temp_Stack[--place]);
	}
	else if (*Otemp == 'i')
	{
		Otemp++;
		p[1]++;
		p[2]++;
	}
	else if (*Otemp == '%')
	{
		putchar(*Otemp);
		Otemp++;
	}
	else if (*Otemp == '!')
	{
		temp = ! Temp_Stack[--place];
		Temp_Stack[place++] = temp;
		Otemp++;
	}
	else if (*Otemp == '~')
	{
		temp = ~Temp_Stack[--place];
		Temp_Stack[place++] = temp;
		Otemp++;
	}
	else if (*Otemp == 'p')
	{
		Otemp++;
		Temp_Stack[place++] = p[*Otemp - '0'];
		Otemp++;
	}
	else if (*Otemp == 'P')
	{
		Otemp++;
		Temp_Stack[place++] = variable[*Otemp - 'a'];
		Otemp++;
	}
	else if (*Otemp == 'g')
	{
		Otemp++;
		variable[*Otemp - 'a'] = Temp_Stack[--place];
		Otemp++;
	}
	else if (*Otemp == '\'')
	{
		Otemp++;
		Temp_Stack[place++] = *Otemp;
		Otemp++;
		Otemp++;
	}
	else if (*Otemp == '{')
	{
		Otemp++;
		temp = atoi(Otemp);
		Temp_Stack[place++] = temp;
		while (*Otemp != '}')
			Otemp++;
		Otemp++;
	}
	return(place);
}

void 
Info_Out(string, p_list, place)	/* interpret the output string if necessary */
char *string;
int p_list[];
int place;
{
	char *tchar;
	int delay;
	int temp;
	int Cond_FLAG;
	int EVAL;
	int Cond_Stack[128];
	int Cond_place;
	int Stack[128];
	int Top_of_stack;

	if (string == NULL)
		return;

	Cond_FLAG = FALSE;
	Cond_place = 0;
	Top_of_stack = 0;
	p[0] = 0;
	p[1] = 0;
	p[2] = 0;
	p[3] = 0;
	p[4] = 0;
	p[5] = 0;
	p[6] = 0;
	p[7] = 0;
	p[8] = 0;
	p[9] = 0;
	if (p_list != NULL)
	{
		for (temp = 1; (place != 0); temp++)
		{
			p[temp] = p_list[--place];
		}
	}
	delay = 0;
	Otemp = string;
	while (*Otemp != (char) NULL)
	{
		if (*Otemp == '%')
		{
			Otemp++;
			if ((*Otemp == '?') || (*Otemp == 't') || (*Otemp == 'e') || (*Otemp == ';'))
			{
				if (*Otemp == '?')
				{
					Otemp++;
					Cond_FLAG = TRUE;
					EVAL = TRUE;
					while (EVAL)
					{
						/*
						 |  find the end of the 
						 |  conditional statement
						 */
						while ((strncmp(Otemp, "%t", 2)) && (*Otemp != (char) NULL))
						{
							/*
							 |  move past '%'
							 */
							Otemp++;
							Cond_place = Operation(Cond_Stack, Cond_place);
						}

						/*
						 |  if condition is true
						 */
						if ((Cond_place > 0) && (Cond_Stack[Cond_place-1]))
						{
							/*
							 |  end conditional 
							 |  parsing
							 */
							EVAL = FALSE;
							Otemp++;
							Otemp++;
						}
						else	/* condition is false */
						{
							/*
							 |  find 'else' or end 
							 |  of if statement
							 */
							while ((strncmp(Otemp, "%e", 2)) && (strncmp(Otemp, "%;", 2)) && (*Otemp != (char) NULL))
								Otemp++;
							/*
							 |  if an 'else' found
							 */
							if ((*Otemp != (char) NULL) && (!strncmp(Otemp, "%e", 2)))
							{
								Otemp++;
								Otemp++;
								tchar = Otemp;
								/*
								 |  check for 'then' part
								 */
								while ((*tchar != (char) NULL) && (strncmp(tchar, "%t", 2)) && (strncmp(tchar, "%;", 2)))
									tchar++;
								/*
								 |  if end of string
								 */
								if (*tchar == (char) NULL)
								{
									EVAL = FALSE;
									Cond_FLAG = FALSE;
									Otemp = tchar;
								}
								/*
								 |  if end of if found,
								 |  set up to parse 
								 |  info
								 */
								else if (!strncmp(tchar, "%;", 2))
									EVAL = FALSE;
								/*
								 |  otherwise, check 
								 |  conditional in 
								 |  'else'
								 */
							}
							/*
							 |  if end of if found,
							 |  get out of if 
							 |  statement
							 */
							else if ((*Otemp != (char) NULL) && (!strncmp(Otemp, "%;", 2)))
							{
								EVAL = FALSE;
								Otemp++;
								Otemp++;
							}
							else /* Otemp == NULL */
							{
								EVAL = FALSE;
								Cond_FLAG = FALSE;
							}
						}
					}
				}
				else
				{
					Otemp++;
					Cond_FLAG = FALSE;
					if (*Otemp != ';')
					{
						while ((*Otemp != (char) NULL) && (strncmp(Otemp, "%;", 2)))
							Otemp++;
						if (*Otemp != (char) NULL)
						{
							Otemp++;
							Otemp++;
						}
					}
					else
						Otemp++;
				}
			}
			else
			{
				Top_of_stack = Operation(Stack, Top_of_stack);
			}
		}
		else if (!strncmp(Otemp, "$<", 2))
		{
			Otemp++;
			Otemp++;
			delay = atoi(Otemp);
			while (*Otemp != '>')
				Otemp++;
			Otemp++;
			chars = delay * chars_per_millisecond;
			delay = chars;
			if ((chars - delay) > 0.0)
				delay++;
			if (String_table[pc__] == NULL)
				temp = 0;
			else
				temp = *String_table[pc__];
			for (; delay > 0; delay--)
				putc(temp, stdout);
		}
		else
		{
			putchar(*Otemp);
			Otemp++;
		}
	}
	fflush(stdout);
}
#endif

void 
wmove(window, row, column)	/* move cursor to indicated position in window */
WINDOW *window;
int row, column;
{
	if ((row < window->Num_lines) && (column < window->Num_cols))
	{
		window->LX = column;
		window->LY = row;
	}
}

void 
clear_line(line, column, cols)
struct _line *line;
int column;
int cols;
{
	int j;

	if (column > line->last_char)
		line->row[line->last_char] = ' ';
	line->last_char = column;
	line->row[column] = (char) NULL;
	line->attributes[column] = (char) NULL;
	line->changed = TRUE;
	for (j = column + 1; j < cols; j++)
	{
		line->row[j] = ' ';
		line->attributes[j] = (char) NULL;
	}
}

void 
werase(window)			/* clear the specified window		*/
WINDOW *window;
{
	int i;
	struct _line *tmp;

	window->SCROLL_CLEAR = CLEAR;
	window->scroll_up = window->scroll_down = 0;
	for (i = 0, tmp = window->first_line; i < window->Num_lines; i++, tmp = tmp->next_screen)
		clear_line(tmp, 0, window->Num_cols);
}

void 
wclrtoeol(window)	/* erase from current cursor position to end of line */
WINDOW *window;
{
	int column, row;
	struct _line *tmp;

	window->SCROLL_CLEAR = CHANGE;
	column = window->LX;
	row = window->LY;
	for (row = 0, tmp = window->first_line; row < window->LY; row++)
		tmp = tmp->next_screen;
	clear_line(tmp, column, window->Num_cols);
}

void 
wrefresh(window)		/* flush all previous output		*/
WINDOW *window;
{
	wnoutrefresh(window);
#ifdef DIAG
{
	struct _line *temp;
	int value;
	fprintf(stderr, "columns=%d, lines=%d, SC=%d, SR=%d\n",window->Num_cols, window->Num_lines, window->SC, window->SR);
	for (value = 0, temp = window->first_line; value < window->Num_lines; value++, temp = temp->next_screen)
	{
		if (temp->number == -1)
			fprintf(stderr, "line moved ");
		if (temp->scroll)
			fprintf(stderr, "scroll_x is set:  ");
		fprintf(stderr, "lc%d=%s|\n", temp->last_char, temp->row);
	}
	fprintf(stderr, "+-------------------- virtual screen ----------------------------------------+\n");
	fprintf(stderr, "columns=%d, lines=%d \n",virtual_scr->Num_cols, virtual_scr->Num_lines);
	for (value = 0, temp = virtual_scr->first_line; value < virtual_scr->Num_lines; value++, temp = temp->next_screen)
	{
		if (temp->number == -1)
			fprintf(stderr, "line moved ");
		if (temp->scroll)
			fprintf(stderr, "scroll_x is set:  ");
		fprintf(stderr, "lc%d=%s|\n", temp->last_char, temp->row);
	}
	fprintf(stderr, "columns=%d, lines=%d \n",curscr->Num_cols, curscr->Num_lines);
	for (value = 0, temp = curscr->first_line; value < curscr->Num_lines; value++, temp = temp->next_screen)
		fprintf(stderr, "line=%s|\n", temp->row);
}
#endif
	doupdate();
	virtual_scr->SCROLL_CLEAR = FALSE;
	virtual_scr->scroll_down = virtual_scr->scroll_up = 0;
	fflush(stdout);
}

void 
touchwin(window)
WINDOW *window;
{
	struct _line *user_line;
	int line_counter = 0;

	for (line_counter = 0, user_line = window->first_line; 
		line_counter < window->Num_lines; line_counter++)
	{
		user_line->changed = TRUE;
	}
	window->SCROLL_CLEAR = TRUE;
}

void 
wnoutrefresh(window)
WINDOW *window;
{
	struct _line *user_line;
	struct _line *virtual_line;
	int line_counter = 0;
	int user_col = 0;
	int virt_col = 0;

	if (window->SR >= virtual_scr->Num_lines)
		return;
	user_line = window->first_line;
	virtual_line = virtual_scr->first_line;
	virtual_scr->SCROLL_CLEAR = window->SCROLL_CLEAR;
	virtual_scr->LX = window->LX + window->SC;
	virtual_scr->LY = window->LY + window->SR;
	virtual_scr->scroll_up = window->scroll_up;
	virtual_scr->scroll_down = window->scroll_down;
	if ((last_window_refreshed == window) && (!window->SCROLL_CLEAR))
		return;
	for (line_counter = 0; line_counter < window->SR; line_counter++)
	{
		virtual_line = virtual_line->next_screen;
	}
	for (line_counter = 0; (line_counter < window->Num_lines)
		&& ((line_counter + window->SR) < virtual_scr->Num_lines); 
			line_counter++)
	{
		if ((last_window_refreshed != window) || (user_line->changed) || ((SCROLL | CLEAR) & window->SCROLL_CLEAR))
		{
			for (user_col = 0, virt_col = window->SC; 
				(virt_col < virtual_scr->Num_cols) 
				  && (user_col < window->Num_cols); 
				  	virt_col++, user_col++)
			{
				virtual_line->row[virt_col] = user_line->row[user_col];
				virtual_line->attributes[virt_col] = user_line->attributes[user_col];
			}
		}
		if (virtual_scr->Num_cols != window->Num_cols)
		{
			if (virtual_line->last_char < (user_line->last_char + window->SC))
			{
				if (virtual_line->row[virtual_line->last_char] == (char) NULL)
					virtual_line->row[virtual_line->last_char] = ' ';
				virtual_line->last_char = 
					min(virtual_scr->Num_cols, 
					  (user_line->last_char + window->SC));
			}
			else if (virtual_line->last_char > (user_line->last_char + window->SC))
			{
				virtual_line->row[min(virtual_scr->Num_cols, 
					  (user_line->last_char + window->SC))] = ' ';
			}
		}
		else
			virtual_line->last_char = user_line->last_char;
		virtual_line->row[virtual_line->last_char] = (char) NULL;
		virtual_line->changed = user_line->changed;
		virtual_line = virtual_line->next_screen;
		user_line = user_line->next_screen;
	}
	window->SCROLL_CLEAR = FALSE;
	window->scroll_up = window->scroll_down = 0;
	last_window_refreshed = window;
}

void 
flushinp()			/* flush input				*/
{
}

void 
ungetch(c)			/* push a character back on input	*/
int c;
{
	if (bufp < 100)
		in_buff[bufp++] = c;
}

#ifdef BSD_SELECT
int 
timed_getchar()
{
	struct timeval tv;
	fd_set fds;
	int ret_val;
	int nfds = 1;
	char temp;

	FD_ZERO(&fds);
	tv.tv_sec = 0;
	tv.tv_usec = 500000;  /* half a second */
	FD_SET(0, &fds);
	Time_Out = FALSE; /* just in case */

	ret_val = select(nfds, &fds, 0, 0, &tv);

	/*
	 |	if ret_val is less than zero, there was no input
	 |	otherwise, get a character and return it
	 */

	if (ret_val <= 0)
	{ 
		Time_Out = TRUE;
		return(-1);
	}

	return(read(STDIN_FILENO, &temp, 1)? temp : -1);
}
#endif

int 
wgetch(window)			/* get character from specified window	*/
WINDOW *window;
{
	int in_value;
	char temp;
#ifndef SYS5
	int old_arg;
#endif /* SYS5 */

#ifdef BSD_SELECT
	if (Noblock)
		in_value = ((bufp > 0) ? in_buff[--bufp] : timed_getchar());
	else
		in_value = ((bufp > 0) ? in_buff[--bufp] : read(STDIN_FILENO, &temp, 1)? temp : -1);
#else /* BSD_SELECT */
#ifdef SYS5
	in_value = ((bufp > 0) ? in_buff[--bufp] : 
					(read(STDIN_FILENO, &temp, 1)> 0) ? temp : -1);
#else /* SYS5 */
	if (Noblock)
	{
		Time_Out = FALSE;
		old_arg = fcntl(0, F_GETFL, 0);
		in_value = fcntl(0, F_SETFL, old_arg | FNDELAY);
	}
	in_value = ((bufp > 0) ? in_buff[--bufp] : read(STDIN_FILENO, &temp, 1)? temp : -1);
	if (Noblock)
	{
		fcntl(0, F_SETFL, old_arg);
		if (Time_Out)
			in_value = -1;
	}
#endif /* SYS5 */
#endif /* BSD_SELECT */

	if (in_value != -1) 
	{
		in_value &= 0xff;
		if ((Parity) && (Num_bits < 8))	
				/* strip eighth bit if parity in use */
		in_value &= 0177;
	}
	else if (interrupt_flag)
	{
		interrupt_flag = FALSE;
		in_value = wgetch(window);
	}

	if ((in_value == '\033') || (in_value == '\037'))/* escape character */
		in_value = Get_key(in_value);
	return(in_value);
}

#ifndef BSD_SELECT
void 
Clear(arg)		/* notify that time out has occurred	*/
int arg;
{
	Time_Out = TRUE;
#ifdef DEBUG
fprintf(stderr, "inside Clear()\n");
fflush(stderr);
#endif /* DEBUG */
}
#endif /* BSD_SELECT */

int 
Get_key(first_char)			/* try to decode key sequence	*/
int first_char;				/* first character of sequence	*/
{
	int in_char;
	int Count;
	char string[128];
	char *Gtemp;
	int Found;
#ifdef SYS5
	struct termio Gterminal;
#else
	struct sgttyb Gterminal;
#endif
	struct KEY_STACK *St_point;
#if (!defined( BSD_SELECT)) || (!defined(SYS5))
	int value;
#endif /* BSD_SELECT */

	Count = 0;
	Gtemp = string;
	string[Count++] = first_char;
	string[Count] = (char) NULL;
	Time_Out = FALSE;
#ifndef BSD_SELECT
	signal(SIGALRM, Clear);
	value = alarm(1);
#endif /* BSD_SELECT */
	Noblock = TRUE;
#ifdef SYS5
	Gterminal.c_cc[VTIME] = 0;		/* timeout value	*/
	Gterminal.c_lflag &= ~ICANON;	/* disable canonical operation	*/
	Gterminal.c_lflag &= ~ECHO;		/* disable echo		*/
#endif
	Count = 1;
	Found = FALSE;
	while ((Count < Max_Key_len) && (!Time_Out) && (!Found))
	{
		in_char = wgetch(stdscr);
#ifdef DEBUG
fprintf(stderr, "back in GetKey()\n");
fflush(stderr);
#endif /* DEBUG */
		if (in_char != -1)
		{
			string[Count++] = in_char;
			string[Count] = (char) NULL;
			St_point = KEY_TOS;
			while ((St_point != NULL) && (!Found))
			{
				if (!strcmp(string, St_point->element->string))
					Found = TRUE;
				else
					St_point = St_point->next;
			}
		}
	}
#ifndef BSD_SELECT
	if (!Time_Out)
		value = alarm(0);
#endif /* BSD_SELECT */
#ifdef SYS5
/*	value = ioctl(0, TCSETA, &Terminal);*/
#else
	value = ioctl(0, TIOCSETP, &Terminal);
/*	value = fcntl(0, F_SETFL, old_arg);*/
#endif
	Noblock = FALSE;
	if (Found)
	{
		return(St_point->element->value);
	}
	else
	{
		while (Count > 1)
		{
			if ((string[--Count] != -1) && 
					((unsigned char) (string[Count]) != 255))
			{
#ifdef DIAG
fprintf(stderr, "ungetting character %d\n", string[Count]);fflush(stdout);
#endif
				ungetch(string[Count]);
			}
		}
		return(first_char);
	}
}

void 
waddch(window, c)	/* output the character in the specified window	*/
WINDOW *window;
int c;
{
	int row, column;
	int shift;	/* number of spaces to shift if a tab		*/
	struct _line *tmpline;

#ifdef DIAG
/*printf("starting waddch \n");fflush(stdout);*/
#endif
	row = window->LY;
	column = window->LX;
	if (c == '\t')
	{
		shift = (column + 1) % 8;
		if (shift == 0)
			shift++;
		else
			shift = 9 - shift;
		while (shift > 0)
		{
			shift--;
			waddch(window, ' ');
		}
	}
	else if ((column < window->Num_cols) && (row < window->Num_lines))
	{
		if ((c == '~') && (Booleans[hz__]))
			c = '@';

		if (( c != '\b') && (c != '\n') && (c != '\r'))
		{
			row = 0;
			tmpline = window->first_line; 
			while (row < window->LY)
			{
				row++;
				tmpline = tmpline->next_screen;
			}
			tmpline->row[column] = c;
			tmpline->attributes[column] = window->Attrib;
			tmpline->changed = TRUE;
			if (column >= tmpline->last_char)
			{
				if (column > tmpline->last_char)
					tmpline->row[tmpline->last_char] = ' ';
				tmpline->row[column + 1] = (char) NULL;
				tmpline->attributes[column + 1] = (char) NULL;
				tmpline->last_char = column + 1;
			}
		}
		if (c == '\n')
		{
			wclrtoeol(window);
			window->LX = window->Num_cols;
		}
		else if (c == '\r')
			window->LX = 0;
		else if (c == '\b')
			window->LX--;
		else
			window->LX++;
	}
	if (window->LX >= window->Num_cols)
	{
		window->LX = 0;
		window->LY++;
		if (window->LY >= window->Num_lines)
		{
			window->LY = window->Num_lines - 1;
/*			window->LY = row;
			wmove(window, 0, 0);
			wdeleteln(window);
			wmove(window, row, 0);*/
		}
	}
	window->SCROLL_CLEAR = CHANGE;
}

void 
winsertln(window)	/* insert a blank line into the specified window */
WINDOW *window;
{
	int row, column;
	struct _line *tmp;
	struct _line *tmp1;

	window->scroll_down += 1;
	window->SCROLL_CLEAR = SCROLL;
	column = window->LX;
	row = window->LY;
	for (row = 0, tmp = window->first_line; (row < window->Num_lines) && (tmp->next_screen != NULL); row++)
		tmp = tmp->next_screen;
	if (tmp->prev_screen != NULL)
		tmp->prev_screen->next_screen = NULL;
	tmp1 = tmp;
	clear_line(tmp1, 0, window->Num_cols);
	tmp1->number = -1;
	for (row = 0, tmp = window->first_line; (row < window->LY) && (tmp->next_screen != NULL); row++)
		tmp = tmp->next_screen;
	if ((window->LY == (window->Num_lines - 1)) && (window->Num_lines > 1))
	{
		tmp1->next_screen = tmp->next_screen;
		tmp->next_screen = tmp1;
		tmp->changed = TRUE;
		tmp->next_screen->prev_screen = tmp;
	}
	else if (window->Num_lines > 1)
	{
		if (tmp->prev_screen != NULL)
			tmp->prev_screen->next_screen = tmp1;
		tmp1->prev_screen = tmp->prev_screen;
		tmp->prev_screen = tmp1;
		tmp1->next_screen = tmp;
		tmp->changed = TRUE;
		tmp->scroll = DOWN;
	}
	if (window->LY == 0)
		window->first_line = tmp1;
}

void 
wdeleteln(window)	/* delete a line in the specified window */
WINDOW *window;
{
	int row, column;
	struct _line *tmp;
	struct _line  *tmpline;

	if (window->Num_lines > 1)
	{
		window->scroll_up += 1;
		window->SCROLL_CLEAR = SCROLL;
		column = window->LX;
		row = window->LY;
		for (row = 0, tmp = window->first_line; row < window->LY; row++)
			tmp = tmp->next_screen;
		if (window->LY == 0)
			window->first_line = tmp->next_screen;
		if (tmp->prev_screen != NULL)
			tmp->prev_screen->next_screen = tmp->next_screen;
		if (tmp->next_screen != NULL)
		{
			tmp->next_screen->changed = TRUE;
			tmp->next_screen->scroll = UP;
			tmp->next_screen->prev_screen = tmp->prev_screen;
		}
		tmpline = tmp;
		clear_line(tmpline, 0, window->Num_cols);
		tmpline->number = -1;
		for (row = 0, tmp = window->first_line; tmp->next_screen != NULL; row++)
			tmp = tmp->next_screen;
		if (tmp != NULL)
		{
			tmp->next_screen = tmpline;
			tmp->next_screen->prev_screen = tmp;
			tmp->changed = TRUE;
			tmp = tmp->next_screen;
		}
		else
			tmp = tmpline;
		tmp->next_screen = NULL;
	}
	else
	{
		clear_line(window->first_line, 0, window->Num_cols);
	}
}

void 
wclrtobot(window)	/* delete from current position to end of the window */
WINDOW *window;
{
	int row, column;
	struct _line *tmp;

	window->SCROLL_CLEAR |= CLEAR;
	column = window->LX;
	row = window->LY;
	for (row = 0, tmp = window->first_line; row < window->LY; row++)
		tmp = tmp->next_screen;
	clear_line(tmp, column, window->Num_cols);
	for (row = (window->LY + 1); row < window->Num_lines; row++)
	{
		tmp = tmp->next_screen;
		clear_line(tmp, 0, window->Num_cols);
	}
	wmove(window, row, column);
}

void 
wstandout(window)	/* begin standout mode in window	*/
WINDOW *window;
{
	if (Numbers[sg__] < 1)	/* if not magic cookie glitch	*/
		window->Attrib |= A_STANDOUT;
}

void 
wstandend(window)	/* end standout mode in window	*/
WINDOW *window;
{
	window->Attrib &= ~A_STANDOUT;
}

void 
waddstr(window, string)	/* write 'string' in window	*/
WINDOW *window;
char *string;
{
	char *wstring;

	for (wstring = string; *wstring != (char) NULL; wstring++)
		waddch(window, *wstring);
}

void 
clearok(window, flag)	/* erase screen and redraw at next refresh	*/
WINDOW *window;
int flag;
{
	Repaint_screen = TRUE;
}


void 
echo()			/* turn on echoing				*/
{
	int value;

#ifdef SYS5
	Terminal.c_lflag |= ECHO;		/* enable echo		*/
	value = ioctl(0, TCSETA, &Terminal);	/* set characteristics	*/
#else
	Terminal.sg_flags |= ECHO;		/* enable echo		*/
	value = ioctl(0, TIOCSETP, &Terminal);	/* set characteristics	*/
#endif
}

void 
noecho()		/* turn off echoing				*/
{
	int value;

#ifdef SYS5
	Terminal.c_lflag &= ~ECHO;		/* disable echo		*/
	value = ioctl(0, TCSETA, &Terminal);	/* set characteristics	*/
#else
	Terminal.sg_flags &= ~ECHO;		/* disable echo		*/
	value = ioctl(0, TIOCSETP, &Terminal);	/* set characteristics	*/
#endif
}

void 
raw()			/* set to read characters immediately		*/
{
	int value;

#ifdef SYS5
	Intr = Terminal.c_cc[VINTR];	/* get the interrupt character	*/
	Terminal.c_lflag &= ~ICANON;	/* disable canonical operation	*/
	Terminal.c_lflag &= ~ISIG;	/* disable signal checking	*/
#ifdef FLUSHO
	Terminal.c_lflag &= ~FLUSHO;
#endif
#ifdef PENDIN
	Terminal.c_lflag &= ~PENDIN;
#endif
#ifdef IEXTEN
	Terminal.c_lflag &= ~IEXTEN;
#endif
	Terminal.c_cc[VMIN] = 1;		/* minimum of one character */
	Terminal.c_cc[VTIME] = 255;		/* timeout value	*/
	Terminal.c_cc[VINTR] = 0;		/* eliminate interrupt	*/
	value = ioctl(0, TCSETA, &Terminal);	/* set characteristics	*/
#else
	Terminal.sg_flags |= RAW;	/* enable raw mode		*/
	value = ioctl(0, TIOCSETP, &Terminal);	/* set characteristics	*/
#endif
}

void 
noraw()			/* set to normal character read mode		*/
{
	int value;

#ifdef SYS5
	Terminal.c_lflag |= ICANON;	/* enable canonical operation	*/
	Terminal.c_lflag |= ISIG;	/* enable signal checking	*/
	Terminal.c_cc[VEOF] = 4;		/* EOF character = 4	*/
	Terminal.c_cc[VEOL] = (char) NULL;	/* EOL = 0		*/
	Terminal.c_cc[VINTR] = Intr;		/* reset interrupt char	*/
	value = ioctl(0, TCSETA, &Terminal);	/* set characteristics	*/
#else
	Terminal.sg_flags &= ~RAW;	/* disable raw mode		*/
	value = ioctl(0, TIOCSETP, &Terminal);	/* set characteristics	*/
/*	old_arg = fcntl(0, F_GETFL, 0);
	value = fcntl(0, F_SETFL, old_arg & ~FNDELAY);*/
#endif
}

void 
nl()
{
	int value;

#ifdef SYS5
	Terminal.c_iflag |= ICRNL;	/* enable carriage-return to line-feed mapping	*/
	value = ioctl(0, TCSETA, &Terminal);	/* set characteristics	*/
#endif
}

void 
nonl()
{
	int value;

#ifdef SYS5
	Terminal.c_iflag &= ~ICRNL;	/* disable carriage-return to line-feed mapping	*/
	Terminal.c_iflag &= ~IGNCR;	/* do not ignore carriage-return	*/
	value = ioctl(0, TCSETA, &Terminal);	/* set characteristics	*/
#endif
}

void 
saveterm()
{
}

void 
fixterm()
{
}

void 
resetterm()
{
}

void 
nodelay(window, flag)
WINDOW *window;
int flag;
{
}

void 
idlok(window, flag)
WINDOW *window;
int flag;
{
}

void 
keypad(window, flag)
WINDOW *window;
int flag;
{
	if (flag)
		String_Out(String_table[ks__], NULL, 0);
	else
		String_Out(String_table[ke__], NULL, 0);
}

void 
savetty()		/* save current tty stats			*/
{
	int value;

#ifdef SYS5
	value = ioctl(0, TCGETA, &Saved_tty);	/* set characteristics	*/
#else
	value = ioctl(0, TIOCGETP, &Saved_tty);	/* set characteristics	*/
#endif
}

void 
resetty()		/* restore previous tty stats			*/
{
	int value;

#ifdef SYS5
	value = ioctl(0, TCSETA, &Saved_tty);	/* set characteristics	*/
#else
	value = ioctl(0, TIOCSETP, &Saved_tty);	/* set characteristics	*/
#endif
}

void 
endwin()		/* end windows					*/
{
	keypad(stdscr, FALSE);
	initialized = FALSE;
	delwin(curscr);
	delwin(virtual_scr);
	delwin(stdscr);
#ifndef SYS5
{
	int old_arg, value;
/*	old_arg = fcntl(0, F_GETFL, 0);
	value = fcntl(0, F_SETFL, old_arg & ~FNDELAY);*/
}
#endif
}

void 
delwin(window)		/* delete the window structure			*/
WINDOW *window;
{
	int i;

	for (i = 1; (i < window->Num_lines) && (window->first_line->next_screen != NULL); i++)
	{
		window->first_line = window->first_line->next_screen;
		free(window->first_line->prev_screen->row);
		free(window->first_line->prev_screen->attributes);
		free(window->first_line->prev_screen);
	}
	if (window == last_window_refreshed)
		last_window_refreshed = 0;
	if (window->first_line != NULL)
	{
		free(window->first_line->row);
		free(window->first_line->attributes);
		free(window->first_line);
		free(window);
	}
}

void 
wprintw(WINDOW *window, const char *format, ...)
{
	va_list ap;
	int value;
	char *fpoint;
	char *wtemp;

	va_start(ap, format);

	fpoint = (char *) format;
	while (*fpoint != (char) NULL)
	{
		if (*fpoint == '%')
		{
			fpoint++;
			if (*fpoint == 'd')
			{
				value = va_arg(ap, int);
				iout(window, value);
			}
			else if (*fpoint == 'c')
			{
				value = va_arg(ap, int);
				waddch(window, value);
			}
			else if (*fpoint == 's')
			{
				wtemp = va_arg(ap, char *);
					waddstr(window, wtemp);
			}
			fpoint++;
		}
		else if (*fpoint == '\\')
		{
			fpoint++;
			if (*fpoint == 'n')
				waddch(window, '\n');
			else if ((*fpoint >= '0') && (*fpoint <= '9'))
			{
				value = 0;
				while ((*fpoint >= '0') && (*fpoint <= '9'))
				{
					value = (value * 8) + (*fpoint - '0');
					fpoint++;
				}
				waddch(window, value);
			}
			fpoint++;
		}
		else
			waddch(window, *fpoint++);
	}
	va_end(ap);
}

void 
iout(window, value)	/* output characters		*/
WINDOW *window;
int value;
{
	int i;

	if ((i = value / 10) != 0)
		iout(window, i);
	waddch(window, ((value % 10) + '0'));
}

int 
Comp_line(line1, line2)		/* compare lines	*/
struct _line *line1;
struct _line *line2;
{
	int count1, count2;
	int i;
	char *att1, *att2;
	char *c1, *c2;

	c1 = line1->row;
	c2 = line2->row;
	att1 = line1->attributes;
	att2 = line2->attributes;
	count2 = strlen(c1) + 1;
	count1 = strlen(c2) + 1;
	if (count1 > count2)
	{
		i = count2;
		count2 = count1;
		count1 = i;
	}
	if (count2 > (count1 + count1))
		return(2);
	i = 0;
	while ((c1[i] != (char) NULL) && (c2[i] != (char) NULL) && (c1[i] == c2[i]) && (att1[i] == att2[i]))
		i++;
	count1 = i + 1;
	if ((count1 == 1) && (count2 == 1))
		count1 = 0;			/* both lines blank	*/
	else if (count2 == count1)
		count1 = -1;			/* equal		*/
	else
		count1 = count2 / count1;	/* lines unequal	*/
	return(count1);
}

struct _line *
Insert_line(row, end_row, window)	/* insert line into screen */
int row;
int end_row;
WINDOW *window;
{
	int i;
	struct _line *tmp;
	struct _line *tmp1;

	for (i = 0, tmp = curscr->first_line; i < window->SR; i++)
		tmp = tmp->next_screen;
	if ((end_row + window->SR) == 0)
		curscr->first_line = curscr->first_line->next_screen;
	top_of_win = tmp;
	/*
	 |	find bottom line to delete
	 */
	for (i = 0, tmp = top_of_win; (tmp->next_screen != NULL) && (i < end_row); i++)
		tmp = tmp->next_screen;
	if (tmp->prev_screen != NULL)
		tmp->prev_screen->next_screen = tmp->next_screen;
	if (tmp->next_screen != NULL)
		tmp->next_screen->prev_screen = tmp->prev_screen;
	tmp1 = tmp;
	/*
	 |	clear deleted line
	 */
	clear_line(tmp, 0, window->Num_cols);
	tmp1->number = -1;
	for (i = 0, tmp = curscr->first_line; (tmp->next_screen != NULL) && (i < window->SR); i++)
		tmp = tmp->next_screen;
	top_of_win = tmp;
	for (i = 0, tmp = top_of_win; i < row; i++)
		tmp = tmp->next_screen;
	if ((tmp->prev_screen != NULL) && (window->Num_lines > 0))
		tmp->prev_screen->next_screen = tmp1;
	tmp1->prev_screen = tmp->prev_screen;
	tmp->prev_screen = tmp1;
	tmp1->next_screen = tmp;
	if ((row + window->SR) == 0)
		curscr->first_line = tmp1;
	if (tmp1->next_screen != NULL)
		tmp1 = tmp1->next_screen;

	if ((!String_table[cs__]) && (end_row < window->Num_lines))
	{
		Position(window, (window->SR + end_row), 0);
		String_Out(String_table[dl__], NULL, 0);
	}
	Position(window, (window->SR + row), 0);
	if (String_table[al__] != NULL)
		String_Out(String_table[al__], NULL, 0);
	else
		String_Out(String_table[sr__], NULL, 0);

	for (i = 0, top_of_win = curscr->first_line; (top_of_win->next_screen != NULL) && (i < window->SR); i++)
		top_of_win = top_of_win->next_screen;
	return(tmp1);
}


struct _line *
Delete_line(row, end_row, window)	/* delete a line on screen */
int row;
int end_row;
WINDOW *window;
{
	int i;
	struct _line *tmp;
	struct _line *tmp1;
	struct _line *tmp2;

	i = 0;
	tmp = curscr->first_line;
	while (i < window->SR)
	{
		i++;
		tmp = tmp->next_screen;
	}
	/*
	 |	find line to delete
	 */
	top_of_win = tmp;
	if ((row + window->SR) == 0)
		curscr->first_line = top_of_win->next_screen;
	for (i = 0, tmp = top_of_win; i < row; i++)
		tmp = tmp->next_screen;
	if (tmp->prev_screen != NULL)
		tmp->prev_screen->next_screen = tmp->next_screen;
	if (tmp->next_screen != NULL)
		tmp->next_screen->prev_screen = tmp->prev_screen;
	tmp2 = tmp->next_screen;
	tmp1 = tmp;
	/*
	 |	clear deleted line
	 */
	clear_line(tmp1, 0, window->Num_cols);
	tmp1->number = -1;
	/*
	 |	find location to insert deleted line
	 */
	for (i = 0, tmp = curscr->first_line; (tmp->next_screen != NULL) && (i < window->SR); i++)
		tmp = tmp->next_screen;
	top_of_win = tmp;
	for (i = 0, tmp = top_of_win; (i < end_row) && (tmp->next_screen != NULL); i++)
		tmp = tmp->next_screen;
	tmp1->next_screen = tmp;
	tmp1->prev_screen = tmp->prev_screen;
	if (tmp1->prev_screen != NULL)
		tmp1->prev_screen->next_screen = tmp1;
	tmp->prev_screen = tmp1;

	Position(window, (window->SR + row), 0);
	String_Out(String_table[dl__], NULL, 0);
	if ((!String_table[cs__]) && (end_row < window->Num_lines))
	{
		Position(window, (window->SR + end_row), 0);
		String_Out(String_table[al__], NULL, 0);
	}
	else if ((String_table[cs__] != NULL) && (String_table[dl__] == NULL))
	{
		Position(window, (window->SR + end_row), 0);
		putchar('\n');
	}

	if (row == (window->Num_lines-1))
		tmp2 = tmp1;
	if ((row + window->SR) == 0)
		curscr->first_line = top_of_win = tmp2;
	return(tmp2);
}

void 
CLEAR_TO_EOL(window, row, column)
WINDOW *window;
int row, column;
{
	int x, y;
	struct _line *tmp1;

	for (y = 0, tmp1 = curscr->first_line; (y < (window->SR+row)) && (tmp1->next_screen != NULL); y++)
		tmp1 = tmp1->next_screen;
	for (x = column; x<window->Num_cols; x++)
	{
		tmp1->row[x] = ' ';
		tmp1->attributes[x] = (char) NULL;
	}
	tmp1->row[column] = (char) NULL;
	tmp1->last_char = column;
	if (column < COLS)
	{
		if (STAND)
		{
			STAND = FALSE;
			Position(window, row, column);
			attribute_off();
		}
		if (String_table[ce__] != NULL)
			String_Out(String_table[ce__], NULL, 0);
		else
		{
			for (x = column; x < window->Num_cols; x++)
				putchar(' ');
			Curr_x = x;
		}
	}
}

int 
check_delete(window, line, offset, pointer_new, pointer_old)
WINDOW *window;
int line, offset;
struct _line *pointer_new, *pointer_old;
{
	int end_old;
	int end_new;
	int k;
	int changed;
	char *old_lin;
	char *new_lin;
	char *old_att;
	char *new_att;
	
	changed = FALSE;
	new_lin = pointer_new->row;
	new_att = pointer_new->attributes;
	old_lin = pointer_old->row;
	old_att = pointer_old->attributes;
	end_old = end_new = offset;
	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))
		end_old++;
	if (old_lin[end_old] != (char) NULL)
	{
		k = 0;
		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))
			k++;
		if ((k > 8) || ((new_lin[end_new+k] == (char) NULL) && (k != 0)))
		{
			if (new_lin[end_new+k] == (char) NULL)
			{
				Position(window, line, (end_new+k));
				CLEAR_TO_EOL(window, line, (end_new+k));
			}
			Position(window, line, offset);
			for (k = offset; k < end_old; k++)
				Char_del(old_lin, old_att, offset, window->Num_cols);
			while ((old_lin[offset] != (char) NULL) && (offset < COLS))
				offset++;
			pointer_old->last_char = offset;
			changed = TRUE;
		}
	}
	return(changed);
}

/*
 |	Check if characters were inserted in the middle of a line, and if 
 |	so, insert them.
 */

int 
check_insert(window, line, offset, pointer_new, pointer_old)
WINDOW *window;
int line, offset;
struct _line *pointer_new, *pointer_old;
{
	int changed;
	int end_old, end_new;
	int k;
	int same = FALSE;
	int old_off;
	int insert;
	char *old_lin;
	char *new_lin;
	char *old_att;
	char *new_att;

	changed = FALSE;
	new_lin = pointer_new->row;
	new_att = pointer_new->attributes;
	old_lin = pointer_old->row;
	old_att = pointer_old->attributes;
	end_old = end_new = offset;
	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))
		end_new++;
	if (new_lin[end_new] != (char) NULL)
	{
		k = 0;
		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))
			k++;
		/*
		 |  check for commonality between rest of lines (are the old 
		 |  and new lines the same, except for a chunk in the middle?)
		 |  if the rest of the lines are common, do not insert text
		 */
		old_off = end_new;
		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]))
			old_off++;
		if ((old_lin[old_off] == new_lin[old_off]) && (old_att[old_off] == new_att[old_off]))
			same = TRUE;
		if ((!same) && ((k > 8) || ((new_lin[end_new+k] == (char) NULL) && (k != 0))))
		{
			Position(window, line, offset);
			insert = FALSE;
			if (String_table[ic__] == NULL)
			{
				String_Out(String_table[im__], NULL, 0);
				insert = TRUE;
			}
			for (k = offset; k < end_new; k++)
			{
				if (!insert)
					String_Out(String_table[ic__], NULL, 0);
				Char_ins(old_lin, old_att, new_lin[k], new_att[k], k, window->Num_cols);
			}
			if (insert)
				String_Out(String_table[ei__], NULL, 0);
			while ((old_lin[offset] != (char) NULL) && (offset < COLS))
				offset++;
			pointer_old->last_char = offset;
			changed = TRUE;
		}
	}
	return(changed);
}

void 
doupdate()
{
	WINDOW *window;
	int similar;
	int diff;
	int begin_old, begin_new;
	int end_old, end_new;
	int count1, j;
	int from_top, tmp_ft, offset;
	int changed;
	int first_time;
	int first_same;
	int last_same;
	int list[10];

	struct _line *curr;
	struct _line *virt;
	struct _line *old;

	struct _line *new;

	char *cur_lin;
	char *vrt_lin;
	char *cur_att;
	char *vrt_att;
	char *att1, *att2;
	char *c1, *c2;

	char NC_chinese = FALSE;	/* flag to indicate handling Chinese */

	window = virtual_scr;

	if ((nc_attributes & A_NC_BIG5) != 0)
		NC_chinese = TRUE;

	if (Repaint_screen)
	{
		if (String_table[cl__])
			String_Out(String_table[cl__], NULL, 0);
		else
		{
			from_top = 0;
			while (from_top < LINES)
			{
				Position(curscr, from_top, 0);
				if (String_table[ce__] != NULL)
					String_Out(String_table[ce__], NULL, 0);
				else
				{
					for (j = 0; j < window->Num_cols; j++)
						putchar(' ');
				}
				from_top++;
			}
		}
		for (from_top = 0, curr = curscr->first_line; from_top < curscr->Num_lines; from_top++, curr = curr->next_screen)
		{
			Position(curscr, from_top, 0);
			for (j = 0; (curr->row[j] != (char) NULL) && (j < curscr->Num_cols); j++)
			{
				Char_out(curr->row[j], curr->attributes[j], curr->row, curr->attributes, j);
			}
			if (STAND)
			{
				STAND = FALSE;
				Position(curscr, from_top, j);
				attribute_off();
			}
		}
		Repaint_screen = FALSE;
	}

	similar = 0;
	diff = FALSE;
	top_of_win = curscr->first_line;

	for (from_top = 0, curr = top_of_win, virt = window->first_line; 
			from_top < window->Num_lines; from_top++)
	{
		virtual_lines[from_top] = TRUE;
		if ((similar = Comp_line(curr, virt)) > 0)
		{
			virtual_lines[from_top] = FALSE;
			diff = TRUE;
		}
		curr = curr->next_screen;
		virt = virt->next_screen;
	}

	from_top = 0;
	virt = window->first_line;
	curr = top_of_win;
	similar = 0;
	/*
	 |  if the window has lines that are different, check for scrolling
	 */
	if (diff)
	{
		last_same = -1;
		changed = FALSE;
		for (first_same = window->Num_lines; 
		    (first_same > from_top) && (virtual_lines[first_same - 1]);
		     first_same--)
			;
		count1 = first_same - 1;
		for (last_same = 0;
		    (last_same < window->Num_lines) && (virtual_lines[last_same]== FALSE);
		     last_same++)
			;
		while ((from_top < first_same) && nc_scrolling_ability)
					/* check entire lines for diffs	*/
		{


			if (from_top >= last_same)
			{
				for (last_same = from_top; 
				     (last_same < window->Num_lines) && 
				     (virtual_lines[last_same] == FALSE);
				      last_same++)
					;
			}
			if (!virtual_lines[from_top])
			{
				diff = TRUE;
				/*
				 |	check for lines deleted (scroll up)
				 */
				for (tmp_ft = from_top+1, old = curr->next_screen; 
					((window->scroll_up) && (diff) && 
					(tmp_ft < last_same) && 
					(!virtual_lines[tmp_ft]));
						tmp_ft++)
				{
					if ((Comp_line(old, virt) == -1) && (!virtual_lines[from_top]))
					{
						if (String_table[cs__]) /* scrolling region */
						{
							list[1] = from_top;
							list[0] = min((last_same - 1), (window->Num_lines - 1));
							String_Out(String_table[cs__], list, 2);
							Curr_y = Curr_x = -1;
						}

						for (offset = (tmp_ft - from_top); (offset > 0); offset--)
						{
							old = Delete_line(from_top, min((last_same - 1), (window->Num_lines - 1)), window);
							diff = FALSE;
						}

						if (String_table[cs__]) /* scrolling region */
						{
							list[1] = 0;
							list[0] = LINES - 1;
							String_Out(String_table[cs__], list, 2);
							Curr_y = Curr_x = -1;
							}

						top_of_win = curscr->first_line;
						curr = top_of_win;
						for (offset = 0; offset < from_top; offset++)
							curr = curr->next_screen;
						for (offset = from_top, old=curr, new=virt; 
						   offset < window->Num_lines; 
						   old=old->next_screen, new=new->next_screen,
						   offset++)
						{
							similar = Comp_line(old, new);
							virtual_lines[offset] = (similar > 0 ? FALSE : TRUE);
						}
					}
					else
						old = old->next_screen;
				}
				/*
				 |	check for lines inserted (scroll down)
				 */
				for (tmp_ft = from_top-1, old = curr->prev_screen; 
					((window->scroll_down) && (tmp_ft >= 0) && 
					(diff) && 
					(!virtual_lines[tmp_ft])); 
					  tmp_ft--)
				{
					if (Comp_line(old, virt) == -1)
					{
						if (String_table[cs__]) /* scrolling region */
						{
							list[1] = tmp_ft;
							list[0] = min((last_same - 1), (window->Num_lines - 1));
							String_Out(String_table[cs__], list, 2);
							Curr_y = Curr_x = -1;
						}

						for (offset = (from_top - tmp_ft); (offset > 0); offset--)
						{
							old = Insert_line(tmp_ft, min((last_same - 1), (window->Num_lines -1)), window);
							diff = FALSE;
						}

						if (String_table[cs__]) /* scrolling region */
						{
							list[1] = 0;
							list[0] = LINES - 1;
							String_Out(String_table[cs__], list, 2);
							Curr_y = Curr_x = -1;
						}

						top_of_win = curscr->first_line;
						curr = top_of_win;
						for (offset = 0; offset < from_top; offset++)
							curr = curr->next_screen;
						for (offset = from_top, old=curr, new=virt; 
						   offset < window->Num_lines; 
						   old=old->next_screen, new=new->next_screen,
						   offset++)
						{
							similar = Comp_line(old, new);
							virtual_lines[offset] = (similar > 0 ? FALSE : TRUE);
						}
					}
					else
						old = old->prev_screen;
				}
			}
			from_top++;
			curr = curr->next_screen;
			virt = virt->next_screen;
		}
	}


	/*
	 |	Scrolling done, now need to insert, delete, or modify text 
	 |	within lines.
	 */

	for (from_top = 0, curr = curscr->first_line; from_top < window->SR; from_top++)
		curr = curr->next_screen;
	top_of_win = curr;
	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)
	{

		/*
		 |	If either 'insert mode' or 'insert char' are 
		 |	available, enter the following 'if' statement, 
		 |	else, need to simply rewrite the contents of the line
		 |	at the point where the contents of the line change.
		 */

		if (((String_table[ic__]) || (String_table[im__])) && 
		    (String_table[dc__]) && (curr->row[0] != (char) NULL) &&
		    (!NC_chinese))
		{
			j = 0;
			first_time = TRUE;
			vrt_lin = virt->row;
			vrt_att = virt->attributes;
			cur_lin = curr->row;
			cur_att = curr->attributes;
			while ((vrt_lin[j] != (char) NULL) && (j < window->Num_cols))
			{
				if ((STAND) && (Booleans[xs__]))
				{
					while ((vrt_lin[j] == cur_lin[j]) && (vrt_att[j] == cur_att[j]) && (vrt_lin[j] != (char) NULL) && (vrt_att[j]))
						j++;
					if ((STAND) && (!vrt_att[j]))
					{
						STAND = FALSE;
						Position(window, from_top, j);
						attribute_off();
						attribute_off();
					}
				}
				else
				{
					while ((vrt_lin[j] == cur_lin[j]) && (vrt_att[j] == cur_att[j]) && (vrt_lin[j] != (char) NULL))
						j++;
				}
				if ((vrt_att[j] != cur_att[j]) && (cur_att[j]) && (Booleans[xs__]))
				{
					Position(window, from_top, j);
/*					CLEAR_TO_EOL(window, from_top, j);*/
					attribute_off();
					attribute_off();
				}
				if (vrt_lin[j] != (char) NULL)
				{
					begin_new = j;
					begin_old = j;
					end_old = j;
					end_new = j;
					if ((first_time) && (virt->changed))
					{
						if (curr->last_char <= virt->last_char)
							changed = check_insert(window, from_top, j, virt, curr);
					}
					changed = check_delete(window, from_top, j, virt, curr);
					first_time = FALSE;
					virt->changed = FALSE;
					if (!changed)
						changed = check_insert(window, from_top, j, virt, curr);
					if (((!changed) || (cur_lin[j] != vrt_lin[j]) || (cur_att[j] != vrt_att[j])) && (j < window->Num_cols))
					{
						if ((vrt_lin[j] == ' ') && (cur_lin[j] == (char) NULL) && (vrt_att[j] == cur_att[j]))
							cur_lin[j] = ' ';
						else
						{
							Position(window, from_top, j);
							Char_out(vrt_lin[j], vrt_att[j], cur_lin, cur_att, j);
						}
					}
					if ((vrt_lin[j] != (char) NULL))
						j++;
				}
				if ((STAND) && (!vrt_att[j]))
				{
					STAND = FALSE;
					Position(window, from_top, j);
					attribute_off();
				}
			}
			if ((vrt_lin[j] == (char) NULL) && (cur_lin[j] != (char) NULL))
			{
				Position(window, from_top, j);
				CLEAR_TO_EOL(window, from_top, j);
			}
		}
		else /*if ((similar != -1) && (similar != 0))*/
		{
			j = 0;
			c1 = curr->row;
			att1 = curr->attributes;
			c2 = virt->row;
			att2 = virt->attributes;
			while ((j < window->Num_cols) && (c2[j] != (char) NULL))
			{
				while ((c1[j] == c2[j]) && (att1[j] == att2[j]) && (j < window->Num_cols) && (c2[j] != (char) NULL))
					j++;

				/*
				 |	if previous character is an eight bit 
				 |	char, start redraw from that character
				 */

				if ((NC_chinese) && (highbitset(c1[j - 1])))
					j--;
				begin_old = j;
				begin_new = j;
				if ((j < window->Num_cols) && (c2[j] != (char) NULL))
				{
					Position(window, from_top, begin_old);
					CLEAR_TO_EOL(window, from_top, j);
					Position(window, from_top, begin_old);
					for (j = begin_old; (c2[j] != (char) NULL) && (j < window->Num_cols); j++)
						Char_out(c2[j], att2[j], c1, att1, j);
				}
			}
			if ((c2[j] == (char) NULL) && (c1[j] != (char) NULL))
			{
				Position(window, from_top, j);
				CLEAR_TO_EOL(window, from_top, j);
			}
		}
		if (STAND)
		{
			STAND = FALSE;
			Position(window, from_top, j);
			attribute_off();
		}
		virt->number = from_top;
	}
	Position(window, window->LY, window->LX);
}

void 
Position(window, row, col)	/* position the cursor for output on the screen	*/
WINDOW *window;
int row;
int col;
{
	int list[10];
	int place;

	int pos_row;
	int pos_column;

	pos_row = row + window->SR;
	pos_column = col + window->SC;
	if ((pos_row != Curr_y) || (pos_column != Curr_x))
	{
		if (String_table[cm__] != NULL) /* && (row < window->Num_lines) && (column < window->Num_cols))*/ 
		{
			place = 0;
			list[place++] = pos_column;
			list[place++] = pos_row;
			String_Out(String_table[cm__], list, place);
			if ((STAND) && (!Booleans[ms__]))
				attribute_on();
		}
		Curr_x = pos_column;
		Curr_y = pos_row;
	}
}

void 
Char_del(line, attrib, offset, maxlen)	/* delete chars from line	*/
char *line;
char *attrib;
int offset;
int maxlen;
{
	int one, two;

	for (one = offset, two = offset+1; (line[one] != (char) NULL) && (one < maxlen); one++, two++)
	{
		line[one] = line[two];
		attrib[one] = attrib[two];
	}
	String_Out(String_table[dc__], NULL, 0);
}

void 
Char_ins(line, attrib, newc, newatt, offset, maxlen)	/* insert chars in line	*/
char *line;
char *attrib;
char newc;
char newatt;
int offset;
int maxlen;
{
	int one, two;

	one = 0;
	while ((line[one] != (char) NULL) && (one < (maxlen - 2)))
		one++;
	for (two = one + 1; (two > offset); one--, two--)
	{
		line[two] = line[one];
		attrib[two] = attrib[one];
	}
	line[offset] = newc;
	attrib[offset] = newatt;
	Char_out(newc, newatt, line, attrib, offset);
}

void 
attribute_on()
{
	if (String_table[sa__])
	{
		attributes_set[0] = 1;
		String_Out(String_table[sa__], attributes_set, 1);
	}
	else if (String_table[so__])
		String_Out(String_table[so__], NULL, 0);
}

void 
attribute_off()
{
	if (String_table[me__])
		String_Out(String_table[me__], NULL, 0);
	else if (String_table[sa__])
	{
		attributes_set[0] = 0;
		String_Out(String_table[sa__], attributes_set, 1);
	}
	else if (String_table[se__])
		String_Out(String_table[se__], NULL, 0);
}

void 
Char_out(newc, newatt, line, attrib, offset)	/* output character with proper attribute	*/
char newc;
char newatt;
char *line;
char *attrib;
int offset;
{


	if ((newatt) && (!STAND))
	{
		STAND = TRUE;
		attribute_on();
	}
	else if ((STAND) && (!newatt))
	{
		STAND = FALSE;
		attribute_off();
	}

	if ((newatt) && (STAND) && (Booleans[xs__]))
	{
		attribute_on();
	}

	if (!((Curr_y >= (LINES - 1)) && (Curr_x >= (COLS - 1))))
	{
		putchar(newc);
		line[offset] = newc;
		attrib[offset] = newatt;
	}
	Curr_x++;
}

/*
 |
 |	The two routines that follow, nc_setattrib(), nc_clearattrib(), are 
 |	hacks that notify new_curse to handle characters that have the high 
 |	bit set as the first of two bytes of a multi-byte string.
 |
 */

void 
nc_setattrib(flag)
int flag;
{
	nc_attributes |= flag;
}

void 
nc_clearattrib(flag)
int flag;
{
	nc_attributes &= ~flag;
}