home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / print / print.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-11-19  |  39.6 KB  |  1,515 lines

  1. /*
  2.  * "$Id: print.c,v 1.43 2000/11/18 00:33:39 mitch Exp $"
  3.  *
  4.  *   Print plug-in for the GIMP.
  5.  *
  6.  *   Copyright 1997-2000 Michael Sweet (mike@easysw.com) and
  7.  *    Robert Krawitz (rlk@alum.mit.edu)
  8.  *
  9.  *   This program is free software; you can redistribute it and/or modify it
  10.  *   under the terms of the GNU General Public License as published by the Free
  11.  *   Software Foundation; either version 2 of the License, or (at your option)
  12.  *   any later version.
  13.  *
  14.  *   This program is distributed in the hope that it will be useful, but
  15.  *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  16.  *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  17.  *   for more details.
  18.  *
  19.  *   You should have received a copy of the GNU General Public License
  20.  *   along with this program; if not, write to the Free Software
  21.  *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  22.  */
  23.  
  24. #ifdef HAVE_CONFIG_H
  25. #include "config.h"
  26. #endif
  27.  
  28. #include "print_gimp.h"
  29.  
  30. #ifdef GIMP_1_0
  31. #include <math.h>
  32. #endif
  33.  
  34. #include <signal.h>
  35. #include <ctype.h>
  36. #include <sys/wait.h>
  37. #ifdef __EMX__
  38. #define INCL_DOSDEVICES
  39. #define INCL_DOSERRORS
  40. #include <os2.h>
  41. #endif
  42.  
  43. #include <unistd.h>
  44.  
  45. #include "print-intl.h"
  46.  
  47. /*
  48.  * Local functions...
  49.  */
  50.  
  51. static void    printrc_load(void);
  52. void            printrc_save(void);
  53. static int    compare_printers(plist_t *p1, plist_t *p2);
  54. static void    get_system_printers(void);
  55.  
  56. static void    query (void);
  57. static void    run (char *, int, GParam *, int *, GParam **);
  58. static int    do_print_dialog (char *proc_name);
  59.  
  60. #ifndef GIMP_1_0
  61. extern void     gimp_create_main_window (void);
  62. #endif
  63. #ifndef NEW_UI_ONLY
  64. extern void     gtk_create_main_window (void);
  65. #endif
  66.  
  67. #if 0
  68. static void    cleanupfunc(void);
  69. #endif
  70.  
  71. /*
  72.  * Globals...
  73.  */
  74.  
  75. GPlugInInfo    PLUG_IN_INFO =        /* Plug-in information */
  76. {
  77.   NULL,  /* init_proc  */
  78.   NULL,  /* quit_proc  */
  79.   query, /* query_proc */
  80.   run,   /* run_proc   */
  81. };
  82.  
  83. vars_t vars =
  84. {
  85.     "",            /* Name of file or command to print to */
  86.     "ps2",            /* Name of printer "driver" */
  87.     "",            /* Name of PPD file */
  88.     OUTPUT_COLOR,        /* Color or grayscale output */
  89.     "",            /* Output resolution */
  90.     "",            /* Size of output media */
  91.     "",            /* Type of output media */
  92.     "",            /* Source of output media */
  93.     "",            /* Ink type */
  94.     "",            /* Dither algorithm */
  95.     1.0,            /* Output brightness */
  96.     100.0,            /* Scaling (100% means entire printable area, */
  97.                 /*          -XXX means scale by PPI) */
  98.     -1,            /* Orientation (-1 = automatic) */
  99.     -1,            /* X offset (-1 = center) */
  100.     -1,            /* Y offset (-1 = center) */
  101.     1.0,            /* Screen gamma */
  102.     1.0,            /* Contrast */
  103.     1.0,            /* Cyan */
  104.     1.0,            /* Magenta */
  105.     1.0,            /* Yellow */
  106.     0,            /* Linear */
  107.     1.0,            /* Output saturation */
  108.     1.0,            /* Density */
  109.     IMAGE_CONTINUOUS,    /* Image type */
  110.     0,            /* Unit 0=Inch */
  111.     1.0,            /* Application gamma placeholder */
  112.     0,            /* Page width */
  113.     0            /* Page height */
  114. };
  115.  
  116. int        plist_current = 0,    /* Current system printer */
  117.         plist_count = 0;    /* Number of system printers */
  118. plist_t        *plist;            /* System printers */
  119.  
  120. int        saveme = FALSE;        /* True if print should proceed */
  121. int        runme = FALSE;        /* True if print should proceed */
  122. const printer_t *current_printer = 0;    /* Current printer index */
  123. gint32          image_ID;            /* image ID */
  124.  
  125. const char *image_filename;
  126. int image_width;
  127. int image_height;
  128.  
  129. static void
  130. check_plist(int count)
  131. {
  132.   static int current_plist_size = 0;
  133.   if (count <= current_plist_size)
  134.     return;
  135.   else if (current_plist_size == 0)
  136.     {
  137.       current_plist_size = count;
  138.       plist = malloc(current_plist_size * sizeof(plist_t));
  139.     }
  140.   else
  141.     {
  142.       current_plist_size *= 2;
  143.       if (current_plist_size < count)
  144.     current_plist_size = count;
  145.       plist = realloc(plist, current_plist_size * sizeof(plist_t));
  146.     }
  147. }
  148.  
  149. /*
  150.  * 'main()' - Main entry - just call gimp_main()...
  151.  */
  152.  
  153. #if 0
  154. int
  155. main(int  argc,        /* I - Number of command-line args */
  156.      char *argv[])    /* I - Command-line args */
  157. {
  158.   return (gimp_main(argc, argv));
  159. }
  160. #else
  161. MAIN()
  162. #endif
  163.  
  164. static int print_finished = 0;
  165.  
  166. #if 0
  167. void
  168. cleanupfunc(void)
  169. {
  170. }
  171. #endif
  172.  
  173. /*
  174.  * 'query()' - Respond to a plug-in query...
  175.  */
  176.  
  177. static void
  178. query (void)
  179. {
  180.   static GParamDef    args[] =
  181.   {
  182.     { PARAM_INT32,    "run_mode",    "Interactive, non-interactive" },
  183.     { PARAM_IMAGE,    "image",    "Input image" },
  184.     { PARAM_DRAWABLE,    "drawable",    "Input drawable" },
  185.     { PARAM_STRING,    "output_to",    "Print command or filename (| to pipe to command)" },
  186.     { PARAM_STRING,    "driver",    "Printer driver short name" },
  187.     { PARAM_STRING,    "ppd_file",    "PPD file" },
  188.     { PARAM_INT32,    "output_type",    "Output type (0 = gray, 1 = color)" },
  189.     { PARAM_STRING,    "resolution",    "Resolution (\"300\", \"720\", etc.)" },
  190.     { PARAM_STRING,    "media_size",    "Media size (\"Letter\", \"A4\", etc.)" },
  191.     { PARAM_STRING,    "media_type",    "Media type (\"Plain\", \"Glossy\", etc.)" },
  192.     { PARAM_STRING,    "media_source",    "Media source (\"Tray1\", \"Manual\", etc.)" },
  193.     { PARAM_FLOAT,    "brightness",    "Brightness (0-400%)" },
  194.     { PARAM_FLOAT,    "scaling",    "Output scaling (0-100%, -PPI)" },
  195.     { PARAM_INT32,    "orientation",    "Output orientation (-1 = auto, 0 = portrait, 1 = landscape)" },
  196.     { PARAM_INT32,    "left",        "Left offset (points, -1 = centered)" },
  197.     { PARAM_INT32,    "top",        "Top offset (points, -1 = centered)" },
  198.     { PARAM_FLOAT,    "gamma",    "Output gamma (0.1 - 3.0)" },
  199.     { PARAM_FLOAT,    "contrast",    "Contrast" },
  200.     { PARAM_FLOAT,    "cyan",        "Cyan level" },
  201.     { PARAM_FLOAT,    "magenta",    "Magenta level" },
  202.     { PARAM_FLOAT,    "yellow",        "Yellow level" },
  203.     { PARAM_INT32,    "linear",    "Linear output (0 = normal, 1 = linear)" },
  204.     { PARAM_INT32,    "image_type",    "Image type (0 = line art, 1 = solid tones, 2 = continuous tone, 3 = monochrome)"},
  205.     { PARAM_FLOAT,    "saturation",    "Saturation (0-1000%)" },
  206.     { PARAM_FLOAT,    "density",    "Density (0-200%)" },
  207.     { PARAM_STRING,    "ink_type",    "Type of ink or cartridge" },
  208.     { PARAM_STRING,    "dither_algorithm", "Dither algorithm" },
  209.     { PARAM_INT32,    "unit",        "Unit 0=Inches 1=Metric" },
  210.   };
  211.   static gint nargs = sizeof(args) / sizeof(args[0]);
  212.  
  213.   static gchar *blurb = "This plug-in prints images from The GIMP.";
  214.   static gchar *help  = "Prints images to PostScript, PCL, or ESC/P2 printers.";
  215.   static gchar *auth  = "Michael Sweet <mike@easysw.com> and Robert Krawitz <rlk@alum.mit.edu>";
  216.   static gchar *copy  = "Copyright 1997-2000 by Michael Sweet and Robert Krawitz";
  217.   static gchar *types = "RGB*,GRAY*,INDEXED*";
  218.  
  219. #ifdef NEW_UI_ONLY
  220.   gimp_install_procedure ("file_print_gimp",
  221.               blurb, help, auth, copy,
  222.               PLUG_IN_VERSION,
  223.               N_("<Image>/File/Print..."),
  224.               types,
  225.               PROC_PLUG_IN,
  226.               nargs, 0,
  227.               args, NULL);
  228. #elif defined(GIMP_1_0)
  229.   gimp_install_procedure ("file_print",
  230.               blurb, help, auth, copy,
  231.               PLUG_IN_VERSION,
  232.               N_("<Image>/File/Print..."),
  233.               types,
  234.               PROC_PLUG_IN,
  235.               nargs, 0,
  236.               args, NULL);
  237. #else
  238.   gimp_install_procedure ("file_print_gtk",
  239.               blurb, help, auth, copy,
  240.               PLUG_IN_VERSION,
  241.               N_("<Image>/File/Print (Gtk)..."),
  242.               types,
  243.               PROC_PLUG_IN,
  244.               nargs, 0,
  245.               args, NULL);
  246.   gimp_install_procedure ("file_print_gimp",
  247.               blurb, help, auth, copy,
  248.               PLUG_IN_VERSION,
  249.               N_("<Image>/File/Print (Gimp)..."),
  250.               types,
  251.               PROC_PLUG_IN,
  252.               nargs, 0,
  253.               args, NULL);
  254. #endif
  255. }
  256.  
  257.  
  258. #ifdef __EMX__
  259. static char *
  260. get_tmp_filename()
  261. {
  262.   char *tmp_path, *s, filename[80];
  263.  
  264.   tmp_path = getenv("TMP");
  265.   if (tmp_path == NULL)
  266.     tmp_path = "";
  267.  
  268.   sprintf(filename, "gimp_print_tmp.%d", getpid());
  269.   s = tmp_path = g_strconcat(tmp_path, "\\", filename, NULL);
  270.   if (!s)
  271.     return NULL;
  272.   for ( ; *s; s++)
  273.     if (*s == '/') *s = '\\';
  274.   return tmp_path;
  275. }
  276. #endif
  277.  
  278. /*
  279.  * 'usr1_handler()' - Make a note when we receive SIGUSR1.
  280.  */
  281.  
  282. static volatile int usr1_interrupt;
  283.  
  284. static void
  285. usr1_handler (int signal)
  286. {
  287.   usr1_interrupt = 1;
  288. }
  289.  
  290. /*
  291.  * 'run()' - Run the plug-in...
  292.  */
  293.  
  294. /* #define DEBUG_STARTUP */
  295.  
  296.  
  297. #ifdef DEBUG_STARTUP
  298. volatile int SDEBUG = 1;
  299. #endif
  300.  
  301. static void
  302. run (char   *name,        /* I - Name of print program. */
  303.      int    nparams,        /* I - Number of parameters passed in */
  304.      GParam *param,        /* I - Parameter values */
  305.      int    *nreturn_vals,    /* O - Number of return values */
  306.      GParam **return_vals)    /* O - Return values */
  307. {
  308.   GDrawable    *drawable;    /* Drawable for image */
  309.   GRunModeType     run_mode;    /* Current run mode */
  310.   FILE        *prn;        /* Print file/command */
  311.   int         ncolors;    /* Number of colors in colormap */
  312.   GParam    *values;    /* Return values */
  313. #ifdef __EMX__
  314.   char        *tmpfile;    /* temp filename */
  315. #endif
  316.   gint32         drawable_ID;   /* drawable ID */
  317. #ifndef GIMP_1_0
  318.   GimpExportReturnType export = EXPORT_CANCEL;    /* return value of gimp_export_image() */
  319. #endif
  320.   int        ppid = getpid (), /* PID of plugin */
  321.         opid,        /* PID of output process */
  322.         cpid = 0,    /* PID of control/monitor process */
  323.         pipefd[2];    /* Fds of the pipe connecting all the above */
  324.   int        dummy;
  325. #ifdef DEBUG_STARTUP
  326.   while (SDEBUG)
  327.     ;
  328. #endif
  329.  
  330. #ifdef INIT_I18N_UI
  331.   INIT_I18N_UI();
  332. #else
  333.   INIT_LOCALE ("gimp-print");
  334. #endif
  335.  
  336.   /*
  337.    * Initialize parameter data...
  338.    */
  339.  
  340.   current_printer = get_printer_by_index (0);
  341.   run_mode = (GRunModeType)param[0].data.d_int32;
  342.  
  343.   values = g_new (GParam, 1);
  344.  
  345.   values[0].type          = PARAM_STATUS;
  346.   values[0].data.d_status = STATUS_SUCCESS;
  347.  
  348.   *nreturn_vals = 1;
  349.   *return_vals  = values;
  350.  
  351.   image_ID = param[1].data.d_int32;
  352.   drawable_ID = param[2].data.d_int32;
  353.  
  354.   image_filename = gimp_image_get_filename (image_ID);
  355.   if (strchr(image_filename, '/'))
  356.     image_filename = strrchr(image_filename, '/') + 1;
  357.  
  358. #ifndef GIMP_1_0
  359.   /*  eventually export the image */
  360.   switch (run_mode)
  361.     {
  362.     case RUN_INTERACTIVE:
  363.     case RUN_WITH_LAST_VALS:
  364.       gimp_ui_init ("print", TRUE);
  365.       export = gimp_export_image (&image_ID, &drawable_ID, "Print",
  366.                   (CAN_HANDLE_RGB |
  367.                    CAN_HANDLE_GRAY |
  368.                    CAN_HANDLE_INDEXED |
  369.                    CAN_HANDLE_ALPHA));
  370.       if (export == EXPORT_CANCEL)
  371.     {
  372.       *nreturn_vals = 1;
  373.       values[0].data.d_status = STATUS_EXECUTION_ERROR;
  374.       return;
  375.     }
  376.       break;
  377.     default:
  378.       break;
  379.     }
  380. #endif
  381.  
  382.   /*
  383.    * Get drawable...
  384.    */
  385.  
  386.   drawable = gimp_drawable_get (drawable_ID);
  387.  
  388.   image_width  = drawable->width;
  389.   image_height = drawable->height;
  390.  
  391.   /*
  392.    * See how we will run
  393.    */
  394.  
  395.   switch (run_mode)
  396.     {
  397.     case RUN_INTERACTIVE:
  398.       /*
  399.        * Get information from the dialog...
  400.        */
  401.  
  402.       if (!do_print_dialog (name))
  403.     goto cleanup;
  404.       break;
  405.  
  406.     case RUN_NONINTERACTIVE:
  407.       /*
  408.        * Make sure all the arguments are present...
  409.        */
  410.       if (nparams < 11)
  411.     values[0].data.d_status = STATUS_CALLING_ERROR;
  412.       else
  413.     {
  414.       strcpy (vars.output_to, param[3].data.d_string);
  415.       strcpy (vars.driver, param[4].data.d_string);
  416.       strcpy (vars.ppd_file, param[5].data.d_string);
  417.       vars.output_type = param[6].data.d_int32;
  418.       strcpy (vars.resolution, param[7].data.d_string);
  419.       strcpy (vars.media_size, param[8].data.d_string);
  420.       strcpy (vars.media_type, param[9].data.d_string);
  421.       strcpy (vars.media_source, param[10].data.d_string);
  422.  
  423.           if (nparams > 11)
  424.         vars.brightness = param[11].data.d_int32;
  425.       else
  426.         vars.brightness = 100;
  427.  
  428.           if (nparams > 12)
  429.             vars.scaling = param[12].data.d_float;
  430.           else
  431.             vars.scaling = 100.0;
  432.  
  433.           if (nparams > 13)
  434.             vars.orientation = param[13].data.d_int32;
  435.           else
  436.             vars.orientation = -1;
  437.  
  438.           if (nparams > 14)
  439.             vars.left = param[14].data.d_int32;
  440.           else
  441.             vars.left = -1;
  442.  
  443.           if (nparams > 15)
  444.             vars.top = param[15].data.d_int32;
  445.           else
  446.             vars.top = -1;
  447.  
  448.           if (nparams > 16)
  449.             vars.gamma = param[16].data.d_float;
  450.           else
  451.             vars.gamma = 1.0;
  452.  
  453.           if (nparams > 17)
  454.         vars.contrast = param[17].data.d_int32;
  455.       else
  456.         vars.contrast = 100;
  457.  
  458.           if (nparams > 18)
  459.         vars.cyan = param[18].data.d_int32;
  460.       else
  461.         vars.cyan = 100;
  462.  
  463.           if (nparams > 19)
  464.         vars.magenta = param[19].data.d_int32;
  465.       else
  466.         vars.magenta = 100;
  467.  
  468.           if (nparams > 20)
  469.         vars.yellow = param[20].data.d_int32;
  470.       else
  471.         vars.yellow = 100;
  472.  
  473.           if (nparams > 21)
  474.             vars.linear = param[21].data.d_int32;
  475.           else
  476.             vars.linear = 0;
  477.  
  478.           if (nparams > 22)
  479.             vars.image_type = param[22].data.d_int32;
  480.           else
  481.             vars.image_type = IMAGE_CONTINUOUS;
  482.  
  483.           if (nparams > 23)
  484.             vars.saturation = param[23].data.d_float;
  485.           else
  486.             vars.saturation = 1.0;
  487.  
  488.           if (nparams > 24)
  489.             vars.density = param[24].data.d_float;
  490.           else
  491.             vars.density = 1.0;
  492.  
  493.       if (nparams > 25)
  494.         strcpy (vars.ink_type, param[25].data.d_string);
  495.       else
  496.         memset (vars.ink_type, 0, 64);
  497.  
  498.       if (nparams > 26)
  499.         strcpy (vars.dither_algorithm, param[26].data.d_string);
  500.       else
  501.         memset (vars.dither_algorithm, 0, 64);
  502.  
  503.           if (nparams > 27)
  504.             vars.unit = param[27].data.d_int32;
  505.           else
  506.             vars.unit = 0;
  507.     }
  508.  
  509.       current_printer = get_printer_by_driver (vars.driver);
  510.       break;
  511.  
  512.     case RUN_WITH_LAST_VALS:
  513.       /*
  514.        * Possibly retrieve data...
  515.        */
  516.       gimp_get_data (PLUG_IN_NAME, &vars);
  517.       vars.page_width = 0;
  518.       vars.page_height = 0;
  519.  
  520.       current_printer = get_printer_by_driver (vars.driver);
  521.       break;
  522.  
  523.     default:
  524.       values[0].data.d_status = STATUS_CALLING_ERROR;
  525.       break;;
  526.     }
  527.  
  528.   /*
  529.    * Print the image...
  530.    */
  531.   if (values[0].data.d_status == STATUS_SUCCESS)
  532.     {
  533.       /*
  534.        * Set the tile cache size...
  535.        */
  536.  
  537.       if (drawable->height > drawable->width)
  538.     gimp_tile_cache_ntiles ((drawable->height + gimp_tile_width () - 1) /
  539.                 gimp_tile_width () + 1);
  540.       else
  541.     gimp_tile_cache_ntiles ((drawable->width + gimp_tile_width () - 1) /
  542.                 gimp_tile_width () + 1);
  543.  
  544.       /*
  545.        * Open the file/execute the print command...
  546.        */
  547.  
  548.       if (plist_current > 0)
  549. #ifndef __EMX__
  550.       {
  551.     /*
  552.      * The following IPC code is only necessary because the GIMP kills
  553.      * plugins with SIGKILL if its "Cancel" button is pressed; this
  554.      * gives the plugin no chance whatsoever to clean up after itself.
  555.      */
  556.     usr1_interrupt = 0;
  557.     signal (SIGUSR1, usr1_handler);
  558.     if (pipe (pipefd) != 0) {
  559.       prn = NULL;
  560.     } else {
  561.       cpid = fork ();
  562.       if (cpid < 0) {
  563.         prn = NULL;
  564.       } else if (cpid == 0) {
  565.         /* LPR monitor process.  Printer output is piped to us. */
  566.         opid = fork ();
  567.         if (opid < 0) {
  568.           /* Errors will cause the plugin to get a SIGPIPE.  */
  569.           exit (1);
  570.         } else if (opid == 0) {
  571.           dup2 (pipefd[0], 0);
  572.           close (pipefd[0]);
  573.           close (pipefd[1]);
  574.           execl("/bin/sh", "/bin/sh", "-c", vars.output_to, NULL);
  575.           /* NOTREACHED */
  576.           exit (1);
  577.         } else {
  578.           /*
  579.            * If the print plugin gets SIGKILLed by gimp, we kill lpr
  580.            * in turn.  If the plugin signals us with SIGUSR1 that it's
  581.            * finished printing normally, we close our end of the pipe,
  582.            * and go away.
  583.            */
  584.           close (pipefd[0]);
  585.           while (usr1_interrupt == 0) {
  586.             if (kill (ppid, 0) < 0) {
  587.           /* The print plugin has been killed!  */
  588.           kill (opid, SIGTERM);
  589.           waitpid (opid, &dummy, 0);
  590.           close (pipefd[1]);
  591.           /*
  592.            * We do not want to allow cleanup before exiting.
  593.            * The exiting parent has already closed the connection
  594.            * to the X server; if we try to clean up, we'll notice
  595.            * that fact and complain.
  596.            */
  597.           _exit (0);
  598.             }
  599.             sleep (5);
  600.           }
  601.           /* We got SIGUSR1.  */
  602.           close (pipefd[1]);
  603.           /*
  604.            * We do not want to allow cleanup before exiting.
  605.            * The exiting parent has already closed the connection
  606.            * to the X server; if we try to clean up, we'll notice
  607.            * that fact and complain.
  608.            */
  609.           _exit (0);
  610.         }
  611.       } else {
  612.         close (pipefd[0]);
  613.         /* Parent process.  We generate the printer output. */
  614.         prn = fdopen (pipefd[1], "w");
  615.         /* and fall through... */
  616.       }
  617.     }
  618.       }
  619. #else
  620.       /* OS/2 PRINT command doesn't support print from stdin, use temp file */
  621.       prn = (tmpfile = get_tmp_filename ()) ? fopen (tmpfile, "w") : NULL;
  622. #endif
  623.       else
  624.     prn = fopen (vars.output_to, "wb");
  625.  
  626.       if (prn != NULL)
  627.     {
  628.       Image image = Image_GDrawable_new(drawable);
  629.       vars.app_gamma = gimp_gamma();
  630.       merge_printvars(&vars, &(current_printer->printvars));
  631.  
  632.       /*
  633.        * Is the image an Indexed type?  If so we need the colormap...
  634.        */
  635.  
  636.       if (gimp_image_base_type (image_ID) == INDEXED)
  637.         vars.cmap = gimp_image_get_cmap (image_ID, &ncolors);
  638.       else
  639.         vars.cmap    = NULL;
  640.  
  641.       /*
  642.        * Finally, call the print driver to send the image to the printer
  643.        * and close the output file/command...
  644.        */
  645.  
  646.       if (verify_printer_params(current_printer, &vars))
  647.         (*current_printer->print) (current_printer, 1, prn, image, &vars);
  648.       else
  649.         values[0].data.d_status = STATUS_EXECUTION_ERROR;
  650.  
  651.       if (plist_current > 0)
  652. #ifndef __EMX__
  653.       {
  654.         fclose (prn);
  655.         kill (cpid, SIGUSR1);
  656.         waitpid (cpid, &dummy, 0);
  657.       }
  658. #else
  659.       { /* PRINT temp file */
  660.         char *s;
  661.         fclose (prn);
  662.         s = g_strconcat (vars.output_to, tmpfile, NULL);
  663.         if (system(s) != 0)
  664.           values[0].data.d_status = STATUS_EXECUTION_ERROR;
  665.         g_free (s);
  666.         remove (tmpfile);
  667.         g_free( tmpfile);
  668.       }
  669. #endif
  670.       else
  671.         fclose (prn);
  672.       print_finished = 1;
  673.     }
  674.       else
  675.     values[0].data.d_status = STATUS_EXECUTION_ERROR;
  676.  
  677.       /*
  678.        * Store data...
  679.        */
  680.  
  681.       if (run_mode == RUN_INTERACTIVE)
  682.     gimp_set_data (PLUG_IN_NAME, &vars, sizeof (vars));
  683.     }
  684.  
  685.   /*
  686.    * Detach from the drawable...
  687.    */
  688.   gimp_drawable_detach (drawable);
  689.  
  690.  
  691.  cleanup:
  692. #ifndef GIMP_1_0
  693.   if (export == EXPORT_EXPORT)
  694.     gimp_image_delete (image_ID);
  695. #else
  696.   ; /* MRS: empty statement to suppress compiler warning */
  697. #endif
  698. }
  699.  
  700. /*
  701.  * 'do_print_dialog()' - Pop up the print dialog...
  702.  */
  703.  
  704. static gint
  705. do_print_dialog (gchar *proc_name)
  706. {
  707. #ifdef GIMP_1_0
  708.   gchar **argv;
  709.   gint    argc;
  710.  
  711.   argc    = 1;
  712.   argv    = g_new (gchar *, 1);
  713.   argv[0] = g_strdup ("print");
  714.  
  715.   gtk_init (&argc, &argv);
  716.   gtk_rc_parse (gimp_gtkrc ());
  717.  
  718.   gdk_set_use_xshm (gimp_use_xshm());
  719. #endif
  720.  
  721.   /*
  722.    * Get printrc options...
  723.    */
  724.   printrc_load ();
  725.  
  726.   /*
  727.    * Print dialog window...
  728.    */
  729. #ifdef NEW_UI_ONLY
  730.   gimp_create_main_window();
  731. #elif defined(GIMP_1_0)
  732.   gtk_create_main_window ();
  733. #else
  734.   if (!strcmp (proc_name, "file_print_gimp"))
  735.     gimp_create_main_window ();
  736.   else
  737.     gtk_create_main_window ();
  738. #endif
  739.  
  740.   gtk_main ();
  741.   gdk_flush ();
  742.  
  743.   /*
  744.    * Set printrc options...
  745.    */
  746.   if (saveme)
  747.     printrc_save ();
  748.  
  749.   /*
  750.    * Return ok/cancel...
  751.    */
  752.   return (runme);
  753. }
  754.  
  755. static void
  756. initialize_printer(plist_t *printer)
  757. {
  758.   const vars_t *def = print_default_settings();
  759.   printer->name[0] = '\0';
  760.   printer->active=0;
  761.   memcpy(&(printer->v), def, sizeof(vars_t));
  762. }
  763.  
  764. #define GET_MANDATORY_STRING_PARAM(param)        \
  765. do {                            \
  766.   if ((commaptr = strchr(lineptr, ',')) == NULL)    \
  767.     continue;                        \
  768.   strncpy(key.param, lineptr, commaptr - line);        \
  769.   key.param[commaptr - lineptr] = '\0';            \
  770.   lineptr = commaptr + 1;                \
  771. } while (0)
  772.  
  773. #define GET_MANDATORY_INT_PARAM(param)            \
  774. do {                            \
  775.   if ((commaptr = strchr(lineptr, ',')) == NULL)    \
  776.     continue;                        \
  777.   key.param = atoi(lineptr);                \
  778.   lineptr = commaptr + 1;                \
  779. } while (0)
  780.  
  781. #define GET_OPTIONAL_STRING_PARAM(param)            \
  782. do {                                \
  783.   if ((commaptr = strchr(lineptr, ',')) == NULL)        \
  784.     {                                \
  785.       strcpy(key.v.param, lineptr);                \
  786.       keepgoing = 0;                        \
  787.       key.v.param[strlen(key.v.param) - 1] = '\0';        \
  788.     }                                \
  789.   else                                \
  790.     {                                \
  791.       strncpy(key.v.param, lineptr, commaptr - lineptr);    \
  792.       key.v.param[commaptr - lineptr] = '\0';            \
  793.       lineptr = commaptr + 1;                    \
  794.     }                                \
  795. } while (0)
  796.  
  797. #define GET_OPTIONAL_INT_PARAM(param)                    \
  798. do {                                    \
  799.   if ((keepgoing == 0) || ((commaptr = strchr(lineptr, ',')) == NULL))    \
  800.     {                                    \
  801.       keepgoing = 0;                            \
  802.     }                                    \
  803.   else                                    \
  804.     {                                    \
  805.       key.v.param = atoi(lineptr);                    \
  806.       lineptr = commaptr + 1;                        \
  807.     }                                    \
  808. } while (0)
  809.  
  810. #define GET_OPTIONAL_FLOAT_PARAM(param)                    \
  811. do {                                    \
  812.   if ((keepgoing == 0) || ((commaptr = strchr(lineptr, ',')) == NULL))    \
  813.     {                                    \
  814.       keepgoing = 0;                            \
  815.     }                                    \
  816.   else                                    \
  817.     {                                    \
  818.       const vars_t *maxvars = print_maximum_settings();            \
  819.       const vars_t *minvars = print_minimum_settings();            \
  820.       const vars_t *defvars = print_default_settings();            \
  821.       key.v.param = atof(lineptr);                    \
  822.       if (key.v.param > 0 &&                        \
  823.       (key.v.param > 2 * maxvars->param ||                \
  824.        key.v.param < minvars->param))                \
  825.     key.v.param = defvars->param;                    \
  826.       lineptr = commaptr + 1;                        \
  827.     }                                    \
  828. } while (0)
  829.  
  830. static void *
  831. psearch(const void *key, const void *base, size_t nmemb, size_t size,
  832.     int (*compar)(const void *, const void *))
  833. {
  834.   int i;
  835.   const char *cbase = (const char *) base;
  836.   for (i = 0; i < nmemb; i++)
  837.     {
  838.       if ((*compar)(key, (const void *) cbase) == 0)
  839.     return (void *) cbase;
  840.       cbase += size;
  841.     }
  842.   return NULL;
  843. }
  844.  
  845. /*
  846.  * 'printrc_load()' - Load the printer resource configuration file.
  847.  */
  848. void
  849. printrc_load(void)
  850. {
  851.   int        i;        /* Looping var */
  852.   FILE        *fp;        /* Printrc file */
  853.   char        *filename;    /* Its name */
  854.   char        line[1024],    /* Line in printrc file */
  855.         *lineptr,    /* Pointer in line */
  856.         *commaptr;    /* Pointer to next comma */
  857.   plist_t    *p = 0,        /* Current printer */
  858.         key;        /* Search key */
  859. #if (GIMP_MINOR_VERSION == 0)
  860.   char        *home;        /* Home dir */
  861. #endif
  862.   int        format = 0;    /* rc file format version */
  863.   int        system_printers; /* printer count before reading printrc */
  864.   char *    current_printer = 0; /* printer to select */
  865.  
  866.   check_plist(1);
  867.  
  868.  /*
  869.   * Get the printer list...
  870.   */
  871.  
  872.   get_system_printers();
  873.  
  874.   system_printers = plist_count - 1;
  875.  
  876.  /*
  877.   * Generate the filename for the current user...
  878.   */
  879.  
  880. #if (GIMP_MINOR_VERSION == 0)
  881.   home = getenv("HOME");
  882.   if (home == NULL)
  883.     filename=g_strdup("/.gimp/printrc");
  884.   else
  885.     filename = malloc(strlen(home) + 15);
  886.     sprintf(filename, "%s/.gimp/printrc", home);
  887. #else
  888.   filename = gimp_personal_rc_file ("printrc");
  889. #endif
  890.  
  891. #ifdef __EMX__
  892.   _fnslashify(filename);
  893. #endif
  894.  
  895. #ifndef __EMX__
  896.   if ((fp = fopen(filename, "r")) != NULL)
  897. #else
  898.   if ((fp = fopen(filename, "rt")) != NULL)
  899. #endif
  900.   {
  901.    /*
  902.     * File exists - read the contents and update the printer list...
  903.     */
  904.  
  905.     (void) memset(&key, 0, sizeof(plist_t));
  906.     (void) memset(line, 0, 1024);
  907.     while (fgets(line, sizeof(line), fp) != NULL)
  908.     {
  909.       int keepgoing = 1;
  910.       if (line[0] == '#')
  911.       {
  912.     if (strncmp("#PRINTRCv", line, 9) == 0)
  913.     {
  914. #ifdef DEBUG
  915.           printf("Found printrc version tag: `%s'\n", line);
  916.           printf("Version number: `%s'\n", &(line[9]));
  917. #endif
  918.       (void) sscanf(&(line[9]), "%d", &format);
  919.     }
  920.         continue;    /* Comment */
  921.       }
  922.       if (format == 0)
  923.       {
  924.        /*
  925.     * Read old format printrc lines...
  926.     */
  927.  
  928.         initialize_printer(&key);
  929.         lineptr = line;
  930.  
  931.        /*
  932.         * Read the command-delimited printer definition data.  Note that
  933.         * we can't use sscanf because %[^,] fails if the string is empty...
  934.         */
  935.  
  936.         GET_MANDATORY_STRING_PARAM(name);
  937.         GET_MANDATORY_STRING_PARAM(v.output_to);
  938.         GET_MANDATORY_STRING_PARAM(v.driver);
  939.  
  940.         if (! get_printer_by_driver(key.v.driver))
  941.       continue;
  942.  
  943.         GET_MANDATORY_STRING_PARAM(v.ppd_file);
  944.         GET_MANDATORY_INT_PARAM(v.output_type);
  945.         GET_MANDATORY_STRING_PARAM(v.resolution);
  946.         GET_MANDATORY_STRING_PARAM(v.media_size);
  947.         GET_MANDATORY_STRING_PARAM(v.media_type);
  948.  
  949.         GET_OPTIONAL_STRING_PARAM(media_source);
  950.         GET_OPTIONAL_FLOAT_PARAM(brightness);
  951.         GET_OPTIONAL_FLOAT_PARAM(scaling);
  952.         GET_OPTIONAL_INT_PARAM(orientation);
  953.         GET_OPTIONAL_INT_PARAM(left);
  954.         GET_OPTIONAL_INT_PARAM(top);
  955.         GET_OPTIONAL_FLOAT_PARAM(gamma);
  956.         GET_OPTIONAL_FLOAT_PARAM(contrast);
  957.         GET_OPTIONAL_FLOAT_PARAM(cyan);
  958.         GET_OPTIONAL_FLOAT_PARAM(magenta);
  959.         GET_OPTIONAL_FLOAT_PARAM(yellow);
  960.         GET_OPTIONAL_INT_PARAM(linear);
  961.         GET_OPTIONAL_INT_PARAM(image_type);
  962.         GET_OPTIONAL_FLOAT_PARAM(saturation);
  963.         GET_OPTIONAL_FLOAT_PARAM(density);
  964.         GET_OPTIONAL_STRING_PARAM(ink_type);
  965.         GET_OPTIONAL_STRING_PARAM(dither_algorithm);
  966.         GET_OPTIONAL_INT_PARAM(unit);
  967.  
  968. /*
  969.  * The format of the list is the File printer followed by a qsort'ed list
  970.  * of system printers. So, if we want to update the file printer, it is
  971.  * always first in the list, else call psearch.
  972.  */
  973.         if ((strcmp(key.name, _("File")) == 0) && (strcmp(plist[0].name,
  974.          _("File")) == 0))
  975.       {
  976. #ifdef DEBUG
  977.         printf("Updated File printer directly\n");
  978. #endif
  979.         p = &plist[0];
  980.         memcpy(p, &key, sizeof(plist_t));
  981.         p->active = 1;
  982.       }
  983.         else
  984.       {
  985.             if ((p = psearch(&key, plist + 1, plist_count - 1, sizeof(plist_t),
  986.                          (int (*)(const void *, const void *))compare_printers))
  987.             != NULL)
  988.           {
  989. #ifdef DEBUG
  990.             printf("Updating printer %s.\n", key.name);
  991. #endif
  992.             memcpy(p, &key, sizeof(plist_t));
  993.             p->active = 1;
  994.           }
  995.             else
  996.               {
  997. #ifdef DEBUG
  998.                 fprintf(stderr, "Adding new printer from printrc file: %s\n",
  999.                   key.name);
  1000. #endif
  1001.             check_plist(plist_count + 1);
  1002.             p = plist + plist_count;
  1003.             memcpy(p, &key, sizeof(plist_t));
  1004.             p->active = 0;
  1005.             plist_count++;
  1006.           }
  1007.       }
  1008.       }
  1009.       else if (format == 1)
  1010.       {
  1011.        /*
  1012.     * Read new format printrc lines...
  1013.     */
  1014.  
  1015.     char *keyword, *end, *value;
  1016.  
  1017.     keyword = line;
  1018.     for (keyword = line; isspace(*keyword); keyword++)
  1019.     {
  1020.       /* skip initial spaces... */
  1021.     }
  1022.     if (!isalpha(*keyword))
  1023.       continue;
  1024.     for (end = keyword; isalnum(*end) || *end == '-'; end++)
  1025.     {
  1026.       /* find end of keyword... */
  1027.     }
  1028.     value = end;
  1029.     while (isspace(*value)) {
  1030.       /* skip over white space... */
  1031.       value++;
  1032.     }
  1033.     if (*value != ':')
  1034.       continue;
  1035.     value++;
  1036.     *end = '\0';
  1037.     while (isspace(*value)) {
  1038.       /* skip over white space... */
  1039.       value++;
  1040.     }
  1041.     for (end = value; *end && *end != '\n'; end++)
  1042.     {
  1043.       /* find end of line... */
  1044.     }
  1045.     *end = '\0';
  1046. #ifdef DEBUG
  1047.         printf("Keyword = `%s', value = `%s'\n", keyword, value);
  1048. #endif
  1049.     if (strcasecmp("current-printer", keyword) == 0) {
  1050.       if (current_printer)
  1051.         free (current_printer);
  1052.       current_printer = strdup(value);
  1053.     } else if (strcasecmp("printer", keyword) == 0) {
  1054.       /* Switch to printer named VALUE */
  1055.       if (strcmp(_("File"), key.name) == 0
  1056.           && strcmp(plist[0].name, _("File")) == 0)
  1057.       {
  1058.         if (get_printer_by_driver(key.v.driver))
  1059.           {
  1060.         p = &plist[0];
  1061.         memcpy(p, &key, sizeof(plist_t));
  1062.         p->active = 1;
  1063.           }
  1064.       }
  1065.       else
  1066.       {
  1067.         if (get_printer_by_driver(key.v.driver))
  1068.           {
  1069.         p = psearch(&key, plist + 1, plist_count - 1,
  1070.                 sizeof(plist_t),
  1071.                 (int (*)(const void *, const void *)) compare_printers);
  1072.         if (p == NULL)
  1073.           {
  1074.             check_plist(plist_count + 1);
  1075.             p = plist + plist_count;
  1076.             plist_count++;
  1077.             memcpy(p, &key, sizeof(plist_t));
  1078.             p->active = 0;
  1079.           }
  1080.         else
  1081.           {
  1082.             memcpy(p, &key, sizeof(plist_t));
  1083.             p->active = 1;
  1084.           }
  1085.           }
  1086.       }
  1087.       initialize_printer(&key);
  1088.       strncpy(key.name, value, 127);
  1089.     } else if (strcasecmp("destination", keyword) == 0) {
  1090.       strncpy(key.v.output_to, value, 255);
  1091.     } else if (strcasecmp("driver", keyword) == 0) {
  1092.       strncpy(key.v.driver, value, 63);
  1093.     } else if (strcasecmp("ppd-file", keyword) == 0) {
  1094.       strncpy(key.v.ppd_file, value, 256);
  1095.     } else if (strcasecmp("output-type", keyword) == 0) {
  1096.       key.v.output_type = atoi(value);
  1097.     } else if (strcasecmp("resolution", keyword) == 0) {
  1098.       strncpy(key.v.resolution, value, 63);
  1099.     } else if (strcasecmp("media-size", keyword) == 0) {
  1100.       strncpy(key.v.media_size, value, 63);
  1101.     } else if (strcasecmp("media-type", keyword) == 0) {
  1102.       strncpy(key.v.media_type, value, 63);
  1103.     } else if (strcasecmp("media-source", keyword) == 0) {
  1104.       strncpy(key.v.media_source, value, 63);
  1105.     } else if (strcasecmp("brightness", keyword) == 0) {
  1106.       key.v.brightness = atof(value);
  1107.     } else if (strcasecmp("scaling", keyword) == 0) {
  1108.       key.v.scaling = atof(value);
  1109.     } else if (strcasecmp("orientation", keyword) == 0) {
  1110.       key.v.orientation = atoi(value);
  1111.     } else if (strcasecmp("left", keyword) == 0) {
  1112.       key.v.left = atoi(value);
  1113.     } else if (strcasecmp("top", keyword) == 0) {
  1114.       key.v.top = atoi(value);
  1115.     } else if (strcasecmp("gamma", keyword) == 0) {
  1116.       key.v.gamma = atof(value);
  1117.     } else if (strcasecmp("contrast", keyword) == 0) {
  1118.       key.v.contrast = atof(value);
  1119.     } else if (strcasecmp("cyan", keyword) == 0) {
  1120.       key.v.cyan = atof(value);
  1121.     } else if (strcasecmp("magenta", keyword) == 0) {
  1122.       key.v.magenta = atof(value);
  1123.     } else if (strcasecmp("yellow", keyword) == 0) {
  1124.       key.v.yellow = atof(value);
  1125.     } else if (strcasecmp("linear", keyword) == 0) {
  1126.       key.v.linear = atoi(value);
  1127.     } else if (strcasecmp("image-type", keyword) == 0) {
  1128.       key.v.image_type = atoi(value);
  1129.     } else if (strcasecmp("saturation", keyword) == 0) {
  1130.       key.v.saturation = atof(value);
  1131.     } else if (strcasecmp("density", keyword) == 0) {
  1132.       key.v.density = atof(value);
  1133.     } else if (strcasecmp("ink-type", keyword) == 0) {
  1134.       strncpy(key.v.ink_type, value, 63);
  1135.     } else if (strcasecmp("dither-algorithm", keyword) == 0) {
  1136.       strncpy(key.v.dither_algorithm, value, 63);
  1137.     } else if (strcasecmp("unit", keyword) == 0) {
  1138.       key.v.unit = atoi(value);
  1139.     } else {
  1140.       /* Unrecognised keyword; ignore it... */
  1141. #if 1
  1142.           printf("Unrecognised keyword `%s' in printrc; value `%s'\n", keyword, value);
  1143. #endif
  1144.     }
  1145.       }
  1146.       else
  1147.       {
  1148.        /*
  1149.         * We cannot read this file format...
  1150.         */
  1151.       }
  1152.     }
  1153.     if (format > 0)
  1154.       {
  1155.     if (strcmp(_("File"), key.name) == 0
  1156.         && strcmp(plist[0].name, _("File")) == 0)
  1157.       {
  1158.         if (get_printer_by_driver(key.v.driver))
  1159.           {
  1160.         p = &plist[0];
  1161.         memcpy(p, &key, sizeof(plist_t));
  1162.         p->active = 1;
  1163.           }
  1164.       }
  1165.     else
  1166.       {
  1167.         if (get_printer_by_driver(key.v.driver))
  1168.           {
  1169.         p = psearch(&key, plist + 1, plist_count - 1,
  1170.                 sizeof(plist_t),
  1171.                 (int (*)(const void *, const void *)) compare_printers);
  1172.         if (p == NULL)
  1173.           {
  1174.             check_plist(plist_count + 1);
  1175.             p = plist + plist_count;
  1176.             plist_count++;
  1177.             memcpy(p, &key, sizeof(plist_t));
  1178.             p->active = 0;
  1179.           }
  1180.         else
  1181.           {
  1182.             memcpy(p, &key, sizeof(plist_t));
  1183.             p->active = 1;
  1184.           }
  1185.           }
  1186.       }
  1187.       }
  1188.     fclose(fp);
  1189.   }
  1190.  
  1191.   g_free (filename);
  1192.  
  1193.  /*
  1194.   * Select the current printer as necessary...
  1195.   */
  1196.  
  1197.   if (format == 1)
  1198.   {
  1199.     if (current_printer)
  1200.     {
  1201.       for (i = 0; i < plist_count; i ++)
  1202.         if (strcmp(current_printer, plist[i].name) == 0)
  1203.       plist_current = i;
  1204.     }
  1205.   }
  1206.   else
  1207.   {
  1208.     if (vars.output_to[0] != '\0')
  1209.     {
  1210.       for (i = 0; i < plist_count; i ++)
  1211.         if (strcmp(vars.output_to, plist[i].v.output_to) == 0)
  1212.           break;
  1213.  
  1214.       if (i < plist_count)
  1215.         plist_current = i;
  1216.     }
  1217.   }
  1218. }
  1219.  
  1220.  
  1221. /*
  1222.  * 'printrc_save()' - Save the current printer resource configuration.
  1223.  */
  1224. void
  1225. printrc_save(void)
  1226. {
  1227.   FILE        *fp;        /* Printrc file */
  1228.   char           *filename;    /* Printrc filename */
  1229.   int        i;        /* Looping var */
  1230.   plist_t    *p;        /* Current printer */
  1231. #if (GIMP_MINOR_VERSION == 0)
  1232.   char        *home;        /* Home dir */
  1233. #endif
  1234.  
  1235.  
  1236.  /*
  1237.   * Generate the filename for the current user...
  1238.   */
  1239.  
  1240. #if (GIMP_MINOR_VERSION == 0)
  1241.   home = getenv("HOME");
  1242.   if (home == NULL)
  1243.     filename=g_strdup("/.gimp/printrc");
  1244.   else
  1245.     filename = malloc(strlen(home) + 15);
  1246.     sprintf(filename, "%s/.gimp/printrc", home);
  1247. #else
  1248.   filename = gimp_personal_rc_file ("printrc");
  1249. #endif
  1250.  
  1251. #ifdef __EMX__
  1252.   _fnslashify(filename);
  1253. #endif
  1254.  
  1255. #ifndef __EMX__
  1256.   if ((fp = fopen(filename, "w")) != NULL)
  1257. #else
  1258.   if ((fp = fopen(filename, "wt")) != NULL)
  1259. #endif
  1260.   {
  1261.    /*
  1262.     * Write the contents of the printer list...
  1263.     */
  1264.  
  1265. #ifdef DEBUG
  1266.     fprintf(stderr, "Number of printers: %d\n", plist_count);
  1267. #endif
  1268.  
  1269. #if 0
  1270.     fputs("#PRINTRC " PLUG_IN_VERSION "\n", fp);
  1271.  
  1272.     for (i = 0, p = plist; i < plist_count; i ++, p ++)
  1273.       {
  1274.     fprintf(fp, "%s,%s,%s,%s,%d,%s,%s,%s,%s,",
  1275.         p->name, p->v.output_to, p->v.driver, p->v.ppd_file,
  1276.         p->v.output_type, p->v.resolution, p->v.media_size,
  1277.         p->v.media_type, p->v.media_source);
  1278.     fprintf(fp, "%.3f,%.3f,%d,%d,%d,%.3f,",
  1279.         p->v.brightness, p->v.scaling, p->v.orientation, p->v.left,
  1280.         p->v.top, p->v.gamma);
  1281.     fprintf(fp, "%.3f,%.3f,%.3f,%.3f,%d,%d,%.3f,%.3f,%s,%s,%d,\n",
  1282.         p->v.contrast, p->v.cyan, p->v.magenta, p->v.yellow,
  1283.         p->v.linear, p->v.image_type, p->v.saturation, p->v.density,
  1284.         p->v.ink_type, p->v.dither_algorithm, p->v.unit);
  1285.  
  1286. #ifdef DEBUG
  1287.         fprintf(stderr, "Wrote printer %d: %s\n", i, p->name);
  1288. #endif
  1289.  
  1290.       }
  1291. #else
  1292.     fputs("#PRINTRCv1 written by GIMP-PRINT " PLUG_IN_VERSION "\n", fp);
  1293.  
  1294.     fprintf(fp, "Current-Printer: %s\n", plist[plist_current].name);
  1295.  
  1296.     for (i = 0, p = plist; i < plist_count; i ++, p ++)
  1297.       {
  1298.     fprintf(fp, "\nPrinter: %s\n", p->name);
  1299.     fprintf(fp, "Destination: %s\n", p->v.output_to);
  1300.     fprintf(fp, "Driver: %s\n", p->v.driver);
  1301.     fprintf(fp, "PPD-File: %s\n", p->v.ppd_file);
  1302.     fprintf(fp, "Output-Type: %d\n", p->v.output_type);
  1303.     fprintf(fp, "Resolution: %s\n", p->v.resolution);
  1304.     fprintf(fp, "Media-Size: %s\n", p->v.media_size);
  1305.     fprintf(fp, "Media-Type: %s\n", p->v.media_type);
  1306.     fprintf(fp, "Media-Source: %s\n", p->v.media_source);
  1307.     fprintf(fp, "Brightness: %.3f\n", p->v.brightness);
  1308.     fprintf(fp, "Scaling: %.3f\n", p->v.scaling);
  1309.     fprintf(fp, "Orientation: %d\n", p->v.orientation);
  1310.     fprintf(fp, "Left: %d\n", p->v.left);
  1311.     fprintf(fp, "Top: %d\n", p->v.top);
  1312.     fprintf(fp, "Gamma: %.3f\n", p->v.gamma);
  1313.     fprintf(fp, "Contrast: %.3f\n", p->v.contrast);
  1314.     fprintf(fp, "Cyan: %.3f\n", p->v.cyan);
  1315.     fprintf(fp, "Magenta: %.3f\n", p->v.magenta);
  1316.     fprintf(fp, "Yellow: %.3f\n", p->v.yellow);
  1317.     fprintf(fp, "Linear: %d\n", p->v.linear);
  1318.     fprintf(fp, "Image-Type: %d\n", p->v.image_type);
  1319.     fprintf(fp, "Saturation: %.3f\n", p->v.saturation);
  1320.     fprintf(fp, "Density: %.3f\n", p->v.density);
  1321.     fprintf(fp, "Ink-Type: %s\n", p->v.ink_type);
  1322.     fprintf(fp, "Dither-Algorithm: %s\n", p->v.dither_algorithm);
  1323.     fprintf(fp, "Unit: %d\n", p->v.unit);
  1324.  
  1325. #ifdef DEBUG
  1326.         fprintf(stderr, "Wrote printer %d: %s\n", i, p->name);
  1327. #endif
  1328.  
  1329.       }
  1330. #endif
  1331.     fclose(fp);
  1332.   } else {
  1333.     fprintf(stderr,"could not open printrc file \"%s\"\n",filename);
  1334.   }
  1335.   g_free (filename);
  1336. }
  1337.  
  1338.  
  1339. /*
  1340.  * 'compare_printers()' - Compare system printer names for qsort().
  1341.  */
  1342.  
  1343. static int
  1344. compare_printers(plist_t *p1,    /* I - First printer to compare */
  1345.                  plist_t *p2)    /* I - Second printer to compare */
  1346. {
  1347.   return (strcmp(p1->name, p2->name));
  1348. }
  1349.  
  1350.  
  1351. /*
  1352.  * 'get_system_printers()' - Get a complete list of printers from the spooler.
  1353.  */
  1354.  
  1355. #define PRINTERS_NONE    0
  1356. #define PRINTERS_LPC    1
  1357. #define PRINTERS_LPSTAT    2
  1358.  
  1359. static void
  1360. get_system_printers(void)
  1361. {
  1362.   int   i;            /* Looping var */
  1363.   int    type;            /* 0 = none, 1 = lpc, 2 = lpstat */
  1364.   char    command[255];        /* Command to run */
  1365.   char  defname[128];        /* Default printer name */
  1366.   FILE *pfile;            /* Pipe to status command */
  1367.   char  line[255];        /* Line from status command */
  1368.   char    *ptr;            /* Pointer into line */
  1369.   char  name[128];        /* Printer name from status command */
  1370. #ifdef __EMX__
  1371.   BYTE  pnum;
  1372. #endif
  1373.   static char    *lpcs[] =    /* Possible locations of LPC... */
  1374.         {
  1375.           "/etc"
  1376.           "/usr/bsd",
  1377.           "/usr/etc",
  1378.           "/usr/libexec",
  1379.           "/usr/sbin"
  1380.         };
  1381.  
  1382.  
  1383.  /*
  1384.   * Setup defaults...
  1385.   */
  1386.  
  1387.   defname[0] = '\0';
  1388.  
  1389.   check_plist(1);
  1390.   plist_count = 1;
  1391.   initialize_printer(&plist[0]);
  1392.   strcpy(plist[0].name, _("File"));
  1393.   plist[0].v.output_to[0] = '\0';
  1394.   strcpy(plist[0].v.driver, "ps2");
  1395.   plist[0].v.output_type = OUTPUT_COLOR;
  1396.  
  1397.  /*
  1398.   * Figure out what command to run...  We use lpstat if it is available over
  1399.   * lpc since Solaris, CUPS, etc. provide both commands.  No need to list
  1400.   * each printer twice...
  1401.   */
  1402.  
  1403.   if (!access("/usr/bin/lpstat", X_OK))
  1404.   {
  1405.     strcpy(command, "/usr/bin/lpstat -d -p");
  1406.     type = PRINTERS_LPSTAT;
  1407.   }
  1408.   else
  1409.   {
  1410.     for (i = 0; i < (sizeof(lpcs) / sizeof(lpcs[0])); i ++)
  1411.     {
  1412.       sprintf(command, "%s/lpc", lpcs[i]);
  1413.  
  1414.       if (!access(command, X_OK))
  1415.         break;
  1416.     }
  1417.  
  1418.     if (i < (sizeof(lpcs) / sizeof(lpcs[0])))
  1419.     {
  1420.       strcat(command, " status < /dev/null");
  1421.       type = PRINTERS_LPC;
  1422.     }
  1423.     else
  1424.       type = PRINTERS_NONE;
  1425.   }
  1426.  
  1427.  /*
  1428.   * Run the command, if any, to get the available printers...
  1429.   */
  1430.  
  1431.   if (type > PRINTERS_NONE)
  1432.   {
  1433.     if ((pfile = popen(command, "r")) != NULL)
  1434.     {
  1435.      /*
  1436.       * Read input as needed...
  1437.       */
  1438.  
  1439.       while (fgets(line, sizeof(line), pfile) != NULL)
  1440.         switch (type)
  1441.     {
  1442.       case PRINTERS_LPC :
  1443.           if (!strncmp(line, "Press RETURN to continue", 24) &&
  1444.           (ptr = strchr(line, ':')) != NULL &&
  1445.           (strlen(ptr) - 2) < (ptr - line))
  1446.         strcpy(line, ptr + 2);
  1447.  
  1448.           if ((ptr = strchr(line, ':')) != NULL &&
  1449.               line[0] != ' ' && line[0] != '\t')
  1450.               {
  1451.         check_plist(plist_count + 1);
  1452.         *ptr = '\0';
  1453.         initialize_printer(&plist[plist_count]);
  1454.         strncpy(plist[plist_count].name, line, sizeof(plist[0].name) - 1);
  1455.         plist[plist_count].name[sizeof(plist[0].name) - 1] = '\0';
  1456.         sprintf(plist[plist_count].v.output_to, "lpr -P%s -l", line);
  1457.         strcpy(plist[plist_count].v.driver, "ps2");
  1458.         plist_count ++;
  1459.           }
  1460.           break;
  1461.  
  1462.       case PRINTERS_LPSTAT :
  1463.           if ((sscanf(line, "printer %127s", name) == 1) ||
  1464.           (sscanf(line, "Printer: %127s", name) == 1))
  1465.           {
  1466.         check_plist(plist_count + 1);
  1467.         initialize_printer(&plist[plist_count]);
  1468.         strcpy(plist[plist_count].name, name);
  1469.         sprintf(plist[plist_count].v.output_to, "lp -s -d%s -oraw", name);
  1470.             strcpy(plist[plist_count].v.driver, "ps2");
  1471.             plist_count ++;
  1472.           }
  1473.           else
  1474.             sscanf(line, "system default destination: %127s", defname);
  1475.           break;
  1476.     }
  1477.  
  1478.       pclose(pfile);
  1479.     }
  1480.   }
  1481.  
  1482. #ifdef __EMX__
  1483.   if (DosDevConfig(&pnum, DEVINFO_PRINTER) == NO_ERROR)
  1484.     {
  1485.       for (i = 1; i <= pnum; i++)
  1486.     {
  1487.       check_plist(plist_count + 1);
  1488.       initialize_printer(&plist[plist_count]);
  1489.       sprintf(plist[plist_count].name, "LPT%d:", i);
  1490.       sprintf(plist[plist_count].v.output_to, "PRINT /D:LPT%d /B ", i);
  1491.           strcpy(plist[plist_count].v.driver, "ps2");
  1492.           plist_count ++;
  1493.     }
  1494.     }
  1495. #endif
  1496.  
  1497.   if (plist_count > 2)
  1498.     qsort(plist + 1, plist_count - 1, sizeof(plist_t),
  1499.           (int (*)(const void *, const void *))compare_printers);
  1500.  
  1501.   if (defname[0] != '\0' && vars.output_to[0] == '\0')
  1502.   {
  1503.     for (i = 0; i < plist_count; i ++)
  1504.       if (strcmp(defname, plist[i].name) == 0)
  1505.         break;
  1506.  
  1507.     if (i < plist_count)
  1508.       plist_current = i;
  1509.   }
  1510. }
  1511.  
  1512. /*
  1513.  * End of "$Id: print.c,v 1.43 2000/11/18 00:33:39 mitch Exp $".
  1514.  */
  1515.