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

  1. Newsgroups: alt.sources
  2. Path: sparky!uunet!paladin.american.edu!darwin.sura.net!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 3 of 10
  5. Message-ID: <By2MHK.Ku0@world.std.com>
  6. Organization: The World Public Access UNIX, Brookline, MA
  7. Date: Sat, 21 Nov 1992 14:48:55 GMT
  8. Lines: 2303
  9.  
  10. Submitted-by: jhallen@world.std.com
  11. Archive-name: joe1.0.5part3
  12.  
  13. BW *bw=(BW *)w->object;
  14. pdupown(bw->cursor,&w->t->markb);
  15. updall();
  16. }
  17. X
  18. void umarkk(w)
  19. W *w;
  20. {
  21. BW *bw=(BW *)w->object;
  22. pdupown(bw->cursor,&w->t->markk);
  23. updall();
  24. }
  25. X
  26. void ublkdel(w)
  27. W *w;
  28. {
  29. BW *bw=(BW *)w->object;
  30. if(w->t->markb && w->t->markk &&
  31. X   w->t->markb->b==w->t->markk->b &&
  32. X   w->t->markk->byte>w->t->markb->byte &&
  33. X   (!square || w->t->markb->col<w->t->markk->col))
  34. X if(square)
  35. X  {
  36. X  pdelrect(w->t->markb,w->t->markk,w->t->markb->col,w->t->markk->col,
  37. X           bw->overtype);
  38. X  return;
  39. X  }
  40. X else
  41. X  {
  42. X  bdel(w->t->markb,w->t->markk);
  43. X  prm(w->t->markb);
  44. X  prm(w->t->markk);
  45. X  return;
  46. X  }
  47. msgnw(w,"No block");
  48. }
  49. X
  50. void ublkmove(w)
  51. W *w;
  52. {
  53. BW *bw=(BW *)w->object;
  54. long size;
  55. if(w->t->markb && w->t->markk && w->t->markb->b==w->t->markk->b &&
  56. X   (size=w->t->markk->byte-w->t->markb->byte)>0 &&
  57. X   (!square || w->t->markb->col<w->t->markk->col))
  58. X if(square)
  59. X  {
  60. X  long height=w->t->markk->line-w->t->markb->line;
  61. X  long width;
  62. X  long ocol=bw->cursor->col;
  63. X  B *tmp=pextrect(w->t->markb,w->t->markk,w->t->markb->col,w->t->markk->col);
  64. X  pdelrect(w->t->markb,w->t->markk,w->t->markb->col,w->t->markk->col,
  65. X           bw->overtype);
  66. X  if(bw->overtype)
  67. X   {
  68. X   while(bw->cursor->col<ocol)
  69. X    if(brc(bw->cursor)==' ') pgetc(bw->cursor);
  70. X    else if(bw->cursor->col+bw->b->tab-bw->cursor->col%bw->b->tab<=
  71. X            bw->cursor->col) pgetc(bw->cursor);
  72. X    else binsc(bw->cursor,' '), pgetc(bw->cursor);
  73. X   width=povrrect(bw->cursor,tmp);
  74. X   }
  75. X  else width=pinsrect(bw->cursor,tmp);
  76. X  brm(tmp);
  77. X  while(bw->cursor->col<ocol) pgetc(bw->cursor);
  78. X  umarkb(w);
  79. X  umarkk(w);
  80. X  pline(w->t->markk,w->t->markk->line+height);
  81. X  pcol(w->t->markk,w->t->markb->col+width);
  82. X  return;
  83. X  }
  84. X else if(bw->cursor->b!=w->t->markk->b ||
  85. X         bw->cursor->byte>w->t->markk->byte ||
  86. X         bw->cursor->byte<w->t->markb->byte)
  87. X  {
  88. X  binsb(bw->cursor,w->t->markb,w->t->markk);
  89. X  ublkdel(w);
  90. X  umarkb(w);
  91. X  umarkk(w);
  92. X  pfwrd(w->t->markk,size);
  93. X  updall();
  94. X  return;
  95. X  }
  96. msgnw(w,"No block");
  97. }
  98. X
  99. void ublkcpy(w)
  100. W *w;
  101. {
  102. BW *bw=(BW *)w->object;
  103. long size;
  104. if(w->t->markb && w->t->markk && w->t->markb->b==w->t->markk->b &&
  105. X   (size=w->t->markk->byte-w->t->markb->byte)>0 &&
  106. X   (!square || w->t->markb->col < w->t->markk->col))
  107. X if(square)
  108. X  {
  109. X  B *tmp=pextrect(w->t->markb,w->t->markk,w->t->markb->col,w->t->markk->col);
  110. X  long width;
  111. X  long height;
  112. X  if(bw->overtype) width=povrrect(bw->cursor,tmp);
  113. X  else width=pinsrect(bw->cursor,tmp);
  114. X  height=w->t->markk->line-w->t->markb->line;
  115. X  brm(tmp);
  116. X  umarkb(w);
  117. X  umarkk(w);
  118. X  pline(w->t->markk,w->t->markk->line+height);
  119. X  pcol(w->t->markk,w->t->markb->col+width);
  120. X  return;
  121. X  }
  122. X else
  123. X  {
  124. X  binsb(bw->cursor,w->t->markb,w->t->markk);
  125. X  umarkb(w);
  126. X  umarkk(w);
  127. X  pfwrd(w->t->markk,size);
  128. X  updall();
  129. X  return;
  130. X  }
  131. msgnw(w,"No block");
  132. }
  133. X
  134. void ushell(w)
  135. W *w;
  136. {
  137. nescape(w->t->t);
  138. ttsusp();
  139. nreturn(w->t->t);
  140. }
  141. X
  142. void dowrite(w,s)
  143. W *w;
  144. char *s;
  145. {
  146. long size;
  147. int fl;
  148. if(w->t->markb && w->t->markk && w->t->markb->b==w->t->markk->b &&
  149. X   (size=w->t->markk->byte-w->t->markb->byte)>0 &&
  150. X   (!square || w->t->markk->col>w->t->markb->col))
  151. X {
  152. X if(square)
  153. X  {
  154. X  B *tmp=pextrect(w->t->markb,w->t->markk,w->t->markb->col,w->t->markk->col);
  155. X  if(fl=bsave(tmp->bof,s,tmp->eof->byte)) msgnw(w,msgs[5+fl]);
  156. X  brm(tmp);
  157. X  }
  158. X else if(fl=bsave(w->t->markb,s,size)) msgnw(w,msgs[5+fl]);
  159. X }
  160. else msgnw(w,"No block");
  161. vsrm(s);
  162. }
  163. X
  164. void ublksave(w)
  165. W *w;
  166. {
  167. BW *bw=(BW *)w->object;
  168. if(w->t->markb && w->t->markk && w->t->markb->b==w->t->markk->b &&
  169. X   (w->t->markk->byte-w->t->markb->byte)>0 &&
  170. X   (!square || w->t->markk->col>w->t->markb->col))
  171. X {
  172. X wmkfpw(w,"Name of file to write (^C to abort): ",&filehist,dowrite,"Names");
  173. X return;
  174. X }
  175. msgnw(w,"No block");
  176. }
  177. X
  178. long pindent();
  179. X
  180. void setindent(w)
  181. W *w;
  182. {
  183. BW *bw=(BW *)w->object;
  184. P *p, *q;
  185. long indent;
  186. if(pblank(bw->cursor)) return;
  187. X
  188. p=pdup(bw->cursor);
  189. q=pdup(p);
  190. indent=pindent(p);
  191. X
  192. do
  193. X if(!pprevl(p)) goto done;
  194. X else pboln(p);
  195. X while(pindent(p)>=indent && !pblank(p));
  196. pnextl(p);
  197. done:
  198. pboln(p);
  199. if(w->t->markb) prm(w->t->markb);
  200. w->t->markb=p; p->owner=&w->t->markb;
  201. X
  202. do
  203. X if(!pnextl(q)) break;
  204. X while(pindent(q)>=indent && !pblank(q));
  205. pfcol(q);
  206. X
  207. if(w->t->markk) prm(w->t->markk);
  208. w->t->markk=q; q->owner=&w->t->markk;
  209. X
  210. updall();
  211. }
  212. X
  213. void urindent(w)
  214. W *w;
  215. {
  216. BW *bw=(BW *)w->object;
  217. if(square)
  218. X {
  219. X if(w->t->markb && w->t->markk && w->t->markb->b==w->t->markk->b &&
  220. X    w->t->markb->byte<=w->t->markk->byte && w->t->markb->col<=w->t->markk->col)
  221. X  {
  222. X  P *p=pdup(w->t->markb);
  223. X  do
  224. X   {
  225. X   pcol(p,w->t->markb->col);
  226. X   pfill(p,w->t->markb->col+bw->istep,bw->indentc=='\t'?1:0);
  227. X   } while(pnextl(p) && p->line<=w->t->markk->line);
  228. X  prm(p);
  229. X  }
  230. X return;
  231. X }
  232. if(!w->t->markb || !w->t->markk || w->t->markb->b!=w->t->markk->b ||
  233. X   bw->cursor->byte<w->t->markb->byte || bw->cursor->byte>w->t->markk->byte)
  234. X {
  235. X setindent(w);
  236. X }
  237. else
  238. X {
  239. X P *p=pdup(w->t->markb);
  240. X while(p->byte<w->t->markk->byte)
  241. X  {
  242. X  pbol(p);
  243. X  while(p->col<bw->istep) binsc(p,bw->indentc), pgetc(p);
  244. X  pnextl(p);
  245. X  }
  246. X prm(p);
  247. X }
  248. }
  249. X
  250. void ulindent(w)
  251. W *w;
  252. {
  253. BW *bw=(BW *)w->object;
  254. if(square)
  255. X {
  256. X if(w->t->markb && w->t->markk && w->t->markb->b==w->t->markk->b &&
  257. X    w->t->markb->byte<=w->t->markk->byte && w->t->markb->col<=w->t->markk->col)
  258. X  {
  259. X  P *p=pdup(w->t->markb);
  260. X  P *q=pdup(p);
  261. X  do
  262. X   {
  263. X   pcol(p,w->t->markb->col);
  264. X   while(p->col<w->t->markb->col+bw->istep)
  265. X    {
  266. X    int c=pgetc(p);
  267. X    if(c!=' ' && c!='\t' && c!=bw->indentc)
  268. X     {
  269. X     prm(p);
  270. X     prm(q);
  271. X     return;
  272. X     }
  273. X    }
  274. X   } while(pnextl(p) && p->line<=w->t->markk->line);
  275. X  pset(p,w->t->markb);
  276. X  do
  277. X   {
  278. X   pcol(p,w->t->markb->col);
  279. X   pset(q,p);
  280. X   pcol(q,w->t->markb->col+bw->istep);
  281. X   bdel(p,q);
  282. X   } while(pnextl(p) && p->line<=w->t->markk->line);
  283. X  prm(p); prm(q);
  284. X  }
  285. X return;
  286. X }
  287. if(!w->t->markb || !w->t->markk || w->t->markb->b!=w->t->markk->b ||
  288. X   bw->cursor->byte<w->t->markb->byte || bw->cursor->byte>w->t->markk->byte)
  289. X {
  290. X setindent(w);
  291. X }
  292. else
  293. X {
  294. X P *p=pdup(w->t->markb);
  295. X P *q=pdup(p);
  296. X pbol(p);
  297. X while(p->byte<w->t->markk->byte)
  298. X  {
  299. X  if(pindent(p)<bw->istep) { prm(p); return; }
  300. X  pnextl(p);
  301. X  }
  302. X pset(p,w->t->markb);
  303. X pbol(p);
  304. X while(p->byte<w->t->markk->byte)
  305. X  {
  306. X  pset(q,p);
  307. X  while(q->col<bw->istep) pgetc(q);
  308. X  bdel(p,q);
  309. X  pnextl(p);
  310. X  }
  311. X prm(p); prm(q);
  312. X }
  313. }
  314. X
  315. static void dofilt(w,s)
  316. W *w;
  317. char *s;
  318. {
  319. BW *bw=(BW *)w->object;
  320. int fr[2];
  321. int fw[2];
  322. char c;
  323. X
  324. if(w->t->markb && w->t->markk && w->t->markb->b==w->t->markk->b &&
  325. X   w->t->markk->byte>w->t->markb->byte &&
  326. X   (!square || w->t->markk->col>w->t->markb->col)) goto go;
  327. msgnw(w,"No block");
  328. return;
  329. X
  330. go:
  331. X
  332. pipe(fr);
  333. pipe(fw);
  334. nescape(w->t->t);
  335. ttclsn();
  336. if(!fork())
  337. X {
  338. X signrm();
  339. X close(0);
  340. X close(1);
  341. X dup(fw[0]);
  342. X dup(fr[1]);
  343. X close(fw[0]);
  344. X close(fr[1]);
  345. X close(fw[1]);
  346. X close(fr[0]);
  347. X execl("/bin/sh","/bin/sh","-c",s,NULL);
  348. X _exit(0);
  349. X }
  350. close(fr[1]);
  351. close(fw[0]);
  352. if(fork())
  353. X {
  354. X long szz;
  355. X close(fw[1]);
  356. X if(square)
  357. X  {
  358. X  B *tmp=bmk();
  359. X  long width;
  360. X  long height;
  361. X  pdelrect(w->t->markb,w->t->markk,w->t->markb->col,w->t->markk->col,
  362. X           bw->overtype);
  363. X  binsfd(tmp->bof,fr[0],MAXLONG);
  364. X  if(bw->overtype) width=povrrect(w->t->markb,tmp);
  365. X  else width=pinsrect(w->t->markb,tmp);
  366. X  if(tmp->eof->col || !tmp->eof->line) height=tmp->eof->line;
  367. X  else height=tmp->eof->line-1;
  368. X  pdupown(w->t->markb,&w->t->markk);
  369. X  pline(w->t->markk,w->t->markk->line+height);
  370. X  pcol(w->t->markk,w->t->markb->col+width);
  371. X  brm(tmp);
  372. X  updall();
  373. X  }
  374. X else
  375. X  {
  376. X  bdel(w->t->markb,w->t->markk);
  377. X  szz=w->t->markk->b->eof->byte;
  378. X  binsfd(w->t->markk,fr[0],MAXLONG);
  379. X  pfwrd(w->t->markk,w->t->markk->b->eof->byte-szz);
  380. X  }
  381. X close(fr[0]);
  382. X wait(0);
  383. X wait(0);
  384. X }
  385. else
  386. X {
  387. X if(square)
  388. X  {
  389. X  B *tmp=pextrect(w->t->markb,w->t->markk,w->t->markb->col,w->t->markk->col);
  390. X  bsavefd(tmp->bof,fw[1],tmp->eof->byte);
  391. X  }
  392. X else bsavefd(w->t->markb,fw[1],w->t->markk->byte-w->t->markb->byte);
  393. X close(fw[1]);
  394. X _exit(0);
  395. X }
  396. vsrm(s);
  397. ttopnn();
  398. nreturn(w->t->t);
  399. bw->cursor->xcol=bw->cursor->col;
  400. }
  401. X
  402. void ufilt(w)
  403. W *w;
  404. {
  405. BW *bw=(BW *)w->object;
  406. if(w->t->markb && w->t->markk && w->t->markb->b==w->t->markk->b &&
  407. X   (w->t->markk->byte-w->t->markb->byte)>0)
  408. X {
  409. X wmkpw(w,"Command to filter block through (^C to abort): ",
  410. X       &filthist,dofilt,NULL);
  411. X return;
  412. X }
  413. msgnw(w,"No block");
  414. }
  415. X
  416. /****************************/
  417. /* File loading and storing */
  418. /****************************/
  419. X
  420. static int backup(w)
  421. W *w;
  422. {
  423. BW *bw=(BW *)w->object;
  424. if(!bw->b->backup)
  425. X {
  426. X char *s=0;
  427. X /* Create command string */
  428. X s=vsncpy(s,0,sc("/bin/cp "));
  429. X s=vsncpy(s,sLEN(s),sz(bw->b->name));
  430. X s=vsadd(s,' ');
  431. X s=vsncpy(s,sLEN(s),sz(bw->b->name));
  432. X s=vsncpy(s,sLEN(s),sc("~ 2>/dev/null"));
  433. X
  434. X if(system(s))
  435. X  {
  436. X  msgnw(w,"Couldn't make backup file... file not saved");
  437. X  vsrm(s);
  438. X  return 1;
  439. X  }
  440. X else
  441. X  {
  442. X  bw->b->backup=1;
  443. X  vsrm(s);
  444. X  return 0;
  445. X  }
  446. X }
  447. else return 0;
  448. }
  449. X
  450. static int dosave(w,s)
  451. W *w;
  452. char *s;
  453. {
  454. BW *bw=(BW *)w->object;
  455. FILE *f;
  456. int fl;
  457. if(backup(w)) { vsrm(s); return 1; }
  458. if(fl=bsave(bw->b->bof,s,bw->b->eof->byte))
  459. X {
  460. X msgnw(w,msgs[fl+5]);
  461. X vsrm(s);
  462. X return 1;
  463. X }
  464. else
  465. X {
  466. X if(!bw->b->name) bw->b->name=zdup(s);
  467. X if(!zcmp(bw->b->name,s)) bw->b->chnged=0;
  468. X vsrm(s);
  469. X return 0;
  470. X }
  471. }
  472. X
  473. void usave(w)
  474. W *w;
  475. {
  476. BW *bw=(BW *)w->object;
  477. W *pw=wmkfpw(w,"Name of file to save (^C to abort): ",&filehist,dosave,"Names");
  478. if(pw && bw->b->name)
  479. X {
  480. X BW *pbw=(BW *)pw->object;
  481. X binss(pbw->cursor,bw->b->name);
  482. X pset(pbw->cursor,pbw->b->eof); pbw->cursor->xcol=pbw->cursor->col;
  483. X }
  484. }
  485. X
  486. static void doedit(w,s)
  487. W *w;
  488. char *s;
  489. {
  490. BW *bw=(BW *)w->object;
  491. void *object=bw->object;
  492. B *b=bfind(s);
  493. if(!b)
  494. X {
  495. X b=bmk();
  496. X if(!zlen(s))
  497. X  msgnwt(w,"New file ");
  498. X else
  499. X  {
  500. X  int fl;
  501. X  if(fl=bload(b,s)) msgnwt(w,msgs[fl+5]);
  502. X  }
  503. X }
  504. bwrm(bw);
  505. w->object=(void *)(bw=bwmk(w->t,b,w->x,w->y+1,w->w,w->h-1));
  506. wredraw(w);
  507. setoptions(bw,s);
  508. bw->object=object;
  509. vsrm(s);
  510. }
  511. X
  512. void uedit(w)
  513. W *w;
  514. {
  515. BW *bw=(BW *)w->object;
  516. if(bw->b->count==1 && bw->b->chnged)
  517. X {
  518. X int c=query(w,"Do you really want to throw away this file (y,n)? ");
  519. X if(c!='y' && c!='Y') return;
  520. X }
  521. wmkfpw(w,"Name of file to edit (^C to abort): ",&filehist,doedit,"Names");
  522. }
  523. X
  524. static void doinsf(w,s)
  525. W *w;
  526. char *s;
  527. {
  528. BW *bw=(BW *)w->object;
  529. int fl;
  530. if(square)
  531. X {
  532. X B *tmp=bmk();
  533. X if(fl=binsf(tmp->bof,s)) msgnw(w,msgs[fl+5]);
  534. X else
  535. X  if(bw->overtype) povrrect(bw->cursor,tmp);
  536. X  else pinsrect(bw->cursor,tmp);
  537. X brm(tmp);
  538. X }
  539. else
  540. X if(fl=binsf(bw->cursor,s)) msgnw(w,msgs[fl+5]);
  541. vsrm(s);
  542. bw->cursor->xcol=bw->cursor->col;
  543. }
  544. X
  545. void uinsf(w)
  546. W *w;
  547. {
  548. BW *bw=(BW *)w->object;
  549. wmkfpw(w,"Name of file to insert (^C to abort): ",&filehist,doinsf,"Names");
  550. }
  551. X
  552. extern char *exmsg;
  553. X
  554. static void doex(w,s)
  555. W *w;
  556. char *s;
  557. {
  558. BW *bw=(BW *)w->object;
  559. bw->b->name=zdup(s); 
  560. if(dosave(w,s)) { free(bw->b->name); bw->b->name=0; return; }
  561. exmsg=vsncpy(NULL,0,sc("File "));
  562. exmsg=vsncpy(exmsg,sLEN(exmsg),sz(bw->b->name));
  563. exmsg=vsncpy(exmsg,sLEN(exmsg),sc(" saved."));
  564. bw->b->chnged=0;
  565. wabort(w);
  566. }
  567. X
  568. void uexsve(w)
  569. W *w;
  570. {
  571. BW *bw=(BW *)w->object;
  572. if(!bw->b->chnged)
  573. X {
  574. X exmsg=vsncpy(NULL,0,sc("File "));
  575. X exmsg=vsncpy(exmsg,sLEN(exmsg),sz(bw->b->name));
  576. X exmsg=vsncpy(exmsg,sLEN(exmsg),sc(" not changed so no updated needed."));
  577. X wabort(w);
  578. X return;
  579. X }
  580. if(bw->b->name)
  581. X {
  582. X if(dosave(w,vsncpy(NULL,0,sz(bw->b->name)))) return;
  583. X exmsg=vsncpy(NULL,0,sc("File "));
  584. X exmsg=vsncpy(exmsg,sLEN(exmsg),sz(bw->b->name));
  585. X exmsg=vsncpy(exmsg,sLEN(exmsg),sc(" saved."));
  586. X bw->b->chnged=0;
  587. X wabort(w);
  588. X } 
  589. else wmkfpw(w,"Name of file to save (^C to abort): ",&filehist,doex,"Names");
  590. }
  591. X
  592. /*************/
  593. /* Goto line */
  594. /*************/
  595. X
  596. static void doline(w,s)
  597. W *w;
  598. char *s;
  599. {
  600. BW *bw=(BW *)w->object;
  601. long num=0;
  602. sscanf(s,"%ld",&num);
  603. if(num>=1) pline(bw->cursor,num-1), bw->cursor->xcol=bw->cursor->col;
  604. else msgnw(w,"Invalid line number");
  605. vsrm(s);
  606. }
  607. X
  608. void uline(w)
  609. W *w;
  610. {
  611. wmkpw(w,"Goto line (^C to abort): ",&linehist,doline,NULL);
  612. }
  613. X
  614. /************************/
  615. /* Basic edit functions */
  616. /************************/
  617. X
  618. void uquote(w)
  619. W *w;
  620. {
  621. BW *bw=(BW *)w->object;
  622. int c=queryn(w,"Ctrl-");
  623. if((c>=0x40 && c<=0x5F) || (c>='a' && c<='z')) c&=0x1F;
  624. if(c=='?') c=127;
  625. utype(w,c);
  626. }
  627. X
  628. void uquote8(w)
  629. W *w;
  630. {
  631. BW *bw=(BW *)w->object;
  632. int c=queryn(w,"Meta-");
  633. if(c=='`')
  634. X {
  635. X c=queryn(w,"Meta-Ctrl-");
  636. X if((c>=0x40 && c<=0x5F) || (c>='a' && c<='z')) c&=0x1F;
  637. X if(c=='?') c=127;
  638. X }
  639. c|=128;
  640. utype(w,c);
  641. }
  642. X
  643. void uretyp(w)
  644. W *w;
  645. {
  646. BW *bw=(BW *)w->object;
  647. nredraw(w->t->t);
  648. }
  649. X
  650. P *pboi(p)
  651. P *p;
  652. {
  653. pbol(p);
  654. while(cwhite(brc(p))) pgetc(p);
  655. return p;
  656. }
  657. X
  658. int pisedge(p)
  659. P *p;
  660. {
  661. P *q;
  662. int c;
  663. if(pisbol(p)) return 1;
  664. if(piseol(p)) return 1;
  665. q=pdup(p);
  666. pboi(q);
  667. if(q->byte==p->byte) goto yes;
  668. if(cwhite(c=brc(p)))
  669. X {
  670. X pset(q,p); if(cwhite(prgetc(q))) goto no;
  671. X if(c=='\t') goto yes;
  672. X pset(q,p); pgetc(q);
  673. X if(pgetc(q)==' ') goto yes;
  674. X goto no;
  675. X }
  676. else
  677. X {
  678. X pset(q,p); c=prgetc(q);
  679. X if(c=='\t') goto yes;
  680. X if(c!=' ') goto no;
  681. X if(prgetc(q)==' ') goto yes;
  682. X goto no;
  683. X }
  684. X
  685. yes: prm(q); return 1;
  686. no:  prm(q); return 0;
  687. }
  688. X
  689. void upedge(w)
  690. W *w;
  691. {
  692. BW *bw=(BW *)w->object;
  693. prgetc(bw->cursor);
  694. while(!pisedge(bw->cursor)) prgetc(bw->cursor);
  695. }
  696. X
  697. void unedge(w)
  698. W *w;
  699. {
  700. BW *bw=(BW *)w->object;
  701. pgetc(bw->cursor);
  702. while(!pisedge(bw->cursor)) pgetc(bw->cursor);
  703. }
  704. X
  705. void ubol(w)
  706. W *w;
  707. {
  708. BW *bw=(BW *)w->object;
  709. pbol(bw->cursor);
  710. }
  711. X
  712. void ueol(w)
  713. W *w;
  714. {
  715. BW *bw=(BW *)w->object;
  716. peol(bw->cursor);
  717. }
  718. X
  719. void ubof(w)
  720. W *w;
  721. {
  722. BW *bw=(BW *)w->object;
  723. pbof(bw->cursor);
  724. }
  725. X
  726. void ueof(w)
  727. W *w;
  728. {
  729. BW *bw=(BW *)w->object;
  730. peof(bw->cursor);
  731. }
  732. X
  733. void ultarw(w)
  734. W *w;
  735. {
  736. BW *bw=(BW *)w->object;
  737. prgetc(bw->cursor);
  738. }
  739. X
  740. X
  741. void urtarw(w)
  742. W *w;
  743. {
  744. BW *bw=(BW *)w->object;
  745. pgetc(bw->cursor);
  746. }
  747. X
  748. void uprvwrd(w)
  749. W *w;
  750. {
  751. BW *bw=(BW *)w->object;
  752. int c, d;
  753. X
  754. /* Move to end of previous word or edge */
  755. lp:
  756. d=' ';
  757. while(c=prgetc(bw->cursor),
  758. X      c!= MAXINT && !cword(c) && (!cwhitel(c) || cwhitel(d)))
  759. X d=c; 
  760. if(c==' ')
  761. X {
  762. X d=prgetc(bw->cursor); if(d!=MAXINT) pgetc(bw->cursor);
  763. X if(!cwhitel(d)) { pgetc(bw->cursor); goto lp; }
  764. X }
  765. if(c!= MAXINT) pgetc(bw->cursor);
  766. X
  767. X
  768. /* Move to beginning of current word */
  769. while(cword(c=prgetc(bw->cursor)));
  770. if(c!= MAXINT) pgetc(bw->cursor);
  771. }
  772. X
  773. void unxtwrd(w)
  774. W *w;
  775. {
  776. BW *bw=(BW *)w->object;
  777. int c, d;
  778. /* Move to start of next word or edge */
  779. lp:
  780. d=' ';
  781. while(c=brc(bw->cursor),
  782. X      c!= MAXINT && !cword(c) && (!cwhitel(c) || cwhitel(d)))
  783. X d=pgetc(bw->cursor);
  784. if(c==' ')
  785. X {
  786. X pgetc(bw->cursor); d=brc(bw->cursor); prgetc(bw->cursor);
  787. X if(!cwhitel(d)) goto lp;
  788. X }
  789. X
  790. /* Move to end of current word */
  791. while(c=brc(bw->cursor), cword(c)) pgetc(bw->cursor);
  792. }
  793. X
  794. void utomatch(w)
  795. W *w;
  796. {
  797. BW *bw=(BW *)w->object;
  798. int c, f, dir, cnt, d;
  799. P *p;
  800. c=brc(bw->cursor);
  801. f= MAXINT; dir=1;
  802. if(c=='(') f=')';
  803. if(c=='[') f=']';
  804. if(c=='{') f='}';
  805. if(c=='`') f='\'';
  806. if(c=='<') f='>';
  807. if(c==')') f='(', dir= -1;
  808. if(c==']') f='[', dir= -1;
  809. if(c=='}') f='{', dir= -1;
  810. if(c=='\'') f='`', dir= -1;
  811. if(c=='>') f='<', dir= -1;
  812. if(f== MAXINT) return;
  813. if(dir==1)
  814. X {
  815. X p=pdup(bw->cursor);
  816. X cnt=0;
  817. X pgetc(p);
  818. X while(d=pgetc(p), d!= MAXINT)
  819. X  if(d==c) ++cnt;
  820. X  else if(d==f) if(!cnt--) break;
  821. X if(d!= MAXINT)
  822. X  {
  823. X  prgetc(p);
  824. X  pset(bw->cursor,p);
  825. X  }
  826. X prm(p);
  827. X }
  828. else
  829. X {
  830. X p=pdup(bw->cursor);
  831. X cnt=0;
  832. X while(d=prgetc(p), d!= MAXINT)
  833. X  if(d==c) ++cnt;
  834. X  else if(d==f) if(!cnt--) break;
  835. X if(d!= MAXINT) pset(bw->cursor,p);
  836. X prm(p);
  837. X }
  838. }
  839. X
  840. void uuparw(w)
  841. W *w;
  842. {
  843. BW *bw=(BW *)w->object;
  844. long col=bw->cursor->xcol;
  845. pprevl(bw->cursor);
  846. pboln(bw->cursor);
  847. pcol(bw->cursor,bw->cursor->xcol=col);
  848. }
  849. X
  850. void udnarw(w)
  851. W *w;
  852. {
  853. BW *bw=(BW *)w->object;
  854. long col=bw->cursor->xcol;
  855. if(!pnextl(bw->cursor)) pboln(bw->cursor);
  856. pcol(bw->cursor,bw->cursor->xcol=col);
  857. }
  858. X
  859. void scrup(w,n,flg)
  860. W *w;
  861. {
  862. BW *bw=(BW *)w->object;
  863. int scrollamnt=0;
  864. int cursoramnt=0;
  865. int x;
  866. long col=bw->cursor->xcol;
  867. if(bw->top->line>=n) scrollamnt=cursoramnt=n;
  868. else if(bw->top->line) scrollamnt=cursoramnt=bw->top->line;
  869. else
  870. X if(flg) cursoramnt=bw->cursor->line;
  871. X else if(bw->cursor->line>=n) cursoramnt=n;
  872. X
  873. for(x=0;x!=scrollamnt;++x) pprevl(bw->top);
  874. pboln(bw->top);
  875. for(x=0;x!=cursoramnt;++x) pprevl(bw->cursor);
  876. pboln(bw->cursor); pcol(bw->cursor,bw->cursor->xcol=col);
  877. if(scrollamnt && scrollamnt<bw->h)
  878. X {
  879. X nscrldn(w->t->t,bw->y,bw->y+bw->h,scrollamnt);
  880. X scrldn(w->t->t->updtab,bw->y,bw->y+bw->h,scrollamnt);
  881. X }
  882. else if(scrollamnt)
  883. X {
  884. X scrldn(w->t->t->updtab,bw->y,bw->y+bw->h,bw->h);
  885. X }
  886. }
  887. X
  888. void scrdn(w,n,flg)
  889. W *w;
  890. {
  891. BW *bw=(BW *)w->object;
  892. int scrollamnt=0;
  893. int cursoramnt=0;
  894. int x;
  895. long col=bw->cursor->xcol;
  896. X
  897. if(bw->top->b->eof->line<bw->top->line+bw->h)
  898. X {
  899. X cursoramnt=bw->top->b->eof->line-bw->cursor->line;
  900. X if(!flg && cursoramnt>n) cursoramnt=n;
  901. X }
  902. else if(bw->top->b->eof->line-(bw->top->line+bw->h)>=n)
  903. X cursoramnt=scrollamnt=n;
  904. else
  905. X cursoramnt=scrollamnt=bw->top->b->eof->line-(bw->top->line+bw->h)+1;
  906. X
  907. for(x=0;x!=scrollamnt;++x) pnextl(bw->top);
  908. for(x=0;x!=cursoramnt;++x) pnextl(bw->cursor);
  909. pcol(bw->cursor,bw->cursor->xcol=col);
  910. if(scrollamnt && scrollamnt<bw->h)
  911. X {
  912. X int x;
  913. X nscrlup(w->t->t,bw->y,bw->y+bw->h,scrollamnt);
  914. X scrlup(w->t->t->updtab,bw->y,bw->y+bw->h,scrollamnt);
  915. X }
  916. else if(scrollamnt) scrlup(w->t->t->updtab,bw->y,bw->y+bw->h,bw->h);
  917. }
  918. X
  919. int pgamnt= -1;
  920. X
  921. void upgup(w)
  922. W *w;
  923. {
  924. BW *bw=(BW *)w->object;
  925. if(pgamnt== -1) scrup(w,bw->h/2+(bw->h&1),1);
  926. else if(pgamnt<bw->h) scrup(w,bw->h-pgamnt,1);
  927. else scrup(w,1,1);
  928. }
  929. X
  930. void upgdn(w)
  931. W *w;
  932. {
  933. BW *bw=(BW *)w->object;
  934. if(pgamnt== -1) scrdn(w,bw->h/2+(bw->h&1),1);
  935. else if(pgamnt<bw->h) scrdn(w,bw->h-pgamnt,1);
  936. else scrdn(w,1,1);
  937. }
  938. X
  939. void uupslide(w)
  940. W *w;
  941. {
  942. scrup(w,1,0);
  943. }
  944. X
  945. void udnslide(w)
  946. W *w;
  947. {
  948. scrdn(w,1,0);
  949. }
  950. X
  951. void udelch(w)
  952. W *w;
  953. {
  954. BW *bw=(BW *)w->object;
  955. P *p;
  956. p=pdup(bw->cursor);
  957. pgetc(p);
  958. bdel(bw->cursor,p);
  959. prm(p);
  960. }
  961. X
  962. void ubacks(w)
  963. W *w;
  964. {
  965. BW *bw=(BW *)w->object;
  966. P *p;
  967. int c;
  968. if(bw->overtype && !pisbol(bw->cursor) && !piseol(bw->cursor))
  969. X {
  970. X if((c=prgetc(bw->cursor))!='\t') return;
  971. X else if(c!=MAXINT) pgetc(bw->cursor);
  972. X }
  973. p=pdup(bw->cursor);
  974. if((c=prgetc(bw->cursor))!= MAXINT) bdel(bw->cursor,p);
  975. prm(p);
  976. }
  977. X
  978. void udelw(w)
  979. W *w;
  980. {
  981. BW *bw=(BW *)w->object;
  982. P *p;
  983. int c;
  984. p=pdup(bw->cursor);
  985. c=brc(p);
  986. if(cword(c))
  987. X while(c=brc(p), cword(c)) pgetc(p);
  988. else if(cwhitel(c))
  989. X while(c=brc(p), cwhitel(c)) pgetc(p);
  990. else pgetc(p);
  991. bdel(bw->cursor,p);
  992. prm(p);
  993. }
  994. X
  995. void ubackw(w)
  996. W *w;
  997. {
  998. BW *bw=(BW *)w->object;
  999. P *p;
  1000. int c;
  1001. p=pdup(bw->cursor);
  1002. c=prgetc(bw->cursor);
  1003. if(cword(c))
  1004. X {
  1005. X while(c=prgetc(bw->cursor), cword(c));
  1006. X if(c!= MAXINT) pgetc(bw->cursor);
  1007. X }
  1008. else if(cwhitel(c))
  1009. X {
  1010. X while(c=prgetc(bw->cursor), cwhitel(c));
  1011. X if(c!= MAXINT) pgetc(bw->cursor);
  1012. X }
  1013. bdel(bw->cursor,p);
  1014. prm(p);
  1015. }
  1016. X
  1017. void udelel(w)
  1018. W *w;
  1019. {
  1020. BW *bw=(BW *)w->object;
  1021. P *p;
  1022. p=pdup(bw->cursor);
  1023. peol(p);
  1024. if(bw->cursor->byte==p->byte)
  1025. X {
  1026. X prm(p);
  1027. X udelch(w);
  1028. X }
  1029. else
  1030. X {
  1031. X bdel(bw->cursor,p);
  1032. X prm(p);
  1033. X }
  1034. }
  1035. X
  1036. void udelbl(w)
  1037. W *w;
  1038. {
  1039. BW *bw=(BW *)w->object;
  1040. P *p;
  1041. p=pdup(bw->cursor);
  1042. pbol(p);
  1043. bdel(p,bw->cursor);
  1044. prm(p);
  1045. }
  1046. X
  1047. void udelln(w)
  1048. W *w;
  1049. {
  1050. BW *bw=(BW *)w->object;
  1051. P *p;
  1052. pbol(bw->cursor);
  1053. p=pdup(bw->cursor);
  1054. pnextl(p);
  1055. bdel(bw->cursor,p);
  1056. prm(p);
  1057. }
  1058. X
  1059. void ucenter(w)
  1060. W *w;
  1061. {
  1062. BW *bw=(BW *)w->object;
  1063. P *p=bw->cursor, *q;
  1064. long endcol, begcol, x;
  1065. int c;
  1066. X
  1067. peol(p);
  1068. while(!pisbol(p) && cwhite(c=prgetc(p)));
  1069. if(pisbol(p)) return;
  1070. pgetc(p); endcol=p->col;
  1071. X
  1072. pbol(p);
  1073. while(!piseol(p) && cwhite(c=pgetc(p)));
  1074. if(piseol(p)) return;
  1075. prgetc(p); begcol=p->col;
  1076. X
  1077. if(endcol-begcol>bw->rmargin+bw->lmargin) return;
  1078. X
  1079. q=pdup(p); pbol(q); bdel(q,p); prm(q);
  1080. X
  1081. for(x=0;x!=(bw->lmargin+bw->rmargin)/2-(endcol-begcol)/2;++x) binsc(p,' ');
  1082. X
  1083. if(!pnextl(p))
  1084. X {
  1085. X binsc(p,'\n');
  1086. X pgetc(p);
  1087. X }
  1088. }
  1089. X
  1090. /* Paragraph stuff */
  1091. X
  1092. /* Determine if line pointer is on is blank */
  1093. X
  1094. int pblank(p)
  1095. P *p;
  1096. {
  1097. P *q=pdup(p);
  1098. int rtval;
  1099. pbol(q);
  1100. while(cwhite(brc(q))) pgetc(q);
  1101. rtval=piseol(q);
  1102. prm(q);
  1103. return rtval;
  1104. }
  1105. X
  1106. /* Determine indentation level of line pointer is on */
  1107. X
  1108. long pindent(p)
  1109. P *p;
  1110. {
  1111. P *q=pdup(p);
  1112. long col;
  1113. pbol(q);
  1114. while(cwhite(brc(q))) pgetc(q);
  1115. col=q->col;
  1116. prm(q);
  1117. return col;
  1118. }
  1119. X
  1120. /* Move pointer to beginning of paragraph */
  1121. X
  1122. P *pbop(p)
  1123. P *p;
  1124. {
  1125. long indent;
  1126. pbol(p);
  1127. indent=pindent(p);
  1128. while(!pisbof(p))
  1129. X {
  1130. X long ind;
  1131. X pprevl(p); pboln(p);
  1132. X ind=pindent(p);
  1133. X if(pblank(p) || ind<indent)
  1134. X  {
  1135. X  pnextl(p);
  1136. X  break;
  1137. X  }
  1138. X if(ind>indent) break;
  1139. X }
  1140. return p;
  1141. }
  1142. X
  1143. /* Move pointer to end of paragraph */
  1144. X
  1145. P *peop(p)
  1146. P *p;
  1147. {
  1148. long indent;
  1149. pbol(p);
  1150. indent=pindent(p);
  1151. while(!piseof(p))
  1152. X {
  1153. X long ind;
  1154. X pnextl(p);
  1155. X ind=pindent(p);
  1156. X if(ind>indent || pblank(p)) break;
  1157. X if(ind<indent) indent=ind;
  1158. X }
  1159. if(piseof(p))  peol(p);
  1160. return p;
  1161. }
  1162. X
  1163. /* Wrap word */
  1164. X
  1165. void wrapword(p,indent)
  1166. P *p;
  1167. long indent;
  1168. {
  1169. int c;
  1170. long to=p->byte;
  1171. while(!pisbol(p) && !cwhite(c=prgetc(p)));
  1172. if(!pisbol(p))
  1173. X {
  1174. X pgetc(p);
  1175. X binsc(p,'\n'), ++to;
  1176. X pgetc(p);
  1177. X if(indent) while(indent--) binsc(p,' '), ++to;
  1178. X }
  1179. pfwrd(p,to-p->byte);
  1180. }
  1181. X
  1182. /* Reformat paragraph */
  1183. X
  1184. void uformat(w)
  1185. W *w;
  1186. {
  1187. BW *bw=(BW *)w->object;
  1188. long indent;
  1189. char *buf, *b;
  1190. int len;
  1191. long curoff;
  1192. int c;
  1193. P *p, *q;
  1194. p=pdup(bw->cursor); pbol(p);
  1195. X
  1196. if(pblank(p))
  1197. X {
  1198. X prm(p);
  1199. X return;
  1200. X }
  1201. X
  1202. pbop(p);
  1203. curoff=bw->cursor->byte-p->byte;
  1204. peop(bw->cursor);
  1205. X
  1206. if(bw->cursor->lbyte) binsc(bw->cursor,'\n'), pgetc(bw->cursor);
  1207. if(piseof(bw->cursor)) binsc(bw->cursor,'\n');
  1208. X
  1209. indent=pindent(p);
  1210. q=pdup(p); pnextl(q);
  1211. if(q->line!=bw->cursor->line) indent=pindent(q);
  1212. prm(q);
  1213. if(bw->lmargin>indent) indent=bw->lmargin;
  1214. X
  1215. buf=(char *)malloc(len=(bw->cursor->byte-p->byte));
  1216. brmem(p,buf,len);
  1217. bdel(p,bw->cursor);
  1218. prm(p);
  1219. X
  1220. /* text is in buffer.  insert it at cursor */
  1221. X
  1222. /* Do first line */
  1223. b=buf;
  1224. p=pdup(bw->cursor);
  1225. X
  1226. while(len--)
  1227. X {
  1228. X if(b-buf==curoff) pset(bw->cursor,p);
  1229. X c= *b++;
  1230. X if(c=='\n') { ++len; --b; break; }
  1231. X if(cwhite(c))
  1232. X  {
  1233. X  char *r=b;
  1234. X  int rlen=len;
  1235. X  int z;
  1236. X  while(rlen--)
  1237. X   {
  1238. X   z=*r++;
  1239. X   if(z=='\n') break;
  1240. X   if(!cwhite(z)) goto ok;
  1241. X   }
  1242. X  ++len; --b; break;
  1243. X  ok:;
  1244. X  }
  1245. X binsc(p,c); pgetc(p);
  1246. X if(p->col>bw->rmargin && !cwhite(c))
  1247. X  {
  1248. X  wrapword(p,indent);
  1249. X  break;
  1250. X  }
  1251. X }
  1252. X
  1253. while(len>0)
  1254. X if(cwhitel(*b))
  1255. X  {
  1256. X  if(b[-1]=='.' || b[-1]=='?' || b[-1]=='!') binsc(p,' '), pgetc(p);
  1257. X  binsc(p,' '); pgetc(p);
  1258. X  while(len && cwhitel(*b))
  1259. X   {
  1260. X   if(b-buf==curoff) pset(bw->cursor,p);
  1261. X   ++b, --len;
  1262. X   }
  1263. X  }
  1264. X else
  1265. X  {
  1266. X  if(b-buf==curoff) pset(bw->cursor,p);
  1267. X  binsc(p,*b++); --len; pgetc(p);
  1268. X  if(p->col>bw->rmargin) wrapword(p,indent);
  1269. X  }
  1270. X
  1271. binsc(p,'\n');
  1272. prm(p);
  1273. free(buf);
  1274. }
  1275. X
  1276. void uinsc(w)
  1277. W *w;
  1278. {
  1279. BW *bw=(BW *)w->object;
  1280. binsc(bw->cursor,' ');
  1281. }
  1282. X
  1283. void utype(w,c)
  1284. W *w;
  1285. int c;
  1286. {
  1287. BW *bw=(BW *)w->object;
  1288. P *p;
  1289. if(pblank(bw->cursor))
  1290. X while(bw->cursor->col<bw->lmargin) binsc(bw->cursor,' '), pgetc(bw->cursor);
  1291. binsc(bw->cursor,c);
  1292. pgetc(bw->cursor);
  1293. if(bw->wordwrap && bw->cursor->col>bw->rmargin && !cwhite(c))
  1294. X wrapword(bw->cursor,bw->lmargin);
  1295. else if(bw->overtype && !piseol(bw->cursor) && c!='\t') udelch(w);
  1296. }
  1297. X
  1298. void urtn(w)
  1299. W *w;
  1300. {
  1301. BW *bw=(BW *)w->object;
  1302. P *p;
  1303. int c;
  1304. p=pdup(bw->cursor);
  1305. binsc(bw->cursor,'\n');
  1306. pgetc(bw->cursor);
  1307. if(bw->autoindent)
  1308. X {
  1309. X pbol(p);
  1310. X while(cwhite(c=pgetc(p))) binsc(bw->cursor,c), pgetc(bw->cursor);
  1311. X }
  1312. prm(p);
  1313. }
  1314. X
  1315. void uopen(w)
  1316. W *w;
  1317. {
  1318. BW *bw=(BW *)w->object;
  1319. P *q=pdup(bw->cursor);
  1320. urtn(w);
  1321. pset(bw->cursor,q);
  1322. prm(q);
  1323. }
  1324. X
  1325. void dotag(w,s)
  1326. W *w;
  1327. char *s;
  1328. {
  1329. BW *bw=(BW *)w->object;
  1330. char buf[512];
  1331. FILE *f;
  1332. void *object=bw->object;
  1333. f=fopen("tags","r");
  1334. while(fgets(buf,512,f))
  1335. X {
  1336. X int x, y, c;
  1337. X for(x=0;buf[x] && buf[x]!=' ' && buf[x]!='\t';++x);
  1338. X c=buf[x]; buf[x]=0;
  1339. X if(!zcmp(s,buf))
  1340. X  {
  1341. X  buf[x]=c;
  1342. X  while(buf[x]==' ' || buf[x]=='\t') ++x;
  1343. X  for(y=x;buf[y] && buf[y]!=' ' && buf[y]!='\t' && buf[y]!='\n';++y);
  1344. X  if(x!=y)
  1345. X   {
  1346. X   B *b;
  1347. X   c=buf[y]; buf[y]=0;
  1348. X   b=bfind(buf+x);
  1349. X   if(!b)
  1350. X    {
  1351. X    int fl;
  1352. X    b=bmk();
  1353. X    if(fl=bload(b,buf+x))
  1354. X     { msgnwt(w,msgs[fl+5]); brm(b); vsrm(s); fclose(f); return; }
  1355. X    }
  1356. X   bwrm(bw);
  1357. X   w->object=(void *)(bw=bwmk(w->t,b,w->x,w->y+1,w->w,w->h-1));
  1358. X   wredraw(w);
  1359. X   setoptions(bw,buf+x);
  1360. X   bw->object=object;
  1361. X   
  1362. X   buf[y]=c;
  1363. X   while(buf[y]==' ' || buf[y]=='\t') ++y;
  1364. X   for(x=y;buf[x] && buf[x]!='\n';++x);
  1365. X   buf[x]=0;
  1366. X   if(x!=y)
  1367. X    {
  1368. X    long line=0;
  1369. X    if(buf[y]>='0' && buf[y]<='9')
  1370. X     {
  1371. X     sscanf(buf+y,"%ld",&line);
  1372. X     if(line>=1) pline(bw->cursor,line-1), bw->cursor->xcol=bw->cursor->col;
  1373. X     else msgnw(w,"Invalid line number");
  1374. X     }
  1375. X    else
  1376. X     {
  1377. X     if(buf[y]=='/' || buf[y]=='?')
  1378. X      {
  1379. X      ++y;
  1380. X      if(buf[y]=='^') buf[--y]='\\';
  1381. X      }
  1382. X     if(buf[x-1]=='/' || buf[x-1]=='?')
  1383. X      {
  1384. X      --x;
  1385. X      buf[x]=0;
  1386. X      if(buf[x-1]=='$')
  1387. X       {
  1388. X       buf[x-1]='\\';
  1389. X       buf[x]='$';
  1390. X       ++x;
  1391. X       buf[x]=0;
  1392. X       }
  1393. X      }
  1394. X     if(x!=y)
  1395. X      {
  1396. X      w->t->pattern=vsncpy(NULL,0,sz(buf+y));
  1397. X      w->t->options=0;
  1398. X      w->t->repeat= -1;
  1399. X      pfnext(w);
  1400. X      }
  1401. X     }
  1402. X    }
  1403. X   vsrm(s);
  1404. X   fclose(f);
  1405. X   return;
  1406. X   }
  1407. X  }
  1408. X }
  1409. msgnw(w,"Not found");
  1410. vsrm(s);
  1411. fclose(f);
  1412. }
  1413. X
  1414. void utag(w)
  1415. W *w;
  1416. {
  1417. BW *bw=(BW *)w->object;
  1418. W *pw;
  1419. if(bw->b->count==1 && bw->b->chnged)
  1420. X {
  1421. X int c=query(w,"Do you really want to throw away this file (y,n)? ");
  1422. X if(c!='y' && c!='Y') return;
  1423. X }
  1424. pw=wmkfpw(w,"Tag string to find (^C to abort): ",&taghist,dotag,NULL);
  1425. if(pw && cword(brc(bw->cursor)))
  1426. X {
  1427. X BW *pbw=(BW *)pw->object;
  1428. X P *p=pdup(bw->cursor);
  1429. X P *q=pdup(p);
  1430. X int c;
  1431. X while(cword(c=prgetc(p))); if(c!=MAXINT) pgetc(p);
  1432. X pset(q,p); while(cword(c=pgetc(q))); if(c!=MAXINT) prgetc(q);
  1433. X binsb(pbw->cursor,p,q);
  1434. X pset(pbw->cursor,pbw->b->eof); pbw->cursor->xcol=pbw->cursor->col;
  1435. X prm(p); prm(q);
  1436. X }
  1437. }
  1438. X
  1439. /* Mode commands */
  1440. X
  1441. void uisquare(w)
  1442. W *w;
  1443. {
  1444. square= !square;
  1445. if(square) msgnw(w,"Rectangle mode selected.  Effects block commands & Insert file");
  1446. else msgnw(w,"Normal text-stream mode selected");
  1447. updall();
  1448. }
  1449. X
  1450. void uiindent(w)
  1451. W *w;
  1452. {
  1453. BW *bw=(BW *)w->object;
  1454. bw->autoindent= !bw->autoindent;
  1455. if(bw->autoindent) msgnw(w,"Autoindent enabled");
  1456. else msgnw(w,"Autoindent disabled");
  1457. }
  1458. X
  1459. void uiwrap(w)
  1460. W *w;
  1461. {
  1462. BW *bw=(BW *)w->object;
  1463. bw->wordwrap= !bw->wordwrap;
  1464. if(bw->wordwrap) msgnw(w,"Word wrap enabled");
  1465. else msgnw(w,"Word wrap disabled");
  1466. }
  1467. X
  1468. void uitype(w)
  1469. W *w;
  1470. {
  1471. BW *bw=(BW *)w->object;
  1472. bw->overtype= !bw->overtype;
  1473. if(bw->overtype==0) msgnw(w,"Insert mode");
  1474. else msgnw(w,"Overtype mode");
  1475. }
  1476. X
  1477. void uimid(w)
  1478. W *w;
  1479. {
  1480. mid= !mid;
  1481. if(mid) msgnw(w,"Cursor will be recentered after a scroll");
  1482. else msgnw(w,"Cursor will not be recentered after a scroll");
  1483. }
  1484. X
  1485. void uiforce(w)
  1486. W *w;
  1487. {
  1488. force= !force;
  1489. if(force) msgnw(w,"Last line forced to have LF when file saved");
  1490. else msgnw(w,"Last line not forced to have LF");
  1491. }
  1492. X
  1493. void uiasis(w)
  1494. W *w;
  1495. {
  1496. dspasis= !dspasis;
  1497. if(dspasis) msgnw(w,"Characters above 127 displayed as-is");
  1498. else msgnw(w,"Characters above 127 remapped");
  1499. refigure();
  1500. updall();
  1501. }
  1502. X
  1503. void uistacol(w)
  1504. W *w;
  1505. {
  1506. stacol= !stacol;
  1507. }
  1508. X
  1509. void uistarow(w)
  1510. W *w;
  1511. {
  1512. starow= !starow;
  1513. }
  1514. X
  1515. static void dolmar(w,s)
  1516. W *w;
  1517. char *s;
  1518. {
  1519. BW *bw=(BW *)w->object;
  1520. long v=bw->lmargin;
  1521. sscanf(s,"%ld",&v);
  1522. vsrm(s);
  1523. bw->lmargin=v;
  1524. }
  1525. X
  1526. void uilmargin(w)
  1527. W *w;
  1528. {
  1529. BW *bw=(BW *)w->object;
  1530. char buf[80];
  1531. sprintf(buf,"Left margin %ld (^C to abort): ",bw->lmargin);
  1532. wmkpw(w,buf,NULL,dolmar,NULL);
  1533. }
  1534. X
  1535. static void docindent(w,s)
  1536. W *w;
  1537. char *s;
  1538. {
  1539. BW *bw=(BW *)w->object;
  1540. int v=bw->indentc;
  1541. sscanf(s,"%d",&v);
  1542. vsrm(s);
  1543. bw->indentc=v;
  1544. }
  1545. X
  1546. void uicindent(w)
  1547. W *w;
  1548. {
  1549. BW *bw=(BW *)w->object;
  1550. char buf[80];
  1551. sprintf(buf,"Indent char %d (SPACE=32, TAB=9, ^C to abort): ",
  1552. X        bw->indentc);
  1553. wmkpw(w,buf,NULL,docindent,NULL);
  1554. }
  1555. X
  1556. static void doistep(w,s)
  1557. W *w;
  1558. char *s;
  1559. {
  1560. BW *bw=(BW *)w->object;
  1561. long v=bw->istep;
  1562. sscanf(s,"%ld",&v);
  1563. vsrm(s);
  1564. bw->istep=v;
  1565. }
  1566. X
  1567. void uiistep(w)
  1568. W *w;
  1569. {
  1570. BW *bw=(BW *)w->object;
  1571. char buf[80];
  1572. sprintf(buf,"Indent step %ld (^C to abort): ",bw->istep);
  1573. wmkpw(w,buf,NULL,doistep,NULL);
  1574. }
  1575. X
  1576. static void dormar(w,s)
  1577. W *w;
  1578. char *s;
  1579. {
  1580. BW *bw=(BW *)w->object;
  1581. long v=bw->rmargin;
  1582. sscanf(s,"%ld",&v);
  1583. vsrm(s);
  1584. bw->rmargin=v;
  1585. }
  1586. X
  1587. void uirmargin(w)
  1588. W *w;
  1589. {
  1590. BW *bw=(BW *)w->object;
  1591. char buf[80];
  1592. sprintf(buf,"Right margin %ld (^C to abort): ",bw->rmargin);
  1593. wmkpw(w,buf,NULL,dormar,NULL);
  1594. }
  1595. X
  1596. static void dotab(w,s)
  1597. W *w;
  1598. char *s;
  1599. {
  1600. BW *bw=(BW *)w->object;
  1601. int v=bw->b->tab;
  1602. sscanf(s,"%ld",&v);
  1603. if(v<0 || v>256) v=8;
  1604. vsrm(s);
  1605. bw->b->tab=v;
  1606. refigure();
  1607. updall();
  1608. }
  1609. X
  1610. void uitab(w)
  1611. W *w;
  1612. {
  1613. BW *bw=(BW *)w->object;
  1614. char buf[80];
  1615. sprintf(buf,"Tab width %d (^C to abort): ",bw->b->tab);
  1616. wmkpw(w,buf,NULL,dotab,NULL);
  1617. }
  1618. X
  1619. static void dopgamnt(w,s)
  1620. W *w;
  1621. char *s;
  1622. {
  1623. BW *bw=(BW *)w->object;
  1624. long v=pgamnt;
  1625. sscanf(s,"%ld",&v);
  1626. vsrm(s);
  1627. if(v<-1) v= -1;
  1628. pgamnt=v;
  1629. }
  1630. X
  1631. void uipgamnt(w)
  1632. W *w;
  1633. {
  1634. char buf[80];
  1635. sprintf(buf,"Lines to keep for pgup/pgdn or -1 for 1/2 (%ld): ",pgamnt);
  1636. wmkpw(w,buf,NULL,dopgamnt,NULL);
  1637. }
  1638. X
  1639. /* Argument setting */
  1640. X
  1641. void uarg(w,c)
  1642. W *w;
  1643. {
  1644. char buf[80];
  1645. if(c>='1' && c<='9') w->t->arg=(c&0xF);
  1646. else w->t->arg=0;
  1647. sprintf(buf,"%d",w->t->arg); msgnw(w,buf);
  1648. while(c=edgetc(), c>='0' && c<='9')
  1649. X {
  1650. X w->t->arg=w->t->arg*10+(c&0xf);
  1651. X sprintf(buf,"%d",w->t->arg); msgnw(w,buf);
  1652. X }
  1653. if(c==3) w->t->arg=0;
  1654. else eungetc(c);
  1655. }
  1656. SHAR_EOF
  1657. chmod 0600 edfuncs.c ||
  1658. echo 'restore of edfuncs.c failed'
  1659. Wc_c="`wc -c < 'edfuncs.c'`"
  1660. test 32824 -eq "$Wc_c" ||
  1661.     echo 'edfuncs.c: original size 32824, current size' "$Wc_c"
  1662. fi
  1663. # ============= edfuncs.h ==============
  1664. if test -f 'edfuncs.h' -a X"$1" != X"-c"; then
  1665.     echo 'x - skipping edfuncs.h (File already exists)'
  1666. else
  1667. echo 'x - extracting edfuncs.h (Text)'
  1668. sed 's/^X//' << 'SHAR_EOF' > 'edfuncs.h' &&
  1669. /* User edit functions
  1670. X   Copyright (C) 1992 Joseph H. Allen
  1671. X
  1672. This file is part of JOE (Joe's Own Editor)
  1673. X
  1674. JOE is free software; you can redistribute it and/or modify it under the 
  1675. terms of the GNU General Public License as published by the Free Software 
  1676. Foundation; either version 1, or (at your option) any later version.  
  1677. X
  1678. JOE is distributed in the hope that it will be useful, but WITHOUT ANY 
  1679. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  1680. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  1681. details.  
  1682. X
  1683. You should have received a copy of the GNU General Public License along with 
  1684. JOE; see the file COPYING.  If not, write to the Free Software Foundation, 
  1685. 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
  1686. X
  1687. #ifndef _Iedfncs
  1688. #define _Iedfncs 1
  1689. X
  1690. #include "config.h"
  1691. X
  1692. extern char *msgs[];
  1693. X
  1694. void umarkb();
  1695. void umarkk();
  1696. void ublkdel();
  1697. void ublkcpy();
  1698. void ublkmove();
  1699. void ublksave();
  1700. X
  1701. void ufilt();
  1702. void ulindent();
  1703. void urindent();
  1704. X
  1705. void uarg();
  1706. X
  1707. void ugroww();
  1708. void ushrnk();
  1709. void unextw();
  1710. void uprevw();
  1711. void uexpld();
  1712. X
  1713. void ushell();
  1714. X
  1715. void uretyp();
  1716. X
  1717. void uexsve();
  1718. void usave();
  1719. void uedit();
  1720. void uinsf();
  1721. X
  1722. void ubof();
  1723. void ueof();
  1724. X
  1725. void ubol();
  1726. void ueol();
  1727. void upedge();
  1728. void unedge();
  1729. X
  1730. void ultarw();
  1731. void urtarw();
  1732. X
  1733. void uprvwrd();
  1734. void unxtwrd();
  1735. X
  1736. void uuparw();
  1737. void udnarw();
  1738. X
  1739. void upgup();
  1740. void upgdn();
  1741. void uupslide();
  1742. void udnslide();
  1743. X
  1744. void uline();
  1745. X
  1746. void utomatch();
  1747. X
  1748. void uopen();
  1749. void uinsc();
  1750. X
  1751. void udelch();
  1752. void ubacks();
  1753. X
  1754. void udelw();
  1755. void ubackw();
  1756. X
  1757. void udelel();
  1758. void udelbl();
  1759. void udelln();
  1760. X
  1761. void uquote();
  1762. void uquote8();
  1763. void urtn();
  1764. void utype();
  1765. X
  1766. void ucenter();
  1767. void uformat();
  1768. X
  1769. void uirmargin();
  1770. void uilmargin();
  1771. void uitype();
  1772. void uiwrap();
  1773. void uiindent();
  1774. void uipgamnt();
  1775. void uimid();
  1776. void uiforce();
  1777. void uiasis();
  1778. void uistarow();
  1779. void uistacol();
  1780. void uitab();
  1781. void uisquare();
  1782. void uiistep();
  1783. void uicindent();
  1784. void utag();
  1785. X
  1786. #endif
  1787. SHAR_EOF
  1788. chmod 0600 edfuncs.h ||
  1789. echo 'restore of edfuncs.h failed'
  1790. Wc_c="`wc -c < 'edfuncs.h'`"
  1791. test 1933 -eq "$Wc_c" ||
  1792.     echo 'edfuncs.h: original size 1933, current size' "$Wc_c"
  1793. fi
  1794. # ============= heap.c ==============
  1795. if test -f 'heap.c' -a X"$1" != X"-c"; then
  1796.     echo 'x - skipping heap.c (File already exists)'
  1797. else
  1798. echo 'x - extracting heap.c (Text)'
  1799. sed 's/^X//' << 'SHAR_EOF' > 'heap.c' &&
  1800. /* Fast space-efficient heap manager
  1801. X   Copyright (C) 1992 Joseph H. Allen
  1802. X
  1803. This file is part of JOE (Joe's Own Editor)
  1804. X
  1805. JOE is free software; you can redistribute it and/or modify it under the 
  1806. terms of the GNU General Public License as published by the Free Software 
  1807. Foundation; either version 1, or (at your option) any later version.  
  1808. X
  1809. JOE is distributed in the hope that it will be useful, but WITHOUT ANY 
  1810. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  1811. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  1812. details.  
  1813. X
  1814. You should have received a copy of the GNU General Public License along with 
  1815. JOE; see the file COPYING.  If not, write to the Free Software Foundation, 
  1816. 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
  1817. X
  1818. #include "blocks.h"
  1819. #include "random.h"
  1820. #include "heap.h"
  1821. X
  1822. #define MAXSIZE (MAXINT-16)
  1823. X
  1824. /* A free block of memory */
  1825. X
  1826. typedef struct freeblck FREE;
  1827. struct freeblck
  1828. X {
  1829. X int size;        /* Includes self, +1 for allocated blocks */
  1830. X             /* Equals '1' for end of heap or segment */
  1831. X FREE *next;        /* Data part of allocated blocks begins here */
  1832. X FREE *prev;
  1833. X };
  1834. X
  1835. static int reent=0;    /* Set if freeit is reentering itself */
  1836. void *sbrk();        /* Operating system memory allocator */
  1837. void (*mtrap)()=0;    /* Memory overflow handler */
  1838. static trapflag=0;    /* Set while handling an overflow condition */
  1839. X
  1840. static char *heapend=0;    /* Top of heap */
  1841. X
  1842. /* A skiplist entry */
  1843. X
  1844. struct skipnode
  1845. X {
  1846. X int key;
  1847. X int nptrs;
  1848. X FREE *value;
  1849. X struct skipnode *ptrs[1];
  1850. X };
  1851. X
  1852. /* Max number of pointers in a skiplist node */
  1853. #define SKIPDPTH 16
  1854. X
  1855. static struct skipnode *freeones[SKIPDPTH+1];    /* Free lists of skip nodes */
  1856. static struct skipnode *top=0;            /* Skip list root node */
  1857. static struct skipnode nil;            /* Ending skiplist node */
  1858. static struct skipnode *update[SKIPDPTH];    /* Record of search path */
  1859. X
  1860. /* Memory allocator for skip-list nodes */
  1861. X
  1862. static char *big=0;
  1863. static int bigx=0;
  1864. X
  1865. /* Allocation amount for skiplist data */
  1866. #define SKIPCHNK 256
  1867. X
  1868. /* Key is for recomputing skip-list search after a reentrant malloc */
  1869. X
  1870. static struct skipnode *skipa(x,key)
  1871. int x, key;
  1872. {
  1873. struct skipnode *t;
  1874. int amnt;
  1875. if(freeones[x])
  1876. X {
  1877. X t=freeones[x];
  1878. X freeones[x]=(struct skipnode *)t->value;
  1879. X return t;
  1880. X }
  1881. amnt=sizeof(struct skipnode)+sizeof(struct skipnode *)*(x-1);
  1882. if(bigx+amnt>SKIPCHNK || !big)
  1883. X {
  1884. X reent=1;
  1885. X big=(char *)malloc(SKIPCHNK);
  1886. X if(key)
  1887. X  {
  1888. X  struct skipnode *t=top;
  1889. X  int y;
  1890. X  for(y=top->nptrs;--y>=0;)
  1891. X   {
  1892. X   while(t->ptrs[y]->key<key) t=t->ptrs[y];
  1893. X   update[y]=t;
  1894. X   }
  1895. X  }
  1896. X reent=0;
  1897. X bigx=0;
  1898. X }
  1899. t=(struct skipnode *)(big+bigx);
  1900. bigx+=amnt;
  1901. return t;
  1902. }
  1903. X
  1904. /* Free a skip node */
  1905. X
  1906. static void freea(t)
  1907. struct skipnode *t;
  1908. {
  1909. t->value=(FREE *)freeones[t->nptrs];
  1910. freeones[t->nptrs]=t;
  1911. }
  1912. X
  1913. /* Insert a free block into the free-list */
  1914. X
  1915. static void freeit(b)
  1916. FREE *b;
  1917. {
  1918. struct skipnode *t=top;
  1919. int x;
  1920. b=normalize(b);
  1921. for(x=top->nptrs;--x>=0;)
  1922. X {
  1923. X while(t->ptrs[x]->key<b->size) t=t->ptrs[x];
  1924. X update[x]=t;
  1925. X }
  1926. t=t->ptrs[0];
  1927. if(t->key==b->size)
  1928. X {
  1929. X b->next=t->value;
  1930. X b->prev=0;
  1931. X t->value->prev=b;
  1932. X t->value=b;
  1933. X }
  1934. else
  1935. X {
  1936. X int level;
  1937. X for(level=1;random()<0x29000000;++level);
  1938. X if(level>15) level=15;
  1939. X b->size+=1;
  1940. X t=(struct skipnode *)skipa(level,b->size-1);
  1941. X b->size-=1;
  1942. X while(level>top->nptrs) update[top->nptrs++]=top;
  1943. X t->nptrs=level;
  1944. X for(x=0;x!=level;++x) t->ptrs[x]=update[x]->ptrs[x], update[x]->ptrs[x]=t;
  1945. X t->key=b->size;
  1946. X t->value=b;
  1947. X b->next=0; b->prev=0;
  1948. X }
  1949. }
  1950. X
  1951. /* Remove an element from the free list */
  1952. X
  1953. static void unfreeit(b)
  1954. FREE *b;
  1955. {
  1956. struct skipnode *t;
  1957. int y;
  1958. if(b->prev)
  1959. X {
  1960. X if(b->prev->next=b->next) b->next->prev=b->prev;
  1961. X return;
  1962. X }
  1963. t=top;
  1964. for(y=top->nptrs;--y>=0;)
  1965. X {
  1966. X while(t->ptrs[y]->key<b->size) t=t->ptrs[y];
  1967. X update[y]=t;
  1968. X }
  1969. t=t->ptrs[0];
  1970. if(b->next) b->next->prev=0, t->value=b->next;
  1971. else
  1972. X {
  1973. X int x;
  1974. X for(x=0;x!=top->nptrs && update[x]->ptrs[x]==t;++x)
  1975. X  update[x]->ptrs[x]=t->ptrs[x];
  1976. X while(top->nptrs && top->ptrs[top->nptrs-1]==&nil) --top->nptrs;
  1977. X freea(t);
  1978. X }
  1979. }
  1980. X
  1981. void *malloc(size)
  1982. {
  1983. int x;
  1984. int flg=0, y;
  1985. FREE *b;
  1986. struct skipnode *t;
  1987. if(!top)
  1988. X {
  1989. X nil.key=MAXINT;
  1990. X nil.nptrs=0;
  1991. X nil.ptrs[0]= &nil;
  1992. X top= &nil;
  1993. X top=(struct skipnode *)skipa(16,0);
  1994. X top->key=0;
  1995. X top->nptrs=0;
  1996. X for(x=0;x!=16;++x) top->ptrs[x]= &nil;
  1997. X }
  1998. size+=sizeof(int);
  1999. if(size<sizeof(FREE)) size=sizeof(FREE);
  2000. size=(size+sizeof(int)-1)&~(sizeof(int)-1);
  2001. loop:
  2002. b=0;
  2003. t=top;
  2004. for(y=top->nptrs;--y>=0;)
  2005. X {
  2006. X while(t->ptrs[y]->key<size) t=t->ptrs[y];
  2007. X update[y]=t;
  2008. X }
  2009. t=t->ptrs[0];
  2010. if(t->key!= MAXINT)
  2011. X {
  2012. X b=t->value;
  2013. X if(b->next) b->next->prev=0, t->value=b->next;
  2014. X else
  2015. X  {
  2016. X  for(x=0;x!=top->nptrs && update[x]->ptrs[x]==t;++x)
  2017. X   update[x]->ptrs[x]=t->ptrs[x];
  2018. X  while(top->nptrs && top->ptrs[top->nptrs-1]==&nil) --top->nptrs;
  2019. X  freea(t);
  2020. X  }
  2021. X }
  2022. if(b)
  2023. X {
  2024. X while(!(1&*(int *)((char *)b+b->size)))
  2025. X  {
  2026. X  FREE *c=(FREE *)((char *)b+b->size);
  2027. X  if((long)b->size+(long)c->size>=MAXSIZE) break;
  2028. X  b->size+=c->size;
  2029. X  unfreeit(c);
  2030. X  }
  2031. X if(normalize((char *)b+b->size)+sizeof(int)==heapend)
  2032. X  {
  2033. X  sbrk(-b->size);
  2034. X  heapend=(char *)b;
  2035. X  b->size=1;
  2036. X  goto loop;
  2037. X  }
  2038. X if((b->size-size)>=(size>>2) && b->size-size>=sizeof(FREE) && !reent)
  2039. X  {
  2040. X  FREE *c=(FREE *)((char *)b+size);
  2041. X  c->size=b->size-size;
  2042. X  b->size=size|1;
  2043. X  freeit(c);
  2044. X  }
  2045. X else b->size|=1;
  2046. X if(flg) trapflag=0;
  2047. X return (void *)((char *)b+sizeof(int));
  2048. X }
  2049. b=(FREE *)sbrk(size+sizeof(int));
  2050. if(!b || b==((FREE *)(long)-1))
  2051. X {
  2052. X if(mtrap && !trapflag)
  2053. X  {
  2054. X  trapflag=1;
  2055. X  flg=1;
  2056. X  mtrap(size);
  2057. X  goto loop;
  2058. X  }
  2059. X write(2,"\rOut of memory\r\n",16);
  2060. X _exit(1);
  2061. X }
  2062. b=normalize(b);
  2063. if(normalize(heapend)==(char *)b)
  2064. X {
  2065. X b=(FREE *)(heapend-sizeof(int));
  2066. X size+=sizeof(int);
  2067. X }
  2068. heapend=normalize((char *)b+size)+sizeof(int);
  2069. *((int *)heapend-1)=1;
  2070. b->size=size|1;
  2071. if(flg) trapflag=0;
  2072. return (void *)((char *)b+sizeof(int));
  2073. }
  2074. X
  2075. void *memalign(align,size)
  2076. int align,size;
  2077. {
  2078. FREE *b;
  2079. char *blk;
  2080. int off;
  2081. size+=sizeof(int);
  2082. if(size<sizeof(FREE)) size=sizeof(FREE);
  2083. size=(size+sizeof(int)-1)&~(sizeof(int)-1);
  2084. align=(align+sizeof(int)-1)&~(sizeof(int)-1);
  2085. if(!align) align=sizeof(int);
  2086. if(size>=align) blk=(char *)malloc(size+align+sizeof(FREE));
  2087. else blk=(char *)malloc(align*2+sizeof(FREE));
  2088. off=physical(blk)%align;
  2089. if(off)
  2090. X {
  2091. X b=(FREE *)(blk-sizeof(int));
  2092. X if(align-off>=sizeof(FREE)) blk+=align-off;
  2093. X else blk+=2*align-off;
  2094. X *((int *)blk-1)=b->size-(blk-sizeof(int)-(char *)b);
  2095. X b->size-= *((int *)blk-1);
  2096. X freeit(b);
  2097. X }
  2098. b=normalize((FREE *)(blk-sizeof(int)));
  2099. if((b->size-1-size)>=(size>>2) && b->size-1-size>=sizeof(FREE))
  2100. X {
  2101. X FREE *c=(FREE *)((char *)b+size);
  2102. X c->size=b->size-1-size;
  2103. X b->size=size+1;
  2104. X freeit(c);
  2105. X }
  2106. return (char *)b+sizeof(int);
  2107. }
  2108. X
  2109. void *realloc(blk,size)
  2110. void *blk;
  2111. int size;
  2112. {
  2113. FREE *b;
  2114. int osize;
  2115. if(!blk) return malloc(size);
  2116. b=(FREE *)((char *)blk-sizeof(int));
  2117. osize=b->size-1-sizeof(int);
  2118. size+=sizeof(int);
  2119. if(size<sizeof(FREE)) size=sizeof(FREE);
  2120. size=(size+sizeof(int)-1)&~(sizeof(int)-1);
  2121. while(!(1&*(int *)((char *)b+b->size-1)))
  2122. X {
  2123. X FREE *c=(FREE *)((char *)b+b->size-1);
  2124. X if((long)b->size+(long)c->size>=MAXSIZE) break;
  2125. X b->size+=c->size;
  2126. X unfreeit(c);
  2127. X }
  2128. if(size<=b->size-1)
  2129. X {
  2130. X if(b->size-1-size>size && b->size-1-size>=sizeof(FREE))
  2131. X  {
  2132. X  FREE *c=(FREE *)((char *)b+size);
  2133. X  c->size=b->size-size-1;
  2134. X  b->size=size+1;
  2135. X  freeit(c);
  2136. X  }
  2137. X return blk;
  2138. X }
  2139. else
  2140. X {
  2141. X char *n=(char *)malloc(size);
  2142. X FREE *c=(FREE *)(n-sizeof(int));
  2143. X if(normalize((char *)c+c->size-1)+sizeof(int)==heapend &&
  2144. X    (FREE *)normalize(((char *)b+b->size-1))==c)
  2145. X  {
  2146. X  sbrk(-(c->size-1+b->size-1-size));
  2147. X  b->size=size+1;
  2148. X  heapend=normalize((char *)b+b->size-1)+sizeof(int);
  2149. X  *((int *)heapend-1)=1;
  2150. X  return blk;
  2151. X  }
  2152. X mcpy(n,blk,osize);
  2153. X free(blk);
  2154. X return (void *)n;
  2155. X }
  2156. }
  2157. X
  2158. void free(blk)
  2159. void *blk;
  2160. {
  2161. FREE *b;
  2162. if(!blk) return;
  2163. b=(FREE *)((char *)blk-sizeof(int));
  2164. b->size-=1;
  2165. while(!(1&*(int *)((char *)b+b->size)))
  2166. X {
  2167. X FREE *c=(FREE *)((char *)b+b->size);
  2168. X if((long)b->size+(long)c->size>=MAXSIZE) break;
  2169. X b->size+=c->size;
  2170. X unfreeit(c);
  2171. X }
  2172. if(normalize((char *)b+b->size)+sizeof(int)==heapend)
  2173. X {
  2174. X heapend=(char *)b+sizeof(int);
  2175. X sbrk(-b->size);
  2176. X b->size=1;
  2177. X }
  2178. else freeit(b);
  2179. }
  2180. X
  2181. void *calloc(a,b)
  2182. int a,b;
  2183. {
  2184. return (void *)mset((char *)malloc(a*b),0,a*b);
  2185. }
  2186. SHAR_EOF
  2187. chmod 0600 heap.c ||
  2188. echo 'restore of heap.c failed'
  2189. Wc_c="`wc -c < 'heap.c'`"
  2190. test 8056 -eq "$Wc_c" ||
  2191.     echo 'heap.c: original size 8056, current size' "$Wc_c"
  2192. fi
  2193. # ============= heap.h ==============
  2194. if test -f 'heap.h' -a X"$1" != X"-c"; then
  2195.     echo 'x - skipping heap.h (File already exists)'
  2196. else
  2197. echo 'x - extracting heap.h (Text)'
  2198. sed 's/^X//' << 'SHAR_EOF' > 'heap.h' &&
  2199. /* Fast space-efficient heap maneger
  2200. X   Copyright (C) 1992 Joseph H. Allen
  2201. X
  2202. This file is part of JOE (Joe's Own Editor)
  2203. X
  2204. JOE is free software; you can redistribute it and/or modify it under the 
  2205. terms of the GNU General Public License as published by the Free Software 
  2206. Foundation; either version 1, or (at your option) any later version.  
  2207. X
  2208. JOE is distributed in the hope that it will be useful, but WITHOUT ANY 
  2209. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  2210. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  2211. details.  
  2212. X
  2213. You should have received a copy of the GNU General Public License along with 
  2214. JOE; see the file COPYING.  If not, write to the Free Software Foundation, 
  2215. 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
  2216. X
  2217. /* - Uses "best-fit" algorithm- but maintains a fast skip-list database of each
  2218. X *   set of equal sized free blocks.  This eliminates the long linked-list
  2219. X *   search delay which slows the "best-fit" algorithm.
  2220. X * - Contiguous free blocks get coalesced
  2221. X * - Gives memory back to operating system when it can
  2222. X * - Overhead for allocated blocks: sizeof(int)
  2223. X * - Minimum allocated block size is 2*sizeof(int) (not including overhead)
  2224. X * - Blocks are always aligned on integer boundaries
  2225. X * - Macro provided for reading block size
  2226. X * - 'memalign' routine provided for allocating blocks on a given alignment
  2227. X * - Works ok in segmented systems or where sbrk() is called by other functions
  2228. X */
  2229. X
  2230. #ifndef _Iheap
  2231. #define _Iheap 1
  2232. X
  2233. #include "config.h"
  2234. X
  2235. /* void (*mtrap)(int size);
  2236. X *
  2237. X * If 'mtrap' is set to 0 (it's default value), then if the system runs
  2238. X * out of memory, an error message is sent to stderr and the program is
  2239. X * aborted.
  2240. X *
  2241. X * If 'mtrap' is set to the address of a function, then that function gets
  2242. X * one chance (mtrap will only ever be called once for each out of memory
  2243. X * condition and it will never be reentered) to free up at least 'size' bytes
  2244. X * of memory.  If 'mtrap' doesn't free up the memory or if there isn't enough
  2245. X * contiguous space to satisfy the allocation request, the default action is
  2246. X * taken.  The 'mtrap' function may call the memory allocation routines (but
  2247. X * hopefully with smaller requests :-).
  2248. X */
  2249. extern void (*mtrap)();
  2250. X
  2251. /* void *malloc(int size);
  2252. X *
  2253. X * Allocate a block of at least 'size' bytes from the heap.  If 'size' is zero,
  2254. X * a small block is allocated.
  2255. X *
  2256. X * The allocated block will begin on an address which is a multiple of
  2257. X * sizeof(int).
  2258. X */
  2259. void *malloc();
  2260. X
  2261. /* void *calloc(int a,int b);
  2262. X *
  2263. X * Allocate a block of at least 'a'*'b' bytes from the heap.  The first 'a'*'b'
  2264. X * bytes are cleared.  If 'a'*'b' is zero, a small block is allocated (and it
  2265. X * is not cleared).
  2266. X *
  2267. X * The allocated block will begin on an address which is a multiple of
  2268. X * sizeof(int).
  2269. X */
  2270. void *calloc();
  2271. X
  2272. /* void *realloc(void *blk,int size);
  2273. X *
  2274. X * Modify amount allocated to 'blk' to 'size' and return pointer to block
  2275. X * (which might be at a different address).  If 'size' is zero, a small amount
  2276. X * is left allocated to the block.  If 'blk' is null, a new block is allocated.
  2277. X *
  2278. X * The allocated block will begin on an address which is a multiple of
  2279. X * sizeof(int).
  2280. X */
  2281. void *realloc();
  2282. X
  2283. /* void free(void *blk);
  2284. X *
  2285. X * Return a block to the heap so that it can be reused.  If 'blk'==0,
  2286. X * nothing happens.
  2287. X */
  2288. void free();
  2289. X
  2290. /* void *memalign(int align,int size);
  2291. X *
  2292. X * Allocate a block of at least 'size' bytes beginning on an address which
  2293. X * is a multiple of 'align'.  'align' is rounded up to a multiple of
  2294. X * sizeof(int).  If 'size' is zero, a small block is allocated.
  2295. X */
  2296. void *memalign();
  2297. X
  2298. /* int msize(void *blk);
  2299. X *
  2300. X * Return size of a block returned by malloc/realloc/calloc/memalign.  Returns
  2301. X * zero if 'blk' is 0.  Warning: this is an unsafe macro (blk can be
  2302. X * accessed more than once).
  2303. X */
  2304. #define msize(blk) ((blk)?*((int *)(blk)-1)-(1+sizeof(int)):0)
  2305. X
  2306. #endif
  2307. SHAR_EOF
  2308. chmod 0600 heap.h ||
  2309. echo 'restore of heap.h failed'
  2310. Wc_c="`wc -c < 'heap.h'`"
  2311. test 3883 -eq "$Wc_c" ||
  2312.     echo 'heap.h: original size 3883, current size' "$Wc_c"
  2313.