fixed mem leaks
[swftools.git] / src / pdf2swf.c
index ea61645..3b67bcc 100644 (file)
@@ -23,6 +23,7 @@
 #include <stdio.h>
 #include <stdarg.h>
 #include <string.h>
+#include <memory.h>
 #include <unistd.h>
 #include "../config.h"
 #ifdef HAVE_SIGNAL_H
@@ -41,6 +42,8 @@
 #include "../lib/devices/swf.h"
 #include "../lib/devices/polyops.h"
 #include "../lib/devices/record.h"
+#include "../lib/devices/rescale.h"
+#include "../lib/gfxfilter.h"
 #include "../lib/pdf/pdf.h"
 #include "../lib/log.h"
 
@@ -49,6 +52,8 @@
 static gfxsource_t*driver = 0;
 static gfxdevice_t*out = 0;
 
+static int maxwidth=0, maxheight=0;
+
 static char * outputname = 0;
 static int loglevel = 3;
 static char * pagerange = 0;
@@ -67,6 +72,8 @@ static int max_time = 0;
 
 static int flatten = 0;
 
+static char* filters = 0;
+
 char* fontpaths[256];
 int fontpathpos = 0;
 
@@ -84,7 +91,7 @@ int systemf(const char* format, ...)
     int ret;
     va_list arglist;
     va_start(arglist, format);
-    vsprintf(buf, format, arglist);
+    vsnprintf(buf, sizeof(buf)-1, format, arglist);
     va_end(arglist);
 
     if(!system_quiet) {
@@ -116,6 +123,40 @@ void sigalarm(int signal)
 }
 #endif
 
