home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / UE311C.ZIP / MPE.C < prev    next >
C/C++ Source or Header  |  1991-01-30  |  18KB  |  935 lines

  1. /***
  2.     MPE driver/Microemacs 3.10b/3.10k,
  3.     Copyright 1991 D. Lawrence, C. Smith
  4.  ***/
  5.  
  6. /** Include files **/
  7. #include <stdio.h>            /* Standard I/O definitions    */
  8. #include "estruct.h"            /* Emacs definitions        */
  9.  
  10. /** Do nothing routine **/
  11. int scnothing()
  12. {
  13.     return(0);
  14. }
  15.  
  16. /** Only compile for MPE machines **/
  17. #if MPE
  18.  
  19. /** Include files **/
  20. #include "eproto.h"            /* Function definitions        */
  21. #include "edef.h"            /* Global variable definitions    */
  22. #include "elang.h"            /* Language definitions        */
  23.  
  24. /** Parameters **/
  25. #define NKEYENT        300        /* Number of keymap entries    */
  26. #define NINCHAR        64        /* Input buffer size        */
  27. #define NOUTCHAR    256        /* Output buffer size        */
  28. #define MARGIN        8        /* Margin size            */
  29. #define SCRSIZ        64        /* Scroll for margin        */
  30. #define NPAUSE        10        /* # times thru update to pause */
  31.  
  32. /** Constants **/
  33. #define CCE        2        /* Command successful        */
  34. #define TIMEOUT        255        /* No character available    */
  35.  
  36. /** Type definitions **/
  37. struct keyent {                /* Key mapping entry        */
  38.     struct keyent * samlvl;        /* Character on same level    */
  39.     struct keyent * nxtlvl;        /* Character on next level    */
  40.     unsigned char ch;        /* Character            */
  41.     int code;            /* Resulting keycode        */
  42. };
  43.  
  44. /** Intrinsics **/
  45. #pragma intrinsic FCLOSE        /* File close intrinsic        */
  46. #pragma intrinsic FREAD            /* File read intrinsic        */
  47. #pragma intrinsic FOPEN            /* File open intrinsic        */
  48. #pragma intrinsic FCONTROL        /* File control intrinsic    */
  49. #pragma intrinsic FDEVICECONTROL    /* Device control intrinsic    */
  50. #pragma intrinsic FWRITE        /* File write intrinsic        */
  51.  
  52. /** Local variables **/
  53. static short mpetermin;            /* Terminal input        */
  54. static short mpetermout;        /* Terminal output        */
  55. static short mpetype;            /* Terminal type        */
  56. static short mpeoecho;            /* Old echo mode        */
  57. static short mpeotahd;            /* Old typeahead mode        */
  58. #if COLOR
  59. static int cfcolor = -1;        /* Current forground color    */
  60. static int cbcolor = -1;        /* Current background color    */
  61. #endif /* COLOR */
  62. static int inbuf[NINCHAR];        /* Input buffer            */
  63. static int * inbufh =            /* Head of input buffer        */
  64.     inbuf;
  65. static int * inbuft =            /* Tail of input buffer        */
  66.     inbuf;
  67. static unsigned char outbuf[NOUTCHAR];    /* Output buffer        */
  68. static unsigned char * outbuft =     /* Output buffer tail        */
  69.     outbuf;
  70. static unsigned char keyseq[256];    /* Prefix escape sequence table    */
  71. static struct keyent keymap[NKEYENT];    /* Key map            */
  72. static struct keyent * nxtkey =        /* Next free key entry        */
  73.     keymap;
  74.  
  75. /** Terminal definition block **/
  76. int scopen(), scclose(), ttgetc(), ttputc(), ttflush();
  77. int scmove(), sceeol(), sceeop(), scbeep(), screv();
  78. #if COLOR
  79. int scfcol(), scbcol();
  80. #endif /* COLOR */
  81. TERM term = {
  82.     23,                /* Maximum number of rows    */
  83.     23,                /* Current number of rows    */
  84.     80,                /* Maximum number of columns    */
  85.     80,                /* Current number of columns    */
  86.     MARGIN,                /* Margin for extending lines    */
  87.     SCRSIZ,                /* Scroll size for extending    */
  88.     NPAUSE,                /* # times thru update to pause    */
  89.     scopen,                /* Open terminal routine    */
  90.     scclose,            /* Close terminal routine    */
  91.     scnothing,            /* Open keyboard routine    */
  92.     scnothing,            /* Close keyboard routine    */
  93.     ttgetc,                /* Get character routine    */
  94.     ttputc,                /* Put character routine    */
  95.     ttflush,            /* Flush output routine        */
  96.     scmove,                /* Move cursor routine        */
  97.     sceeol,                /* Erase to end of line routine    */
  98.     sceeop,                /* Erase to end of page routine    */
  99.     scbeep,                /* Beep! routine        */
  100.     screv,                /* Set reverse video routine    */
  101.     scnothing,            /* Set resolution routine    */
  102. #if COLOR
  103.     scfcol,                /* Set forground color routine    */
  104.     scbcol                /* Set background color routine    */
  105. #endif /* COLOR */
  106. };
  107.  
  108. /** Open terminal device **/
  109. int ttopen()
  110. {
  111.     short value;
  112.     short error;
  113.  
  114.     /* Open terminal for input */
  115.     mpetermin = FOPEN(0, 0444, 0, -80);
  116.     if (ccode() != CCE) {
  117. #ifdef DEBUG
  118.         printf("Cannot open $STDIN\n");
  119. #endif /* DEBUG */
  120.         goto error_stdin;
  121.     }
  122.  
  123.     /* Open terminal for output */
  124.     mpetermout = FOPEN(0, 0414, 1, -80);
  125.     if (ccode() != CCE) {
  126. #ifdef DEBUG
  127.         printf("Cannot open $STDLIST\n");
  128. #endif /* DEBUG */
  129.         goto error_stdlist;
  130.     }
  131.  
  132.     /* Get terminal type */
  133.     FCONTROL(mpetermin, 39, &mpetype);
  134.     if (ccode() != CCE) {
  135. #ifdef DEBUG
  136.         printf("FCONTROL(39) failed\n");
  137. #endif /* DEBUG */
  138.         goto error_other;
  139.     }
  140.  
  141.     /* Set transparent editing mode */
  142. #ifdef DEBUG
  143.     value = '*';
  144. #else
  145.     value = '\377';
  146. #endif
  147.     FDEVICECONTROL(mpetermin, &value, 1, 192, 15, 2, &error);
  148.     if (ccode() != CCE) {
  149. #ifdef DEBUG
  150.         printf("FDEVICECONTROL(15) failed; error %d\n", error);
  151. #endif /* DEBUG */
  152.         goto error_other;
  153.     }
  154.  
  155.     /* Turn off echo */
  156.     mpeoecho = 0;
  157.     FDEVICECONTROL(mpetermin, &mpeoecho, 1, 192, 4, 3, &error);
  158.     if (ccode() != CCE) {
  159. #ifdef DEBUG
  160.         printf("FDEVICECONTROL(4) failed; error %d\n", error);
  161. #endif /* DEBUG */
  162.         goto error_other;
  163.     }
  164.  
  165.     /* Set type ahead */
  166.     mpeotahd = 1;
  167.     FDEVICECONTROL(mpetermin, &mpeotahd, 1, 192, 51, 3, &error);
  168.     if (ccode() != CCE) {
  169. #ifdef DEBUG
  170.         printf("FDEVICECONTROL(51) failed; error %d\n", error);
  171. #endif /* DEBUG */
  172.         goto error_other;
  173.     }
  174.  
  175.     /* Success */
  176.     return(0);
  177.  
  178. error_other:
  179.     FCLOSE(mpetermout, 0, 0);
  180. error_stdlist:
  181.     FCLOSE(mpetermin, 0, 0);
  182. error_stdin:
  183.     return -1;
  184. }
  185.  
  186. /** Close terminal device **/
  187. int ttclose()
  188. {
  189.     short value;
  190.     short error;
  191.  
  192.     /* Cancel transparent editing mode */
  193.     value = 0;
  194.     FDEVICECONTROL(mpetermin, &value, 1, 192, 15, 2, &error);
  195. #ifdef DEBUG
  196.     if (ccode() != CCE) {
  197.         printf("FDEVICECONTROL(15) failed; error %d\n", error);
  198.     }
  199. #endif /* DEBUG */
  200.  
  201.     /* Restore echoing */
  202.     FDEVICECONTROL(mpetermin, &mpeoecho, 1, 192, 4, 2, &error);
  203. #ifdef DEBUG
  204.     if (ccode() != CCE) {
  205.         printf("FDEVICECONTROL(4) failed; error %d\n", error);
  206.     }
  207. #endif /* DEBUG */
  208.  
  209.     /* Restore type ahead */
  210.     FDEVICECONTROL(mpetermin, &mpeotahd, 1, 192, 51, 2, &error);
  211. #ifdef DEBUG
  212.     if (ccode() != CCE) {
  213.         printf("FDEVICECONTROL(51) failed; error %d\n", error);
  214.     }
  215. #endif /* DEBUG */
  216.  
  217.     /* Close terminal */
  218.     FCLOSE(mpetermin, 0, 0);
  219.     FCLOSE(mpetermout, 0, 0);
  220.  
  221.     /* Success */
  222.     return(0);
  223. }
  224.  
  225. /** Flush output buffer to display **/
  226. int ttflush()
  227. {
  228.     int len;
  229.  
  230.     /* Compute length of write */
  231.     len = outbuft - outbuf;
  232.     if (len == 0)
  233.         return(0);
  234.  
  235.     /* Reset buffer position */
  236.     outbuft = outbuf;
  237.  
  238.     /* Perform write to screen */
  239.     FWRITE(mpetermout, outbuf, -len, 0320);
  240. #ifdef DEBUG
  241.     if (ccode() != CCE) {
  242.         printf("FWRITE fails\n");
  243.     }
  244. #endif
  245.     return 0;
  246. }
  247.  
  248. /** Put character onto display **/
  249. int ttputc(ch)
  250. char ch;                /* Character to display        */
  251. {
  252.     /* Check for buffer full */
  253.     if (outbuft == &outbuf[sizeof(outbuf)])
  254.         ttflush();
  255.  
  256.     /* Add to buffer */
  257.     *outbuft++ = ch;
  258.     return(0);
  259. }
  260.  
  261. /** Put out sequence, with padding **/
  262. void putpad(pad, seq)
  263. int pad;                /* Number of padding characters    */
  264. char * seq;                /* Character sequence        */
  265. {
  266.     /* Check for null */
  267.     if (!seq)
  268.         return;
  269.  
  270.     /* Output sequence */
  271.     while (*seq)
  272.         ttputc(*seq++);
  273.  
  274.     /* Output padding */
  275.     while (pad-- > 0)
  276.         ttputc('\0');
  277. }
  278.  
  279. /** Add character sequence to keycode entry **/
  280. void addkey(seq, fn)
  281. unsigned char * seq;            /* Character sequence        */
  282. int fn;                    /* Resulting keycode        */
  283. {
  284.     int first;
  285.     struct keyent * cur, * nxtcur;
  286.  
  287.     /* Skip on null sequences */
  288.     if (!seq)
  289.         return;
  290.  
  291.     /* Skip single character sequences */
  292.     if (strlen(seq) < 2)
  293.         return;
  294.  
  295.     /* If no keys defined, go directly to insert mode */
  296.     first = 1;
  297.     if (nxtkey != keymap) {
  298.         
  299.         /* Start at top of key map */
  300.         cur = keymap;
  301.         
  302.         /* Loop until matches exhast */
  303.         while (*seq) {
  304.             
  305.             /* Do we match current character */
  306.             if (*seq == cur->ch) {
  307.                 
  308.                 /* Advance to next level */
  309.                 seq++;
  310.                 cur = cur->nxtlvl;
  311.                 first = 0;
  312.             } else {
  313.                 
  314.                 /* Try next character on same level */
  315.                 nxtcur = cur->samlvl;
  316.                 
  317.                 /* Stop if no more */
  318.                 if (nxtcur)
  319.                     cur = nxtcur;
  320.                 else
  321.                     break;
  322.             }
  323.         }
  324.     }
  325.     
  326.     /* Check for room in keymap */
  327.     if (strlen(seq) > NKEYENT - (nxtkey - keymap))
  328.         return;
  329.         
  330.     /* If first character in sequence is inserted, add to prefix table */
  331.     if (first)
  332.         keyseq[*seq] = 1;
  333.         
  334.     /* If characters are left over, insert them into list */
  335.     for (first = 1; *seq; first = 0) {
  336.         
  337.         /* Make new entry */
  338.         nxtkey->ch = *seq++;
  339.         nxtkey->code = fn;
  340.         
  341.         /* If root, nothing to do */
  342.         if (nxtkey != keymap) {
  343.             
  344.             /* Set first to samlvl, others to nxtlvl */
  345.             if (first)
  346.                 cur->samlvl = nxtkey;
  347.             else
  348.                 cur->nxtlvl = nxtkey;
  349.         }
  350.  
  351.         /* Advance to next key */
  352.         cur = nxtkey++;
  353.     }
  354. }
  355.  
  356. /** Grab input characters, with wait **/
  357. unsigned char grabwait()
  358. {
  359.     char ch;
  360.     int count;
  361.  
  362.     /* Read character */
  363.     count = FREAD(mpetermin, &ch, -1);
  364.     if (count != 1) {
  365.         puts("** Horrible read error occured **");
  366.         exit(1);
  367.     }
  368.  
  369.     /* Return new character */
  370.     return ch;
  371. }
  372.  
  373. /** Grab input characters, short wait **/
  374. unsigned char grabnowait()
  375. {
  376.     char ch;
  377.     int count;
  378.     short value;
  379.     short error;
  380.  
  381.     /* Set read timeout */
  382.     value = 1;
  383.     FDEVICECONTROL(mpetermin, &value, 1, 192, 2, 2, &error);
  384. #ifdef DEBUG
  385.     if (ccode() != CCE) {
  386.         printf("FDEVICECONTROL(2) failed; error %d\n", error);
  387.     }
  388. #endif /* DEBUG */
  389.  
  390.     /* Read character */
  391.     count = FREAD(mpetermin, &ch, -1);
  392.     if (count == 0)
  393.         return TIMEOUT;
  394.     if (count != 1) {
  395.         puts("** Horrible read error occured **");
  396.         exit(1);
  397.     }
  398.  
  399.     /* Return new character */
  400.     return ch;
  401. }
  402.  
  403. /** Queue input character **/
  404. void qin(ch)
  405. int ch;                    /* Character to add        */
  406. {
  407.     /* Check for overflow */
  408.     if (inbuft == &inbuf[sizeof(inbuf)]) {
  409.         
  410.         /* Annoy user */
  411.         scbeep();
  412.         return;
  413.     }
  414.     
  415.     /* Add character */
  416.     *inbuft++ = ch;
  417. }
  418.  
  419. /** Cook input characters **/
  420. void cook()
  421. {
  422.     unsigned char ch;
  423.     struct keyent * cur;
  424.     
  425.     /* Get first character untimed */
  426.     ch = grabwait();
  427.     qin(ch);
  428.     
  429.     /* Skip if the key isn't a special leading escape sequence */
  430.     if (keyseq[ch] == 0)
  431.         return;
  432.  
  433.     /* Start at root of keymap */
  434.     cur = keymap;
  435.  
  436.     /* Loop until keymap exhasts */
  437.     while (cur) {
  438.  
  439.         /* Did we find a matching character */
  440.         if (cur->ch == ch) {
  441.  
  442.             /* Is this the end */
  443.             if (cur->nxtlvl == NULL) {
  444.  
  445.                 /* Replace all character with new sequence */
  446.                 inbuft = inbuf;
  447.                 qin(cur->code);
  448.                 return;
  449.             } else {
  450.                 /* Advance to next level */
  451.                 cur = cur->nxtlvl;
  452.             
  453.                 /* Get next character, timed */
  454.                 ch = grabnowait();
  455.                 if (ch == TIMEOUT)
  456.                     return;
  457.  
  458.                 /* Queue character */
  459.                 qin(ch);
  460.             }
  461.         } else
  462.             /* Try next character on same level */
  463.             cur = cur->samlvl;
  464.     }
  465. }
  466.  
  467. /** Return cooked characters **/
  468. int ttgetc()
  469. {
  470.     int ch;
  471.  
  472.     /* Loop until character found */
  473.     while (1) {
  474.     
  475.         /* Get input from buffer, if available */
  476.         if (inbufh != inbuft) {
  477.             ch = *inbufh++;
  478.             if (inbufh == inbuft)
  479.                 inbufh = inbuft = inbuf;
  480.             break;
  481.         } else
  482.  
  483.             /* Fill input buffer */
  484.             cook();
  485.     }
  486.     
  487.     /* Return next character */
  488.     return ch;
  489. }
  490.  
  491. #if TYPEAH
  492. int typahead()
  493. {
  494.     /* See if internal buffer is non-empty */
  495.     if (inbufh != inbuft)
  496.         return 1;
  497.  
  498.     /* Now check with system */
  499.     /* Offhand, I don't see a function call but I'm sure there is a way */
  500.     return 0;
  501. }
  502. #endif /* TYPEAH */
  503.  
  504. /** Initialize screen package **/
  505. int scopen()
  506. {
  507.     /* Open terminal device */
  508.     if (ttopen()) {
  509.         puts("Cannot open terminal");
  510.         exit(1);
  511.     }
  512.  
  513.     /* Success */
  514.     return(0);
  515. }
  516.  
  517. /** Close screen package **/
  518. int scclose()
  519. {
  520.     /* Close terminal device */
  521.     ttclose();
  522.  
  523.     /* Success */
  524.     return(0);
  525. }
  526.  
  527. /** Move cursor **/
  528. int scmove(row, col)
  529. int row;                /* Row number            */
  530. int col;                /* Column number        */
  531. {
  532.     char buffer[12];
  533.  
  534.     /* Output addressing */
  535.     sprintf(buffer, "\033&a%dc%dY", col, row);
  536.     putpad(6, buffer);
  537.  
  538.     /* Success */
  539.     return(0);
  540. }
  541.  
  542. /** Erase to end of line **/
  543. int sceeol()
  544. {
  545.     /* Send erase sequence */
  546.     putpad(0, "\033K");
  547.  
  548.     /* Success */
  549.     return(0);
  550. }
  551.  
  552. /** Clear screen **/
  553. int sceeop()
  554. {
  555. #if COLOR
  556.     scfcol(gfcolor);
  557.     scbcol(gbcolor);
  558. #endif /* COLOR */
  559.  
  560.     /* Send clear sequence */
  561.     putpad(0, "\033H\033J");
  562.  
  563.     /* Success */
  564.     return(0);
  565. }
  566.  
  567. /** Set reverse video state **/
  568. int screv(state)
  569. int state;                /* New state            */
  570. {
  571. #if COLOR
  572.     int ftmp, btmp;        /* temporaries for colors */
  573. #endif /* COLOR */
  574.  
  575.     /* Set reverse video state */
  576.     putpad(0, state ? "\033&dJ" : "\033&d@");
  577.  
  578. #if COLOR
  579.     if (state == FALSE) {
  580.         ftmp = cfcolor;
  581.         btmp = cbcolor;
  582.         cfcolor = -1;
  583.         cbcolor = -1;
  584.         scfcol(ftmp);
  585.         scbcol(btmp);
  586.     }
  587. #endif /* COLOR */
  588.  
  589.     /* Success */
  590.     return(0);
  591. }
  592.  
  593. /** Beep **/
  594. scbeep()
  595. {
  596.     /* The old standby method */
  597.     ttputc('\7');
  598.  
  599.     /* Success */
  600.     return(0);
  601. }
  602.  
  603. #if COLOR
  604. /** Set foreground color **/
  605. int scfcol(color)
  606. int color;        /* Color to set            */
  607. {
  608.     /* Skip if already the correct color */
  609.     if (color == cfcolor)
  610.         return;
  611.  
  612.     /* Set the color */
  613.     cfcolor = color;
  614.     return(0);
  615. }
  616.  
  617. /** Set background color **/
  618. int scbcol(color)
  619. int color;            /* Color to set            */
  620. {
  621.     /* Skip if already the correct color */
  622.     if (color == cbcolor)
  623.         return;
  624.  
  625.     /* Set the color */
  626.         cbcolor = color;
  627.     return(0);
  628. }
  629. #endif /* COLOR */
  630.  
  631. /** Set palette **/
  632. int spal(cmd)
  633. char * cmd;                /* Palette command        */
  634. {
  635.     int code, dokeymap;
  636.     char * cp;
  637.  
  638.     /* Check for keymapping command */
  639.     if (strncmp(cmd, "KEYMAP ", 7) == 0)
  640.         dokeymap = 1;
  641.     else if (strncmp(cmd, "CLRMAP ", 7) == 0)
  642.         dokeymap = 0;
  643.     else
  644.         return(0);
  645.     cmd += 7;
  646.  
  647.     /* Look for space */
  648.     for (cp = cmd; *cp != '\0'; cp++)
  649.         if (*cp == ' ') {
  650.             *cp++ = '\0';
  651.             break;
  652.         }
  653.     if (*cp == '\0')
  654.         return 1;
  655.  
  656.     /* Perform operation */
  657.     if (dokeymap) {
  658.  
  659.         /* Convert to keycode */
  660.         code = stock(cmd);
  661.  
  662.         /* Add to tree */
  663.         addkey(cp, code);
  664.     } else {
  665.  
  666.         /* Convert to color number */
  667.         code = atoi(cmd);
  668.         if (code < 0 || code > 15)
  669.             return 1;
  670.  
  671. #if COLOR
  672.         /* Move color code to capability structure */
  673. #endif /* COLOR */
  674.     }
  675.     return(0);
  676. }
  677.  
  678. /** Get time of day **/
  679. char * timeset()
  680. {
  681.     long int buf; /* Should be time_t */
  682.     char * sp, * cp;
  683.  
  684.     char * ctime();
  685.  
  686.     /* Get system time */
  687.     time(&buf);
  688.  
  689.     /* Pass system time to converter */
  690.     sp = ctime(&buf);
  691.  
  692.     /* Eat newline character */
  693.     for (cp = sp; *cp; cp++)
  694.         if (*cp == '\n') {
  695.             *cp = '\0';
  696.             break;
  697.         }
  698.     return sp;
  699. }
  700.  
  701. /** Callout to system to perform command **/
  702. int callout(cmd)
  703. char * cmd;                /* Command to execute        */
  704. {
  705.     int status;
  706.  
  707.     /* Close down */
  708.     scmove(term.t_nrow, 0);
  709.     ttflush();
  710.     ttclose();
  711.  
  712.     /* Do command */
  713.     status = system(cmd) == 0;
  714.  
  715.     /* Restart system */
  716.         sgarbf = TRUE;
  717.     if (ttopen()) {
  718.         puts("** Error reopening terminal device **");
  719.         exit(1);
  720.     }
  721.  
  722.     /* Success */
  723.         return status;
  724. }
  725.  
  726. /** Create subshell **/
  727. int spawncli(f, n)
  728. int f;                    /* Flags            */
  729. int n;                    /* Argument count        */
  730. {
  731.     char * sh;
  732.  
  733.     char * getenv();
  734.  
  735.     /* Don't allow this command if restricted */
  736.     if (restflag)
  737.         return resterr();
  738.  
  739.     /* Do shell */
  740.     return callout("ci.pub.sys");
  741. }
  742.  
  743. /** Spawn a command **/
  744. int spawn(f, n)
  745. int f;                    /* Flags            */
  746. int n;                    /* Argument count        */
  747. {
  748.     char line[NLINE];
  749.     int s;
  750.  
  751.     /* Don't allow this command if restricted */
  752.     if (restflag)
  753.         return resterr();
  754.  
  755.     /* Get command line */
  756.     s = mlreply("!", line, NLINE);
  757.     if (!s)
  758.         return s;
  759.  
  760.     /* Perform the command */
  761.     s = callout(line);
  762.  
  763.     /* if we are interactive, pause here */
  764.     if (clexec == FALSE) {
  765.             mlwrite("[End]");
  766.         ttflush();
  767.         ttgetc();
  768.         }
  769.         return s;
  770. }
  771.  
  772. /** Execute program **/
  773. int execprg(f, n)
  774. int f;                    /* Flags            */
  775. int n;                    /* Argument count        */
  776. {
  777.     /* Same as spawn */
  778.     return spawn(f, n);
  779. }
  780.  
  781. /** Pipe output of program to buffer **/
  782. int pipecmd(f, n)
  783. int f;                    /* Flags            */
  784. int n;                    /* Argument count        */
  785. {
  786.     char line[NLINE];
  787.     int s;
  788.     BUFFER * bp;
  789.     WINDOW * wp;
  790.     static char filnam[] = "command";
  791.  
  792.     /* Don't allow this command if restricted */
  793.     if (restflag)
  794.         return resterr();
  795.  
  796.     /* Get pipe-in command */
  797.     s = mlreply("@", line, NLINE);
  798.     if (!s)
  799.         return s;
  800.  
  801.     /* Get rid of the command output buffer if it exists */
  802.     bp = bfind(filnam, FALSE, 0);
  803.     if (bp) {
  804.         /* Try to make sure we are off screen */
  805.         wp = wheadp;
  806.         while (wp) {
  807.             if (wp->w_bufp == bp) {
  808.                 onlywind(FALSE, 1);
  809.                 break;
  810.             }
  811.             wp = wp->w_wndp;
  812.         }
  813.         if (!zotbuf(bp))
  814.             return(0);
  815.     }
  816.  
  817.     /* Add output specification */
  818.     strcat(line, ">");
  819.     strcat(line, filnam);
  820.  
  821.     /* Do command */
  822.     s = callout(line);
  823.     if (!s)
  824.         return s;
  825.  
  826.     /* Split the current window to make room for the command output */
  827.     if (!splitwind(FALSE, 1))
  828.         return(0);
  829.  
  830.     /* ...and read the stuff in */
  831.     if (!getfile(filnam, FALSE))
  832.         return(0);
  833.  
  834.     /* Make this window in VIEW mode, update all mode lines */
  835.     curwp->w_bufp->b_mode |= MDVIEW;
  836.     wp = wheadp;
  837.     while (wp) {
  838.         wp->w_flag |= WFMODE;
  839.         wp = wp->w_wndp;
  840.     }
  841.  
  842.     /* ...and get rid of the temporary file */
  843.     unlink(filnam);
  844.     return 1;
  845. }
  846.  
  847. /** Filter buffer through command **/
  848. int filter(f, n)
  849. int f;                    /* Flags            */
  850. int n;                    /* Argument count        */
  851. {
  852.     char line[NLINE], tmpnam[NFILEN];
  853.     int s;
  854.     BUFFER * bp;
  855.     static char bname1[] = "fltinp";
  856.     static char filnam1[] = "fltinp";
  857.     static char filnam2[] = "fltout";
  858.  
  859.     /* Don't allow this command if restricted */
  860.     if (restflag)
  861.         return resterr();
  862.  
  863.     /* Don't allow filtering of VIEW mode buffer */
  864.     if (curbp->b_mode & MDVIEW)
  865.         return rdonly();
  866.  
  867.     /* Get the filter name and its args */
  868.     s = mlreply("#", line, NLINE);
  869.     if (!s)
  870.         return s;
  871.  
  872.     /* Setup the proper file names */
  873.     bp = curbp;
  874.     strcpy(tmpnam, bp->b_fname);    /* Save the original name */
  875.     strcpy(bp->b_fname, bname1);    /* Set it to our new one */
  876.  
  877.     /* Write it out, checking for errors */
  878.     if (!writeout(filnam1, "w")) {
  879.         mlwrite("[Cannot write filter file]");
  880.         strcpy(bp->b_fname, tmpnam);
  881.         return(0);
  882.     }
  883.  
  884.     /* Setup input and output */
  885.     strcat(line," <fltinp >fltout");
  886.  
  887.     /* Perform command */
  888.     s = callout(line);
  889.  
  890.     /* If successful, read in file */
  891.     if (s) {
  892.         s = readin(filnam2, FALSE);
  893.         if (s)
  894.             /* Mark buffer as changed */
  895.             bp->b_flag |= BFCHG;
  896.     }
  897.             
  898.  
  899.     /* Reset file name */
  900.     strcpy(bp->b_fname, tmpnam);
  901.  
  902.     /* and get rid of the temporary file */
  903.     unlink(filnam1);
  904.     unlink(filnam2);
  905.  
  906.     /* Show status */
  907.     if (!s)
  908.         mlwrite("[Execution failed]");
  909.     return s;
  910. }
  911.  
  912. #if FLABEL
  913. int fnclabel(f, n)    /* label a function key */
  914. int f,n;    /* default flag, numeric argument [unused] */
  915. {
  916.     /* on machines with no function keys...don't bother */
  917.     return(TRUE);
  918. }
  919. #endif /* FLABEL */
  920.  
  921. /** Get first filename from pattern **/
  922. char *getffile(fspec)
  923. char *fspec;                /* Filename specification    */
  924. {
  925.     return(NULL);
  926. }
  927.  
  928. /** Get next filename from pattern **/
  929. char *getnfile()
  930. {
  931.     return(NULL);
  932. }
  933.  
  934. #endif /* MPE */
  935.