/* * emit.c: PPD code emission routines. * * This library 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 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 * General Public License for more details. * * You should have received a copy of the GNU 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. * * * See the AUTHORS file for a list of people who have hacked on * this code. * See the ChangeLog file for a list of changes. * * Contents: * * ppd_emit_to_file() - Emit code for marked options to a file. * ppd_emit_to_fd() - Emit code for marked options to a file. * * OLD Contents: * * ppdEmit() - Emit code for marked options to a file. * ppdEmitFd() - Emit code for marked options to a file. */ /* * Include necessary headers... */ #include "ppd.h" #include #include #include /* Local functions... */ static guint ppd_collect(PpdFile * ppd, PpdSectionOrder section, GSList ** choices); static gint ppd_sort(gconstpointer c1, gconstpointer c2); /* ppd_emit_to_file() - Emit code for marked options to a file. */ gboolean ppd_emit_to_file(PpdFile * ppd, FILE * fp, PpdSectionOrder section) { guint count; /* Number of choices */ GSList *choices; /* Choices */ GSList *list; /* List iterator */ PpdSize *size; /* Custom page size */ PpdOption *o, *otmp; PpdChoice *choice; if ((count = ppd_collect(ppd, section, &choices)) == 0) return (TRUE); list = choices; while (list) { // for (i = 0; i < count; i++) { choice = PPD_CHOICE(list->data); o = PPD_OPTION(choice->option); if (o->keyword == NULL) return (FALSE); /* error */ if (section != PPD_ORDER_EXIT && section != PPD_ORDER_JCL) { /* * Send DSC comments with option... */ otmp = PPD_OPTION(choice->option); if (fprintf (fp, "%%%%BeginFeature: %s %s\n", otmp->keyword->str, choice->choice->str) < 0) { g_slist_free(choices); return (FALSE); } if (g_strcasecmp(o->keyword->str, "PageSize") == 0 && g_strcasecmp(choice->choice->str, "Custom") == 0) { /* * Variable size; write out standard size options (this should * eventually be changed to use the parameter positions defined * in the PPD file...) */ size = ppd_get_page_size(ppd, "Custom"); fprintf(fp, "%.0f %.0f 0 0 0\n", size->width, size->length); if (choice->code == NULL) { /* * This can happen with certain buggy PPD files that don't include * a CustomPageSize command sequence... We just use a generic * Level 2 command sequence... */ fputs("pop pop pop\n", fp); fputs("<>setpagedevice\n", fp); } } /* if (g_strcasecmp...) */ if (choice->code != NULL && choice->code[0] != '\0') { if (fputs(choice->code, fp) < 0) { g_slist_free(choices); return (FALSE); } if (choice->code[strlen(choice->code) - 1] != '\n') putc('\n', fp); } if (fputs("%%EndFeature\n", fp) < 0) { g_slist_free(choices); return (FALSE); } } /* if (section != ...) */ else if (fputs(choice->code, fp) < 0) { g_slist_free(choices); return (FALSE); } /* * Mark the option as already emitted */ o->emitted = TRUE; list = g_slist_next(list); } /* while */ g_slist_free(choices); return (TRUE); } /* * 'ppd_emit_to_fd()' - Emit code for marked options to a file descriptor. */ gboolean ppd_emit_to_fd(PpdFile * ppd, int fd, PpdSectionOrder section) { guint count; /* Number of choices */ GSList *choices, /* Choices */ *list; /* List iterator var */ char buf[1024]; /* Output buffer for feature */ PpdOption *o; /* Current PpdOption */ PpdChoice *choice; /* Current PpdChoice */ if ((count = ppd_collect(ppd, section, &choices)) == 0) return (TRUE); list = choices; while (list) { // for (i = 0; i < count; i++) { choice = PPD_CHOICE(list->data); o = choice->option; if (section != PPD_ORDER_EXIT && section != PPD_ORDER_JCL) { /* * Send DSC comments with option... */ sprintf(buf, "%%%%BeginFeature: %s %s\n", o->keyword->str, choice->choice->str); if (write(fd, buf, strlen(buf)) < 1) { g_slist_free(choices); return (FALSE); } if (write(fd, choice->code, strlen(choice->code)) < 1) { g_slist_free(choices); return (FALSE); } if (write(fd, "%%EndFeature\n", 13) < 1) { g_slist_free(choices); return (FALSE); } } /* if (section != ...) */ else if (write(fd, choice->code, strlen(choice->code)) < 1) { g_slist_free(choices); return (FALSE); } /* * Mark the option as already emitted */ o->emitted = TRUE; list = g_slist_next(list); } /* while (list) */ g_slist_free(choices); return (TRUE); } /* * 'ppd_sort()' - Sort options by ordering numbers... */ /* return O - -1 if c1 < c2, 0 if equal, 1 otherwise */ /* c1 -- I - First choice */ static gint ppd_sort(gconstpointer c1, gconstpointer c2) { PpdOption *o1, *o2; PpdChoice *tc1, *tc2; tc1 = PPD_CHOICE(c1); tc2 = PPD_CHOICE(c2); o1 = tc1->option; o2 = tc2->option; /* I - Second choice */ if (o1->order < o2->order) return (-1); else if (o1->order > o2->order) return (1); else return (0); } /* 'ppd_collect()' - Collect all marked options that reside in the * specified section. */ /* O - Number of options marked */ /* ppd -- PPD File Data */ /* section -- Section to collect */ /* choices -- Pointers to choices */ static guint ppd_collect(PpdFile * ppd, PpdSectionOrder section, GSList ** choices) { GSList *collect = NULL; /* Collected choices */ GSList *glist; /* Group list iterator */ PpdGroup *g; /* Current group */ PpdGroup *sg; /* Current sub-group */ PpdChoice *c; /* Current choice */ GSList *clist; /* Choice list iterator */ GSList *sglist; /* Sub Group list iterator */ if (ppd == NULL) return (0); /* Loop through all options and add choices as needed... */ for (glist = ppd->groups; glist; glist = g_slist_next(glist)) { GSList *olist; /* Option list iterator */ PpdOption *o; /* Current option */ for (olist = (g = PPD_GROUP(glist->data))->options; olist; olist = g_slist_next(olist)) { /* Check if this is the section we asked for. If we asked for * the Document and Page sections we also include the Any * section Unless it has already been emitted */ if ((o = PPD_OPTION(olist->data))->emitted == 0 && (o->section == section || (section == PPD_ORDER_DOCUMENT && o->section == PPD_ORDER_ANY) || (section == PPD_ORDER_PAGE && o->section == PPD_ORDER_ANY))) for (clist = o->choices; clist; clist = g_slist_next(clist)) if ((c = PPD_CHOICE(clist->data))->marked) collect = g_slist_append(collect, c); } /* for (olist) */ for (sglist = g->subgroups; sglist; sglist = g_slist_next(sglist)) for (olist = (sg = PPD_GROUP(sglist->data))->options; olist; olist = g_slist_next(olist)) /* Check if this is the section we asked for. If we asked * for the Document and Page sections we also include the Any * section Unless it has already been emitted */ if ((o = PPD_OPTION(olist->data))->emitted == 0 && (o->section == section || (section == PPD_ORDER_DOCUMENT && o->section == PPD_ORDER_ANY) || (section == PPD_ORDER_PAGE && o->section == PPD_ORDER_ANY))) for (clist = o->choices; clist; clist = g_slist_next(clist)) if ((c = PPD_CHOICE(clist->data))->marked) collect = g_slist_append(collect, c); } /* for (glist) */ /* If we have more than 1 marked choice, sort them... */ if (g_slist_length(collect) > 1) collect = g_slist_sort(collect, ppd_sort); /* Return the sorted GSList, and the number of choices in the list. */ *choices = collect; return (g_slist_length(*choices)); } /* End of emit.c */