home *** CD-ROM | disk | FTP | other *** search
/ vsiftp.vmssoftware.com / VSIPUBLIC@vsiftp.vmssoftware.com.tar / FREEWARE / FREEWARE40.ZIP / flistfrontend / src / fledit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-06  |  16.0 KB  |  454 lines

  1. #ifndef NO_IDENT
  2. static char *Id = "$Id: fledit.c,v 1.12 1995/06/06 10:02:34 tom Exp $";
  3. #endif
  4.  
  5. /*
  6.  * Title:    fledit.c
  7.  * Author:    T.E.Dickey
  8.  * Created:    15 May 1984
  9.  * Last update:
  10.  *        18 Mar 1995, prototypes
  11.  *        01 Jul 1988- added hack to permit us to run LSEDIT
  12.  *        24 Aug 1985, use 'dds_add2' instead of 'dirdata_one'
  13.  *        20 Aug 1985, do 'dirent_width' scan on return from directory
  14.  *        31 Jul 1985, added 'dateflag', 'datechek' to stack.
  15.  *        30 Jul 1985, do 'dds_pack' on exit from edit-directory.
  16.  *        24 Jul 1985, pass-thru argument string to 'flist_opts' in case
  17.  *                 we get to provide it for /LOG.
  18.  *        23 Jul 1985, recompute 'numdlets' after directory-edit, permit
  19.  *                 options in EDIT-directory.
  20.  *        20 Jul 1985, corrected update-after-edit (use 'dirdata_one')
  21.  *        05 Jul 1985, make 'namelist' a global, structured heap.  Let
  22.  *                 'dirpath' do this for 'namelist' and 'pathlist'.
  23.  *        03 Jul 1985, cleanup 'filelist' definition.  Use 'scanint' to
  24.  *                 bypass 'sscanf' bug in CC2.0
  25.  *        11 Jun 1985, added cli-argument to dds_spawn
  26.  *        18 May 1985, added 'pcolumns[]'
  27.  *        14 Apr 1985, use 'flist_info' for log-routing
  28.  *        08 Mar 1985, use 'dirent_isdir'
  29.  *        08 Feb 1985, altered message shown on entry to directory.
  30.  *        01 Feb 1985, added 'readllen'
  31.  *        30 Dec 1984, make "/mark" re-entrant ('dircmd_select' calls).
  32.  *        24 Dec 1984, added 'D_mode', 'D_opt' save/restore
  33.  *        15 Dec 1984, added 'cpy_dft' argument to 'dclarg'
  34.  *        05 Dec 1984, added "namelist"
  35.  *        18 Sep 1984, use "canopen"
  36.  *        08 Sep 1984, use "highver"
  37.  *        03 Sep 1984, use "import", added 'flquit'
  38.  *        25 Aug 1984, cleanup of buffer sizes
  39.  *        27 Jul 1984, added 'readlist'
  40.  *        25 Jul 1984, added 'cmd_arg' to 'dclarg()'
  41.  *        20 Jul 1984, added 'dirchk' logic, added 'numreads'
  42.  *        18 Jul 1984, changed sense of 'V_opt'
  43.  *        15 Jul 1984, use PATHOF()
  44.  *        10 Jul 1984, changed calling convention
  45.  *        03 Jul 1984, changed 'faccess' to 'dirent_acc'
  46.  *        30 Jun 1984, to combine with recurring-call on 'flist' main
  47.  *        28 May 1984
  48.  *
  49.  * Function:    This module supports an edit-function for "FLIST".  It tests
  50.  *        the file-access to see if the file's directory is writeable.
  51.  *        If not, it restricts the file to readonly.  Also, since we
  52.  *        use EDT, it tests for the presence of the init-file in the
  53.  *        user's home directory to generate the "/COMMAND" option.
  54.  *
  55.  *        If the file happens to be a directory, 'fledit' calls the main
  56.  *        program of FLIST with a new argument: the new directory.
  57.  *        (If the directory-name is NOT in 'filelist[], however, FLIST
  58.  *        will simply open a new level on the single entry.  This is
  59.  *        done to permit FLIST to alter protection, etc., of a root-
  60.  *        level directory without exiting from the current level.)
  61.  *
  62.  *        If any sort of wildcard, or multiple-file argument is given,
  63.  *        a new level of FLIST is entered, like the directory-file
  64.  *        treatment.
  65.  */
  66.  
  67. #include    <stdlib.h>
  68. #include    <stdio.h>
  69. #include    <signal.h>    /* for 'sleep()' */
  70. #include    <string.h>
  71.  
  72. #include    "bool.h"
  73. #include    "dclarg.h"
  74. #include    "flist.h"
  75.  
  76. #include    "canopen.h"
  77. #include    "dds.h"
  78. #include    "dircmd.h"
  79. #include    "dirent.h"
  80. #include    "dds.h"
  81. #include    "pathup.h"
  82. #include    "scanver.h"
  83.  
  84. #include    "strutils.h"
  85.  
  86. import(filelist);    import(numfiles);    import(numdlets);
  87. import(D_mode);        import(datechek);    import(dateflag);
  88. import(D_opt);
  89. import(V_opt);
  90. import(pcolumns);
  91. import(conv_list);
  92. import(maxfiles);
  93. import(readlist);    import(readllen);
  94.  
  95. extern    int    multi_quit;
  96. static    int    pack_exit = 0;
  97.  
  98. static    void    fledit_dir (int *curfile_, char *xcmd_, DCLARG *xdcl_);
  99. static    void    fledit_file (int *curfile_, char *xcmd_, DCLARG *xdcl_, FILENT *z, int inlist);
  100. static    void    fledit_tell (char *path_);
  101.  
  102. tDIRCMD(fledit)
  103. {
  104.     FILENT    ztmp,    *z = &ztmp;
  105.     int    inx,
  106.         single    = dirchk (xcmd_, xdcl_, v_1, FALSE);
  107.     DCLARG    *dcl_;        /* arg-list pointer for built-command */
  108.     char    path    [MAX_PATH],
  109.         *spec,
  110.         longname[MAX_PATH];
  111.  
  112.     /*
  113.      * Parse the name from 'xdcl_', test for use of wildcard.
  114.      * If wildcard or directory-name, do directory-call.  Otherwise,
  115.      * edit/view file.  If directory-call, no options are permitted.
  116.      * Otherwise, may include options.
  117.      *
  118.      * patch: should permit options on new level.
  119.      */
  120.     if (single || (xcmd_ == nullC))
  121.     {
  122.         if (single)
  123.         {
  124.             spec    = dclinx (xdcl_, 1, 0);
  125.             inx    = dirent_old_any (&ztmp, spec, 0);
  126.         }
  127.         else
  128.         {
  129.             ztmp    = FK(inx = *curfile_);
  130.             dirent_glue2 (spec = longname, z, *curfile_);
  131.         }
  132.  
  133.         /*
  134.          * 'inx' is set to -2 if the file wasn't found, -1 if it is
  135.          * not in the current 'filelist[]'.
  136.          */
  137.         if (dirent_isdir(&ztmp))
  138.         {
  139.             if (inx >= 0)
  140.             {
  141.                 if (!pathdown (path, zPATHOF(z), ztmp.fname))
  142.                 {
  143.                     warn ("Illegal pathname: %s", path);
  144.                     return;
  145.                 }
  146.                 fledit_tell (path);
  147.                 dcl_    = dclarg (path, dirent_dft(), 1, FALSE);
  148.                 fledit_dir (curfile_, xcmd_, dcl_);
  149.             }
  150.             else if (inx >= -1)
  151.             {
  152.                 fledit_tell (zPATHOF(z));
  153.                 fledit_dir (curfile_, xcmd_, xdcl_->dcl_next);
  154.             }
  155.             else
  156.                 warn ("Directory not found: %s", spec);
  157.         }
  158.         else
  159.             fledit_file (curfile_, xcmd_, xdcl_, z, inx);
  160.     }
  161.     else if (dirchk (xcmd_, xdcl_, v_M, TRUE))
  162.         fledit_dir (curfile_, xcmd_, xdcl_->dcl_next);
  163. }
  164.  
  165. /*
  166.  * Enter a new directory.  The 'xdcl_' linked-list begins with the first
  167.  * actual argument, rather than the command name.
  168.  */
  169. static
  170. void    fledit_dir (
  171.     int    *curfile_,
  172.     char    *xcmd_,
  173.     DCLARG    *xdcl_)
  174. {
  175.     FLINK    *fixed_      = 0;
  176.     FLINK  **SAVEfile = filelist;
  177.     FILENT    *SAVEread = readlist;
  178.     DATENT    SAVEdchk  = datechek;
  179.     int    j,
  180.         SAVEpack  = pack_exit,
  181.         SAVEmaxf  = maxfiles,
  182.         SAVEnumf  = numfiles,
  183.         SAVEnumR  = readllen,
  184.         SAVEdmod  = D_mode,
  185.         SAVEdopt  = D_opt,
  186.         SAVEpcol  size_pcolumns,
  187.         SAVEtopf  = dds_fast(DDS_U_C),
  188.         PACKtopf  = SAVEtopf,
  189.         SAVEmark  = dircmd_select(-2);
  190.     char    SAVEconv  size_conv_list,
  191.         SAVEdflg  size_dateflag;
  192.  
  193.     /* If options given are illegal, don't go anywhere    */
  194.     if (flist_opts (1, &xcmd_, xdcl_, TRUE))    return;
  195.  
  196.     memcpy (SAVEpcol, pcolumns, sizeof(pcolumns));
  197.     memcpy (SAVEdflg, dateflag, sizeof(dateflag));
  198.     strcpy (SAVEconv, conv_list);
  199.  
  200.     if (SAVEmark >= 0)    fixed_ = filelist[SAVEmark];
  201.     dircmd_select (-1);    /* Start with cleared display-flag */
  202.     pack_exit = FALSE;
  203.     flist (xdcl_);        /* Do recursive call on main    */
  204.     dircmd_select (-1);    /* Call display-flag, if any    */
  205.  
  206.     filelist = SAVEfile;    /* Restore caller's state    */
  207.     readlist = SAVEread;
  208.     maxfiles = SAVEmaxf;
  209.     numfiles = SAVEnumf;
  210.     readllen = SAVEnumR;
  211.     D_mode     = SAVEdmod;
  212.     D_opt     = SAVEdopt;
  213.     datechek = SAVEdchk;
  214.     memcpy (pcolumns, SAVEpcol, sizeof(pcolumns));
  215.     memcpy (dateflag, SAVEdflg, sizeof(dateflag));
  216.     strcpy (conv_list, SAVEconv);
  217.  
  218.     /*
  219.      * Recompute the number of deleted-entries (in case the lower-level did
  220.      * it), and adjust the top-of-screen index 'PACKtopf', to account for
  221.      * whatever 'dds_pack' will do:
  222.      */
  223.     for (j = numdlets = 0; j < numfiles; j++)
  224.         if (DELETED(j))
  225.         {    numdlets++;
  226.             if (pack_exit && (j < SAVEtopf)) PACKtopf--;
  227.         }
  228.  
  229.     /*
  230.      * If we are not skipping display levels, refresh the screen.  If there
  231.      * were any files in the lower-level, do a screen-pack.  Recompute the
  232.      * longest-column data, and finally reset the marker-entry.
  233.      */
  234.     if (multi_quit <= 0)
  235.     {
  236.         if (pack_exit)    dds_pack (curfile_, TRUE);
  237.         dirent_width ((FILENT *)0);
  238.         dds_all (PACKtopf, *curfile_);
  239.  
  240.         if (fixed_) for (j = 0; j < numfiles; j++)
  241.             if (fixed_ == filelist[j] && !DELETED(j))
  242.             {
  243.                 dircmd_select (j);
  244.                 break;
  245.             }
  246.     }
  247.     pack_exit= SAVEpack;
  248. }
  249.  
  250. /*
  251.  * Show the pathname in a form which will cause minimal refresh for very
  252.  * short display-lists:
  253.  */
  254. static
  255. void    fledit_tell (char *path_)
  256. {
  257.     flist_info ("Read: %s", path_);
  258.     sleep (1);
  259. }
  260.  
  261. /*
  262.  * EDIT/VIEW a file.  Normally the user will use the default entry, which
  263.  * edits the current file-entry.  In this case, if the file is updated,
  264.  * the entry receives the data for the updated file, and the old entry
  265.  * (if /NOVERSIONS isn't set) is moved to a free slot.
  266.  *
  267.  * On the other hand, if the user employs a "/o" escape to make a different
  268.  * filename, one of two cases may happen:
  269.  *    (a) The file exists, whether somewhere else in 'filelist[]', or as
  270.  *        a file not read into 'filelist[]'.  If it is not already in the
  271.  *        an entry is added for the file.
  272.  *    (b) The file doesn't exist.
  273.  *
  274.  * In any case, the 'filelist[]' entry which corresponds to the highest
  275.  * version of the file will receive the updated filename.
  276.  *
  277.  * patch: may alter this to put the updated name on the current line.
  278.  * patch: cmd-size should be done with calloc.
  279.  */
  280. static
  281. void    fledit_file (
  282.     int    *curfile_,
  283.     char    *xcmd_,
  284.     DCLARG    *xdcl_,
  285.     FILENT    *z,        /* => data for file to edit        */
  286.     int    inlist)        /* >= 0 iff 'z' is found in 'filelist[]'*/
  287. {
  288.     FILENT    zold    = *z;        /* original old-file data    */
  289.     int    status,    curvers, j,
  290.         oldver    = z->fvers,
  291.         rmode    = (xdcl_->dcl_text[0] == 'V'),    /* "EDIT" or "VIEW" */
  292.         width    = crt_width() - 6;    /* nominally 74    */
  293.     static    char    sFMT1[]    = "%%s %%-%d.%ds";
  294.     char    fullname[MAX_PATH],
  295.         tstspec    [MAX_PATH],
  296.         *c_,
  297.         format    [sizeof(sFMT1)+6],
  298.         cmd    [(3*MAX_PATH)+CRT_COLS]; /* filenames, plus options */
  299.  
  300.     static    char    *bad_type[] = {"EXE", "OBJ", "OLB"};
  301.     static    int    max_bad_type = sizeof (bad_type) / sizeof(bad_type[0]);
  302.  
  303.     dirent_glue (fullname, z);
  304.  
  305.     for (j = 0; j < max_bad_type; j++)
  306.     {
  307.         if (strcmp (z->ftype, bad_type[j]) == 0)
  308.         {
  309.             warn ("You cannot edit this file-type: %s", z->ftype);
  310.             return;
  311.         }
  312.     }
  313.  
  314.     if (inlist == -1)    /* Add it to the list to edit it    */
  315.         inlist = dds_add (z);
  316.  
  317.     if (inlist >= 0)    /* If an old-file, check readability    */
  318.     {
  319.         if (! dirent_acc (z, "r"))
  320.         {
  321.             flist_info ("You cannot view this file");
  322.             return;
  323.         }
  324.     }
  325.  
  326.     /*
  327.      * If the user has defaulted to EDIT mode, test to ensure that the
  328.      * directory is writeable (i.e., that we can make a new version via
  329.      * EDIT).  If not, 'diropen' emits a warning message.  In this case,
  330.      * coerce to readonly, and proceed.
  331.      */
  332.     if (! rmode)
  333.     {
  334.         if (! diropen (fullname))
  335.         {
  336.             rmode = TRUE;
  337.             sleep(1);
  338.             clrwarn ();
  339.         }
  340.     }
  341.  
  342.     /*
  343.      * Another reason for forcing readonly mode is if the edited-version
  344.      * is not the highest (current) version.  By selecting readonly edit,
  345.      * the editor warning message is suppressed.
  346.      */
  347.     strcpy (tstspec, fullname);
  348.     curvers = highver (tstspec);    /* tstspec <= name w/o version */
  349.     if (z->fvers < curvers)
  350.         rmode = TRUE;
  351.  
  352.     if (xdcl_->dcl_text[0] == 'L') {
  353.         strcpy (cmd, "LSEDIT");
  354.     } else {
  355.         strcpy (cmd, "EDIT");
  356.         if (strcmp (getenv("HOME"), zPATHOF(z)))
  357.         {
  358.             char    edtini[MAX_PATH];
  359.             sprintf (edtini, "%s%s", getenv("HOME"), "EDTINI.EDT");
  360.             if (!canopen (edtini))
  361.                 sprintf (strnull(cmd), "/COMMAND=%s", edtini);
  362.         }
  363.     }
  364.  
  365.     /*
  366.      * Provide for passing through options:
  367.      * (patch: should do better for storage allocation
  368.      */
  369.     if (xcmd_)
  370.     {
  371.         for (xdcl_ = xdcl_->dcl_next; xdcl_; xdcl_ = xdcl_->dcl_next)
  372.         {
  373.             strcat (cmd, " ");
  374.             strcat (cmd, xdcl_->dcl_text);
  375.         }
  376.     }
  377.     else
  378.     {
  379.         strcat (cmd, " ");
  380.         strcat (cmd, fullname);
  381.     }
  382.     if (rmode) strcat (cmd, "/READ_ONLY");    /* (override "/NOREAD") */
  383.  
  384.     sprintf (format, sFMT1, width, width);
  385.     flist_info (format,  (rmode ? "VIEW" : "EDIT"), fullname);
  386.  
  387.     dds_spawn (0, *curfile_, cmd, 0, FALSE, 2);
  388.  
  389.     /*
  390.      * On exit, the refresh-option may have altered the current entry,
  391.      * but the prior entry probably still exists.  If altered, do a scan
  392.      * to pick up the prior entry, and insert it on the end of the list.
  393.      */
  394.     if (!rmode)
  395.     {
  396.         dirent_chk (z, tstspec);
  397.         if (inlist >= 0)
  398.         {
  399.             if (memcmp (z, &zold, sizeof(FILENT)))
  400.                 dds_add2 (z, inlist);
  401.         }
  402.         else
  403.             dds_add (z);
  404.         if (V_opt && oldver && (oldver != z->fvers))
  405.             dds_add (&zold);
  406.     }
  407. }
  408.  
  409. /*
  410.  * Title:    flquit.c
  411.  *
  412.  * Function:    Process a "quit" command for FLIST.  If an argument is given,
  413.  *        it must be the number of levels to quit from (default: 1).
  414.  *        An asterisk quits all levels (actually 999).
  415.  */
  416. tDIRCMD(flquit)
  417. {
  418.     int    num;
  419.     register char    *c_, *d_;
  420.  
  421.     if (xdcl_ = xdcl_->dcl_next)
  422.     {
  423.         c_ = scanint (d_ = xdcl_->dcl_text, &num);
  424.         if (!strcmp("*", d_))
  425.             multi_quit = 999;
  426.         else if (c_ != d_ && *c_ == '\0')
  427.         {
  428.             if (num >= 1)
  429.                 multi_quit = num;
  430.             else
  431.             {
  432.                 warn ("Argument for QUIT must be positive");
  433.                 return;
  434.             }
  435.         }
  436.         else
  437.         {
  438.             warn ("Argument for QUIT must be '*' or number");
  439.             return;
  440.         }
  441.     }
  442.     numfiles = 0;    /* Force quit by clearing file count    */
  443. }
  444.  
  445. /*
  446.  * This entrypoint is called from the main-loop immediately after succeeding
  447.  * in reading a directory.  We know that we have a new screen to display, and
  448.  * thus, on exit from the screen, can start over again by a 'dds_pack'.
  449.  */
  450. void    fledit_pack (void)
  451. {
  452.     pack_exit = (numfiles > 0);
  453. }
  454.