home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / CMDS / memacs400_src.lzh / MEMACS400 / SRC / xvtdos.c < prev    next >
Text File  |  1996-04-25  |  18KB  |  783 lines

  1. /*    XVTDOS.C:    Operating specific I/O and Spawning functions
  2.             under the XVT portability system
  3.             for MicroEMACS 4.00
  4.             (C)Copyright 1995 by Daniel M. Lawrence
  5. */
  6.  
  7. #include        <stdio.h>
  8. #include    "estruct.h"
  9. #include    "eproto.h"
  10.  
  11. #ifdef    XVT
  12. #include        "edef.h"
  13. #include    "elang.h"
  14.  
  15. /* The Mouse driver only works with typeahead defined */
  16. #if    MOUSE
  17. #undef    TYPEAH
  18. #define    TYPEAH    1
  19. #endif
  20.  
  21. #if  TURBO
  22. #include <conio.h>
  23. #include <dir.h>
  24. #include <dos.h>
  25. #include <bios.h>
  26.  
  27. struct ffblk fileblock;    /* structure for directory searches */
  28. #endif
  29. #if    MSC | ZTC
  30. #include <dos.h>
  31.  
  32. struct find_t fileblock;    /* structure for directory searches */
  33. #endif
  34.  
  35. #if     LATTICE | MSC | TURBO | IC | MWC | ZTC
  36. union REGS rg;        /* cpu register for use of DOS calls */
  37. struct SREGS segreg;    /* cpu segment registers         */
  38. int nxtchar = -1;    /* character held from type ahead    */
  39. #endif
  40.  
  41. #if    MSC | TURBO
  42. #include    <process.h>
  43. #endif
  44.  
  45. #if    IC
  46. #include    <time.h>
  47. #endif
  48.  
  49. /*    Some global variable    */
  50. #define INBUFSIZ    40
  51. static int mexist;    /* is the mouse driver installed? */
  52. static int nbuttons;    /* number of buttons on the mouse */
  53. static int oldbut;    /* Previous state of mouse buttons */
  54. static int oldcol;    /* previous x position of mouse */
  55. static int oldrow;    /* previous y position of mouse */
  56.  
  57. int PASCAL NEAR execprog(char *cmd);
  58.  
  59. /*    input buffers and pointers    */
  60.  
  61. #define    IBUFSIZE    64    /* this must be a power of 2 */
  62.  
  63. unsigned char in_buf[IBUFSIZE];    /* input character buffer */
  64. int in_next = 0;        /* pos to retrieve next input character */
  65. int in_last = 0;        /* pos to place most recent input character */
  66.  
  67. in_init()    /* initialize the input buffer */
  68.  
  69. {
  70.     in_next = in_last = 0;
  71. }
  72.  
  73. in_check()    /* is the input buffer non-empty? */
  74.  
  75. {
  76.     if (in_next == in_last)
  77.         return(FALSE);
  78.     else
  79.         return(TRUE);
  80. }
  81.  
  82. in_put(event)
  83.  
  84. int event;    /* event to enter into the input buffer */
  85.  
  86. {
  87.     in_buf[in_last++] = event;
  88.     in_last &= (IBUFSIZE - 1);
  89. }
  90.  
  91. int in_get()    /* get an event from the input buffer */
  92.  
  93. {
  94.     register int event;    /* event to return */
  95.  
  96.     event = in_buf[in_next++];
  97.     in_next &= (IBUFSIZE - 1);
  98.     return(event);
  99. }
  100.  
  101. /*
  102.  * This function is called once to set up the terminal device streams.
  103.  */
  104.  
  105. int PASCAL NEAR ttopen()
  106.  
  107. {
  108.  
  109.     /* on all screens we are not sure of the initial position
  110.        of the cursor                    */
  111.     ttrow = 999;
  112.     ttcol = 999;
  113.     strcpy(os, "XVT");
  114.  
  115.     mexist = TRUE;
  116.     nbuttons = 3;
  117.  
  118.     /* initialize our character input queue */
  119.     in_init();
  120.  
  121. }
  122.  
  123. /*
  124.  * This function gets called just before we go back home to the command
  125.  * interpreter. On VMS it puts the terminal back in a reasonable state.
  126.  * Another no-operation on CPM.
  127.  */
  128. int PASCAL NEAR ttclose()
  129. {
  130.     /* nothing here! */
  131. }
  132.  
  133. /*
  134.  * Flush terminal buffer. Does real work where the terminal output is buffered
  135.  * up. A no-operation on systems where byte at a time terminal I/O is done.
  136.  */
  137. int PASCAL NEAR ttflush()
  138. {
  139. }
  140.  
  141. /* typahead:    Check to see if any characters are already in the
  142.         keyboard buffer
  143. */
  144.  
  145. int PASCAL NEAR typahead()
  146.  
  147. {
  148.     return(in_check());
  149. }
  150.  
  151. /*
  152.  * Create a subjob with a copy of the command intrepreter in it. When the
  153.  * command interpreter exits, mark the screen as garbage so that you do a full
  154.  * repaint. Bound to "^X C".
  155.  */
  156.  
  157. int PASCAL NEAR spawncli(f, n)
  158.  
  159. int f, n;
  160.  
  161. {
  162.     /* don't allow this command if restricted */
  163.     if (restflag)
  164.         return(resterr());
  165.  
  166.         movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  167.         TTflush();
  168.     TTkclose();
  169.     shellprog("");
  170. #if    WINDOW_TEXT
  171.     refresh_screen(first_screen);
  172. #endif
  173.     TTkopen();
  174.         sgarbf = TRUE;
  175.         return(TRUE);
  176. }
  177.  
  178. /*
  179.  * Run a one-liner in a subjob. When the command returns, wait for a single
  180.  * character to be typed, then mark the screen as garbage so a full repaint is
  181.  * done. Bound to "C-X !".
  182.  */
  183. int PASCAL NEAR spawn(f, n)
  184.  
  185. int f, n;
  186.  
  187. {
  188.         register int s;
  189.         char line[NLINE];
  190.  
  191.     /* don't allow this command if restricted */
  192.     if (restflag)
  193.         return(resterr());
  194.  
  195.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  196.                 return(s);
  197.     movecursor(term.t_nrow - 1, 0);
  198.     TTkclose();
  199.         shellprog(line);
  200.     TTkopen();
  201.  
  202.     /* if we are interactive, pause here */
  203.     if (clexec == FALSE) {
  204. #if    XVT == 0
  205.         printf(TEXT227);
  206. /*            "\n--- Press any key to Continue ---" */
  207. #endif
  208.         tgetc();
  209.         }
  210. #if    WINDOW_TEXT
  211.     refresh_screen(first_screen);
  212. #endif
  213.         sgarbf = TRUE;
  214.         return (TRUE);
  215. }
  216.  
  217. /*
  218.  * Run an external program with arguments. When it returns, wait for a single
  219.  * character to be typed, then mark the screen as garbage so a full repaint is
  220.  * done. Bound to "C-X $".
  221.  */
  222.  
  223. int PASCAL NEAR execprg(f, n)
  224.  
  225. {
  226.         register int s;
  227.         char line[NLINE];
  228.  
  229.     /* don't allow this command if restricted */
  230.     if (restflag)
  231.         return(resterr());
  232.  
  233.         if ((s=mlreply("$", line, NLINE)) != TRUE)
  234.                 return(s);
  235.     movecursor(term.t_nrow - 1, 0);
  236.     TTkclose();
  237.         execprog(line);
  238. #if    WINDOW_TEXT
  239.     refresh_screen(first_screen);
  240. #endif
  241.     TTkopen();
  242.     /* if we are interactive, pause here */
  243.     if (clexec == FALSE) {
  244.             mlputs(TEXT6);
  245. /*                     "\r\n\n[End]" */
  246.             tgetc();
  247.         }
  248.         sgarbf = TRUE;
  249.         return (TRUE);
  250. }
  251.  
  252. /*
  253.  * Pipe a one line command into a window
  254.  * Bound to ^X @
  255.  */
  256. int PASCAL NEAR pipecmd(f, n)
  257.  
  258. int f, n;
  259.  
  260. {
  261.     register EWINDOW *wp;    /* pointer to new window */
  262.     register BUFFER *bp;    /* pointer to buffer to zot */
  263.     register char *tmp;    /* ptr to TMP DOS environment variable */
  264.     FILE *fp;
  265.         char line[NLINE];    /* command line send to shell */
  266.     static char bname[] = "command";
  267.     static char filnam[NSTRING] = "command";
  268.  
  269.     /* don't allow this command if restricted */
  270.     if (restflag)
  271.         return(resterr());
  272.  
  273.     if ((tmp = getenv("TMP")) == NULL)
  274.         filnam[0] = 0;
  275.     else {
  276.         strcpy(filnam, tmp);
  277.         if (filnam[strlen(filnam) - 1] != '\\')
  278.             strcat(filnam, "\\");
  279.         }
  280.     strcat(filnam,"command");
  281.  
  282.     /* get the command to pipe in */
  283.         if (mlreply("@", line, NLINE) != TRUE)
  284.                 return(FALSE);
  285.  
  286.     /* get rid of the command output buffer if it exists */
  287.         if ((bp=bfind(bname, FALSE, 0)) != FALSE) {
  288.         /* try to make sure we are off screen */
  289.         wp = wheadp;
  290.         while (wp != NULL) {
  291.             if (wp->w_bufp == bp) {
  292.                 onlywind(FALSE, 1);
  293.                 break;
  294.             }
  295.             wp = wp->w_wndp;
  296.         }
  297.         /* get rid of the existing command buffer */
  298.         if (zotbuf(bp) != TRUE)
  299.             return(FALSE);
  300.     }
  301.  
  302.     /* redirect the command output to the output file */
  303.     strcat(line, " >>");
  304.     strcat(line, filnam);
  305.     movecursor(term.t_nrow - 1, 0);
  306.  
  307.     /* execute the command */
  308.     TTkclose();
  309.         shellprog(line);
  310. #if    WINDOW_TEXT
  311.     refresh_screen(first_screen);
  312. #endif
  313.     TTkopen();
  314.         sgarbf = TRUE;
  315.  
  316.         /* did the output file get generated? */
  317.     if ((fp = fopen(filnam, "r")) == NULL)
  318.         return(FALSE);
  319.     fclose(fp);
  320.  
  321.     /* split the current window to make room for the command output */
  322.     if (splitwind(FALSE, 1) == FALSE)
  323.             return(FALSE);
  324.  
  325.     /* and read the stuff in */
  326.     if (getfile(filnam, FALSE) == FALSE)
  327.         return(FALSE);
  328.  
  329.     /* make this window in VIEW mode, update all mode lines */
  330.     curwp->w_bufp->b_mode |= MDVIEW;
  331.     wp = wheadp;
  332.     while (wp != NULL) {
  333.         wp->w_flag |= WFMODE;
  334.         wp = wp->w_wndp;
  335.     }
  336.  
  337.     /* and get rid of the temporary file */
  338.     unlink(filnam);
  339.     return(TRUE);
  340. }
  341.  
  342. /*
  343.  * filter a buffer through an external DOS program
  344.  * Bound to ^X #
  345.  */
  346. int PASCAL NEAR filter(f, n)
  347.  
  348. int f, n;
  349.  
  350. {
  351.         register int    s;    /* return status from CLI */
  352.     register BUFFER *bp;    /* pointer to buffer to zot */
  353.         char line[NLINE];    /* command line send to shell */
  354.     char tmpnam[NFILEN];    /* place to store real file name */
  355.     static char bname1[] = "fltinp";
  356.  
  357.     static char filnam1[] = "fltinp";
  358.     static char filnam2[] = "fltout";
  359.  
  360.     /* don't allow this command if restricted */
  361.     if (restflag)
  362.         return(resterr());
  363.  
  364.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  365.         return(rdonly());    /* we are in read only mode    */
  366.  
  367.     /* get the filter name and its args */
  368.         if ((s=mlreply("#", line, NLINE)) != TRUE)
  369.                 return(s);
  370.  
  371.     /* setup the proper file names */
  372.     bp = curbp;
  373.     strcpy(tmpnam, bp->b_fname);    /* save the original name */
  374.     strcpy(bp->b_fname, bname1);    /* set it to our new one */
  375.  
  376.     /* write it out, checking for errors */
  377.     if (writeout(filnam1, "w") != TRUE) {
  378.         mlwrite(TEXT2);
  379. /*                      "[Cannot write filter file]" */
  380.         strcpy(bp->b_fname, tmpnam);
  381.         return(FALSE);
  382.     }
  383.  
  384.     strcat(line," <fltinp >fltout");
  385.     movecursor(term.t_nrow - 1, 0);
  386.     TTkclose();
  387.         shellprog(line);
  388. #if    WINDOW_TEXT
  389.     refresh_screen(first_screen);
  390. #endif
  391.     TTkopen();
  392.         sgarbf = TRUE;
  393.     s = TRUE;
  394.  
  395.     /* on failure, escape gracefully */
  396.     if (s != TRUE || (readin(filnam2,FALSE) == FALSE)) {
  397.         mlwrite(TEXT3);
  398. /*                      "[Execution failed]" */
  399.         strcpy(bp->b_fname, tmpnam);
  400.         unlink(filnam1);
  401.         unlink(filnam2);
  402.         return(s);
  403.     }
  404.  
  405.     /* reset file name */
  406.     strcpy(bp->b_fname, tmpnam);    /* restore name */
  407.     bp->b_flag |= BFCHG;        /* flag it as changed */
  408.  
  409.     /* and get rid of the temporary file */
  410.     unlink(filnam1);
  411.     unlink(filnam2);
  412.     return(TRUE);
  413. }
  414.  
  415. #if    LATTICE
  416. extern int _oserr;
  417. #endif
  418.  
  419. #if    MWC
  420. extern int errno;
  421. #endif
  422.  
  423. #if    MSC
  424. extern int _doserrno;
  425. #endif
  426.  
  427. /*    SHELLPROG: Execute a command in a subshell        */
  428.  
  429. int PASCAL NEAR shellprog(cmd)
  430.  
  431. char *cmd;    /*  Incoming command line to execute  */
  432.  
  433. {
  434.     char *shell;        /* Name of system command processor */
  435.     char swchar;        /* switch character to use */
  436.     union REGS regs;    /* parameters for dos call */
  437.     char comline[NSTRING];    /* constructed command line */
  438.  
  439.     /*  detect current switch character and set us up to use it */
  440.     regs.h.ah = 0x37;    /*  get setting data  */
  441.     regs.h.al = 0x00;    /*  get switch character  */
  442.     intdos(®s, ®s);
  443.     swchar = (char)regs.h.dl;
  444.  
  445.     /*  get name of system shell  */
  446.     if ((shell = getenv("COMSPEC")) == NULL) {
  447.         return(FALSE);        /*  No shell located  */
  448.     }
  449.  
  450.     /* trim leading whitespace off the command */
  451.     while (*cmd == ' ' || *cmd == '\t')    /*  find out if null command */
  452.         cmd++;
  453.  
  454.     /**  If the command line is not empty, bring up the shell  **/
  455.     /**  and execute the command.  Otherwise, bring up the     **/
  456.     /**  shell in interactive mode.   **/
  457.  
  458.     if (*cmd) {
  459.         strcpy(comline, shell);
  460.         strcat(comline, " ");
  461.         comline[strlen(comline) + 1] = 0;
  462.         comline[strlen(comline)] = swchar;
  463.         strcat(comline, "c ");
  464.         strcat(comline, cmd);
  465.         return(execprog(comline));
  466.     } else
  467.         return(execprog(shell));
  468. }
  469.  
  470. /*    EXECPROG:    A function to execute a named program
  471.             with arguments
  472. */
  473.  
  474. #if    LATTICE | MWC
  475. #define    CFLAG    1
  476. #endif
  477.  
  478. int PASCAL NEAR execprog(cmd)
  479.  
  480. char *cmd;    /*  Incoming command line to execute  */
  481.  
  482. {
  483.     char *sp;        /* temporary string pointer */
  484.     int rv;            /* numeric return value from subprocess */
  485.     char f1[38];        /* FCB1 area (not initialized */
  486.     char f2[38];        /* FCB2 area (not initialized */
  487.     char prog[NSTRING];    /* program filespec */
  488.     char tail[NSTRING];    /* command tail with length byte */
  489.     union REGS regs;    /* parameters for dos call  */
  490. #if    MWC == 0
  491.     struct SREGS segreg;    /* segment registers for dis call */
  492. #endif
  493.     struct Pblock {        /* EXEC parameter block */
  494.         short envptr;    /* 2 byte pointer to environment string */
  495.         char *cline;    /* 4 byte pointer to command line */
  496.         char *fcb1;    /* 4 byte pointer to FCB at PSP+5Ch */
  497.         char *fcb2;    /* 4 byte pointer to FCB at PSP+6Ch */
  498.     } pblock;
  499.  
  500.     /* parse the command name from the command line */
  501.     sp = prog;
  502.     while (*cmd && (*cmd != ' ') && (*cmd != '\t'))
  503.         *sp++ = *cmd++;
  504.     *sp = 0;
  505.  
  506.     /* and parse out the command tail */
  507.     while (*cmd && ((*cmd == ' ') || (*cmd == '\t')))
  508.         ++cmd;
  509.     *tail = (char)(strlen(cmd)); /* record the byte length */
  510.     strcpy(&tail[1], cmd);
  511.     strcat(&tail[1], "\r");
  512.  
  513.     /* look up the program on the path trying various extentions */
  514.     if ((sp = flook(prog, TRUE)) == NULL)
  515.         if ((sp = flook(strcat(prog, ".exe"), TRUE)) == NULL) {
  516.             strcpy(&prog[strlen(prog)-4], ".com");
  517.             if ((sp = flook(prog, TRUE)) == NULL)
  518.                 return(FALSE);
  519.         }
  520.     strcpy(prog, sp);
  521.  
  522. #if    MWC == 0
  523.     /* get a pointer to this PSPs environment segment number */
  524. #if    IC
  525.     _segread(&segreg);
  526. #else /* IC */
  527.     segread(&segreg);
  528. #endif /* IC */
  529. #endif /* MWC == 0 */
  530.  
  531.     /* set up the EXEC parameter block */
  532.     pblock.envptr = 0;    /* make the child inherit the parents env */
  533.     pblock.fcb1 = f1;        /* point to a blank FCB */
  534.     pblock.fcb2 = f2;        /* point to a blank FCB */
  535.         pblock.cline = tail;        /* parameter line pointer */
  536.  
  537.     /* and make the call */
  538.     regs.h.ah = 0x4b;    /* EXEC Load or Execute a Program */
  539.     regs.h.al = 0x00;    /* load end execute function subcode */
  540. #if    MWC
  541.     regs.x.ds = ((unsigned long)(prog) >> 16);    /* program name ptr */
  542.     regs.x.dx = (unsigned int)(prog);
  543.     regs.x.es = regs.x.ds;
  544.     /*regs.x.es = ((unsigned long)(&pblock) >> 16);    * set up param block ptr */
  545.     regs.x.bx = (unsigned int)(&pblock);
  546. #endif
  547. #if    LATTICE | MSC | TURBO | IC | ZTC
  548.     segreg.ds = ((unsigned long)(prog) >> 16);    /* program name ptr */
  549.     regs.x.dx = (unsigned int)(prog);
  550.     segreg.es = ((unsigned long)(&pblock) >> 16);    /* set up param block ptr */
  551.     regs.x.bx = (unsigned int)(&pblock);
  552. #endif
  553. #if    LATTICE
  554.     if ((intdosx(®s, ®s, &segreg) & CFLAG) == 0) {
  555.         regs.h.ah = 0x4d;    /* get child process return code */
  556.         intdos(®s, ®s);    /* go do it */
  557.         rv = regs.x.ax;        /* save child's return code */
  558.     } else
  559.         rv = -_oserr;        /* failed child call */
  560. #endif
  561. #if    MWC
  562.     intcall(®s, ®s, DOSINT);
  563.     if ((regs.x.flags & CFLAG) == 0) {
  564.         regs.h.ah = 0x4d;    /* get child process return code */
  565.         intcall(®s, ®s, DOSINT);    /* go do it */
  566.         rv = regs.x.ax;        /* save child's return code */
  567.     } else
  568.         rv = -errno;        /* failed child call */
  569. #endif
  570. #if    TURBO | IC | MSC | ZTC
  571.     intdosx(®s, ®s, &segreg);
  572.     if (regs.x.cflag == 0) {
  573.         regs.h.ah = 0x4d;    /* get child process return code */
  574.         intdos(®s, ®s);    /* go do it */
  575.         rv = regs.x.ax;        /* save child's return code */
  576.     } else
  577. #if    IC
  578.         rv = -1;
  579. #else /* IC */
  580.         rv = -_doserrno;    /* failed child call */
  581. #endif /* IC */
  582. #endif
  583.     strcpy(rval, int_asc(rv));
  584.     return((rval < 0) ? FALSE : TRUE);
  585. }
  586.  
  587. /* return a system dependant string with the current time */
  588.  
  589. char *PASCAL NEAR timeset()
  590.  
  591. {
  592. #if    MWC | TURBO | IC | MSC | ZTC
  593.     register char *sp;    /* temp string pointer */
  594.     char buf[16];        /* time data buffer */
  595.     extern char *ctime();
  596.  
  597. #if    IC
  598.     time((time_t *)buf);
  599.     sp = ctime((time_t *)buf);
  600. #else
  601.     time(buf);
  602.     sp = ctime(buf);
  603. #endif
  604.     sp[strlen(sp)-1] = 0;
  605.     return(sp);
  606. #else
  607.     return(errorm);
  608. #endif
  609. }
  610.  
  611. #if    TURBO
  612. /*    FILE Directory routines        */
  613.  
  614. char path[NFILEN];    /* path of file to find */
  615. char rbuf[NFILEN];    /* return file buffer */
  616.  
  617. /*    do a wild card directory search (for file name completion) */
  618.  
  619. char *PASCAL NEAR getffile(fspec)
  620.  
  621. char *fspec;    /* pattern to match */
  622.  
  623. {
  624.     register int index;        /* index into various strings */
  625.     register int point;        /* index into other strings */
  626.     register int extflag;        /* does the file have an extention? */
  627.     char fname[NFILEN];        /* file/path for DOS call */
  628.  
  629.     /* first parse the file path off the file spec */
  630.     strcpy(path, fspec);
  631.     index = strlen(path) - 1;
  632.     while (index >= 0 && (path[index] != '/' &&
  633.                 path[index] != '\\' && path[index] != ':'))
  634.         --index;
  635.     path[index+1] = 0;
  636.  
  637.     /* check for an extension */
  638.     point = strlen(fspec) - 1;
  639.     extflag = FALSE;
  640.     while (point > index) {
  641.         if (fspec[point] == '.') {
  642.             extflag = TRUE;
  643.             break;
  644.         }
  645.         point--;
  646.     }
  647.  
  648.     /* construct the composite wild card spec */
  649.     strcpy(fname, path);
  650.     strcat(fname, &fspec[index+1]);
  651.     strcat(fname, "*");
  652.     if (extflag == FALSE)
  653.         strcat(fname, ".*");
  654.  
  655.     /* and call for the first file */
  656.     if (findfirst(fname, &fileblock, FA_DIREC) == -1)
  657.         return(NULL);
  658.  
  659.     /* return the first file name! */
  660.     strcpy(rbuf, path);
  661.     strcat(rbuf, fileblock.ff_name);
  662.     mklower(rbuf);
  663.     if (fileblock.ff_attrib == 16)
  664.         strcat(rbuf, DIRSEPSTR);
  665.     return(rbuf);
  666. }
  667.  
  668. char *PASCAL NEAR getnfile()
  669.  
  670. {
  671.     register int index;        /* index into various strings */
  672.     register int point;        /* index into other strings */
  673.     register int extflag;        /* does the file have an extention? */
  674.     char fname[NFILEN];        /* file/path for DOS call */
  675.  
  676.     /* and call for the first file */
  677.     if (findnext(&fileblock) == -1)
  678.         return(NULL);
  679.  
  680.     /* return the first file name! */
  681.     strcpy(rbuf, path);
  682.     strcat(rbuf, fileblock.ff_name);
  683.     mklower(rbuf);
  684.     if (fileblock.ff_attrib == 16)
  685.         strcat(rbuf, DIRSEPSTR);
  686.     return(rbuf);
  687. }
  688. #else
  689. #if    MSC | ZTC
  690. /*    FILE Directory routines        */
  691.  
  692. char path[NFILEN];    /* path of file to find */
  693. char rbuf[NFILEN];    /* return file buffer */
  694.  
  695. /*    do a wild card directory search (for file name completion) */
  696.  
  697. char *PASCAL NEAR getffile(fspec)
  698.  
  699. char *fspec;    /* pattern to match */
  700.  
  701. {
  702.     register int index;        /* index into various strings */
  703.     register int point;        /* index into other strings */
  704.     register int extflag;        /* does the file have an extention? */
  705.     char fname[NFILEN];        /* file/path for DOS call */
  706.  
  707.     /* first parse the file path off the file spec */
  708.     strcpy(path, fspec);
  709.     index = strlen(path) - 1;
  710.     while (index >= 0 && (path[index] != '/' &&
  711.                 path[index] != '\\' && path[index] != ':'))
  712.         --index;
  713.     path[index+1] = 0;
  714.  
  715.     /* check for an extension */
  716.     point = strlen(fspec) - 1;
  717.     extflag = FALSE;
  718.     while (point > index) {
  719.         if (fspec[point] == '.') {
  720.             extflag = TRUE;
  721.             break;
  722.         }
  723.         point--;
  724.     }
  725.  
  726.     /* construct the composite wild card spec */
  727.     strcpy(fname, path);
  728.     strcat(fname, &fspec[index+1]);
  729.     strcat(fname, "*");
  730.     if (extflag == FALSE)
  731.         strcat(fname, ".*");
  732.  
  733.     /* and call for the first file */
  734.     if (_dos_findfirst(fname, _A_NORMAL|_A_SUBDIR, &fileblock) != 0)
  735.         return(NULL);
  736.  
  737.     /* return the first file name! */
  738.     strcpy(rbuf, path);
  739.     strcat(rbuf, fileblock.name);
  740.     mklower(rbuf);
  741.     if (fileblock.attrib == 16)
  742.         strcat(rbuf, DIRSEPSTR);
  743.     return(rbuf);
  744. }
  745.  
  746. char *PASCAL NEAR getnfile()
  747.  
  748. {
  749.     register int index;        /* index into various strings */
  750.     register int point;        /* index into other strings */
  751.     register int extflag;        /* does the file have an extention? */
  752.     char fname[NFILEN];        /* file/path for DOS call */
  753.  
  754.     /* and call for the first file */
  755.     if (_dos_findnext(&fileblock) != 0)
  756.         return(NULL);
  757.  
  758.     /* return the first file name! */
  759.     strcpy(rbuf, path);
  760.     strcat(rbuf, fileblock.name);
  761.     mklower(rbuf);
  762.     if (fileblock.attrib == 16)
  763.         strcat(rbuf, DIRSEPSTR);
  764.     return(rbuf);
  765. }
  766. #else
  767. char *PASCAL NEAR getffile(fspec)
  768.  
  769. char *fspec;    /* file to match */
  770.  
  771. {
  772.     return(NULL);
  773. }
  774.  
  775. char *PASCAL NEAR getnfile()
  776.  
  777. {
  778.     return(NULL);
  779. }
  780. #endif
  781. #endif
  782. #endif
  783.