#include "ppd.h"
#include <stdlib.h>
#include "string.h"
#if defined(WIN32) || defined(__EMX__)
# include <io.h>
#else
# include <unistd.h>
#endif
static void ppd_handle_media(ppd_file_t *ppd);
static int ppd_sort(ppd_choice_t **c1, ppd_choice_t **c2);
static const char *ppd_custom_code =
"pop pop pop\n"
"<</PageSize[5 -2 roll]/ImagingBBox null>>setpagedevice\n";
int
ppdCollect(ppd_file_t *ppd,
ppd_section_t section,
ppd_choice_t ***choices)
{
int i, j, k, m;
ppd_group_t *g,
*sg;
ppd_option_t *o;
ppd_choice_t *c;
int count;
ppd_choice_t **collect;
if (ppd == NULL)
return (0);
count = 0;
collect = calloc(sizeof(ppd_choice_t *), 1000);
for (i = ppd->num_groups, g = ppd->groups; i > 0; i --, g ++)
{
for (j = g->num_options, o = g->options; j > 0; j --, o ++)
if (o->section == section)
for (k = o->num_choices, c = o->choices; k > 0; k --, c ++)
if (c->marked && count < 1000)
{
collect[count] = c;
count ++;
}
for (j = g->num_subgroups, sg = g->subgroups; j > 0; j --, sg ++)
for (k = sg->num_options, o = sg->options; k > 0; k --, o ++)
if (o->section == section)
for (m = o->num_choices, c = o->choices; m > 0; m --, c ++)
if (c->marked && count < 1000)
{
collect[count] = c;
count ++;
}
}
if (count > 1)
qsort(collect, count, sizeof(ppd_choice_t *),
(int (*)(const void *, const void *))ppd_sort);
if (count > 0)
{
*choices = collect;
return (count);
}
else
{
*choices = NULL;
free(collect);
return (0);
}
}
int
ppdEmit(ppd_file_t *ppd,
FILE *fp,
ppd_section_t section)
{
return ppdEmitAfterOrder(ppd, fp, section, 0, 0); }
int
ppdEmitAfterOrder(ppd_file_t *ppd,
FILE *fp,
ppd_section_t section,
int limitOrder,
float minOrder)
{
int i,
count;
ppd_choice_t **choices;
ppd_size_t *size;
ppd_handle_media(ppd);
if ((count = ppdCollect(ppd, section, &choices)) == 0)
return (0);
for (i = 0; i < count; i ++)
if (section != PPD_ORDER_EXIT && section != PPD_ORDER_JCL)
{
if( !limitOrder || ( (ppd_option_t *)choices[i]->option)->order >= minOrder)
{
if (fputs("[{\n", fp) < 0)
{
free(choices);
return (-1);
}
if ((strcasecmp(((ppd_option_t *)choices[i]->option)->keyword, "PageSize") == 0 ||
strcasecmp(((ppd_option_t *)choices[i]->option)->keyword, "PageRegion") == 0) &&
strcasecmp(choices[i]->choice, "Custom") == 0)
{
ppd_attr_t *attr;
int j, pos;
int isfloat[5];
float values[5];
float orientation;
fputs("%%BeginFeature: *CustomPageSize True\n", fp);
size = ppdPageSize(ppd, "Custom");
memset(values, 0, sizeof(values));
memset(isfloat, 0, sizeof(isfloat));
if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize", "Width")) != NULL)
{
pos = atoi(attr->value) - 1;
if (pos < 0 || pos > 4)
pos = 0;
}
else
pos = 0;
values[pos] = size->width;
isfloat[pos] = 1;
if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize", "Height")) != NULL)
{
pos = atoi(attr->value) - 1;
if (pos < 0 || pos > 4)
pos = 1;
}
else
pos = 1;
values[pos] = size->length;
isfloat[pos] = 1;
if (size->width < size->length)
orientation = 1;
else
orientation = 0;
if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize",
"Orientation")) != NULL)
{
int min_orient, max_orient;
if (sscanf(attr->value, "%d%*s%d%d", &pos, &min_orient,
&max_orient) != 3)
pos = 4;
else
{
pos = pos - 1;
if (pos < 0 || pos > 4)
pos = 4;
if (orientation > max_orient)
orientation = max_orient;
else if (orientation < min_orient)
orientation = min_orient;
}
}
else
pos = 4;
values[pos] = orientation;
for(j = 0; j < 5 ; j++ ){
if(isfloat[j])
fprintf(fp, "%.2f ", values[j]);
else
fprintf(fp, "%d ", (int)values[j]);
}
fprintf(fp, "\n");
if (choices[i]->code == NULL)
{
fputs(ppd_custom_code, fp);
}
}
else if (fprintf(fp, "%%%%BeginFeature: *%s %s\n",
((ppd_option_t *)choices[i]->option)->keyword,
choices[i]->choice) < 0)
{
free(choices);
return (-1);
}
if (choices[i]->code != NULL && choices[i]->code[0] != '\0')
{
if (fputs(choices[i]->code, fp) < 0)
{
free(choices);
return (-1);
}
if (choices[i]->code[strlen(choices[i]->code) - 1] != '\n')
putc('\n', fp);
}
if (fputs("%%EndFeature\n", fp) < 0)
{
free(choices);
return (-1);
}
if (fputs("} stopped cleartomark\n", fp) < 0)
{
free(choices);
return (-1);
}
}
}
else if (fputs(choices[i]->code, fp) < 0)
{
free(choices);
return (-1);
}
free(choices);
return (0);
}
int
ppdEmitFd(ppd_file_t *ppd,
int fd,
ppd_section_t section)
{
int i,
count,
custom_size;
ppd_choice_t **choices;
ppd_size_t *size;
char buf[1024];
ppd_handle_media(ppd);
if ((count = ppdCollect(ppd, section, &choices)) == 0)
return (0);
for (i = 0; i < count; i ++)
if (section != PPD_ORDER_EXIT && section != PPD_ORDER_JCL)
{
if (write(fd, "[{\n", 3) < 1)
{
free(choices);
return (-1);
}
if ((strcasecmp(((ppd_option_t *)choices[i]->option)->keyword, "PageSize") == 0 ||
strcasecmp(((ppd_option_t *)choices[i]->option)->keyword, "PageRegion") == 0) &&
strcasecmp(choices[i]->choice, "Custom") == 0)
{
custom_size = 1;
strcpy(buf, "%%BeginFeature: *CustomPageSize True\n");
}
else
{
custom_size = 0;
snprintf(buf, sizeof(buf), "%%%%BeginFeature: *%s %s\n",
((ppd_option_t *)choices[i]->option)->keyword,
choices[i]->choice);
}
if (write(fd, buf, strlen(buf)) < 1)
{
free(choices);
return (-1);
}
if (custom_size)
{
ppd_attr_t *attr;
int pos,
values[5],
orientation;
size = ppdPageSize(ppd, "Custom");
memset(values, 0, sizeof(values));
if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize", "Width")) != NULL)
{
pos = atoi(attr->value) - 1;
if (pos < 0 || pos > 4)
pos = 0;
}
else
pos = 0;
values[pos] = (int)size->width;
if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize", "Height")) != NULL)
{
pos = atoi(attr->value) - 1;
if (pos < 0 || pos > 4)
pos = 1;
}
else
pos = 1;
values[pos] = (int)size->length;
if (size->width < size->length)
orientation = 1;
else
orientation = 0;
if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize",
"Orientation")) != NULL)
{
int min_orient, max_orient;
if (sscanf(attr->value, "%d%*s%d%d", &pos, &min_orient,
&max_orient) != 3)
pos = 4;
else
{
pos = pos - 1;
if (pos < 0 || pos > 4)
pos = 4;
if (orientation > max_orient)
orientation = max_orient;
else if (orientation < min_orient)
orientation = min_orient;
}
}
else
pos = 4;
values[pos] = orientation;
snprintf(buf, sizeof(buf), "%d %d %d %d %d\n", values[0], values[1],
values[2], values[3], values[4]);
if (write(fd, buf, strlen(buf)) < 1)
{
free(choices);
return (-1);
}
if (choices[i]->code == NULL)
{
if (write(fd, ppd_custom_code, strlen(ppd_custom_code)) < 1)
{
free(choices);
return (-1);
}
}
}
if (choices[i]->code != NULL && choices[i]->code[0] != '\0')
{
if (write(fd, choices[i]->code, strlen(choices[i]->code)) < 1)
{
free(choices);
return (-1);
}
}
if (write(fd, "%%EndFeature\n", 13) < 1)
{
free(choices);
return (-1);
}
if (write(fd, "} stopped cleartomark\n", 22) < 1)
{
free(choices);
return (-1);
}
}
else if (write(fd, choices[i]->code, strlen(choices[i]->code)) < 1)
{
free(choices);
return (-1);
}
free(choices);
return (0);
}
int
ppdEmitJCL(ppd_file_t *ppd,
FILE *fp,
int job_id,
const char *user,
const char *title)
{
char *ptr;
char temp[81];
if (ppd == NULL || ppd->jcl_begin == NULL || ppd->jcl_ps == NULL)
return (0);
if (strncmp(ppd->jcl_begin, "\033%-12345X@", 10) == 0)
{
fputs("\033%-12345X@PJL\n", fp);
for (ptr = ppd->jcl_begin + 9; *ptr;)
if (strncmp(ptr, "@PJL JOB", 8) == 0)
{
for (;*ptr; ptr ++)
if (*ptr == '\n')
break;
if (*ptr)
ptr ++;
}
else
{
for (;*ptr; ptr ++)
{
putc(*ptr, fp);
if (*ptr == '\n')
break;
}
if (*ptr)
ptr ++;
}
if ((ptr = strrchr(title, '/')) != NULL)
title = ptr + 1;
strlcpy(temp, title, sizeof(temp));
for (ptr = temp; *ptr; ptr ++)
if (*ptr == '\"')
*ptr = '\'';
fprintf(fp, "@PJL JOB NAME = \"%s\" DISPLAY = \"%d %s %s\"\n", temp,
job_id, user, temp);
}
else
fputs(ppd->jcl_begin, fp);
ppdEmit(ppd, fp, PPD_ORDER_JCL);
fputs(ppd->jcl_ps, fp);
return (0);
}
static void
ppd_handle_media(ppd_file_t *ppd)
{
ppd_choice_t *manual_feed,
*input_slot,
*page;
ppd_size_t *size;
ppd_attr_t *rpr;
if ((size = ppdPageSize(ppd, NULL)) == NULL)
return;
manual_feed = ppdFindMarkedChoice(ppd, "ManualFeed");
input_slot = ppdFindMarkedChoice(ppd, "InputSlot");
if (input_slot != NULL)
rpr = ppdFindAttr(ppd, "RequiresPageRegion", input_slot->choice);
else
rpr = NULL;
if (!rpr)
rpr = ppdFindAttr(ppd, "RequiresPageRegion", "All");
if (strcasecmp(size->name, "Custom") == 0 ||
(manual_feed == NULL && input_slot == NULL) ||
!(
(manual_feed != NULL && strcasecmp(manual_feed->choice, "True") == 0) ||
(input_slot != NULL && input_slot->code != NULL && input_slot->code[0]))
)
{
ppdMarkOption(ppd, "PageSize", size->name);
}
else
{
ppdMarkOption(ppd, "PageRegion", size->name);
if ( !(manual_feed != NULL && strcasecmp(manual_feed->choice, "True") == 0) &&
( (rpr && rpr->value && !strcmp(rpr->value, "False")) ||
(!rpr && !ppd->num_filters) )
)
{
page = ppdFindMarkedChoice(ppd, "PageRegion");
if (page)
page->marked = 0;
}
}
}
static int
ppd_sort(ppd_choice_t **c1,
ppd_choice_t **c2)
{
if (((ppd_option_t *)(*c1)->option)->order < ((ppd_option_t *)(*c2)->option)->order)
return (-1);
else if (((ppd_option_t *)(*c1)->option)->order > ((ppd_option_t *)(*c2)->option)->order)
return (1);
else
return (0);
}