summaryrefslogtreecommitdiffstats
path: root/src/LYEdit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/LYEdit.c')
-rw-r--r--src/LYEdit.c298
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);
+}