+typedef struct _parameter {
+    struct _parameter*next;
+    const char*name;
+    const char*value;
+} parameter_t;
+
+static parameter_t* device_config = 0;
+static parameter_t* device_config_next = 0;
+static void store_parameter(const char*name, const char*value)
+{
+    parameter_t*o = device_config;
+    while(o) {
+        if(!strcmp(name, o->name)) {
+            /* overwrite old value */
+            free((void*)o->value);
+            o->value = strdup(value);
+            return;
+        }
+        o = o->next;
+    }
+    parameter_t*p = (parameter_t*)malloc(sizeof(parameter_t));
+    p->name = strdup(name);
+    p->value = strdup(value);
+    p->next = 0;
+
+    if(device_config_next) {
+       device_config_next->next = p;
+       device_config_next = p;
+    } else {
+       device_config = p;
+       device_config_next = p;
+    }
+}
+
 int args_callback_option(char*name,char*val) {
     if (!strcmp(name, "o"))
     {
@@ -146,6 +187,16 @@ int args_callback_option(char*name,char*val) {
         ynup = 3;
        return 0;
     }
+    else if (!strcmp(name, "X"))
+    {
+        maxwidth = atoi(val);
+       return 1;
+    }
+    else if (!strcmp(name, "Y"))
+    {
+        maxheight = atoi(val);
+       return 1;
+    }
     else if (!strcmp(name, "q"))
     {
        loglevel --;
@@ -209,27 +260,34 @@ int args_callback_option(char*name,char*val) {
     }
     else if (!strcmp(name, "s"))
     {
-       char*s = strdup(val);
+       char*s = val;
        char*c = strchr(s, '=');
        if(c && *c && c[1])  {
            *c = 0;
            c++;
-           driver->set_parameter(driver, s,c);
-           out->setparameter(out, s,c);
+           store_parameter(s,c);
+       } else if(!strcmp(s,"help")) {
+           printf("PDF Parameters:\n");
+           gfxsource_t*pdf = gfxsource_pdf_create();
+           pdf->setparameter(pdf, "help", "");
+           gfxdevice_t swf;
+           gfxdevice_swf_init(&swf);
+           printf("SWF Parameters:\n");
+           swf.setparameter(&swf, "help", "");
+           exit(0);
        } else {
-           driver->set_parameter(driver, s,"1");
-           out->setparameter(out, s,"1");
+           store_parameter(s,"1");
        }
        return 1;
     }
     else if (!strcmp(name, "S"))
     {
-       driver->set_parameter(driver, "drawonlyshapes", "1");
+       store_parameter("drawonlyshapes", "1");
        return 0;
     }
     else if (!strcmp(name, "i"))
     {
-       driver->set_parameter(driver, "ignoredraworder", "1");
+       store_parameter("ignoredraworder", "1");
        return 0;
     }
 #ifndef WIN32
@@ -245,13 +303,13 @@ int args_callback_option(char*name,char*val) {
 #endif
     else if (!strcmp(name, "z"))
     {
-       driver->set_parameter(driver, "enablezlib", "1");
+       store_parameter("enablezlib", "1");
        zlib = 1;
        return 0;
     }
     else if (!strcmp(name, "n"))
     {
-       driver->set_parameter(driver, "opennewwindow", "1");
+       store_parameter("opennewwindow", "1");
        return 0;
     }
     else if (!strcmp(name, "I"))
@@ -261,27 +319,41 @@ int args_callback_option(char*name,char*val) {
     }
     else if (!strcmp(name, "t"))
     {
-       driver->set_parameter(driver, "insertstop", "1");
+       store_parameter("insertstop", "1");
        return 0;
     }
     else if (!strcmp(name, "T"))
     {
        if(!strcasecmp(val, "mx"))
-           driver->set_parameter(driver, "flashversion", "6");
+           store_parameter("flashversion", "6");
        else
-           driver->set_parameter(driver, "flashversion", val);
+           store_parameter("flashversion", val);
 
        return 1;
     }
     else if (!strcmp(name, "f"))
     {
-       driver->set_parameter(driver, "storeallcharacters", "1");
-       driver->set_parameter(driver, "extrafontdata", "1");
+       store_parameter("storeallcharacters", "1");
+       store_parameter("extrafontdata", "1");
        return 0;
     }
+    else if (!strcmp(name, "ff"))
+    {
+       if(filters) {
+           // append this to the current filter expression (we allow more than one --filter)
+           int l = strlen(filters);
+           int new_len = l + strlen(val) + 2;
+           filters = (char*)realloc(filters, new_len);
+           filters[l] = ':';
+           strcpy(filters+l+1, val);
+       } else {
+           filters = strdup(val);
+       }
+       return 1;
+    }
     else if (!strcmp(name, "w"))
     {
-       driver->set_parameter(driver, "linksopennewwindow", "0");
+       store_parameter("linksopennewwindow", "0");
        return 0;
     }
     else if (!strcmp(name, "O"))
@@ -293,16 +365,16 @@ int args_callback_option(char*name,char*val) {
            ret=1;
        }
        if(level>=1)
-           driver->set_parameter(driver, "poly2bitmap", "1");
+           store_parameter("poly2bitmap", "1");
        if(level>=2)
-           driver->set_parameter(driver, "bitmapfonts", "1");
+           store_parameter("bitmapfonts", "1");
        if(level>=3)
-           driver->set_parameter(driver, "ignoredraworder", "1");
+           store_parameter("ignoredraworder", "1");
        return ret;
     }
     else if (!strcmp(name, "G"))
     {
-       //driver->set_parameter(driver, "optimize_polygons", "1");
+       //store_parameter("optimize_polygons", "1");
        flatten = 1;
        return 0;
     }
@@ -364,10 +436,10 @@ int args_callback_option(char*name,char*val) {
     else if (!strcmp(name, "j"))
     {
        if(name[1]) {
-           driver->set_parameter(driver, "jpegquality", &name[1]);
+           store_parameter("jpegquality", &name[1]);
            return 0;
        } else {
-           driver->set_parameter(driver, "jpegquality", val);
+           store_parameter("jpegquality", val);
            return 1;
        }
     }
@@ -384,46 +456,35 @@ int args_callback_option(char*name,char*val) {
     return 0;
 }
 
-/*struct docoptions_t options[] =
-{{"o","output","filename::Specify output file"},
- {"V","version","Print program version"},
- {"i","ignore","Ignore draw order (makes the SWF file smaller, but may produce graphic errors)"},
- {"z","zlib","Use Flash 6 (MX) zlib compression (Needs at least Flash 6 Plugin to play)"},
- {"s","shapes","Don't use SWF Fonts, but store everything as shape"},
- {"j","jpegquality","Set quality of embedded jpeg pictures (default: 85)"},
- {"p","pages","Convert only pages in range. (E.g. 3-85)"},
- {"w","samewindow","Don't open a new browser window for links in the SWF"},
- {"f","fonts","Stroe full fonts in SWF. (Don't reduce to used characters)"},
- {"F","fontpath","path::Add directory to font search path"},
- {"B","viewer","name::Link viewer \"name\" to the pdf"},
- {"L","preloader","file.swf::Link preloader \"file.swf\" to the pdf"},
- {"b","defaultviewer","Link default viewer to the pdf"},
- {"l","defaultpreloader","Link default preloader to the pdf"}
- {0,0}
-};*/
-struct options_t options[] =
-{{"o","output"},
- {"q","quiet"},
- {"V","version"},
- {"i","ignore"},
- {"I","info"},
- {"z","zlib"},
- {"s","set"},
- {"S","shapes"},
- {"Q","maxtime"},
- {"j","jpegquality"},
- {"p","pages"},
- {"w","samewindow"},
- {"f","fonts"},
- {"F","fontdir"},
- {"B","viewer"},
- {"G","flatten"},
- {"L","preloader"},
- {"b","defaultviewer"},
- {"l","defaultpreloader"},
- {"t","stop"},
- {"T","flashversion"},
- {0,0}
+static struct options_t options[] = {
+{"h", "help"},
+{"V", "version"},
+{"o", "output"},
+{"p", "pages"},
+{"P", "password"},
+{"v", "verbose"},
+{"z", "zlib"},
+{"i", "ignore"},
+{"j", "jpegquality"},
+{"s", "set"},
+{"w", "samewindow"},
+{"t", "stop"},
+{"T", "flashversion"},
+{"F", "fontdir"},
+{"ff", "filter"},
+{"b", "defaultviewer"},
+{"l", "defaultloader"},
+{"B", "viewer"},
+{"L", "preloader"},
+{"q", "quiet"},
+{"S", "shapes"},
+{"f", "fonts"},
+{"G", "flatten"},
+{"I", "info"},
+{"Q", "maxtime"},
+{"X", "width"},
+{"Y", "height"},
+{0,0}
 };
 
 int args_callback_longoption(char*name,char*val) {
@@ -445,43 +506,36 @@ int args_callback_command(char*name, char*val) {
     return 0;
 }
 
-void args_callback_usage(char*name)
+void args_callback_usage(char *name)
 {
-    printf("Usage: %s [Options] input.pdf [-o output.swf]\n", name);
-    printf("\nBasic options:\n");
-    printf("-p  --pages=range          Convert only pages in range\n");
-    printf("-P  --password=password    Use password for deciphering the pdf\n");
-    printf("-v  --verbose              Be verbose. Use more than one -v for greater effect\n");
-    printf("-q  --quiet                Suppress normal messages. Use -qq to suppress warnings, also.\n");
-#ifdef HAVE_DIRENT_H
-    printf("-F  --fontdir directory    Add directory to font search path\n");
-#endif
-    printf("-V  --version              Print program version\n");
-    printf("\nEnhanced conversion options:\n");
-    printf("-S  --shapes               Don't use SWF Fonts, but store everything as shape\n");
-    printf("-z  --zlib                 Use Flash 6 (MX) zlib compression (Needs at least Flash 6 Plugin to play)\n");
-    printf("-w  --samewindow           Don't open a new Browser Window for Links in the SWF\n");
-    printf("-f  --fonts                Store full fonts in SWF. (Don't reduce to used characters)\n");
-    printf("-T  --flashversion=num     Set the flash version in the header to num (default: 4)\n");
-    printf("-s insertstop              Insert a \"Stop\" Tag in every frame (don't turn pages automatically)\n");
-    printf("-s zoom=factor             Scale result, default: 72\n");
-    printf("-s jpegquality=quality     Set quality of embedded jpeg pictures (default:85)\n");
-    printf("-s caplinewidth=value      Set the minimum line width to trigger cap style handling to value. (3)\n");
-    printf("-s splinequality=value     Set the quality of spline convertion to value (0-100, default: 100).\n");
-    printf("-s fontquality=value       Set the quality of font convertion to value (0-100, default: 100).\n");
-    printf("-s ignoredraworder         Ignore draw order (makes the SWF file smaller and faster, but may produce\n"
-          "                           graphic errors)\n");
-    printf("-s filloverlap             Make intersecting shapes overlap, instead of canceling each\n"
-          "                           other out. (Needed for some Powerpoint PDFs)\n");
-    printf("-s transparent             Make the SWF transparent\n");
-    //deliberately undocumented (for now)
-    //printf("-2                         Put 2 pages into each frame.\n");
-    //printf("-4                         Put 4 pages into each frame.\n");
-    printf("Postprocessing options:\n");
-    printf("-b  --defaultviewer        Link default viewer to the pdf (%s)\n", concatPaths(SWFDIR, "default_viewer.swf"));
-    printf("-l  --defaultpreloader     Link default preloader the pdf (%s)\n", concatPaths(SWFDIR, "default_loader.swf"));
-    printf("-B  --viewer=filename      Link viewer \"name\" to the pdf (\"%s -B\" for list)\n", name);
-    printf("-L  --preloader=filename   Link preloader \"name\" to the pdf (\"%s -L\" for list)\n",name);
+    printf("\n");
+    printf("Usage: %s [-options] file.pdf -o file.swf\n", name);
+    printf("\n");
+    printf("-h , --help                    Print short help message and exit\n");
+    printf("-V , --version                 Print version info and exit\n");
+    printf("-o , --output file.swf         Direct output to file.swf. If file.swf contains '%%' (file%%.swf), then each page goes to a seperate file.\n");
+    printf("-p , --pages range             Convert only pages in range with range e.g. 1-20 or 1,4,6,9-11 or\n");
+    printf("-P , --password password       Use password for deciphering the pdf.\n");
+    printf("-v , --verbose                 Be verbose. Use more than one -v for greater effect.\n");
+    printf("-z , --zlib                    Use Flash 6 (MX) zlib compression.\n");
+    printf("-i , --ignore                  Allows pdf2swf to change the draw order of the pdf. This may make the generated\n");
+    printf("-j , --jpegquality quality     Set quality of embedded jpeg pictures to quality. 0 is worst (small), 100 is best (big). (default:85)\n");
+    printf("-s , --set param=value         Set a SWF encoder specific parameter.  See pdf2swf -s help for more information.\n");
+    printf("-w , --samewindow              When converting pdf hyperlinks, don't make the links open a new window. \n");
+    printf("-t , --stop                    Insert a stop() command in each page. \n");
+    printf("-T , --flashversion num        Set Flash Version in the SWF header to num.\n");
+    printf("-F , --fontdir directory       Add directory to the font search path.\n");
+    printf("-b , --defaultviewer           Link a standard viewer to the swf file. \n");
+    printf("-l , --defaultloader           Link a standard preloader to the swf file which will be displayed while the main swf is loading.\n");
+    printf("-B , --viewer filename         Link viewer filename to the swf file. \n");
+    printf("-L , --preloader filename      Link preloader filename to the swf file. \n");
+    printf("-q , --quiet                   Suppress normal messages.  Use -qq to suppress warnings, also.\n");
+    printf("-S , --shapes                  Don't use SWF Fonts, but store everything as shape.\n");
+    printf("-f , --fonts                   Store full fonts in SWF. (Don't reduce to used characters).\n");
+    printf("-G , --flatten                 Remove as many clip layers from file as possible. \n");
+    printf("-I , --info                    Don't do actual conversion, just display a list of all pages in the PDF.\n");
+    printf("-Q , --maxtime n               Abort conversion after n seconds. Only available on Unix.\n");
+    printf("\n");
 }
 
 float getRate(char*filename)
@@ -533,6 +587,44 @@ void show_info(gfxsource_t*driver, char*filename)
     pdf->destroy(pdf);
 }
 
+
+static gfxdevice_t swf,wrap,rescale;
+gfxdevice_t*create_output_device()
+{
+    gfxdevice_swf_init(&swf);
+
+    /* set up filter chain */
+       
+    out = &swf;
+    if(flatten) {
+        gfxdevice_removeclippings_init(&wrap, &swf);
+        out = &wrap;
+    }
+
+    if(maxwidth || maxheight) {
+        gfxdevice_rescale_init(&rescale, out, maxwidth, maxheight, 0);
+        out = &rescale;
+    }
+
+    if(filters) {
+       gfxfilterchain_t*chain = gfxfilterchain_parse(filters);
+       if(!chain) {
+           fprintf(stderr, "Unable to parse filters: %s\n", filters);
+           exit(1);
+       }
+       out = gfxfilterchain_apply(chain, out);
+       gfxfilterchain_destroy(chain);
+    }
+
+    /* pass global parameters to output device */
+    parameter_t*p = device_config;
+    while(p) {
+       out->setparameter(out, p->name, p->value);
+       p = p->next;
+    }
+    return out;
+}
+
 int main(int argn, char *argv[])
 {
     int ret;
@@ -542,7 +634,7 @@ int main(int argn, char *argv[])
     char t1searchpath[1024];
     int nup_pos = 0;
     int x,y;
-    char* installPath = getInstallationPath();
+    int one_file_per_page = 0;
     
     initLog(0,-1,0,0,-1,loglevel);
 
@@ -558,65 +650,87 @@ int main(int argn, char *argv[])
     srand(time(0));
 #endif
 #endif
-    driver = gfxsource_pdf_create();
-
-    gfxdevice_t swf,wrap;
-    gfxdevice_swf_init(&swf);
-    
-    gfxdevice_removeclippings_init(&wrap, &swf);
 
-    out = &wrap;
     processargs(argn, argv);
     
-    if(!flatten) {
-       out = &swf;
-    }
+    driver = gfxsource_pdf_create();
     
+    /* pass global parameters to PDF driver*/
+    parameter_t*p = device_config;
+    while(p) {
+       driver->setparameter(driver, p->name, p->value);
+       p = p->next;
+    }
+
     if(!filename)
     {
        fprintf(stderr, "Please specify an input file\n");
        exit(1);
     }
 
-    if(info_only) {
-       show_info(driver, filename);
-       return 0;
-    }
-
-    if(!outputname)
-    {
-       if(filename) {
-           outputname = stripFilename(filename, ".swf");
-           msg("<notice> Output filename not given. Writing to %s", outputname);
-       } 
-    }
-       
-    if(!outputname)
-    {
-       fprintf(stderr, "Please use -o to specify an output file\n");
-       exit(1);
+    if (!info_only) {
+        if(!outputname)
+        {
+            if(filename) {
+                outputname = stripFilename(filename, ".swf");
+                msg("<notice> Output filename not given. Writing to %s", outputname);
+            } 
+        }
+            
+        if(!outputname)
+        {
+            fprintf(stderr, "Please use -o to specify an output file\n");
+            exit(1);
+        }
     }
 
     // test if the page range is o.k.
     is_in_range(0x7fffffff, pagerange);
 
-    if(pagerange)
-       driver->set_parameter(driver, "pages", pagerange);
-
     if (!filename) {
        args_callback_usage(argv[0]);
        exit(0);
     }
+    
+    char fullname[256];
+    if(password && *password) {
+       sprintf(fullname, "%s|%s", filename, password);
+       filename = fullname;
+    }
+    
+    if(pagerange)
+       driver->setparameter(driver, "pages", pagerange);
 
     /* add fonts */
     for(t=0;t<fontpathpos;t++) {
-       driver->set_parameter(driver, "fontdir", fontpaths[t]);
+       driver->setparameter(driver, "fontdir", fontpaths[t]);
     }
 
-    char fullname[256];
-    if(password && *password) {
-       sprintf(fullname, "%s|%s", filename, password);
-       filename = fullname;
+    if(info_only) {
+       show_info(driver, filename);
+       return 0;
+    }
+
+    char*u = 0;
+    if((u = strchr(outputname, '%'))) {
+       if(strchr(u+1, '%') || 
+          strchr(outputname, '%')!=u)  {
+           msg("<error> only one %% allowed in filename\n");
+           return 1;
+       }
+       if(preloader || viewer) {
+           msg("<error> -b/-l/-B/-L not supported together with %% in filename\n");
+           return 1;
+       }
+       msg("<notice> outputting one file per page");
+       one_file_per_page = 1;
+       char*pattern = (char*)malloc(strlen(outputname)+2);
+       /* convert % to %d */
+       int l = u-outputname+1;
+       memcpy(pattern, outputname, l);
+       pattern[l]='d';
+       strcpy(pattern+l+1, outputname+l);
+       outputname = pattern;
     }
 
     gfxdocument_t* pdf = driver->open(driver, filename);
@@ -624,6 +738,12 @@ int main(int argn, char *argv[])
         msg("<error> Couldn't open %s", filename);
         exit(1);
     }
+    /* pass global parameters document */
+    p = device_config;
+    while(p) {
+       pdf->setparameter(pdf, p->name, p->value);
+       p = p->next;
+    }
 
     struct mypage_t {
        int x;
@@ -640,7 +760,7 @@ int main(int argn, char *argv[])
        if(is_in_range(pagenr, pagerange)) {
            char mapping[80];
            sprintf(mapping, "%d:%d", pagenr, frame);
-           pdf->set_parameter(pdf, "pagemap", mapping);
+           pdf->setparameter(pdf, "pagemap", mapping);
            pagenum++;
        }
        if(pagenum == xnup*ynup || (pagenr == pdf->num_pages && pagenum>1)) {
@@ -648,9 +768,16 @@ int main(int argn, char *argv[])
            frame++;
        }
     }
+    if(pagerange && !pagenum && frame==1) {
+       fprintf(stderr, "No pages in range %s", pagerange);
+       exit(1);
+    }
 
     pagenum = 0;
 
+    gfxdevice_t*out = create_output_device();;
+    pdf->prepare(pdf, out);
+
     for(pagenr = 1; pagenr <= pdf->num_pages; pagenr++) 
     {
        if(is_in_range(pagenr, pagerange)) {
@@ -712,56 +839,86 @@ int main(int argn, char *argv[])
                pages[t].page->destroy(pages[t].page);
            }
            pagenum = 0;
+
+           if(one_file_per_page) {
+               gfxresult_t*result = out->finish(out);out=0;
+               char buf[1024];
+               sprintf(buf, outputname, pagenr);
+               if(result->save(result, buf) < 0) {
+                   return 1;
+               }
+               result->destroy(result);result=0;
+               out = create_output_device();;
+               msg("<notice> Writing SWF file %s", buf);
+           }
        }
     }
-    
-    gfxresult_t*result = out->finish(out);
-
-    if(result->save(result, outputname) < 0) {
-        exit(1);
+   
+    if(one_file_per_page) {
+       // remove empty device
+       gfxresult_t*result = out->finish(out);out=0;
+       result->destroy(result);result=0;
+    } else {
+       gfxresult_t*result = out->finish(out);
+       msg("<notice> Writing SWF file %s", outputname);
+       if(result->save(result, outputname) < 0) {
+           exit(1);
+       }
+       int width = (int)(ptroff_t)result->get(result, "width");
+       int height = (int)(ptroff_t)result->get(result, "height");
+       result->destroy(result);result=0;
+
+       if(preloader || viewer) {
+           const char*zip = "";
+           if(zlib) {
+               zip = "-z";
+           }
+           if(!preloader && viewer) {
+               systemf("swfcombine %s -X %d -Y %d \"%s\" viewport=\"%s\" -o \"%s\"",zip,width,height,
+                       viewer, outputname, outputname);
+               if(!system_quiet)
+                   printf("\n");
+           }
+           if(preloader && !viewer) {
+               msg("<warning> --preloader option without --viewer option doesn't make very much sense.");
+               ret = systemf("swfcombine %s -Y %d -X %d %s/PreLoaderTemplate.swf loader=\"%s\" movie=\"%s\" -o \"%s\"",zip,width,height,
+                       SWFDIR, preloader, outputname, outputname);
+               if(!system_quiet)
+                   printf("\n");
+           }
+           if(preloader && viewer) {
+#ifdef HAVE_MKSTEMP
+               char tmpname[] = "__swf__XXXXXX";
+               mkstemp(tmpname);
+#else 
+               char*tmpname = "__tmp__.swf";
+#endif
+               systemf("swfcombine \"%s\" viewport=%s -o %s",
+                       viewer, outputname, tmpname);
+               systemf("swfcombine %s -X %d -Y %d -r %f %s/PreLoaderTemplate.swf loader=%s movie=%s -o \"%s\"",zip,width,height,
+                       getRate(preloader), SWFDIR, preloader, tmpname, outputname);
+               systemf("rm %s", tmpname);
+           }
+       }
     }
 
-    int width = (int)result->get(result, "width");
-    int height = (int)result->get(result, "height");
-    msg("<notice> SWF written");
-    
-    result->destroy(result);
-
     pdf->destroy(pdf);
     driver->destroy(driver);
 
-    const char*zip = "";
-    if(zlib) {
-       zip = "-z";
-    }
-    if(!preloader && viewer) {
-       systemf("swfcombine %s -X %d -Y %d \"%s\" viewport=\"%s\" -o \"%s\"",zip,width,height,
-               viewer, outputname, outputname);
-       if(!system_quiet)
-           printf("\n");
-    }
-    if(preloader && !viewer) {
-       msg("<warning> --preloader option without --viewer option doesn't make very much sense.");
-       ret = systemf("swfcombine %s -Y %d -X %d %s/PreLoaderTemplate.swf loader=\"%s\" movie=\"%s\" -o \"%s\"",zip,width,height,
-               SWFDIR, preloader, outputname, outputname);
-       if(!system_quiet)
-           printf("\n");
-    }
-    if(preloader && viewer) {
-#ifdef HAVE_MKSTEMP
-        char tmpname[] = "__swf__XXXXXX";
-        mkstemp(tmpname);
-#else 
-       char*tmpname = "__tmp__.swf";
-#endif
-       systemf("swfcombine \"%s\" viewport=%s -o %s",
-               viewer, outputname, tmpname);
-        systemf("swfcombine %s -X %d -Y %d -r %f %s/PreLoaderTemplate.swf loader=%s movie=%s -o \"%s\"",zip,width,height,
-                getRate(preloader), SWFDIR, preloader, tmpname, outputname);
-        systemf("rm %s", tmpname);
+   
+    /* free global parameters */
+    p = device_config;
+    while(p) {
+       parameter_t*next = p->next;
+       if(p->name) free((void*)p->name);p->name = 0;
+       if(p->value) free((void*)p->value);p->value =0;
+       p->next = 0;free(p);
+       p = next;
+    }
+    if(filters) {
+       free(filters);
     }
 
-
     return 0;
 }