home *** CD-ROM | disk | FTP | other *** search
- #ifndef NO_IDENT
- static char *Id = "$Id: fledit.c,v 1.12 1995/06/06 10:02:34 tom Exp $";
- #endif
-
- /*
- * Title: fledit.c
- * Author: T.E.Dickey
- * Created: 15 May 1984
- * Last update:
- * 18 Mar 1995, prototypes
- * 01 Jul 1988- added hack to permit us to run LSEDIT
- * 24 Aug 1985, use 'dds_add2' instead of 'dirdata_one'
- * 20 Aug 1985, do 'dirent_width' scan on return from directory
- * 31 Jul 1985, added 'dateflag', 'datechek' to stack.
- * 30 Jul 1985, do 'dds_pack' on exit from edit-directory.
- * 24 Jul 1985, pass-thru argument string to 'flist_opts' in case
- * we get to provide it for /LOG.
- * 23 Jul 1985, recompute 'numdlets' after directory-edit, permit
- * options in EDIT-directory.
- * 20 Jul 1985, corrected update-after-edit (use 'dirdata_one')
- * 05 Jul 1985, make 'namelist' a global, structured heap. Let
- * 'dirpath' do this for 'namelist' and 'pathlist'.
- * 03 Jul 1985, cleanup 'filelist' definition. Use 'scanint' to
- * bypass 'sscanf' bug in CC2.0
- * 11 Jun 1985, added cli-argument to dds_spawn
- * 18 May 1985, added 'pcolumns[]'
- * 14 Apr 1985, use 'flist_info' for log-routing
- * 08 Mar 1985, use 'dirent_isdir'
- * 08 Feb 1985, altered message shown on entry to directory.
- * 01 Feb 1985, added 'readllen'
- * 30 Dec 1984, make "/mark" re-entrant ('dircmd_select' calls).
- * 24 Dec 1984, added 'D_mode', 'D_opt' save/restore
- * 15 Dec 1984, added 'cpy_dft' argument to 'dclarg'
- * 05 Dec 1984, added "namelist"
- * 18 Sep 1984, use "canopen"
- * 08 Sep 1984, use "highver"
- * 03 Sep 1984, use "import", added 'flquit'
- * 25 Aug 1984, cleanup of buffer sizes
- * 27 Jul 1984, added 'readlist'
- * 25 Jul 1984, added 'cmd_arg' to 'dclarg()'
- * 20 Jul 1984, added 'dirchk' logic, added 'numreads'
- * 18 Jul 1984, changed sense of 'V_opt'
- * 15 Jul 1984, use PATHOF()
- * 10 Jul 1984, changed calling convention
- * 03 Jul 1984, changed 'faccess' to 'dirent_acc'
- * 30 Jun 1984, to combine with recurring-call on 'flist' main
- * 28 May 1984
- *
- * Function: This module supports an edit-function for "FLIST". It tests
- * the file-access to see if the file's directory is writeable.
- * If not, it restricts the file to readonly. Also, since we
- * use EDT, it tests for the presence of the init-file in the
- * user's home directory to generate the "/COMMAND" option.
- *
- * If the file happens to be a directory, 'fledit' calls the main
- * program of FLIST with a new argument: the new directory.
- * (If the directory-name is NOT in 'filelist[], however, FLIST
- * will simply open a new level on the single entry. This is
- * done to permit FLIST to alter protection, etc., of a root-
- * level directory without exiting from the current level.)
- *
- * If any sort of wildcard, or multiple-file argument is given,
- * a new level of FLIST is entered, like the directory-file
- * treatment.
- */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <signal.h> /* for 'sleep()' */
- #include <string.h>
-
- #include "bool.h"
- #include "dclarg.h"
- #include "flist.h"
-
- #include "canopen.h"
- #include "dds.h"
- #include "dircmd.h"
- #include "dirent.h"
- #include "dds.h"
- #include "pathup.h"
- #include "scanver.h"
-
- #include "strutils.h"
-
- import(filelist); import(numfiles); import(numdlets);
- import(D_mode); import(datechek); import(dateflag);
- import(D_opt);
- import(V_opt);
- import(pcolumns);
- import(conv_list);
- import(maxfiles);
- import(readlist); import(readllen);
-
- extern int multi_quit;
- static int pack_exit = 0;
-
- static void fledit_dir (int *curfile_, char *xcmd_, DCLARG *xdcl_);
- static void fledit_file (int *curfile_, char *xcmd_, DCLARG *xdcl_, FILENT *z, int inlist);
- static void fledit_tell (char *path_);
-
- tDIRCMD(fledit)
- {
- FILENT ztmp, *z = &ztmp;
- int inx,
- single = dirchk (xcmd_, xdcl_, v_1, FALSE);
- DCLARG *dcl_; /* arg-list pointer for built-command */
- char path [MAX_PATH],
- *spec,
- longname[MAX_PATH];
-
- /*
- * Parse the name from 'xdcl_', test for use of wildcard.
- * If wildcard or directory-name, do directory-call. Otherwise,
- * edit/view file. If directory-call, no options are permitted.
- * Otherwise, may include options.
- *
- * patch: should permit options on new level.
- */
- if (single || (xcmd_ == nullC))
- {
- if (single)
- {
- spec = dclinx (xdcl_, 1, 0);
- inx = dirent_old_any (&ztmp, spec, 0);
- }
- else
- {
- ztmp = FK(inx = *curfile_);
- dirent_glue2 (spec = longname, z, *curfile_);
- }
-
- /*
- * 'inx' is set to -2 if the file wasn't found, -1 if it is
- * not in the current 'filelist[]'.
- */
- if (dirent_isdir(&ztmp))
- {
- if (inx >= 0)
- {
- if (!pathdown (path, zPATHOF(z), ztmp.fname))
- {
- warn ("Illegal pathname: %s", path);
- return;
- }
- fledit_tell (path);
- dcl_ = dclarg (path, dirent_dft(), 1, FALSE);
- fledit_dir (curfile_, xcmd_, dcl_);
- }
- else if (inx >= -1)
- {
- fledit_tell (zPATHOF(z));
- fledit_dir (curfile_, xcmd_, xdcl_->dcl_next);
- }
- else
- warn ("Directory not found: %s", spec);
- }
- else
- fledit_file (curfile_, xcmd_, xdcl_, z, inx);
- }
- else if (dirchk (xcmd_, xdcl_, v_M, TRUE))
- fledit_dir (curfile_, xcmd_, xdcl_->dcl_next);
- }
-
- /*
- * Enter a new directory. The 'xdcl_' linked-list begins with the first
- * actual argument, rather than the command name.
- */
- static
- void fledit_dir (
- int *curfile_,
- char *xcmd_,
- DCLARG *xdcl_)
- {
- FLINK *fixed_ = 0;
- FLINK **SAVEfile = filelist;
- FILENT *SAVEread = readlist;
- DATENT SAVEdchk = datechek;
- int j,
- SAVEpack = pack_exit,
- SAVEmaxf = maxfiles,
- SAVEnumf = numfiles,
- SAVEnumR = readllen,
- SAVEdmod = D_mode,
- SAVEdopt = D_opt,
- SAVEpcol size_pcolumns,
- SAVEtopf = dds_fast(DDS_U_C),
- PACKtopf = SAVEtopf,
- SAVEmark = dircmd_select(-2);
- char SAVEconv size_conv_list,
- SAVEdflg size_dateflag;
-
- /* If options given are illegal, don't go anywhere */
- if (flist_opts (1, &xcmd_, xdcl_, TRUE)) return;
-
- memcpy (SAVEpcol, pcolumns, sizeof(pcolumns));
- memcpy (SAVEdflg, dateflag, sizeof(dateflag));
- strcpy (SAVEconv, conv_list);
-
- if (SAVEmark >= 0) fixed_ = filelist[SAVEmark];
- dircmd_select (-1); /* Start with cleared display-flag */
- pack_exit = FALSE;
- flist (xdcl_); /* Do recursive call on main */
- dircmd_select (-1); /* Call display-flag, if any */
-
- filelist = SAVEfile; /* Restore caller's state */
- readlist = SAVEread;
- maxfiles = SAVEmaxf;
- numfiles = SAVEnumf;
- readllen = SAVEnumR;
- D_mode = SAVEdmod;
- D_opt = SAVEdopt;
- datechek = SAVEdchk;
- memcpy (pcolumns, SAVEpcol, sizeof(pcolumns));
- memcpy (dateflag, SAVEdflg, sizeof(dateflag));
- strcpy (conv_list, SAVEconv);
-
- /*
- * Recompute the number of deleted-entries (in case the lower-level did
- * it), and adjust the top-of-screen index 'PACKtopf', to account for
- * whatever 'dds_pack' will do:
- */
- for (j = numdlets = 0; j < numfiles; j++)
- if (DELETED(j))
- { numdlets++;
- if (pack_exit && (j < SAVEtopf)) PACKtopf--;
- }
-
- /*
- * If we are not skipping display levels, refresh the screen. If there
- * were any files in the lower-level, do a screen-pack. Recompute the
- * longest-column data, and finally reset the marker-entry.
- */
- if (multi_quit <= 0)
- {
- if (pack_exit) dds_pack (curfile_, TRUE);
- dirent_width ((FILENT *)0);
- dds_all (PACKtopf, *curfile_);
-
- if (fixed_) for (j = 0; j < numfiles; j++)
- if (fixed_ == filelist[j] && !DELETED(j))
- {
- dircmd_select (j);
- break;
- }
- }
- pack_exit= SAVEpack;
- }
-
- /*
- * Show the pathname in a form which will cause minimal refresh for very
- * short display-lists:
- */
- static
- void fledit_tell (char *path_)
- {
- flist_info ("Read: %s", path_);
- sleep (1);
- }
-
- /*
- * EDIT/VIEW a file. Normally the user will use the default entry, which
- * edits the current file-entry. In this case, if the file is updated,
- * the entry receives the data for the updated file, and the old entry
- * (if /NOVERSIONS isn't set) is moved to a free slot.
- *
- * On the other hand, if the user employs a "/o" escape to make a different
- * filename, one of two cases may happen:
- * (a) The file exists, whether somewhere else in 'filelist[]', or as
- * a file not read into 'filelist[]'. If it is not already in the
- * an entry is added for the file.
- * (b) The file doesn't exist.
- *
- * In any case, the 'filelist[]' entry which corresponds to the highest
- * version of the file will receive the updated filename.
- *
- * patch: may alter this to put the updated name on the current line.
- * patch: cmd-size should be done with calloc.
- */
- static
- void fledit_file (
- int *curfile_,
- char *xcmd_,
- DCLARG *xdcl_,
- FILENT *z, /* => data for file to edit */
- int inlist) /* >= 0 iff 'z' is found in 'filelist[]'*/
- {
- FILENT zold = *z; /* original old-file data */
- int status, curvers, j,
- oldver = z->fvers,
- rmode = (xdcl_->dcl_text[0] == 'V'), /* "EDIT" or "VIEW" */
- width = crt_width() - 6; /* nominally 74 */
- static char sFMT1[] = "%%s %%-%d.%ds";
- char fullname[MAX_PATH],
- tstspec [MAX_PATH],
- *c_,
- format [sizeof(sFMT1)+6],
- cmd [(3*MAX_PATH)+CRT_COLS]; /* filenames, plus options */
-
- static char *bad_type[] = {"EXE", "OBJ", "OLB"};
- static int max_bad_type = sizeof (bad_type) / sizeof(bad_type[0]);
-
- dirent_glue (fullname, z);
-
- for (j = 0; j < max_bad_type; j++)
- {
- if (strcmp (z->ftype, bad_type[j]) == 0)
- {
- warn ("You cannot edit this file-type: %s", z->ftype);
- return;
- }
- }
-
- if (inlist == -1) /* Add it to the list to edit it */
- inlist = dds_add (z);
-
- if (inlist >= 0) /* If an old-file, check readability */
- {
- if (! dirent_acc (z, "r"))
- {
- flist_info ("You cannot view this file");
- return;
- }
- }
-
- /*
- * If the user has defaulted to EDIT mode, test to ensure that the
- * directory is writeable (i.e., that we can make a new version via
- * EDIT). If not, 'diropen' emits a warning message. In this case,
- * coerce to readonly, and proceed.
- */
- if (! rmode)
- {
- if (! diropen (fullname))
- {
- rmode = TRUE;
- sleep(1);
- clrwarn ();
- }
- }
-
- /*
- * Another reason for forcing readonly mode is if the edited-version
- * is not the highest (current) version. By selecting readonly edit,
- * the editor warning message is suppressed.
- */
- strcpy (tstspec, fullname);
- curvers = highver (tstspec); /* tstspec <= name w/o version */
- if (z->fvers < curvers)
- rmode = TRUE;
-
- if (xdcl_->dcl_text[0] == 'L') {
- strcpy (cmd, "LSEDIT");
- } else {
- strcpy (cmd, "EDIT");
- if (strcmp (getenv("HOME"), zPATHOF(z)))
- {
- char edtini[MAX_PATH];
- sprintf (edtini, "%s%s", getenv("HOME"), "EDTINI.EDT");
- if (!canopen (edtini))
- sprintf (strnull(cmd), "/COMMAND=%s", edtini);
- }
- }
-
- /*
- * Provide for passing through options:
- * (patch: should do better for storage allocation
- */
- if (xcmd_)
- {
- for (xdcl_ = xdcl_->dcl_next; xdcl_; xdcl_ = xdcl_->dcl_next)
- {
- strcat (cmd, " ");
- strcat (cmd, xdcl_->dcl_text);
- }
- }
- else
- {
- strcat (cmd, " ");
- strcat (cmd, fullname);
- }
- if (rmode) strcat (cmd, "/READ_ONLY"); /* (override "/NOREAD") */
-
- sprintf (format, sFMT1, width, width);
- flist_info (format, (rmode ? "VIEW" : "EDIT"), fullname);
-
- dds_spawn (0, *curfile_, cmd, 0, FALSE, 2);
-
- /*
- * On exit, the refresh-option may have altered the current entry,
- * but the prior entry probably still exists. If altered, do a scan
- * to pick up the prior entry, and insert it on the end of the list.
- */
- if (!rmode)
- {
- dirent_chk (z, tstspec);
- if (inlist >= 0)
- {
- if (memcmp (z, &zold, sizeof(FILENT)))
- dds_add2 (z, inlist);
- }
- else
- dds_add (z);
- if (V_opt && oldver && (oldver != z->fvers))
- dds_add (&zold);
- }
- }
-
- /*
- * Title: flquit.c
- *
- * Function: Process a "quit" command for FLIST. If an argument is given,
- * it must be the number of levels to quit from (default: 1).
- * An asterisk quits all levels (actually 999).
- */
- tDIRCMD(flquit)
- {
- int num;
- register char *c_, *d_;
-
- if (xdcl_ = xdcl_->dcl_next)
- {
- c_ = scanint (d_ = xdcl_->dcl_text, &num);
- if (!strcmp("*", d_))
- multi_quit = 999;
- else if (c_ != d_ && *c_ == '\0')
- {
- if (num >= 1)
- multi_quit = num;
- else
- {
- warn ("Argument for QUIT must be positive");
- return;
- }
- }
- else
- {
- warn ("Argument for QUIT must be '*' or number");
- return;
- }
- }
- numfiles = 0; /* Force quit by clearing file count */
- }
-
- /*
- * This entrypoint is called from the main-loop immediately after succeeding
- * in reading a directory. We know that we have a new screen to display, and
- * thus, on exit from the screen, can start over again by a 'dds_pack'.
- */
- void fledit_pack (void)
- {
- pack_exit = (numfiles > 0);
- }
-