diff -N -uwp qemacs-0.3pre13/Makefile qemacs-0.3pre13.hacked/Makefile --- qemacs-0.3pre13/Makefile 2003-01-29 00:45:22.000000000 +0100 +++ qemacs-0.3pre13.hacked/Makefile 2003-01-30 14:37:17.000000000 +0100 @@ -112,7 +112,7 @@ OBJS+=charsetmore.o charset_table.o endif ifdef CONFIG_ALL_MODES -OBJS+= unihex.o clang.o xml.o bufed.o +OBJS+= unihex.o clang.o latex-mode.o xml.o bufed.o ifndef CONFIG_WIN32 OBJS+= shell.o dired.o endif @@ -234,7 +234,7 @@ css.c cssid.h cssparse.c xmlparse.c html indic.c unicode_join.c css.h input.c qeconfig.h \ qeend.c unihex.c arabic.c csstoqe.c kmaptoqe.c util.c \ bufed.c html_style.c qestyles.h x11.c buffer.c ligtoqe.c \ -qfribidi.c clang.c xml.c dired.c list.c qfribidi.h html2png.c \ +qfribidi.c clang.c latex-mode.c xml.c dired.c list.c qfribidi.h html2png.c \ charsetmore.c charset_table.c cptoqe.c \ libfbf.c fbfrender.c cfb.c fbftoqe.c libfbf.h fbfrender.h cfb.h \ display.c display.h mpeg.c shell.c \ Common subdirectories: qemacs-0.3pre13/fonts and qemacs-0.3pre13.hacked/fonts diff -N -uwp qemacs-0.3pre13/latex-mode.c qemacs-0.3pre13.hacked/latex-mode.c --- qemacs-0.3pre13/latex-mode.c 1970-01-01 01:00:00.000000000 +0100 +++ qemacs-0.3pre13/latex-mode.c 2003-01-30 14:37:37.000000000 +0100 @@ -0,0 +1,338 @@ +/* + * LaTeX mode for QEmacs. + * Copyright (c) 2003 Martin Hedenfalk + * Based on c-mode by Fabrice Bellard + * Requires the shell mode + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "qe.h" + +#define MAX_BUF_SIZE 512 + +EditBuffer *new_shell_buffer(const char *name, + const char *path, char **argv, int is_shell); +static ModeDef latex_mode; + +/* TODO: add state handling to allow colorization of elements longer + * than one line (eg, multi-line functions and strings) + */ +static void latex_colorize_line(unsigned int *buf, int len, + int *colorize_state_ptr, int state_only) +{ + int c, state; + unsigned int *p, *p_start; + + state = *colorize_state_ptr; + p = buf; + p_start = p; + + for(;;) { + p_start = p; + c = *p; + switch(c) { + case '\n': + goto the_end; + case '`': + p++; + /* a ``string'' */ + if(*p == '`') { + while(1) { + p++; + if(*p == '\n' || (*p == '\'' && *(p+1) == '\'')) + break; + } + if(*p == '\'' && *++p == '\'') + p++; + set_color(p_start, p - p_start, QE_STYLE_STRING); + } + break; + case '\\': + p++; + /* \function[keyword]{variable} */ + if(*p == '\'' || *p == '\"' || *p == '~' || *p == '%' || *p == '\\') + p++; + else { + while(*p != '{' && *p != '[' && *p != '\n' && *p != ' ' && *p != '\\') + p++; + } + set_color(p_start, p - p_start, QE_STYLE_FUNCTION); + while(*p == ' ' || *p == '\t') + /* skip space */ + p++; + while(*p == '{' || *p == '[') { + if(*p++ == '[') { + /* handle [keyword] */ + p_start = p; + while(*p != ']' && *p != '\n') + p++; + set_color(p_start, p - p_start, QE_STYLE_KEYWORD); + if(*p == ']') + p++; + } else { + int braces = 0; + /* handle {variable} */ + p_start = p; + while(*p != '\n') { + if(*p == '{') + braces++; + else if(*p == '}') + if(braces-- == 0) + break; + p++; + } + set_color(p_start, p - p_start, QE_STYLE_VARIABLE); + if(*p == '}') + p++; + } + while(*p == ' ' || *p == '\t') + /* skip space */ + p++; + } + break; + case '%': + p++; + /* line comment */ + while (*p != '\n') + p++; + set_color(p_start, p - p_start, QE_STYLE_COMMENT); + break; + default: + p++; + break; + } + } + the_end: + *colorize_state_ptr = state; +} + +static int latex_mode_probe(ModeProbeData *p) +{ + const char *r; + + /* currently, only use the file extension */ + r = strrchr(p->filename, '.'); + if (r) { + r++; + if (strcasecmp(r, "tex") == 0) + return 100; + } + return 0; +} + +static int latex_mode_init(EditState *s, ModeSavedData *saved_data) +{ + int ret; + ret = text_mode_init(s, saved_data); + if (ret) + return ret; + set_colorize_func(s, latex_colorize_line); + return ret; +} + +static void do_tex_insert_quote(EditState *s) +{ + int offset_bol, len, offset1; + unsigned int buf[MAX_BUF_SIZE]; + int p; + + offset_bol = eb_goto_bol(s->b, s->offset); + offset1 = offset_bol; + len = eb_get_line(s->b, buf, MAX_BUF_SIZE - 1, &offset1); + p = s->offset - offset_bol; + + if(p >= 1 && buf[p-1] == '\"') { + eb_insert(s->b, s->offset, "\"", 1); + s->offset++; + } else if(p >= 2 && (buf[p-1] == '`' || buf[p-1] == '\'') && + buf[p-1] == buf[p-2]) + { + eb_delete(s->b, s->offset - 2, 2); + eb_insert(s->b, s->offset, "\"", 1); + s->offset++; + } else { + if(p == 0 || buf[p-1] == ' ') { + eb_insert(s->b, s->offset, "``", 2); + s->offset += 2; + } else { + eb_insert(s->b, s->offset, "''", 2); + s->offset += 2; + } + } +} + +static struct latex_function { + char *name; + char *fmt; + int ask; + int output_to_buffer; + StringArray history; + EditState *es; +} latex_funcs[] = { +{"AmSTeX", "amstex '\\nonstopmode\\input %s'", 0, 1}, +{"PDFLaTeX", "pdflatex '\\nonstopmode\\input{%s}'", 0, 1}, +{"PDFTeX", "pdftex '\\nonstopmode\\input %s'", 0, 1}, +{"Check", "lacheck %s", 0, 1}, +{"BibTeX", "bibtex %s", 0, 1}, +{"LaTeX", "latex --src-specials '\\nonstopmode\\input{%s}'", 0, 1}, +{"ThumbPDF", "thumbpdf %s", 0, 1}, +{"View", "xdvi %s.dvi -paper a4", 1, 0}, +{"Print", "dvips %s -Plp", 1, 0}, +{"File", "dvips %s.dvi -o %s.ps", 1, 1}, +{0, 0, 0, 0} +}; + +static void latex_completion(StringArray *cs, const char *input) +{ + int i, len; + + len = strlen(input); + for(i = 0; latex_funcs[i].name; i++) { + if(strncasecmp(input, latex_funcs[i].name, len) == 0) + add_string(cs, latex_funcs[i].name); + } +} + +static void latex_cmd_run(void *opaque, char *cmd) +{ + struct latex_function *func = (struct latex_function *)opaque; + char *argv[4], cwd[1024]; + char *wd, *p; + int len; + + if(cmd == 0) { + put_status(func->es, "aborted"); + return; + } + + argv[0] = "/bin/sh"; + argv[1] = "-c"; + argv[2] = cmd; + argv[3] = NULL; + + getcwd(cwd, sizeof(cwd)); + + /* get the directory of the open file and change into it + */ + p = strrchr(func->es->b->filename, '/'); + if(p == func->es->b->filename) + p++; + len = p - func->es->b->filename + 1; + wd = (char *)malloc(len); + pstrcpy(wd, len, func->es->b->filename); + chdir(wd); + free(wd); + + if(func->output_to_buffer) { + /* if the buffer already exists, kill it */ + EditBuffer *b = eb_find("*LaTeX output*"); + if (b) { + /* XXX: e should not become invalid */ + b->modified = 0; + do_kill_buffer(func->es, "*LaTeX output*"); + } + + /* create new buffer */ + b = new_shell_buffer("*LaTeX output*", "/bin/sh", argv, 0); + if (b) + /* XXX: try to split window if necessary */ + switch_to_buffer(func->es, b); + } else { + int pid = fork(); + if (pid == 0) { + /* child process */ + setsid(); + execv("/bin/sh", (char *const*)argv); + exit(1); + } + } + chdir(cwd); +} + +static void do_latex(EditState *e, const char *cmd) +{ + char buf[1024]; + int i; + char *p, *f; + char *bname; + + /* strip extension from filename, find the last dot after the last + * slash (ie, the last dot in the filename) + */ + f = strrchr(e->b->filename, '/'); + if(f) f++; + else f = e->b->filename; + p = strrchr(f, '.'); + if(p) { + int len = p - e->b->filename; + bname = (char *)malloc(len + 1); + pstrncpy(bname, len + 1, e->b->filename, len); + } else + bname = strdup(e->b->filename); + + if(!cmd || cmd[0] == '\0') + strcpy(buf, "LaTeX"); + else + strcpy(buf, cmd); + + /* check what command to run */ + for(i = 0; latex_funcs[i].name; i++) { + if(strcasecmp(buf, latex_funcs[i].name) == 0) { + /* pass the EditState through to latex_cmd_run() */ + latex_funcs[i].es = e; + /* construct the command line to run */ + snprintf(buf, sizeof(buf), latex_funcs[i].fmt, bname, bname); + if(latex_funcs[i].ask) { + char prompt[128]; + snprintf(prompt, sizeof(prompt), "%s command: ", + latex_funcs[i].name); + minibuffer_edit(buf, prompt, &latex_funcs[i].history, + NULL /* completion */, + latex_cmd_run, (void *)&latex_funcs[i]); + } else + latex_cmd_run((void *)&latex_funcs[i], buf); + break; + } + } + if(latex_funcs[i].name == 0) + put_status(e, "%s: No match", buf); + free(bname); +} + +/* specific LaTeX commands */ +static CmdDef latex_commands[] = { + CMD0('\"', KEY_NONE, "tex-insert-quote", do_tex_insert_quote) + /* this should actually be KEY_CTRLC(KEY_CTRL('c')), ie C-c C-c */ + CMD( KEY_CTRL('c'), KEY_NONE, "TeX-command-master\0s{Command: (default LaTeX) }[latex]|latex|", do_latex) + CMD_DEF_END, +}; + +static int latex_init(void) +{ + /* LaTeX mode is almost like the text mode, so we copy and patch it */ + memcpy(&latex_mode, &text_mode, sizeof(ModeDef)); + latex_mode.name = "LaTeX"; + latex_mode.mode_probe = latex_mode_probe; + latex_mode.mode_init = latex_mode_init; + + qe_register_mode(&latex_mode); + qe_register_cmd_table(latex_commands, "LaTeX"); + register_completion("latex", latex_completion); + + return 0; +} + +qe_module_init(latex_init); Common subdirectories: qemacs-0.3pre13/plugin-example and qemacs-0.3pre13.hacked/plugin-example Common subdirectories: qemacs-0.3pre13/tests and qemacs-0.3pre13.hacked/tests