diff --git a/manual/luatex-callbacks.tex b/manual/luatex-callbacks.tex index ddeeb05b1b49916057391734bee115ef39881a93..62a37c5bce1b1b3e46ee08cecb6314afc36bf09c 100644 --- a/manual/luatex-callbacks.tex +++ b/manual/luatex-callbacks.tex @@ -852,6 +852,17 @@ end This callback replaces the code that prints \LUATEX's when a file is closed like the \type {)} for regular files. +\subsection{\type {call_edit}} + +\startfunctioncall +function(filename,linenumber) +end +\stopfunctioncall + +This callback replaces the call to an external editor when \quote{E} is pressed +in reply to an error message. Processing will end immediately after the callback +returns control to the main program. + \section{PDF-related callbacks} \subsection{\type {finish_pdffile}} diff --git a/manual/luatex.pdf b/manual/luatex.pdf index cdc2b22a5a2db413a496e9f804898555aa8fa215..a757b4395a0ace0633a81203785f8a888f0c633b 100644 Binary files a/manual/luatex.pdf and b/manual/luatex.pdf differ diff --git a/source/texk/web2c/luatexdir/lua/lcallbacklib.c b/source/texk/web2c/luatexdir/lua/lcallbacklib.c index 6bdaca016fd3215f44cadf7c9dc75b1b477fa804..812ad437b1ae50d79571da075c80d55f1cc17290 100644 --- a/source/texk/web2c/luatexdir/lua/lcallbacklib.c +++ b/source/texk/web2c/luatexdir/lua/lcallbacklib.c @@ -72,6 +72,7 @@ static const char *const callbacknames[] = { "process_rule", "insert_local_par", "contribute_filter", + "call_edit", NULL }; diff --git a/source/texk/web2c/luatexdir/luatex.c b/source/texk/web2c/luatexdir/luatex.c index 7e06c9388857cf10c466010c373f1ecec161b9e4..5d91ccbbbc49006002c0f14b441ab23b05a132f8 100644 --- a/source/texk/web2c/luatexdir/luatex.c +++ b/source/texk/web2c/luatexdir/luatex.c @@ -61,10 +61,6 @@ const char *engine_name = my_name; /* the name of this engine */ #include <signal.h> /* Catch interrupts. */ -/* {tex,mf}d.h defines TeX, MF, INI, and other such symbols. - Unfortunately there's no way to get the banner into this code, so - just repeat the text. */ -#define edit_var "TEXEDIT" /* Shell escape. diff --git a/source/texk/web2c/luatexdir/luatex_svnversion.h b/source/texk/web2c/luatexdir/luatex_svnversion.h index bef33fd6cdaf731b952407c2dbd829dc4602d29a..4e8e09752805256625103566cf71be7bc0c6f133 100644 --- a/source/texk/web2c/luatexdir/luatex_svnversion.h +++ b/source/texk/web2c/luatexdir/luatex_svnversion.h @@ -1 +1 @@ -#define luatex_svn_revision -1 +#define luatex_svn_revision 6128 diff --git a/source/texk/web2c/luatexdir/luatexcallbackids.h b/source/texk/web2c/luatexdir/luatexcallbackids.h index 4a02f05d058e785b932f610482364a3f947dfa83..cfd865b896a84d9a9e73c1ea339c3b9476850731 100644 --- a/source/texk/web2c/luatexdir/luatexcallbackids.h +++ b/source/texk/web2c/luatexdir/luatexcallbackids.h @@ -66,6 +66,7 @@ typedef enum { process_rule_callback, insert_local_par_callback, contribute_filter_callback, + call_edit_callback, total_callbacks } callback_callback_types; diff --git a/source/texk/web2c/luatexdir/tex/errors.w b/source/texk/web2c/luatexdir/tex/errors.w index 1af16ec58ef41ea8092cf103672927a8b4b1f6c8..5dfdc8d6a8c1ca46d77e1b82dc9148f6d563d471 100644 --- a/source/texk/web2c/luatexdir/tex/errors.w +++ b/source/texk/web2c/luatexdir/tex/errors.w @@ -24,6 +24,7 @@ luafflib.c @ @c #include "ptexlib.h" +#define edit_var "TEXEDIT" @ When something anomalous is detected, \TeX\ typically does something like this: $$\vbox{\halign{#\hfil\cr @@ -232,6 +233,147 @@ void jump_out(void) close_files_and_terminate(); do_final_end(); } +@ Here is the function that calls the editor, if one is defined. This +is loosely based on a similar function in kpathsea, but the calling +convention is quite different. + +@c +static const_string edit_value = EDITOR; + +__attribute__ ((noreturn)) +static void luatex_calledit (int baseptr, int linenumber) +{ + char *temp, *command, *fullcmd; + char c; + int sdone, ddone, i; + char *filename = makecstring(input_stack[base_ptr].name_field); + int fnlength = strlen(filename); + +#ifdef WIN32 + char *fp, *ffp, *env, editorname[256], buffer[256]; + int cnt = 0; + int dontchange = 0; +#endif + + sdone = ddone = 0; + + /* Close any open input files, since we're going to kill the job. */ + close_files_and_terminate(); + + /* Replace the default with the value of the appropriate environment + variable or config file value, if it's set. */ + temp = kpse_var_value (edit_var); + if (temp != NULL) + edit_value = temp; + + /* Construct the command string. The `11' is the maximum length an + integer might be. */ + command = xmalloc (strlen (edit_value) + fnlength + 11); + + /* So we can construct it as we go. */ + temp = command; + +#ifdef WIN32 + fp = editorname; + if ((isalpha(*edit_value) && *(edit_value + 1) == ':' + && IS_DIR_SEP (*(edit_value + 2))) + || (*edit_value == '"' && isalpha(*(edit_value + 1)) + && *(edit_value + 2) == ':' + && IS_DIR_SEP (*(edit_value + 3))) + ) + dontchange = 1; +#endif + + while ((c = *edit_value++) != 0) + { + if (c == '%') + { + switch (c = *edit_value++) + { + case 'd': + if (ddone) + FATAL1 ("call_edit: `%%d' appears twice in editor command: `%s'", edit_value); + sprintf (temp, "%ld", (long int)linenumber); + while (*temp != '\0') + temp++; + ddone = 1; + break; + + case 's': + if (sdone) + FATAL1 ("call_edit: `%%s' appears twice in editor command: `%s'", edit_value); + for (i =0; i < fnlength; i++) + *temp++ = filename[i]; + sdone = 1; + break; + + case '\0': + *temp++ = '%'; + /* Back up to the null to force termination. */ + edit_value--; + break; + + default: + *temp++ = '%'; + *temp++ = c; + break; + } + } + else { +#ifdef WIN32 + if (dontchange) + *temp++ = c; + else { if(Isspace(c) && cnt == 0) { + cnt++; + temp = command; + *temp++ = c; + *fp = '\0'; + } else if(!Isspace(c) && cnt == 0) { + *fp++ = c; + } else { + *temp++ = c; + } + } +#else + *temp++ = c; +#endif + } + } + + *temp = 0; + +#ifdef WIN32 + if (dontchange == 0) { + if(editorname[0] == '.' || + editorname[0] == '/' || + editorname[0] == '\\') { + fprintf(stderr, "%s is not allowed to execute.\n", editorname); + do_final_end(); + } + env = (char *)getenv("PATH"); + if(SearchPath(env, editorname, ".exe", 256, buffer, &ffp)==0) { + if(SearchPath(env, editorname, ".bat", 256, buffer, &ffp)==0) { + fprintf(stderr, "I cannot find %s in the PATH.\n", editorname); + do_final_end(); + } + } + fullcmd = (char *)xmalloc(strlen(buffer)+strlen(command)+5); + strcpy(fullcmd, "\""); + strcat(fullcmd, buffer); + strcat(fullcmd, "\""); + strcat(fullcmd, command); + } else +#endif + fullcmd = command; + + /* Execute the command. */ + if (system (fullcmd) != 0) + fprintf (stderr, "! Trouble executing `%s'.\n", command); + + /* Quit, since we found an error. */ + do_final_end (); +} + @ @c void error(void) @@ -325,12 +467,18 @@ void error(void) #endif case 'E': if (base_ptr > 0) { - tprint_nl("You want to edit file "); - print(input_stack[base_ptr].name_field); - tprint(" at line "); - print_int(line); - interaction = scroll_mode; - jump_out(); + int callback_id = callback_defined(call_edit_callback); + if (callback_id>0) { + (void)run_callback(callback_id, "Sd->", makecstring(input_stack[base_ptr].name_field), line); + jump_out(); /* should not be reached */ + } else { + tprint_nl("You want to edit file "); + print(input_stack[base_ptr].name_field); + tprint(" at line "); + print_int(line); + interaction = scroll_mode; + luatex_calledit(base_ptr, line); + } } break; case 'H':