home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / alt / sources / 2593 < prev    next >
Encoding:
Text File  |  1992-11-20  |  51.8 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 6 of 10
  5. Message-ID: <By2ML1.L0q@world.std.com>
  6. Organization: The World Public Access UNIX, Brookline, MA
  7. Date: Sat, 21 Nov 1992 14:51:00 GMT
  8. Lines: 2303
  9.  
  10. Submitted-by: jhallen@world.std.com
  11. Archive-name: joe1.0.5part6
  12.  
  13. X      rand_type = TYPE_4;
  14. X      rand_deg = DEG_4;
  15. X      rand_sep = SEP_4;
  16. X    }
  17. X
  18. X  state = &((long *) arg_state)[1];    /* First location.  */
  19. X  /* Must set END_PTR before srandom.  */
  20. X  end_ptr = &state[rand_deg];
  21. X  srandom(seed);
  22. X  if (rand_type == TYPE_0)
  23. X    state[-1] = rand_type;
  24. X  else
  25. X    state[-1] = (MAX_TYPES * (rptr - state)) + rand_type;
  26. X
  27. X  return ostate;
  28. }
  29. X
  30. /* Restore the state from the given state array.
  31. X   Note: It is important that we also remember the locations of the pointers
  32. X   in the current state information, and restore the locations of the pointers
  33. X   from the old state information.  This is done by multiplexing the pointer
  34. X   location into the zeroeth word of the state information. Note that due
  35. X   to the order in which things are done, it is OK to call setstate with the
  36. X   same state as the current state
  37. X   Returns a pointer to the old state information.  */
  38. void *setstate(arg_state)
  39. void *arg_state;
  40. {
  41. X  register long *new_state = (long *) arg_state;
  42. X  register int type = new_state[0] % MAX_TYPES;
  43. X  register int rear = new_state[0] / MAX_TYPES;
  44. X  void *ostate = (void *) &state[-1];
  45. X
  46. X  if (rand_type == TYPE_0)
  47. X    state[-1] = rand_type;
  48. X  else
  49. X    state[-1] = (MAX_TYPES * (rptr - state)) + rand_type;
  50. X
  51. X  switch (type)
  52. X    {
  53. X    case TYPE_0:
  54. X    case TYPE_1:
  55. X    case TYPE_2:
  56. X    case TYPE_3:
  57. X    case TYPE_4:
  58. X      rand_type = type;
  59. X      rand_deg = degrees[type];
  60. X      rand_sep = seps[type];
  61. X      break;
  62. X    default:
  63. X      /* State info munged.  */
  64. X      return NULL;
  65. X    }
  66. X
  67. X  state = &new_state[1];
  68. X  if (rand_type != TYPE_0)
  69. X    {
  70. X      rptr = &state[rear];
  71. X      fptr = &state[(rear + rand_sep) % rand_deg];
  72. X    }
  73. X  /* Set end_ptr too.  */
  74. X  end_ptr = &state[rand_deg];
  75. X
  76. X  return ostate;
  77. }
  78. X
  79. /* If we are using the trivial TYPE_0 R.N.G., just do the old linear
  80. X   congruential bit.  Otherwise, we do our fancy trinomial stuff, which is the
  81. X   same in all ther other cases due to all the global variables that have been
  82. X   set up.  The basic operation is to add the number at the rear pointer into
  83. X   the one at the front pointer.  Then both pointers are advanced to the next
  84. X   location cyclically in the table.  The value returned is the sum generated,
  85. X   reduced to 31 bits by throwing away the "least random" low bit.
  86. X   Note: The code takes advantage of the fact that both the front and
  87. X   rear pointers can't wrap on the same call by not testing the rear
  88. X   pointer if the front one has wrapped.  Returns a 31-bit random number.  */
  89. X
  90. long random()
  91. {
  92. X  if (rand_type == TYPE_0)
  93. X    {
  94. X      state[0] = ((state[0] * 1103515245) + 12345) & MAXLONG;
  95. X      return state[0];
  96. X    }
  97. X  else
  98. X    {
  99. X      long i;
  100. X      *fptr += *rptr;
  101. X      /* Chucking least random bit.  */
  102. X      i = (*fptr >> 1) & MAXLONG;
  103. X      ++fptr;
  104. X      if (fptr >= end_ptr)
  105. X    {
  106. X      fptr = state;
  107. X      ++rptr;
  108. X    }
  109. X      else
  110. X    {
  111. X      ++rptr;
  112. X      if (rptr >= end_ptr)
  113. X        rptr = state;
  114. X    }
  115. X      return i;
  116. X    }
  117. }
  118. SHAR_EOF
  119. chmod 0600 random.c ||
  120. echo 'restore of random.c failed'
  121. Wc_c="`wc -c < 'random.c'`"
  122. test 12354 -eq "$Wc_c" ||
  123.     echo 'random.c: original size 12354, current size' "$Wc_c"
  124. fi
  125. # ============= random.h ==============
  126. if test -f 'random.h' -a X"$1" != X"-c"; then
  127.     echo 'x - skipping random.h (File already exists)'
  128. else
  129. echo 'x - extracting random.h (Text)'
  130. sed 's/^X//' << 'SHAR_EOF' > 'random.h' &&
  131. #ifndef _Irandom
  132. #define _Irandom 1
  133. X
  134. #include "config.h"
  135. X
  136. long random();
  137. void srandom();
  138. void *initstate();
  139. void *setstate();
  140. X
  141. #endif
  142. SHAR_EOF
  143. chmod 0600 random.h ||
  144. echo 'restore of random.h failed'
  145. Wc_c="`wc -c < 'random.h'`"
  146. test 134 -eq "$Wc_c" ||
  147.     echo 'random.h: original size 134, current size' "$Wc_c"
  148. fi
  149. # ============= reg.c ==============
  150. if test -f 'reg.c' -a X"$1" != X"-c"; then
  151.     echo 'x - skipping reg.c (File already exists)'
  152. else
  153. echo 'x - extracting reg.c (Text)'
  154. sed 's/^X//' << 'SHAR_EOF' > 'reg.c' &&
  155. /* Generate list of matching directory entries
  156. X   Copyright (C) 1992 Joseph H. Allen
  157. X
  158. This file is part of JOE (Joe's Own Editor)
  159. X
  160. JOE is free software; you can redistribute it and/or modify it under the 
  161. terms of the GNU General Public License as published by the Free Software 
  162. Foundation; either version 1, or (at your option) any later version.  
  163. X
  164. JOE is distributed in the hope that it will be useful, but WITHOUT ANY 
  165. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  166. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  167. details.  
  168. X
  169. You should have received a copy of the GNU General Public License along with 
  170. JOE; see the file COPYING.  If not, write to the Free Software Foundation, 
  171. 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
  172. X
  173. #include <stdio.h>
  174. #include <sys/types.h>
  175. #include <sys/dir.h>
  176. #include "config.h"
  177. #include "vs.h"
  178. #include "va.h"
  179. #include "regex.h"
  180. X
  181. char **rexpnd(path,word)
  182. char *path, *word;
  183. {
  184. void *dir;
  185. char **lst=0;
  186. struct direct *de;
  187. if(path && path[0]) dir=opendir(path);
  188. else dir=opendir(".");
  189. if(!dir) return 0;
  190. while(de=readdir(dir))
  191. X if(zcmp(".",de->d_name))
  192. X  if(rmatch(word,de->d_name))
  193. X   lst=vaadd(lst,vsncpy(NULL,0,de->d_name,slen(de->d_name)));
  194. closedir(dir);
  195. return lst;
  196. }
  197. SHAR_EOF
  198. chmod 0600 reg.c ||
  199. echo 'restore of reg.c failed'
  200. Wc_c="`wc -c < 'reg.c'`"
  201. test 1259 -eq "$Wc_c" ||
  202.     echo 'reg.c: original size 1259, current size' "$Wc_c"
  203. fi
  204. # ============= regex.c ==============
  205. if test -f 'regex.c' -a X"$1" != X"-c"; then
  206.     echo 'x - skipping regex.c (File already exists)'
  207. else
  208. echo 'x - extracting regex.c (Text)'
  209. sed 's/^X//' << 'SHAR_EOF' > 'regex.c' &&
  210. /* Regular expression subroutines
  211. X   Copyright (C) 1992 Joseph H. Allen
  212. X
  213. This file is part of JOE (Joe's Own Editor)
  214. X
  215. JOE is free software; you can redistribute it and/or modify it under the 
  216. terms of the GNU General Public License as published by the Free Software 
  217. Foundation; either version 1, or (at your option) any later version.  
  218. X
  219. JOE is distributed in the hope that it will be useful, but WITHOUT ANY 
  220. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  221. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  222. details.  
  223. X
  224. You should have received a copy of the GNU General Public License along with 
  225. JOE; see the file COPYING.  If not, write to the Free Software Foundation, 
  226. 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
  227. X
  228. #include "config.h"
  229. #include "zstr.h"
  230. #include "vs.h"
  231. #include "b.h"
  232. #include "regex.h"
  233. X
  234. static int brackz(a,c)
  235. unsigned char **a;
  236. unsigned char c;
  237. {
  238. int flag;
  239. unsigned char *s= *a;
  240. if(*s=='^' || *s=='*')
  241. X {
  242. X flag=1;
  243. X ++s;
  244. X if(*s==']')
  245. X  {
  246. X  ++s;
  247. X  if(c==']') flag=0;
  248. X  }
  249. X
  250. X while(*s)
  251. X  if(*s==']') { ++s; break; }
  252. X  else
  253. X   {
  254. X   if(c==*s) flag=0;
  255. X   if(s[1]=='-' && s[2] && s[2]!=']' && s[0]<=s[2])
  256. X    {
  257. X    if(c>=s[0] && c<=s[2]) flag=0;
  258. X    s+=2;
  259. X    }
  260. X   ++s;
  261. X   }
  262. X
  263. X *a=s;
  264. X return flag;
  265. X }
  266. else
  267. X {
  268. X flag=0;
  269. X
  270. X if(*s==']')
  271. X  {
  272. X  ++s;
  273. X  if(c==']') flag=1;
  274. X  }
  275. X
  276. X while(*s)
  277. X  if(*s==']') { ++s; break; }
  278. X  else
  279. X   {
  280. X   if(c==*s) flag=1;
  281. X   if(s[1]=='-' && s[2] && s[2]!=']' && s[0]<=s[2])
  282. X    {
  283. X    if(c>=s[0] && c<=s[2]) flag=1;
  284. X    s+=2;
  285. X    }
  286. X   ++s;
  287. X   }
  288. X *a=s;
  289. X return flag;
  290. X }
  291. }
  292. X
  293. static int brack(a,la,c)
  294. unsigned char **a;
  295. int *la;
  296. unsigned char c;
  297. {
  298. int flag;
  299. unsigned char *s= *a;
  300. int l= *la;
  301. if(!l) return 0;
  302. if(*s=='^' || *s=='*')
  303. X {
  304. X flag=1;
  305. X ++s; --l;
  306. X if(l && *s==']')
  307. X  {
  308. X  ++s; --l;
  309. X  if(c==']') flag=0;
  310. X  }
  311. X
  312. X while(l)
  313. X  if(*s==']') { ++s; --l; break; }
  314. X  else
  315. X   {
  316. X   if(c==*s) flag=0;
  317. X   if(l>=3 && s[1]=='-' && s[2]!=']' && s[0]<=s[2])
  318. X    {
  319. X    if(c>=s[0] && c<=s[2]) flag=0;
  320. X    s+=2; l-=2;
  321. X    }
  322. X   ++s; --l;
  323. X   }
  324. X
  325. X *a=s; *la=l;
  326. X return flag;
  327. X }
  328. else
  329. X {
  330. X flag=0;
  331. X
  332. X if(l && *s==']')
  333. X  {
  334. X  ++s; --l;
  335. X  if(c==']') flag=1;
  336. X  }
  337. X
  338. X while(l)
  339. X  if(*s==']') { ++s; --l; break; }
  340. X  else
  341. X   {
  342. X   if(c==*s) flag=1;
  343. X   if(l>=3 && s[1]=='-' && s[2]!=']' && s[0]<=s[2])
  344. X    {
  345. X    if(c>=s[0] && c<=s[2]) flag=1;
  346. X    s+=2; l-=2;
  347. X    }
  348. X   ++s; --l;
  349. X   }
  350. X *a=s; *la=l;
  351. X return flag;
  352. X }
  353. }
  354. X
  355. int rmatch(a,b)
  356. char *a, *b;
  357. {
  358. for(;;)
  359. X switch(*a)
  360. X  {
  361. X case '*': ++a;
  362. X           do if(rmatch(a,b)) return 1; while(*b++);
  363. X           return 0;
  364. X
  365. X case '[': ++a;
  366. X           if(!*b) return 0;
  367. X           if(!brackz(&a,*b)) return 0;
  368. X           ++b;
  369. X           break;
  370. X
  371. X case '?': ++a;
  372. X           if(!*b) return 0;
  373. X           ++b;
  374. X           break;
  375. X
  376. X case 0:   if(!*b) return 1;
  377. X           else return 0;
  378. X
  379. X case '\\':
  380. X           if(!*++a) return 0;
  381. X
  382. X default:  if(*a++!=*b++) return 0;
  383. X  }
  384. }
  385. X
  386. int rimatch(a,b)
  387. char *a, *b;
  388. {
  389. for(;;)
  390. X switch(*a)
  391. X  {
  392. X case '*': ++a;
  393. X           do if(rimatch(a,b)) return 1; while(*b++);
  394. X           return 0;
  395. X
  396. X case '[': ++a;
  397. X           if(!*b) return 0;
  398. X           if(!brackz(&a,*b)) return 0;
  399. X           ++b;
  400. X           break;
  401. X
  402. X case '?': ++a;
  403. X           if(!*b) return 0;
  404. X           ++b;
  405. X           break;
  406. X
  407. X case 0:   if(!*b) return 1;
  408. X           else return 0;
  409. X
  410. X case '\\':
  411. X           if(!*++a) return 0;
  412. X
  413. X default:  if(toup(*a++)!=toup(*b++)) return 0;
  414. X  }
  415. }
  416. X
  417. char *pieces[26]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  418. X
  419. static void savec(n,c)
  420. char c;
  421. {
  422. char *s=0;
  423. if(pieces[n]) vsrm(pieces[n]);
  424. s=vsncpy(s,0,&c,1);
  425. pieces[n]=s;
  426. }
  427. X
  428. static void saves(n,p,szz)
  429. P *p;
  430. long szz;
  431. {
  432. if(szz>=MAXINT-31) pieces[n]=vstrunc(pieces[n],0);
  433. else
  434. X {
  435. X pieces[n]=vstrunc(pieces[n],szz);
  436. X brmem(p,pieces[n],szz);
  437. X }
  438. }
  439. X
  440. static int skip_special(p)
  441. X P *p;
  442. X {
  443. X  int to, s;
  444. X  P *q;
  445. X  switch(s=pgetc(p))
  446. X   {
  447. X    case '"':
  448. X    do
  449. X     if((s=pgetc(p))=='\\') pgetc(p), s=pgetc(p);
  450. X     while(s!=MAXINT && s!='\"');
  451. X    if(s=='\"') return MAXINT-1;
  452. X    break;
  453. X
  454. X    case '\'':
  455. X    do
  456. X     if((s=pgetc(p))=='\\') s=pgetc(p), s=pgetc(p);
  457. X     while(s!=MAXINT && s!='\'');
  458. X    if(s=='\'') return MAXINT-1;
  459. X    break;
  460. X
  461. X    case '[': to=']'; goto skip;
  462. X    case '(': to=')'; goto skip;
  463. X    case '{': to='}';
  464. X    skip: do
  465. X     s=skip_special(p);
  466. X     while(s!=to && s!=MAXINT);
  467. X    if(s==to) return MAXINT-1;
  468. X    break;
  469. X
  470. X    case '/':
  471. X    s=pgetc(p);
  472. X    if(s=='*')
  473. X     do
  474. X      {
  475. X      s=pgetc(p);
  476. X      while(s=='*') if((s=pgetc(p))=='/') return MAXINT-1;
  477. X      } while(s!=MAXINT);
  478. X    else
  479. X     if(s!=MAXINT) s=prgetc(p);
  480. X     else s='/';
  481. X    break;
  482. X
  483. X   }
  484. X  return s;
  485. X }
  486. X
  487. int pmatch(regex,len,p,n)
  488. char *regex;
  489. P *p;
  490. {
  491. int c,d;
  492. P *q;
  493. while(len--)
  494. X switch(c=*regex++)
  495. X  {
  496. X case '\\':
  497. X  if(!len--) return 0;
  498. X  switch(c=*regex++)
  499. X   {
  500. X  case '?':
  501. X   d=pgetc(p);
  502. X   if(d== MAXINT) return 0;
  503. X   savec(n++,(char)d);
  504. X   break;
  505. X
  506. X  case 'n':
  507. X   d=pgetc(p);
  508. X   if(d!='\n') return 0;
  509. X   break;
  510. X
  511. X  case '*':
  512. X   q=pdup(p);
  513. X   do
  514. X    {
  515. X    long pb=p->byte;
  516. X    if(pmatch(regex,len,p,n+1))
  517. X     { saves(n,q,pb-q->byte); prm(q); return 1; }
  518. X    }
  519. X    while(pgetc(p)!= MAXINT);
  520. X   pset(p,q); prm(q);
  521. X   return 0;
  522. X    
  523. X  case 'c':
  524. X   q=pdup(p);
  525. X   do
  526. X    {
  527. X    long pb=p->byte;
  528. X    if(pmatch(regex,len,p,n+1))
  529. X     { saves(n,q,pb-q->byte); prm(q); return 1; }
  530. X    }
  531. X    while((c=skip_special(p))!= MAXINT);
  532. X   pset(p,q); prm(q);
  533. X   return 0;
  534. X
  535. X  case '[':
  536. X   d=pgetc(p);
  537. X   if(d== MAXINT) return 0;
  538. X   if(!brack(®ex,&len,d)) { prgetc(p); return 0; }
  539. X   savec(n++,(char)d);
  540. X   break;
  541. X
  542. X  case '+':
  543. X   {
  544. X    char *oregex=regex;
  545. X    int olen=len;
  546. X    q=pdup(p);
  547. X    /* move forward */
  548. X    if (len--,(*regex++=='['))
  549. X     brack(®ex,&len,c);
  550. X    do
  551. X     {
  552. X      long pb=p->byte;
  553. X      if(pmatch(regex,len,p,n+1))
  554. X       { saves(n,q,pb-q->byte); prm(q); return 1; }
  555. X      regex=oregex;
  556. X      len=olen;
  557. X     }
  558. X    while(
  559. X     (MAXINT!=(c=pgetc(p))) &&
  560. X      (
  561. X       (len--,(*regex++=='[')) ?
  562. X        brack(®ex,&len,c) :
  563. X        regex[-1]==c
  564. X      ));
  565. X    pset(p,q); prm(q);
  566. X    return 0;
  567. X   }
  568. X   
  569. X  case '^':
  570. X   if(!pisbol(p)) return 0;
  571. X   break;
  572. X
  573. X  case '$':
  574. X   if(!piseol(p)) return 0;
  575. X   break;
  576. X
  577. X  case '<':
  578. X   if(!pisbow(p)) return 0;
  579. X   break;
  580. X  
  581. X  case '>':
  582. X   if(!piseow(p)) return 0;
  583. X   break;
  584. X  
  585. X  default:
  586. X   d=pgetc(p);
  587. X   if(d!=c) { if(d!= MAXINT) prgetc(p); return 0; }
  588. X   }
  589. X  break;
  590. X
  591. X default:
  592. X  d=pgetc(p);
  593. X  if(d!=c) { if(d!= MAXINT) prgetc(p); return 0; }
  594. X  }
  595. return 1;
  596. }
  597. X
  598. int pimatch(regex,len,p,n)
  599. char *regex;
  600. P *p;
  601. {
  602. int c,d;
  603. P *q;
  604. while(len--)
  605. X switch(c=*regex++)
  606. X  {
  607. X case '\\':
  608. X  if(!len--) return 0;
  609. X  switch(c=*regex++)
  610. X   {
  611. X  case '?':
  612. X   d=pgetc(p);
  613. X   if(d==MAXINT) return 0;
  614. X   savec(n++,(char)d);
  615. X   break;
  616. X  
  617. X  case 'n':
  618. X   d=pgetc(p);
  619. X   if(d!='\n') return 0;
  620. X   break;
  621. X  
  622. X  case '*':
  623. X   q=pdup(p);
  624. X   do
  625. X    {
  626. X    long pb=p->byte;
  627. X    if(pimatch(regex,len,p,n+1))
  628. X     { saves(n,q,pb-q->byte); prm(q); return 1; }
  629. X    }
  630. X    while(pgetc(p)!= MAXINT);
  631. X   pset(p,q); prm(q);
  632. X   return 0;
  633. X
  634. X  case 'c':
  635. X   q=pdup(p);
  636. X   do
  637. X    {
  638. X    long pb=p->byte;
  639. X    if(pimatch(regex,len,p,n+1))
  640. X     { saves(n,q,pb-q->byte); prm(q); return 1; }
  641. X    }
  642. X    while((c=skip_special(p))!= MAXINT);
  643. X   pset(p,q); prm(q);
  644. X   return 0;
  645. X
  646. X  case '[':
  647. X   d=pgetc(p);
  648. X   if(d==MAXINT) return 0;
  649. X   if(!brack(®ex,&len,d)) { prgetc(p); return 0; }
  650. X   savec(n++,(char)d);
  651. X   break;
  652. X
  653. X  case '+':
  654. X   {
  655. X    char *oregex=regex;
  656. X    int olen=len;
  657. X    q=pdup(p);
  658. X    /* move forward */
  659. X    if (len--,(*regex++=='['))
  660. X     brack(®ex,&len,c);
  661. X    do
  662. X     {
  663. X      long pb=p->byte;
  664. X      if(pimatch(regex,len,p,n+1))
  665. X       { saves(n,q,pb-q->byte); prm(q); return 1; }
  666. X      regex=oregex;
  667. X      len=olen;
  668. X     }
  669. X    while(
  670. X     (MAXINT!=(c=pgetc(p))) &&
  671. X      (
  672. X       (len--,(*regex++=='[')) ?
  673. X        brack(®ex,&len,c) :
  674. X        toup(regex[-1])==toup(c)
  675. X      ));
  676. X    pset(p,q); prm(q);
  677. X    return 0;
  678. X   }
  679. X
  680. X  case '^':
  681. X   if(!pisbol(p)) return 0;
  682. X   break;
  683. X
  684. X  case '$':
  685. X   if(!piseol(p)) return 0;
  686. X   break;
  687. X
  688. X  case '<':
  689. X   if(!pisbow(p)) return 0;
  690. X   break;
  691. X  
  692. X  case '>':
  693. X   if(!piseow(p)) return 0;
  694. X   break;
  695. X  
  696. X  default:
  697. X   d=pgetc(p);
  698. X   if(toup(d)!=toup(c)) { if(d!=MAXINT) prgetc(p); return 0; }
  699. X   }
  700. X  break;
  701. X
  702. X default:
  703. X  d=pgetc(p);
  704. X  if(toup(d)!=toup(c)) { if(d!=MAXINT) prgetc(p); return 0; }
  705. X  }
  706. return 1;
  707. }
  708. SHAR_EOF
  709. chmod 0600 regex.c ||
  710. echo 'restore of regex.c failed'
  711. Wc_c="`wc -c < 'regex.c'`"
  712. test 8187 -eq "$Wc_c" ||
  713.     echo 'regex.c: original size 8187, current size' "$Wc_c"
  714. fi
  715. # ============= regex.h ==============
  716. if test -f 'regex.h' -a X"$1" != X"-c"; then
  717.     echo 'x - skipping regex.h (File already exists)'
  718. else
  719. echo 'x - extracting regex.h (Text)'
  720. sed 's/^X//' << 'SHAR_EOF' > 'regex.h' &&
  721. /* Regular expression subroutines
  722. X   Copyright (C) 1992 Joseph H. Allen
  723. X
  724. This file is part of JOE (Joe's Own Editor)
  725. X
  726. JOE is free software; you can redistribute it and/or modify it under the 
  727. terms of the GNU General Public License as published by the Free Software 
  728. Foundation; either version 1, or (at your option) any later version.  
  729. X
  730. JOE is distributed in the hope that it will be useful, but WITHOUT ANY 
  731. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  732. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  733. details.  
  734. X
  735. You should have received a copy of the GNU General Public License along with 
  736. JOE; see the file COPYING.  If not, write to the Free Software Foundation, 
  737. 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
  738. X
  739. #ifndef _Iregex
  740. #define _Iregex 1
  741. X
  742. extern char *pieces[];
  743. int rmatch();
  744. int pmatch();
  745. int pimatch();
  746. X
  747. #endif
  748. SHAR_EOF
  749. chmod 0600 regex.h ||
  750. echo 'restore of regex.h failed'
  751. Wc_c="`wc -c < 'regex.h'`"
  752. test 879 -eq "$Wc_c" ||
  753.     echo 'regex.h: original size 879, current size' "$Wc_c"
  754. fi
  755. # ============= scrn.c ==============
  756. if test -f 'scrn.c' -a X"$1" != X"-c"; then
  757.     echo 'x - skipping scrn.c (File already exists)'
  758. else
  759. echo 'x - extracting scrn.c (Text)'
  760. sed 's/^X//' << 'SHAR_EOF' > 'scrn.c' &&
  761. /* Device independant TTY interface for JOE
  762. X   Copyright (C) 1992 Joseph H. Allen
  763. X
  764. This file is part of JOE (Joe's Own Editor)
  765. X
  766. JOE is free software; you can redistribute it and/or modify it under the 
  767. terms of the GNU General Public License as published by the Free Software 
  768. Foundation; either version 1, or (at your option) any later version.  
  769. X
  770. JOE is distributed in the hope that it will be useful, but WITHOUT ANY 
  771. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  772. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  773. details.  
  774. X
  775. You should have received a copy of the GNU General Public License along with 
  776. JOE; see the file COPYING.  If not, write to the Free Software Foundation, 
  777. 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
  778. X
  779. #include <stdio.h>
  780. #include <signal.h>
  781. #include "blocks.h"
  782. #include "heap.h"
  783. #include "vs.h"
  784. #include "termcap.h"
  785. #include "tty.h"
  786. #include "zstr.h"
  787. #include "scrn.h"
  788. X
  789. extern int mid;
  790. X
  791. /* Table of key sequences which we will translate to single codes */
  792. X
  793. SEQ seqs[NKEYS]=
  794. {
  795. X { "kd", KEYDOWN, "DOWN" },
  796. X { "ku", KEYUP, "UP" },
  797. X { "kl", KEYLEFT, "LEFT" },
  798. X { "kr", KEYRIGHT, "RIGHT" },
  799. X { "k0", KEYF0, "F0" },
  800. X { "k1", KEYF1, "F1" },
  801. X { "k2", KEYF2, "F2" },
  802. X { "k3", KEYF3, "F3" },
  803. X { "k4", KEYF4, "F4" },
  804. X { "k5", KEYF5, "F5" },
  805. X { "k6", KEYF6, "F6" },
  806. X { "k7", KEYF7, "F7" },
  807. X { "k8", KEYF8, "F8" },
  808. X { "k9", KEYF9, "F9" },
  809. X { "kD", KEYDEL, "DEL" },
  810. X { "kI", KEYINS, "INS" },
  811. X { "kh", KEYHOME, "HOME" },
  812. X { "kH", KEYEND, "END" },
  813. X { "kN", KEYPGDN, "PGDN" },
  814. X { "kP", KEYPGUP, "PGUP" }
  815. };
  816. X
  817. /* Set attributes */
  818. X
  819. void attr(t,c)
  820. SCRN *t;
  821. int c;
  822. {
  823. int e;
  824. c&=~255;
  825. e=(t->attrib&~c);
  826. if(e&UNDERLINE)
  827. X {
  828. X if(t->ue) texec(t->cap,t->ue,1), e&=~UNDERLINE;
  829. X t->attrib&=~UNDERLINE;
  830. X }
  831. if(e&INVERSE)
  832. X {
  833. X if(t->se) texec(t->cap,t->se,1), e&=~INVERSE;
  834. X else if(t->me) texec(t->cap,t->me,1), e=0, t->attrib=0;
  835. X t->attrib&=~INVERSE;
  836. X }
  837. if(e)
  838. X {
  839. X if(t->me) texec(t->cap,t->me,1);
  840. X t->attrib=0;
  841. X }
  842. e=(c&~t->attrib);
  843. if(e&INVERSE)
  844. X if(t->mr) texec(t->cap,t->mr,1);
  845. X else if(t->so) texec(t->cap,t->so,1);
  846. if(e&UNDERLINE)
  847. X if(t->us) texec(t->cap,t->us,1);
  848. if(e&BLINK)
  849. X if(t->mb) texec(t->cap,t->mb,1);
  850. if(e&BOLD)
  851. X if(t->md) texec(t->cap,t->md,1);
  852. if(e&DIM)
  853. X if(t->mh) texec(t->cap,t->mh,1);
  854. t->attrib=c;
  855. }
  856. X
  857. /* Set scrolling region */
  858. X
  859. void setregn(t,top,bot)
  860. SCRN *t;
  861. int top,bot;
  862. {
  863. if(!t->cs)
  864. X {
  865. X t->top=top;
  866. X t->bot=bot;
  867. X return;
  868. X }
  869. if(t->top!=top || t->bot!=bot)
  870. X {
  871. X t->top=top;
  872. X t->bot=bot;
  873. X texec(t->cap,t->cs,1,top,bot-1);
  874. X t->x= -1; t->y= -1;
  875. X }
  876. }
  877. X
  878. /* Enter insert mode */
  879. X
  880. void setins(t,x)
  881. SCRN *t;
  882. {
  883. if(t->ins!=1 && t->im)
  884. X {
  885. X t->ins=1;
  886. X texec(t->cap,t->im,1,x);
  887. X }
  888. }
  889. X
  890. /* Exit insert mode */
  891. X
  892. void clrins(t)
  893. SCRN *t;
  894. {
  895. if(t->ins!=0)
  896. X {
  897. X texec(t->cap,t->ei,1);
  898. X t->ins=0;
  899. X }
  900. }
  901. X
  902. /* Erase from given screen coordinate to end of line */
  903. X
  904. int eraeol(t,x,y)
  905. SCRN *t;
  906. {
  907. int *s, *ss;
  908. int w=t->co-x-1;            /* Don't worry about last column */
  909. if(w<=0) return 0;
  910. s=t->scrn+y*t->co+x;
  911. ss=s+w;
  912. do if(*--ss!=' ') { ++ss; break; } while(ss!=s);
  913. if((ss-s>3 || s[w]!=' ') && t->ce)
  914. X {
  915. X cpos(t,x,y);
  916. X attr(t,0);
  917. X texec(t->cap,t->ce,1);
  918. X msetI(s,' ',w);
  919. X }
  920. else while(s!=ss) outatr(t,x,y,' '), ++x, *s++=' ';
  921. return 0;
  922. }
  923. X
  924. /* Output a character with attributes */
  925. X
  926. void outatr(t,x,y,c)
  927. SCRN *t;
  928. {
  929. unsigned char ch;
  930. if(c== -1) c=' ';
  931. if(t->ins) clrins(t);
  932. ch=c; c-=ch;
  933. if(t->x!=x || t->y!=y) cpos(t,x,y);
  934. if(c!=t->attrib) attr(t,c);
  935. if(t->hz && ch=='~') ch='\\';
  936. ttputc(ch);
  937. ++t->x;
  938. }
  939. X
  940. /* As above but useable in insert mode */
  941. /* The cursor position must already be correct */
  942. X
  943. void outatri(t,x,y,c)
  944. SCRN *t;
  945. {
  946. unsigned char ch;
  947. if(c== -1) c=' ';
  948. ch=c; c-=ch;
  949. if(c!=t->attrib) attr(t,c);
  950. if(t->hz && ch=='~') ch='\\';
  951. ttputc(ch);
  952. ++t->x;
  953. }
  954. X
  955. /* Overstrike terminal handling */
  956. X
  957. void outatr1(t,x,y,c)
  958. SCRN *t;
  959. {
  960. if(t->os && t->eo &&
  961. X   (t->scrn[x+t->co*y]!=' ' || (t->scrn[x+t->co*y]&~255)!=(c&~255)) ||
  962. X   t->ul && (c&255)=='_' && (!t->os || t->eo)
  963. X  )
  964. X outatr(t,x,y,' ');
  965. outatr(t,x,y,c);
  966. if(c&UNDERLINE && !t->us)
  967. X {
  968. X cpos(t,x,y), texec(t->cap,t->uc,1);
  969. X if(++t->x==t->co)
  970. X  if(t->am) t->x=0, ++t->y;
  971. X  else if(t->xn) t->x= -1, t->y= -1;
  972. X  else --t->x;
  973. X }
  974. }
  975. X
  976. void out(t,c)
  977. char *t;
  978. char c;
  979. {
  980. ttputc(c);
  981. }
  982. X
  983. SCRN *nopen()
  984. {
  985. SCRN *t=(SCRN *)malloc(sizeof(SCRN));
  986. int x,y;
  987. char *p;
  988. ttopen();
  989. X
  990. if(!(t->cap=getcap(NULL,baud,out,NULL)))
  991. X {
  992. X free(t);
  993. X ttclose();
  994. X fprintf(stdout,"Couldn't load termcap/terminfo entry\n");
  995. X return 0;
  996. X }
  997. X
  998. t->li=getnum(t->cap,"li"); if(t->li<1) t->li=24;
  999. t->co=getnum(t->cap,"co"); if(t->co<2) t->co=80;
  1000. x=y=0;
  1001. ttgtsz(&x,&y);
  1002. if(x>7 && y>3) t->li=y, t->co=x;
  1003. x=y=0;
  1004. if(p=getenv("LINES")) sscanf(p,"%d",&y);
  1005. if(p=getenv("COLUMNS")) sscanf(p,"%d",&x);
  1006. if(x>7) t->co=x;
  1007. if(y>3) t->li=y;
  1008. X
  1009. t->hz=getflag(t->cap,"hz");
  1010. t->os=getflag(t->cap,"os");
  1011. t->eo=getflag(t->cap,"eo");
  1012. if(getflag(t->cap,"hc")) t->os=1;
  1013. if(t->os || getflag(t->cap,"ul")) t->ul=1;
  1014. else t->ul=0;
  1015. X
  1016. t->xn=getflag(t->cap,"xn");
  1017. t->am=getflag(t->cap,"am");
  1018. X
  1019. t->ti=getstr(t->cap,"ti");
  1020. t->cl=getstr(t->cap,"cl");
  1021. t->cd=getstr(t->cap,"cd");
  1022. X
  1023. t->te=getstr(t->cap,"te");
  1024. X
  1025. t->mb=0; t->md=0; t->mh=0; t->mr=0; t->avattr=0;
  1026. if(!(t->me=getstr(t->cap,"me"))) goto oops;
  1027. if((t->mb=getstr(t->cap,"mb"))) t->avattr|=BLINK;
  1028. if((t->md=getstr(t->cap,"md"))) t->avattr|=BOLD;
  1029. if((t->mh=getstr(t->cap,"mh"))) t->avattr|=DIM;
  1030. if((t->mr=getstr(t->cap,"mr"))) t->avattr|=INVERSE;
  1031. oops:
  1032. X
  1033. t->so=0; t->se=0;
  1034. if(getnum(t->cap,"sg")<=0 && !t->mr && getstr(t->cap,"se"))
  1035. X {
  1036. X if(t->so=getstr(t->cap,"so")) t->avattr|=INVERSE;
  1037. X t->se=getstr(t->cap,"se");
  1038. X }
  1039. if(getflag(t->cap,"xs") || getflag(t->cap,"xt")) t->so=0;
  1040. X
  1041. t->us=0; t->ue=0;
  1042. if(getnum(t->cap,"ug")<=0 && getstr(t->cap,"ue"))
  1043. X {
  1044. X if(t->us=getstr(t->cap,"us")) t->avattr|=UNDERLINE;
  1045. X t->ue=getstr(t->cap,"ue");
  1046. X }
  1047. X
  1048. if(!(t->uc=getstr(t->cap,"uc"))) if(t->ul) t->uc="_";
  1049. if(t->uc) t->avattr|=UNDERLINE;
  1050. X
  1051. t->ms=getflag(t->cap,"ms");
  1052. X
  1053. t->da=getflag(t->cap,"da");
  1054. t->db=getflag(t->cap,"db");
  1055. t->cs=getstr(t->cap,"cs");
  1056. t->rr=getflag(t->cap,"rr");
  1057. t->sf=getstr(t->cap,"sf");
  1058. t->sr=getstr(t->cap,"sr");
  1059. t->SF=getstr(t->cap,"SF");
  1060. t->SR=getstr(t->cap,"SR");
  1061. t->al=getstr(t->cap,"al");
  1062. t->dl=getstr(t->cap,"dl");
  1063. t->AL=getstr(t->cap,"AL");
  1064. t->DL=getstr(t->cap,"DL");
  1065. if(!getflag(t->cap,"ns") && !t->sf) t->sf="\12";
  1066. X
  1067. if(!getflag(t->cap,"in") && baud<38400)
  1068. X {
  1069. X t->dc=getstr(t->cap,"dc");
  1070. X t->DC=getstr(t->cap,"DC");
  1071. X t->dm=getstr(t->cap,"dm");
  1072. X t->ed=getstr(t->cap,"ed");
  1073. X
  1074. X t->im=getstr(t->cap,"im");
  1075. X t->ei=getstr(t->cap,"ei");
  1076. X t->ic=getstr(t->cap,"ic");
  1077. X t->IC=getstr(t->cap,"IC");
  1078. X t->ip=getstr(t->cap,"ip");
  1079. X t->mi=getflag(t->cap,"mi");
  1080. X }
  1081. else
  1082. X {
  1083. X t->dm=0; t->dc=0; t->DC=0; t->ed=0;
  1084. X t->im=0; t->ic=0; t->IC=0; t->ip=0; t->ei=0;
  1085. X t->mi=1;
  1086. X }
  1087. X
  1088. t->bs=0;
  1089. if(getstr(t->cap,"bc")) t->bs=getstr(t->cap,"bc");
  1090. else if(getstr(t->cap,"le")) t->bs=getstr(t->cap,"le");
  1091. if(getflag(t->cap,"bs")) t->bs="\10";
  1092. X
  1093. t->cbs=tcost(t->cap,t->bs,1,2,2);
  1094. X
  1095. t->lf="\12";
  1096. if(getstr(t->cap,"do")) t->lf=getstr(t->cap,"do");
  1097. t->clf=tcost(t->cap,t->lf,1,2,2);
  1098. X
  1099. t->up=getstr(t->cap,"up");
  1100. t->cup=tcost(t->cap,t->up,1,2,2);
  1101. X
  1102. t->nd=getstr(t->cap,"nd");
  1103. X
  1104. t->tw=8;
  1105. if(getnum(t->cap,"it")>0) t->tw=getnum(t->cap,"it");
  1106. else if(getnum(t->cap,"tw")>0) t->tw=getnum(t->cap,"tw");
  1107. X
  1108. if(!(t->ta=getstr(t->cap,"ta"))) if(getflag(t->cap,"pt")) t->ta="\11";
  1109. t->bt=getstr(t->cap,"bt");
  1110. if(getflag(t->cap,"xt")) t->ta=0, t->bt=0;
  1111. X
  1112. t->cta=tcost(t->cap,t->ta,1,2,2);
  1113. t->cbt=tcost(t->cap,t->bt,1,2,2);
  1114. X
  1115. t->ho=getstr(t->cap,"ho");
  1116. t->cho=tcost(t->cap,t->ho,1,2,2);
  1117. t->ll=getstr(t->cap,"ll");
  1118. t->cll=tcost(t->cap,t->ll,1,2,2);
  1119. X
  1120. t->cr="\15";
  1121. if(getstr(t->cap,"cr")) t->cr=getstr(t->cap,"cr");
  1122. if(getflag(t->cap,"nc") || getflag(t->cap,"xr")) t->cr=0;
  1123. t->ccr=tcost(t->cap,t->cr,1,2,2);
  1124. X
  1125. t->cRI=tcost(t->cap,t->RI=getstr(t->cap,"RI"),1,2,2);
  1126. t->cLE=tcost(t->cap,t->LE=getstr(t->cap,"LE"),1,2,2);
  1127. t->cUP=tcost(t->cap,t->UP=getstr(t->cap,"UP"),1,2,2);
  1128. t->cDO=tcost(t->cap,t->DO=getstr(t->cap,"DO"),1,2,2);
  1129. t->cch=tcost(t->cap,t->ch=getstr(t->cap,"ch"),1,2,2);
  1130. t->ccv=tcost(t->cap,t->cv=getstr(t->cap,"cv"),1,2,2);
  1131. t->ccb=tcost(t->cap,t->cb=getstr(t->cap,"cb"),1,2,2);
  1132. t->ccm=tcost(t->cap,t->cm=getstr(t->cap,"cm"),1,2,2);
  1133. X
  1134. t->cce=tcost(t->cap,t->ce=getstr(t->cap,"ce"),1,2,2);
  1135. X
  1136. x=0;
  1137. for(y=0;y!=NKEYS;++y)
  1138. X if(getstr(t->cap,seqs[y].seq))
  1139. X  {
  1140. X  char *s=tcompile(t->cap,getstr(t->cap,seqs[y].seq));
  1141. X  if(s)
  1142. X   {
  1143. X   t->ktab[x].s=s;
  1144. X   t->ktab[x].l=sLen(s);
  1145. X   t->ktab[x].n=seqs[y].code;
  1146. X   ++x;
  1147. X   }
  1148. X  }
  1149. t->tabsize=x;
  1150. t->kbufp=0;
  1151. t->dumpptr= -1;
  1152. X
  1153. /* Make sure terminal can do absolute positioning */
  1154. if(t->cm) goto ok;
  1155. if(t->ch && t->cv) goto ok;
  1156. if(t->ho && (t->lf || t->DO || t->cv)) goto ok;
  1157. if(t->ll && (t->up || t->UP || t->cv)) goto ok;
  1158. if(t->cr && t->cv) goto ok;
  1159. leave=1;
  1160. ttclose();
  1161. signrm();
  1162. fprintf(stderr,"Sorry, your terminal can't do absolute cursor positioning\n");
  1163. fprintf(stderr,"It\'s broken\n");
  1164. return 0;
  1165. ok:
  1166. X
  1167. /* Determine if we can scroll */
  1168. if((t->sr || t->SR) && (t->sf || t->SF) && t->cs ||
  1169. X   (t->al || t->AL) && (t->dl || t->DL)) t->scroll=1;
  1170. else t->scroll=0, mid=1;
  1171. X
  1172. /* Determine if we can ins/del within lines */
  1173. if((t->im || t->ic || t->IC) && (t->dc || t->DC)) t->insdel=1;
  1174. else t->insdel=0;
  1175. X
  1176. /* Adjust for high baud rates */
  1177. if(baud>=38400) t->scroll=0, t->insdel=0, mid=0;
  1178. X
  1179. /* Initialize variable screen size dependant vars */
  1180. t->scrn=0; t->sary=0; t->updtab=0; t->compose=0;
  1181. t->ofst=0; t->ary=0;
  1182. t->htab=(struct hentry *)malloc(256*sizeof(struct hentry));
  1183. nresize(t,t->co,t->li);
  1184. X
  1185. /* Send out terminal initialization string */
  1186. if(t->ti) texec(t->cap,t->ti,1);
  1187. X
  1188. return t;
  1189. X
  1190. /* Change size of screen */
  1191. X
  1192. void nresize(t,w,h)
  1193. SCRN *t;
  1194. {
  1195. if(h<4) h=4;
  1196. if(w<8) w=8;
  1197. t->li=h;
  1198. t->co=w;
  1199. if(t->sary) free(t->sary);
  1200. if(t->updtab) free(t->updtab);
  1201. if(t->scrn) free(t->scrn);
  1202. if(t->compose) free(t->compose);
  1203. if(t->ofst) free(t->ofst);
  1204. if(t->ary) free(t->ary);
  1205. t->scrn=(int *)malloc(t->li*t->co*sizeof(int));
  1206. t->sary=(int *)calloc(t->li,sizeof(int));
  1207. t->updtab=(int *)malloc(t->li*sizeof(int));
  1208. t->compose=(int *)malloc(t->co*sizeof(int));
  1209. t->ofst=(int *)malloc(t->co*sizeof(int));
  1210. t->ary=(struct hentry *)malloc(t->co*sizeof(struct hentry));
  1211. nredraw(t);
  1212. }
  1213. X
  1214. /* Calculate cost of positioning the cursor using only relative cursor
  1215. X * positioning functions: t->(lf, DO, up, UP, bs, LE, RI, ta, bt) and rewriting
  1216. X * characters (to move right)
  1217. X *
  1218. X * This doesn't use the am and bw capabilities although it probably could.
  1219. X */
  1220. X
  1221. static int relcost(t,x,y,ox,oy)
  1222. register SCRN *t;
  1223. register int x,y,ox,oy;
  1224. {
  1225. int cost=0, c;
  1226. X
  1227. /* If we don't know the cursor position, force use of absolute positioning */
  1228. if(oy== -1 || ox== -1) return 10000;
  1229. X
  1230. /* First adjust row */
  1231. if(y>oy)
  1232. X /* Have to go down */
  1233. X if(t->lf)
  1234. X  if(t->cDO<(c=(y-oy)*t->clf)) cost+=t->cDO;
  1235. X  else cost+=c;
  1236. X else if(t->DO) cost+=t->cDO;
  1237. X else return 10000;
  1238. else if(y<oy)
  1239. X /* Have to go up */
  1240. X if(t->up)
  1241. X  if(t->cUP<(c=(oy-y)*t->cup)) cost+=t->cUP;
  1242. X  else cost+=c;
  1243. X else if(t->UP) cost+=t->cUP;
  1244. X else return 10000;
  1245. X
  1246. /* Now adjust column */
  1247. X
  1248. /* Use tabs */
  1249. if(x>ox && t->ta)
  1250. X {
  1251. X int ntabs=(x-ox+ox%t->tw)/t->tw;
  1252. X int cstunder=x%t->tw+t->cta*ntabs, cstover;
  1253. X if(x+t->tw<t->co && t->bs) cstover=t->cbs*(t->tw-x%t->tw)+t->cta*(ntabs+1);
  1254. X else cstover=10000;
  1255. X if(cstunder<t->cRI && cstunder<x-ox && cstover>cstunder)
  1256. X  return cost+cstunder;
  1257. X else if(cstover<t->cRI && cstover<x-ox) return cost+cstover;
  1258. X }
  1259. else if(x<ox && t->bt)
  1260. X {
  1261. X int ntabs=(ox-x+t->tw-ox%t->tw)/t->tw;
  1262. X int cstunder,cstover;
  1263. X if(t->bs) cstunder=t->cbt*ntabs+t->cbs*(t->tw-x%t->tw); else cstunder=10000;
  1264. X if(x-t->tw>=0) cstover=t->cbt*(ntabs+1)+x%t->tw; else cstover=10000;
  1265. X if(cstunder<t->cLE && (t->bs?cstunder<(ox-x)*t->cbs:1) && cstover>cstunder)
  1266. X  return cost+cstunder;
  1267. X else if(cstover<t->cRI && (t->bs?cstover<(ox-x)*t->cbs:1)) return cost+cstover;
  1268. X }
  1269. X
  1270. /* Use simple motions */
  1271. if(x<ox)
  1272. X /* Have to go left */
  1273. X if(t->bs) 
  1274. X  if(t->cLE<(c=(ox-x)*t->cbs)) cost+=t->cLE;
  1275. X  else cost+=c;
  1276. X else if(t->LE) cost+=t->cLE;
  1277. X else return 10000;
  1278. else if(x>ox)
  1279. X /* Have to go right */
  1280. X /* Hmm.. this should take into account possible attribute changes */
  1281. X if(t->cRI<x-ox) cost+=t->cRI;
  1282. X else cost+=x-ox;
  1283. X
  1284. return cost;
  1285. }
  1286. X
  1287. /* Find optimal set of cursor positioning commands to move from the current
  1288. X * cursor row and column (either or both of which might be unknown) to the
  1289. X * given new row and column and execute them.
  1290. X */
  1291. X
  1292. static void cposs(t,x,y)
  1293. register SCRN *t;
  1294. register int x,y;
  1295. {
  1296. register int bestcost,cost;
  1297. int bestway;
  1298. int hy;
  1299. int hl;
  1300. X
  1301. /* Home y position is usually 0, but it is 'top' if we have scrolling region
  1302. X * relative addressing
  1303. X */
  1304. if(t->rr) hy=t->top, hl=t->bot-1;
  1305. else hy=0, hl=t->li-1;
  1306. X
  1307. /* Assume best way is with only using relative cursor positioning */
  1308. X
  1309. bestcost=relcost(t,x,y,t->x,t->y); bestway=0;
  1310. X
  1311. /* Now check if combinations of absolute cursor positioning functions are
  1312. X * better (or necessary in case one or both cursor positions are unknown)
  1313. X */
  1314. X
  1315. if(t->ccr<bestcost)
  1316. X {
  1317. X cost=relcost(t,x,y,0,t->y)+t->ccr;
  1318. X if(cost<bestcost) bestcost=cost, bestway=1;
  1319. X }
  1320. if(t->cho<bestcost)
  1321. X {
  1322. X cost=relcost(t,x,y,0,hy)+t->cho;
  1323. X if(cost<bestcost) bestcost=cost, bestway=2;
  1324. X }
  1325. if(t->cll<bestcost)
  1326. X {
  1327. X cost=relcost(t,x,y,0,hl)+t->cll;
  1328. X if(cost<bestcost) bestcost=cost, bestway=3;
  1329. X }
  1330. if(t->cch<bestcost && x!=t->x)
  1331. X {
  1332. X cost=relcost(t,x,y,x,t->y)+tcost(t->cap,t->ch,1,x);
  1333. X if(cost<bestcost) bestcost=cost, bestway=4;
  1334. X }
  1335. if(t->ccv<bestcost && y!=t->y)
  1336. X {
  1337. X cost=relcost(t,x,y,t->x,y)+tcost(t->cap,t->cv,1,y);
  1338. X if(cost<bestcost) bestcost=cost, bestway=5;
  1339. X }
  1340. if(t->ccb<bestcost)
  1341. X {
  1342. X cost=relcost(t,x,y,0,y)+tcost(t->cap,t->cb,1,y);
  1343. X if(cost<bestcost) bestcost=cost, bestway=13;
  1344. X }
  1345. if(t->ccm<bestcost)
  1346. X {
  1347. X cost=tcost(t->cap,t->cm,1,y,x);
  1348. X if(cost<bestcost) bestcost=cost, bestway=6;
  1349. X }
  1350. if(t->cch+t->ccv<bestcost && x!=t->x && y!=t->y)
  1351. X {
  1352. X cost=tcost(t->cap,t->cv,1,y-hy)+tcost(t->cap,t->ch,1,x);
  1353. X if(cost<bestcost) bestcost=cost, bestway=7;
  1354. X }
  1355. if(t->ccv+t->ccr<bestcost && y!=t->y)
  1356. X {
  1357. X cost=tcost(t->cap,t->cv,1,y)+tcost(t->cap,t->cr,1)+
  1358. X      relcost(t,x,y,0,y);
  1359. X if(cost<bestcost) bestcost=cost, bestway=8;
  1360. X }
  1361. if(t->cll+t->cch<bestcost)
  1362. X {
  1363. X cost=tcost(t->cap,t->ll,1)+tcost(t->cap,t->ch,1,x)+
  1364. X      relcost(t,x,y,x,hl);
  1365. X if(cost<bestcost) bestcost=cost, bestway=9;
  1366. X }
  1367. if(t->cll+t->ccv<bestcost)
  1368. X {
  1369. X cost=tcost(t->cap,t->ll,1)+tcost(t->cap,t->cv,1,y)+
  1370. X      relcost(t,x,y,0,y);
  1371. X if(cost<bestcost) bestcost=cost, bestway=10;
  1372. X }
  1373. if(t->cho+t->cch<bestcost)
  1374. X {
  1375. X cost=tcost(t->cap,t->ho,1)+tcost(t->cap,t->ch,1,x)+
  1376. X      relcost(t,x,y,x,hy);
  1377. X if(cost<bestcost) bestcost=cost, bestway=11;
  1378. X }
  1379. if(t->cho+t->ccv<bestcost)
  1380. X {
  1381. X cost=tcost(t->cap,t->ho,1)+tcost(t->cap,t->cv,1,y)+
  1382. X      relcost(t,x,y,0,y);
  1383. X if(cost<bestcost) bestcost=cost, bestway=12;
  1384. X }
  1385. X
  1386. /* Do absolute cursor positioning if we don't know the cursor position or
  1387. X * if it is faster than doing only relative cursor positioning
  1388. X */
  1389. X
  1390. switch(bestway)
  1391. X {
  1392. case 1: texec(t->cap,t->cr,1); t->x=0; break;
  1393. case 2: texec(t->cap,t->ho,1); t->x=0; t->y=hy; break;
  1394. case 3: texec(t->cap,t->ll,1); t->x=0; t->y=hl; break;
  1395. case 9: texec(t->cap,t->ll,1); t->x=0; t->y=hl; goto doch;
  1396. case 11: texec(t->cap,t->ho,1); t->x=0; t->y=hy;
  1397. X  doch:
  1398. case 4: texec(t->cap,t->ch,1,x); t->x=x; break;
  1399. case 10: texec(t->cap,t->ll,1); t->x=0; t->y=hl; goto docv;
  1400. case 12: texec(t->cap,t->ho,1); t->x=0; t->y=hy; goto docv;
  1401. case 8: texec(t->cap,t->cr,1); t->x=0;
  1402. X  docv:
  1403. case 5: texec(t->cap,t->cv,1,y); t->y=y; break;
  1404. case 6: texec(t->cap,t->cm,1,y,x); t->y=y, t->x=x; break;
  1405. case 7: texec(t->cap,t->cv,1,y); t->y=y;
  1406. X        texec(t->cap,t->ch,1,x); t->x=x;
  1407. X        break;
  1408. case 13: texec(t->cap,t->cb,1,y); t->y=y; t->x=0; break;
  1409. X }
  1410. X
  1411. /* Use relative cursor position functions if we're not there yet */
  1412. X
  1413. /* First adjust row */
  1414. if(y>t->y)
  1415. X /* Have to go down */
  1416. X if(!t->lf || t->cDO<(y-t->y)*t->clf)
  1417. X  texec(t->cap,t->DO,1,y-t->y), t->y=y;
  1418. X else while(y>t->y) texec(t->cap,t->lf,1), ++t->y;
  1419. else if(y<t->y)
  1420. X /* Have to go up */
  1421. X if(!t->up || t->cUP<(t->y-y)*t->cup)
  1422. X  texec(t->cap,t->UP,1,t->y-y), t->y=y;
  1423. X else while(y<t->y) texec(t->cap,t->up,1), --t->y;
  1424. X
  1425. /* Use tabs */
  1426. if(x>t->x && t->ta)
  1427. X {
  1428. X int ntabs=(x-t->x+t->x%t->tw)/t->tw;
  1429. X int cstunder=x%t->tw+t->cta*ntabs, cstover;
  1430. X if(x+t->tw<t->co && t->bs) cstover=t->cbs*(t->tw-x%t->tw)+t->cta*(ntabs+1);
  1431. X else cstover=10000;
  1432. X if(cstunder<t->cRI && cstunder<x-t->x && cstover>cstunder)
  1433. X  {
  1434. X  if(ntabs)
  1435. X   {
  1436. X   t->x=x-x%t->tw;
  1437. X   do texec(t->cap,t->ta,1); while(--ntabs);
  1438. X   }
  1439. X  }
  1440. X else if(cstover<t->cRI && cstover<x-t->x)
  1441. X  {
  1442. X  t->x=t->tw+x-x%t->tw;
  1443. X  ++ntabs;
  1444. X  do texec(t->cap,t->ta,1); while(--ntabs);
  1445. X  }
  1446. X }
  1447. else if(x<t->x && t->bt)
  1448. X {
  1449. X int ntabs=((t->x+t->tw-1)-(t->x+t->tw-1)%t->tw-
  1450. X            ((x+t->tw-1)-(x+t->tw-1)%t->tw))/t->tw;
  1451. X int cstunder,cstover;
  1452. X if(t->bs) cstunder=t->cbt*ntabs+t->cbs*(t->tw-x%t->tw); else cstunder=10000;
  1453. X if(x-t->tw>=0) cstover=t->cbt*(ntabs+1)+x%t->tw; else cstover=10000;
  1454. X if(cstunder<t->cLE && (t->bs?cstunder<(t->x-x)*t->cbs:1) && cstover>cstunder)
  1455. X  {
  1456. X  if(ntabs)
  1457. X   {
  1458. X   do texec(t->cap,t->bt,1); while(--ntabs);
  1459. X   t->x=x+t->tw-x%t->tw;
  1460. X   }
  1461. X  }
  1462. X else if(cstover<t->cRI && (t->bs?cstover<(t->x-x)*t->cbs:1))
  1463. X  {
  1464. X  t->x=x-x%t->tw; ++ntabs;
  1465. X  do texec(t->cap,t->bt,1); while(--ntabs);
  1466. X  }
  1467. X }
  1468. X
  1469. /* Now adjust column */
  1470. if(x<t->x)
  1471. X /* Have to go left */
  1472. X if(!t->bs || t->cLE<(t->x-x)*t->cbs)
  1473. X  texec(t->cap,t->LE,1,t->x-x), t->x=x;
  1474. X else while(x<t->x) texec(t->cap,t->bs,1), --t->x;
  1475. else if(x>t->x)
  1476. X /* Have to go right */
  1477. X /* Hmm.. this should take into account possible attribute changes */
  1478. X if(t->cRI<x-t->x) texec(t->cap,t->RI,1,x-t->x), t->x=x;
  1479. X else
  1480. X  {
  1481. X  if(t->ins) clrins(t);
  1482. X  while(x>t->x)
  1483. X   {
  1484. X   int c=t->scrn[t->x+t->y*t->co];
  1485. X   outatr(t,t->x,y,c);
  1486. X   }
  1487. X  }
  1488. }
  1489. X
  1490. void cpos(t,x,y)
  1491. register SCRN *t;
  1492. register int x,y;
  1493. {
  1494. if(y==t->y)
  1495. X {
  1496. X if(x==t->x) return;
  1497. X if(x>t->x && x-t->x<4)
  1498. X  {
  1499. X  int *cs=t->scrn+t->x+t->co*t->y;
  1500. X  if(t->ins)
  1501. X   if(t->nd)
  1502. X    {
  1503. X    do texec(t->cap,t->nd,1); while(++t->x!=x);
  1504. X    return;
  1505. X    }
  1506. X   else clrins(t);
  1507. X  do { int c=*cs++; outatr(t,t->x,t->y,c); } while(x!=t->x);
  1508. X  return;
  1509. X  }
  1510. X }
  1511. if(!t->ms && t->attrib&(INVERSE|UNDERLINE))
  1512. X attr(t,t->attrib&~(INVERSE|UNDERLINE));
  1513. if(y<t->top || y>=t->bot) setregn(t,0,t->li);
  1514. cposs(t,x,y);
  1515. }
  1516. X
  1517. static void doinschr(t,x,y,s,n)
  1518. SCRN *t;
  1519. int x,y,*s,n;
  1520. {
  1521. int a;
  1522. if(x<0) s-=x, x=0;
  1523. if(x>=t->co-1 || n<=0) return;
  1524. if(t->im || t->ic || t->IC)
  1525. X {
  1526. X cpos(t,x,y);
  1527. X setins(t,x);
  1528. X if(n==1 && t->ic || !t->IC)
  1529. X  for(a=0;a!=n;++a)
  1530. X   {
  1531. X   texec(t->cap,t->ic,1,x);
  1532. X   outatri(t,x+a,y,s[a]);
  1533. X   texec(t->cap,t->ip,1,x);
  1534. X   }
  1535. X else
  1536. X  {
  1537. X  texec(t->cap,t->IC,1,n);
  1538. X  for(a=0;a!=n;++a) outatri(t,x+a,y,s[a]);
  1539. X  }
  1540. X if(!t->mi) clrins(t);
  1541. X }
  1542. mmove(t->scrn+x+t->co*y+n,t->scrn+x+t->co*y,(t->co-(x+n))*sizeof(int));
  1543. mcpy(t->scrn+x+t->co*y,s,n*sizeof(int));
  1544. }
  1545. X
  1546. static void dodelchr(t,x,y,n)
  1547. SCRN *t;
  1548. int x,y,n;
  1549. {
  1550. int a;
  1551. if(x<0) x=0;
  1552. if(!n || x>=t->co-1) return;
  1553. if(t->dc || t->DC)
  1554. X {
  1555. X cpos(t,x,y);
  1556. X texec(t->cap,t->dm,1,x);        /* Enter delete mode */
  1557. X if(n==1 && t->dc || !t->DC)
  1558. X  for(a=n;a;--a) texec(t->cap,t->dc,1,x);
  1559. X else texec(t->cap,t->DC,1,n);
  1560. X texec(t->cap,t->ed,1,x);        /* Exit delete mode */
  1561. X }
  1562. mmove(t->scrn+t->co*y+t->x,t->scrn+t->co*y+t->x+n,(t->co-(x+n))*sizeof(int));
  1563. }
  1564. X
  1565. /* Insert/Delete within line */
  1566. X
  1567. void magic(t,y,cs,s,placex)
  1568. SCRN *t;
  1569. int y,*cs,*s;
  1570. {
  1571. struct hentry *htab=t->htab;
  1572. int *ofst=t->ofst;
  1573. int aryx=1;
  1574. int x;
  1575. if(!(t->im || t->ic || t->IC) ||
  1576. X   !(t->dc || t->DC)) return;
  1577. mset(htab,0,256*sizeof(struct hentry));
  1578. msetI(ofst,0,t->co);
  1579. X
  1580. /* Build hash table */
  1581. for(x=0;x!=t->co-1;++x)
  1582. X t->ary[aryx].next=htab[cs[x]&255].next,
  1583. X t->ary[aryx].loc=x,
  1584. X ++htab[cs[x]&255].loc,
  1585. X htab[cs[x]&255].next=aryx++;
  1586. X
  1587. /* Build offset table */
  1588. for(x=0;x<t->co-1;)
  1589. X if(htab[s[x]&255].loc>=15) ofst[x++]= t->co-1;
  1590. X else
  1591. X  {
  1592. X  int aryy;
  1593. X  int maxaryy;
  1594. X  int maxlen=0;
  1595. X  int best=0;
  1596. X  int bestback=0;
  1597. X  int z;
  1598. X  for(aryy=htab[s[x]&255].next;aryy;aryy=t->ary[aryy].next)
  1599. X   {
  1600. X   int amnt,back;
  1601. X   int tsfo=t->ary[aryy].loc-x;
  1602. X   int cst= -Iabs(tsfo);
  1603. X   int pre=32;
  1604. X   for(amnt=0;x+amnt<t->co-1 && x+tsfo+amnt<t->co-1;++amnt)
  1605. X    {
  1606. X    if(cs[x+tsfo+amnt]!=s[x+amnt]) break;
  1607. X    else if(s[x+amnt]&255!=32 || pre!=32) ++cst;
  1608. X    pre=s[x+amnt]&255;
  1609. X    }
  1610. X   pre=32;
  1611. X   for(back=0;back+x>0 && back+tsfo+x>0;--back)
  1612. X    {
  1613. X    if(cs[x+tsfo+back-1]!=s[x+back-1]) break;
  1614. X    else if(s[x+back-1]&255!=32 || pre!=32) ++cst;
  1615. X    pre=s[x+back-1]&255;
  1616. X    }
  1617. X   if(cst>best) maxaryy=aryy, maxlen=amnt, best=cst, bestback=back;
  1618. X   }
  1619. X  if(!maxlen) ofst[x]=t->co-1, maxlen=1;
  1620. X  else if(best<2) for(z=0;z!=maxlen;++z) ofst[x+z]=t->co-1;
  1621. X  else for(z=0;z!=maxlen-bestback;++z)
  1622. X   ofst[x+z+bestback]=t->ary[maxaryy].loc-x;
  1623. X  x+=maxlen;
  1624. X  }
  1625. X
  1626. /* Apply scrolling commands */
  1627. X
  1628. for(x=0;x!=t->co-1;++x)
  1629. X {
  1630. X int q=ofst[x];
  1631. X if(q && q!=t->co-1)
  1632. X  if(q>0)
  1633. X   {
  1634. X   int z,fu;
  1635. X   for(z=x;z!=t->co-1 && ofst[z]==q;++z);
  1636. X   while(s[x]==cs[x] && x<placex) ++x;
  1637. X   dodelchr(t,x,y,q);
  1638. X   for(fu=x;fu!=t->co-1;++fu) if(ofst[fu]!=t->co-1) ofst[fu]-=q;
  1639. X   x=z-1;
  1640. X   }
  1641. X  else
  1642. X   {
  1643. X   int z,fu;
  1644. X   for(z=x;z!=t->co-1 && ofst[z]==q;++z);
  1645. X   while(s[x+q]==cs[x+q] && x-q<placex) ++x;
  1646. X   doinschr(t,x+q,y,s+x+q,-q);
  1647. X   for(fu=x;fu!=t->co-1;++fu) if(ofst[fu]!=t->co-1) ofst[fu]-=q;
  1648. X   x=z-1;
  1649. X   }
  1650. X }
  1651. }
  1652. X
  1653. static void doupscrl(t,top,bot,amnt)
  1654. SCRN *t;
  1655. int top,bot,amnt;
  1656. {
  1657. int a=amnt, x;
  1658. if(!amnt) return;
  1659. attr(t,0);
  1660. if(top==0 && bot==t->li && (t->sf || t->SF))
  1661. X {
  1662. X setregn(t,0,t->li);
  1663. X cpos(t,0,t->li-1);
  1664. X if(amnt==1 && t->sf || !t->SF) while(a--) texec(t->cap,t->sf,1,t->li-1);
  1665. X else texec(t->cap,t->SF,a,a);
  1666. X goto done;
  1667. X }
  1668. if(bot==t->li && (t->dl || t->DL))
  1669. X {
  1670. X setregn(t,0,t->li);
  1671. X cpos(t,0,top);
  1672. X if(amnt==1 && t->dl || !t->DL) while(a--) texec(t->cap,t->dl,1,top);
  1673. X else texec(t->cap,t->DL,a,a);
  1674. X goto done;
  1675. X }
  1676. if(t->cs && ( t->sf || t->SF ))
  1677. X {
  1678. X setregn(t,top,bot);
  1679. X cpos(t,0,bot-1);
  1680. X if(amnt==1 && t->sf || !t->SF) while(a--) texec(t->cap,t->sf,1,bot-1);
  1681. X else texec(t->cap,t->SF,a,a);
  1682. X goto done;
  1683. X }
  1684. if((t->dl || t->DL) && (t->al || t->AL))
  1685. X {
  1686. X cpos(t,0,top);
  1687. X if(amnt==1 && t->dl || !t->DL) while(a--) texec(t->cap,t->dl,1,top);
  1688. X else texec(t->cap,t->DL,a,a);
  1689. X a=amnt;
  1690. X cpos(t,0,bot-amnt);
  1691. X if(amnt==1 && t->al || !t->AL) while(a--) texec(t->cap,t->al,1,bot-amnt);
  1692. X else texec(t->cap,t->AL,a,a);
  1693. X goto done;
  1694. X }
  1695. msetI(t->updtab+top,1,bot-top);
  1696. return;
  1697. X
  1698. done:
  1699. mfwrd(t->scrn+top*t->co,t->scrn+(top+amnt)*t->co,
  1700. X      (bot-top-amnt)*t->co*sizeof(int));
  1701. if(bot==t->li && t->db)
  1702. X {
  1703. X msetI(t->scrn+(t->li-amnt)*t->co,-1,amnt*t->co);
  1704. X msetI(t->updtab+t->li-amnt,1,amnt);
  1705. X }
  1706. else msetI(t->scrn+(bot-amnt)*t->co,' ',amnt*t->co);
  1707. }
  1708. X
  1709. static void dodnscrl(t,top,bot,amnt)
  1710. SCRN *t;
  1711. int top,bot,amnt;
  1712. {
  1713. int a=amnt,x;
  1714. if(!amnt) return;
  1715. attr(t,0);
  1716. if(top==0 && bot==t->li && (t->sr || t->SR))
  1717. X {
  1718. X setregn(t,0,t->li);
  1719. X cpos(t,0,0);
  1720. X if(amnt==1 && t->sr || !t->SR)
  1721. X  while(a--) texec(t->cap,t->sr,1,0);
  1722. X else texec(t->cap,t->SR,a,a);
  1723. X goto done;
  1724. X }
  1725. if(bot==t->li && (t->al || t->AL))
  1726. X {
  1727. X setregn(t,0,t->li);
  1728. X cpos(t,0,top);
  1729. X if(amnt==1 && t->al || !t->AL)
  1730. X  while(a--) texec(t->cap,t->al,1,top);
  1731. X else texec(t->cap,t->AL,a,a);
  1732. X goto done;
  1733. X }
  1734. if(t->cs && (t->sr || t->SR))
  1735. X {
  1736. X setregn(t,top,bot);
  1737. X cpos(t,0,top);
  1738. X if(amnt==1 && t->sr || !t->SR)
  1739. X  while(a--) texec(t->cap,t->sr,1,top);
  1740. X else texec(t->cap,t->SR,a,a);
  1741. X goto done;
  1742. X }
  1743. if((t->dl || t->DL) && (t->al || t->AL))
  1744. X {
  1745. X cpos(t,0,bot-amnt);
  1746. X if(amnt==1 && t->dl || !t->DL)
  1747. X  while(a--) texec(t->cap,t->dl,1,bot-amnt);
  1748. X else texec(t->cap,t->DL,a,a);
  1749. X a=amnt;
  1750. X cpos(t,0,top);
  1751. X if(amnt==1 && t->al || !t->AL)
  1752. X  while(a--) texec(t->cap,t->al,1,top);
  1753. X else texec(t->cap,t->AL,a,a);
  1754. X goto done;
  1755. X }
  1756. msetI(t->updtab+top,1,bot-top);
  1757. return;
  1758. done:
  1759. mbkwd(t->scrn+(top+amnt)*t->co,t->scrn+top*t->co,
  1760. X      (bot-top-amnt)*t->co*sizeof(int));
  1761. if(!top && t->da)
  1762. X {
  1763. X msetI(t->scrn,-1,amnt*t->co);
  1764. X msetI(t->updtab,1,amnt);
  1765. X }
  1766. else msetI(t->scrn+t->co*top,' ',amnt*t->co);
  1767. }
  1768. X
  1769. void nscroll(t)
  1770. SCRN *t;
  1771. {
  1772. int y,z,q,r,p;
  1773. for(y=0;y!=t->li;++y)
  1774. X {
  1775. X q=t->sary[y];
  1776. X if(have) return;
  1777. X if(q && q!=t->li)
  1778. X  if(q>0)
  1779. X   {
  1780. X   for(z=y;z!=t->li && t->sary[z]==q;++z) t->sary[z]=0;
  1781. X   doupscrl(t,y,z+q,q), y=z-1;
  1782. X   }
  1783. X  else
  1784. X   {
  1785. X   for(r=y;r!=t->li && (t->sary[r]<0 || t->sary[r]==t->li);++r);
  1786. X   p=r-1; do
  1787. X    {
  1788. X    q=t->sary[p];
  1789. X    if(q && q!=t->li)
  1790. X     {
  1791. X     for(z=p;t->sary[z]=0, (z && t->sary[z-1]==q);--z);
  1792. X     dodnscrl(t,z+q,p+1,-q);
  1793. X     p=z+1;
  1794. X     }
  1795. X    }
  1796. X    while(p--!=y);
  1797. X   y=r-1;
  1798. X   }
  1799. X }
  1800. msetI(t->sary,0,t->li);
  1801. }
  1802. X
  1803. void nescape(t)
  1804. SCRN *t;
  1805. {
  1806. attr(t,0);
  1807. clrins(t,0);
  1808. setregn(t,0,t->li);
  1809. cpos(t,0,t->li-1);
  1810. eraeol(t,0,t->li-1);
  1811. if(t->te) texec(t->cap,t->te,1);
  1812. }
  1813. X
  1814. void nreturn(t)
  1815. SCRN *t;
  1816. {
  1817. if(t->ti) texec(t->cap,t->ti,1);
  1818. nredraw(t);
  1819. }
  1820. X
  1821. void nclose(t)
  1822. SCRN *t;
  1823. {
  1824. int x;
  1825. leave=1;
  1826. attr(t,0);
  1827. clrins(t);
  1828. setregn(t,0,t->li);
  1829. cpos(t,0,t->li-1);
  1830. if(t->te) texec(t->cap,t->te,1);
  1831. ttclose();
  1832. rmcap(t->cap);
  1833. free(t->scrn);
  1834. free(t->sary);
  1835. free(t->ofst);
  1836. free(t->htab);
  1837. free(t->ary);
  1838. for(x=0;x!=t->tabsize;++x) vsrm(t->ktab[x].s);
  1839. free(t);
  1840. }
  1841. X
  1842. int ngetc(t)
  1843. SCRN *t;
  1844. {
  1845. int c,w,h,x;
  1846. wayup:
  1847. if(t->dumpptr>=0)
  1848. X {
  1849. X c=t->kbuf[t->dumpptr++];
  1850. X if(t->dumpptr==t->kbufp)
  1851. X  {
  1852. X  t->dumpptr= -1;
  1853. X  t->kbufp=0;
  1854. X  }
  1855. X return c;
  1856. X }
  1857. up:
  1858. c=ttgetc();
  1859. if(t->kbufp==32) t->kbufp=0;
  1860. t->kbuf[t->kbufp++]=c;
  1861. w=0;
  1862. for(h=0;h!=t->tabsize;++h)
  1863. X {
  1864. X for(x=0;x!=t->kbufp && x!=t->ktab[h].l;++x)
  1865. X  if(t->ktab[h].s[x]!=t->kbuf[x]) goto nomatch;
  1866. X if(x==t->ktab[h].l)
  1867. X  {
  1868. X  c=t->ktab[h].n;
  1869. X  goto found;
  1870. X  }
  1871. X else if(x==t->kbufp) w=1;
  1872. X nomatch:;
  1873. X }
  1874. if(w) goto up;
  1875. /* Have to dump each char */
  1876. t->dumpptr=0;
  1877. goto wayup;
  1878. found:
  1879. t->kbufp=0;
  1880. X
  1881. return c;
  1882. }
  1883. X
  1884. void nscrldn(t,top,bot,amnt)
  1885. SCRN *t;
  1886. int top,bot,amnt;
  1887. {
  1888. int x;
  1889. if(!amnt || top>=bot || bot>t->li) return;
  1890. if(amnt<bot-top && bot-top-amnt<amnt/2 || !t->scroll) amnt=bot-top;
  1891. if(amnt<bot-top)
  1892. X {
  1893. X for(x=bot;x!=top+amnt;--x)
  1894. X  t->sary[x-1]=(t->sary[x-amnt-1]==t->li?t->li:t->sary[x-amnt-1]-amnt),
  1895. X  t->updtab[x-1]=t->updtab[x-amnt-1];
  1896. X for(x=top;x!=top+amnt;++x) t->updtab[x]=0;
  1897. X }
  1898. if(amnt>bot-top) amnt=bot-top;
  1899. msetI(t->sary+top,t->li,amnt);
  1900. if(amnt==bot-top) msetI(t->updtab+top,1,amnt);
  1901. }
  1902. X
  1903. void nscrlup(t,top,bot,amnt)
  1904. SCRN *t;
  1905. int top,bot,amnt;
  1906. {
  1907. int x;
  1908. if(!amnt || top>=bot || bot>t->li) return;
  1909. if(amnt<bot-top && bot-top-amnt<amnt/2 || !t->scroll) amnt=bot-top;
  1910. if(amnt<bot-top)
  1911. X {
  1912. X for(x=top+amnt;x!=bot;++x)
  1913. X  t->sary[x-amnt]=(t->sary[x]==t->li?t->li:t->sary[x]+amnt),
  1914. X  t->updtab[x-amnt]=t->updtab[x];
  1915. X for(x=bot-amnt;x!=bot;++x) t->updtab[x]=0;
  1916. X }
  1917. if(amnt>bot-top) amnt=bot-top;
  1918. msetI(t->sary+bot-amnt,t->li,amnt);
  1919. if(amnt==bot-top) msetI(t->updtab+bot-amnt,1,amnt);
  1920. }
  1921. X
  1922. void nredraw(t)
  1923. SCRN *t;
  1924. {
  1925. msetI(t->scrn,-1,t->li*t->co);
  1926. msetI(t->sary,0,t->li);
  1927. msetI(t->updtab,-1,t->li);
  1928. t->x= -1;
  1929. t->y= -1;
  1930. t->top=t->li;
  1931. t->bot=0;
  1932. t->attrib= -1;
  1933. t->ins= -1;
  1934. attr(t,0);
  1935. clrins(t);
  1936. setregn(t);
  1937. if(t->cl)
  1938. X {
  1939. X texec(t->cap,t->cl,1,0);
  1940. X t->x=0; t->y=0;
  1941. X msetI(t->scrn,' ',t->li*t->co);
  1942. X }
  1943. else if(t->cd)
  1944. X {
  1945. X cpos(t,0,0);
  1946. X texec(t->cap,t->cd,1,0);
  1947. X msetI(t->scrn,' ',t->li*t->co);
  1948. X }
  1949. }
  1950. SHAR_EOF
  1951. chmod 0600 scrn.c ||
  1952. echo 'restore of scrn.c failed'
  1953. Wc_c="`wc -c < 'scrn.c'`"
  1954. test 26464 -eq "$Wc_c" ||
  1955.     echo 'scrn.c: original size 26464, current size' "$Wc_c"
  1956. fi
  1957. # ============= scrn.h ==============
  1958. if test -f 'scrn.h' -a X"$1" != X"-c"; then
  1959.     echo 'x - skipping scrn.h (File already exists)'
  1960. else
  1961. echo 'x - extracting scrn.h (Text)'
  1962. sed 's/^X//' << 'SHAR_EOF' > 'scrn.h' &&
  1963. /* Device independant tty interface for JOE
  1964. X   Copyright (C) 1992 Joseph H. Allen
  1965. X
  1966. This file is part of JOE (Joe's Own Editor)
  1967. X
  1968. JOE is free software; you can redistribute it and/or modify it under the 
  1969. terms of the GNU General Public License as published by the Free Software 
  1970. Foundation; either version 1, or (at your option) any later version.  
  1971. X
  1972. JOE is distributed in the hope that it will be useful, but WITHOUT ANY 
  1973. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  1974. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  1975. details.  
  1976. X
  1977. You should have received a copy of the GNU General Public License along with 
  1978. JOE; see the file COPYING.  If not, write to the Free Software Foundation, 
  1979. 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
  1980. X
  1981. #ifndef _Iscrn
  1982. #define _Iscrn 1
  1983. X
  1984. #include "config.h"
  1985. #include "termcap.h"
  1986. #include "tty.h"
  1987. X
  1988. typedef struct seq SEQ;
  1989. typedef struct scrn SCRN;
  1990. X
  1991. /* Number of key sequence translation entries */
  1992. X
  1993. #define NKEYS 20
  1994. X
  1995. /* Sepecial key sequence structure */
  1996. X
  1997. struct seq
  1998. X {
  1999. X char *seq;
  2000. X int code;
  2001. X char *name;
  2002. X };
  2003. X
  2004. extern SEQ seqs[];
  2005. X
  2006. struct hentry
  2007. X {
  2008. X int next;
  2009. X int loc;
  2010. X };
  2011. X
  2012. /* Each terminal has one of these */
  2013. X
  2014. struct scrn
  2015. X {
  2016. X CAP *cap;        /* Termcap/Terminfo data */
  2017. X
  2018. X int li;            /* Screen height */
  2019. X int co;            /* Screen width */
  2020. X
  2021. X char *ti;            /* Initialization string */
  2022. X char *cl;            /* Home and clear screen... really an
  2023. X                    init. string */
  2024. X char *cd;            /* Clear to end of screen */
  2025. X char *te;            /* Restoration string */
  2026. X
  2027. X int hz;            /* Terminal can't print ~s */
  2028. X int os;            /* Terminal overstrikes */
  2029. X int eo;            /* Can use blank to erase even if os */
  2030. X int ul;            /* _ overstrikes */
  2031. X int am;            /* Terminal has autowrap, but not magicwrap */
  2032. X int xn;            /* Terminal has magicwrap */
  2033. X
  2034. X char *so;            /* Enter standout (inverse) mode */
  2035. X char *se;            /* Exit standout mode */
  2036. X
  2037. X char *us;            /* Enter underline mode */
  2038. X char *ue;            /* Exit underline mode */
  2039. X char *uc;            /* Single time underline character */
  2040. X
  2041. X int ms;            /* Ok to move when in standout/underline mode */
  2042. X
  2043. X char *mb;            /* Enter blinking mode */
  2044. X char *md;            /* Enter bold mode */
  2045. X char *mh;            /* Enter dim mode */
  2046. X char *mr;            /* Enter inverse mode */
  2047. X char *me;            /* Exit above modes */
  2048. X
  2049. X int da, db;            /* Extra lines exist above, below */
  2050. X char *al, *dl, *AL, *DL;    /* Insert/delete lines */
  2051. X char *cs;            /* Set scrolling region */
  2052. X int rr;            /* Set for scrolling region relative addressing */
  2053. X char *sf, *SF, *sr, *SR;    /* Scroll */
  2054. X
  2055. X char *dm, *dc, *DC, *ed;    /* Delete characters */
  2056. X char *im, *ic, *IC, *ip, *ei;    /* Insert characters */
  2057. X int mi;            /* Set if ok to move while in insert mode */
  2058. X
  2059. X char *bs;            /* Move cursor left 1 */
  2060. X int cbs;
  2061. X char *lf;            /* Move cursor down 1 */
  2062. X int clf;
  2063. X char *up;            /* Move cursor up 1 */
  2064. X int cup;
  2065. X char *nd;            /* Move cursor right 1 */
  2066. X
  2067. X char *ta;            /* Move cursor to next tab stop */
  2068. X int cta;
  2069. X char *bt;            /* Move cursor to previous tab stop */
  2070. X int cbt;
  2071. X int tw;            /* Tab width */
  2072. X
  2073. X char *ho;            /* Home cursor to upper left */
  2074. X int cho;
  2075. X char *ll;            /* Home cursor to lower left */
  2076. X int cll;
  2077. X char *cr;            /* Move cursor to left edge */
  2078. X int ccr;
  2079. X char *RI;            /* Move cursor right n */
  2080. X int cRI;
  2081. X char *LE;            /* Move cursor left n */
  2082. X int cLE;
  2083. X char *UP;            /* Move cursor up n */
  2084. X int cUP;
  2085. X char *DO;            /* Move cursor down n */
  2086. X int cDO;
  2087. X char *ch;            /* Set cursor column */
  2088. X int cch;
  2089. X char *cv;            /* Set cursor row */
  2090. X int ccv;
  2091. X char *cb;            /* Goto beginning of specified line */
  2092. X int ccb;
  2093. X char *cm;            /* Set cursor row and column */
  2094. X int ccm;
  2095. X
  2096. X char *ce;            /* Clear to end of line */
  2097. X int cce;
  2098. X
  2099. X /* Basic abilities */
  2100. X int scroll;            /* Set to use scrolling */
  2101. X int insdel;            /* Set to use insert/delete within line */
  2102. X
  2103. X /* Key-sequence translation table */
  2104. X
  2105. X struct
  2106. X  {
  2107. X  char *s;            /* Key sequence string */
  2108. X  int l;            /* Key sequence string length */
  2109. X  int n;            /* Value which should be returned for this string */
  2110. X  } ktab[NKEYS];
  2111. X
  2112. X int tabsize;            /* Number of entries in translation table */
  2113. X
  2114. X /* Input buffer for translations */
  2115. X
  2116. X char kbuf[32];            /* Keyboard buffer */
  2117. X int kbufp;            /* Keyboard buffer index */
  2118. X int dumpptr;            /* When we pass unmatched chars */
  2119. X
  2120. X /* Current state of terminal */
  2121. X int *scrn;            /* Current contents of screen */
  2122. X int x,y;            /* Current cursor position (-1 for unknown) */
  2123. X int top,bot;            /* Current scrolling region */
  2124. X int attrib;            /* Current character attributes */
  2125. X int ins;            /* Set if we're in insert mode */
  2126. X
  2127. X int *updtab;            /* Dirty lines table */
  2128. X int avattr;            /* Bits set for available attributes */
  2129. X int *sary;            /* Scroll buffer array */
  2130. X
  2131. X int *compose;            /* Line compose buffer */
  2132. X int *ofst;            /* stuff for magic */
  2133. X struct hentry *htab;
  2134. X struct hentry *ary;
  2135. X };
  2136. X
  2137. /* SCRN *nopen(void);
  2138. X *
  2139. X * Open the screen (sets TTY mode so that screen may be used immediatly after
  2140. X * the 'nopen').
  2141. X */
  2142. SCRN *nopen();
  2143. X
  2144. /* void nresize(SCRN *t,int w,int h);
  2145. X *
  2146. X * Change size of screen.  For example, call this when you find out that
  2147. X * the Xterm changed size.
  2148. X */
  2149. void nresize();
  2150. X
  2151. /* void nredraw(SCRN *t);
  2152. X *
  2153. X * Invalidate all state variables for the terminal.  This way, everything gets
  2154. X * redrawn.
  2155. X */
  2156. void nredraw();
  2157. X
  2158. void nescape();
  2159. void nreturn();
  2160. X
  2161. /* void nclose(SCRN *t);
  2162. X *
  2163. X * Close the screen and restore TTY to initial state.
  2164. X *
  2165. X * if 'flg' is set, tclose doesn't mess with the signals.
  2166. X */
  2167. void nclose();
  2168. X
  2169. /* int ngetc(SCRN *t);
  2170. X *
  2171. X * Get next input character.  Arrow keys are translated into the integer codes
  2172. X * shown below.
  2173. X */
  2174. int ngetc();
  2175. X
  2176. #define KEYUP 256    /* Arrow keys */            /* ku */
  2177. #define KEYDOWN 257                        /* kd */
  2178. #define KEYLEFT 258                        /* kl */
  2179. #define KEYRIGHT 259                        /* kr */
  2180. #define KEYF0 260    /* Function keys (is F0 really F10?) */ /* k0 */
  2181. #define KEYF1 261                        /* k1 */
  2182. #define KEYF2 262
  2183. #define KEYF3 263
  2184. #define KEYF4 270
  2185. #define KEYF5 265
  2186. #define KEYF6 266
  2187. #define KEYF7 267
  2188. #define KEYF8 268
  2189. #define KEYF9 269                        /* k9 */
  2190. #define KEYDEL 383    /* Delete character */            /* kD */
  2191. #define KEYINS 271    /* Insert character */            /* kI */
  2192. #define KEYHOME 272    /* Home key */                /* kh */
  2193. #define KEYEND 273    /* End key */                /* kH */
  2194. #define KEYPGDN 274    /* Page down key */            /* kN */
  2195. #define KEYPGUP 275    /* Page up key */            /* kP */
  2196. #define KEYBACKS 264    /* Backspace key */            /* kb */
  2197. X
  2198. /* void cpos(SCRN *t,int x,int y);
  2199. X *
  2200. X * Set cursor position
  2201. X */
  2202. void cpos();
  2203. X
  2204. /* void attr(SCRN *t,int a);
  2205. X *
  2206. X * Set attributes
  2207. X */
  2208. void attr();
  2209. X
  2210. /* void outatr(SCRN *t,int x,int y,int c);
  2211. X *
  2212. X * Output a character at the given screen cooridinate.  The cursor position
  2213. X * after this function is executed is indeterminate.
  2214. X */
  2215. void outatr();
  2216. X
  2217. /* Character attribute bits */
  2218. X
  2219. #define INVERSE 256
  2220. #define UNDERLINE 512
  2221. #define BOLD 1024
  2222. #define BLINK 2048
  2223. #define DIM 4096
  2224. X
  2225. /* int eraeol(SCRN *t,int x,int y);
  2226. X *
  2227. X * Erase from screen coordinate to end of line.
  2228. X */
  2229. int eraeol();
  2230. X
  2231. /* void nscrlup(SCRN *t,int top,int bot,int amnt);
  2232. X *
  2233. X * Buffered scroll request.  Request that some lines up.  'top' and 'bot'
  2234. X * indicate which lines to scroll.  'bot' is the last line to scroll + 1.
  2235. X * 'amnt' is distance in lines to scroll.
  2236. X */
  2237. void nscrlup();
  2238. X
  2239. /* void nscrldn(SCRN *t,int top,int bot,int amnt);
  2240. X *
  2241. X * Buffered scroll request.  Scroll some lines down.  'top' and 'bot'
  2242. X * indicate which lines to scroll.  'bot' is the last line to scroll + 1.
  2243. X * 'amnt' is distance in lines to scroll.
  2244. X */
  2245. void nscrldn();
  2246. X
  2247. /* void nscroll(SCRN *t);
  2248. X *
  2249. X * Execute buffered scroll requests
  2250. X */
  2251. void nscroll();
  2252. X
  2253. /* void magic(SCRN *t,int y,int *cur,int *new);
  2254. X *
  2255. X * Figure out and execute line shifting
  2256. X */
  2257. void magic();
  2258. X
  2259. #endif
  2260. SHAR_EOF
  2261. chmod 0600 scrn.h ||
  2262. echo 'restore of scrn.h failed'
  2263. Wc_c="`wc -c < 'scrn.h'`"
  2264. test 7538 -eq "$Wc_c" ||
  2265.     echo 'scrn.h: original size 7538, current size' "$Wc_c"
  2266. fi
  2267. # ============= tab.c ==============
  2268. if test -f 'tab.c' -a X"$1" != X"-c"; then
  2269.     echo 'x - skipping tab.c (File already exists)'
  2270. else
  2271. echo 'x - extracting tab.c (Text)'
  2272. sed 's/^X//' << 'SHAR_EOF' > 'tab.c' &&
  2273. /* File selection menu
  2274. X   Copyright (C) 1992 Joseph H. Allen
  2275. X
  2276. This file is part of JOE (Joe's Own Editor)
  2277. X
  2278. JOE is free software; you can redistribute it and/or modify it under the 
  2279. terms of the GNU General Public License as published by the Free Software 
  2280. Foundation; either version 1, or (at your option) any later version.  
  2281. X
  2282. JOE is distributed in the hope that it will be useful, but WITHOUT ANY 
  2283. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  2284. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  2285. details.  
  2286. X
  2287. You should have received a copy of the GNU General Public License along with 
  2288. JOE; see the file COPYING.  If not, write to the Free Software Foundation, 
  2289. 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
  2290. X
  2291. #include <stdio.h>
  2292. #include <sys/types.h>
  2293. #include <sys/stat.h>
  2294. #include "config.h"
  2295. #include "heap.h"
  2296. #include "scrn.h"
  2297. #include "kbd.h"
  2298. #include "vs.h"
  2299. #include "w.h"
  2300. #include "bw.h"
  2301. #include "zstr.h"
  2302. #include "pathfunc.h"
  2303. #include "va.h"
  2304. #include "menu.h"
  2305. #include "edfuncs.h"
  2306. #include "tty.h"
  2307. #include "tab.h"
  2308.