home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume28 / screen32 / part01 < prev    next >
Encoding:
Text File  |  1992-02-08  |  56.6 KB  |  2,553 lines

  1. Newsgroups: comp.sources.misc
  2. From: jnweiger@immd4.informatik.uni-erlangen.de (Juergen Weigert)
  3. Subject:  v28i018:  screen-3.2 - multiple windows on an ASCII terminal, v3.2, Part01/11
  4. Message-ID: <csm-v28i018=screen-3.2.163016@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: 7ecf76aeefa3a688b10fdb6406d58388
  6. Date: Sun, 9 Feb 1992 22:33:55 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: jnweiger@immd4.informatik.uni-erlangen.de (Juergen Weigert)
  10. Posting-number: Volume 28, Issue 18
  11. Archive-name: screen-3.2/part01
  12. Environment: UNIX
  13.  
  14. This is iScreen version 3.2.  It is an upgrade to version 3.1.1 that was posted
  15. in dec 91 to comp.sources.unix.  Versions 3.1.x of iScreen are potential 
  16. security risks under SunOS 4.1.1. These versions fail to detach or terminate 
  17. the session when the modem line hangs up.  Anyone using telnet or rlogin could 
  18. (unwillingly) connect to such a session.
  19.  
  20. iScreen users on SunOS 4.1.1 please do upgrade to version 3.2! 
  21.  
  22. Although fixing the bug described above was the main reason for this posting,
  23. there are numerous other fixes/enhancements:
  24.  
  25.     * support for NeXT, Apollo, Ultrix, SVR4, SCO, ISC, SGI, bsd386, ...
  26.       added or enhanced. 
  27.     
  28.     * the "dead CTRL-O key" bug is fixed.
  29.     
  30.     * flow control has been redesigned.
  31.     
  32.     * I/O is no longer stripped to 7 bit.
  33.     
  34.     * new commands "hardcopy_append on", "bufferfile /tmp/myown", 
  35.       "(set) refresh off".
  36.       
  37.     * redesign of interrupt passing. The use of "screen -i" is now 
  38.       encouraged.
  39.     
  40.     * overall code cleanup.
  41.     
  42. The complete distribution of iScreen 3.2 is available via ftp from:
  43.  
  44.    ftp.uni-erlangen.de[131.188.1.43]:portal/utilities/screen/screen32.tar.Z
  45.    
  46. For a brief introduction and a short summary of essential commands
  47. refer to the files "readme" and "README".
  48.    
  49. I wish to thank all contributors for requesting features or sending patches.
  50. Special thanks to Marc Boucher who tested and patched iScreen on numerous
  51. platforms.
  52.  
  53. Juergen Weigert || jnweiger@immd4.informatik.uni-erlangen.de || irc: Ellrond
  54. Boing... Boing..|| feeping creaturism -- bugs and bunnies everywhere.
  55. Boing... Boing..|| "Oh! No!!!" -- Plopp!  
  56. ------------------------------------------
  57. #!/bin/sh
  58. # This is a shell archive (produced by shar 3.49)
  59. # To extract the files from this archive, save it to a file, remove
  60. # everything above the "!/bin/sh" line above, and type "sh file_name".
  61. #
  62. # existing files will NOT be overwritten unless -c is specified
  63. #
  64. # This is part 1 of a multipart archive                                    
  65. # do not concatenate these parts, unpack them in order with /bin/sh        
  66. #
  67. # This shar contains:
  68. # length  mode       name
  69. # ------ ---------- ------------------------------------------
  70. #  68724 -r--r--r-- screen3.2/ansi.c
  71. #   2276 -r--r--r-- screen3.2/ansi.h
  72. #   9213 -r--r--r-- screen3.2/extern.h
  73. #  54830 -r--r--r-- screen3.2/fileio.c
  74. #  12878 -r--r--r-- screen3.2/help.c
  75. #  25395 -r--r--r-- screen3.2/mark.c
  76. #   3666 -r--r--r-- screen3.2/patchlevel.h
  77. #   5664 -r--r--r-- screen3.2/putenv.c
  78. #  63790 -r--r--r-- screen3.2/screen.1
  79. #  86700 -r--r--r-- screen3.2/screen.c
  80. #  12454 -r--r--r-- screen3.2/screen.h
  81. #  27101 -r--r--r-- screen3.2/socket.c
  82. #  14071 -r--r--r-- screen3.2/window.c
  83. #    643 -rw-r--r-- screen3.2/terminfo/s/screen-w
  84. #    999 -rw-r--r-- screen3.2/terminfo/s/screen
  85. #    668 -rw-r--r-- screen3.2/terminfo/screeninfo.src
  86. #    515 -rw-r--r-- screen3.2/terminfo/screencap
  87. #    671 -rw-r--r-- screen3.2/terminfo/screenwinfo.src
  88. #    768 -rw-r--r-- screen3.2/terminfo/getwinsize.c
  89. #   3056 -rw------- screen3.2/terminfo/screen-sco.src
  90. #  38899 -rw-rw-r-- screen3.2/terminfo/test.txt
  91. #   7535 -rw-r--r-- screen3.2/.iscreenrc
  92. #   3741 -r--r--r-- screen3.2/readme
  93. #   3036 -r--r--r-- screen3.2/README
  94. #   1377 -r--r--r-- screen3.2/Makefile
  95. #   1450 -rw-rw-r-- screen3.2/INSTALLATION
  96. #   9292 -r--r--r-- screen3.2/CHANGES
  97. #   9934 -rw-r--r-- screen3.2/COPYING
  98. #   1389 -rw-rw-r-- screen3.2/poster
  99. #   8666 -r--r--r-- screen3.2/config/config.all
  100. #    908 -r--r--r-- screen3.2/config/config.apollo
  101. #   1385 -r--r--r-- screen3.2/config/config.bsd386
  102. #    986 -r--r--r-- screen3.2/config/config.gould_np1
  103. #    841 -r--r--r-- screen3.2/config/config.hpux
  104. #   1213 -r--r--r-- screen3.2/config/config.isc
  105. #    940 -r--r--r-- screen3.2/config/config.mips
  106. #   1043 -r--r--r-- screen3.2/config/config.mot88
  107. #   1010 -r--r--r-- screen3.2/config/config.next
  108. #    879 -r--r--r-- screen3.2/config/config.rs600
  109. #    920 -r--r--r-- screen3.2/config/config.rs6000
  110. #   1314 -r--r--r-- screen3.2/config/config.sco32
  111. #   1007 -r--r--r-- screen3.2/config/config.sequent_ptx
  112. #   1071 -r--r--r-- screen3.2/config/config.sgi
  113. #   1000 -r--r--r-- screen3.2/config/config.sunos41
  114. #   1422 -r--r--r-- screen3.2/config/config.svr4
  115. #    993 -r--r--r-- screen3.2/config/config.symmetry
  116. #   1061 -r--r--r-- screen3.2/config/config.sysv68
  117. #   1174 -r--r--r-- screen3.2/config/config.ultrix4
  118. #    992 -r--r--r-- screen3.2/config/config.xelos
  119. #   1056 -r--r--r-- screen3.2/config/config.xenix
  120. #   1508 -r--r--r-- screen3.2/config/Makefile.bsd386
  121. #   1479 -r--r--r-- screen3.2/config/Makefile.gould_np1
  122. #   1073 -r--r--r-- screen3.2/config/Makefile.isc
  123. #   1626 -r--r--r-- screen3.2/config/Makefile.mips
  124. #   1545 -r--r--r-- screen3.2/config/Makefile.putenv
  125. #   1455 -r--r--r-- screen3.2/config/Makefile.rs6000
  126. #   1372 -r--r--r-- screen3.2/config/Makefile.sco32
  127. #   1466 -r--r--r-- screen3.2/config/Makefile.sgi
  128. #   1435 -r--r--r-- screen3.2/config/Makefile.svr4
  129. #   1485 -r--r--r-- screen3.2/config/Makefile.ultrix4
  130. #   1936 -r--r--r-- screen3.2/config/Makefile.xenix
  131. #   3523 -rw-rw-r-- screen3.2/etcscreenrc
  132. #
  133. if test -r _shar_seq_.tmp; then
  134.     echo 'Must unpack archives in sequence!'
  135.     echo Please unpack part `cat _shar_seq_.tmp` next
  136.     exit 1
  137. fi
  138. # ============= screen3.2/ansi.c ==============
  139. if test ! -d 'screen3.2'; then
  140.     echo 'x - creating directory screen3.2'
  141.     mkdir 'screen3.2'
  142. fi
  143. if test -f 'screen3.2/ansi.c' -a X"$1" != X"-c"; then
  144.     echo 'x - skipping screen3.2/ansi.c (File already exists)'
  145.     rm -f _shar_wnt_.tmp
  146. else
  147. > _shar_wnt_.tmp
  148. echo 'x - extracting screen3.2/ansi.c (Text)'
  149. sed 's/^X//' << 'SHAR_EOF' > 'screen3.2/ansi.c' &&
  150. /* Copyright (c) 1991
  151. X *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  152. X *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  153. X * Copyright (c) 1987 Oliver Laumann
  154. X * All rights reserved.  Not derived from licensed software.
  155. X *
  156. X * Permission is granted to freely use, copy, modify, and redistribute
  157. X * this software, provided that no attempt is made to gain profit from it,
  158. X * the authors are not construed to be liable for any results of using the
  159. X * software, alterations are clearly marked as such, and this notice is
  160. X * not modified.
  161. X *
  162. X * Noteworthy contributors to screen's design and implementation:
  163. X *    Wayne Davison (davison@borland.com)
  164. X *    Patrick Wolfe (pat@kai.com, kailand!pat)
  165. X *    Bart Schaefer (schaefer@cse.ogi.edu)
  166. X *    Nathan Glasser (nathan@brokaw.lcs.mit.edu)
  167. X *    Larry W. Virden (lwv27%cas.BITNET@CUNYVM.CUNY.Edu)
  168. X *    Howard Chu (hyc@hanauma.jpl.nasa.gov)
  169. X *    Tim MacKenzie (tym@dibbler.cs.monash.edu.au)
  170. X *    Markku Jarvinen (mta@{cc,cs,ee}.tut.fi)
  171. X *    Marc Boucher (marc@CAM.ORG)
  172. X *
  173. X ****************************************************************
  174. X */
  175. X
  176. #ifndef lint
  177. X  static char rcs_id[] = "$Id: ansi.c,v 1.2 92/02/03 02:27:30 jnweiger Exp $ FAU";
  178. #endif
  179. X
  180. #include <stdio.h>
  181. #include <sys/types.h>
  182. #ifdef BSDI
  183. #include <sys/signal.h>
  184. #endif /* BSDI */
  185. #include <fcntl.h>
  186. #include "config.h"
  187. #include "screen.h"
  188. #include "ansi.h"
  189. #include "extern.h"
  190. #ifndef sun /* we want to know about TIOCGWINSZ. jw. */
  191. # include <sys/ioctl.h>
  192. #endif
  193. X
  194. extern char *getenv(), *tgetstr(), *tgoto();
  195. #ifndef __STDC__
  196. extern char *malloc();
  197. #endif
  198. X
  199. extern struct win *fore;
  200. extern int ForeNum;
  201. extern force_vt, assume_LP;
  202. extern int BellDisplayed;
  203. extern int MsgMinWait;
  204. extern int all_norefresh;
  205. X
  206. int TermcapROWS, TermcapCOLS;    /* defaults that we learned from termcap */
  207. int default_width, default_height;    /* width/height a new window will get */
  208. X
  209. int maxwidth;
  210. X
  211. int Z0width, Z1width;        /* widths for Z0/Z1 switching */
  212. X
  213. char display_tty[MAXPATH];
  214. int screenwidth, screenheight;    /* width/height of the screen */
  215. int screentop, screenbot;    /* scrollregion start/end */
  216. int screenx, screeny;        /* cursor position */
  217. char GlobalAttr;        /* current attributes */
  218. char GlobalCharset;        /* current font */
  219. int insert;            /* insert mode */
  220. int keypad;            /* application keypad */
  221. int flow = 1;            /* flow control */
  222. X
  223. int status;            /* status is displayed */
  224. static int status_lastx, status_lasty;
  225. X
  226. static int rows, cols;        /* window size of the curr window */
  227. X
  228. int default_flow = -1, wrap = 1, default_monitor = 0; 
  229. int visual_bell = 0, termcapHS, use_hardstatus = 1;
  230. char *Termcap, *extra_incap, *extra_outcap;
  231. static int Termcaplen;
  232. char *blank, *null, *LastMsg;
  233. char Term[MAXSTR+5];    /* +5: "TERM=" */
  234. char screenterm[20] = "screen";
  235. char *Z0, *Z1;
  236. int ISO2022, HS;
  237. time_t TimeDisplayed, time();
  238. X
  239. /*
  240. X * the termcap routines need this to work
  241. X */
  242. short ospeed;
  243. char *BC;
  244. char *UP;
  245. X
  246. static void AddCap __P((char *));
  247. static void MakeString __P((char *, char *, int, char *));
  248. static int Special __P((int));
  249. static void DoESC __P((int, int ));
  250. static void DoCSI __P((int, int ));
  251. static void CPutStr __P((char *, int));
  252. static void SetChar __P(());
  253. static void StartString __P((enum string_t));
  254. static void AddChar __P((int ));
  255. static void PrintChar __P((int ));
  256. static void PrintFlush __P((void));
  257. static void KeypadMode __P((int));
  258. static void DesignateCharset __P((int, int ));
  259. static void MapCharset __P((int));
  260. static void SaveCursor __P((void));
  261. static void RestoreCursor __P((void));
  262. static void CountChars __P((int));
  263. static int CalcCost __P((char *));
  264. static int Rewrite __P((int, int, int, int));
  265. static void BackSpace __P((void));
  266. static void Return __P((void));
  267. static void LineFeed __P((int));
  268. static void ReverseLineFeed __P((void));
  269. static void InsertAChar __P((int));
  270. static void InsertChar __P((int));
  271. static void DeleteChar __P((int));
  272. static void DeleteLine __P((int));
  273. static void InsertLine __P((int));
  274. static void ScrollUpMap __P((int));
  275. static void ScrollDownMap __P((int));
  276. static void Scroll __P((char *, int, int, char *));
  277. static void ForwardTab __P((void));
  278. static void BackwardTab __P((void));
  279. static void ClearScreen __P((void));
  280. static void ClearFromBOS __P((void));
  281. static void ClearToEOS __P((void));
  282. static void ClearLine __P((void));
  283. static void ClearToEOL __P((void));
  284. static void ClearFromBOL __P((void));
  285. static void ClearInLine __P((int, int, int, int ));
  286. static void CursorRight __P(());
  287. static void CursorUp __P(());
  288. static void CursorDown __P(());
  289. static void CursorLeft __P(());
  290. static void ASetMode __P((int));
  291. static void SelectRendition __P((void));
  292. static void FillWithEs __P((void));
  293. static void RedisplayLine __P((char *, char *, char *, int, int, int ));
  294. static void FindAKA __P((void));
  295. static void SetCurr __P((struct win *));
  296. static void inpRedisplayLine __P((int, int, int, int));
  297. static void process_inp_input __P((char **, int *));
  298. static void AbortInp __P((void));
  299. static void AKAfin __P((char *, int));
  300. static void Colonfin __P((char *, int));
  301. static void RAW_PUTCHAR __P((int));
  302. static char *e_tgetstr __P((char *, char **));
  303. static int e_tgetflag __P((char *));
  304. static int e_tgetnum __P((char *));
  305. X
  306. X
  307. static char *tbuf, *tentry, *termname;
  308. static char *tp;
  309. static char *TI, *TE, *BL, *VB, *CR, *NL, *CL, *IS;
  310. char *WS;    /* used in ResizeScreen() */
  311. char *CE;    /* used in help.c */
  312. static char *CM, *US, *UE, *SO, *SE, *CD, *DO, *SR, *SF, *AL;
  313. static char *CS, *DL, *DC, *IC, *IM, *EI, *ND, *KS, *KE;
  314. static char *MB, *MD, *MH, *MR, *ME, *PO, *PF, *HO;
  315. static char *TS, *FS, *DS, *VI, *VE, *VS;
  316. static char *CDC, *CDL, *CAL, *CUP, *CDO, *CLE, *CRI, *CIC;
  317. static char *attrtab[NATTR];
  318. static AM, MS, COP;
  319. int LP;
  320. /*
  321. X * Do not confuse S0 (es-zero), E0 (e-zero) with SO (es-oh), PO (pe-oh),
  322. X * Z0 (z-zero), DO (de-oh)... :-)
  323. X */
  324. static char *C0, *S0, *E0;
  325. static char c0_tab[256];
  326. /*
  327. X */
  328. static screencap = 0;
  329. char *OldImage, *OldAttr, *OldFont;
  330. static struct win *curr;
  331. static display = 1;
  332. static StrCost;
  333. static UPcost, DOcost, LEcost, NDcost, CRcost, IMcost, EIcost, NLcost;
  334. static tcLineLen;
  335. static StatLen;
  336. static lp_missing = 0;
  337. X
  338. int in_ovl;
  339. int ovl_blockfore;
  340. void (*ovl_process)();
  341. void (*ovl_RedisplayLine)();
  342. int (*ovl_Rewrite)();
  343. X
  344. static char *KeyCaps[] =
  345. {
  346. X  "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7", "k8", "k9",
  347. X  "kb", "kd", "kh", "kl", "ko", "kr", "ku",
  348. X  "K1", "K2", "K3", "K4", "K5",
  349. X  "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", "l8", "l9"
  350. };
  351. #define NKEYCAPS ((int)(sizeof(KeyCaps)/sizeof(*KeyCaps)))
  352. static char *KeyCapsArr[NKEYCAPS];
  353. X
  354. static char TermcapConst[] = "\\\n\
  355. \t:DO=\\E[%dB:LE=\\E[%dD:RI=\\E[%dC:UP=\\E[%dA:bs:bt=\\E[Z:\\\n\
  356. \t:cd=\\E[J:ce=\\E[K:cl=\\E[H\\E[J:cm=\\E[%i%d;%dH:ct=\\E[3g:\\\n\
  357. \t:do=^J:nd=\\E[C:pt:rc=\\E8:rs=\\Ec:sc=\\E7:st=\\EH:up=\\EM:\\\n\
  358. \t:le=^H:bl=^G:cr=^M:it#8:ho=\\E[H:nw=\\EE:ta=^I:is=\\E)0:xv:";
  359. X
  360. void
  361. InitTermcap()
  362. {
  363. X  register char *s;
  364. X  int i;
  365. X
  366. X  screencap = 0;
  367. X  if ((s = getenv("SCREENCAP")) != 0)
  368. X    {
  369. X      if ((Termcap = malloc(strlen(s) + 10)) != 0)
  370. X    {
  371. X      sprintf(Termcap, "TERMCAP=%s", s);
  372. X      screencap = 1;
  373. X    }
  374. X    }
  375. X  else
  376. X    Termcap = malloc((unsigned) 1024);
  377. X  Termcaplen = 0;
  378. X  tbuf = malloc((unsigned) 1024);
  379. X  tentry = tp = malloc((unsigned) 1024);
  380. X  if (!(Termcap && tbuf && tentry))
  381. X    Msg_nomem;
  382. X  bzero(tbuf, 1024);
  383. X  if ((termname = getenv("TERM")) == 0)
  384. X    Msg(0, "No TERM in environment.");
  385. X  debug1("InitTermcap: looking for tgetent('%s');\n", termname);
  386. X  if (tgetent(tbuf, termname) != 1)
  387. X    Msg(0, "Cannot find termcap entry for %s.", termname);
  388. X  debug1("got it:\n%s\n",tbuf);
  389. #ifdef DEBUG
  390. X  if (extra_incap)
  391. X    debug1("Extra incap: %s\n", extra_incap);
  392. X  if (extra_outcap)
  393. X    debug1("Extra outcap: %s\n", extra_outcap);
  394. #endif
  395. X
  396. X  TermcapCOLS = TermcapROWS = 0;
  397. X  if (s = getenv("COLUMNS"))
  398. X    TermcapCOLS = atoi(s);
  399. X  if (TermcapCOLS <= 0)
  400. X    TermcapCOLS = e_tgetnum("co");
  401. X  if (TermcapCOLS <= 0)
  402. X    TermcapCOLS = 80;
  403. X  if (s = getenv("LINES"))
  404. X    TermcapROWS = atoi(s);
  405. X  if (TermcapROWS <= 0)
  406. X    TermcapROWS = e_tgetnum("li");
  407. X  if (TermcapROWS <= 0)
  408. X    TermcapROWS = 24;
  409. X
  410. X  if (e_tgetflag("hc"))
  411. X    Msg(0, "You can't run screen on a hardcopy terminal.");
  412. X  if (e_tgetflag("os"))
  413. X    Msg(0, "You can't run screen on a terminal that overstrikes.");
  414. X  if (e_tgetflag("ns"))
  415. X    Msg(0, "Terminal must support scrolling.");
  416. X  if (!(CL = e_tgetstr("cl", &tp)))
  417. X    Msg(0, "Clear screen capability required.");
  418. X  if (!(CM = e_tgetstr("cm", &tp)))
  419. X    Msg(0, "Addressable cursor capability required.");
  420. X  if (default_flow < 0)
  421. X    default_flow = e_tgetflag("NF") ? FLOW_NOW * 0 : 
  422. X           e_tgetflag("xo") ? FLOW_NOW * 1 :
  423. X           FLOW_AUTOFLAG;
  424. X  AM = e_tgetflag("am");
  425. X  LP = assume_LP || (!extra_incap && !strncmp(termname, "vt", 2))
  426. X           || !AM || e_tgetflag("LP") || e_tgetflag("xv");
  427. X  COP = e_tgetflag("OP");
  428. X  HO = e_tgetstr("ho", &tp);
  429. X  TI = e_tgetstr("ti", &tp);
  430. X  TE = e_tgetstr("te", &tp);
  431. X  if (!(BL = e_tgetstr("bl", &tp)))
  432. X    BL = "\007";
  433. X  VB = e_tgetstr("vb", &tp);
  434. X  if (!(BC = e_tgetstr("bc", &tp)))
  435. X    {
  436. X      if (e_tgetflag("bs"))
  437. X    BC = "\b";
  438. X      else
  439. X    BC = e_tgetstr("le", &tp);
  440. X    }
  441. X  if (!(CR = e_tgetstr("cr", &tp)))
  442. X    CR = "\r";
  443. X  if (!(NL = e_tgetstr("nl", &tp)))
  444. X    NL = "\n";
  445. X  IS = e_tgetstr("is", &tp);
  446. X  MS = 1;
  447. X  if (e_tgetnum("sg") <= 0 && e_tgetnum("ug") <= 0)
  448. X    {
  449. X      MS = e_tgetflag("ms");
  450. X      attrtab[ATTR_DI] = MH = e_tgetstr("mh", &tp);    /* Dim */
  451. X      attrtab[ATTR_US] = US = e_tgetstr("us", &tp);    /* Underline */
  452. X      attrtab[ATTR_BD] = MD = e_tgetstr("md", &tp);    /* Bold */
  453. X      attrtab[ATTR_RV] = MR = e_tgetstr("mr", &tp);    /* Reverse */
  454. X      attrtab[ATTR_SO] = SO = e_tgetstr("so", &tp);    /* Standout */
  455. X      attrtab[ATTR_BL] = MB = e_tgetstr("mb", &tp);    /* Blinking */
  456. X      ME = e_tgetstr("me", &tp);
  457. X      SE = e_tgetstr("se", &tp);
  458. X      UE = e_tgetstr("ue", &tp);
  459. X      /*
  460. X       * Does ME also reverse the effect of SO and/or US?  This is not
  461. X       * clearly specified by the termcap manual. Anyway, we should at
  462. X       * least look whether ME and SE/UE are equal:
  463. X       */
  464. X      if (UE && ((SE && strcmp(SE, UE) == 0) || (ME && strcmp(ME, UE) == 0)))
  465. X    UE = 0;
  466. X      if (SE && (ME && strcmp(ME, SE) == 0))
  467. X    SE = 0;
  468. X
  469. X      /* Set up missing entries */
  470. X      s = 0;
  471. X      for (i = NATTR-1; i >= 0; i--)
  472. X    if (attrtab[i])
  473. X      s = attrtab[i];
  474. X      for (i = 0; i < NATTR; i++)
  475. X    {
  476. X      if (attrtab[i] == 0)
  477. X        attrtab[i] = s;
  478. X      else
  479. X        s = attrtab[i];
  480. X    }
  481. X    }
  482. X  else
  483. X    {
  484. X      US = UE = SO = SE = MB = MD = MH = MR = ME = 0;
  485. X      for (i = 0; i < NATTR; i++)
  486. X    attrtab[i] = 0;
  487. X    }
  488. X  CE = e_tgetstr("ce", &tp);
  489. X  CD = e_tgetstr("cd", &tp);
  490. X  if (!(DO = e_tgetstr("do", &tp)))
  491. X    DO = NL;
  492. X  UP = e_tgetstr("up", &tp);
  493. X  ND = e_tgetstr("nd", &tp);
  494. X  SR = e_tgetstr("sr", &tp);
  495. X  if (!(SF = e_tgetstr("sf", &tp)))
  496. X    SF = NL;
  497. X  AL = e_tgetstr("al", &tp);
  498. X  DL = e_tgetstr("dl", &tp);
  499. X  CS = e_tgetstr("cs", &tp);
  500. X  DC = e_tgetstr("dc", &tp);
  501. X  IC = e_tgetstr("ic", &tp);
  502. X  CIC = e_tgetstr("IC", &tp);
  503. X  CDC = e_tgetstr("DC", &tp);
  504. X  CDL = e_tgetstr("DL", &tp);
  505. X  CAL = e_tgetstr("AL", &tp);
  506. X  CUP = e_tgetstr("UP", &tp);
  507. X  CDO = e_tgetstr("DO", &tp);
  508. X  CLE = e_tgetstr("LE", &tp);
  509. X  CRI = e_tgetstr("RI", &tp);
  510. X  IM = e_tgetstr("im", &tp);
  511. X  EI = e_tgetstr("ei", &tp);
  512. X  if (e_tgetflag("in"))
  513. X    IC = IM = 0;
  514. X  if (IC && IC[0] == '\0')
  515. X    IC = 0;
  516. X  if (CIC && CIC[0] == '\0')
  517. X    CIC = 0;
  518. X  if (IM && IM[0] == '\0')
  519. X    IM = 0;
  520. X  if (EI && EI[0] == '\0')
  521. X    EI = 0;
  522. X  if (EI == 0)
  523. X    IM = 0;
  524. X  if (IC && IM && strcmp(IC, IM) == 0)
  525. X    IC = 0;
  526. X  KS = e_tgetstr("ks", &tp);
  527. X  KE = e_tgetstr("ke", &tp);
  528. X  if (KE == 0)
  529. X    KS = 0;
  530. X  ISO2022 = e_tgetflag("G0");
  531. X  if (ISO2022)
  532. X    {
  533. X      if ((S0 = e_tgetstr("S0", &tp)) == NULL)
  534. #ifdef TERMINFO
  535. X    S0 = "\033(%p1%c";
  536. #else
  537. X    S0 = "\033(%.";
  538. #endif
  539. X      if ((E0 = e_tgetstr("E0", &tp)) == NULL)
  540. X    E0 = "\033(B";
  541. X      C0 = e_tgetstr("C0", &tp);
  542. X    }
  543. X  else if ((S0 = e_tgetstr("as", &tp)) != NULL
  544. X        && (E0 = e_tgetstr("ae", &tp)) != NULL)
  545. X    {
  546. X      ISO2022 = 1;
  547. X      C0 = e_tgetstr("ac", &tp);
  548. X    }
  549. X  else
  550. X    {
  551. X      S0 = E0 = "";
  552. X      C0 = "g.h.i'j-k-l-m-n+o~p\"q-r-s_t+u+v+w+x|y<z>";
  553. X    }
  554. X  for (i = 0; i < 256; i++)
  555. X    c0_tab[i] = i;
  556. X  if (C0)
  557. X    for (i = strlen(C0)&~1; i >= 0; i-=2)
  558. X      c0_tab[C0[i]] = C0[i+1];
  559. X  debug1("ISO2022 = %d\n", ISO2022);
  560. X  /* WS changes the window size */
  561. X  WS = e_tgetstr("WS", &tp);
  562. X  VI = e_tgetstr("vi", &tp);
  563. X  VE = e_tgetstr("ve", &tp);
  564. X  VS = e_tgetstr("vs", &tp);
  565. X  PO = e_tgetstr("po", &tp);
  566. X  if (!(PF = e_tgetstr("pf", &tp)))
  567. X    PO = 0;
  568. X  debug2("terminal size is %d, %d (says TERMCAP)\n", TermcapCOLS, TermcapROWS);
  569. X  /* Termcap fields Z0 & Z1 contain width-changing sequences. */
  570. X  if ((Z0 = e_tgetstr("Z0", &tp)) != NULL
  571. X      && (Z1 = e_tgetstr("Z1", &tp)) == NULL)
  572. X    Z0 = NULL;
  573. X
  574. X  Z0width = 132;
  575. X  Z1width = 80;
  576. X
  577. X  CheckScreenSize(0);
  578. X  if ((HS = e_tgetflag("hs")) != 0)
  579. X    {
  580. X      debug("oy! we have a hardware status line, says termcap\n");
  581. X      TS = e_tgetstr("ts", &tp);
  582. X      FS = e_tgetstr("fs", &tp);
  583. X      DS = e_tgetstr("ds", &tp);
  584. X      if ((HS = e_tgetnum("ws")) <= 0)
  585. X    HS = screenwidth;
  586. X      if (!TS || !FS || !DS)
  587. X    HS = 0;
  588. X    }
  589. X  termcapHS = HS;
  590. X  if (!use_hardstatus)
  591. X    HS = 0;
  592. X
  593. X  UPcost = CalcCost(UP);
  594. X  DOcost = CalcCost(DO);
  595. X  NLcost = CalcCost(NL);
  596. X  LEcost = CalcCost(BC);
  597. X  NDcost = CalcCost(ND);
  598. X  CRcost = CalcCost(CR);
  599. X  IMcost = CalcCost(IM);
  600. X  EIcost = CalcCost(EI);
  601. X  for (i = 0; i < NKEYCAPS; i++)
  602. X    KeyCapsArr[i] = e_tgetstr(KeyCaps[i], &tp);
  603. X  MakeTermcap(0);
  604. }
  605. X
  606. /*
  607. X * if the adaptflag is on, we keep the size of this display, else
  608. X * we may try to restore our old window sizes.
  609. X */
  610. void
  611. InitTerm(adapt)
  612. int adapt;
  613. {
  614. X  display = 1;
  615. X  screentop = screenbot = -1;
  616. X  PutStr(IS);
  617. X  PutStr(TI);
  618. X  if (IM && strcmp(IM, EI))
  619. X    PutStr(EI);
  620. X  insert = 0;
  621. X  if (KS && strcmp(KS, KE))
  622. X    PutStr(KE);
  623. X  keypad = 0;
  624. X  PutStr(E0);
  625. X  GlobalCharset = ASCII;
  626. X  ResizeScreen((struct win *)0);
  627. X  ChangeScrollRegion(0, screenheight-1);
  628. X  PutStr(CL);
  629. X  screenx = screeny = 0;
  630. X  fflush(stdout);
  631. X  debug1("we %swant to adapt all our windows to the display\n", 
  632. X     (adapt) ? "" : "don't ");
  633. X  /* In case the size was changed by a init sequence */
  634. X  CheckScreenSize((adapt) ? 2 : 0);
  635. }
  636. X
  637. void
  638. FinitTerm()
  639. {
  640. X  display = 1;
  641. X  InsertMode(0);
  642. X  KeypadMode(0);
  643. X  ResizeScreen((struct win *)0);
  644. X  ChangeScrollRegion(0, screenheight - 1);
  645. X  SaveSetAttr(0, ASCII);
  646. X  screenx = screeny = -1;
  647. X  GotoPos(0, screenheight - 1);
  648. X  PutStr(TE);
  649. X  fflush(stdout);
  650. X  if (Termcap) 
  651. X    {
  652. X      Free(Termcap);
  653. X      debug("FinitTerm: old termcap freed\n");
  654. X    }
  655. X  if (tbuf) 
  656. X    {
  657. X      Free(tbuf);
  658. X      debug("FinitTerm: old tbuf freed\n");
  659. X    }
  660. X  if (tentry) 
  661. X    {
  662. X      Free(tentry);
  663. X      debug("FinitTerm: old tentry freed\n");
  664. X    }
  665. }
  666. X
  667. static void AddCap(s)
  668. char *s;
  669. {
  670. X  register int n;
  671. X
  672. X  if (tcLineLen + (n = strlen(s)) > 55 && Termcaplen < 1024-4)
  673. X    {
  674. X      strcpy(Termcap + Termcaplen, "\\\n\t:");
  675. X      Termcaplen += 4;
  676. X      tcLineLen = 0;
  677. X    }
  678. X  if (Termcaplen + n < 1024)
  679. X    {
  680. X      strcpy(Termcap + Termcaplen, s);
  681. X      Termcaplen += n;
  682. X      tcLineLen += n;
  683. X    }
  684. X  else
  685. X    Msg(0, "TERMCAP overflow - sorry.");
  686. }
  687. X
  688. char *MakeTermcap(aflag)
  689. int aflag;
  690. {
  691. X  char buf[1024];
  692. X  register char *p, *cp, ch;
  693. X  int i;
  694. X
  695. X  if (screencap)
  696. X    {
  697. X      sprintf(Term, "TERM=screen");
  698. X      return Termcap;
  699. X    }
  700. X  if (screenterm == 0 || *screenterm == '\0')
  701. X    {
  702. X      debug("MakeTermcap sets screenterm=screen\n");
  703. X      strcpy(screenterm, "screen");
  704. X    }
  705. X  for (;;)
  706. X    {
  707. X      sprintf(Term, "TERM=");
  708. X      p = Term + 5;
  709. X      if (!aflag && strlen(screenterm) + strlen(termname) < MAXSTR-1)
  710. X    {
  711. X      sprintf(p, "%s.%s", screenterm, termname);
  712. X      if (tgetent(buf, p) == 1)
  713. X        break;
  714. X    }
  715. X      if (screenwidth >= 132)
  716. X    {
  717. X      sprintf(p, "%s-w", screenterm);
  718. X          if (tgetent(buf, p) == 1)
  719. X        break;
  720. X    }
  721. X      sprintf(p, "%s", screenterm);
  722. X      if (tgetent(buf, p) == 1)
  723. X    break;
  724. X      sprintf(p, "vt100");
  725. X      break;
  726. X    }
  727. X  tcLineLen = 100;    /* Force NL */
  728. X  sprintf(Termcap,
  729. X      "TERMCAP=SC|%s|VT 100/ANSI X3.64 virtual terminal|", p);
  730. X  Termcaplen = strlen(Termcap);
  731. X  if (extra_outcap && *extra_outcap)
  732. X    {
  733. X      for (cp = extra_outcap; p = index(cp, ':'); cp = p)
  734. X    {
  735. X      ch = *++p;
  736. X      *p = '\0';
  737. X      AddCap(cp);
  738. X      *p = ch;
  739. X    }
  740. X      tcLineLen = 100;    /* Force NL */
  741. X    }
  742. X  if (Termcaplen + strlen(TermcapConst) < 1024)
  743. X    {
  744. X      strcpy(Termcap + Termcaplen, TermcapConst);
  745. X      Termcaplen += strlen(TermcapConst);
  746. X    }
  747. X  sprintf(buf, "li#%d:co#%d:", screenheight, screenwidth);
  748. X  AddCap(buf);
  749. X  if ((force_vt && !COP) || LP || !AM)
  750. X    AddCap("LP:");
  751. X  else
  752. X    AddCap("am:");
  753. X  if (VB)
  754. X    AddCap("vb=\\E[?5h\\E[?5l:");
  755. X  if (US)
  756. X    {
  757. X      AddCap("us=\\E[4m:");
  758. X      AddCap("ue=\\E[24m:");
  759. X    }
  760. X  if (SO)
  761. X    {
  762. X      AddCap("so=\\E[3m:");
  763. X      AddCap("se=\\E[23m:");
  764. X    }
  765. X  if (MB)
  766. X    AddCap("mb=\\E[5m:");
  767. X  if (MD)
  768. X    AddCap("md=\\E[1m:");
  769. X  if (MH)
  770. X    AddCap("mh=\\E[2m:");
  771. X  if (MR)
  772. X    AddCap("mr=\\E[7m:");
  773. X  if (MB || MD || MH || MR)
  774. X    AddCap("me=\\E[m:ms:");
  775. X  if ((CS && SR) || AL || CAL || aflag)
  776. X    {
  777. X      AddCap("sr=\\EM:");
  778. X      AddCap("al=\\E[L:");
  779. X      AddCap("AL=\\E[%dL:");
  780. X    }
  781. X  else if (SR)
  782. X    AddCap("sr=\\EM:");
  783. X  if (CS || DL || CDL || aflag)
  784. X    {
  785. X      AddCap("dl=\\E[M:");
  786. X      AddCap("DL=\\E[%dM:");
  787. X    }
  788. X  if (CS)
  789. X    AddCap("cs=\\E[%i%d;%dr:");
  790. X  if (DC || CDC || aflag)
  791. X    {
  792. X      AddCap("dc=\\E[P:");
  793. X      AddCap("DC=\\E[%dP:");
  794. X    }
  795. X  if (CIC || IC || IM || aflag)
  796. X    {
  797. X      AddCap("im=\\E[4h:");
  798. X      AddCap("ei=\\E[4l:");
  799. X      AddCap("mi:");
  800. X      AddCap("ic=\\E[@:");
  801. X      AddCap("IC=\\E[%d@:");
  802. X    }
  803. X  if (KS)
  804. X    AddCap("ks=\\E=:");
  805. X  if (KE)
  806. X    AddCap("ke=\\E>:");
  807. X  if (ISO2022)
  808. X    AddCap("G0:");
  809. X  if (PO)
  810. X    {
  811. X      AddCap("po=\\E[5i:");
  812. X      AddCap("pf=\\E[4i:");
  813. X    }
  814. X  if (Z0)
  815. X    {
  816. X      AddCap("Z0=\\E[?3h:");
  817. X      AddCap("Z1=\\E[?3l:");
  818. X    }
  819. X  if (WS)
  820. X    AddCap("WS=\\E[8;%d;%dt:");
  821. X  for (i = 0; i < NKEYCAPS; i++)
  822. X    {
  823. X      if (KeyCapsArr[i] == 0)
  824. X    continue;
  825. X      MakeString(KeyCaps[i], buf, sizeof(buf), KeyCapsArr[i]);
  826. X      AddCap(buf);
  827. X    }
  828. X  return Termcap;
  829. }
  830. X
  831. static void MakeString(cap, buf, buflen, s)
  832. char *cap, *buf;
  833. int buflen;
  834. char *s;
  835. {
  836. X  register char *p, *pmax;
  837. X  register unsigned int c;
  838. X
  839. X  p = buf;
  840. X  pmax = p + buflen - (3+4+2);
  841. X  *p++ = *cap++;
  842. X  *p++ = *cap;
  843. X  *p++ = '=';
  844. X  while ((c = *s++) && (p < pmax))
  845. X    {
  846. X      switch (c)
  847. X    {
  848. X    case '\033':
  849. X      *p++ = '\\';
  850. X      *p++ = 'E';
  851. X      break;
  852. X    case ':':
  853. X      sprintf(p, "\\072");
  854. X      p += 4;
  855. X      break;
  856. X    case '^':
  857. X    case '\\':
  858. X      *p++ = '\\';
  859. X      *p++ = c;
  860. X      break;
  861. X    default:
  862. X      if (c >= 200)
  863. X        {
  864. X          sprintf(p, "\\%03o", c & 0377);
  865. X          p += 4;
  866. X        }
  867. X      else if (c < ' ')
  868. X        {
  869. X          *p++ = '^';
  870. X          *p++ = c + '@';
  871. X        }
  872. X      else
  873. X        *p++ = c;
  874. X    }
  875. X    }
  876. X  *p++ = ':';
  877. X  *p = '\0';
  878. }
  879. X
  880. void
  881. Activate(norefresh)
  882. int norefresh;
  883. {
  884. X  debug1("Activate(%d)\n", norefresh);
  885. X  if (display)
  886. X    RemoveStatus();
  887. X  display = fore->active = 1;
  888. X  ResizeScreen(fore);
  889. X  SetCurr(fore);
  890. X  debug3("Fore (%d) has size %dx%d", ForeNum, curr->width, curr->height);
  891. X  debug1("(%d)\n", curr->histheight);
  892. X  ChangeScrollRegion(curr->top, curr->bot);
  893. X  KeypadMode(curr->keypad);
  894. X  SetFlow(curr->flow & FLOW_NOW);
  895. X  if (curr->monitor != MON_OFF)
  896. X    curr->monitor = MON_ON;
  897. X  curr->bell = BELL_OFF;
  898. X  Redisplay(norefresh || all_norefresh);
  899. }
  900. X
  901. void
  902. ResetScreen(p)
  903. register struct win *p;
  904. {
  905. X  register int i;
  906. X
  907. X  p->wrap = wrap;
  908. X  p->origin = 0;
  909. X  p->insert = 0;
  910. X  p->vbwait = 0;
  911. X  p->keypad = 0;
  912. X  p->top = 0;
  913. X  p->bot = p->height - 1;
  914. X  p->saved = 0;
  915. X  p->LocalAttr = 0;
  916. X  p->x = p->y = 0;
  917. X  p->state = LIT;
  918. X  p->StringType = NONE;
  919. X  p->ss = 0;
  920. X  p->LocalCharset = G0;
  921. X  bzero(p->tabs, p->width);
  922. X  for (i = 8; i < p->width; i += 8)
  923. X    p->tabs[i] = 1;
  924. X  for (i = G0; i <= G3; i++)
  925. X    p->charsets[i] = ASCII;
  926. }
  927. X
  928. void
  929. WriteString(wp, buf, len)
  930. struct win *wp;
  931. char *buf;
  932. int len;
  933. {
  934. X  register int c, intermediate = 0;
  935. X
  936. X  if (!len)
  937. X    return;
  938. X  if (wp->logfp != NULL)
  939. X    if ((int)fwrite(buf, len, 1, wp->logfp) < 1)
  940. X      {
  941. X    extern int errno;
  942. X
  943. X    Msg(errno, "Error writing logfile");
  944. X    fclose(wp->logfp);
  945. X    wp->logfp = NULL;
  946. X      }
  947. X  /*
  948. X   * SetCurr() here may prevent output, as it may set display = 0
  949. X   */
  950. X  SetCurr(wp);
  951. X  if (display)
  952. X    {
  953. X      if (!HS)
  954. X    RemoveStatus();
  955. X    }
  956. X  else if (curr->monitor == MON_ON)
  957. X    curr->monitor = MON_FOUND;
  958. X
  959. X  do
  960. X    {
  961. X      c = (unsigned char)*buf++;
  962. X      if (c == '\0' || c == '\177')
  963. X    continue;
  964. X    NextChar:
  965. X      switch (curr->state)
  966. X    {
  967. X    case PRIN:
  968. X      switch (c)
  969. X        {
  970. X        case '\033':
  971. X          curr->state = PRINESC;
  972. X          break;
  973. X        default:
  974. X          PrintChar(c);
  975. X        }
  976. X      break;
  977. X    case PRINESC:
  978. X      switch (c)
  979. X        {
  980. X        case '[':
  981. X          curr->state = PRINCSI;
  982. X          break;
  983. X        default:
  984. X          PrintChar('\033');
  985. X          PrintChar(c);
  986. X          curr->state = PRIN;
  987. X        }
  988. X      break;
  989. X    case PRINCSI:
  990. X      switch (c)
  991. X        {
  992. X        case '4':
  993. X          curr->state = PRIN4;
  994. X          break;
  995. X        default:
  996. X          PrintChar('\033');
  997. X          PrintChar('[');
  998. X          PrintChar(c);
  999. X          curr->state = PRIN;
  1000. X        }
  1001. X      break;
  1002. X    case PRIN4:
  1003. X      switch (c)
  1004. X        {
  1005. X        case 'i':
  1006. X          curr->state = LIT;
  1007. X          PrintFlush();
  1008. X          break;
  1009. X        default:
  1010. X          PrintChar('\033');
  1011. X          PrintChar('[');
  1012. X          PrintChar('4');
  1013. X          PrintChar(c);
  1014. X          curr->state = PRIN;
  1015. X        }
  1016. X      break;
  1017. X    case STRESC:
  1018. X      switch (c)
  1019. X        {
  1020. X        case '\\':
  1021. X          curr->state = LIT;
  1022. X          *(curr->stringp) = '\0';
  1023. X          switch (curr->StringType)
  1024. X        {
  1025. X        case PM:
  1026. X          if (!display)
  1027. X            break;
  1028. X          MakeStatus(curr->string);
  1029. X          if (!HS && status && len > 1)
  1030. X            {
  1031. X              curr->outlen = len - 1;
  1032. X              bcopy(buf, curr->outbuf, curr->outlen);
  1033. X              return;
  1034. X            }
  1035. X          break;
  1036. X        case DCS:
  1037. X          if (display)
  1038. X            printf("%s", curr->string);
  1039. X          break;
  1040. X        case AKA:
  1041. X          if (curr->akapos == 0 && !*curr->string)
  1042. X            break;
  1043. X          strncpy(curr->cmd + curr->akapos, curr->string, 20);
  1044. X          if (!*curr->string)
  1045. X            curr->autoaka = curr->y + 1;
  1046. X          break;
  1047. X        default:
  1048. X          break;
  1049. X        }
  1050. X          break;
  1051. X        default:
  1052. X          curr->state = ASTR;
  1053. X          AddChar('\033');
  1054. X          AddChar(c);
  1055. X        }
  1056. X      break;
  1057. X    case ASTR:
  1058. X      switch (c)
  1059. X        {
  1060. X        case '\0':
  1061. X          break;
  1062. X        case '\033':
  1063. X          curr->state = STRESC;
  1064. X          break;
  1065. X        default:
  1066. X          AddChar(c);
  1067. X        }
  1068. X      break;
  1069. X    case ESC:
  1070. X      switch (c)
  1071. X        {
  1072. X        case '[':
  1073. X          curr->NumArgs = 0;
  1074. X          intermediate = 0;
  1075. X          bzero((char *) curr->args, MAXARGS * sizeof(int));
  1076. X          curr->state = CSI;
  1077. X          break;
  1078. X        case ']':
  1079. X          StartString(OSC);
  1080. X          break;
  1081. X        case '_':
  1082. X          StartString(APC);
  1083. X          break;
  1084. X        case 'P':
  1085. X          StartString(DCS);
  1086. X          break;
  1087. X        case '^':
  1088. X          StartString(PM);
  1089. X          break;
  1090. X        case '"':
  1091. X        case 'k':
  1092. X          StartString(AKA);
  1093. X          break;
  1094. X        default:
  1095. X          if (Special(c))
  1096. X        break;
  1097. X          if (c >= ' ' && c <= '/')
  1098. X        intermediate = intermediate ? -1 : c;
  1099. X          else if (c >= '0' && c <= '~')
  1100. X        {
  1101. X          DoESC(c, intermediate);
  1102. X          curr->state = LIT;
  1103. X        }
  1104. X          else
  1105. X        {
  1106. X          curr->state = LIT;
  1107. X          goto NextChar;
  1108. X        }
  1109. X        }
  1110. X      break;
  1111. X    case CSI:
  1112. X      switch (c)
  1113. X        {
  1114. X        case '0':
  1115. X        case '1':
  1116. X        case '2':
  1117. X        case '3':
  1118. X        case '4':
  1119. X        case '5':
  1120. X        case '6':
  1121. X        case '7':
  1122. X        case '8':
  1123. X        case '9':
  1124. X          if (curr->NumArgs < MAXARGS)
  1125. X        {
  1126. X          curr->args[curr->NumArgs] =
  1127. X            10 * curr->args[curr->NumArgs] + c - '0';
  1128. X        }
  1129. X          break;
  1130. X        case ';':
  1131. X        case ':':
  1132. X          curr->NumArgs++;
  1133. X          break;
  1134. X        default:
  1135. X          if (Special(c))
  1136. X        break;
  1137. X          if (c >= '@' && c <= '~')
  1138. X        {
  1139. X          curr->NumArgs++;
  1140. X          DoCSI(c, intermediate);
  1141. X          if (curr->state != PRIN)
  1142. X            curr->state = LIT;
  1143. X        }
  1144. X          else if ((c >= ' ' && c <= '/') || (c >= '<' && c <= '?'))
  1145. X        intermediate = intermediate ? -1 : c;
  1146. X          else
  1147. X        {
  1148. X          curr->state = LIT;
  1149. X          goto NextChar;
  1150. X        }
  1151. X        }
  1152. X      break;
  1153. X    case LIT:
  1154. X    default:
  1155. X      if (!Special(c))
  1156. X        {
  1157. X          if (c == '\033')
  1158. X        {
  1159. X          intermediate = 0;
  1160. X          curr->state = ESC;
  1161. X          if (display && lp_missing && (CIC || IC || IM))
  1162. X            {
  1163. X              RedisplayLine(blank, null, null, screenbot,
  1164. X                    cols - 2, cols - 1);
  1165. X              GotoPos(curr->x, curr->y);
  1166. X            }
  1167. X          if (curr->autoaka < 0)
  1168. X            curr->autoaka = 0;
  1169. X        }
  1170. X          else if (c < ' ')
  1171. X        break;
  1172. X          else
  1173. X        {
  1174. X          NewRendition(curr->LocalAttr);
  1175. X          NewCharset(curr->charsets[(curr->ss) ? curr->ss :
  1176. X                         curr->LocalCharset]);
  1177. X          if (curr->x < cols - 1)
  1178. X            {
  1179. X              if (curr->insert)
  1180. X            InsertAChar(c);
  1181. X              else
  1182. X            {
  1183. X              if (display)
  1184. X                PUTCHAR(c);
  1185. X              SetChar(c);
  1186. X            }
  1187. X              curr->x++;
  1188. X            }
  1189. X          else if (curr->x == cols - 1)
  1190. X            {
  1191. X              if (curr->wrap && (LP || !force_vt || COP))
  1192. X            {
  1193. X              if (display)
  1194. X                RAW_PUTCHAR(c);
  1195. X              SetChar(c);
  1196. X              if (AM && !LP)
  1197. X                {
  1198. X                  curr->x = 0; /* terminal auto-wrapped */
  1199. X                  LineFeed(0);
  1200. X                }
  1201. X              else
  1202. X                curr->x++;
  1203. X            }
  1204. X              else
  1205. X            {
  1206. X              if (display)
  1207. X                {
  1208. X                  if (LP || curr->y != screenbot)
  1209. X                {
  1210. X                  RAW_PUTCHAR(c);
  1211. X                  GotoPos(curr->x, curr->y);
  1212. X                }
  1213. X                  else
  1214. X                CheckLP(c);
  1215. X                }
  1216. X              SetChar(c);
  1217. X              if (curr->wrap)
  1218. X                curr->x++;
  1219. X            }
  1220. X            }
  1221. X          else
  1222. X            {
  1223. X              LineFeed(2); /* cr+lf, handle LP */
  1224. X              if (curr->insert)
  1225. X            InsertAChar(c);
  1226. X              else
  1227. X            {
  1228. X              if (display)
  1229. X                PUTCHAR(c);
  1230. X              SetChar(c);
  1231. X            }
  1232. X              curr->x = 1;
  1233. X            }
  1234. X          if (curr->ss)
  1235. X            {
  1236. X              NewCharset(curr->charsets[curr->LocalCharset]);
  1237. X              curr->ss = 0;
  1238. X            }
  1239. X        }
  1240. X        }
  1241. X    }
  1242. X    } while (--len);
  1243. X  curr->outlen = 0;
  1244. X  if (curr->state == PRIN)
  1245. X    PrintFlush();
  1246. }
  1247. X
  1248. static int Special(c)
  1249. register int c;
  1250. {
  1251. X  switch (c)
  1252. X    {
  1253. X    case '\b':
  1254. X      BackSpace();
  1255. X      return 1;
  1256. X    case '\r':
  1257. X      Return();
  1258. X      return 1;
  1259. X    case '\n':
  1260. X      if (curr->autoaka)
  1261. X    FindAKA();
  1262. X      LineFeed(1);
  1263. X      return 1;
  1264. X    case '\007':
  1265. X      if (!visual_bell)
  1266. X    PutStr(BL);
  1267. X      else
  1268. X    {
  1269. X      if (!VB)
  1270. X        curr->bell = BELL_VISUAL;
  1271. X      else
  1272. X        PutStr(VB);
  1273. X    }
  1274. X      if (!display)
  1275. X    curr->bell = BELL_ON;
  1276. X      return 1;
  1277. X    case '\t':
  1278. X      ForwardTab();
  1279. X      return 1;
  1280. X    case '\017':        /* SI */
  1281. X      MapCharset(G0);
  1282. X      return 1;
  1283. X    case '\016':        /* SO */
  1284. X      MapCharset(G1);
  1285. X      return 1;
  1286. X    }
  1287. X  return 0;
  1288. }
  1289. X
  1290. static void DoESC(c, intermediate)
  1291. int c, intermediate;
  1292. {
  1293. X  switch (intermediate)
  1294. X    {
  1295. X    case 0:
  1296. X      switch (c)
  1297. X    {
  1298. X    case 'E':
  1299. X      LineFeed(2);
  1300. X      break;
  1301. X    case 'D':
  1302. X      LineFeed(1);
  1303. X      break;
  1304. X    case 'M':
  1305. X      ReverseLineFeed();
  1306. X      break;
  1307. X    case 'H':
  1308. X      curr->tabs[curr->x] = 1;
  1309. X      break;
  1310. X    case 'Z':        /* jph: Identify as VT100 */
  1311. X      Report(curr, "\033[?%d;%dc", 1, 2);
  1312. X      break;
  1313. X    case '7':
  1314. X      SaveCursor();
  1315. X      break;
  1316. X    case '8':
  1317. X      RestoreCursor();
  1318. X      break;
  1319. X    case 'c':
  1320. X      ClearScreen();
  1321. X      ResetScreen(curr);
  1322. X      NewRendition(0);
  1323. X      NewCharset(ASCII);
  1324. X      InsertMode(0);
  1325. X      KeypadMode(0);
  1326. X      ChangeScrollRegion(0, rows-1);
  1327. X      break;
  1328. X    case '=':
  1329. X      KeypadMode(curr->keypad = 1);
  1330. #if !defined(TIOCPKT) || defined(sgi)
  1331. X      NewAutoFlow(curr, 0);
  1332. #endif /* !TIOCPKT || sgi */
  1333. X      break;
  1334. X    case '>':
  1335. X      KeypadMode(curr->keypad = 0);
  1336. #if !defined(TIOCPKT) || defined(sgi)
  1337. X      NewAutoFlow(curr, 1);
  1338. #endif /* !TIOCPKT || sgi */
  1339. X      break;
  1340. X    case 'n':        /* LS2 */
  1341. X      MapCharset(G2);
  1342. X      break;
  1343. X    case 'o':        /* LS3 */
  1344. X      MapCharset(G3);
  1345. X      break;
  1346. X    case 'N':        /* SS2 */
  1347. X      if (curr->charsets[curr->LocalCharset] != curr->charsets[G2])
  1348. X        curr->ss = G2;
  1349. X      else
  1350. X        curr->ss = 0;
  1351. X      break;
  1352. X    case 'O':        /* SS3 */
  1353. X      if (curr->charsets[curr->LocalCharset] != curr->charsets[G3])
  1354. X        curr->ss = G3;
  1355. X      else
  1356. X        curr->ss = 0;
  1357. X      break;
  1358. X    }
  1359. X      break;
  1360. X    case '#':
  1361. X      switch (c)
  1362. X    {
  1363. X    case '8':
  1364. X      FillWithEs();
  1365. X      break;
  1366. X    }
  1367. X      break;
  1368. X    case '(':
  1369. X      DesignateCharset(c, G0);
  1370. X      break;
  1371. X    case ')':
  1372. X      DesignateCharset(c, G1);
  1373. X      break;
  1374. X    case '*':
  1375. X      DesignateCharset(c, G2);
  1376. X      break;
  1377. X    case '+':
  1378. X      DesignateCharset(c, G3);
  1379. X      break;
  1380. X    }
  1381. }
  1382. X
  1383. static void DoCSI(c, intermediate)
  1384. int c, intermediate;
  1385. {
  1386. X  register int i, a1 = curr->args[0], a2 = curr->args[1];
  1387. X
  1388. X  if (curr->NumArgs > MAXARGS)
  1389. X    curr->NumArgs = MAXARGS;
  1390. X  switch (intermediate)
  1391. X    {
  1392. X    case 0:
  1393. X      switch (c)
  1394. X    {
  1395. X    case 'H':
  1396. X    case 'f':
  1397. X      if (a1 < 1)
  1398. X        a1 = 1;
  1399. X      if (curr->origin)
  1400. X        a1 += curr->top;
  1401. X      if (a1 > rows)
  1402. X        a1 = rows;
  1403. X      if (a2 < 1)
  1404. X        a2 = 1;
  1405. X      if (a2 > cols)
  1406. X        a2 = cols;
  1407. X      GotoPos(--a2, --a1);
  1408. X      curr->x = a2;
  1409. X      curr->y = a1;
  1410. X      if (curr->autoaka)
  1411. X        curr->autoaka = a1 + 1;
  1412. X      break;
  1413. X    case 'J':
  1414. X      if (a1 < 0 || a1 > 2)
  1415. X        a1 = 0;
  1416. X      switch (a1)
  1417. X        {
  1418. X        case 0:
  1419. X          ClearToEOS();
  1420. X          break;
  1421. X        case 1:
  1422. X          ClearFromBOS();
  1423. X          break;
  1424. X        case 2:
  1425. X          ClearScreen();
  1426. X          GotoPos(curr->x, curr->y);
  1427. X          break;
  1428. X        }
  1429. X      break;
  1430. X    case 'K':
  1431. X      if (a1 < 0 || a1 > 2)
  1432. X        a1 %= 3;
  1433. X      switch (a1)
  1434. X        {
  1435. X        case 0:
  1436. X          ClearToEOL();
  1437. X          break;
  1438. X        case 1:
  1439. X          ClearFromBOL();
  1440. X          break;
  1441. X        case 2:
  1442. X          ClearLine();
  1443. X          break;
  1444. X        }
  1445. X      break;
  1446. X    case 'A':
  1447. X      CursorUp(a1 ? a1 : 1);
  1448. X      break;
  1449. X    case 'B':
  1450. X      CursorDown(a1 ? a1 : 1);
  1451. X      break;
  1452. X    case 'C':
  1453. X      CursorRight(a1 ? a1 : 1);
  1454. X      break;
  1455. X    case 'D':
  1456. X      CursorLeft(a1 ? a1 : 1);
  1457. X      break;
  1458. X    case 'm':
  1459. X      SelectRendition();
  1460. X      break;
  1461. X    case 'g':
  1462. X      if (a1 == 0)
  1463. X        curr->tabs[curr->x] = 0;
  1464. X      else if (a1 == 3)
  1465. X        bzero(curr->tabs, cols);
  1466. X      break;
  1467. X    case 'r':
  1468. X      if (!a1)
  1469. X        a1 = 1;
  1470. X      if (!a2)
  1471. X        a2 = rows;
  1472. X      if (a1 < 1 || a2 > rows || a1 >= a2)
  1473. X        break;
  1474. X      curr->top = a1 - 1;
  1475. X      curr->bot = a2 - 1;
  1476. X      ChangeScrollRegion(curr->top, curr->bot);
  1477. X      if (curr->origin)
  1478. X        {
  1479. X          GotoPos(0, curr->top);
  1480. X          curr->y = curr->top;
  1481. X          curr->x = 0;
  1482. X        }
  1483. X      else
  1484. X        {
  1485. X          GotoPos(0, 0);
  1486. X          curr->y = curr->x = 0;
  1487. X        }
  1488. X      break;
  1489. X    case 's':
  1490. X      SaveCursor();
  1491. X      break;
  1492. X    case 't':
  1493. X      if (a1 != 8)
  1494. X        break;
  1495. X      a1 = curr->args[2];
  1496. X      if (a1 < 1)
  1497. X        a1 = curr->width;
  1498. X      if (a2 < 1)
  1499. X        a2 = curr->height;
  1500. X      if (WS == NULL)
  1501. X        {
  1502. X          a2 = curr->height;
  1503. X          if (Z0 == NULL || (a1 != Z0width && a1 != Z1width))
  1504. X            a1 = curr->width;
  1505. X         }
  1506. X      if (a1 == curr->width && a2 == curr->height)
  1507. X        break;
  1508. X          ChangeWindowSize(curr, a1, a2);
  1509. X      SetCurr(curr);
  1510. X      if (display)
  1511. X        Activate(0);
  1512. X      break;
  1513. X    case 'u':
  1514. X      RestoreCursor();
  1515. X      break;
  1516. X    case 'I':
  1517. X      if (!a1)
  1518. X        a1 = 1;
  1519. X      while (a1--)
  1520. X        ForwardTab();
  1521. X      break;
  1522. X    case 'Z':
  1523. X      if (!a1)
  1524. X        a1 = 1;
  1525. X      while (a1--)
  1526. X        BackwardTab();
  1527. X      break;
  1528. X    case 'L':
  1529. X      InsertLine(a1 ? a1 : 1);
  1530. X      break;
  1531. X    case 'M':
  1532. X      DeleteLine(a1 ? a1 : 1);
  1533. X      break;
  1534. X    case 'P':
  1535. X      DeleteChar(a1 ? a1 : 1);
  1536. X      break;
  1537. X    case '@':
  1538. X      InsertChar(a1 ? a1 : 1);
  1539. X      break;
  1540. X    case 'h':
  1541. X      ASetMode(1);
  1542. X      break;
  1543. X    case 'l':
  1544. X      ASetMode(0);
  1545. X      break;
  1546. X    case 'i':
  1547. X      if (PO && a1 == 5)
  1548. X        {
  1549. X          curr->stringp = curr->string;
  1550. X          curr->state = PRIN;
  1551. X        }
  1552. X      break;
  1553. X    case 'n':
  1554. X      if (a1 == 6)        /* Report cursor position */
  1555. X        Report(curr, "\033[%d;%dR", curr->y + 1, curr->x + 1);
  1556. X      break;
  1557. X    case 'c':        /* Identify as VT100 */
  1558. X      Report(curr, "\033[?%d;%dc", 1, 2);
  1559. X      break;
  1560. X    }
  1561. X      break;
  1562. X    case '?':
  1563. X      debug2("\\E[?%d%c\n",a1,c);
  1564. X      if (c != 'h' && c != 'l')
  1565. X    break;
  1566. X      i = (c == 'h');
  1567. X      switch (a1)
  1568. X    {
  1569. X    case 3:
  1570. X      i = (i ? Z0width : Z1width);
  1571. X      if ((Z0 || WS) && curr->width != i)
  1572. X        {
  1573. X              ChangeWindowSize(curr, i, curr->height);
  1574. X          SetCurr(curr);
  1575. X          if (display)
  1576. X        Activate(0);
  1577. X        }
  1578. X      break;
  1579. X    case 5:
  1580. X      if (i)
  1581. X        curr->vbwait = 1;
  1582. X      else
  1583. X        {
  1584. X          if (curr->vbwait)
  1585. X        PutStr(VB);
  1586. X          curr->vbwait = 0;
  1587. X        }
  1588. X      break;
  1589. X    case 6:
  1590. X      if ((curr->origin = i) != 0)
  1591. X        {
  1592. X          GotoPos(0, curr->top);
  1593. X          curr->y = curr->top;
  1594. X          curr->x = 0;
  1595. X        }
  1596. X      else
  1597. X        {
  1598. X          GotoPos(0, 0);
  1599. X          curr->y = curr->x = 0;
  1600. X        }
  1601. X      break;
  1602. X    case 7:
  1603. X      curr->wrap = i;
  1604. X      break;
  1605. X    case 35:
  1606. X      debug1("Cursor %svisible\n", i?"in":"");
  1607. X      curr->cursor_invisible = i;
  1608. X      break;
  1609. X    }
  1610. X      break;
  1611. X    }
  1612. }
  1613. X
  1614. void
  1615. INSERTCHAR(c)
  1616. int c;
  1617. {
  1618. X  if (!insert && (IC || CIC))
  1619. X    {
  1620. X      if (IC)
  1621. X        PutStr(IC);
  1622. X      else
  1623. X        CPutStr(CIC, 1);
  1624. X      RAW_PUTCHAR(c);
  1625. X      return;
  1626. X    }
  1627. X  InsertMode(1);
  1628. X  if (insert)
  1629. X    RAW_PUTCHAR(c);
  1630. X  else
  1631. X    RefreshLine(screeny, screenx, screenwidth-1);
  1632. }
  1633. X
  1634. void
  1635. PUTCHAR(c)
  1636. int c;
  1637. {
  1638. X  if (insert)
  1639. X    InsertMode(0);
  1640. X  RAW_PUTCHAR(c);
  1641. }
  1642. X
  1643. /*
  1644. X * RAW_PUTCHAR() is for all text that will be displayed.
  1645. X * NOTE, that charset Nr. 0 has a conversion table, but c1, c2, ... don't.
  1646. X */
  1647. X
  1648. static void
  1649. RAW_PUTCHAR(c)
  1650. int c;
  1651. {
  1652. X  if (GlobalCharset == '0')
  1653. X    putchar(c0_tab[c]);
  1654. X  else
  1655. X    putchar(c);
  1656. X  if (screenx < screenwidth - 1)
  1657. X    screenx++;
  1658. X  else
  1659. X    {
  1660. X      screenx++;
  1661. X      if ((AM && !LP) || screenx > screenwidth)
  1662. X    {
  1663. X      screenx -= screenwidth;
  1664. X      if (screeny < screenheight-1 && screeny != screenbot)
  1665. X        screeny++;
  1666. X    }
  1667. X    }
  1668. }
  1669. X
  1670. void
  1671. PutChar(c)
  1672. int c;
  1673. {
  1674. X  /* this PutChar for ESC-sequences only */
  1675. X  putchar(c);
  1676. }
  1677. X
  1678. void
  1679. PutStr(s)
  1680. char *s;
  1681. {
  1682. X  if (display && s)
  1683. X    tputs(s, 1, PutChar);
  1684. }
  1685. X
  1686. static void CPutStr(s, c)
  1687. char *s;
  1688. int c;
  1689. {
  1690. X  if (display && s)
  1691. X    tputs(tgoto(s, 0, c), 1, PutChar);
  1692. }
  1693. X
  1694. static void SetChar(c)
  1695. register int c;
  1696. {
  1697. X  register struct win *p = curr;
  1698. X
  1699. X  p->image[p->y][p->x] = c;
  1700. X  p->attr[p->y][p->x] = p->LocalAttr;
  1701. X  p->font[p->y][p->x] = p->charsets[p->ss ? p->ss : p->LocalCharset];
  1702. }
  1703. X
  1704. static void StartString(type)
  1705. enum string_t type;
  1706. {
  1707. X  curr->StringType = type;
  1708. X  curr->stringp = curr->string;
  1709. X  curr->state = ASTR;
  1710. }
  1711. X
  1712. static void AddChar(c)
  1713. int c;
  1714. {
  1715. X  if (curr->stringp >= curr->string + MAXSTR - 1)
  1716. X    curr->state = LIT;
  1717. X  else
  1718. X    *(curr->stringp)++ = c;
  1719. }
  1720. X
  1721. static void PrintChar(c)
  1722. int c;
  1723. {
  1724. X  if (curr->stringp >= curr->string + MAXSTR - 1)
  1725. X    PrintFlush();
  1726. X  *(curr->stringp)++ = c;
  1727. }
  1728. X
  1729. static void PrintFlush()
  1730. {
  1731. X  if (curr->stringp > curr->string)
  1732. X    {
  1733. X      tputs(PO, 1, PutChar);
  1734. X      (void) fflush(stdout);
  1735. X      (void) write(1, curr->string, curr->stringp - curr->string);
  1736. X      tputs(PF, 1, PutChar);
  1737. X      (void) fflush(stdout);
  1738. X      curr->stringp = curr->string;
  1739. X    }
  1740. }
  1741. X
  1742. /* Insert mode is a toggle on some terminals, so we need this hack:
  1743. X */
  1744. void
  1745. InsertMode(on)
  1746. int on;
  1747. {
  1748. X  if (display && on != insert && IM)
  1749. X    {
  1750. X      insert = on;
  1751. X      if (insert)
  1752. X    PutStr(IM);
  1753. X      else
  1754. X    PutStr(EI);
  1755. X    }
  1756. }
  1757. X
  1758. /* ...and maybe keypad application mode is a toggle, too:
  1759. X */
  1760. static void KeypadMode(on)
  1761. int on;
  1762. {
  1763. X  if (display && keypad != on && KS)
  1764. X    {
  1765. X      keypad = on;
  1766. X      if (keypad)
  1767. X    PutStr(KS);
  1768. X      else
  1769. X    PutStr(KE);
  1770. X    }
  1771. }
  1772. X
  1773. void
  1774. NewAutoFlow(win, on)
  1775. struct win *win;
  1776. int on;
  1777. {
  1778. X  debug1("NewAutoFlow: %d\n", on);
  1779. X  SetCurr(win);
  1780. X  if (win->flow & FLOW_AUTOFLAG)
  1781. X    win->flow = FLOW_AUTOFLAG | (FLOW_AUTO|FLOW_NOW) * on;
  1782. X  else
  1783. X    win->flow = (win->flow & ~FLOW_AUTO) | FLOW_AUTO * on;
  1784. X  if (display)
  1785. X    SetFlow(win->flow & FLOW_NOW);
  1786. }
  1787. X
  1788. static void DesignateCharset(c, n)
  1789. int c, n;
  1790. {
  1791. X  curr->ss = 0;
  1792. X  if (c == 'B')
  1793. X    c = ASCII;
  1794. X  if (curr->charsets[n] != c)
  1795. X    {
  1796. X      curr->charsets[n] = c;
  1797. X      if (curr->LocalCharset == n)
  1798. X    NewCharset(c);
  1799. X    }
  1800. }
  1801. X
  1802. static void MapCharset(n)
  1803. int n;
  1804. {
  1805. X  curr->ss = 0;
  1806. X  if (curr->LocalCharset != n)
  1807. X    {
  1808. X      curr->LocalCharset = n;
  1809. X      NewCharset(curr->charsets[n]);
  1810. X    }
  1811. }
  1812. X
  1813. void
  1814. NewCharset(new)
  1815. int new;
  1816. {
  1817. X  if (!display || GlobalCharset == new)
  1818. X    return;
  1819. X  GlobalCharset = new;
  1820. X  if (new == ASCII)
  1821. X    PutStr(E0);
  1822. X  else
  1823. X    CPutStr(S0, new);
  1824. }
  1825. X
  1826. static void SaveCursor()
  1827. {
  1828. X  curr->saved = 1;
  1829. X  curr->Saved_x = curr->x;
  1830. X  curr->Saved_y = curr->y;
  1831. X  curr->SavedLocalAttr = curr->LocalAttr;
  1832. X  curr->SavedLocalCharset = curr->LocalCharset;
  1833. X  bcopy((char *) curr->charsets, (char *) curr->SavedCharsets,
  1834. X    4 * sizeof(int));
  1835. }
  1836. X
  1837. static void RestoreCursor()
  1838. {
  1839. X  if (curr->saved)
  1840. X    {
  1841. X      GotoPos(curr->Saved_x, curr->Saved_y);
  1842. X      curr->x = curr->Saved_x;
  1843. X      curr->y = curr->Saved_y;
  1844. X      curr->LocalAttr = curr->SavedLocalAttr;
  1845. X      NewRendition(curr->LocalAttr);
  1846. X      bcopy((char *) curr->SavedCharsets, (char *) curr->charsets,
  1847. X        4 * sizeof(int));
  1848. X      curr->LocalCharset = curr->SavedLocalCharset;
  1849. X      NewCharset(curr->charsets[curr->LocalCharset]);
  1850. X    }
  1851. }
  1852. X
  1853. /*ARGSUSED*/
  1854. static void CountChars(c)
  1855. int c;
  1856. {
  1857. X  StrCost++;
  1858. }
  1859. X
  1860. static int CalcCost(s)
  1861. register char *s;
  1862. {
  1863. X  if (s)
  1864. X    {
  1865. X      StrCost = 0;
  1866. X      tputs(s, 1, CountChars);
  1867. X      return StrCost;
  1868. X    }
  1869. X  else
  1870. X    return EXPENSIVE;
  1871. }
  1872. X
  1873. void
  1874. GotoPos(x2, y2)
  1875. int x2, y2;
  1876. {
  1877. X  register int dy, dx, x1, y1;
  1878. X  register int costx, costy;
  1879. X  register int m;
  1880. X  register char *s;
  1881. X  int CMcost;
  1882. X  enum move_t xm = M_NONE, ym = M_NONE;
  1883. X
  1884. X  if (!display)
  1885. X    return;
  1886. X
  1887. X  x1 = screenx;
  1888. X  y1 = screeny;
  1889. X
  1890. X  if (x1 == screenwidth)
  1891. X    if (LP && AM)
  1892. X      x1 = -1;        /* don't know how the terminal treats this */
  1893. X    else
  1894. X      x1--;
  1895. X  if (x2 == screenwidth)
  1896. X    x2--;
  1897. X  dx = x2 - x1;
  1898. X  dy = y2 - y1;
  1899. X  if (dy == 0 && dx == 0)
  1900. X    {
  1901. X      return;
  1902. X    }
  1903. X  if (!MS && GlobalAttr)    /* Safe to move in SO mode ? */
  1904. X    NewRendition(0);
  1905. X  if (y1 < 0            /* don't know the y position */
  1906. X      || (y2 > screenbot && y1 <= screenbot)    /* have to cross border */
  1907. X      || (y2 < screentop && y1 >= screentop))    /* of scrollregion ?    */
  1908. X    {
  1909. X    DoCM:
  1910. X      if (HO && !x2 && !y2)
  1911. X        PutStr(HO);
  1912. X      else
  1913. X        PutStr(tgoto(CM, x2, y2));
  1914. X      screenx = x2;
  1915. X      screeny = y2;
  1916. X      return;
  1917. X    }
  1918. X  /* Calculate CMcost */
  1919. X  if (HO && !x2 && !y2)
  1920. X    s = HO;
  1921. X  else
  1922. X    s = tgoto(CM, x2, y2);
  1923. X  CMcost = CalcCost(s);
  1924. X
  1925. X  /* Calculate the cost to move the cursor to the right x position */
  1926. X  costx = EXPENSIVE;
  1927. X  if (x1 >= 0)    /* relativ x positioning only if we know where we are */
  1928. X    {
  1929. X      if (dx > 0)
  1930. X    {
  1931. X      if (CRI && (dx > 1 || !ND))
  1932. X        {
  1933. X          costx = CalcCost(tgoto(CRI, 0, dx));
  1934. X          xm = M_CRI;
  1935. X        }
  1936. X      if ((m = NDcost * dx) < costx)
  1937. X        {
  1938. X          costx = m;
  1939. X          xm = M_RI;
  1940. X        }
  1941. X      /* Speedup: dx <= Rewrite() */
  1942. X      if (dx < costx && (m = Rewrite(y1, x1, x2, 0)) < costx)
  1943. X        {
  1944. X          costx = m;
  1945. X          xm = M_RW;
  1946. X        }
  1947. X    }
  1948. X      else if (dx < 0)
  1949. X    {
  1950. X      if (CLE && (dx < -1 || !BC))
  1951. X        {
  1952. X          costx = CalcCost(tgoto(CLE, 0, -dx));
  1953. X          xm = M_CLE;
  1954. X        }
  1955. X      if ((m = -dx * LEcost) < costx)
  1956. X        {
  1957. X          costx = m;
  1958. X          xm = M_LE;
  1959. X        }
  1960. X    }
  1961. X      else
  1962. X    costx = 0;
  1963. X    }
  1964. X  /* Speedup: Rewrite() >= x2 */
  1965. X  if (x2 + CRcost < costx && (m = Rewrite(y1, 0, x2, 0) + CRcost) < costx)
  1966. X    {
  1967. X      costx = m;
  1968. X      xm = M_CR;
  1969. X    }
  1970. X
  1971. X  /* Check if it is already cheaper to do CM */
  1972. X  if (costx >= CMcost)
  1973. X    goto DoCM;
  1974. X
  1975. X  /* Calculate the cost to move the cursor to the right y position */
  1976. X  costy = EXPENSIVE;
  1977. X  if (dy > 0)
  1978. X    {
  1979. X      if (CDO && dy > 1)    /* DO & NL are always != 0 */
  1980. X    {
  1981. X      costy = CalcCost(tgoto(CDO, 0, dy));
  1982. X      ym = M_CDO;
  1983. X    }
  1984. X      if ((m = dy * ((x2 == 0) ? NLcost : DOcost)) < costy)
  1985. X    {
  1986. X      costy = m;
  1987. X      ym = M_DO;
  1988. X    }
  1989. X    }
  1990. X  else if (dy < 0)
  1991. X    {
  1992. X      if (CUP && (dy < -1 || !UP))
  1993. X    {
  1994. X      costy = CalcCost(tgoto(CUP, 0, -dy));
  1995. X      ym = M_CUP;
  1996. X    }
  1997. X      if ((m = -dy * UPcost) < costy)
  1998. X    {
  1999. X      costy = m;
  2000. X      ym = M_UP;
  2001. X    }
  2002. X    }
  2003. X  else
  2004. X    costy = 0;
  2005. X
  2006. X  /* Finally check if it is cheaper to do CM */
  2007. X  if (costx + costy >= CMcost)
  2008. X    goto DoCM;
  2009. X
  2010. X  switch (xm)
  2011. X    {
  2012. X    case M_LE:
  2013. X      while (dx++ < 0)
  2014. X    PutStr(BC);
  2015. X      break;
  2016. X    case M_CLE:
  2017. X      CPutStr(CLE, -dx);
  2018. X      break;
  2019. X    case M_RI:
  2020. X      while (dx-- > 0)
  2021. X    PutStr(ND);
  2022. X      break;
  2023. X    case M_CRI:
  2024. X      CPutStr(CRI, dx);
  2025. X      break;
  2026. X    case M_CR:
  2027. X      PutStr(CR);
  2028. X      screenx = 0;
  2029. X      x1 = 0;
  2030. X      /* FALLTHROUGH */
  2031. X    case M_RW:
  2032. X      if (x1 < x2)
  2033. X    (void) Rewrite(y1, x1, x2, 1);
  2034. X      break;
  2035. X    default:
  2036. X      break;
  2037. X    }
  2038. X  switch (ym)
  2039. X    {
  2040. X    case M_UP:
  2041. X      while (dy++ < 0)
  2042. X    PutStr(UP);
  2043. X      break;
  2044. X    case M_CUP:
  2045. X      CPutStr(CUP, -dy);
  2046. X      break;
  2047. X    case M_DO:
  2048. X      s =  (x2 == 0) ? NL : DO;
  2049. X      while (dy-- > 0)
  2050. X    PutStr(s);
  2051. X      break;
  2052. X    case M_CDO:
  2053. X      CPutStr(CDO, dy);
  2054. X      break;
  2055. X    default:
  2056. X      break;
  2057. X    }
  2058. X  screenx = x2;
  2059. X  screeny = y2;
  2060. }
  2061. X
  2062. static int
  2063. Rewrite(y, x1, x2, doit)
  2064. int y, x1, x2, doit;
  2065. {
  2066. X  register int cost, dx;
  2067. X  register char *p, *f, *i;
  2068. X
  2069. X  if (x1 == x2)
  2070. X    return(0);
  2071. X  if (in_ovl)
  2072. X    {
  2073. X      if (ovl_Rewrite == 0)
  2074. X        return EXPENSIVE;
  2075. X      else
  2076. X        return ((*ovl_Rewrite)(y, x1, x2, doit));
  2077. X    }
  2078. X  dx = x2 - x1;
  2079. X  if (doit)
  2080. X    {
  2081. X      i = curr->image[y] + x1;
  2082. X      while (dx-- > 0)
  2083. X    PUTCHAR(*i++);
  2084. X      return(0);
  2085. X    }
  2086. X  p = curr->attr[y] + x1;
  2087. X  f = curr->font[y] + x1;
  2088. X
  2089. X  cost = dx = x2 - x1;
  2090. X  if (insert)
  2091. X    cost += EIcost + IMcost;
  2092. X  while(dx-- > 0)
  2093. X    {
  2094. X      if (*p++ != GlobalAttr || *f++ != GlobalCharset)
  2095. X    return EXPENSIVE;
  2096. X    }
  2097. X  return cost;
  2098. }
  2099. X
  2100. static void BackSpace()
  2101. {
  2102. X  if (curr->x > 0)
  2103. X    {
  2104. X      curr->x--;
  2105. X    }
  2106. X  else if (curr->wrap && curr->y > 0)
  2107. X    {
  2108. X      curr->x = cols - 1;
  2109. X      curr->y--;
  2110. X    }
  2111. X  if (display)
  2112. X    GotoPos(curr->x, curr->y);
  2113. }
  2114. X
  2115. static void Return()
  2116. {
  2117. X  if (curr->x > 0)
  2118. X    {
  2119. X      curr->x = 0;
  2120. X      if (display)
  2121. X        GotoPos(curr->x, curr->y);
  2122. X    }
  2123. }
  2124. X
  2125. static void LineFeed(out_mode)
  2126. int out_mode;
  2127. {
  2128. X  /* out_mode: 0=no-output lf, 1=lf, 2=cr+lf */
  2129. X  if (out_mode == 2)
  2130. X    curr->x = 0;
  2131. X  if (curr->y != curr->bot)        /* Don't scroll */
  2132. X    {
  2133. X      if (curr->y < rows-1)
  2134. X    curr->y++;
  2135. X      if (out_mode && display)
  2136. X    GotoPos(curr->x, curr->y);
  2137. X      return;
  2138. X    }
  2139. X  ScrollUpMap(1);
  2140. X  if (curr->autoaka > 1)
  2141. X    curr->autoaka--;
  2142. X  if (out_mode && display)
  2143. X    {
  2144. X      ScrollRegion(curr->top, curr->bot, 1);
  2145. X      GotoPos(curr->x, curr->y);
  2146. X    }
  2147. }
  2148. X
  2149. static void ReverseLineFeed()
  2150. {
  2151. X  if (curr->y == curr->top)
  2152. X    {
  2153. X      ScrollDownMap(1);
  2154. X      if (!display)
  2155. X    return;
  2156. X      ScrollRegion(curr->top, curr->bot, -1);
  2157. X      GotoPos(curr->x, curr->y);
  2158. X    }
  2159. X  else if (curr->y > 0)
  2160. X    CursorUp(1);
  2161. }
  2162. X
  2163. static void InsertAChar(c)
  2164. int c;
  2165. {
  2166. X  register int y = curr->y, x = curr->x;
  2167. X
  2168. X  if (x == cols)
  2169. X    x--;
  2170. X  bcopy(curr->image[y], OldImage, cols);
  2171. X  bcopy(curr->attr[y], OldAttr, cols);
  2172. X  bcopy(curr->font[y], OldFont, cols);
  2173. X  bcopy(curr->image[y] + x, curr->image[y] + x + 1, cols - x - 1);
  2174. X  bcopy(curr->attr[y] + x, curr->attr[y] + x + 1, cols - x - 1);
  2175. X  bcopy(curr->font[y] + x, curr->font[y] + x + 1, cols - x - 1);
  2176. X  SetChar(c);
  2177. X  if (!display)
  2178. X    return;
  2179. X  if (CIC || IC || IM)
  2180. X    {
  2181. X      InsertMode(curr->insert);
  2182. X      INSERTCHAR(c);
  2183. X      if (y == screenbot)
  2184. X    lp_missing = 0;
  2185. X    }
  2186. X  else
  2187. X    {
  2188. X      RedisplayLine(OldImage, OldAttr, OldFont, y, x, cols - 1);
  2189. X      GotoPos(++x, y);
  2190. X    }
  2191. }
  2192. X
  2193. static void InsertChar(n)
  2194. int n;
  2195. {
  2196. X  register int i, y = curr->y, x = curr->x;
  2197. X
  2198. X  if (n <= 0)
  2199. X    return;
  2200. X  /*
  2201. X   * The termcap manual states that only one of IM and IC is
  2202. X   * to be defined unless the terminal needs both sequences.
  2203. X   * We don't like this because we think that there may be cases
  2204. X   * where it is preferable to send IC instead of IM/EI.
  2205. X   * The hack is to ignore the IC sequence if we are already
  2206. X   * in insert mode, so that programs which follow the termcap
  2207. X   * guidelines still work. (I don't believe that there are
  2208. X   * terminals which need IC in the insert mode. Why switch to
  2209. X   * insert mode if you must send IC before every character ?)
  2210. X   */
  2211. X  if (curr->insert)
  2212. X    return;
  2213. X  if (x == cols)
  2214. X    --x;
  2215. X  bcopy(curr->image[y], OldImage, cols);
  2216. X  bcopy(curr->attr[y], OldAttr, cols);
  2217. X  bcopy(curr->font[y], OldFont, cols);
  2218. X  if (n > cols - x)
  2219. X    n = cols - x;
  2220. X  bcopy(curr->image[y] + x, curr->image[y] + x + n, cols - x - n);
  2221. X  bcopy(curr->attr[y] + x, curr->attr[y] + x + n, cols - x - n);
  2222. X  bcopy(curr->font[y] + x, curr->font[y] + x + n, cols - x - n);
  2223. X  ClearInLine(0, y, x, x + n - 1);
  2224. X  if (!display)
  2225. X    return;
  2226. X  if (IC || CIC || IM)
  2227. X    {
  2228. X      if (y == screenbot)
  2229. X    lp_missing = 0;
  2230. X      if (!insert)
  2231. X    {
  2232. X      if (n == 1 && IC)
  2233. X        {
  2234. X          PutStr(IC);
  2235. X          return;
  2236. X            }
  2237. X      if (CIC)
  2238. X        {
  2239. X          CPutStr(CIC, n);
  2240. X          return;
  2241. X            }
  2242. X    }
  2243. X      InsertMode(1);
  2244. X      for (i = n; i--; )
  2245. X    INSERTCHAR(' ');
  2246. X      GotoPos(x, y);
  2247. X    }
  2248. X  else
  2249. X    {
  2250. X      RedisplayLine(OldImage, OldAttr, OldFont, y, x, cols - 1);
  2251. X      GotoPos(x, y);
  2252. X    }
  2253. }
  2254. X
  2255. static void DeleteChar(n)
  2256. int n;
  2257. {
  2258. X  register int i, y = curr->y, x = curr->x;
  2259. X
  2260. X  if (x == cols)
  2261. X    --x;
  2262. X  bcopy(curr->image[y], OldImage, cols);
  2263. X  bcopy(curr->attr[y], OldAttr, cols);
  2264. X  bcopy(curr->font[y], OldFont, cols);
  2265. X  if (n > cols - x)
  2266. X    n = cols - x;
  2267. X  bcopy(curr->image[y] + x + n, curr->image[y] + x, cols - x - n);
  2268. X  bcopy(curr->attr[y] + x + n, curr->attr[y] + x, cols - x - n);
  2269. X  bcopy(curr->font[y] + x + n, curr->font[y] + x, cols - x - n);
  2270. X  ClearInLine(0, y, cols - n, cols - 1);
  2271. X  if (!display)
  2272. X    return;
  2273. X  if (CDC && !(n == 1 && DC))
  2274. X    {
  2275. X      CPutStr(CDC, n);
  2276. X      if (lp_missing && y == screenbot)
  2277. X    {
  2278. X      FixLP(cols - 1 - n, y);
  2279. X          GotoPos(x, y);
  2280. X    }
  2281. X    }
  2282. X  else if (DC)
  2283. X    {
  2284. X      for (i = n; i; i--)
  2285. X    PutStr(DC);
  2286. X      if (lp_missing && y == screenbot)
  2287. X    {
  2288. X      FixLP(cols - 1 - n, y);
  2289. X          GotoPos(x, y);
  2290. X    }
  2291. X    }
  2292. X  else
  2293. X    {
  2294. X      RedisplayLine(OldImage, OldAttr, OldFont, y, x, cols - 1);
  2295. X      GotoPos(x, y);
  2296. X    }
  2297. }
  2298. X
  2299. static void DeleteLine(n)
  2300. int n;
  2301. {
  2302. X  register int old = curr->top;
  2303. X  
  2304. X  if (curr->y < curr->top || curr->y > curr->bot)
  2305. X    return;
  2306. X  if (n > curr->bot - curr->y + 1)
  2307. X    n = curr->bot - curr->y + 1;
  2308. X  curr->top = curr->y;
  2309. X  ScrollUpMap(n);
  2310. X  curr->top = old;
  2311. X  if (!display)
  2312. X    return;
  2313. X  ScrollRegion(curr->y, curr->bot, n);
  2314. X  GotoPos(curr->x, curr->y);
  2315. }
  2316. X
  2317. static void InsertLine(n)
  2318. int n;
  2319. {
  2320. X  register int old = curr->top;
  2321. X
  2322. X  if (curr->y < curr->top || curr->y > curr->bot)
  2323. X    return;
  2324. X  if (n > curr->bot - curr->y + 1)
  2325. X    n = curr->bot - curr->y + 1;
  2326. X  curr->top = curr->y;
  2327. X  ScrollDownMap(n);
  2328. X  curr->top = old;
  2329. X  if (!display)
  2330. X    return;
  2331. X  ScrollRegion(curr->y, curr->bot, -n);
  2332. X  GotoPos(curr->x, curr->y);
  2333. }
  2334. X
  2335. void
  2336. ScrollRegion(ys, ye, n)
  2337. int ys, ye, n;
  2338. {
  2339. X  int i;
  2340. X  int up;
  2341. X  int oldtop, oldbot;
  2342. X  int alok, dlok, aldlfaster;
  2343. X  int missy = 0;
  2344. X
  2345. X  if (n == 0)
  2346. X    return;
  2347. X  if (ys == 0 && ye == screenheight-1 && 
  2348. X      (n >= screenheight || -n >= screenheight))
  2349. X    {
  2350. X      PutStr(CL);
  2351. X      screeny = screenx = 0;
  2352. X      lp_missing = 0;
  2353. X      return;
  2354. X    }
  2355. X
  2356. X  if (lp_missing)
  2357. X    {
  2358. X      if (screenbot>ye || screenbot<ys)
  2359. X    missy = screenbot;
  2360. X      else
  2361. X    {
  2362. X      missy = screenbot - n;
  2363. X          if (missy>ye || missy<ys)
  2364. X        lp_missing = 0;
  2365. X    }
  2366. X    }
  2367. X
  2368. X  up = 1;
  2369. X  if (n < 0)
  2370. X    {
  2371. X      up = 0;
  2372. X      n = -n;
  2373. X    }
  2374. X  if (n >= ye-ys+1)
  2375. X    n = ye-ys+1;
  2376. X
  2377. X  oldtop = screentop;
  2378. X  oldbot = screenbot;
  2379. X  if (screenbot != ye)
  2380. X    ChangeScrollRegion(ys, ye);
  2381. X  alok = (AL || CAL || (ye == screenbot &&  up));
  2382. X  dlok = (DL || CDL || (ye == screenbot && !up));
  2383. X  if (screentop != ys && !(alok && dlok))
  2384. X    ChangeScrollRegion(ys, ye);
  2385. X
  2386. X  if (lp_missing && 
  2387. X      (oldbot != screenbot ||
  2388. X       (oldbot == screenbot && up && screentop == ys && screenbot == ye)))
  2389. X    {
  2390. X      /* Can't use FixLP */
  2391. X      GotoPos(screenwidth-1, oldbot);
  2392. X      SaveSetAttr(curr->attr[missy][screenwidth-1], curr->font[missy][screenwidth-1]);
  2393. X      PUTCHAR(curr->image[missy][screenwidth-1]);
  2394. X      RestoreAttr();
  2395. X      lp_missing = 0;
  2396. X      if (oldbot == screenbot)        /* have scrolled */
  2397. X    {
  2398. X      if (--n == 0)
  2399. X        {
  2400. X          ChangeScrollRegion(oldtop, oldbot);
  2401. X          return;
  2402. X        }
  2403. X    }
  2404. X    }
  2405. X
  2406. X  aldlfaster = (n > 1 && ye == screenbot && ((up && CDL) || (!up && CAL)));
  2407. X
  2408. X  if ((up || SR) && screentop == ys && screenbot == ye && !aldlfaster)
  2409. X    {
  2410. X      if (up)
  2411. X    {
  2412. X      GotoPos(0, ye);
  2413. X      while (n-- > 0)
  2414. X        PutStr(NL); /* was SF, I think NL is faster */
  2415. X    }
  2416. X      else
  2417. X    {
  2418. X      GotoPos(0, ys);
  2419. X      while (n-- > 0)
  2420. X        PutStr(SR);
  2421. X    }
  2422. X    }
  2423. X  else if (alok && dlok)
  2424. X    {
  2425. X      if (up || ye != screenbot)
  2426. X    {
  2427. X          GotoPos(0, up ? ys : ye+1-n);
  2428. X          if (CDL && !(n == 1 && DL))
  2429. X        CPutStr(CDL, n);
  2430. X      else
  2431. X        for(i=n; i--; )
  2432. X          PutStr(DL);
  2433. X    }
  2434. X      if (!up || ye != screenbot)
  2435. X    {
  2436. X          GotoPos(0, up ? ye+1-n : ys);
  2437. X          if (CAL && !(n == 1 && AL))
  2438. X        CPutStr(CAL, n);
  2439. X      else
  2440. X        for(i=n; i--; )
  2441. X          PutStr(AL);
  2442. X    }
  2443. X    }
  2444. X  else
  2445. X    {
  2446. X      Redisplay(0);
  2447. X      return;
  2448. X    }
  2449. X  if (lp_missing && missy != screenbot)
  2450. X    FixLP(screenwidth-1, missy);
  2451. X  ChangeScrollRegion(oldtop, oldbot);
  2452. X  if (lp_missing && missy != screenbot)
  2453. X    FixLP(screenwidth-1, missy);
  2454. }
  2455. X
  2456. static void ScrollUpMap(n)
  2457. int n;
  2458. {
  2459. X  char tmp[256 * sizeof(char *)];
  2460. X  register int ii, i, cnt1, cnt2;
  2461. X  register char **ppi, **ppa, **ppf;
  2462. X
  2463. X  i = curr->top + n;
  2464. X  cnt1 = n * sizeof(char *);
  2465. X  cnt2 = (curr->bot - i + 1) * sizeof(char *);
  2466. X  ppi = curr->image + i;
  2467. X  ppa = curr->attr + i;
  2468. X  ppf = curr->font + i;
  2469. X  for(ii = curr->top; ii < i; ii++)
  2470. X     AddLineToHist(curr, &curr->image[ii], &curr->attr[ii], &curr->font[ii]);
  2471. X  for (i = n; i; --i)
  2472. X    {
  2473. X      bclear(*--ppi, cols);
  2474. X      bzero(*--ppa, cols);
  2475. X      bzero(*--ppf, cols);
  2476. X    }
  2477. X  Scroll((char *) ppi, cnt1, cnt2, tmp);
  2478. X  Scroll((char *) ppa, cnt1, cnt2, tmp);
  2479. X  Scroll((char *) ppf, cnt1, cnt2, tmp);
  2480. }
  2481. X
  2482. static void ScrollDownMap(n)
  2483. int n;
  2484. {
  2485. X  char tmp[256 * sizeof(char *)];
  2486. X  register int i, cnt1, cnt2;
  2487. X  register char **ppi, **ppa, **ppf;
  2488. X
  2489. X  i = curr->top;
  2490. X  cnt1 = (curr->bot - i - n + 1) * sizeof(char *);
  2491. X  cnt2 = n * sizeof(char *);
  2492. X  Scroll((char *) (ppi = curr->image + i), cnt1, cnt2, tmp);
  2493. X  Scroll((char *) (ppa = curr->attr + i), cnt1, cnt2, tmp);
  2494. X  Scroll((char *) (ppf = curr->font + i), cnt1, cnt2, tmp);
  2495. X  for (i = n; i; --i)
  2496. X    {
  2497. X      bclear(*ppi++, cols);
  2498. X      bzero(*ppa++, cols);
  2499. X      bzero(*ppf++, cols);
  2500. X    }
  2501. }
  2502. X
  2503. static void Scroll(cp, cnt1, cnt2, tmp)
  2504. char *cp, *tmp;
  2505. int cnt1, cnt2;
  2506. {
  2507. X  if (!cnt1 || !cnt2)
  2508. X    return;
  2509. X  if (cnt1 <= cnt2)
  2510. X    {
  2511. X      bcopy(cp, tmp, cnt1);
  2512. X      bcopy(cp + cnt1, cp, cnt2);
  2513. X      bcopy(tmp, cp + cnt2, cnt1);
  2514. X    }
  2515. X  else
  2516. X    {
  2517. X      bcopy(cp + cnt1, tmp, cnt2);
  2518. X      bcopy(cp, cp + cnt2, cnt1);
  2519. X      bcopy(tmp, cp, cnt2);
  2520. X    }
  2521. }
  2522. X
  2523. static void ForwardTab()
  2524. {
  2525. X  register int x = curr->x;
  2526. X
  2527. X  if (x == cols)
  2528. X    {
  2529. X      LineFeed(2);
  2530. X      x = 0;
  2531. X    }
  2532. X  if (curr->tabs[x] && x < cols - 1)
  2533. X    x++;
  2534. X  while (x < cols - 1 && !curr->tabs[x])
  2535. X    x++;
  2536. X  GotoPos(x, curr->y);
  2537. X  curr->x = x;
  2538. }
  2539. X
  2540. static void BackwardTab()
  2541. {
  2542. X  register int x = curr->x;
  2543. X
  2544. X  if (curr->tabs[x] && x > 0)
  2545. SHAR_EOF
  2546. true || echo 'restore of screen3.2/ansi.c failed'
  2547. fi
  2548. echo 'End of  part 1'
  2549. echo 'File screen3.2/ansi.c is continued in part 2'
  2550. echo 2 > _shar_seq_.tmp
  2551. exit 0
  2552. exit 0 # Just in case...
  2553.