home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / Applications / Em_Editor / Em.shar / em2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-10-12  |  8.7 KB  |  441 lines

  1. #
  2. /*    This is the second and final segment of the QMC Unix Editor - em */
  3. #define EOF -1
  4. #define LBSIZE    512
  5. #define    SIGHUP    1
  6. #define    SIGINTR    2
  7. #define    SIGQUIT    3
  8. #define UNIXBUFL 100
  9. #define error    goto errlab
  10. #define TABSET    7    /* this should be determined dynamically */
  11.  
  12. #define RAW    040
  13. #define ECHO    010
  14. #define OPEN    '/'
  15. #define BELL    07
  16. #define ESCAPE    033
  17. #define SPACE    040
  18. #define BACKSL    0134
  19. #define RUBOUT    0177
  20. #define CTRLA    01
  21. #define CTRLB    02
  22. #define CTRLC    03
  23. #define CTRLD    04
  24. #define CTRLE    05
  25. #define CTRLF    06
  26. #define CTRLH    010
  27. #define CTRLI    011
  28. #define CTRLQ    021
  29. #define CTRLR    022
  30. #define CTRLS    023
  31. #define    CTRLV    026
  32. #define CTRLW    027
  33. #define CTRLX    030
  34. #define CTRLZ    032
  35.  
  36. #define ITT    0100000
  37.  
  38. extern char    peekc, *linebp, *loc2, linebuf[LBSIZE], genbuf[LBSIZE],
  39.             unixbuffer[UNIXBUFL];
  40. extern int    onquit,onhup;
  41. extern int    *zero, *addr1, *addr2;
  42. extern int    *errlab;
  43. int    margin    LBSIZE - 40;
  44. int    oflag;
  45. char    *threshold, *savethresh;
  46. char    *lnp,*gnp,*brp;
  47. int    savetty, tty[3];
  48.  
  49.  
  50. op(inglob)
  51. {    register *a1;
  52.     register char *lp, *sp;
  53.     char seof, ch;
  54.     int t, nl, getopen(), getnil();
  55.  
  56.     threshold = genbuf + margin;
  57.     savethresh = 0;
  58.  
  59.     switch (ch = peekc = getchar()) {
  60.         case BACKSL:
  61.             t = 1;
  62.             delete();
  63.             addr2 = addr1;
  64.             break;
  65.  
  66.         case ';':
  67.         case '+':
  68.             t = 0;
  69.             break;
  70.  
  71.         case '-':
  72.             t =1;
  73.             break;
  74.  
  75.         default:
  76.             goto normal;
  77.  
  78.     }
  79.  
  80.     peekc = 0;
  81.     if(addr1 != addr2) error;
  82.     oflag = 0;
  83.     append(getnil, addr2 - t);
  84.     addr1 = addr2 =- (t-1);
  85.     setdot();
  86.     nonzero();
  87.  
  88.  
  89. normal:
  90.     if(addr1 == zero) error;
  91.     if ((seof = getchar()) == '\n') { loc2 = linebuf-1;
  92.                         seof = 0;}
  93.         else compile(seof);
  94.     setraw(); /* terminal into raw mode*/
  95.  
  96.     for ( a1 = addr1; a1 <= addr2; a1++) {
  97.         if (seof) {if (execute(0,a1) == 0) continue;}
  98.             else getline(*a1);
  99.         puts("\\\r");
  100.         lp = linebuf;
  101.         sp = genbuf;
  102.         inglob =| 01;
  103.         while (lp < loc2){ putch(*lp); *sp++ = *lp++; }
  104.         lnp = lp;
  105.         gnp = sp;
  106.  
  107.  
  108.         oflag = gopen(); /* open the current line */
  109.         *a1 = putline(); /* write revised line */
  110.             nl = append( getopen,a1);
  111.             a1 =+ nl;
  112.             addr2 =+ nl;
  113.     }
  114.     setcook(); /* terminal in cook mode */
  115.     putchar('\n');
  116.     if (inglob == 0) { putchar('?'); error;}
  117. }
  118.  
  119. getnil()
  120. {
  121.     if(oflag == EOF) return EOF;
  122.     linebuf[0] = '\0';
  123.     oflag = EOF;
  124.     return 0;
  125. }
  126.  
  127. setraw()
  128. {
  129.     if(gtty(0,tty) == -1) error;
  130.     savetty = tty[2];
  131.     tty[2] =| RAW;
  132.     stty(0, tty);
  133. }
  134.  
  135. setcook()
  136. {
  137.     tty[2] = savetty;
  138.     stty(0, tty);
  139. }
  140.  
  141. inword(c) char c;
  142. {    if(c -'0' < 0 ) return 0;
  143.     if(c - '9' <= 0) return 1;
  144.     c =& 0137;
  145.     if(c -'A' < 0) return 0;
  146.     if(c - 'Z' <= 0) return 1;
  147.     return 0;
  148. }
  149.  
  150. rescan()
  151. {    register char *lp, *sp;
  152.  
  153.     if(savethresh) { threshold = savethresh; savethresh = 0; }
  154.     lp = linebuf;
  155.     sp = genbuf;
  156.     while(*lp++ = *sp++) if(lp>linebuf+LBSIZE) {
  157.                 *(--lp) = 0;
  158.                 return 0;
  159.                 }
  160. }
  161.  
  162.  
  163. gopen()
  164.     /*leaves revised line in linebuf,
  165.     returns 0 if more to follow, EOF if last line */
  166. {    register char *lp, *sp, *rp;
  167.     char ch, *br, *pr;
  168.     int tabs;
  169.     int retcode, savint, pid, rpid;
  170.  
  171.     lp = lnp;
  172.     sp = gnp;
  173.     tabs = 0;
  174.     for (rp = genbuf; rp < sp; rp++) if (*rp == CTRLI) tabs =+ TABSET;
  175.  
  176.     for(;;){
  177.         switch (ch = getchar()) {
  178.  
  179.             case CTRLD:
  180.             case ESCAPE:    /* close the line (see case '\n' also) */
  181.             close:
  182.                 putb(lp);
  183.                 while(*sp++ = *lp++);
  184.                 rescan();
  185.                 return(EOF);
  186.  
  187.             case CTRLA:    /* verify line */
  188.             verify: puts("\\\r");
  189.                 *sp = '\0';
  190.                 putb(genbuf);
  191.                 continue;
  192.  
  193.             case CTRLB:    /* back a word */
  194.                 if(sp == genbuf) goto backquery;
  195.  
  196.                 while((*(--lp) = *(--sp)) == SPACE)
  197.                     if(sp < genbuf) goto out;
  198.                 if(inword(*sp)) {
  199.                     while(inword((*(--lp) = *(--sp))))
  200.                          if(sp < genbuf) goto out;
  201.                     if(*sp == SPACE)
  202.                         while((*(--lp) = *(--sp)) == SPACE)
  203.                             if(sp < genbuf) goto out;
  204.                 }    
  205.                 else while(sp >= genbuf && !inword(*sp))
  206.                     if((*lp-- = *sp--) == CTRLI) tabs =- TABSET;
  207.             out:    sp++;
  208.                 lp++;
  209.                 goto verify;
  210.  
  211.             case CTRLC:
  212.             case CTRLQ: /* forward one char */
  213.                 if(*lp == 0) goto backquery;
  214.                 putch(*lp);
  215.             forward:
  216.                 if(*lp == SPACE && sp + tabs > threshold) {
  217.                     putch('\r');
  218.                     ch = '\n'; putch(ch);
  219.                     lp++;
  220.                     *sp++ = ch;
  221.                     br = sp;
  222.                     break;
  223.                 }
  224.                 if(*lp == CTRLI) tabs =+ TABSET;
  225.                 *sp++ = *lp++;    /* one character */
  226.                 if(sp + tabs == threshold) putch(BELL);
  227.                 continue;
  228.  
  229.  
  230.             case CTRLF:
  231.             /* delete forward */
  232.                 while(*lp++);
  233.                 lp--;
  234.                 goto verify;
  235.  
  236.             case CTRLE:
  237.                 putb(lp);
  238.                 goto verify;
  239.  
  240.             case CTRLH:  help(); goto verify;
  241.  
  242.             case CTRLR:    /* margin release */
  243.                 if(threshold-genbuf<LBSIZE-40) {
  244.                     savethresh = threshold;
  245.                     threshold = genbuf+LBSIZE-40;
  246.                 }
  247.                 else goto backquery;
  248.                 continue;
  249.  
  250.             case CTRLS:    /* re-set to start of line */
  251.                 while(*sp++ = *lp++);
  252.                 rescan();
  253.                 lp = linebuf; sp = genbuf;
  254.                 tabs = 0;
  255.                 goto verify;
  256.  
  257.             case CTRLV:    /* verify spelling */
  258.                 rp = sp;
  259.                 pr = unixbuffer+UNIXBUFL-2;
  260.                 *pr = 0;
  261.                 while(*(--rp) == SPACE);
  262.                 while(inword(*rp) && rp >= genbuf)
  263.                     *(--pr) = *rp--;
  264.                 if(*pr == 0) goto backquery;
  265.                 puts("!!");
  266.                 setcook();
  267.                 if((pid = fork()) == 0)
  268.                     {signal(SIGHUP, onhup);
  269.                       signal(SIGQUIT, onquit);
  270.                       execl("/bin/spell", "spell", pr, 0);
  271.                       puts("sorry, can't spell today");
  272.                       exit();
  273.                 }
  274.                 savint = signal(SIGINTR,1);
  275.                 while((rpid = wait(&retcode)) != pid
  276.                      && rpid != -1);
  277.                 signal(SIGINTR, savint);
  278.                 setraw();
  279.                 puts("!!");
  280.                 goto verify;
  281.  
  282.  
  283.             case CTRLW:    /* forward one word */
  284.                 if(*lp == '\0') goto backquery;
  285.                 while(*lp == SPACE)
  286.                     putch(*sp++ = *lp++);
  287.                 if(inword(*lp)) {
  288.                     while(inword(*lp)) {
  289.                         putch(*sp++ = *lp++);
  290.                         if(sp+tabs==threshold) putch(BELL);
  291.                     }
  292.                     if(*lp == SPACE) {
  293.                         if(sp+tabs>threshold) {
  294.                             ch = '\n';
  295.                             lp++;
  296.                             *sp++ = ch;
  297.                             br = sp;
  298.                             putch('\r');
  299.                             putch('\n');
  300.                         }
  301.                         if(*lp == SPACE)
  302.                             while(*(lp+1) == SPACE)
  303.                                putch(*sp++ = *lp++);
  304.                     }
  305.                 }
  306.                 else while(*lp && !inword(*lp)) {
  307.                     if(*lp == CTRLI) tabs =+ TABSET;
  308.                     putch(*sp++ = *lp++);
  309.                     if(sp+tabs==threshold) putch(BELL);
  310.                 }
  311.                 break;
  312.  
  313.  
  314.             case CTRLZ:    /* delete a word */
  315.                 if(sp == genbuf) goto backquery;
  316.  
  317.                 while(*(--sp) == SPACE) if(sp < genbuf) goto zout;
  318.                 if(inword(*sp)) {
  319.                     while(inword(*(--sp)))
  320.                          if(sp < genbuf) goto zout;
  321.                     if(*sp == SPACE)
  322.                         while(*(--sp) == SPACE)
  323.                             if(sp < genbuf) goto zout;
  324.                 }    
  325.                 else while(sp >= genbuf && !inword(*sp))
  326.                     if(*sp-- == CTRLI) tabs =- TABSET;
  327.             zout:    sp++;
  328.                 goto verify;
  329.  
  330.             case '@':    /*delete displayed line */
  331.             /* delete backward */
  332.                 sp = genbuf;
  333.                 tabs = 0;
  334.                 goto verify;
  335.  
  336.             case RUBOUT:
  337.                 puts("\\\r");
  338.                 setcook();
  339.                 error;
  340.  
  341.             case CTRLX:
  342.                 putch('#');
  343.             case '#':
  344.                 if( sp == genbuf) goto backquery;
  345.                 if(*(--sp) == CTRLI) tabs =- TABSET;
  346.                 if( ch == CTRLX) goto verify;
  347.                 continue;
  348.  
  349.             case '\n':
  350.             case '\r': /* split line, actually handled at
  351.                     end of switch block */
  352.                 ch = '\n';
  353.                 *sp++ = ch;
  354.                 br = sp;
  355.                 break;
  356.  
  357.             case BACKSL: /* special symbols */
  358.                 switch (ch = peekc = getchar()) {
  359.                 case '(':  ch = '{'; peekc = 0; break;
  360.                 case ')':  ch = '}'; peekc = 0; break;
  361.                 case '!':  ch = '|'; peekc = 0; break;
  362.                 case '^':  ch = '~'; peekc = 0; break;
  363.                 case '\'':  ch = '`'; peekc = 0; break;
  364.                 case BACKSL:
  365.                 case '#':
  366.                 case '@':  peekc = 0; break;
  367.  
  368.                 default:  if(ch >= 'a' && ch <= 'z') {
  369.                         peekc = 0; ch =- 040;}
  370.                     else {
  371.                         *(--lp) = BACKSL;
  372.                         goto forward;
  373.                         }
  374.                 }
  375.  
  376.             default:    *(--lp) = ch;
  377.                     goto forward;
  378.             }
  379.  
  380.         if (ch == '\n') { /* split line */
  381.             if(*(br-1) != '\n') puts("!!");    /*debugging only */
  382.             lnp = sp;
  383.             while(*sp++ = *lp++); /*move the rest over */
  384.             brp  = linebuf +(br - genbuf);
  385.             lnp = linebuf + (lnp - br);
  386.             rescan();
  387.             *(brp-1) ='\0';
  388.             return(0);
  389.             }
  390.         else continue;
  391.     backquery: putch(CTRLZ);
  392.         } /* end of forloop block */
  393. } /* end of gopen */
  394.  
  395.  
  396.  
  397. getopen()  /* calls gopen, deals with multiple lines etc. */
  398. {    register char *lp, *sp;
  399.     if (oflag == EOF) return EOF;
  400.  
  401. /* otherwise, multiple lines */
  402.  
  403.     lp = linebuf;
  404.     sp = brp;
  405.     while(*lp++ = *sp++); /*move it down */
  406.     sp = genbuf;
  407.     lp = linebuf;
  408.     while (lp < lnp) *sp++ = *lp++;
  409.     gnp = sp;
  410.     /* should check whether empty line returned */
  411.     oflag = gopen();
  412.     return 0;
  413. }
  414.  
  415. putch(ch) char ch;
  416. { write(1, &ch, 1); }
  417.  
  418. putb(ptr)    char *ptr;    /*display string */
  419.  
  420. {    register char *p;
  421.  
  422.     p = ptr;
  423.     if(*p == '\0') return;
  424.     while(*(++p));
  425.     write(1,ptr,p-ptr);
  426. }
  427.  
  428. help()
  429. {    puts("\n");
  430.     puts("    ^A    display Again        ^Q    next character");
  431.     puts("    ^B    backup word        ^R    Release margin");
  432.     puts("    ESCAPE                ^S    re-scan from Start");
  433.     puts("    or ^D    close line and exit    ^V    verify spelling");
  434.     puts("    ^E    display to End        ^W    next Word");
  435.     puts("    ^F    delete line Forward    ^Z    delete word");
  436.     puts("    ^H    Help            # or ^X delete character");
  437.     puts("    RUBOUT    exit unchanged        @    delete line backward\n");
  438.     puts("    Other characters (including RETURN) inserted as typed");
  439. }
  440.  
  441.