/* * Copyright (c) 2003 Benedikt Meurer (benedikt.meurer@unix-ag.uni-siegen.de) * 2004 Jean-François Wauthy (pollux@xfce.org) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 Library General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include #endif /* !HAVE_CONFIG_H */ #include #include #include #include #include #include #include #include #include #include #include "option.h" #include "xfprintsettings.h" #ifndef HAVE_STRLCPY #define strlcpy g_strlcpy #endif /* list of supported papersizes */ const XfprintOption papersizes[] = { { "10x14", "10x14" }, { "DIN A3", "A3" }, { "DIN A4", "A4" }, { "DIN A4 (Deskjet)", "A4dj" }, { "DIN A5", "A5" }, { "DIN B4", "B4" }, { "DIN B5", "B5" }, { "Executive", "Executive" }, { "Folio", "Folio" }, { "Ledger", "Ledger" }, { "Legal", "Legal" }, { "Letter", "Letter" }, { "Letter (Deskjet)", "Letterdj" }, { "Quatro", "Quatro" }, { "Statement", "Statement" }, { "Tabloid", "Tabloid" }, { NULL, NULL } }; /* list of supported encodings */ const XfprintOption encodings[] = { { "US-ASCII", "ascii" }, { "HP", "hp" }, { "IBM Codepage 437", "ibm-cp437" }, { "IBM Codepage 850", "ibm-cp850" }, { "ISO-8859-1", "iso1" }, { "ISO-8859-2", "iso2" }, { "ISO-8859-3", "iso3" }, { "ISO-8859-4", "iso4" }, { "ISO-8859-5", "iso5" }, { "ISO-8859-7", "iso7" }, { "ISO-8859-9", "iso9" }, { "ISO-8859-10", "iso10" }, { "ISO-8859-13", "iso13" }, { "ISO-8859-15", "iso15" }, { "KOI8", "koi8" }, { "MAC", "mac" }, { "MS Codepage 1250", "ms-cp1250" }, { NULL, NULL } }; /* list of supported style sheets */ const XfprintOption languages[] = { { "Autoselect", "__auto__" }, { "Ada", "ada" }, { "Autoconf", "autoconf" }, { "AWK", "awk" }, { "B", "b" }, { "bc", "bc" }, { "C", "c" }, { "C shell", "csh" }, { "Fortran", "fortran" }, { "GNU Make", "gmake" }, { "HTML", "html" }, { "IDL", "idl" }, { "Java", "java" }, { "JavaScript", "js" }, { "Lex", "lex" }, { "Make", "make" }, { "Modula 2", "modula2" }, { "Modula 3", "modula3" }, { "Perl", "perl" }, { "Python", "python" }, { "Sather", "sather" }, { "Tex", "tex" }, { "Z shell", "zsh" }, { NULL, NULL } }; /* list of supported non-printable format handlings */ const XfprintOption non_printable_fmts[] = { { "Octal", "octal" }, { "Hexadecimal", "hexa" }, { "Emacs", "emacs" }, { "Questionmark", "Questionmark" }, { "Left blank", "blank" }, { "Caret", "caret" }, { NULL, NULL } }; /* list of supported highlight levels */ const XfprintOption hilevels[] = { { "None", "none" }, { "Normal", "normal" }, { "Heavy", "heavy" }, { NULL, NULL } }; static void load_settings_from_file(const gchar *, XfprintSettings *); static void save_settings_to_file(const gchar *, const XfprintSettings *); void xfprintsettings_save(const XfprintSettings *settings) { gchar *path; g_return_if_fail(settings != NULL); path = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, "xfce4/printsettings.xml", TRUE); save_settings_to_file(path, settings); g_free(path); } XfprintSettings * xfprintsettings_defaults(void) { XfprintSettings *settings; settings = g_new0(XfprintSettings, 1); /* set default values */ settings->sheets.landscape = FALSE; settings->sheets.fillcols = TRUE; settings->sheets.cols = 1; settings->sheets.rows = 1; #ifdef DEFAULT_LETTER settings->sheets.papersize = "Letter"; #else settings->sheets.papersize = "A4dj"; #endif settings->sheets.borders = FALSE; settings->sheets.reverse = FALSE; settings->vpages.linenumbers = 0; settings->vpages.lpp = 0; settings->vpages.cpl = 0; settings->vpages.tabsize = 8; settings->vpages.nonprtfmt = "caret"; settings->pprint.language = "__auto__"; settings->pprint.highlight = "normal"; settings->pprint.strip = 0; settings->input.encoding = "iso1"; settings->input.all = TRUE; settings->input.from = 1; settings->input.to = 1; settings->input.cut = TRUE; settings->input.interpret = TRUE; settings->input.binary = FALSE; settings->headings.headers = FALSE; strcpy(settings->headings.header, "%a"); strcpy(settings->headings.underlay, ""); strcpy(settings->headings.ctitle, "#?1|$t1|$n|"); strcpy(settings->headings.ltitle, "#?2||$e $T|"); strcpy(settings->headings.rtitle, "#?2|$t2|$Q|"); strcpy(settings->headings.cfooter, "#?l|#!s-$f-, -||"); strcpy(settings->headings.lfooter, "#?l!%E!#?v|%E|%s./%s#|!"); strcpy(settings->headings.rfooter, "#?l!%s./%s#!#?v|%s./%s#|%E|!"); settings->copies = 1; return(settings); } XfprintSettings * xfprintsettings_load(void) { XfprintSettings *settings; gchar *path; path = xfce_resource_lookup (XFCE_RESOURCE_CONFIG, "xfce4/printsettings.xml"); settings = xfprintsettings_defaults(); load_settings_from_file(path, settings); g_free(path); return(settings); } void xfprintsettings_free(XfprintSettings *settings) { if (settings) g_free(settings); } /* * XML stuff */ typedef enum _SettingsParserState SettingsParserState; enum _SettingsParserState { START, PRINTSETTINGS }; typedef struct _SettingsParser SettingsParser; struct _SettingsParser { XfprintSettings *settings; SettingsParserState state; }; static void start_element_handler(GMarkupParseContext *ctx, const gchar *element_name, const gchar **attr_names, const gchar **attr_values, gpointer user_data, GError **error) { XfprintSettingsVirtualPages *v; XfprintSettingsPrettyPrint *p; XfprintSettingsHeadings *h; XfprintSettingsSheets *s; XfprintSettingsInput *i; SettingsParser *parser; gint n; parser = (SettingsParser *)user_data; i = &parser->settings->input; h = &parser->settings->headings; p = &parser->settings->pprint; s = &parser->settings->sheets; v = &parser->settings->vpages; switch (parser->state) { case START: if (strcmp(element_name, "printsettings") != 0) break; parser->state = PRINTSETTINGS; break; case PRINTSETTINGS: for (n = 0; attr_names[n] != NULL; n++) { if (!strcmp(element_name, "sheets")) { if (!strcmp(attr_names[n], "mode")) { s->landscape = !strcmp(attr_values[n], "landscape"); } else if (!strcmp(attr_names[n], "major")) { s->fillcols = !strcmp(attr_values[n], "cols"); } else if (!strcmp(attr_names[n], "cols")) { s->cols = strtol(attr_values[n], NULL, 10); } else if (!strcmp(attr_names[n], "rows")) { s->rows = strtol(attr_values[n], NULL, 10); } else if (!strcmp(attr_names[n], "papersize")) { s->papersize = xfprint_option(papersizes, attr_values[n]); } else if (!strcmp(attr_names[n], "borders")) { s->borders = !strcmp(attr_values[n], "true"); } else if (!strcmp(attr_names[n], "reverse")) { s->reverse = !strcmp(attr_values[n], "true"); } } else if (!strcmp(element_name, "vpages")) { if (!strcmp(attr_names[n], "linenumbers")) { v->linenumbers = strtol(attr_values[n], NULL, 10); } if (!strcmp(attr_names[n], "linesperpage")) { v->lpp = strtol(attr_values[n], NULL, 10); } if (!strcmp(attr_names[n], "charsperline")) { v->cpl = strtol(attr_values[n], NULL, 10); } if (!strcmp(attr_names[n], "tabsize")) { v->tabsize = strtol(attr_values[n], NULL, 10); } else if (!strcmp(attr_names[n], "nonprtfmt")) { v->nonprtfmt = xfprint_option( non_printable_fmts, attr_values[n]); } } else if (!strcmp(element_name, "pprint")) { if (!strcmp(attr_names[n], "highlight")) { p->highlight = xfprint_option(hilevels, attr_values[n]); } else if (!strcmp(attr_names[n], "strip")) { p->strip = strtol(attr_values[n], NULL, 10); } } else if (!strcmp(element_name, "input")) { if (!strcmp(attr_names[n], "encoding")) { i->encoding = xfprint_option(encodings, attr_values[n]); } else if (!strcmp(attr_names[n], "cut")) { i->cut = !strcmp(attr_values[n], "true"); } else if (!strcmp(attr_names[n], "interpret")) { i->interpret = !strcmp(attr_values[n], "true"); } else if (!strcmp(attr_names[n], "binary")) { i->binary = !strcmp(attr_values[n], "true"); } } else if (!strcmp(element_name, "headings")) { if (!strcmp(attr_names[n], "headers")) { h->headers = !strcmp(attr_values[n], "true"); } else if (!strcmp(attr_names[n], "header")) { strlcpy(h->header, attr_values[n], sizeof(h->header)); } else if (!strcmp(attr_names[n], "underlay")) { strlcpy(h->underlay, attr_values[n], sizeof(h->underlay)); } else if (!strcmp(attr_names[n], "ctitle")) { strlcpy(h->ctitle, attr_values[n], sizeof(h->ctitle)); } else if (!strcmp(attr_names[n], "ltitle")) { strlcpy(h->ltitle, attr_values[n], sizeof(h->ltitle)); } else if (!strcmp(attr_names[n], "rtitle")) { strlcpy(h->rtitle, attr_values[n], sizeof(h->rtitle)); } else if (!strcmp(attr_names[n], "cfooter")) { strlcpy(h->cfooter, attr_values[n], sizeof(h->cfooter)); } else if (!strcmp(attr_names[n], "lfooter")) { strlcpy(h->lfooter, attr_values[n], sizeof(h->lfooter)); } else if (!strcmp(attr_names[n], "rfooter")) { strlcpy(h->rfooter, attr_values[n], sizeof(h->rfooter)); } } } break; default: g_warning("start unknown element \"%s\"", element_name); break; } } static void end_element_handler(GMarkupParseContext *ctx, const gchar *element_name, gpointer user_data, GError **error) { SettingsParser *parser; parser = (SettingsParser *)user_data; switch (parser->state) { case START: /* XXX - this shouldn't happen */ break; case PRINTSETTINGS: if (!strcmp(element_name, "printsettings")) parser->state = START; break; default: g_warning("end unknown element \"%s\"", element_name); break; } } static void error_handler(GMarkupParseContext *ctx, GError *error, gpointer user_data) { if (error && error->message) g_warning(" %s", error->message); } static GMarkupParser markup_parser = { start_element_handler, end_element_handler, NULL, NULL, error_handler }; static void load_settings_from_file(const gchar *filename, XfprintSettings *settings) { GMarkupParseContext *ctx; SettingsParser parser; gchar *contents; GError *error; struct stat sb; #ifdef HAVE_MMAP void *addr; #endif int fd; error = NULL; parser.settings = settings; parser.state = START; #ifdef O_SHLOCK if ((fd = open(filename, O_RDONLY | O_SHLOCK, 0)) < 0) #else if ((fd = open(filename, O_RDONLY, 0)) < 0) #endif return; if (fstat(fd, &sb) < 0) goto finished; #ifdef HAVE_MMAP /* Try to mmap(2) the config file, as this save us a lot of * kernelspace -> userspace copying */ #ifdef MAP_FILE addr = mmap(NULL, sb.st_size, PROT_READ, MAP_FILE | MAP_SHARED, fd, 0); #else addr = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0); #endif if (addr != NULL) { /* nice, mmap did the job */ contents = addr; } else { #endif if ((contents = malloc(sb.st_size * sizeof(gchar))) == NULL) goto finished; /* read(2): * -------- * The system guarantees to read the number of bytes requested * if the descriptor references a normal file that has that * many bytes left before the end-of-file. */ if (read(fd, contents, sb.st_size) < sb.st_size) goto finished2; #ifdef HAVE_MMAP } #endif ctx = g_markup_parse_context_new(&markup_parser, 0, &parser, NULL); if (!g_markup_parse_context_parse(ctx, contents, sb.st_size, &error)) { g_print(error->message); goto finished3; } if (!g_markup_parse_context_end_parse(ctx, NULL)) goto finished3; finished3: g_markup_parse_context_free(ctx); finished2: #ifdef HAVE_MMAP if (addr != NULL) munmap(addr, sb.st_size); else #endif free(contents); finished: (void)close(fd); } static void save_settings_to_file(const gchar *filename, const XfprintSettings *settings) { FILE *fp; int fd; #ifdef O_EXLOCK if ((fd = open(filename, O_CREAT|O_EXLOCK|O_TRUNC|O_WRONLY, S_IRUSR | S_IWUSR))< 0) #else if ((fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR)) < 0) #endif return; if ((fp = fdopen(fd, "w")) == NULL) { (void)close(fd); return; } fprintf(fp, "\n" "\n" "\n"); fprintf(fp, "\n"); fprintf(fp, "\t\n", settings->sheets.landscape ? "landscape" : "portrait", settings->sheets.fillcols ? "cols" : "rows", settings->sheets.cols, settings->sheets.rows, settings->sheets.papersize, settings->sheets.borders ? "true" : "false", settings->sheets.reverse ? "true" : "false"); fprintf(fp, "\tvpages.linenumbers > 0) fprintf(fp, "linenumbers=\"%d\" ",settings->vpages.linenumbers); if (settings->vpages.lpp > 0) fprintf(fp, "linesperpage=\"%d\" ", settings->vpages.lpp); if (settings->vpages.cpl > 0) fprintf(fp, "charsperline=\"%d\" ", settings->vpages.cpl); fprintf(fp, "tabsize=\"%d\" nonprtfmt=\"%s\" />\n", settings->vpages.tabsize, settings->vpages.nonprtfmt); fprintf(fp, "\t\n", settings->pprint.highlight, settings->pprint.strip); fprintf(fp, "\t\n", settings->input.encoding, settings->input.cut ? "true" : "false", settings->input.interpret ? "true" : "false", settings->input.binary ? "true" : "false"); fprintf(fp, "\t\n", settings->headings.headers ? "true" : "false", settings->headings.header, settings->headings.underlay, settings->headings.ctitle, settings->headings.ltitle, settings->headings.rtitle, settings->headings.cfooter, settings->headings.lfooter, settings->headings.rfooter); fprintf(fp, "\n"); (void)fflush(fp); (void)fclose(fp); }