]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/filter.c
Revise the network printer help page with documentation on the supported
[thirdparty/cups.git] / scheduler / filter.c
CommitLineData
79df52e3 1/*
c9d3f842 2 * "$Id$"
79df52e3 3 *
0b74af7d 4 * File type conversion routines for the Common UNIX Printing System (CUPS).
79df52e3 5 *
0557217b 6 * Copyright 1997-2006 by Easy Software Products, all rights reserved.
79df52e3 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
8784b6a6 17 * 44141 Airport View Drive, Suite 204
8650fcf2 18 * Hollywood, Maryland 20636 USA
79df52e3 19 *
edfd3c3d 20 * Voice: (301) 373-9600
79df52e3 21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * Contents:
25 *
0557217b 26 * mimeAddFilter() - Add a filter to the current MIME database.
238ad980 27 * mimeFilter() - Find the fastest way to convert from one type to
28 * another.
0557217b 29 * compare_filters() - Compare two filters...
238ad980 30 * find_filters() - Find the filters to convert from one type to another.
0557217b 31 * lookup() - Lookup a filter...
79df52e3 32 */
33
34/*
35 * Include necessary headers...
36 */
37
3b960317 38#include <stdio.h>
39#include <stdlib.h>
40#include <ctype.h>
41
c5488f2f 42#include <cups/debug.h>
68edc300 43#include <cups/string.h>
0b74af7d 44#include "mime.h"
45
46
238ad980 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
0b74af7d 58/*
59 * Local functions...
60 */
61
0557217b 62static int compare_filters(mime_filter_t *, mime_filter_t *);
9acc1468 63static int compare_srcs(mime_filter_t *, mime_filter_t *);
238ad980 64static cups_array_t *find_filters(mime_t *mime, mime_type_t *src,
65 mime_type_t *dst, int *cost,
66 _mime_typelist_t *visited);
0b74af7d 67static mime_filter_t *lookup(mime_t *, mime_type_t *, mime_type_t *);
68
69
70/*
71 * 'mimeAddFilter()' - Add a filter to the current MIME database.
72 */
73
74mime_filter_t * /* O - New filter */
75mimeAddFilter(mime_t *mime, /* I - MIME database */
76 mime_type_t *src, /* I - Source type */
77 mime_type_t *dst, /* I - Destination type */
78 int cost, /* I - Relative time/resource cost */
063e1ac7 79 const char *filter) /* I - Filter program to run */
0b74af7d 80{
81 mime_filter_t *temp; /* New filter */
82
83
84 /*
85 * Range-check the input...
86 */
87
0557217b 88 if (!mime || !src || !dst || !filter)
0b74af7d 89 return (NULL);
90
91 /*
92 * See if we already have an existing filter for the given source and
93 * destination...
94 */
95
96 if ((temp = lookup(mime, src, dst)) != NULL)
97 {
98 /*
99 * Yup, does the existing filter have a higher cost? If so, copy the
100 * filter and cost to the existing filter entry and return it...
101 */
102
103 if (temp->cost > cost)
104 {
105 temp->cost = cost;
def978d5 106 strlcpy(temp->filter, filter, sizeof(temp->filter));
e8fda7b9 107 }
0b74af7d 108 }
109 else
110 {
111 /*
112 * Nope, add a new one...
113 */
114
0557217b 115 if (!mime->filters)
116 mime->filters = cupsArrayNew((cups_array_func_t)compare_filters, NULL);
0b74af7d 117
48b71928 118 if (!mime->filters)
0b74af7d 119 return (NULL);
120
0557217b 121 if ((temp = calloc(1, sizeof(mime_filter_t))) == NULL)
122 return (NULL);
0b74af7d 123
124 /*
125 * Copy the information over and sort if necessary...
126 */
127
128 temp->src = src;
129 temp->dst = dst;
130 temp->cost = cost;
def978d5 131 strlcpy(temp->filter, filter, sizeof(temp->filter));
0b74af7d 132
0557217b 133 cupsArrayAdd(mime->filters, temp);
e8fda7b9 134 }
0b74af7d 135
136 /*
137 * Return the new/updated filter...
138 */
139
140 return (temp);
141}
142
143
144/*
145 * 'mimeFilter()' - Find the fastest way to convert from one type to another.
0b74af7d 146 */
147
0557217b 148cups_array_t * /* O - Array of filters to run */
0b74af7d 149mimeFilter(mime_t *mime, /* I - MIME database */
150 mime_type_t *src, /* I - Source file type */
151 mime_type_t *dst, /* I - Destination file type */
238ad980 152 int *cost) /* O - Cost of filters */
0b74af7d 153{
0b74af7d 154 /*
155 * Range-check the input...
156 */
157
0557217b 158 DEBUG_printf(("mimeFilter(mime=%p, src=%p(%s/%s), dst=%p(%s/%s), "
238ad980 159 "cost=%p(%d))\n",
c5488f2f 160 mime, src, src ? src->super : "?", src ? src->type : "?",
161 dst, dst ? dst->super : "?", dst ? dst->type : "?",
238ad980 162 cost, cost ? *cost : 0));
163
c5488f2f 164
0557217b 165 if (cost)
166 *cost = 0;
0b74af7d 167
d318937f 168 if (!mime || !src || !dst)
0557217b 169 return (NULL);
0b74af7d 170
48b71928 171 /*
172 * (Re)build the source lookup array as needed...
173 */
174
175 if (!mime->srcs)
176 {
177 mime_filter_t *current; /* Current filter */
178
179
180 mime->srcs = cupsArrayNew((cups_array_func_t)compare_srcs, NULL);
181
182 for (current = mimeFirstFilter(mime);
183 current;
184 current = mimeNextFilter(mime))
185 cupsArrayAdd(mime->srcs, current);
186 }
187
238ad980 188 /*
189 * Find the filters...
190 */
191
192 return (find_filters(mime, src, dst, cost, NULL));
193}
194
195
196/*
197 * 'compare_filters()' - Compare two filters...
198 */
199
200static int /* O - Comparison result */
201compare_filters(mime_filter_t *f0, /* I - First filter */
202 mime_filter_t *f1) /* I - Second filter */
203{
204 int i; /* Result of comparison */
205
206
207 if ((i = strcmp(f0->src->super, f1->src->super)) == 0)
208 if ((i = strcmp(f0->src->type, f1->src->type)) == 0)
209 if ((i = strcmp(f0->dst->super, f1->dst->super)) == 0)
210 i = strcmp(f0->dst->type, f1->dst->type);
211
212 return (i);
213}
214
215
9acc1468 216/*
217 * 'compare_srcs()' - Compare two srcs...
218 */
219
220static int /* O - Comparison result */
221compare_srcs(mime_filter_t *f0, /* I - First filter */
222 mime_filter_t *f1) /* I - Second filter */
223{
224 int i; /* Result of comparison */
225
226
227 if ((i = strcmp(f0->src->super, f1->src->super)) == 0)
228 i = strcmp(f0->src->type, f1->src->type);
229
230 return (i);
231}
232
233
238ad980 234/*
235 * 'find_filters()' - Find the filters to convert from one type to another.
236 */
237
95c68078 238static cups_array_t * /* O - Array of filters to run */
238ad980 239find_filters(mime_t *mime, /* I - MIME database */
240 mime_type_t *src, /* I - Source file type */
241 mime_type_t *dst, /* I - Destination file type */
242 int *cost, /* O - Cost of filters */
243 _mime_typelist_t *list) /* I - Source types we've used */
244{
245 int tempcost, /* Temporary cost */
246 mincost; /* Current minimum */
247 cups_array_t *temp, /* Temporary filter */
248 *mintemp; /* Current minimum */
9acc1468 249 mime_filter_t *current, /* Current filter */
250 srckey; /* Source type key */
238ad980 251 _mime_typelist_t listnode, /* New list node */
252 *listptr; /* Pointer in list */
253
254
d318937f 255 DEBUG_printf(("find_filters(mime=%p, src=%p(%s/%s), dst=%p(%s/%s), "
256 "cost=%p, list=%p)\n", mime, src, src->super, src->type,
257 dst, dst->super, dst->type, cost, list));
258
0b74af7d 259 /*
260 * See if there is a filter that can convert the files directly...
261 */
262
0557217b 263 if ((current = lookup(mime, src, dst)) != NULL)
0b74af7d 264 {
265 /*
266 * Got a direct filter!
267 */
268
d318937f 269 DEBUG_puts("Direct filter found!");
270
0557217b 271 if ((mintemp = cupsArrayNew(NULL, NULL)) == NULL)
0b74af7d 272 return (NULL);
273
0557217b 274 cupsArrayAdd(mintemp, current);
275
276 mincost = current->cost;
c5488f2f 277
9acc1468 278 if (!cost)
279 return (mintemp);
280
767ae392 281 DEBUG_puts(" Found direct filter:");
d318937f 282 DEBUG_printf((" %s (cost=%d)\n", current->filter, mincost));
767ae392 283 }
284 else
285 {
286 /*
287 * No direct filter...
288 */
c5488f2f 289
0557217b 290 mintemp = NULL;
291 mincost = 9999999;
e8fda7b9 292 }
0b74af7d 293
238ad980 294 /*
295 * Initialize this node in the type list...
296 */
297
298 listnode.next = list;
299
0b74af7d 300 /*
301 * OK, now look for filters from the source type to any other type...
302 */
303
9acc1468 304 srckey.src = src;
238ad980 305
9acc1468 306 for (current = (mime_filter_t *)cupsArrayFind(mime->srcs, &srckey);
307 current && current->src == src;
308 current = (mime_filter_t *)cupsArrayNext(mime->srcs))
309 {
310 /*
311 * See if we have already tried the destination type as a source
312 * type (this avoids extra filter looping...)
313 */
238ad980 314
9acc1468 315 mime_type_t *current_dst; /* Current destination type */
238ad980 316
0b74af7d 317
9acc1468 318 for (listptr = list, current_dst = current->dst;
319 listptr;
320 listptr = listptr->next)
321 if (current_dst == listptr->src)
322 break;
323
324 if (listptr)
325 continue;
326
327 /*
328 * See if we have any filters that can convert from the destination type
329 * of this filter to the final type...
330 */
331
332 listnode.src = current->src;
333
334 cupsArraySave(mime->srcs);
335 temp = find_filters(mime, current->dst, dst, &tempcost, &listnode);
336 cupsArrayRestore(mime->srcs);
238ad980 337
9acc1468 338 if (!temp)
339 continue;
0557217b 340
9acc1468 341 if (!cost)
342 return (temp);
343
344 /*
345 * Found a match; see if this one is less costly than the last (if
346 * any...)
347 */
348
5adebf48 349 tempcost += current->cost;
350
9acc1468 351 if (tempcost < mincost)
352 {
353 cupsArrayDelete(mintemp);
0b74af7d 354
355 /*
9acc1468 356 * Hey, we got a match! Add the current filter to the beginning of the
357 * filter list...
0b74af7d 358 */
359
9acc1468 360 mintemp = temp;
5adebf48 361 mincost = tempcost;
9acc1468 362 cupsArrayInsert(mintemp, current);
4ca01b29 363 }
9acc1468 364 else
365 cupsArrayDelete(temp);
366 }
0b74af7d 367
0557217b 368 if (mintemp)
4ca01b29 369 {
370 /*
7b3a0e77 371 * Hey, we got a match!
4ca01b29 372 */
0b74af7d 373
c5488f2f 374#ifdef DEBUG
0557217b 375 printf(" Returning %d filters:\n", cupsArrayCount(mintemp));
376 for (current = (mime_filter_t *)cupsArrayFirst(mintemp);
377 current;
378 current = (mime_filter_t *)cupsArrayNext(mintemp))
379 printf(" %s\n", current->filter);
c5488f2f 380#endif /* DEBUG */
381
d318937f 382 if (cost)
383 *cost = mincost;
0557217b 384
7b3a0e77 385 return (mintemp);
4ca01b29 386 }
387
c5488f2f 388 DEBUG_puts(" Returning zippo...");
389
0b74af7d 390 return (NULL);
391}
392
393
0b74af7d 394/*
395 * 'lookup()' - Lookup a filter...
396 */
397
0557217b 398static mime_filter_t * /* O - Filter for src->dst */
399lookup(mime_t *mime, /* I - MIME database */
400 mime_type_t *src, /* I - Source type */
401 mime_type_t *dst) /* I - Destination type */
0b74af7d 402{
0557217b 403 mime_filter_t key; /* Key record for filter search */
0b74af7d 404
405
0b74af7d 406 key.src = src;
407 key.dst = dst;
408
0557217b 409 return ((mime_filter_t *)cupsArrayFind(mime->filters, &key));
0b74af7d 410}
79df52e3 411
412
413/*
c9d3f842 414 * End of "$Id$".
79df52e3 415 */