diff options
Diffstat (limited to 'src/LYEdit.c')
-rw-r--r-- | src/LYEdit.c | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/src/LYEdit.c b/src/LYEdit.c new file mode 100644 index 0000000..ee0b832 --- /dev/null +++ b/src/LYEdit.c @@ -0,0 +1,298 @@ +/* $LynxId: LYEdit.c,v 1.42 2013/11/28 11:18:19 tom Exp $ */ +#include <HTUtils.h> +#include <HTParse.h> +#include <HTAlert.h> +#include <LYCurses.h> +#include <LYUtils.h> +#include <LYGlobalDefs.h> +#include <LYStrings.h> +#include <LYEdit.h> +#ifdef VMS +#include <unixio.h> +#endif /* VMS */ + +#include <LYLeaks.h> +#include <www_wait.h> + +BOOLEAN editor_can_position(void) +{ + char *value; + HTList *p = positionable_editor; + static const char *table[] = + { +#ifdef VMS + "sedt", +#else + "emacs", /* + xemacs */ + "jed", + "jmacs", + "joe", /* + rjoe */ + "jove", + "jstar", + "nano", + "pico", /* + jpico */ + "vi" /* + vim, xvi, vile, elvis, view... + likely false matches */ +#endif + }; + unsigned n; + + for (n = 0; n < TABLESIZE(table); n++) { + if (LYstrstr(editor, table[n]) != 0) { + return TRUE; + } + } + /* + * This really isn't right. LYstrstr() might be too lax, + * but this should at least match basename to basename... + */ + if (positionable_editor != NULL) { + while ((value = (char *) HTList_nextObject(p)) != NULL) { + if (strcmp(editor, value) == 0) { + return TRUE; + } + } + } + return FALSE; +} + +/* + * In edit mode invoke the given (or default) editor to display and edit the + * current file. For editors listed in 'editor_can_position()', Lynx will open + * the file to the same line that the screen cursor is on (or close...) when + * editing is invoked. + * + * Returns FALSE if file is uneditable. + */ +int edit_current_file(char *newfile, + int cur, + int lineno) +{ + int result = FALSE; + char *filename = NULL; + +#if !(defined(VMS) || defined(USE_DOS_DRIVES)) + char *colon; +#endif + char *number_sign; + char position[80]; + +#if defined(VMS) || defined(CANT_EDIT_UNWRITABLE_FILES) + FILE *fp; +#endif + + CTRACE((tfp, "edit_current_file(newfile=%s, cur=%d, lineno=%d)\n", + newfile, cur, lineno)); + + /* + * If it's a remote file then we can't edit it. + */ + if (!LYisLocalFile(newfile)) { + HTUserMsg(CANNOT_EDIT_REMOTE_FILES); + return FALSE; + } + + /* + * If there's a fragment, trim it. - FM + */ + number_sign = trimPoundSelector(newfile); + + /* + * On Unix, first try to open it as a completely referenced file, then via + * the path alone. + * + * On VMS, only try the path. + */ +#if defined (VMS) || defined (USE_DOS_DRIVES) + filename = HTParse(newfile, "", PARSE_PATH + PARSE_PUNCTUATION); + HTUnEscape(filename); + StrAllocCopy(filename, HTSYS_name(filename)); + if (!LYCanReadFile(filename)) { +#ifdef SH_EX + HTUserMsg2(COULD_NOT_EDIT_FILE, filename); +#else + HTAlert(COULD_NOT_ACCESS_FILE); +#endif + CTRACE((tfp, "filename: '%s'\n", filename)); + goto done; + } +#else /* something like UNIX */ + if (StrNCmp(newfile, "file://localhost/", 16) == 0) + colon = newfile + 16; + else + colon = StrChr(newfile, ':'); + StrAllocCopy(filename, (colon + 1)); + HTUnEscape(filename); + if (!LYCanReadFile(filename)) { + FREE(filename); + filename = HTParse(newfile, "", PARSE_PATH + PARSE_PUNCTUATION); + HTUnEscape(filename); + if (!LYCanReadFile(HTSYS_name(filename))) { + HTAlert(COULD_NOT_ACCESS_FILE); + goto done; + } + } +#endif + +#if defined(VMS) || defined(CANT_EDIT_UNWRITABLE_FILES) + /* + * Don't allow editing if user lacks append access. + */ + if ((fp = fopen(filename, TXT_A)) == NULL) { + HTUserMsg(NOAUTH_TO_EDIT_FILE); + goto done; + } + fclose(fp); +#endif /* VMS || CANT_EDIT_UNWRITABLE_FILES */ + + /* + * Make sure cur is at least zero. - FM + */ + if (cur < 0) { + cur = 0; + } + + /* + * Set up the command for the editor. - FM + */ + if (lineno >= 0) { + *position = 0; +#ifdef VMS + lineno--; +#endif + lineno += (nlinks ? links[cur].ly : 0); + if (lineno > 0) + sprintf(position, "%d", lineno); + } else { + *position = '\0'; + } + + edit_temporary_file(filename, position, NULL); + result = TRUE; + + done: + /* + * Restore the fragment if there was one. - FM + */ + restorePoundSelector(number_sign); + + FREE(filename); + CTRACE((tfp, "edit_current_file returns %d\n", result)); + return (result); +} + +void edit_temporary_file(char *filename, + const char *position, + const char *message) +{ +#ifdef UNIX + struct stat stat_info; +#endif + const char *format = "%s %s"; + char *command = NULL; + const char *editor_arg = ""; + int params = 1; + int rv; + + if (LYstrstr(editor, "pico")) { + editor_arg = " -t"; /* No prompt for filename to use */ + } + if (editor_can_position() && *position) { +#ifdef VMS + format = "%s %s -%s%s"; + HTAddXpand(&command, format, params++, editor); + HTAddParam(&command, format, params++, filename); + HTAddParam(&command, format, params++, position); + HTAddParam(&command, format, params++, editor_arg); + HTEndParam(&command, format, params); +#else + format = "%s +%s%s %s"; + HTAddXpand(&command, format, params++, editor); + HTAddParam(&command, format, params++, position); + HTAddParam(&command, format, params++, editor_arg); + HTAddParam(&command, format, params++, filename); + HTEndParam(&command, format, params); +#endif + } +#ifdef DOSPATH + else if (StrNCmp(editor, "VZ", 2) == 0) { + /* for Vz editor */ + format = "%s %s -%s"; + HTAddXpand(&command, format, params++, editor); + HTAddParam(&command, format, params++, HTDOS_short_name(filename)); + HTAddParam(&command, format, params++, position); + HTEndParam(&command, format, params); + } else if (StrNCmp(editor, "edit", 4) == 0) { + /* for standard editor */ + HTAddXpand(&command, format, params++, editor); + HTAddParam(&command, format, params++, HTDOS_short_name(filename)); + HTEndParam(&command, format, params); + } +#endif + else { +#ifdef _WINDOWS + if (StrChr(editor, ' ')) + HTAddXpand(&command, format, params++, HTDOS_short_name(editor)); + else + HTAddXpand(&command, format, params++, editor); +#else + HTAddXpand(&command, format, params++, editor); +#endif + HTAddParam(&command, format, params++, filename); + HTEndParam(&command, format, params); + } + if (message != NULL) { + _statusline(message); + } + + CTRACE((tfp, "LYEdit: %s\n", command)); + CTRACE_SLEEP(MessageSecs); + + stop_curses(); + +#ifdef UNIX + set_errno(0); +#endif + if ((rv = LYSystem(command)) != 0) { /* Spawn Editor */ + start_curses(); + /* + * If something went wrong, we should probably return soon; currently + * we don't, but at least put out a message. - kw + */ + { +#if defined(UNIX) && defined(WIFEXITED) + int save_err = errno; + + CTRACE((tfp, "ExtEditForm: system() returned %d (0x%x), %s\n", + rv, rv, + (save_err + ? LYStrerror(save_err) + : "reason unknown"))); + LYFixCursesOn("show error warning:"); + if (rv == -1) { + HTUserMsg2(gettext("Error starting editor, %s"), + LYStrerror(save_err)); + } else if (WIFSIGNALED(rv)) { + HTAlwaysAlert(NULL, gettext("Editor killed by signal")); + } else if (WIFEXITED(rv) && WEXITSTATUS(rv) != 127) { + char exitcode[80]; + + sprintf(exitcode, "%d", WEXITSTATUS(rv)); + HTUserMsg2(gettext("Editor returned with error status %s"), + exitcode); + } else +#endif + HTAlwaysAlert(NULL, ERROR_SPAWNING_EDITOR); + } + } else { + start_curses(); + } +#ifdef UNIX + /* + * Delete backup file, if that's your style. + */ + HTSprintf0(&command, "%s~", filename); + if (stat(command, &stat_info) == 0) + remove(command); +#endif + FREE(command); +} |