]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/filter.c
Load cups into easysw/current.
[thirdparty/cups.git] / scheduler / filter.c
CommitLineData
ef416fc2 1/*
bd7854cb 2 * "$Id: filter.c 5083 2006-02-06 02:57:43Z mike $"
ef416fc2 3 *
4 * File type conversion routines for the Common UNIX Printing System (CUPS).
5 *
fa73b229 6 * Copyright 1997-2006 by Easy Software Products, all rights reserved.
ef416fc2 7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
19 *
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * Contents:
25 *
fa73b229 26 * mimeAddFilter() - Add a filter to the current MIME database.
bd7854cb 27 * mimeFilter() - Find the fastest way to convert from one type to
28 * another.
fa73b229 29 * compare_filters() - Compare two filters...
bd7854cb 30 * find_filters() - Find the filters to convert from one type to another.
fa73b229 31 * lookup() - Lookup a filter...
ef416fc2 32 */
33
34/*
35 * Include necessary headers...
36 */
37
38#include <stdio.h>
39#include <stdlib.h>
40#include <ctype.h>
41
42#include <cups/debug.h>
43#include <cups/string.h>
44#include "mime.h"
45
46
bd7854cb 47/*
48 * Local types...
49 */
50
51typedef struct _mime_typelist_s /**** List of source types ****/
52{
53 struct _mime_typelist_s *next; /* Next source type */
54 mime_type_t *src; /* Source type */
55} _mime_typelist_t;
56
57
ef416fc2 58/*
59 * Local functions...
60 */
61
fa73b229 62static int compare_filters(mime_filter_t *, mime_filter_t *);
bd7854cb 63static cups_array_t *find_filters(mime_t *mime, mime_type_t *src,
64 mime_type_t *dst, int *cost,
65 _mime_typelist_t *visited);
ef416fc2 66static mime_filter_t *lookup(mime_t *, mime_type_t *, mime_type_t *);
67
68
69/*
70 * 'mimeAddFilter()' - Add a filter to the current MIME database.
71 */
72
73mime_filter_t * /* O - New filter */
74mimeAddFilter(mime_t *mime, /* I - MIME database */
75 mime_type_t *src, /* I - Source type */
76 mime_type_t *dst, /* I - Destination type */
77 int cost, /* I - Relative time/resource cost */
78 const char *filter) /* I - Filter program to run */
79{
80 mime_filter_t *temp; /* New filter */
81
82
83 /*
84 * Range-check the input...
85 */
86
fa73b229 87 if (!mime || !src || !dst || !filter)
ef416fc2 88 return (NULL);
89
90 /*
91 * See if we already have an existing filter for the given source and
92 * destination...
93 */
94
95 if ((temp = lookup(mime, src, dst)) != NULL)
96 {
97 /*
98 * Yup, does the existing filter have a higher cost? If so, copy the
99 * filter and cost to the existing filter entry and return it...
100 */
101
102 if (temp->cost > cost)
103 {
104 temp->cost = cost;
105 strlcpy(temp->filter, filter, sizeof(temp->filter));
106 }
107 }
108 else
109 {
110 /*
111 * Nope, add a new one...
112 */
113
fa73b229 114 if (!mime->filters)
115 mime->filters = cupsArrayNew((cups_array_func_t)compare_filters, NULL);
ef416fc2 116
fa73b229 117 if (!mime->filters)
ef416fc2 118 return (NULL);
119
fa73b229 120 if ((temp = calloc(1, sizeof(mime_filter_t))) == NULL)
121 return (NULL);
ef416fc2 122
123 /*
124 * Copy the information over and sort if necessary...
125 */
126
127 temp->src = src;
128 temp->dst = dst;
129 temp->cost = cost;
130 strlcpy(temp->filter, filter, sizeof(temp->filter));
131
fa73b229 132 cupsArrayAdd(mime->filters, temp);
ef416fc2 133 }
134
135 /*
136 * Return the new/updated filter...
137 */
138
139 return (temp);
140}
141
142
143/*
144 * 'mimeFilter()' - Find the fastest way to convert from one type to another.
145 */
146
fa73b229 147cups_array_t * /* O - Array of filters to run */
ef416fc2 148mimeFilter(mime_t *mime, /* I - MIME database */
149 mime_type_t *src, /* I - Source file type */
150 mime_type_t *dst, /* I - Destination file type */
bd7854cb 151 int *cost) /* O - Cost of filters */
ef416fc2 152{
ef416fc2 153 /*
154 * Range-check the input...
155 */
156
fa73b229 157 DEBUG_printf(("mimeFilter(mime=%p, src=%p(%s/%s), dst=%p(%s/%s), "
bd7854cb 158 "cost=%p(%d))\n",
ef416fc2 159 mime, src, src ? src->super : "?", src ? src->type : "?",
160 dst, dst ? dst->super : "?", dst ? dst->type : "?",
bd7854cb 161 cost, cost ? *cost : 0));
162
ef416fc2 163
fa73b229 164 if (cost)
165 *cost = 0;
ef416fc2 166
bd7854cb 167 if (!mime || !src || !dst)
fa73b229 168 return (NULL);
ef416fc2 169
bd7854cb 170 /*
171 * Find the filters...
172 */
173
174 return (find_filters(mime, src, dst, cost, NULL));
175}
176
177
178/*
179 * 'compare_filters()' - Compare two filters...
180 */
181
182static int /* O - Comparison result */
183compare_filters(mime_filter_t *f0, /* I - First filter */
184 mime_filter_t *f1) /* I - Second filter */
185{
186 int i; /* Result of comparison */
187
188
189 if ((i = strcmp(f0->src->super, f1->src->super)) == 0)
190 if ((i = strcmp(f0->src->type, f1->src->type)) == 0)
191 if ((i = strcmp(f0->dst->super, f1->dst->super)) == 0)
192 i = strcmp(f0->dst->type, f1->dst->type);
193
194 return (i);
195}
196
197
198/*
199 * 'find_filters()' - Find the filters to convert from one type to another.
200 */
201
202cups_array_t * /* O - Array of filters to run */
203find_filters(mime_t *mime, /* I - MIME database */
204 mime_type_t *src, /* I - Source file type */
205 mime_type_t *dst, /* I - Destination file type */
206 int *cost, /* O - Cost of filters */
207 _mime_typelist_t *list) /* I - Source types we've used */
208{
209 int tempcost, /* Temporary cost */
210 mincost; /* Current minimum */
211 cups_array_t *temp, /* Temporary filter */
212 *mintemp; /* Current minimum */
213 mime_filter_t *current; /* Current filter */
214 _mime_typelist_t listnode, /* New list node */
215 *listptr; /* Pointer in list */
216
217
218 DEBUG_printf(("find_filters(mime=%p, src=%p(%s/%s), dst=%p(%s/%s), "
219 "cost=%p, list=%p)\n", mime, src, src->super, src->type,
220 dst, dst->super, dst->type, cost, list));
221
ef416fc2 222 /*
223 * See if there is a filter that can convert the files directly...
224 */
225
fa73b229 226 if ((current = lookup(mime, src, dst)) != NULL)
ef416fc2 227 {
228 /*
229 * Got a direct filter!
230 */
231
bd7854cb 232 DEBUG_puts("Direct filter found!");
233
fa73b229 234 if ((mintemp = cupsArrayNew(NULL, NULL)) == NULL)
ef416fc2 235 return (NULL);
236
fa73b229 237 cupsArrayAdd(mintemp, current);
238
239 mincost = current->cost;
ef416fc2 240
241 DEBUG_puts(" Found direct filter:");
bd7854cb 242 DEBUG_printf((" %s (cost=%d)\n", current->filter, mincost));
ef416fc2 243 }
244 else
245 {
246 /*
247 * No direct filter...
248 */
249
fa73b229 250 mintemp = NULL;
251 mincost = 9999999;
ef416fc2 252 }
253
bd7854cb 254 /*
255 * Initialize this node in the type list...
256 */
257
258 listnode.next = list;
259
ef416fc2 260 /*
261 * OK, now look for filters from the source type to any other type...
262 */
263
fa73b229 264 for (current = (mime_filter_t *)cupsArrayFirst(mime->filters);
265 current;
266 current = (mime_filter_t *)cupsArrayNext(mime->filters))
ef416fc2 267 if (current->src == src)
268 {
bd7854cb 269 /*
270 * See if we have already tried the destination type as a source
271 * type (this avoids extra filter looping...)
272 */
273
274 for (listptr = list; listptr; listptr = listptr->next)
275 if (current->dst == listptr->src)
276 break;
277
278 if (listptr)
279 continue;
280
ef416fc2 281 /*
282 * See if we have any filters that can convert from the destination type
283 * of this filter to the final type...
284 */
285
bd7854cb 286 listnode.src = current->src;
287
fa73b229 288 cupsArraySave(mime->filters);
bd7854cb 289 temp = find_filters(mime, current->dst, dst, &tempcost, &listnode);
fa73b229 290 cupsArrayRestore(mime->filters);
291
292 if (!temp)
ef416fc2 293 continue;
294
295 /*
296 * Found a match; see if this one is less costly than the last (if
297 * any...)
298 */
299
fa73b229 300 if (tempcost < mincost)
ef416fc2 301 {
fa73b229 302 cupsArrayDelete(mintemp);
ef416fc2 303
304 /*
305 * Hey, we got a match! Add the current filter to the beginning of the
306 * filter list...
307 */
308
fa73b229 309 mintemp = temp;
310 mincost = tempcost + current->cost;
311 cupsArrayInsert(mintemp, current);
ef416fc2 312 }
313 else
fa73b229 314 cupsArrayDelete(temp);
ef416fc2 315 }
316
fa73b229 317 if (mintemp)
ef416fc2 318 {
319 /*
320 * Hey, we got a match!
321 */
322
ef416fc2 323#ifdef DEBUG
fa73b229 324 printf(" Returning %d filters:\n", cupsArrayCount(mintemp));
325 for (current = (mime_filter_t *)cupsArrayFirst(mintemp);
326 current;
327 current = (mime_filter_t *)cupsArrayNext(mintemp))
328 printf(" %s\n", current->filter);
ef416fc2 329#endif /* DEBUG */
330
bd7854cb 331 if (cost)
332 *cost = mincost;
fa73b229 333
ef416fc2 334 return (mintemp);
335 }
336
337 DEBUG_puts(" Returning zippo...");
338
339 return (NULL);
340}
341
342
ef416fc2 343/*
344 * 'lookup()' - Lookup a filter...
345 */
346
fa73b229 347static mime_filter_t * /* O - Filter for src->dst */
348lookup(mime_t *mime, /* I - MIME database */
349 mime_type_t *src, /* I - Source type */
350 mime_type_t *dst) /* I - Destination type */
ef416fc2 351{
fa73b229 352 mime_filter_t key; /* Key record for filter search */
ef416fc2 353
354
ef416fc2 355 key.src = src;
356 key.dst = dst;
357
fa73b229 358 return ((mime_filter_t *)cupsArrayFind(mime->filters, &key));
ef416fc2 359}
360
361
362/*
bd7854cb 363 * End of "$Id: filter.c 5083 2006-02-06 02:57:43Z mike $".
ef416fc2 364 */