home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / alt / sources / 2594 < prev    next >
Encoding:
Text File  |  1992-11-20  |  53.0 KB  |  2,313 lines

  1. Newsgroups: alt.sources
  2. Path: sparky!uunet!zaphod.mps.ohio-state.edu!sol.ctr.columbia.edu!eff!world!jhallen
  3. From: jhallen@world.std.com (Joseph H Allen)
  4. Subject: JOE 1.0.5 Part 7 of 10
  5. Message-ID: <By2MM7.L2t@world.std.com>
  6. Organization: The World Public Access UNIX, Brookline, MA
  7. Date: Sat, 21 Nov 1992 14:51:42 GMT
  8. Lines: 2303
  9.  
  10. Submitted-by: jhallen@world.std.com
  11. Archive-name: joe1.0.5part7
  12.  
  13. X
  14. CONTEXT cttab={"tab",0};
  15. X
  16. #define F_DIR        1
  17. #define F_NORMAL    2
  18. #define F_EXEC        4
  19. X
  20. char **rexpnd();
  21. X
  22. static int get_entries(tab,prv)
  23. TAB *tab;
  24. {
  25. int a;
  26. int which=0;
  27. char *oldpwd;
  28. char **files=(char **)rexpnd(tab->path,tab->pattern);
  29. if(!files) return -1;
  30. if(!aLEN(files)) return -1;
  31. tab->len=aLEN(files);
  32. vsrm(tab->files); tab->files=files;
  33. vasort(files,tab->len);
  34. if(tab->type) free(tab->type);
  35. tab->type=(char *)malloc(tab->len);
  36. oldpwd=pwd(); chdir(tab->path);
  37. for(a=0;a!=tab->len;a++)
  38. X {
  39. X struct stat buf;
  40. X mset(&buf,0,sizeof(struct stat));
  41. X stat(files[a],&buf);
  42. X if(buf.st_ino==prv) which=a;
  43. X if((buf.st_mode&S_IFMT)==S_IFDIR) tab->type[a]=F_DIR;
  44. X else if(buf.st_mode&(0100|0010|0001)) tab->type[a]=F_EXEC;
  45. X else tab->type[a]=F_NORMAL;
  46. X }
  47. chdir(oldpwd);
  48. return which;
  49. }
  50. X
  51. static void wkilltab(w)
  52. W *w;
  53. {
  54. MENU *m=(MENU *)w->object;
  55. TAB *tab;
  56. if(m) tab=(TAB *)m->object;
  57. else tab=0;
  58. if(tab)
  59. X {
  60. X vsrm(tab->path);
  61. X vsrm(tab->pattern);
  62. X varm(tab->files);
  63. X free(tab->type);
  64. X free(tab);
  65. X }
  66. if(m)
  67. X {
  68. X varm(m->list);
  69. X menurm(m);
  70. X }
  71. }
  72. X
  73. static void followtab(w)
  74. W *w;
  75. {
  76. MENU *m=(MENU *)w->object;
  77. menufllw(m);
  78. }
  79. X
  80. static void disptab(w)
  81. W *w;
  82. {
  83. MENU *m=(MENU *)w->object;
  84. menugen(m);
  85. w->cury=0;
  86. w->curx=(m->cursor-m->top)*(m->width+1);
  87. }
  88. X
  89. static void resizetab(w,wi,he)
  90. W *w;
  91. {
  92. MENU *m=(MENU *)w->object;
  93. menuresz(m,wi,he);
  94. }
  95. static void movetab(w,x,y)
  96. W *w;
  97. {
  98. MENU *m=(MENU *)w->object;
  99. menumove(m,x,y);
  100. }
  101. static void tdumb() {}
  102. X
  103. void tltarw(w)
  104. W *w;
  105. {
  106. MENU *m=(MENU *)w->object;
  107. mltarw(m);
  108. }
  109. void trtarw(w)
  110. W *w;
  111. {
  112. MENU *m=(MENU *)w->object;
  113. mrtarw(m);
  114. }
  115. void tuparw(w)
  116. W *w;
  117. {
  118. MENU *m=(MENU *)w->object;
  119. muparw(m);
  120. }
  121. void tdnarw(w)
  122. W *w;
  123. {
  124. MENU *m=(MENU *)w->object;
  125. mdnarw(m);
  126. }
  127. void tbof(w)
  128. W *w;
  129. {
  130. MENU *m=(MENU *)w->object;
  131. mbof(m);
  132. }
  133. void teof(w)
  134. W *w;
  135. {
  136. MENU *m=(MENU *)w->object;
  137. meof(m);
  138. }
  139. void tbol(w)
  140. W *w;
  141. {
  142. MENU *m=(MENU *)w->object;
  143. mbol(m);
  144. }
  145. void teol(w)
  146. W *w;
  147. {
  148. MENU *m=(MENU *)w->object;
  149. meol(m);
  150. }
  151. X
  152. int treload(w,m,tab,flg)
  153. W *w;
  154. MENU *m;
  155. TAB *tab;
  156. {
  157. BW *bw;
  158. P *p;
  159. int x;
  160. int which;
  161. char **list;
  162. struct stat buf;
  163. if((which=get_entries(tab,tab->prv))<0) return 1;
  164. if(tab->path && tab->path[0]) stat(tab->path,&buf);
  165. else stat(".",&buf);
  166. tab->prv=buf.st_ino;
  167. if(!flg) which=0;
  168. if(m) { vsrm(m->list); menurm(m); }
  169. list=vaensure(NULL,aLEN(tab->files));
  170. for(x=0;tab->files[x];++x)
  171. X {
  172. X vaset(list,x,vsncpy(NULL,0,sv(tab->files[x])));
  173. X if(tab->type[x]==F_DIR) list[x]=vsncpy(list[x],sLEN(list[x]),sc("/"));
  174. X else if(tab->type[x]==F_EXEC) list[x]=vsncpy(list[x],sLEN(list[x]),sc("*"));
  175. X }
  176. w->object=(void *)(m=mkmenu(w->t,list,w->x,w->y,w->w,w->h));
  177. m->object=tab;
  178. m->cursor=which;
  179. bw=(BW *)w->win->object;
  180. p=pdup(bw->cursor); pbol(p);
  181. peol(bw->cursor);
  182. bdel(p,bw->cursor);
  183. if(sLEN(tab->path))
  184. X {
  185. X binsm(bw->cursor,sv(tab->path)), peol(bw->cursor);
  186. X if(tab->path[sLEN(tab->path)-1]!='/')
  187. X  binsm(bw->cursor,sc("/")), peol(bw->cursor);
  188. X }
  189. binsm(bw->cursor,sv(tab->pattern)); peol(bw->cursor);
  190. prm(p);
  191. return 0;
  192. }
  193. void trtn(w)
  194. W *w;
  195. {
  196. MENU *m=(MENU *)w->object;
  197. TAB *tab=(TAB *)m->object;
  198. if(tab->type[m->cursor]==F_DIR)
  199. X { /* Switch directories */
  200. X char *orgpath=tab->path;
  201. X char *orgpattern=tab->pattern;
  202. X char *e=endprt(tab->path);
  203. X if(!zcmp(tab->files[m->cursor],"..") && sLEN(e) &&
  204. X    !(e[0]=='.' && e[1]=='.' && (!e[2] || e[2]=='/')))
  205. X  tab->path=begprt(tab->path);
  206. X else
  207. X  {
  208. X  tab->path=vsncpy(NULL,0,sv(tab->path));
  209. X  tab->path=vsncpy(tab->path,sLEN(tab->path),sv(m->list[m->cursor]));
  210. X  }
  211. X vsrm(e);
  212. X tab->pattern=vsncpy(NULL,0,sc("*"));
  213. X if(treload(w,m,tab,0))
  214. X  {
  215. X  msgnw(w,"Couldn\'t read directory ");
  216. X  vsrm(tab->pattern); tab->pattern=orgpattern;
  217. X  vsrm(tab->path); tab->path=orgpath;
  218. X  }
  219. X else
  220. X  {
  221. X  vsrm(orgpattern);
  222. X  vsrm(orgpath);
  223. X  }
  224. X }
  225. else
  226. X { /* Select name */
  227. X BW *bw=(BW *)w->win->object;
  228. X P *p;
  229. X p=pdup(bw->cursor); pbol(p);
  230. X peol(bw->cursor);
  231. X bdel(p,bw->cursor);
  232. X if(sLEN(tab->path))
  233. X  {
  234. X  binsm(bw->cursor,sv(tab->path)), peol(bw->cursor);
  235. X  if(tab->path[sLEN(tab->path)-1]!='/')
  236. X   binsm(bw->cursor,sc("/")), peol(bw->cursor);
  237. X  }
  238. X binsm(bw->cursor,sv(tab->files[m->cursor])); peol(bw->cursor);
  239. X bw->cursor->xcol=bw->cursor->col;
  240. X prm(p);
  241. X wabort(w);
  242. X }
  243. }
  244. X
  245. void tbacks(w)
  246. W *w;
  247. {
  248. MENU *m=(MENU *)w->object;
  249. TAB *tab=(TAB *)m->object;
  250. char *orgpath=tab->path;
  251. char *orgpattern=tab->pattern;
  252. char *e=endprt(tab->path);
  253. if(sLEN(e)) tab->path=begprt(tab->path);
  254. else
  255. X {
  256. X vsrm(e);
  257. X return;
  258. X }
  259. vsrm(e);
  260. tab->pattern=vsncpy(NULL,0,sc("*"));
  261. if(treload(w,m,tab,1))
  262. X {
  263. X msgnw(w,"Couldn\'t read directory ");
  264. X vsrm(tab->pattern); tab->pattern=orgpattern;
  265. X vsrm(tab->path); tab->path=orgpath;
  266. X }
  267. else
  268. X {
  269. X vsrm(orgpattern);
  270. X vsrm(orgpath);
  271. X }
  272. }
  273. X
  274. void tuabort(w)
  275. W *w;
  276. {
  277. BW *bw=(BW *)w->win->object;
  278. P *p=pdup(bw->cursor); pbol(p);
  279. peol(bw->cursor);
  280. bdel(p,bw->cursor);
  281. prm(p);
  282. wabort(w);
  283. }
  284. X
  285. static WATOM watomtab=
  286. {
  287. &cttab,
  288. disptab,
  289. followtab,
  290. wkilltab,
  291. resizetab,
  292. movetab,
  293. tdumb,
  294. tdumb,
  295. TYPETAB
  296. };
  297. X
  298. /* Create a tab window */
  299. X
  300. void ucmplt(w)
  301. W *w;
  302. {
  303. W *new;
  304. TAB *tab;
  305. P *p, *q;
  306. char *cline, *tmp;
  307. BW *bw;
  308. long a,b;
  309. if(!(new=wcreate(w->t,&watomtab,w,w,w->main,1,NULL))) return;
  310. tab=(TAB *)malloc(sizeof(TAB));
  311. tab->files=0;
  312. tab->type=0;
  313. bw=(BW *)w->object;
  314. p=pdup(bw->cursor); pbol(p);
  315. q=pdup(bw->cursor); peol(q);
  316. tmp=brvs(p,q->byte-p->byte);
  317. cline=parsens(tmp,&a,&b);
  318. vsrm(tmp);
  319. prm(p); prm(q);
  320. tmp=namprt(cline);
  321. tab->pattern=vsncpy(sv(tmp),sc("*"));
  322. tab->path=dirprt(cline);
  323. tab->prv=0;
  324. vsrm(cline);
  325. if(treload(new,NULL,tab,0))
  326. X {
  327. /* msgnw(w,"Couldn\'t read directory "); */
  328. X vsrm(tab->path);
  329. X vsrm(tab->pattern);
  330. X free(tab);
  331. X w->t->curwin=new;
  332. X wabort(new);
  333. X }
  334. else
  335. X {
  336. X w->t->curwin=new;
  337. X if(!sLEN(tab->files)) tuabort(new);
  338. X else if(sLEN(tab->files)==1) trtn(new);
  339. X }
  340. }
  341. SHAR_EOF
  342. chmod 0600 tab.c ||
  343. echo 'restore of tab.c failed'
  344. Wc_c="`wc -c < 'tab.c'`"
  345. test 6687 -eq "$Wc_c" ||
  346.     echo 'tab.c: original size 6687, current size' "$Wc_c"
  347. fi
  348. # ============= tab.h ==============
  349. if test -f 'tab.h' -a X"$1" != X"-c"; then
  350.     echo 'x - skipping tab.h (File already exists)'
  351. else
  352. echo 'x - extracting tab.h (Text)'
  353. sed 's/^X//' << 'SHAR_EOF' > 'tab.h' &&
  354. /* File selection menu
  355. X   Copyright (C) 1992 Joseph H. Allen
  356. X
  357. This file is part of JOE (Joe's Own Editor)
  358. X
  359. JOE is free software; you can redistribute it and/or modify it under the 
  360. terms of the GNU General Public License as published by the Free Software 
  361. Foundation; either version 1, or (at your option) any later version.  
  362. X
  363. JOE is distributed in the hope that it will be useful, but WITHOUT ANY 
  364. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  365. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  366. details.  
  367. X
  368. You should have received a copy of the GNU General Public License along with 
  369. JOE; see the file COPYING.  If not, write to the Free Software Foundation, 
  370. 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
  371. X
  372. #ifndef _Itab
  373. #define _Itab 1
  374. X
  375. #include "config.h"
  376. #include "kbd.h"
  377. X
  378. typedef struct tab TAB;
  379. X
  380. struct tab
  381. X {
  382. X char *path;
  383. X char *pattern;
  384. X int len;
  385. X char **files;
  386. X char *type;
  387. X int prv;
  388. X };
  389. X
  390. #define TYPETAB 0x400
  391. X
  392. void ucmplt();
  393. extern CONTEXT cttab;
  394. void tuabort();
  395. void tbacks();
  396. void tbof();
  397. void tbol();
  398. void teol();
  399. void teof();
  400. void tltarw();
  401. void tdnarw();
  402. void trtarw();
  403. void trtn();
  404. void tuparw();
  405. X
  406. #endif
  407. SHAR_EOF
  408. chmod 0600 tab.h ||
  409. echo 'restore of tab.h failed'
  410. Wc_c="`wc -c < 'tab.h'`"
  411. test 1173 -eq "$Wc_c" ||
  412.     echo 'tab.h: original size 1173, current size' "$Wc_c"
  413. fi
  414. # ============= termcap ==============
  415. if test -f 'termcap' -a X"$1" != X"-c"; then
  416.     echo 'x - skipping termcap (File already exists)'
  417. else
  418. echo 'x - extracting termcap (Text)'
  419. sed 's/^X//' << 'SHAR_EOF' > 'termcap' &&
  420. ##############################################################################
  421. #
  422. # Joe's termcap file
  423. #
  424. # These expect that you're using some kind of handshaking (no padding info
  425. # is given).  Also JOE doesn't use the last column of the screen, so the
  426. # am/xn parameters can be wrong
  427. #
  428. # JOE understands these extensions to termcap:
  429. #
  430. # AL DL SF SR IC DC UP DO RI LE - parametized versions of normal termcap
  431. #                                 capabilities.  For example, AL inserts n
  432. #                                 lines and LE moves n positions left.
  433. #
  434. # rr                            - Flag which indicates that the cursor
  435. #                                 is restricted to scrolling region (cursor
  436. #                                 addressing is still screen relative, however).
  437. #
  438. # cb                            - Like cv, but goes to beginning of given
  439. #                                 line.
  440. #
  441. ##############################################################################
  442. X
  443. # The pre-ansi terminal
  444. X
  445. vt52|dec vt52:\
  446. X    :co#80:li#24:\
  447. X    :ho=\EH:cm=\EY%+ %+ :\
  448. X    :up=\EA:nd=\EC:pt:bs:\
  449. X    :cd=\EJ:ce=\EK:cl=\EH\EJ:\
  450. X    :sr=\EI:\
  451. X    :ku=\EA:kd=\EB:kr=\EC:kl=\ED:
  452. X
  453. ##############################################################################
  454. #
  455. # The "ANSI" family of terminals
  456. #
  457. ##############################################################################
  458. X
  459. # The capabilities in this entry are understood to be the least-common
  460. # denominator of what's called ANSI (except, of course, for the IBM PC, which
  461. # doesn't know what ESC [ J is).
  462. X
  463. ansi|Basic Ansi tty:\
  464. X    :co#80:li#25:am:\
  465. X    :ho=\E[H:cm=\E[%i%d;%dH:cb=\E[%i%dH:\
  466. X    :up=\E[A:UP=\E[%dA:DO=\E[%dB:nd=\E[C:RI=\E[%dC:pt:bs:LE=\E[%dD:\
  467. X    :cd=\E[J:ce=\E[K:cl=\E[H\E[J:\
  468. X    :so=\E[7m:se=\E[m:ms:us=\E[4m:ue=\E[m:\
  469. X    :mb=\E[5m:md=\E[1m:mh=\E[2m:me=\E[m:\
  470. X    :ku=\E[A:kd=\E[B:kl=\E[D:kr=\E[C:
  471. X
  472. # Use for good implementations of non-DEC ansi.  Most PC UNIX consoles
  473. # look like this
  474. X
  475. fansi|Full Ansi tty (includes inserts and deletes):\
  476. X    :al=\E[L:AL=\E[%dL:dl=\E[M:DL=\E[%dM:\
  477. X    :ic=\E[@:IC=\E[%d@:dc=\E[P:DC=\E[%dP:\
  478. X    :tc=ansi:
  479. X
  480. # Use for vt100-like ansi implementations
  481. X
  482. ansi100:Ansi tty with scrolling regions but no inserts or deletes:\
  483. X    :li#24:\
  484. X    :cs=\E[%i%d;%dr:sr=\EM:\
  485. X    :tc=ansi:
  486. X
  487. # Advanced DEC-style ansi terminals.  Use for vt102s and above
  488. X
  489. decansi:Full DEC-style Ansi tty (scrolling regions/insert mode/deletes):\
  490. X    :li#24:\
  491. X    :cs=\E[%i%d;%dr:sr=\EM:\
  492. X    :al=\E[L:AL=\E[%dL:dl=\E[M:DL=\E[%dM:\
  493. X    :im=\E[4h:ei=\E[4l:mi:dc=\E[P:DC=\E[%dP:\
  494. X    :tc=ansi:
  495. X
  496. ##############################################################################
  497. #
  498. # Derived "ANSI" terminals
  499. #
  500. ##############################################################################
  501. X
  502. ansisys|IBM PC using ANSI.SYS:\
  503. X        :cd@:ms@:pt@:cl=\E[H\E[2J:do=\E[B:\
  504. X    :ku=^@H:kd=^@P:kl=^@K:kr=^@M:\
  505. X    :kI=^@R:kD=^@S:kh=^@G:kH=^@O:kP=^@I:kN=^@Q:\
  506. X    :k1=^@;:k2=^@<:k3=^@=:k4=^@>:k5=^@?:\
  507. X    :k6=^@@:k7=^@A:k8=^@B:k9=^@C:k0=^@D:\
  508. X        :tc=ansi:
  509. X
  510. nansisys|IBM PC using NANSI.SYS or ZANSI.SYS:\
  511. X        :cd@:ms@:pt@:cl=\E[H\E[2J:do=\E[B:\
  512. X    :ku=^@H:kd=^@P:kl=^@K:kr=^@M:\
  513. X    :kI=^@R:kD=^@S:kh=^@G:kH=^@O:kP=^@I:kN=^@Q:\
  514. X    :k1=^@;:k2=^@<:k3=^@=:k4=^@>:k5=^@?:\
  515. X    :k6=^@@:k7=^@A:k8=^@B:k9=^@C:k0=^@D:\
  516. X        :tc=fansi:
  517. X
  518. xenix:Xenix console:\
  519. X    :bt=\E[Z:\
  520. X    :kI=\E[L:kD=^?:kh=\E[H:kH=\E[F:kP=\E[I:kN=\E[G:\
  521. X    :k1=\E[M:k2=\E[N:k3=\E[O:k4=\E[P:k5=\E[Q:\
  522. X    :k6=\E[R:k7=\E[S:k8=\E[T:k9=\E[U:k0=\E[V:\
  523. X    :tc=fansi:
  524. X
  525. linux:Linux console:\
  526. X    :kI=\E[2~:kD=\E[3~:kh=\E[1~:kH=\E[4~:kP=\E[5~:kN=\E[6~:\
  527. X    :k1=\E[[A:k2=\E[[B:k3=\E[[C:k4=\E[[D:k5=\E[[E:\
  528. X    :k6=\E[17~:k7=\E[18~:k8=\E[19~:k9=\E[20~:k10=\E[21~:\
  529. X    :tc=fansi:
  530. X
  531. pt:Convergent Technologies PT booted from a miniframe:\
  532. X    :li#26:ns:\
  533. X    :k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k5=\EOT:\
  534. X    :k6=\EOU:k7=\EOV:k8=\EOW:k9=\EOX:k0=\EOY:\
  535. X    :tc=fansi:
  536. X
  537. ptem:Convergent Technologies PT using its own firmware:\
  538. X    :li#26:rr:\
  539. X    :k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k5=\EOT:\
  540. X    :k6=\EOU:k7=\EOV:k8=\EOW:k9=\EOX:k0=\EOY:\
  541. X    :tc=decansi:
  542. X
  543. xterm|X windows terminal emulator:\
  544. X    :xn:\
  545. X    :kb=\b:ks=\E=:ke=\E>:\
  546. X    :k1=\E[11~:k2=\E[12~:k3=\E[13~:k4=\E[14~:k5=\E[15~:\
  547. X    :k6=\E[17~:k7=\E[18~:k8=\E[19~:k9=\E[20~:k0=\E[21~:\
  548. X    :kh=\E[8~:\
  549. X    :tc=decansi:
  550. X
  551. vt100|DEC VT100:\
  552. X    :li#24:\
  553. X    :ks=\E\075:ke=\E\076:\
  554. X    :kh=\E[H:\
  555. X    :k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\
  556. X    :tc=ansi100:
  557. X
  558. vt102|DEC VT102:\
  559. X    :li#24:\
  560. X    :ks=\E\075:ke=\E\076:\
  561. X    :kh=\E[H:\
  562. X    :k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\
  563. X    :tc=decansi:
  564. X
  565. vt220|DEC VT220:\
  566. X    :ke=\E>:ks=\E=:\
  567. X    :kb=^?:\
  568. X    :kI=\E[2~:kD=\E[3~:kh=\E[1~:kH=\E[4~:kP=\E[5~:kN=\E[6~:\
  569. X    :k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k5=\E[17~:\
  570. X    :k6=\E[18~:k7=\E[19~:k8=\E[20~:k9=\E[21~:k0=\E[29~:\
  571. X    :tc=decansi:
  572. SHAR_EOF
  573. chmod 0600 termcap ||
  574. echo 'restore of termcap failed'
  575. Wc_c="`wc -c < 'termcap'`"
  576. test 4577 -eq "$Wc_c" ||
  577.     echo 'termcap: original size 4577, current size' "$Wc_c"
  578. fi
  579. # ============= termcap.c ==============
  580. if test -f 'termcap.c' -a X"$1" != X"-c"; then
  581.     echo 'x - skipping termcap.c (File already exists)'
  582. else
  583. echo 'x - extracting termcap.c (Text)'
  584. sed 's/^X//' << 'SHAR_EOF' > 'termcap.c' &&
  585. /* TERMCAP database interface
  586. X   Copyright (C) 1992 Joseph H. Allen
  587. X
  588. This file is part of JOE (Joe's Own Editor)
  589. X
  590. JOE is free software; you can redistribute it and/or modify it under the 
  591. terms of the GNU General Public License as published by the Free Software 
  592. Foundation; either version 1, or (at your option) any later version.  
  593. X
  594. JOE is distributed in the hope that it will be useful, but WITHOUT ANY 
  595. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  596. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  597. details.  
  598. X
  599. You should have received a copy of the GNU General Public License along with 
  600. JOE; see the file COPYING.  If not, write to the Free Software Foundation, 
  601. 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
  602. X
  603. #include <stdio.h>
  604. #include <sys/types.h>
  605. #include <sys/stat.h>
  606. #include "config.h"
  607. #include "blocks.h"
  608. #include "heap.h"
  609. #include "vs.h"
  610. #include "va.h"
  611. #include "zstr.h"
  612. #include "queue.h"
  613. #include "termcap.h"
  614. X
  615. /* Return true if termcap line matches name */
  616. X
  617. static int match(s,name)
  618. char *s, *name;
  619. {
  620. if(s[0]==0 || s[0]=='#') return 0;
  621. do
  622. X {
  623. X int x;
  624. X for(x=0;s[x]==name[x] && name[x] && s[x];++x);
  625. X if(name[x]==0 && (s[x]==':' || s[x]=='|')) return 1;
  626. X while(s[x]!=':' && s[x]!='|' && s[x]) ++x;
  627. X s+=x+1;
  628. X }
  629. X while(s[-1]=='|');
  630. return 0;
  631. }
  632. X
  633. /* Find termcap entry in a file */
  634. X
  635. static char *lfind(s,pos,fd,name)
  636. char *s, *name;
  637. FILE *fd;
  638. int pos;
  639. {
  640. int c,x;
  641. if(!s) s=vsmk(1024);
  642. loop:
  643. while(c=getc(fd), c==' ' || c=='\t' || c=='#')
  644. X do c=getc(fd); while(!(c== -1 || c=='\n'));
  645. if(c== -1) return s=vstrunc(s,pos);
  646. ungetc(c,fd);
  647. s=vstrunc(s,x=pos);
  648. while(1)
  649. X {
  650. X c=getc(fd);
  651. X if(c== -1 || c=='\n')
  652. X  if(x!=pos && s[x-1]=='\\')
  653. X   {
  654. X   --x;
  655. X   if(!match(s+pos,name)) goto loop;
  656. X   else break;
  657. X   }
  658. X  else
  659. X   if(!match(s+pos,name)) goto loop;
  660. X   else return vstrunc(s,x);
  661. X else if(c=='\r') ;
  662. X else s=vsset(s,x,c), ++x;
  663. X }
  664. while(c=getc(fd), c!= -1)
  665. X if(c=='\n')
  666. X  if(s[x-1]=='\\') --x;
  667. X  else break;
  668. X else if(c=='\r') ;
  669. X else s=vsset(s,x,c), ++x;
  670. s=vstrunc(s,x);
  671. return s;
  672. }
  673. X
  674. /* Lookup termcap entry in index */
  675. X
  676. static long findidx(file,name)
  677. FILE *file;
  678. char *name;
  679. {
  680. char buf[80];
  681. long addr=0;
  682. while(fgets(buf,80,file))
  683. X {
  684. X int x=0, flg=0, c, y, z;
  685. X do
  686. X  {
  687. X  int y;
  688. X  for(y=x;buf[y] && buf[y]!=' ' && buf[y]!='\n';++y);
  689. X  c=buf[y]; buf[y]=0;
  690. X  if(c=='\n' || !c)
  691. X   {
  692. X   z=0; sscanf(buf+x,"%x",&z);
  693. X   addr+=z;
  694. X   }
  695. X  else if(!zcmp(buf+x,name)) flg=1;
  696. X  x=y+1;
  697. X  }
  698. X  while(c && c!='\n');
  699. X if(flg) return addr;
  700. X }
  701. return 0;
  702. }
  703. X
  704. /* Load termcap entry */
  705. X
  706. CAP *getcap(name,baud,out,outptr)
  707. char *name;
  708. unsigned baud;
  709. void (*out)();
  710. void *outptr;
  711. {
  712. CAP *cap;
  713. FILE *f, *f1;
  714. long idx;
  715. int x,y,c,z,ti;
  716. char *tp, *pp, *qq, *namebuf, **npbuf, *idxname;
  717. int sortsiz;
  718. X
  719. if(!name && !(name=getenv("TERM"))) return 0;
  720. name=vsncpy(NULL,0,sz(name));
  721. X
  722. cap=(CAP *)malloc(sizeof(CAP));
  723. cap->tbuf=vsmk(1024);
  724. cap->sort=(struct sortentry *)malloc(sizeof(struct sortentry)*(sortsiz=64));
  725. cap->sortlen=0;
  726. X
  727. tp=getenv("TERMCAP");
  728. X
  729. if(tp && tp[0]=='/') namebuf=vsncpy(NULL,0,sz(tp));
  730. else
  731. X {
  732. X if(tp) vsncpy(sv(cap->tbuf),sz(tp));
  733. X if((tp=getenv("TERMPATH"))) namebuf=vsncpy(NULL,0,sz(tp));
  734. X else if((tp=getenv("HOME")))
  735. X  namebuf=vsncpy(NULL,0,sz(tp)),
  736. X  namebuf=vsadd(namebuf,'/'),
  737. X  namebuf=vsncpy(sv(namebuf),sz(TERMPATH));
  738. X else namebuf=vsncpy(NULL,0,sz(TERMPATH));
  739. X }
  740. X
  741. npbuf=vawords(NULL,sv(namebuf),sc("\t "));
  742. vsrm(namebuf);
  743. X
  744. y=0; ti=0;
  745. X
  746. if(match(cap->tbuf,name)) goto checktc;
  747. X
  748. dofiles:
  749. cap->tbuf=vstrunc(cap->tbuf,0);
  750. X
  751. nextfile:
  752. if(!npbuf[y])
  753. X {
  754. X varm(npbuf);
  755. X vsrm(name);
  756. X vsrm(cap->tbuf);
  757. X free(cap->sort);
  758. X free(cap);
  759. X return 0;
  760. X }
  761. idx=0;
  762. idxname=vsncpy(NULL,0,sz(npbuf[y]));
  763. idxname=vsncpy(idxname,sLEN(idxname),sc(".idx"));
  764. f1=fopen(npbuf[y],"r");
  765. ++y;
  766. if(!f1) goto nextfile;
  767. f=fopen(idxname,"r");
  768. if(f)
  769. X {
  770. X struct stat buf, buf1;
  771. X fstat(fileno(f),&buf);
  772. X fstat(fileno(f1),&buf1);
  773. X if(buf.st_mtime>buf1.st_mtime) idx=findidx(f,name);
  774. X else fprintf(stderr,"%s is out of date\n",idxname);
  775. X fclose(f);
  776. X }
  777. vsrm(idxname);
  778. fseek(f1,idx,0);
  779. cap->tbuf=lfind(cap->tbuf,ti,f1,name);
  780. fclose(f1);
  781. if(sLEN(cap->tbuf)==ti) goto nextfile;
  782. X
  783. checktc:
  784. x=sLEN(cap->tbuf);
  785. do
  786. X {
  787. X cap->tbuf[x]=0;
  788. X while(x && cap->tbuf[--x]!=':');
  789. X }
  790. X while(x && (!cap->tbuf[x+1] || cap->tbuf[x+1]==':'));
  791. X
  792. if(cap->tbuf[x+1]=='t' && cap->tbuf[x+2]=='c' && cap->tbuf[x+3]=='=')
  793. X {
  794. X name=vsncpy(NULL,0,sz(cap->tbuf+x+4));
  795. X cap->tbuf[x]=0;
  796. X cap->tbuf[x+1]=0;
  797. X ti=x+1;
  798. X sLen(cap->tbuf)=x+1;
  799. X if(y) --y;
  800. X goto nextfile;
  801. X }
  802. X
  803. doline:
  804. pp=cap->tbuf+ti;
  805. X
  806. /* Process line at pp */
  807. X
  808. loop:
  809. while(*pp && *pp!=':') ++pp;
  810. if(*pp)
  811. X {
  812. X int q;
  813. X *pp++=0;
  814. X loop1:
  815. X if(pp[0]==' ' || pp[0]=='\t') goto loop;
  816. X for(q=0;pp[q] && pp[q]!='#' && pp[q]!='=' && pp[q]!='@' && pp[q]!=':';++q);
  817. X qq=pp;
  818. X c=pp[q]; pp[q]=0;
  819. X if(c) pp+=q+1;
  820. X else pp+=q;
  821. X
  822. X x=0; y=cap->sortlen; z= -1;
  823. X if(!y) { z=0; goto in; }
  824. X while(z!=(x+y)/2)
  825. X  {
  826. X  z=(x+y)/2;
  827. X  switch(zcmp(qq,cap->sort[z].name))
  828. X   {
  829. X  case  1: x=z; break;
  830. X  case -1: y=z; break;
  831. X  case  0:
  832. X   if(c=='@')
  833. X    mfwrd(cap->sort+z,cap->sort+z+1,
  834. X          (cap->sortlen---(z+1))*sizeof(struct sortentry));
  835. X   else
  836. X    if(c && c!=':') cap->sort[z].value=qq+q+1;
  837. X    else cap->sort[z].value=0;
  838. X   if(c==':') goto loop1;
  839. X   else goto loop;
  840. X   }
  841. X  }
  842. X in:
  843. X if(cap->sortlen==sortsiz)
  844. X  cap->sort=(struct sortentry *)realloc(cap->sort,
  845. X                                        (sortsiz+=32)*sizeof(struct sortentry));
  846. X mbkwd(cap->sort+y+1,cap->sort+y,
  847. X       (cap->sortlen++-y)*sizeof(struct sortentry));
  848. X cap->sort[y].name=qq;
  849. X if(c && c!=':') cap->sort[y].value=qq+q+1;
  850. X else cap->sort[y].value=0;
  851. X if(c==':') goto loop1;
  852. X else goto loop;
  853. X }
  854. X
  855. if(ti)
  856. X {
  857. X for(--ti;ti;--ti) if(!cap->tbuf[ti-1]) break;
  858. X goto doline;
  859. X }
  860. X
  861. varm(npbuf);
  862. vsrm(name);
  863. X
  864. cap->pad=getstr(cap,"pc");
  865. if(getenv("DOPADDING")) cap->dopadding=1;
  866. else cap->dopadding=0;
  867. return setcap(cap,baud,out,outptr);
  868. }
  869. X
  870. struct sortentry *findcap(cap,name)
  871. CAP *cap;
  872. char *name;
  873. {
  874. int x,y,z;
  875. x=0; y=cap->sortlen; z= -1;
  876. while(z!=(x+y)/2)
  877. X {
  878. X z=(x+y)/2;
  879. X switch(zcmp(name,cap->sort[z].name))
  880. X  {
  881. X case  1: x=z; break;
  882. X case -1: y=z; break;
  883. X case  0: return cap->sort+z;
  884. X  }
  885. X }
  886. return 0;
  887. }
  888. X
  889. CAP *setcap(cap,baud,out,outptr)
  890. CAP *cap;
  891. unsigned baud;
  892. void (*out)();
  893. void *outptr;
  894. {
  895. cap->baud=baud;
  896. cap->div=100000/baud;
  897. cap->out=out;
  898. cap->outptr=outptr;
  899. return cap;
  900. }
  901. X
  902. int getflag(cap,name)
  903. CAP *cap;
  904. char *name;
  905. {
  906. return findcap(cap,name)!=0;
  907. }
  908. X
  909. char *getstr(cap,name)
  910. CAP *cap;
  911. char *name;
  912. {
  913. struct sortentry *s=findcap(cap,name);
  914. if(s) return s->value;
  915. else return 0;
  916. }
  917. X
  918. int getnum(cap,name)
  919. CAP *cap;
  920. char *name;
  921. {
  922. struct sortentry *s=findcap(cap,name);
  923. if(s && s->value) return atoi(s->value);
  924. return -1;
  925. }
  926. X
  927. void rmcap(cap)
  928. CAP *cap;
  929. {
  930. vsrm(cap->tbuf);
  931. free(cap->sort);
  932. free(cap);
  933. }
  934. X
  935. static char escape(s)
  936. char **s;
  937. {
  938. char c= *(*s)++;
  939. if(c=='^' && **s)
  940. X if(**s!='?') return 037&*(*s)++;
  941. X else return (*s)++, 127;
  942. else if(c=='\\' && **s)
  943. X switch(c= *((*s)++))
  944. X  {
  945. X case '0': case '1': case '2': case'3': case '4': case '5': case '6': case '7':
  946. X           c-='0';
  947. X           if(**s>='0' && **s<='7') c=(c<<3)+*((*s)++)-'0';
  948. X           if(**s>='0' && **s<='7') c=(c<<3)+*((*s)++)-'0';
  949. X           return c;
  950. X case 'e':
  951. X case 'E': return 27;
  952. X case 'n':
  953. X case 'l': return 10;
  954. X case 'r': return 13;
  955. X case 't': return 9;
  956. X case 'b': return 8;
  957. X case 'f': return 12;
  958. X case 's': return 32;
  959. X default: return c;
  960. X  }
  961. else return c;
  962. }
  963. X
  964. void texec(cap,s,l,a0,a1,a2,a3)
  965. CAP *cap;
  966. char *s;
  967. int l,a0,a1,a2,a3;
  968. {
  969. int c, tenth=0, x;
  970. int args[4];
  971. int vars[128];
  972. int *a=args;
  973. X
  974. /* Copy args into array (yuk) */
  975. args[0]=a0; args[1]=a1; args[2]=a2; args[3]=a3;
  976. X
  977. /* Do nothing if there is no string */
  978. if(!s) return;
  979. X
  980. /* Get tenths of MS of padding needed */
  981. while(*s>='0' && *s<='9') tenth=tenth*10+*s++-'0';
  982. tenth*=10;
  983. if(*s=='.') ++s, tenth+= *s++-'0';
  984. X
  985. /* Check if we have to multiply by number of lines */
  986. if(*s=='*') ++s, tenth*=l;
  987. X
  988. /* Output string */
  989. while(c= *s++)
  990. X if(c=='%' && *s)
  991. X  switch(x=a[0], c= escape(&s))
  992. X   {
  993. X  case 'C': if(x>=96) cap->out(cap->outptr,x/96), x%=96;
  994. X  case '+': if(*s) x+= escape(&s);
  995. X  case '.': cap->out(cap->outptr,x); ++a; break;
  996. X  case 'd': if(x<10) goto one;
  997. X  case '2': if(x<100) goto two;
  998. X  case '3': c='0'; while(x>=100) ++c, x-=100; cap->out(cap->outptr,c);
  999. X       two: c='0'; while(x>=10) ++c, x-=10; cap->out(cap->outptr,c);
  1000. X       one: cap->out(cap->outptr,'0'+x); ++a; break;
  1001. X  case 'r': a[0]=a[1]; a[1]=x; break;
  1002. X  case 'i': ++a[0]; ++a[1]; break;
  1003. X  case 'n': a[0]^=0140; a[1]^=0140; break;
  1004. X  case 'm': a[0]^=0177; a[1]^=0177; break;
  1005. X  case 'f': ++a; break;
  1006. X  case 'b': --a; break;
  1007. X  case 'a': x=s[2];
  1008. X            if(s[1]=='p') x=a[x-0100];
  1009. X            switch(*s)
  1010. X             {
  1011. X             case '+': a[0]+=x; break;
  1012. X             case '-': a[0]-=x; break;
  1013. X             case '*': a[0]*=x; break;
  1014. X             case '/': a[0]/=x; break;
  1015. X             case '%': a[0]%=x; break;
  1016. X             case 'l': a[0]=vars[x]; break;
  1017. X             case 's': vars[x]=a[0]; break;
  1018. X             default:  a[0]=x;
  1019. X             }
  1020. X            s+=3;
  1021. X            break;
  1022. X  case 'D': a[0]=a[0]-2*(a[0]&15); break;
  1023. X  case 'B': a[0]=16*(a[0]/10)+a[0]%10; break;
  1024. X  case '>': if(a[0]>escape(&s)) a[0]+=escape(&s); else escape(&s);
  1025. X   default: cap->out(cap->outptr,'%'); cap->out(cap->outptr,c);
  1026. X   }
  1027. X else --s, cap->out(cap->outptr,escape(&s));
  1028. X
  1029. /* Output padding characters */
  1030. if(cap->dopadding)
  1031. X if(cap->pad)
  1032. X  while(tenth>=cap->div)
  1033. X   for(s=cap->pad;*s;++s) cap->out(cap->outptr,*s), tenth-=cap->div;
  1034. X else
  1035. X  while(tenth>=cap->div) cap->out(cap->outptr,0), tenth-=cap->div;
  1036. }
  1037. X
  1038. static int total;
  1039. X
  1040. static void cst()
  1041. {
  1042. ++total;
  1043. }
  1044. X
  1045. int tcost(cap,s,l,a0,a1,a2,a3)
  1046. CAP *cap;
  1047. char *s;
  1048. int l,a0,a1,a2,a3;
  1049. {
  1050. void (*out)()=cap->out;
  1051. if(!s) return 10000;
  1052. total=0;
  1053. cap->out=cst;
  1054. texec(cap,s,l,a0,a1,a2,a3);
  1055. cap->out=out;
  1056. return total;
  1057. }
  1058. X
  1059. static char *ssp;
  1060. static void cpl(ptr,c)
  1061. char *ptr;
  1062. char c;
  1063. {
  1064. vsadd(ssp,c);
  1065. }
  1066. X
  1067. char *tcompile(cap,s,a0,a1,a2,a3)
  1068. CAP *cap;
  1069. char *s;
  1070. int a0,a1,a2,a3;
  1071. {
  1072. void (*out)()=cap->out;
  1073. int div=cap->div;
  1074. if(!s) return 0;
  1075. cap->out=cpl; cap->div=10000;
  1076. ssp=vsmk(10);
  1077. texec(cap,s,0,a0,a1,a2,a3);
  1078. cap->out=out; cap->div=div;
  1079. return ssp;
  1080. }
  1081. X
  1082. /* Old termcap compatibility */
  1083. X
  1084. short ospeed;        /* Output speed */
  1085. char PC, *UP, *BC;        /* Unused */
  1086. static CAP *latest;    /* CAP entry to use */
  1087. X
  1088. static stupid(ptr,c)
  1089. void (*ptr)();
  1090. char c;
  1091. {
  1092. ptr(c);
  1093. }
  1094. X
  1095. int tgetent(buf,name)
  1096. char *buf, *name;
  1097. {
  1098. latest=getcap(name,9600,stupid,NULL);
  1099. if(latest) return 1;
  1100. else return -1;
  1101. }
  1102. X
  1103. int tgetflag(name)
  1104. char *name;
  1105. {
  1106. return getflag(latest,name);
  1107. }
  1108. X
  1109. int tgetnum(name)
  1110. char *name;
  1111. {
  1112. return getnum(latest,name);
  1113. }
  1114. X
  1115. char *tgetstr(name)
  1116. char *name;
  1117. {
  1118. return getstr(latest,name);
  1119. }
  1120. X
  1121. static int latestx, latesty;
  1122. X
  1123. char *tgoto(str,x,y)
  1124. char *str;
  1125. int x,y;
  1126. {
  1127. latestx=x; latesty=y;
  1128. return str;
  1129. }
  1130. X
  1131. void tputs(str,l,out)
  1132. char *str;
  1133. int l;
  1134. void (*out)();
  1135. {
  1136. latest->outptr=(void *)out;
  1137. if(latest->baud!=ospeed) latest->baud=ospeed, latest->div=100000/ospeed;
  1138. texec(latest,str,l,latesty,latestx);
  1139. }
  1140. SHAR_EOF
  1141. chmod 0600 termcap.c ||
  1142. echo 'restore of termcap.c failed'
  1143. Wc_c="`wc -c < 'termcap.c'`"
  1144. test 10843 -eq "$Wc_c" ||
  1145.     echo 'termcap.c: original size 10843, current size' "$Wc_c"
  1146. fi
  1147. # ============= termcap.h ==============
  1148. if test -f 'termcap.h' -a X"$1" != X"-c"; then
  1149.     echo 'x - skipping termcap.h (File already exists)'
  1150. else
  1151. echo 'x - extracting termcap.h (Text)'
  1152. sed 's/^X//' << 'SHAR_EOF' > 'termcap.h' &&
  1153. /* TERMCAP/TERMINFO header file
  1154. X   Copyright (C) 1992 Joseph H. Allen
  1155. X
  1156. This file is part of JOE (Joe's Own Editor)
  1157. X
  1158. JOE is free software; you can redistribute it and/or modify it under the 
  1159. terms of the GNU General Public License as published by the Free Software 
  1160. Foundation; either version 1, or (at your option) any later version.  
  1161. X
  1162. JOE is distributed in the hope that it will be useful, but WITHOUT ANY 
  1163. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  1164. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  1165. details.  
  1166. X
  1167. You should have received a copy of the GNU General Public License along with 
  1168. JOE; see the file COPYING.  If not, write to the Free Software Foundation, 
  1169. 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
  1170. X
  1171. #ifndef _Itermcap
  1172. #define _Itermcap 1
  1173. X
  1174. #include "config.h"
  1175. X
  1176. typedef struct cap CAP;
  1177. X
  1178. #define TERMPATH ".termcap /etc/termcap"
  1179. X
  1180. struct sortentry
  1181. X {
  1182. X char *name;
  1183. X char *value;
  1184. X };
  1185. X
  1186. struct cap
  1187. X {
  1188. X char *tbuf;            /* Termcap entry loaded here */
  1189. X
  1190. X struct sortentry *sort;    /* Pointers to each capability stored in here */
  1191. X int sortlen;            /* Number of capabilities */
  1192. X
  1193. X char *abuf;            /* For terminfo compatible version */
  1194. X char *abufp;
  1195. X int div;            /* tenths of MS per char */
  1196. X int baud;            /* Baud rate */
  1197. X char *pad;            /* Padding string or NULL to use NUL */
  1198. X void (*out)();            /* Character output routine */
  1199. X void *outptr;            /* First arg passed to output routine.  Second
  1200. X                    arg is character to write */
  1201. X int dopadding;            /* Set if pad characters should be used */
  1202. X };
  1203. X
  1204. /* CAP *getcap(char *s,int baud,void (*out)(void *outptr,char c),void *outptr);
  1205. X *
  1206. X * Get CAP entry for terminal named in 's'.  If 's' is zero, the name in
  1207. X * the environment variable 'TERM' is used instead.  Space for the returned
  1208. X * CAP is allocated from the heap using malloc.
  1209. X *
  1210. X * 'baud'   is the baud rate used for 'texec' to calculate number of pad chars
  1211. X * 'out'    is the function 'texec' uses to output characters
  1212. X * 'outptr' is the passed as the first arg to 'out'
  1213. X *
  1214. X * This is how 'getcap' finds the entry:  First a list of file names is
  1215. X * built.  If the environment variable 'TERMCAP' begins with a '/', it
  1216. X * is used as the list of file names.  Otherwise, if the environment
  1217. X * variable 'TERMPATH' is set, it is used as the list of file names.  If
  1218. X * that isn't set, then the string TERMPATH defined above is appended
  1219. X * to value of the 'HOME' environment variable, and that is used as the
  1220. X * list of names (a '/' is placed between the value of the environment
  1221. X * variable and the string).  If HOME isn't set, then TERMPATH alone is
  1222. X * used as the list of file names (without prepending a '/').
  1223. X *
  1224. X * Now the contents of the environment variable 'TERMCAP' (if it's defined and
  1225. X * if it doesn't begin with a '/') and the files from the above list are
  1226. X * scanned for the terminal name.  The contents of the environment variable
  1227. X * are scanned first, then the files are scanned in the order they appear in
  1228. X * the named list.
  1229. X *
  1230. X * If the last part of a matching termcap entry is a 'tc=filename', then
  1231. X * the current file is rewound and rescanned for the matching entry (and if
  1232. X * it's not found, the next entry in the file name list is searched).  If
  1233. X * a matching termcap entry in the TERMCAP environment variable ends with
  1234. X * a 'tc=filename', then all of the files in the name list are searched.
  1235. X *
  1236. X * There is no limit on the size of the termcap entries.  No checking is
  1237. X * done for self-refering 'tc=filename' links (so all of core will be
  1238. X * allocated if there are any).
  1239. X */
  1240. CAP *getcap();
  1241. X
  1242. /* CAP *setcap(CAP *cap,int baud,void (*out)(void *outptr,char c),void *outptr);
  1243. X *
  1244. X * Reset baud, out and outptr for a CAP
  1245. X */ 
  1246. CAP *setcap();
  1247. X
  1248. /* char *getstr(CAP *cap,char *name);
  1249. X *
  1250. X * Get value of string capability or return NULL if it's not found.  A fast
  1251. X * binary search is used to find the capability.  The char * returned points into
  1252. X * the buffer used to load the termcap entry.  It should not be modified or
  1253. X * freed.
  1254. X */
  1255. char *getstr();
  1256. X
  1257. /* int getflag(CAP *cap,char *name);
  1258. X *
  1259. X * Return true if the named capability is found in 'cap'.  A fast binary
  1260. X * search is used to lookup the capability.
  1261. X */
  1262. int getflag();
  1263. X
  1264. /* int getnum(CAP *cap,char *name);
  1265. X *
  1266. X * Return value of numeric capability or return -1 if it's not found.  A fast
  1267. X * binary search is used to lookup the capability.
  1268. X */
  1269. int getnum();
  1270. X
  1271. /* void rmcap(CAP *cap);
  1272. X *
  1273. X * Eliminate a CAP entry.
  1274. X */
  1275. void rmcap();
  1276. X
  1277. /* void texec(CAP *cap,char *str,int l,int a0,int a1,int a2,int a3);
  1278. X
  1279. X   Execute and output a termcap string capability.
  1280. X
  1281. X   'cap' is the CAP returned by getcap which contains the baud rate and output
  1282. X   function.
  1283. X   
  1284. X   'str' is the string to execute.  If 'str'==NULL, nothing happens.
  1285. X   
  1286. X   'l' is the number of lines effected by this string.  For example, if you
  1287. X   use the clear to end of screen capability, the number of lines between
  1288. X   the current cursor position and the end of the screen should be
  1289. X   given here.
  1290. X
  1291. X   'a0' - 'a1' are the arguments for the string
  1292. */
  1293. void texec();
  1294. X
  1295. /* int tcost(CAP *cap,char *str, int l, int a0, int a1, int a2, int a3);
  1296. X   Return cost in number of characters which need to be sent
  1297. X   to execute a termcap string capability.
  1298. X
  1299. X   'cap' is the CAP returned by getcap which contains the baud rate and output
  1300. X   functions.
  1301. X   
  1302. X   'str' is the string to execute.  If 'str'==NULL, tcost return 10000.
  1303. X   
  1304. X   'l' is the number of lines effected by this string.  Ex: if you
  1305. X   use the clear to end of screen capability, the number of lines between
  1306. X   the current cursor position and the end of the screen should be
  1307. X   given here.
  1308. X
  1309. X   'a0' - 'a3' are arguements passed to the string
  1310. */
  1311. int tcost();
  1312. X
  1313. /* char *tcompile(CAP *cap,char *str,int a0,int a1,int a2,int a3);
  1314. X
  1315. X   Compile a string capability.  Returns a pointer to a variable length
  1316. X   string (see vstr.h) containing the compiled string capability.
  1317. X   Pad characters are not placed in the string.
  1318. */
  1319. char *tcompile();
  1320. X
  1321. /* Old termcap support */
  1322. int tgetent();
  1323. char *tgetstr();
  1324. int tgetflag();
  1325. int tgetnum();
  1326. char *tgoto();
  1327. void tputs();
  1328. extern short ospeed;
  1329. extern char PC, *UP, *BC;
  1330. X
  1331. #endif
  1332. SHAR_EOF
  1333. chmod 0600 termcap.h ||
  1334. echo 'restore of termcap.h failed'
  1335. Wc_c="`wc -c < 'termcap.h'`"
  1336. test 6116 -eq "$Wc_c" ||
  1337.     echo 'termcap.h: original size 6116, current size' "$Wc_c"
  1338. fi
  1339. # ============= termidx.c ==============
  1340. if test -f 'termidx.c' -a X"$1" != X"-c"; then
  1341.     echo 'x - skipping termidx.c (File already exists)'
  1342. else
  1343. echo 'x - extracting termidx.c (Text)'
  1344. sed 's/^X//' << 'SHAR_EOF' > 'termidx.c' &&
  1345. /* Program to generate termcap index file
  1346. X   Copyright (C) 1992 Joseph H. Allen
  1347. X
  1348. This file is part of JOE (Joe's Own Editor)
  1349. X
  1350. JOE is free software; you can redistribute it and/or modify it under the 
  1351. terms of the GNU General Public License as published by the Free Software 
  1352. Foundation; either version 1, or (at your option) any later version.  
  1353. X
  1354. JOE is distributed in the hope that it will be useful, but WITHOUT ANY 
  1355. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  1356. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  1357. details.  
  1358. X
  1359. You should have received a copy of the GNU General Public License along with 
  1360. JOE; see the file COPYING.  If not, write to the Free Software Foundation, 
  1361. 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
  1362. X
  1363. #include <stdio.h>
  1364. X
  1365. gen(s,fd)
  1366. char *s;
  1367. FILE *fd;
  1368. {
  1369. int c,x;
  1370. long addr=0, oaddr;
  1371. loop:
  1372. while(c=getc(fd), c==' ' || c=='\t' || c=='#')
  1373. X do c=getc(fd); while(!(c== -1 || c=='\n'));
  1374. if(c== -1) return;
  1375. if(c=='\n') goto loop;
  1376. oaddr=addr;
  1377. addr=ftell(fd)-1;
  1378. ungetc(c,fd);
  1379. s[x=0]=0;
  1380. while(1)
  1381. X {
  1382. X c=getc(fd);
  1383. X if(c== -1 || c=='\n')
  1384. X  {
  1385. X  if(x!=0 && s[x-1]=='\\') --x;
  1386. X  if(x)
  1387. X   {
  1388. X   int y,z,flg;
  1389. X   s[x]=0; z=0; flg=0;
  1390. X   do
  1391. X    {
  1392. X    for(y=z;s[y] && s[y]!='|' && s[y]!=':';++y);
  1393. X    c=s[y]; s[y]=0;
  1394. X    if(strlen(s+z)>2 && !strchr(s+z,' ') &&
  1395. X       !strchr(s+z,'\t')) (flg && putchar(' ')), fputs(s+z,stdout), flg=1;
  1396. X    s[y]=c;
  1397. X    z=y+1;
  1398. X    }
  1399. X    while(c && c!=':');
  1400. X   if(flg) printf(" %x\n",addr-oaddr);
  1401. X   }
  1402. X  goto loop;
  1403. X  }
  1404. X else if(c=='\r') ;
  1405. X else s[x++]=c;
  1406. X }
  1407. }
  1408. X
  1409. main()
  1410. {
  1411. char array[65536];
  1412. gen(array,stdin);
  1413. }
  1414. SHAR_EOF
  1415. chmod 0600 termidx.c ||
  1416. echo 'restore of termidx.c failed'
  1417. Wc_c="`wc -c < 'termidx.c'`"
  1418. test 1592 -eq "$Wc_c" ||
  1419.     echo 'termidx.c: original size 1592, current size' "$Wc_c"
  1420. fi
  1421. # ============= terminfo.c ==============
  1422. if test -f 'terminfo.c' -a X"$1" != X"-c"; then
  1423.     echo 'x - skipping terminfo.c (File already exists)'
  1424. else
  1425. echo 'x - extracting terminfo.c (Text)'
  1426. sed 's/^X//' << 'SHAR_EOF' > 'terminfo.c' &&
  1427. /* TERMINFO database interface
  1428. X   Copyright (C) 1992 Joseph H. Allen
  1429. X
  1430. This file is part of JOE (Joe's Own Editor)
  1431. X
  1432. JOE is free software; you can redistribute it and/or modify it under the 
  1433. terms of the GNU General Public License as published by the Free Software 
  1434. Foundation; either version 1, or (at your option) any later version.  
  1435. X
  1436. JOE is distributed in the hope that it will be useful, but WITHOUT ANY 
  1437. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  1438. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  1439. details.  
  1440. X
  1441. You should have received a copy of the GNU General Public License along with 
  1442. JOE; see the file COPYING.  If not, write to the Free Software Foundation, 
  1443. 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
  1444. X
  1445. #include "termcap.h"
  1446. #include "vs.h"
  1447. X
  1448. /* Get terminfo entry */
  1449. X
  1450. CAP *getcap(name,baud,out,outptr)
  1451. char *name;
  1452. int baud;
  1453. void (*out)();
  1454. void *outptr;
  1455. {
  1456. CAP *cap;
  1457. if(NULL==name && NULL==(name=getenv("TERM"))) return NULL;
  1458. cap=(CAP *)malloc(sizeof(CAP));
  1459. cap->out=out;
  1460. cap->outptr=outptr;
  1461. cap->tbuf=(char *)malloc(4096);
  1462. cap->abuf=(char *)malloc(4096);
  1463. cap->abufp=cap->abuf;
  1464. cap->baud=baud;
  1465. cap->div=100000/baud;
  1466. ospeed=baud;
  1467. if(tgetent(cap->tbuf,name)!=1)
  1468. X {
  1469. X free(cap->tbuf);
  1470. X free(cap->abuf);
  1471. X return NULL;
  1472. X }
  1473. cap->pad=getstr(cap,"pc");
  1474. if(NULL!=cap->pad) PC=cap->pad[0];
  1475. else PC=0;
  1476. BC=0; UP=0;
  1477. return cap;
  1478. }
  1479. X
  1480. /* Get string capability */
  1481. /* Warning, repeated calls to this will eventually use up all of cap->abuf */
  1482. X
  1483. char *getstr(cap,name)
  1484. CAP *cap;
  1485. char *name;
  1486. {
  1487. return tgetstr(name,&cap->abufp);
  1488. }
  1489. X
  1490. /* Get flag capability */
  1491. X
  1492. int getflag(cap,name)
  1493. CAP *cap;
  1494. char *name;
  1495. {
  1496. return tgetflag(name);
  1497. }
  1498. X
  1499. /* Get numeric capability */
  1500. X
  1501. int getnum(cap,name)
  1502. CAP *cap;
  1503. char *name;
  1504. {
  1505. return tgetnum(name);
  1506. }
  1507. X
  1508. /* Eliminate a CAP */
  1509. X
  1510. void rmcap(cap)
  1511. CAP *cap;
  1512. {
  1513. free(cap->tbuf);
  1514. free(cap->abuf);
  1515. free(cap); 
  1516. }
  1517. X
  1518. /* Execute a string capability */
  1519. X
  1520. static CAP *outcap;
  1521. X
  1522. static int outout(c)
  1523. {
  1524. outcap->out(outcap->outptr,c);
  1525. }
  1526. X
  1527. void texec(cap,str,l,a0,a1,a2,a3)
  1528. CAP *cap;
  1529. char *str;
  1530. int l,a0,a1,a2,a3;
  1531. {
  1532. char *a;
  1533. outcap=cap;
  1534. a=tgoto(str,a1,a0);
  1535. tputs(a,l,outout);
  1536. }
  1537. X
  1538. static int total;
  1539. X
  1540. static void cst()
  1541. {
  1542. ++total;
  1543. }
  1544. X
  1545. int tcost(cap,s,l,a0,a1,a2,a3)
  1546. CAP *cap;
  1547. char *s;
  1548. int l,a0,a1,a2,a3;
  1549. {
  1550. void (*out)()=cap->out;
  1551. if(NULL==s) return 10000;
  1552. total=0;
  1553. cap->out=cst;
  1554. texec(cap,s,l,a0,a1,a2,a3);
  1555. cap->out=out;
  1556. return total;
  1557. }
  1558. X
  1559. static char *ssp;
  1560. static void cpl(ptr,c)
  1561. char *ptr;
  1562. char c;
  1563. {
  1564. vsadd(ssp,c);
  1565. }
  1566. X
  1567. char *tcompile(cap,s,a0,a1,a2,a3)
  1568. CAP *cap;
  1569. char *s;
  1570. int a0,a1,a2,a3;
  1571. {
  1572. void (*out)()=cap->out;
  1573. int div=cap->div;
  1574. if(NULL==s) return NULL;
  1575. cap->out=cpl; cap->div=10000;
  1576. ssp=vsmk(10);
  1577. texec(cap,s,0,a0,a1,a2,a3);
  1578. cap->out=out; cap->div=div;
  1579. return ssp;
  1580. }
  1581. SHAR_EOF
  1582. chmod 0600 terminfo.c ||
  1583. echo 'restore of terminfo.c failed'
  1584. Wc_c="`wc -c < 'terminfo.c'`"
  1585. test 2705 -eq "$Wc_c" ||
  1586.     echo 'terminfo.c: original size 2705, current size' "$Wc_c"
  1587. fi
  1588. # ============= todojoe ==============
  1589. if test -f 'todojoe' -a X"$1" != X"-c"; then
  1590.     echo 'x - skipping todojoe (File already exists)'
  1591. else
  1592. echo 'x - extracting todojoe (Text)'
  1593. sed 's/^X//' << 'SHAR_EOF' > 'todojoe' &&
  1594. =-=-=
  1595. shell window
  1596. background loading
  1597. X
  1598. =-=-=
  1599. make identifier length significant in first 8 (6?) places for old C compilers
  1600. X
  1601. =-=-=
  1602. block restricted searches
  1603. X
  1604. =-=-=
  1605. key bindings which depend on file type
  1606. X
  1607. =-=-=
  1608. hexadecimal edit mode
  1609. fixed record length edit mode
  1610. X
  1611. =-=-=
  1612. key layout:
  1613. X  delete to beginning of line    ?
  1614. X  search backwards        ?
  1615. X  yank/unyank            ?/?
  1616. X
  1617. =-=-=
  1618. message file for easily changing languages
  1619. X
  1620. =-=-=
  1621. should use temporary edit buffers instead of memory blocks for
  1622. undo, cut, s&r.  Will be faster and eliminate malloc
  1623. problem on small machines (with undo: use a single buffer?)
  1624. X
  1625. maybe there should be a cut block to buffer function which does no
  1626. copying except at the ends...
  1627. X
  1628. at least undo records should be eliminated when a large block is requested
  1629. X
  1630. =-=-=
  1631. ttybad?
  1632. X
  1633. X
  1634. msdos-
  1635. X
  1636. X how to get it to recognize CR-LF? - use translating fopen?
  1637. X
  1638. X msdos doesn't have 'sys/dir.h' does it?  yuck...
  1639. X
  1640. X how to give memory back during shell escapes?
  1641. X
  1642. =-=-=
  1643. verticle windows          - difficult to get scrolling to work right
  1644. X
  1645. =-=-=
  1646. xedit and folding stuff        - regex too slow?
  1647. X
  1648. =-=-=
  1649. multiple line prompts/menu windows
  1650. X
  1651. =-=-=
  1652. block coalescing in b.c.
  1653. X
  1654. =-=-=
  1655. store number of lines in block headers, maybe could then use faster search
  1656. algorithm
  1657. X
  1658. =-=-=
  1659. insert and delete should determine number of columns so that fixup doesn't
  1660. have to call pfcol so much.
  1661. SHAR_EOF
  1662. chmod 0600 todojoe ||
  1663. echo 'restore of todojoe failed'
  1664. Wc_c="`wc -c < 'todojoe'`"
  1665. test 1341 -eq "$Wc_c" ||
  1666.     echo 'todojoe: original size 1341, current size' "$Wc_c"
  1667. fi
  1668. # ============= toomany.c ==============
  1669. if test -f 'toomany.c' -a X"$1" != X"-c"; then
  1670.     echo 'x - skipping toomany.c (File already exists)'
  1671. else
  1672. echo 'x - extracting toomany.c (Text)'
  1673. sed 's/^X//' << 'SHAR_EOF' > 'toomany.c' &&
  1674. /* Oh no! Too many files!
  1675. X   Copyright (C) 1992 Joseph H. Allen
  1676. X
  1677. This file is part of JOE (Joe's Own Editor)
  1678. X
  1679. JOE is free software; you can redistribute it and/or modify it under the 
  1680. terms of the GNU General Public License as published by the Free Software 
  1681. Foundation; either version 1, or (at your option) any later version.  
  1682. X
  1683. JOE is distributed in the hope that it will be useful, but WITHOUT ANY 
  1684. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  1685. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  1686. details.  
  1687. X
  1688. You should have received a copy of the GNU General Public License along with 
  1689. JOE; see the file COPYING.  If not, write to the Free Software Foundation, 
  1690. 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
  1691. X
  1692. #include <fcntl.h>
  1693. #include <sys/types.h>
  1694. #include <sys/stat.h>
  1695. #include "config.h"
  1696. #include "vs.h"
  1697. #include "heap.h"
  1698. #include "toomany.h"
  1699. X
  1700. static int nopen=0;
  1701. static File openfiles={{&openfiles,&openfiles}};
  1702. X
  1703. static void toomany()
  1704. {
  1705. File *f;
  1706. for(f=openfiles.link.prev;f!=&openfiles;f=f->link.prev)
  1707. X if(f->fd!= -1)
  1708. X  {
  1709. X  close(f->fd);
  1710. X  f->fd= -1;
  1711. X  --nopen;
  1712. X  return;
  1713. X  }
  1714. }
  1715. X
  1716. static void reopen(file)
  1717. File *file;
  1718. {
  1719. if(nopen==Fmaxopen) toomany();
  1720. if(file->writeable) file->fd=open(file->name,O_RDWR /* | O_BINARY */);
  1721. else file->fd=open(file->name,O_RDONLY /* |O_BINARY */);
  1722. if(file->fd== -1)
  1723. X {
  1724. X /* Uh... */
  1725. X }
  1726. ++nopen;
  1727. lseek(file->fd,file->pos,0);
  1728. }
  1729. X
  1730. File *Fopen(name)
  1731. char *name;
  1732. {
  1733. File *file;
  1734. int fd;
  1735. int writeable;
  1736. struct stat buf;
  1737. if(nopen==Fmaxopen) toomany();
  1738. fd=open(name,O_RDWR /*|O_BINARY*/);
  1739. if(fd== -1) fd=open(name,O_RDONLY/*|O_BINARY*/), writeable=0;
  1740. else writeable=1;
  1741. if(fd== -1) return NULL;
  1742. ++nopen;
  1743. fstat(fd,&buf);
  1744. file=(File *)malloc(sizeof(File));
  1745. file->fd= fd;
  1746. file->writeable= writeable;
  1747. file->name=vsncpy(NULL,0,sz(name));
  1748. file->size=buf.st_size;
  1749. file->pos=0;
  1750. file->inode=buf.st_ino;
  1751. file->dev=buf.st_dev;
  1752. enquef(File,link,&openfiles,file);
  1753. return file;
  1754. }
  1755. X
  1756. void Fclose(file)
  1757. File *file;
  1758. {
  1759. if(file->fd!= -1) close(file->fd), --nopen;
  1760. deque(File,link,file);
  1761. free(file);
  1762. }
  1763. X
  1764. int Fread(file,buf,size)
  1765. File *file;
  1766. char *buf;
  1767. {
  1768. int amnt;
  1769. promote(File,link,&openfiles,file);
  1770. if(file->fd== -1) reopen(file);
  1771. amnt=read(file->fd,buf,size);
  1772. if(amnt>0) file->pos+=amnt;
  1773. return amnt;
  1774. }
  1775. X
  1776. int Fwrite(file,buf,size)
  1777. File *file;
  1778. char *buf;
  1779. {
  1780. int amnt;
  1781. if(!file->writeable) return -1;
  1782. promote(File,link,&openfiles,file);
  1783. if(file->fd== -1) reopen(file);
  1784. amnt=write(file->fd,buf,size);
  1785. if(amnt>0)
  1786. X {
  1787. X file->pos+=amnt;
  1788. X if(file->pos>file->size) file->size=file->pos;
  1789. X }
  1790. return amnt;
  1791. }
  1792. X
  1793. int Fseek(file,pos)
  1794. File *file;
  1795. long pos;
  1796. {
  1797. promote(File,link,&openfiles,file);
  1798. if(file->fd== -1) reopen(file);
  1799. file->pos=lseek(file->fd,pos,0);
  1800. if(file->pos<0) return -1;
  1801. return 0;
  1802. }
  1803. SHAR_EOF
  1804. chmod 0600 toomany.c ||
  1805. echo 'restore of toomany.c failed'
  1806. Wc_c="`wc -c < 'toomany.c'`"
  1807. test 2733 -eq "$Wc_c" ||
  1808.     echo 'toomany.c: original size 2733, current size' "$Wc_c"
  1809. fi
  1810. # ============= toomany.h ==============
  1811. if test -f 'toomany.h' -a X"$1" != X"-c"; then
  1812.     echo 'x - skipping toomany.h (File already exists)'
  1813. else
  1814. echo 'x - extracting toomany.h (Text)'
  1815. sed 's/^X//' << 'SHAR_EOF' > 'toomany.h' &&
  1816. /* Too many files!
  1817. X   Copyright (C) 1992 Joseph H. Allen
  1818. X
  1819. This file is part of JOE (Joe's Own Editor)
  1820. X
  1821. JOE is free software; you can redistribute it and/or modify it under the 
  1822. terms of the GNU General Public License as published by the Free Software 
  1823. Foundation; either version 1, or (at your option) any later version.  
  1824. X
  1825. JOE is distributed in the hope that it will be useful, but WITHOUT ANY 
  1826. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  1827. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  1828. details.  
  1829. X
  1830. You should have received a copy of the GNU General Public License along with 
  1831. JOE; see the file COPYING.  If not, write to the Free Software Foundation, 
  1832. 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
  1833. X
  1834. #ifndef _Itoomany
  1835. #define _Itoomany 1
  1836. X
  1837. #include "config.h"
  1838. #include "queue.h"
  1839. X
  1840. typedef struct File File;
  1841. X
  1842. #define Fmaxopen 16
  1843. X
  1844. struct File
  1845. X {
  1846. X LINK(File) link;        /* Linked list of open files */
  1847. X int fd;            /* The file or -1 if closed */
  1848. X char *name;            /* Name of the file */
  1849. X int writeable;            /* Set if it's ok to write to the file */
  1850. X long size;            /* Current size of file */
  1851. X long pos;            /* Current file pointer */
  1852. X int inode;            /* Inode of file */
  1853. X int dev;            /* Device file is on */
  1854. X };
  1855. X
  1856. File *Fopen();
  1857. int Fread();
  1858. int Fwrite();
  1859. int Fseek();
  1860. void Fclose();
  1861. X
  1862. #endif
  1863. SHAR_EOF
  1864. chmod 0600 toomany.h ||
  1865. echo 'restore of toomany.h failed'
  1866. Wc_c="`wc -c < 'toomany.h'`"
  1867. test 1322 -eq "$Wc_c" ||
  1868.     echo 'toomany.h: original size 1322, current size' "$Wc_c"
  1869. fi
  1870. # ============= tty.h ==============
  1871. if test -f 'tty.h' -a X"$1" != X"-c"; then
  1872.     echo 'x - skipping tty.h (File already exists)'
  1873. else
  1874. echo 'x - extracting tty.h (Text)'
  1875. sed 's/^X//' << 'SHAR_EOF' > 'tty.h' &&
  1876. /* TTY interface header file
  1877. X   Copyright (C) 1992 Joseph H. Allen
  1878. X
  1879. This file is part of JOE (Joe's Own Editor)
  1880. X
  1881. JOE is free software; you can redistribute it and/or modify it under the 
  1882. terms of the GNU General Public License as published by the Free Software 
  1883. Foundation; either version 1, or (at your option) any later version.  
  1884. X
  1885. JOE is distributed in the hope that it will be useful, but WITHOUT ANY 
  1886. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  1887. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  1888. details.  
  1889. X
  1890. You should have received a copy of the GNU General Public License along with 
  1891. JOE; see the file COPYING.  If not, write to the Free Software Foundation, 
  1892. 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
  1893. X
  1894. #ifndef _Itty
  1895. #define _Itty 1
  1896. X
  1897. #include "config.h"
  1898. X
  1899. /* void ttopen(void);  Open the tty (attached to stdin) for use inside of JOE
  1900. X *
  1901. X * (0) Call sigjoe()
  1902. X *     There is also 'void ttopnn(void)' which does not do this step.
  1903. X *
  1904. X * (1) fflush(stdout)
  1905. X *
  1906. X * (2) Save the current state of the tty
  1907. X *
  1908. X * (3) Disable CR/LF/NL input translations,
  1909. X *     Disable all output processing,
  1910. X *     Disable echo and line editing, and
  1911. X *     Place tty in character at a time mode.
  1912. X *     (basically, disable all processing except for XON/XOFF if it's set)
  1913. X *
  1914. X * (4) Set this new tty state without loosing any typeahead
  1915. X *
  1916. X * (5) Store the baud rate in the global variable 'baud'
  1917. X *
  1918. X * (6) Divide the baud rate into the constant DIVIDEND and store the result
  1919. X *     in the global variable 'upc'.  This should come out to the number
  1920. X *     of microseconds needed to send each character.  The constant 'DIVIDEND'
  1921. X *     should be chosen so that 'upc' reflects the real throughput of the
  1922. X *     tty, not the theoretical best throughput.
  1923. X *
  1924. X * (7) Create an output buffer of a size which depends on 'upc' and the
  1925. X *     constant 'TIMES'.  'TIMES' is the number of times per second JOE
  1926. X *     should check for typeahead.  Since we only check for typehead after
  1927. X *     the output buffer is flushed, 'upc' and the size of the output buffer
  1928. X *     determine how often this occurs.  So for example if 'upc'==1000 (~9600
  1929. X *     baud) and 'TIMES'==3, the output buffer size is set to 333 characters.
  1930. X *     Each time this buffer is completely flushed, 1/3 of a second will go by.
  1931. X */
  1932. void ttopen();
  1933. void ttopnn();
  1934. extern unsigned long upc;
  1935. extern unsigned baud;
  1936. X
  1937. #define TIMES 3
  1938. #define DIVIDEND 10000000
  1939. X
  1940. /* void ttclose(void);  Restore the tty back to its original mode.
  1941. X *
  1942. X * (1) ttyflsh()
  1943. X *
  1944. X * (2) Restore the original tty mode which aopen() had saved.  Do this without
  1945. X *     loosing any typeahead.
  1946. X *
  1947. X * (3) Call signrm().  There is also 'void ttyclsn(void)' which does not do
  1948. X *     the this step.
  1949. X */
  1950. void ttclose();
  1951. void ttclsn();
  1952. X
  1953. /* int ttgetc(void);  Flush the output and get the next character from the tty
  1954. X *
  1955. X * (1) ttflsh()
  1956. X *
  1957. X * (2) Read the next input character
  1958. X *     If the input closed, call 'ttsig' with 0 as its argument.
  1959. X *
  1960. X * (3) Clear 'have'
  1961. X */
  1962. int ttgetc();
  1963. X
  1964. /* void ttputc(char c);  Write a character to the output buffer.  If it becomes
  1965. X * full, call ttflsh()
  1966. X */
  1967. extern int obufp;
  1968. extern int obufsiz;
  1969. extern char *obuf;
  1970. #define ttputc(c) (obuf[obufp++]=(c), obufp==obufsiz && ttflsh())
  1971. X
  1972. /* void ttputs(char *s);  Write a string to the output buffer.  Any time the
  1973. X * output buffer gets full, call ttflsh()
  1974. X */
  1975. void ttputs();
  1976. X
  1977. /* void ttshell(char *s);  Run a shell command or if 's' is zero, run a
  1978. X * sub-shell
  1979. X */
  1980. void ttshell();
  1981. X
  1982. /* void ttsusp(void);  Suspend the process, or if the UNIX can't do it, call
  1983. X * ttshell(NULL)
  1984. X */
  1985. void ttsusp();
  1986. X
  1987. /* int ttflsh(void);  Flush the output buffer and check for typeahead.
  1988. X *
  1989. X * (1) write() any character in the output buffer to the tty.  Sleep for the
  1990. X *     amount of time it should take for all of these characters to get
  1991. X *     to the tty.  This is so that any buffering between the editor and the
  1992. X *     tty is defeated.  If this is not done, the screen update will not be
  1993. X *     able to defer for typeahead.
  1994. X *
  1995. X *     The best way to do this (and it's currently only possible in BSD) is to
  1996. X *     set a timer for the necessary amount, write the characters to the tty,
  1997. X *     and then sleep until the timer expires.
  1998. X *
  1999. X *     If this can't be done, it's usually ok to 'write' and then to sleep for
  2000. X *     the necessary amount of time.  However, you will notice delays in the
  2001. X *     screen update if the 'write' actually takes any significant amount of
  2002. X *     time to execute (it usually takes none since all it usually does is
  2003. X *     write to an operating system buffer).
  2004. X *
  2005. X * (2) If the global variable 'leave' is not set and if the global variable
  2006. X *     'have' is not set, check for typeahead.  If there is any, set the global
  2007. X *     variable 'have'.  This absolutely must not read any characters from the
  2008. X *     'tty' if 'leave' is set or typeahead will be lost when the editor exits
  2009. X *     or does a shell escape.
  2010. X */
  2011. int ttflsh();
  2012. X
  2013. extern int have;
  2014. extern int leave;
  2015. X
  2016. /* void ttsig(int n);  Signal handler you provide.  This is called if the
  2017. X * editor gets a hangup signal, termination signal or if the input closes.
  2018. X * It is called with 'n' set to the number of the caught signal or 0 if the
  2019. X * input closed.
  2020. X */
  2021. void ttsig();
  2022. X
  2023. /* void ttgtsz(int *x,int *y);  Get size of screen from ttsize/winsize
  2024. X * structure */
  2025. void ttgtsz();
  2026. X
  2027. /* You don't have to call these: ttopen/ttclose do it for you.  These
  2028. X * may be needed to make your own shell escape sequences.
  2029. X */
  2030. X
  2031. /* void sigjoe(void);  Set the signal handling for joe.  I.E., ignore all
  2032. X * signals the user can generate from the keyboard (SIGINT, SIGQUIT, SIGPIPE)
  2033. X * and trap the software terminate and hangup signals (SIGTERM, SIGHUP) so
  2034. X * that 'ttsig' gets called.
  2035. X */
  2036. void sigjoe();
  2037. X
  2038. /* void signrm(void);  Set above signals back to their default values.
  2039. X */
  2040. void signrm();
  2041. X
  2042. /* char *pwd();  Get current working directory into a static buffer.
  2043. X */
  2044. char *pwd();
  2045. X
  2046. #endif
  2047. SHAR_EOF
  2048. chmod 0600 tty.h ||
  2049. echo 'restore of tty.h failed'
  2050. Wc_c="`wc -c < 'tty.h'`"
  2051. test 5951 -eq "$Wc_c" ||
  2052.     echo 'tty.h: original size 5951, current size' "$Wc_c"
  2053. fi
  2054. # ============= ttybsd.c ==============
  2055. if test -f 'ttybsd.c' -a X"$1" != X"-c"; then
  2056.     echo 'x - skipping ttybsd.c (File already exists)'
  2057. else
  2058. echo 'x - extracting ttybsd.c (Text)'
  2059. sed 's/^X//' << 'SHAR_EOF' > 'ttybsd.c' &&
  2060. /* TTY interface for BSD UNIX
  2061. X   Copyright (C) 1991 Joseph H. Allen
  2062. X
  2063. This file is part of JOE (Joe's Own Editor)
  2064. X
  2065. JOE is free software; you can redistribute it and/or modify it under the 
  2066. terms of the GNU General Public License as published by the Free Software 
  2067. Foundation; either version 1, or (at your option) any later version.  
  2068. X
  2069. JOE is distributed in the hope that it will be useful, but WITHOUT ANY 
  2070. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  2071. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  2072. details.  
  2073. X
  2074. You should have received a copy of the GNU General Public License
  2075. along with JOE; see the file COPYING.  If not, write to
  2076. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  2077. X
  2078. #include <sgtty.h>
  2079. #include <fcntl.h>
  2080. #include <stdio.h>
  2081. #include <signal.h>
  2082. #include <sys/time.h>
  2083. #include "config.h"
  2084. #include "heap.h"
  2085. #include "tty.h"
  2086. X
  2087. #ifndef HZ
  2088. #define HZ 10            /* Clock ticks/second */
  2089. #endif
  2090. X
  2091. /* The terminal */
  2092. X
  2093. FILE *term=0;
  2094. X
  2095. /* The original tty state */
  2096. X
  2097. static struct sgttyb oarg;
  2098. static struct tchars otarg;
  2099. static struct ltchars oltarg;
  2100. X
  2101. /* The output buffer, index and size. */
  2102. X
  2103. char *obuf=0;
  2104. int obufp=0;
  2105. int obufsiz;
  2106. X
  2107. /* The baud rate */
  2108. X
  2109. unsigned baud;
  2110. unsigned long upc;
  2111. X
  2112. /* Code to baud-rate conversion table */
  2113. X
  2114. static int speeds[]=
  2115. {
  2116. B50,50,B75,75,B110,110,B134,134,B150,150,B200,200,B300,300,B600,600,B1200,1200,
  2117. B1800,1800,B2400,2400,B4800,4800,B9600,9600,EXTA,19200,EXTB,38400
  2118. };
  2119. X
  2120. /* Input buffer, typeahead indication flag and editor is about to exit flag */
  2121. X
  2122. int have=0;
  2123. static char havec;
  2124. int leave=0;
  2125. X
  2126. /* TTY mode flag.  1 for open, 0 for closed */
  2127. X
  2128. static int ttymode=0;
  2129. X
  2130. void sigjoe()
  2131. {
  2132. signal(SIGHUP,ttsig);
  2133. signal(SIGTERM,ttsig);
  2134. signal(SIGINT,SIG_IGN);
  2135. signal(SIGPIPE,SIG_IGN);
  2136. signal(SIGQUIT,SIG_IGN);
  2137. }
  2138. X
  2139. void signrm()
  2140. {
  2141. signal(SIGHUP,SIG_DFL);
  2142. signal(SIGTERM,SIG_DFL);
  2143. signal(SIGINT,SIG_DFL);
  2144. signal(SIGPIPE,SIG_DFL);
  2145. signal(SIGQUIT,SIG_DFL);
  2146. }
  2147. X
  2148. void ttopen()
  2149. {
  2150. sigjoe();
  2151. ttopnn();
  2152. }
  2153. X
  2154. void ttopnn()
  2155. {
  2156. int x;
  2157. struct sgttyb arg;
  2158. struct tchars targ;
  2159. struct ltchars ltarg;
  2160. if(!term && !(term=fopen("/dev/tty","r+")))
  2161. X {
  2162. X fprintf(stderr,"Couldn\'t open tty\n");
  2163. X exit(1);
  2164. X }
  2165. if(ttymode) return;
  2166. ttymode=1;
  2167. fflush(term);
  2168. ioctl(fileno(term),TIOCGETP,&arg);
  2169. ioctl(fileno(term),TIOCGETC,&targ);
  2170. ioctl(fileno(term),TIOCGLTC,<arg);
  2171. oarg=arg; otarg=targ; oltarg=ltarg;
  2172. arg.sg_flags=( (arg.sg_flags&~(ECHO|CRMOD) ) | CBREAK) ;
  2173. targ.t_intrc= -1;
  2174. targ.t_quitc= -1;
  2175. targ.t_eofc= -1;
  2176. targ.t_brkc= -1;
  2177. ltarg.t_suspc= -1;
  2178. ltarg.t_dsuspc= -1;
  2179. ltarg.t_rprntc= -1;
  2180. ltarg.t_flushc= -1;
  2181. ltarg.t_werasc= -1;
  2182. ltarg.t_lnextc= -1;
  2183. ioctl(fileno(term),TIOCSETN,&arg);
  2184. ioctl(fileno(term),TIOCSETC,&targ);
  2185. ioctl(fileno(term),TIOCSLTC,<arg);
  2186. baud=9600;
  2187. upc=0;
  2188. for(x=0;x!=30;x+=2)
  2189. X if(arg.sg_ospeed==speeds[x])
  2190. X  {
  2191. X  baud=speeds[x+1];
  2192. X  break;
  2193. X  }
  2194. {
  2195. char *bs=getenv("BAUD");
  2196. if(bs)
  2197. X {
  2198. X sscanf(bs,"%u",&baud);
  2199. X }
  2200. }
  2201. upc=DIVIDEND/baud;
  2202. if(obuf) free(obuf);
  2203. if(!(TIMES*upc)) obufsiz=4096;
  2204. else
  2205. X {
  2206. X obufsiz=1000000/(TIMES*upc);
  2207. X if(obufsiz>4096) obufsiz=4096;
  2208. X }
  2209. if(!obufsiz) obufsiz=1;
  2210. obuf=(char *)malloc(obufsiz);
  2211. }
  2212. X
  2213. void ttclose()
  2214. {
  2215. ttclsn();
  2216. signrm();
  2217. }
  2218. X
  2219. void ttclsn()
  2220. {
  2221. int oleave=leave;
  2222. if(ttymode) ttymode=0;
  2223. else return;
  2224. leave=1;
  2225. ttflsh();
  2226. ioctl(fileno(term),TIOCSETN,&oarg);
  2227. ioctl(fileno(term),TIOCSETC,&otarg);
  2228. ioctl(fileno(term),TIOCSLTC,&oltarg);
  2229. leave=oleave;
  2230. }
  2231. X
  2232. static int yep;
  2233. static dosig() { yep=1; } 
  2234. X
  2235. int ttflsh()
  2236. {
  2237. if(obufp)
  2238. X {
  2239. X struct itimerval a,b;
  2240. X unsigned long usec=obufp*upc;
  2241. X if(usec>=500000/HZ && baud<38400)
  2242. X  {
  2243. X  a.it_value.tv_sec=usec/1000000;
  2244. X  a.it_value.tv_usec=usec%1000000;
  2245. X  a.it_interval.tv_usec=0;
  2246. X  a.it_interval.tv_sec=0;
  2247. X  signal(SIGALRM,dosig);
  2248. X  yep=0;
  2249. X  sigsetmask(sigmask(SIGALRM));
  2250. X  setitimer(ITIMER_REAL,&a,&b);
  2251. X  write(fileno(term),obuf,obufp);
  2252. X  while(!yep) sigpause(0);
  2253. X  signal(SIGALRM,SIG_DFL);
  2254. X  }
  2255. X else write(fileno(term),obuf,obufp);
  2256. X obufp=0;
  2257. X }
  2258. if(!have && !leave)
  2259. X {
  2260. X fcntl(fileno(term),F_SETFL,FNDELAY);
  2261. X if(read(fileno(term),&havec,1)==1) have=1;
  2262. X fcntl(fileno(term),F_SETFL,0);
  2263. X }
  2264. return 0;
  2265. }
  2266. X
  2267. int ttgetc()
  2268. {
  2269. ttflsh();
  2270. if(have) have=0;
  2271. else if(read(fileno(term),&havec,1)<1) ttsig(0);
  2272. return havec;
  2273. }
  2274. X
  2275. void ttputs(s)
  2276. char *s;
  2277. {
  2278. while(*s)
  2279. X {
  2280. X obuf[obufp++]= *(s++);
  2281. X if(obufp==obufsiz) ttflsh();
  2282. X }
  2283. }
  2284. X
  2285. void ttgtsz(x,y)
  2286. int *x, *y;
  2287. {
  2288. #ifdef TIOCGSIZE
  2289. struct ttysize getit;
  2290. #else
  2291. #ifdef TIOCGWINSZ
  2292. struct winsize getit;
  2293. #endif
  2294. #endif
  2295. *x=0; *y=0;
  2296. #ifdef TIOCGSIZE
  2297. if(ioctl(fileno(term),TIOCGSIZE,&getit)!= -1)
  2298. X {
  2299. X *x=getit.ts_cols;
  2300. X *y=getit.ts_lines;
  2301. X }
  2302.