home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / ue312os2.zip / src / mpe.c < prev    next >
C/C++ Source or Header  |  1994-08-26  |  19KB  |  944 lines

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