home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3966 < prev    next >
Text File  |  1991-09-03  |  32KB  |  2,017 lines

  1. Newsgroups: alt.sources
  2. Path: wupost!zaphod.mps.ohio-state.edu!qt.cs.utexas.edu!yale.edu!cmcl2!sbcs.sunysb.edu!libserv1.ic.sunysb.edu!jallen
  3. From: jallen@libserv1.ic.sunysb.edu (Joseph Allen)
  4. Subject: JOE Version 0.1.0: Part 2 of 3
  5. Message-ID: <1991Sep3.204854.10598@sbcs.sunysb.edu>
  6. Originator: jallen@libserv1.ic.sunysb.edu
  7. Sender: rcarter@wpi.wpi.edu
  8. Nntp-Posting-Host: libserv1.ic.sunysb.edu
  9. Organization: State University of New York at Stony Brook
  10. Date: Tue, 3 Sep 1991 20:48:54 GMT
  11.  
  12. unsigned char *bset();
  13. unsigned char *bmove();
  14. unsigned char *bfwrd();
  15. unsigned char *bbkwd();
  16. unsigned umin();
  17. unsigned umax();
  18. int min();
  19. int max();
  20. int beq();
  21. int bieq();
  22. unsigned char *bchr();
  23. unsigned char *brchr();
  24. SHAR_EOF
  25. if test 1012 -ne "`wc -c < 'blocks.h'`"
  26. then
  27.     echo shar: error transmitting "'blocks.h'" '(should have been 1012 characters)'
  28. fi
  29. fi # end of overwriting check
  30. if test -f 'cruddy.c'
  31. then
  32.     echo shar: will not over-write existing file "'cruddy.c'"
  33. else
  34. cat << \SHAR_EOF > 'cruddy.c'
  35. /* Cruddy terminal interface - should be very portable though
  36.    Copyright (C) 1991 Joseph H. Allen
  37.  
  38. This file is part of JOE (Joe's Own Editor)
  39.  
  40. JOE is free software; you can redistribute it and/or modify it under the terms
  41. of the GNU General Public License as published by the Free Software
  42. Foundation; either version 1, or (at your option) any later version. 
  43.  
  44. JOE is distributed in the hope that it will be useful, but WITHOUT ANY
  45. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  46. A PARTICULAR PURPOSE.  See the GNU General Public License for more details.  
  47.  
  48. You should have received a copy of the GNU General Public License
  49. along with JOE; see the file COPYING.  If not, write to
  50. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  51.  
  52.  
  53. #include <stdio.h>
  54. #include <signal.h>
  55. #include "async.h"
  56.  
  57. int have=0;
  58.  
  59. eputs(s)
  60. char *s;
  61. {
  62. fputs(s,stdout);
  63. }
  64.  
  65. eputc(c)
  66. {
  67. putchar(c);
  68. }
  69.  
  70. aopen()
  71. {
  72. fflush(stdout);
  73. system("/bin/stty raw -echo");
  74. signal(SIGHUP,tsignal);
  75. signal(SIGINT,SIG_IGN);
  76. signal(SIGQUIT,SIG_IGN);
  77. signal(SIGPIPE,SIG_IGN);
  78. signal(SIGALRM,SIG_IGN);
  79. signal(SIGTERM,tsignal);
  80. signal(SIGUSR1,SIG_IGN);
  81. signal(SIGUSR2,SIG_IGN);
  82. }
  83.  
  84. aclose()
  85. {
  86. fflush(stdout);
  87. signal(SIGHUP,SIG_DFL);
  88. signal(SIGINT,SIG_DFL);
  89. signal(SIGQUIT,SIG_DFL);
  90. signal(SIGPIPE,SIG_DFL);
  91. signal(SIGALRM,SIG_DFL);
  92. signal(SIGTERM,SIG_DFL);
  93. signal(SIGUSR1,SIG_DFL);
  94. signal(SIGUSR2,SIG_DFL);
  95. system("/bin/stty cooked echo");
  96. }
  97.  
  98. aflush()
  99. {
  100. }
  101.  
  102. anext()
  103. {
  104. unsigned char c;
  105. fflush(stdout);
  106. while(read(fileno(stdin),&c,1)!=1);
  107. return c;
  108. }
  109.  
  110. getsize()
  111. {
  112. }
  113.  
  114. termtype()
  115. {
  116. }
  117.  
  118. shell(s)
  119. char *s;
  120. {
  121. aclose();
  122. if(fork()) wait(0);
  123. else
  124.  {
  125.  execl(s,s,0);
  126.  _exit(0);
  127.  }
  128. aopen();
  129. }
  130. SHAR_EOF
  131. if test 1682 -ne "`wc -c < 'cruddy.c'`"
  132. then
  133.     echo shar: error transmitting "'cruddy.c'" '(should have been 1682 characters)'
  134. fi
  135. fi # end of overwriting check
  136. if test -f 'joe.1'
  137. then
  138.     echo shar: will not over-write existing file "'joe.1'"
  139. else
  140. cat << \SHAR_EOF > 'joe.1'
  141. ..TH JOE 1
  142. ..SH NAME
  143. joe \- Joe's Own Editor
  144. ..SH SYNOPSIS
  145. ..B joe file
  146. ..br
  147. ..BR joe
  148. ..SH DESCRIPTION
  149. JOE is a screen editor designed to be easy to learn for novice users and
  150. powerfull enough for experienced users.  After you invoke the editor, you can
  151. hit ^K H ('^' mean hold the Ctrl key down while pressing the following key) to
  152. turn on the help text.  From this you should be able to figure out how to use
  153. the editor.  A few things need further explanation however:
  154.  
  155. JOE uses the "TERM" environment entry and termcap to determine the height and
  156. width of the screen and to determine if the terminal uses scrolling regions. 
  157. Except for these differences the terminal must be ANSI/VT100 compatible.
  158.  
  159. Be sure that the baud rate as reported by stty is correct.  JOE uses this
  160. to optimize its screen writes.  If you're going over a network, set the
  161. baud rate to your best estimate of the actual througput.  If you're using
  162. JOE in a window, set the baud rate to the highest possible (usually
  163. 'stty extb' or 'stty 38400').
  164.  
  165. ^K J reformats the current paragraph.  ^T R can be used to change the right
  166. margin.  The default is the width of the screen.  If auto-indent mode is set,
  167. indented paragraphs are formated.
  168.  
  169. Use ^K B to set the beginning of a block and ^K K to set the end of a block. 
  170. You can then copy, move save or delete the marked blocks.  To turn the
  171. highlighting off, hit ^K B ^K K (make the beginning and ending the same or
  172. move the beginning past the ending or move the ending before the beginning).
  173.  
  174. ^K O splits a window into two.  You can then use ^K E to load a file into the
  175. new window.  ^K I shows either one window or it shows all of the windows.  Use
  176. ^C to eliminate a window.
  177.  
  178. Control characters (0-31, 127) are shown underlined.  Characters above 127 are
  179. shown in inverse.  You can use ` and ^\ to enter control characters
  180. orcharacters with the 7th bit set.
  181.  
  182. Hit ^K F to find text.  You will be prompted to enter the search string. 
  183. After hitting Return, you will be prompted for options- you can type 1 or more
  184. of:  
  185.  
  186. ..br
  187.             i    Ignore case
  188. ..br
  189.             b    Backwards
  190. ..br
  191.             r    Replace
  192. ..br
  193.             nnn    Find the nth occurance or do nnn replacements
  194. ..br
  195.  
  196.         If you hit r, you will also be prompted to enter the
  197.         replacement string.
  198.  
  199.         Hit ^L to find the next occurance of the previous search
  200.         string (with all the same options).
  201.  
  202. If for some reason JOE gets a signal (that it's going to crash or that the
  203. system is messing up), it attempts to save the last file edited in a file
  204. "aborted" in the current directory.
  205.  
  206. ..SH FILES
  207. ..DT
  208. ..ta 25n
  209.  
  210.  \.joerc             Initialization file.  JOE looks for
  211. ..br
  212.                 this in the current directory, the
  213. ..br
  214.                 user's home directory and in the 
  215. ..br
  216.                 directory containing JOE
  217.  
  218. ..SH RESTRICTIONS
  219.  
  220. The file size is limited to the system process size limit 
  221.  
  222. ..SH BUGS
  223. Send bug reports to rcarter@wpi.wpi.edu (Joseph H. Allen).  This should be
  224. valid to at least January, 1991.  You can also contact me through snail mail:
  225.  
  226. ..br
  227.         Joseph H. Allen
  228. ..br
  229.         28 Dale Lane
  230. ..br
  231.         Smithtown, N.Y. 11787
  232. SHAR_EOF
  233. if test 3013 -ne "`wc -c < 'joe.1'`"
  234. then
  235.     echo shar: error transmitting "'joe.1'" '(should have been 3013 characters)'
  236. fi
  237. fi # end of overwriting check
  238. if test -f 'joe.c'
  239. then
  240.     echo shar: will not over-write existing file "'joe.c'"
  241. else
  242. cat << \SHAR_EOF > 'joe.c'
  243. /* JOE - Joe's Own Editor - the bulk of the code is here
  244.    Copyright (C) 1991 Joseph H. Allen
  245.  
  246. This file is part of JOE (Joe's Own Editor)
  247.  
  248. JOE is free software; you can redistribute it and/or modify it under the terms
  249. of the GNU General Public License as published by the Free Software
  250. Foundation; either version 1, or (at your option) any later version.  
  251.  
  252. JOE is distributed in the hope that it will be useful, but WITHOUT ANY
  253. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  254. A PARTICULAR PURPOSE.  See the GNU General Public License for more details.  
  255.  
  256. You should have received a copy of the GNU General Public License
  257. along with JOE; see the file COPYING.  If not, write to
  258. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  259.  
  260. #include <stdio.h>
  261. /* #include <stdlib.h> */
  262. #include <string.h>
  263. #include <sys/types.h>
  264. #include <sys/stat.h>
  265. #include <errno.h>
  266. #include <pwd.h>
  267. extern errno;
  268. #include "async.h"
  269. #include "blocks.h"
  270. #include "joe.h"
  271. int width=80;
  272. int height=24;
  273. int scroll=1;
  274.  
  275. unsigned char stalin[PATHSIZE];
  276.  
  277. int smode=0;
  278. int tops=0;
  279. int bots;
  280. int oxpos=0;            /* Current cursor position */
  281. int oypos=0;
  282. int *scrn;            /* Screen buffer address */
  283.  
  284. unsigned char *omsg=0;           /* Pointer to opening message */
  285.  
  286. dopen()
  287. {
  288. int x;
  289. unsigned char buf[30];
  290. scrn=(int *)malloc(width*height*sizeof(int));
  291. for(x=0;x<width*height;x++) scrn[x]= ' ';
  292. if(scroll)
  293.  {
  294.  sprintf(buf,"\033[0m\033[1;%dr\033[H\033[J",height), eputs(buf);
  295.  bots=height-1;
  296.  }
  297. else eputs("\033[0m\033[H\033[J");
  298. }
  299.  
  300. dclose(ms)
  301. unsigned char *ms;
  302. {
  303. setregn(0,height-1);
  304. cpos(height-1,0);
  305. attrib(0);
  306. eputs(ms);
  307. eputs("\033[K");
  308. oxpos=strlen(ms);
  309. cpos(height-1,0);
  310. eputc(10);
  311. }
  312.  
  313. resize()
  314. {
  315. int x;
  316. unsigned char buf[30];
  317. free(scrn);
  318. scrn=(int *)malloc(width*height*sizeof(int));
  319. for(x=0;x<width*height;x++) scrn[x]= ' ';
  320. if(scroll)
  321.  {
  322.  sprintf(buf,"\033[0m\033[1;%dr\033[H\033[J",height), eputs(buf);
  323.  bots=height-1;
  324.  }
  325. else eputs("\033[0m\033[H\033[J");
  326. smode=0;
  327. if(wind>height-3) wind=height-3;
  328. if(wind) hupd=1;
  329. wfit();
  330. upd=1;
  331. }
  332.  
  333. cposs(y,x)
  334. {
  335. unsigned char s[9];
  336. if(y>bots || y<tops) setregn(0,height-1);
  337. if(y==oypos)
  338.  {
  339.  if(x==oxpos) return;
  340.  if(x==0)
  341.   {
  342.   eputc(13);
  343.   return;
  344.   }
  345.  if(oxpos>=x+1 && oxpos<=x+4)
  346.   {
  347.   while(oxpos!=x) eputc(8), x++;
  348.   return;
  349.   }
  350.  if(x>=oxpos+1 && x<=oxpos+4)
  351.   {
  352.   while(x!=oxpos) tputcc(scrn[oypos*width+oxpos++]);
  353.   return;
  354.   }
  355.  if(x>oxpos)
  356.   sprintf(s,"\033[%dC",x-oxpos);
  357.  else
  358.   sprintf(s,"\033[%dD",oxpos-x);
  359.  eputs(s);
  360.  return;
  361.  }
  362. if(x==oxpos)
  363.  {
  364.  if(y>=oypos+1 && y<=oypos+4)
  365.   {
  366.   while(y!=oypos) /* acheck(), */ eputc(10), oypos++;
  367.   return;
  368.   }
  369.  if(y==0 && x==0)
  370.   {
  371.   eputs("\033[H");
  372.   return;
  373.   }
  374.  if(y>oypos)
  375.   sprintf(s,"\033[%dB",y-oypos);
  376.  else
  377.   sprintf(s,"\033[%dA",oypos-y);
  378.  eputs(s);
  379.  return;
  380.  }
  381. if(x<3 && y>oypos && y<oypos+5)
  382.  {
  383.  while(oypos!=y) ++oypos, eputc('\012');
  384.  eputc('\015'); oxpos=0;
  385.  while(x!=oxpos) tputcc(scrn[oypos*width+oxpos++]);
  386.  return;
  387.  }
  388. if(x==0 && y==0)
  389.  {
  390.  eputs("\033[H");
  391.  return;
  392.  }
  393. if(x==0)
  394.  {
  395.  sprintf(s,"\033[%dH",y+1);
  396.  eputs(s);
  397.  return;
  398.  }
  399. sprintf(s,"\033[%d;%dH",y+1,x+1);
  400. eputs(s);
  401. return;
  402. }
  403.  
  404. cpos(y,x)
  405. {
  406. cposs(y,x);
  407. oxpos=x;
  408. oypos=y;
  409. }
  410.  
  411. setregn(top,bot)
  412. {
  413. unsigned char sst[16];
  414. if(top!=tops || bots!=bot)
  415.  {
  416.  tops=top;
  417.  bots=bot;
  418.  if(scroll)
  419.   {
  420.   oxpos=0;
  421.   oypos=0;
  422.   sprintf(sst,"\033[%d;%dr",top+1,bot+1);
  423.   eputs(sst);
  424.   }
  425.  }
  426. }
  427.  
  428. attrib(x)
  429. {
  430. if(smode== -1) goto clr;
  431. if(!(x&INVERSE) && (smode&INVERSE)) goto clr;
  432. if(!(x&BLINK) && (smode&BLINK)) goto clr;
  433. if(!(x&UNDERLINE) && (smode&UNDERLINE)) goto clr;
  434. if(!(x&BOLD) && (smode&BOLD)) goto clr;
  435. goto ovr;
  436. clr:
  437. smode=0;
  438. eputs("\033[m");
  439. ovr:
  440. if(x&INVERSE && !(smode&INVERSE)) eputs("\033[7m");
  441. if(x&BLINK && !(smode&BLINK)) eputs("\033[5m");
  442. if(x&UNDERLINE && !(smode&UNDERLINE)) eputs("\033[4m");
  443. if(x&BOLD && !(smode&BOLD)) eputs("\033[1m");
  444. smode=x;
  445. }
  446.  
  447. int uuu=0;
  448. int cntr=0;
  449. int upd=1;
  450. int hupd=0;
  451. int newy=1;
  452. int helpon=0;
  453. int wind=0;
  454. int xpos=0;
  455. int ypos=0;
  456. TXTSIZ saddr=0;
  457. TXTSIZ xoffset=0;
  458.  
  459. unsigned char *help=0;
  460. int helplines=0;
  461. int helpsize=0;
  462. int helpblksize=0;
  463.  
  464. /* Clear end of line if needed.  i is row number and j is column number */
  465.  
  466. clreolchk(i,j)
  467. TXTSIZ j;
  468. {
  469. int *k=scrn+i*width;
  470. int t, jj;
  471. if(j<xoffset) jj=0;
  472. else
  473.  if(j>=xoffset+width-1) return;
  474.  else jj=j-xoffset;
  475. for(t=width-1;t>=jj;--t) if(k[t]!=' ') goto ohoh;
  476. return;
  477. ohoh:
  478. if(t==jj)
  479.  {
  480.  cpos(i,jj);
  481.  tputcc(' ');
  482.  k[jj]=' ';
  483.  oxpos++;
  484.  return;
  485.  }
  486. while(t>=jj) k[t--]=' ';
  487. cpos(i,jj);
  488. attrib(0);
  489. eputs("\033[K");
  490. }
  491.  
  492. /* Change buffer character to displayable form */
  493.  
  494. showas(ch)
  495. {
  496. #ifdef NOHIGHBIT
  497. if(ch>=128)
  498.  {
  499.  ch&=127;
  500.  ch|=INVERSE;
  501.  }
  502. #endif
  503. if((ch&127)<32)
  504.  {
  505.  ch+='@';
  506.  ch|=UNDERLINE;
  507.  }
  508. if((ch&127)==127)
  509.  {
  510.  ch&=~127;
  511.  ch|='?'|UNDERLINE;
  512.  }
  513. return ch;
  514. }
  515.  
  516. int udline(i)
  517. {
  518. int q=i*width;
  519. TXTSIZ j;
  520. int t;
  521. int u;
  522. int ch;
  523. for(j=0;1;j++)
  524.  {
  525.  if(have) return -1;
  526.  if(fmeof())
  527.   {
  528.   clreolchk(i++,j);
  529.   j=0;
  530.   while(i<curwin->wind+curwin->height) clreolchk(i++,j);
  531.   return 1;
  532.   }
  533.  ch=fmgetc();
  534.  if(ch==NL)
  535.   {
  536.   clreolchk(i,j);
  537.   return 0;
  538.   }
  539.  if(ch==TAB)
  540.   {
  541.   ch=' ';
  542.   if(fmnote()-1>=markb && fmnote()<=marke && curbuf==markbuf) ch^=128;
  543.   t=i*width+j-xoffset;
  544.   do
  545.    {
  546.    if(j>=xoffset && j<xoffset+width-1)
  547.     {
  548.     u=scrn[t];
  549.     if(ch!=u || u==-1)
  550.      {
  551.      cpos(i,(int)(j-xoffset));
  552.      scrn[t]=ch;
  553.      tputcc(ch);
  554.      oxpos++;
  555.      }
  556.     }
  557.    t++;
  558.    j++;
  559.    } while(j&7);
  560.   j--;
  561.   }
  562.  else
  563.   {
  564.   ch=showas(ch);
  565.   if(fmnote()-1>=markb && fmnote()<=marke && curbuf==markbuf) ch^=INVERSE;
  566.   t=q+j-xoffset;
  567.   if(j>=xoffset && j<xoffset+width-1)
  568.    {
  569.    u=scrn[t];
  570.    if(ch!=u || u==-1)
  571.     {
  572.     cpos(i,(int)(j-xoffset));
  573.     scrn[t]=ch;
  574.     tputcc(ch);
  575.     oxpos++;
  576.     }
  577.    }
  578.   }
  579.  }
  580. }
  581.  
  582. int udscrn()
  583. {
  584. int i;
  585. int v;
  586. for(i=ypos;i<curwin->height+curwin->wind;i++)
  587.  if(v=udline(i)) break;
  588. if(v== -1) return 0;
  589. fmpoint(saddr);
  590. for(i=curwin->wind+1;i<ypos;i++)
  591.  if(udline(i)) return 0;
  592. return 1;
  593. }
  594.  
  595. dupdate1(fgf)
  596. {
  597. int y;
  598. TXTSIZ x;
  599. TXTSIZ sve=fmnote();
  600.  
  601. TXTSIZ sve1;
  602.  
  603. /* Status line */
  604. strcpy(stalin,"\\i");
  605. if(gfnam[0]) strcat(stalin,gfnam);
  606. else strcat(stalin,"(Unnamed)");
  607. if(changed) strcat(stalin," (Modified)");
  608. if(!helpon && strlen(stalin)+21<width+1)
  609.  {
  610.  int x=strlen(stalin);
  611.  while(x<width-20) stalin[x++]=' ';
  612.  stalin[x]=0;
  613.  strcat(stalin,"Hit Ctrl-K H for help");
  614.  }
  615. else
  616.  {
  617.  int x=strlen(stalin);
  618.  while(x<width+1) stalin[x++]=' ';
  619.  stalin[x]=0;
  620.  }
  621.  
  622. msgout(curwin->wind,stalin,0);
  623.  
  624. x=getcol();
  625. if(fmnrnl()) fmpoint(fmnote()+1);
  626. sve1=fmnote();
  627.  
  628. /* calculate what screen cursor position should be */
  629.  
  630. if(x>xoffset+width-2)
  631.  xpos=width-2, xoffset=x-width+2;
  632. else
  633.  if(x<xoffset)
  634.   xpos=0, xoffset=x;
  635.  else
  636.   xpos=x-xoffset;
  637.  
  638. /* calculate new y cursor position and point to beginning of screen */
  639.  
  640. if(newy)
  641.  {
  642.  if(fmnote()<=saddr)
  643.   {
  644.   ypos=curwin->wind+1;
  645.   saddr=fmnote();
  646.   }
  647.  else
  648.   {
  649.   /* is cursor within 24 lines of old beginning of screen */
  650.  
  651.   for(y=0;y!=curwin->height-2;y++)
  652.    {
  653.    if(fmnote()==saddr) goto over;
  654.    fmrgetc();
  655.    if(fmnrnl()) fmpoint(fmnote()+1);
  656.    }
  657.   if(cntr)
  658.    {
  659.    for(x=0;x<(curwin->height-1)/2;x++)
  660.     {
  661.     fmfnl();
  662.     y--;
  663.     fmgetc();
  664.     }
  665.    }
  666.   over:
  667.   cntr=0;
  668.   saddr=fmnote();
  669.   ypos=y+curwin->wind+1;
  670.   }
  671.  newy=0;
  672.  }
  673.  
  674. /* Now update screen */
  675. if(have)
  676.  { if(fgf) cpos(ypos,xpos); }
  677. else
  678.  {
  679.  fmpoint(sve1);
  680.  if(udscrn()) upd=0;
  681.  if(fgf) cpos(ypos,xpos);
  682.  }
  683. fmpoint(sve);
  684. }
  685.  
  686. dupdatehelp()
  687. {
  688. int att;
  689. int i,j,c;
  690. unsigned char *from=help;
  691. int *too=scrn;
  692. if(helplines>height-3) wind=height-3;
  693. else wind=helplines;
  694. for(i=0;i!=wind;++too, ++i)
  695.  {
  696.  j=0; att=0;
  697.  loop:
  698.  if(have) return;
  699.  if(j==width-1)
  700.   {
  701.   while(*from!='\n') ++from;
  702.   ++from;
  703.   continue;
  704.   }
  705.  if(*from=='\n')
  706.   {
  707.   hclreol:
  708.   ++from;
  709.   cpos(i,j);
  710.   eputs("\033[K");
  711.   while(j!=width-1) *too++ =' ', ++j;
  712.   continue;
  713.   }
  714.  if(*from=='\\')
  715.   {
  716.   ++from;
  717.   if(*from=='\n') goto hclreol;
  718.   if(*from=='u')
  719.    {
  720.    att^=UNDERLINE;
  721.    ++from;
  722.    goto loop;
  723.    }
  724.   if(*from=='i')
  725.    {
  726.    att^=INVERSE;
  727.    ++from;
  728.    goto loop;
  729.    }
  730.   }
  731.  c= *from++ | att;
  732.  if(c!= *too)
  733.   {
  734.   cpos(i,j);
  735.   tputcc(*too= c);
  736.   oxpos++;
  737.   }
  738.  ++too; ++j;
  739.  goto loop;
  740.  }
  741. hupd=0;
  742. }
  743.  
  744. int updall=0;
  745.  
  746. dupdate()
  747. {
  748. int xp,yp;
  749.  
  750. aflush();
  751. if(hupd) dupdatehelp();
  752. if(upd)
  753.  {
  754.  int total=height-wind;
  755.  struct window *x;
  756.  dupdate1(1);
  757.  stwin(curwin);
  758.  x=curwin;
  759.  curwin=topwin;
  760.  xp=xpos; yp=ypos;
  761.  do
  762.   {
  763.   if((curbuf==x->buffer || updall) && curwin!=x)
  764.    {
  765.    if(total<=0) break;
  766.    ldwin(curwin);
  767.    total-=curwin->height;
  768.    newy=1;
  769.    dupdate1(0);
  770.    stwin(curwin);
  771.    }
  772.   else if(curwin==x)
  773.    total-=curwin->height;
  774.   }
  775.   while(curwin=curwin->next,curwin!=topwin);
  776.  updall=0;
  777.  ldwin(x);
  778.  curwin=x;
  779.  cpos(ypos=yp,xpos=xp);
  780.  }
  781. }
  782.  
  783. invalidate(line)
  784. {
  785. int x;
  786. for(x=0;x<width;x++) scrn[width*line+x]= -1;
  787. }
  788.  
  789. tputcc(c)
  790. {
  791. attrib(c);
  792. eputc(c&255);
  793. }
  794.  
  795. int backup=0;
  796. FILE *handle;
  797. unsigned char gfnam[PATHSIZE];
  798.  
  799. TXTSIZ bufsiz;        /* Size of buffer */
  800. TXTPTR point;        /* The point */
  801. TXTPTR buffer;        /* The buffer */
  802. TXTPTR filend;        /* First character not in buffer */
  803. TXTPTR hole;        /* Beginning of hole */
  804. TXTPTR ehole;        /* First character not in hole */
  805. int changed=0;        /* Set when file has been changed */
  806.  
  807. fmopen()
  808. {
  809. buffer=(unsigned char *)TXTMALLOC(bufsiz=HOLESIZE);
  810. point=buffer;
  811. hole=buffer;
  812. ehole=buffer+HOLESIZE;
  813. filend=ehole;
  814. changed=0;
  815. }
  816.  
  817. fmexpand(amount)
  818. unsigned amount;
  819. {
  820. if(filend+amount-buffer>bufsiz)
  821.  {
  822.  unsigned char *old=buffer;
  823.  buffer=(TXTPTR)TXTREALLOC(buffer,bufsiz=(filend+amount+HOLESIZE-buffer));
  824.  point+=buffer-old;
  825.  filend+=buffer-old;
  826.  hole+=buffer-old;
  827.  ehole+=buffer-old;
  828.  }
  829. }
  830.  
  831. fmhole()
  832. {
  833. if(point==hole) return;
  834. if(point==ehole)
  835.  {
  836.  point=hole;
  837.  return;
  838.  }
  839. if(point<hole)
  840.  {
  841.  bmove(ehole-(hole-point),point,hole-point);
  842.  ehole-=(hole-point);
  843.  hole=point;
  844.  }
  845. else
  846.  {
  847.  bmove(hole,ehole,point-ehole);
  848.  hole+=point-ehole;
  849.  ehole=point;
  850.  point=hole;
  851.  }
  852. }
  853.  
  854. fmbig(size)
  855. TXTSIZ size;
  856. {
  857. if(size>fmholesize())
  858.  {
  859.  size+=HOLESIZE;
  860.  fmexpand(size);
  861.  bmove(ehole+size,ehole,filend-ehole);
  862.  ehole+=size;
  863.  filend+=size;
  864.  }
  865. }
  866.  
  867. int fmfnl()
  868. {
  869. while(((point==hole)?(point=ehole):point)!=filend)
  870.  if(*point==NL) return 1;
  871.  else point++;
  872. return 0;
  873. }
  874.  
  875. int fmrnl()
  876. {
  877. if(fmrc()==NL) return 1;
  878. while((point==ehole?point=hole:point)!=buffer)
  879.  if(*(--point)==NL) return 1;
  880. return 0;
  881. }
  882.  
  883.  
  884. int nundorecs=0;
  885. struct undorec
  886.  {
  887.  struct undorec *next;
  888.  TXTSIZ size;
  889.  TXTSIZ where;
  890.  struct buffer *buf;
  891.  unsigned char *buffer;
  892.  }
  893.  *undorecs=0;
  894.  
  895. fminsu(size)
  896. TXTSIZ size;
  897. {
  898. struct window *z;
  899. if(undorecs) undorecs->buf=0;
  900. if(curbuf==markbuf)
  901.  {
  902.  if(fmnote()<markb) markb+=size;
  903.  if(fmnote()<marke) marke+=size;
  904.  }
  905. z=topwin;
  906. do
  907.  {
  908.  if(z->buffer==curbuf)
  909.   {
  910.   if(z==curwin)
  911.    {
  912.    if(fmnote()<saddr) saddr+=size;
  913.    }
  914.   else
  915.    {
  916.    if(fmnote()<z->saddr) z->saddr+=size;
  917.    if(fmnote()<z->cursor) z->cursor+=size;
  918.    }
  919.   }
  920.  z=z->next;
  921.  }
  922.  while(z!=topwin);
  923. }
  924.  
  925. struct undorec *undoptr=0;
  926. int undoflag=1;
  927.  
  928. undo()
  929. {
  930. if(!undorecs) return;
  931. extend=0;
  932. if(undoptr)
  933.  {
  934.  undoflag=0;
  935.  fmdel(undoptr->size);
  936.  undoflag=1;
  937.  undoptr=undoptr->next;
  938.  if(!undoptr)
  939.   {
  940.   marke=markb;
  941.   return;
  942.   }
  943.  }
  944. else undoptr=undorecs;
  945. fminss(undoptr->buffer,undoptr->size);
  946. markbuf=curbuf;
  947. markb=fmnote();
  948. marke=markb+undoptr->size;
  949. }
  950.  
  951. redo()
  952. {
  953. if(!undorecs) return;
  954. extend=0;
  955. if(undoptr)
  956.  {
  957.  undoflag=0;
  958.  fmdel(undoptr->size);
  959.  undoflag=1;
  960.  if(undoptr==undorecs)
  961.   {
  962.   undoptr=0;
  963.   marke=markb;
  964.   return;
  965.   }
  966.  else
  967.   {
  968.   struct undorec *p;
  969.   for(p=undorecs;p->next!=undoptr;p=p->next);
  970.   undoptr=p;
  971.   }
  972.  }
  973. else for(undoptr=undorecs;undoptr->next;undoptr=undoptr->next);
  974. fminss(undoptr->buffer,undoptr->size);
  975. markbuf=curbuf;
  976. markb=fmnote();
  977. marke=markb+undoptr->size;
  978. }
  979.  
  980. fmdelu(size)
  981. TXTSIZ size;
  982. {
  983. struct window *z;
  984. struct undorec *it;
  985. if(undoflag)
  986.  {
  987.  if(undorecs)
  988.   if(undorecs->buf==curbuf && (undorecs->where==fmnote()))
  989.    {
  990.    /* Add to end */
  991.    undorecs->buffer=(unsigned char *)realloc(undorecs->buffer,
  992.    undorecs->size+size);
  993.    fmcpy(undorecs->buffer+undorecs->size,size);
  994.    undorecs->size+=size;
  995.    }
  996.   else if(undorecs->buf==curbuf && (undorecs->where==fmnote()+size))
  997.    {
  998.    /* Add to beginning */
  999.    undorecs->buffer=(unsigned char *)realloc(
  1000.    undorecs->buffer,undorecs->size+size);
  1001.    bbkwd(undorecs->buffer+size,undorecs->buffer,undorecs->size);
  1002.    fmcpy(undorecs->buffer,size);
  1003.    undorecs->size+=size;
  1004.    undorecs->where-=size;
  1005.    }
  1006.   else goto in;
  1007.  else
  1008.   {
  1009.   in:
  1010.   /* New record */
  1011.   it=(struct undorec *)malloc(sizeof(struct undorec));
  1012.   it->next=undorecs;
  1013.   undorecs=it;
  1014.   it->buf=curbuf;
  1015.   it->size=size;
  1016.   it->where=fmnote();
  1017.   it->buffer=(unsigned char *)malloc(size);
  1018.   fmcpy(it->buffer,size);
  1019.   ++nundorecs;
  1020.   if(nundorecs==20)
  1021.    {
  1022.    struct undorec *p;
  1023.    for(it=undorecs;it->next;p=it,it=it->next);
  1024.    free(it->buffer);
  1025.    free(it);
  1026.    p->next=0;
  1027.    }
  1028.   }
  1029.  }
  1030. if(markbuf==curbuf)
  1031.  {
  1032.  if(fmnote()<markb) markb-=umin(size,markb-fmnote());
  1033.  if(fmnote()<marke) marke-=umin(size,marke-fmnote());
  1034.  }
  1035. z=topwin;
  1036. do
  1037.  {
  1038.  if(curbuf==z->buffer)
  1039.   {
  1040.   if(z==curwin)
  1041.    {
  1042.    if(fmnote()<saddr) saddr-=umin(size,saddr-fmnote());
  1043.    }
  1044.   else
  1045.    {
  1046.    if(fmnote()<z->saddr) z->saddr-=umin(size,z->saddr-fmnote());
  1047.    if(fmnote()<z->cursor) z->cursor-=umin(size,z->cursor-fmnote());
  1048.    }
  1049.   }
  1050.  z=z->next;
  1051.  }
  1052.  while(z!=topwin);
  1053. }
  1054.  
  1055. fmdel(x)
  1056. TXTSIZ x;
  1057. {
  1058. fmhole();
  1059. fmdelu(x);
  1060. ehole+=x;
  1061. changed=1;
  1062. }
  1063.  
  1064. fminss(string,size)
  1065. unsigned char *string;
  1066. unsigned size;
  1067. {
  1068. fminsu(size);
  1069. fmhole();
  1070. if(size>fmholesize()) fmbig(size);
  1071. bmove(hole,string,size);
  1072. hole+=size;
  1073. changed=1;
  1074. }
  1075.  
  1076. fmcpy(string,size)
  1077. unsigned char *string;
  1078. {
  1079. fmhole();
  1080. bbkwd(string,ehole,size);
  1081. }
  1082.  
  1083. int fmcmp(string,size)
  1084. unsigned char *string;
  1085. int size;
  1086. {
  1087. unsigned char *x;
  1088. if(point==hole) point=ehole;
  1089. if(hole>point && hole<point+size && hole!=ehole)
  1090.  {
  1091.  if(fmcmp(string,hole-point)) return 1;
  1092.  else
  1093.   {
  1094.   x=point;
  1095.   point=ehole;
  1096.   if(fmcmp(string+(hole-x),size-(hole-x)))
  1097.    {
  1098.    point=x;
  1099.    return 1;
  1100.    }
  1101.   else
  1102.    {
  1103.    point=x;
  1104.    return 0;
  1105.    }
  1106.   }
  1107.  }
  1108. else
  1109.  {
  1110.  x=point;
  1111.  do
  1112.   if(*(x++)!=*(string++)) return 1;
  1113.   while(--size);
  1114.  return 0;
  1115.  }
  1116. }
  1117.  
  1118. int tupp(c)
  1119. unsigned char c;
  1120. {
  1121. if(c>='a' && c<='z') return c+'A'-'a';
  1122. else return c;
  1123. }
  1124.  
  1125. int fmicmp(string,size)
  1126. unsigned char *string;
  1127. int size;
  1128. {
  1129. unsigned char *x;
  1130. if(point==hole) point=ehole;
  1131. if(hole>point && hole<point+size && hole!=ehole)
  1132.  {
  1133.  if(fmcmp(string,hole-point)) return 1;
  1134.  else
  1135.   {
  1136.   x=point;
  1137.   point=ehole;
  1138.   if(fmcmp(string+(hole-x),size-(hole-x)))
  1139.    {
  1140.    point=x;
  1141.    return 1;
  1142.    }
  1143.   else
  1144.    {
  1145.    point=x;
  1146.    return 0;
  1147.    }
  1148.   }
  1149.  }
  1150. else
  1151.  {
  1152.  x=point;
  1153.  do
  1154.   if(tupp(*(x++))!=tupp(*(string++))) return 1;
  1155.   while(--size);
  1156.  return 0;
  1157.  }
  1158. }
  1159.  
  1160. int fmsave(file,size)
  1161. FILE *file;
  1162. TXTSIZ size;
  1163. {
  1164. if(!size) return 1;
  1165. if(point==hole) point=ehole;
  1166. if(hole>point && hole<point+size && hole!=ehole)
  1167.  {
  1168.  if(hole-point!=fwrite(point,1,hole-point,file)) return 0;
  1169.  if(size-(hole-point)!=fwrite(ehole,1,size-(hole-point),file)) return 0;
  1170.  return 1;
  1171.  }
  1172. else
  1173.  return size==fwrite(point,1,size,file);
  1174. }
  1175.  
  1176. int fminsfil(file)
  1177. FILE *file;
  1178. {
  1179. struct stat buf;
  1180. TXTSIZ amount;
  1181. fstat(fileno(file),&buf);
  1182. if(buf.st_size==0) return 1;
  1183. fminsu(buf.st_size);
  1184. changed=1;
  1185. fmhole();
  1186. fmbig(buf.st_size);
  1187. amount=fread(hole,1,buf.st_size,file);
  1188. hole+=amount;
  1189. return amount==buf.st_size;
  1190. }
  1191.  
  1192. /* Output a message string */
  1193. /* The right part of it is chopped */
  1194.  
  1195. msgout(row,str,flg)
  1196. unsigned char *str;
  1197. {
  1198. int j=0, c, att=0;
  1199. int *too=scrn+width*row;
  1200. loop:
  1201. if(j==width-1)
  1202.  {
  1203.  if(flg) cpos(row,j);
  1204.  return;
  1205.  }
  1206. if(!*str)
  1207.  {
  1208.  hclreol:
  1209.  cpos(row,j);
  1210.  eputs("\033[K");
  1211.  while(j!=width-1) *too++ =' ', ++j;
  1212.  return;
  1213.  }
  1214. if(*str=='\\')
  1215.  {
  1216.  ++str;
  1217.  if(!*str) goto hclreol;
  1218.  if(*str=='u')
  1219.   {
  1220.   att^=UNDERLINE;
  1221.   ++str;
  1222.   goto loop;
  1223.   }
  1224.  if(*str=='i')
  1225.   {
  1226.   att^=INVERSE;
  1227.   ++str;
  1228.   goto loop;
  1229.   }
  1230.  }
  1231. c= *str++ | att;
  1232. if(c!= *too)
  1233.  {
  1234.  cpos(row,j);
  1235.  tputcc(*too= c);
  1236.  oxpos++;
  1237.  }
  1238. ++too; ++j;
  1239. goto loop;
  1240. }
  1241.  
  1242. int getl(prompt,dat)
  1243. unsigned char *prompt;
  1244. unsigned char *dat;
  1245. {
  1246. int ch,x,y;
  1247. unsigned char buf[PATHSIZE];
  1248. strcpy(buf,prompt);
  1249. strcat(buf," (^C to abort): ");
  1250. y=strlen(buf);
  1251. strcat(buf,dat);
  1252. x=strlen(buf);
  1253. while(1)
  1254.  {
  1255.  if(x>width-1) msgout(height-1,buf+x-(width-1),1);
  1256.  else msgout(height-1,buf,1);
  1257.  ch=anext();
  1258.  if(ch=='L'-'@')
  1259.   {
  1260.   ch= -1;
  1261.   break;
  1262.   }
  1263.  if(ch==13 || ch==10)
  1264.   {
  1265.   ch=1;
  1266.   break;
  1267.   }
  1268.  if(ch>=32 && ch<127)
  1269.   {
  1270.   buf[x+1]=0, dat[x+1-y]=0;
  1271.   buf[x]=ch, dat[x++-y]=ch;
  1272.   continue;
  1273.   }
  1274.  if((ch==8 || ch==127) && x-y)
  1275.   {
  1276.   x--;
  1277.   dat[x-y]=0;
  1278.   buf[x]=0;
  1279.   continue;
  1280.   }
  1281.  if(ch==3)
  1282.   {
  1283.   ch=0;
  1284.   break;
  1285.   }
  1286.  }
  1287. return ch;
  1288. }
  1289.  
  1290. msg(ms)
  1291. unsigned char *ms;
  1292. {
  1293. msgout(height-1,ms,1);
  1294. anext();
  1295. }
  1296.  
  1297. int askyn(ms)
  1298. unsigned char *ms;
  1299. {
  1300. int ch;
  1301. msgout(height-1,ms,1);
  1302. up:
  1303. ch=anext();
  1304. switch(ch)
  1305.  {
  1306. case 'y':
  1307. case 'n':
  1308.  eputc(ch);
  1309.  ch&=0x5f;
  1310.  break;
  1311. case 'Y':
  1312. case 'N':
  1313.  eputc(ch);
  1314.  break;
  1315. case 3:
  1316.  ch= -1;
  1317.  break;
  1318. default:
  1319.  goto up;
  1320.  }
  1321. return ch;
  1322. }
  1323.  
  1324. int query(ms)
  1325. unsigned char *ms;
  1326. {
  1327. msgout(height-1,ms,1);
  1328. return anext();
  1329. }
  1330.  
  1331. int nquery(ms)
  1332. unsigned char *ms;
  1333. {
  1334. msgout(height-1,ms,1);
  1335. cpos(ypos,xpos);
  1336. return anext();
  1337. }
  1338.  
  1339. imsg()
  1340. {
  1341. attrib(0);
  1342. if(omsg) msgout(1,omsg,0);
  1343. upd=1;
  1344. msgout(height-1,"\\i** Joe's Own Editor version 0.1.0 (1991) **\\i",0);
  1345. cpos(1,0);
  1346. }
  1347.  
  1348. int pic;
  1349. int autoind;
  1350. int overwrite;
  1351. int wrap;
  1352. int tabmagic;
  1353. TXTSIZ rmargin;
  1354.  
  1355. int options=0;
  1356. unsigned char sstring[PATHSIZE];
  1357. unsigned char rstring[PATHSIZE];
  1358. int len;
  1359.  
  1360. TXTSIZ markb=0;
  1361. TXTSIZ marke=0;
  1362.  
  1363. TXTSIZ added;
  1364. TXTSIZ extend;
  1365. int leave;       /* set if editor should now exit */
  1366.  
  1367. TXTSIZ getrcol()
  1368. {
  1369. TXTSIZ x,y;
  1370. unsigned char ch;
  1371. x=fmnote();
  1372. if(fmnrnl()) fmgetc();
  1373. y=0;
  1374. while(fmnote()!=x)
  1375.  {
  1376.  ch=fmgetc();
  1377.  if(ch==TAB)
  1378.   while((++y)&7);
  1379.  else
  1380.   y++;
  1381.  }
  1382. return y;
  1383. }
  1384.  
  1385. gocol(x)
  1386. TXTSIZ x;
  1387. {
  1388. TXTSIZ y;
  1389. int ch;
  1390. if(fmnrnl()) fmgetc();
  1391. extend=0;
  1392. for(y=0;y!=x;y++)
  1393.  {
  1394.  if(fmeof()) goto dn;
  1395.  ch=fmgetc();
  1396.  if(ch==NL)
  1397.   {
  1398.   fmpoint(fmnote()-1);
  1399.   extend=x;
  1400.   return;
  1401.   }
  1402.  if(ch==TAB)
  1403.   {
  1404.   while((++y)&7)
  1405.    {
  1406.    if(y==x)
  1407.     {
  1408.     fmpoint(fmnote()-1);
  1409. dn:
  1410.     extend=x;
  1411.     return;
  1412.     }
  1413.    }
  1414.   y--;
  1415.   }
  1416.  }
  1417. }
  1418.  
  1419. TXTSIZ calcs()
  1420. {
  1421. TXTSIZ y=0;
  1422. if(fmnrnl()) fmgetc();
  1423. extend=0;
  1424. while(! (fmeof()?1:fmrc()==NL))
  1425.  if(fmrc()==' ')
  1426.   {
  1427.   ++y;
  1428.   fmgetc();
  1429.   }
  1430.  else if(fmrc()==TAB)
  1431.   {
  1432.   do ++y; while(y%TABWIDTH);
  1433.   fmgetc();
  1434.   }
  1435.  else break;
  1436. return y;
  1437. }
  1438.  
  1439. unfill()
  1440. {
  1441. fmfnl();
  1442. extend=0;
  1443. while(fmnote())
  1444.  {
  1445.  unsigned char x=fmrgetc();
  1446.  if(x==' ' || x==TAB) fmdel(1);
  1447.  else
  1448.   {
  1449.   fmgetc();
  1450.   break;
  1451.   }
  1452.  }
  1453. }
  1454.  
  1455. /* Fill from end of line to extend position */
  1456.  
  1457. fillup()
  1458. {
  1459. TXTSIZ x;
  1460. if(extend && pic)
  1461.  {
  1462.  x=getrcol();
  1463.  while(extend>x)
  1464.   {
  1465.   fminsc(' ');
  1466.   fmgetc();
  1467.   ++x;
  1468.   }
  1469.  }
  1470. extend=0;
  1471. }
  1472.  
  1473. /* Save current buffer in named file.  Returns 0 on error.  Clears 'changed'
  1474.  * variable if sucessfull
  1475.  */
  1476.  
  1477. int saveit1(tos)
  1478. unsigned char *tos;
  1479. {
  1480. unsigned char sting[PATHSIZE];
  1481. TXTSIZ temp=fmnote();
  1482. fmpoint(0);
  1483. handle=fopen(tos,"w+");
  1484. if(handle)
  1485.  {
  1486.  if(!fmsave(handle,fmsize()))
  1487.   {
  1488.   sprintf(sting,"\\iError writing to file %s\\i",tos);
  1489.   msg(sting);
  1490.   fmpoint(temp);
  1491.   return(0);
  1492.   }
  1493.  fmpoint(temp);
  1494.  if(fclose(handle)==EOF)
  1495.   {
  1496.   sprintf(sting,"\\iError closing file %s\\i",tos);
  1497.   msg(sting);
  1498.   fmpoint(temp);
  1499.   return(0);
  1500.   }
  1501.  changed=0;
  1502.  curbuf->changed=0;
  1503.  return(1);
  1504.  }
  1505. else
  1506.  {
  1507.  sprintf(sting,"\\iError opening file %s\\i",tos);
  1508.  msg(sting);
  1509.  fmpoint(temp);
  1510.  return(0);
  1511.  }
  1512. }
  1513.  
  1514. rewrite()
  1515. {
  1516. unsigned char s[25];
  1517. int *t,c;
  1518. oxpos= 0;
  1519. oypos= 0;
  1520. tops= 0;
  1521. bots= height-1;
  1522. if(scroll) sprintf(s,"\033[m\033[1;%dr\033[H\033[J",height);
  1523. else sprintf(s,"\033[m\033[H\033[J");
  1524. eputs(s);
  1525. t=scrn;
  1526. c=width*height;
  1527. do *(t++)= ' '; while(--c);
  1528. upd=1;
  1529. newy=1;
  1530. updall=1;
  1531. if(helpon) hupd=1;
  1532. }
  1533.  
  1534. /* Toggle help text */
  1535.  
  1536. thelp()
  1537. {
  1538. struct window *x;
  1539. newy=1;
  1540. upd=1;
  1541. if(helpon)
  1542.  {
  1543.  x=topwin;
  1544.  do
  1545.   {
  1546.   if(x->hheight) x->height=x->hheight;
  1547.   else x->height*=height, x->height/=height-wind;
  1548.   x=x->next;
  1549.   }
  1550.   while(x!=topwin);
  1551.  wind=0, hupd=0;
  1552.  }
  1553. else
  1554.  {
  1555.  if(helplines>height-3) wind=height-3;
  1556.  else wind=helplines;
  1557.  hupd=1;
  1558.  x=topwin;
  1559.  do
  1560.   {
  1561.   x->hheight=x->height;
  1562.   x->height*=height-wind;
  1563.   x->height/=height;
  1564.   x=x->next;
  1565.   }
  1566.   while(x!=topwin);
  1567.  }
  1568. helpon= !helpon;
  1569. wfit();
  1570. }
  1571.  
  1572. /* Move cursor to beginning of file */
  1573.  
  1574. bof()
  1575. {
  1576. extend=0;
  1577. fmpoint(0);
  1578. newy=1;
  1579. }
  1580.  
  1581. /* Move cursor to beginning of line */
  1582.  
  1583. bol()
  1584. {
  1585. if(fmnrnl()) fmgetc();
  1586. extend=0;
  1587. }
  1588.  
  1589. /* Move cursor to end of line */
  1590.  
  1591. eol()
  1592. {
  1593. extend=0;
  1594. fmfnl();
  1595. }
  1596.  
  1597. /* Move cursor to end of file */
  1598.  
  1599. eof()
  1600. {
  1601. extend=0;
  1602. fmpoint(fmsize());
  1603. newy=1;
  1604. }
  1605.  
  1606. /* Move cursor right */
  1607.  
  1608. urtarw()
  1609. {
  1610. fillup();
  1611. extend=0;
  1612. if(fmeof())
  1613.  {
  1614.  if(pic)
  1615.   {
  1616.   into:
  1617.   fminsc(' ');
  1618.   fmgetc();
  1619.   }
  1620.  return;
  1621.  }
  1622. else if(fmrc()==NL)
  1623.  {
  1624.  if(pic) goto into;
  1625.  bol();
  1626.  udnarw();
  1627.  return;
  1628.  }
  1629. fmgetc();
  1630. }
  1631.  
  1632. rtarw()
  1633. {
  1634. fillup();
  1635. extend=0;
  1636. if(fmeof())
  1637.  {
  1638.  if(pic)
  1639.   {
  1640.   into:
  1641.   fminsc(' ');
  1642.   fmgetc();
  1643.   }
  1644.  return;
  1645.  }
  1646. else if(fmrc()==NL)
  1647.  {
  1648.  if(pic) goto into;
  1649.  newy=1;
  1650.  }
  1651. fmgetc();
  1652. }
  1653.  
  1654. ultarw()
  1655. {
  1656. if(extend)
  1657.  {
  1658.  extend=0;
  1659.  return;
  1660.  }
  1661. fillup();
  1662. if(fmnote())
  1663.  {
  1664.  fmpoint(fmnote()-1);
  1665.  if(fmrc()==NL)
  1666.   {
  1667.   fmgetc();
  1668.   uuparw();
  1669.   eol();
  1670.   }
  1671.  }
  1672. }
  1673.  
  1674. ltarw()
  1675. {
  1676. if(extend)
  1677.  {
  1678.  extend=0;
  1679.  return;
  1680.  }
  1681. fillup();
  1682. if(fmnote())
  1683.  fmpoint(fmnote()-1);
  1684. if(fmrc()==NL) newy=1;
  1685. }
  1686.  
  1687. /* Move cursor up */
  1688.  
  1689. uparw()
  1690. {
  1691. TXTSIZ x;
  1692. x=getcol();
  1693. bol();
  1694. if(fmnote())
  1695.  {
  1696.  fmpoint(fmnote()-1);
  1697.  if(fmnrnl())
  1698.   fmgetc();
  1699.  }
  1700. gocol(x);
  1701. newy=1;
  1702. }
  1703.  
  1704. /* user's cursor up routine (uses scrolling regions) */
  1705.  
  1706. uuparw()
  1707. {
  1708. TXTSIZ sve=fmnote();
  1709. int y=(curwin->wind+1)*width;
  1710. int x;
  1711. if(scroll)
  1712.  {
  1713.  if(fmnrnl())
  1714.   {
  1715.   if(fmnote()+1==saddr)
  1716.    {
  1717.    if(fmnrnl()) fmgetc();
  1718.    saddr=fmnote();
  1719.    setregn(curwin->wind+1,curwin->wind+(curwin->height-1));
  1720.    cpos(curwin->wind+1,oxpos);
  1721.    attrib(0);
  1722.    eputs("\033M");
  1723.    for(x=(curwin->wind+curwin->height)*width-1;x>=y+width;x--)
  1724.     scrn[x]=scrn[x-width];
  1725.    for(x=y;x<y+width;x++) scrn[x]= ' ';
  1726.    }
  1727.   fmpoint(sve);
  1728.   }
  1729.  else
  1730.   fmpoint(sve);
  1731.  }
  1732. uparw();
  1733. }
  1734.  
  1735. /* Move cursor down */
  1736.  
  1737. dnarw()
  1738. {
  1739. TXTSIZ x;
  1740. newy=1;
  1741. x=getcol();
  1742. if(!fmfnl())
  1743.  bol();
  1744. else
  1745.  fmgetc();
  1746. gocol(x);
  1747. }
  1748.  
  1749. /* user's down arrow function */
  1750.  
  1751. udnarw()
  1752. {
  1753. TXTSIZ sve=fmnote();
  1754. int x;
  1755. if(!fmfnl())
  1756.  {
  1757.  if(pic)
  1758.   {
  1759.   fminsc(NL);
  1760.   fmpoint(sve);
  1761.   udnarw();
  1762.   return;
  1763.   }
  1764.  else
  1765.   {
  1766.   goto cant;
  1767.   }
  1768.  }
  1769. if(scroll)
  1770.  {
  1771.  if(ypos!=curwin->height+curwin->wind-1) goto cant;
  1772.  for(x=0;x!=curwin->height-2;x++) fmnrnl();
  1773.  fmfnl();
  1774.  fmgetc();
  1775.  saddr=fmnote();
  1776.  setregn(curwin->wind+1,curwin->wind+curwin->height-1);
  1777.  cpos((curwin->wind+curwin->height-1),oxpos);
  1778.  attrib(0);
  1779.  eputc(10);
  1780.  for(x=(curwin->wind+1)*width;x!=(curwin->wind+curwin->height-1)*width;x++)
  1781.   scrn[x]=scrn[x+width];
  1782.  for(x=(curwin->wind+curwin->height-1)*width;
  1783.      x!=(curwin->wind+curwin->height)*width;x++)
  1784.   scrn[x]= ' ';
  1785.  }
  1786. cant:
  1787. fmpoint(sve);
  1788. dnarw();
  1789. }
  1790.  
  1791. /* Magic Tabs (tm) */
  1792.  
  1793. TXTSIZ tabcol;    /* Original column of text preceeded by tab stops */
  1794.  
  1795. tabmark()
  1796. {
  1797. TXTSIZ cur=fmnote();
  1798. unsigned char c;
  1799. tabcol=0;
  1800. if(!tabmagic) return;
  1801. while(!fmeof())
  1802.  {
  1803.  c=fmgetc();
  1804.  if(c=='\t')
  1805.   {
  1806.   while(!fmeof())
  1807.    {
  1808.    c=fmgetc();
  1809.    if(c=='\n') break;
  1810.    if(c!='\t')
  1811.     {
  1812.     fmrgetc();
  1813.     tabcol=getrcol();
  1814.     break;
  1815.     }
  1816.    }
  1817.   fmpoint(cur); return;
  1818.   }
  1819.  if(c=='\n') break;
  1820.  }
  1821. fmpoint(cur); return;
  1822. }
  1823.  
  1824. tabfix()
  1825. {
  1826. TXTSIZ cur=fmnote(),newcol;
  1827. unsigned char c;
  1828. if(!tabcol) return;
  1829. while(!fmeof())
  1830.  {
  1831.  c=fmgetc();
  1832.  if(c=='\t')
  1833.   {
  1834.   while(!fmeof())
  1835.    {
  1836.    c=fmgetc();
  1837.    if(c=='\n') break;
  1838.    if(c!='\t')
  1839.     {
  1840.     fmrgetc();
  1841.     newcol=getrcol();
  1842.     while(newcol<tabcol)
  1843.      {
  1844.      fminsc('\t');
  1845.      newcol+=8;
  1846.      }
  1847.     fmrgetc();
  1848.     while(newcol>tabcol)
  1849.      {
  1850.      if(fmrgetc()=='\t')
  1851.       {
  1852.       fmdel(1);
  1853.       newcol-=8;
  1854.       }
  1855.      else break;
  1856.      }
  1857.     break;
  1858.     }
  1859.    }
  1860.   fmpoint(cur); return;
  1861.   }
  1862.  if(c=='\n') break;
  1863.  }
  1864. fmpoint(cur); return;
  1865. }
  1866.  
  1867. /* Delete character under cursor */
  1868.  
  1869. delch()
  1870. {
  1871. unsigned char c;
  1872. int x;
  1873. if(extend && pic) return;
  1874. if(extend)
  1875.  {
  1876.  extend=0;
  1877.  return;
  1878.  }
  1879. if(!fmeof())
  1880.  {
  1881.  if((c=fmrc())==NL && scroll)
  1882.   {
  1883.   if(ypos<curwin->wind+curwin->height-2)
  1884.    {
  1885.    for(x=(ypos+1)*width;x<width*(curwin->wind+curwin->height-1);x++)
  1886.     scrn[x]=scrn[x+width];
  1887.    for(x=(curwin->wind+curwin->height-1)*width;
  1888.    x<(curwin->wind+curwin->height)*width;x++) scrn[x]= ' ';
  1889.    setregn(ypos+1,(curwin->wind+curwin->height-1));
  1890.    cpos((curwin->wind+curwin->height-1),oxpos);
  1891.    attrib(0);
  1892.    eputc(10);
  1893.    }
  1894.   fmdel(1);
  1895.   }
  1896.  else if(c==TAB) fmdel(1);
  1897.  else
  1898.   {
  1899.   tabmark();
  1900.   fmdel(1);
  1901.   tabfix();
  1902.   }
  1903.  }
  1904. }
  1905.  
  1906. type(ch)
  1907. unsigned char ch;
  1908. {
  1909. int ox=oxpos;
  1910. int x,y;
  1911. TXTSIZ temp, temp1;
  1912. int eflag=0;
  1913. if(quote8th)
  1914.  {
  1915.  quote8th=0;
  1916.  ch|=128;
  1917.  }
  1918. ypos=oypos;
  1919. if(extend)
  1920.  {
  1921.  if(ch!=NL) fillup();
  1922.  else extend=0;
  1923.  eflag=1;
  1924.  }
  1925. if(ch==NL)
  1926.  {
  1927.  if(overwrite && !tabmagic && !fmeof()) fmdel(1);
  1928.  fminsc(ch);
  1929.  fmgetc();
  1930.  newy=1;
  1931.  if(ypos!=(curwin->wind+curwin->height-1))
  1932.   {
  1933.   if(!fmeof())
  1934.    {
  1935.    if(ypos<curwin->wind+curwin->height-2 && scroll)
  1936.     {
  1937.     setregn(ypos+1,(curwin->wind+curwin->height-1));
  1938.     cpos(ypos+1,oxpos);
  1939.     attrib(0);
  1940.     eputs("\033M");
  1941.     cpos(ypos+1,0);
  1942.     for(x=(curwin->wind+curwin->height)*width-1;x>=(ypos+2)*width;x--)
  1943.      scrn[x]=scrn[x-width];
  1944.     for(x=(ypos+1)*width;x<(ypos+2)*width;x++) scrn[x]=' ';
  1945.     }
  1946.    else cpos(ypos+1,0);
  1947.    }
  1948.   else
  1949.    cpos(ypos+1,0);
  1950.   }
  1951.  else if(scroll)
  1952.    {
  1953.    setregn(curwin->wind+1,(curwin->wind+curwin->height-1));
  1954.    cpos((curwin->height+curwin->wind-1),0);
  1955.    attrib(0);
  1956.    eputc(10);
  1957.    for(x=curwin->wind*width;x<(curwin->wind+curwin->height-1)*width;x++)
  1958.     scrn[x]=scrn[x+width];
  1959.    for(x=(curwin->wind+curwin->height-1)*width;
  1960.        x<(curwin->wind+curwin->height)*width;x++) scrn[x]= ' ';
  1961.    temp=fmnote();
  1962.    fmpoint(saddr);
  1963.    fmfnl();
  1964.    fmgetc();
  1965.    saddr=fmnote();
  1966.    fmpoint(temp);
  1967.    }
  1968.  if(ox<(width-2) && (fmeof()) && scroll) uuu=1;
  1969.  if(autoind)
  1970.   {
  1971.   temp=fmnote();
  1972.   uparw();
  1973.   for(x=0;1;x++)
  1974.    {
  1975.    ch=fmgetc();
  1976.    if(!(ch==' ' || ch==TAB)) break;
  1977.    temp1=fmnote();
  1978.    fmpoint(temp);
  1979.    fminsc(ch);
  1980.    uuu=0;
  1981.    added++;
  1982.    fmpoint(temp1);
  1983.    temp++;
  1984.    }
  1985.   fmpoint(fmnote()-(x+1));
  1986.   dnarw();
  1987.   y=overwrite, overwrite=0;
  1988.   for(;x;x--) rtarw();
  1989.   overwrite=y;
  1990.   }
  1991.  }
  1992. else
  1993.  {
  1994.  if(overwrite)
  1995.   {
  1996.   if(!tabmagic)
  1997.    {
  1998.    if(!fmeof())
  1999.     {
  2000.     unsigned char c=fmrc();
  2001.     fmdel(1);
  2002.     if(ch!=TAB && c!=TAB && c!=NL && ox<(width-2)) uuu=1;
  2003.     }
  2004.    else if(ch!=TAB && ox<(width-2)) uuu=1;
  2005.    }
  2006.   else
  2007.    if(fmrc()!=NL && !fmeof())
  2008.     if(ch==TAB && fmrc()!=TAB)
  2009.      {
  2010.      TXTSIZ foo=getrcol();
  2011.      do
  2012. -- 
  2013. /*  rcarter@wpi.wpi.edu */      /* Amazing */             /* Joseph H. Allen */
  2014. int a[1817];main(z,p,q,r){for(p=80;q+p-80;p-=2*a[p])for(z=9;z--;)q=3&(r=time(0)
  2015. +r*57)/7,q=q?q-1?q-2?1-p%79?-1:0:p%79-77?1:0:p<1659?79:0:p>158?-79:0,q?!a[p+q*2
  2016. ]?a[p+=a[p+=q]=q]=q:0:0;for(;q++-1817;)printf(q%79?"%c":"%c\n"," #"[!a[q-1]]);}
  2017.