/* * Postscript language mode for QEmacs. * * Copyright (c) 2000-2024 Charlie Gordon. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "qe.h" /*---------------- PostScript colors ----------------*/ enum { IN_PS_STRING = 0x0F /* ( ... ) level */, IN_PS_COMMENT = 0x10, }; enum { PS_STYLE_TEXT = QE_STYLE_DEFAULT, PS_STYLE_COMMENT = QE_STYLE_COMMENT, PS_STYLE_STRING = QE_STYLE_STRING, PS_STYLE_NUMBER = QE_STYLE_DEFAULT, PS_STYLE_IDENTIFIER = QE_STYLE_FUNCTION, }; #define wrap 0 static void ps_colorize_line(QEColorizeContext *cp, const char32_t *str, int n, QETermStyle *sbuf, ModeDef *syn) { int i = 0, start = i; char32_t c; int colstate = cp->colorize_state; if (colstate & IN_PS_COMMENT) goto in_comment; if (colstate & IN_PS_STRING) goto in_string; colstate = 0; while (i < n) { start = i; c = str[i++]; switch (c) { /* Should deal with '<...>' '<<...>>' '<~...~>' tokens. */ case '%': in_comment: if (wrap) colstate |= IN_PS_COMMENT; else colstate &= ~IN_PS_COMMENT; i = n; SET_STYLE(sbuf, start, i, PS_STYLE_COMMENT); continue; case '(': colstate++; in_string: /* parse string skipping embedded \\ */ while (i < n) { switch (str[i++]) { case '(': colstate++; continue; case ')': colstate--; if (!(colstate & IN_PS_STRING)) break; continue; case '\\': if (i == n) break; i++; continue; default: continue; } break; } SET_STYLE(sbuf, start, i, PS_STYLE_STRING); continue; default: break; } /* parse numbers */ if (qe_isdigit(c)) { for (; i < n; i++) { if (!qe_isalnum(str[i]) && str[i] != '.') break; } SET_STYLE(sbuf, start, i, PS_STYLE_NUMBER); continue; } /* parse identifiers and keywords */ if (qe_isalpha_(c)) { for (; i < n; i++) { if (qe_findchar(" \t\r\n,()<>[]{}/", str[i])) break; } SET_STYLE(sbuf, start, i, PS_STYLE_IDENTIFIER); continue; } } cp->colorize_state = colstate; #undef wrap } static int ps_mode_probe(ModeDef *mode, ModeProbeData *p) { if (match_extension(p->filename, mode->extensions)) return 80; if (*p->buf == '%' && qe_stristr((const char *)p->buf, "script")) return 40; return 1; } static ModeDef ps_mode = { .name = "Postscript", .extensions = "ps|ms|eps", .mode_probe = ps_mode_probe, .colorize_func = ps_colorize_line, }; static int ps_init(QEmacsState *qs) { qe_register_mode(qs, &ps_mode, MODEF_SYNTAX); return 0; } qe_module_init(ps_init);