source: abuse/trunk/src/imlib/readxwd.cpp @ 39

Last change on this file since 39 was 17, checked in by Sam Hocevar, 18 years ago
  • absolute shitloads of 64 bit fixes.
File size: 18.0 KB
Line 
1#include "image.hpp"
2#include "palette.hpp"
3#define MAXCOLORS 256
4//#define MC(x) (((x)<3)==0)
5#define MC(x) (x!=0)
6
7// the following table converts rgb to cym.
8int ca[8]={1,1,1,1,0,0,0,0},
9    ma[8]={1,0,1,0,1,0,1,0},
10    ya[8]={1,1,0,0,1,1,0,0};
11// the following defines make a color threshold
12#define RGB2C(r,g,b) (char)(ca[MC(b)|MC(g)<<1|MC(r)<<2])
13#define RGB2Y(r,g,b) (char)(ya[MC(b)|MC(g)<<1|MC(r)<<2])
14#define RGB2M(r,g,b) (char)(ma[MC(b)|MC(g)<<1|MC(r)<<2])
15
16#define LSBFirst        0
17#define MSBFirst        1
18
19#define XYBitmap        0
20#define XYPixmap        1
21#define ZPixmap         2
22
23#define StaticGray      0
24#define GrayScale       1
25#define StaticColor     2
26#define PseudoColor     3
27#define TrueColor       4
28#define DirectColor     5
29
30typedef unsigned long xwdval;
31#define X11WD_FILE_VERSION 7
32typedef struct {
33    xwdval header_size;         /* Size of the entire file header (bytes). */
34    xwdval file_version;        /* X11WD_FILE_VERSION */
35    xwdval pixmap_format;       /* Pixmap format */
36    xwdval pixmap_depth;        /* Pixmap depth */
37    xwdval pixmap_width;        /* Pixmap width */
38    xwdval pixmap_height;       /* Pixmap height */
39    xwdval xoffset;             /* Bitmap x offset */
40    xwdval byte_order;          /* MSBFirst, LSBFirst */
41    xwdval bitmap_unit;         /* Bitmap unit */
42    xwdval bitmap_bit_order;    /* MSBFirst, LSBFirst */
43    xwdval bitmap_pad;          /* Bitmap scanline pad */
44    xwdval bits_per_pixel;      /* Bits per pixel */
45    xwdval bytes_per_line;      /* Bytes per scanline */
46    xwdval visual_class;        /* Class of colormap */
47    xwdval red_mask;            /* Z red mask */
48    xwdval green_mask;          /* Z green mask */
49    xwdval blue_mask;           /* Z blue mask */
50    xwdval bits_per_rgb;        /* Log base 2 of distinct color values */
51    xwdval colormap_entries;    /* Number of entries in colormap */
52    xwdval ncolors;             /* Number of Color structures */
53    xwdval window_width;        /* Window width */
54    xwdval window_height;       /* Window height */
55    long window_x;              /* Window upper left X coordinate */
56    long window_y;              /* Window upper left Y coordinate */
57    xwdval window_bdrwidth;     /* Window border width */
58    } X11WDFileHeader;
59
60typedef struct {
61    unsigned long pixel;
62    unsigned short red, green, blue;
63    char flags;                 /* do_red, do_green, do_blue */
64    char pad;
65    } X11XColor;
66
67image *getinit(FILE *file, palette *&pal, int *padrightP);
68void getimage(FILE *file,image *image, int pad);
69int getpixnum(FILE *file);
70
71
72HBITMAP readxwd(char *input_file,palette *&pal)
73//char *hdfpal,int *palsize,int *cols,int *rows)
74{
75  FILE *ifd;
76  char *imageP;
77  unsigned int nspace;
78  int padright;
79  HBITMAP im;
80
81  /* open input file */
82  if (strcmp(input_file,"-") == 0)
83    ifd = stdin;d)
84  { printf("Unable to open %s\n"
85           "Get your story right and try again.\n",input_file);
86    exit(0);
87  }
88  printf("Reading image\n");
89  im=getinit( ifd, pal, &padright, int &xres, int &yres);
90//cols, rows, &padright, palsize, hdfpal);
91
92  /* alloc image array */
93
94  /* fill image array */
95  getimage(ifd, im, padright);
96
97  return(im);
98}
99
100int bits_per_item, bits_used, bit_shift, bits_per_pixel, pixel_mask;
101int bit_order, byte_swap;
102char buf[4];
103char *byteP;
104short *shortP;
105long *longP;
106
107
108int32_t bs_int32(int32_t s);
109int16_t bs_int16(int16_t s );
110
111
112HBITMAP getinit(FILE *file, palette *&pal, int *padrightP, int &xres, int &yres);)
113{
114  /* Assume X11 headers are larger than X10 ones. */
115  unsigned char header[sizeof(X11WDFileHeader)];
116  image *im;
117  X11WDFileHeader *h11P;
118  char junk[800];
119  int i, np, dummy1, dummy2, dummy3;
120  unsigned  short minred, maxred;
121  X11XColor x11col;
122
123  h11P = (X11WDFileHeader *) header;
124
125  if (fread(header,sizeof(*h11P),1,file) != 1 )
126    {
127      fprintf(stderr,"couldn't read X11 XWD file header");
128      exit(-1);
129    }
130  if ( h11P->file_version != X11WD_FILE_VERSION )
131    {
132      byte_swap = 1;
133      h11P->header_size = bltl(h11P->header_size);
134      h11P->file_version = bltl(h11P->file_version);
135      h11P->pixmap_format = bltl(h11P->pixmap_format);
136      h11P->pixmap_depth = bltl(h11P->pixmap_depth);
137      h11P->pixmap_width = bltl(h11P->pixmap_width);
138      h11P->pixmap_height = bltl(h11P->pixmap_height);
139      h11P->xoffset =  bltl(h11P->xoffset);
140      h11P->byte_order =  bltl(h11P->byte_order);
141      h11P->bitmap_unit = bltl(h11P->bitmap_unit);
142      h11P->bitmap_bit_order = bltl(h11P->bitmap_bit_order);
143      h11P->bitmap_pad = bltl(h11P->bitmap_pad);
144      h11P->bits_per_pixel = bltl(h11P->bits_per_pixel);
145      h11P->bytes_per_line = bltl(h11P->bytes_per_line);
146      h11P->visual_class = bltl(h11P->visual_class);
147      h11P->red_mask = bltl(h11P->red_mask);
148      h11P->green_mask = bltl(h11P->green_mask);
149      h11P->blue_mask = bltl(h11P->blue_mask);
150      h11P->bits_per_rgb = bltl(h11P->bits_per_rgb);
151      h11P->colormap_entries = bltl(h11P->colormap_entries);
152      h11P->ncolors = bltl(h11P->ncolors);
153      h11P->window_width = bltl(h11P->window_width);
154      h11P->window_height = bltl(h11P->window_height);
155      h11P->window_x = bltl(h11P->window_x);
156      h11P->window_y = bltl(h11P->window_y);
157      h11P->window_bdrwidth = bltl(h11P->window_bdrwidth);
158    }
159
160  if ( fread( junk, 1, h11P->header_size - sizeof(*h11P), file ) !=
161      h11P->header_size - sizeof(*h11P) )
162    {
163      fprintf(stderr,"couldn't read rest of X11 XWD file header");
164      exit(-1);
165    }
166
167  /* Check whether we can handle this dump. */
168  if ( h11P->pixmap_depth > 8 )
169    {
170      fprintf(stderr,"can't handle X11 pixmap_depth > 8");
171      exit(-1);
172    }
173  if ( h11P->bits_per_rgb > 8 )
174    {
175      fprintf(stderr,"can't handle X11 bits_per_rgb > 8");
176      exit(-1);
177    }
178  if ( h11P->ncolors > MAXCOLORS )
179    {
180      fprintf(stderr,"can't handle X11 ncolors > %d");
181      exit(-1);
182    }
183  if ( h11P->pixmap_format != ZPixmap )
184    {
185      fprintf(stderr,"can't handle X11 pixmap_format %d", h11P->pixmap_format,
186              0,0,0,0 );
187      exit(-1);
188    }
189  if ( h11P->bitmap_unit != 8 && h11P->bitmap_unit != 16 &&
190      h11P->bitmap_unit != 32 )
191    {
192      fprintf(stderr,"X11 bitmap_unit (%d) is non-standard - can't handle");
193      exit(-1);
194    }
195  xres=h11P->pixmap_width;
196  yres=h11P->pixmap_height;
197  im=new image(h11P->pixmap_width,h11P->pixmap_height);
198  pal=new palette(h11P->colormap_entries);
199  *padrightP = h11P->bytes_per_line * 8 / h11P->bits_per_pixel - im->width();
200
201/*****************************************************************************/
202  /* Read X11 colormap. */
203minred = 65535;
204maxred = 0;
205  for ( i = 0; i < h11P->colormap_entries; i++ )
206    {
207      if ( fread( &x11col, sizeof(X11XColor), 1, file ) != 1 )
208        {
209          fprintf(stderr,"couldn't read X11 XWD colormap");
210          exit(-1);
211        }
212        else
213        {
214          x11col.pixel=bltl(x11col.pixel);
215          x11col.red=bstl(x11col.red);
216          x11col.green=bstl(x11col.green);
217          x11col.blue=bstl(x11col.blue);
218        }
219      if (x11col.pixel < 256)
220        {
221          if (minred > x11col.red) minred = x11col.red;
222          if (maxred < x11col.red) maxred = x11col.red;
223          dummy1 = (unsigned) x11col.red / 256 ;
224          dummy2 = (unsigned) x11col.green / 256 ;
225          dummy3 = (unsigned) x11col.blue / 256 ;
226          pal->set(i,dummy1,dummy2,dummy3);
227        }
228      else
229        {
230          fprintf(stderr,"pixel value outside of valid HDF palette\n");
231          exit(-1);
232        }
233    }
234  /* rest of stuff for getpixnum */
235  bits_per_item = h11P->bitmap_unit;
236  bits_used = bits_per_item;
237  bits_per_pixel = h11P->bits_per_pixel;
238  bit_order = h11P->bitmap_bit_order;
239  pixel_mask = ( 1 << bits_per_pixel ) - 1;
240
241  byteP = (char *) buf;
242  shortP = (short *) buf;
243  longP = (long *) buf;
244  return im;
245}
246
247void getimage(FILE *file,HBITMAP &im.int pad)
248{
249  int i,j;
250  unsigned char *sl;
251  for (i=0; i<im->height(); i++)
252    {
253      if (i%50==0)
254        printf("Line %d of %d\n",i+1,im->height());
255      sl=im->scan_line(i);
256      for (j=0; j<im->width(); j++)
257        sl[j]= getpixnum(file);
258
259      for ( j = 0; j < pad; j++ )
260        getpixnum( file );
261    }
262}
263
264
265int getpixnum(FILE *file)
266{
267  int p;
268
269  if ( bits_used == bits_per_item )
270    {
271      if ( fread( buf, bits_per_item / 8, 1, file ) != 1 )
272        fprintf(stderr, "couldn't read bits" );
273      if ( byte_swap )
274        switch ( bits_per_item )
275          {
276          case 8:
277            break;
278
279          case 16:
280            *shortP = bstl(*shortP) ;
281            break;
282
283          case 32:
284            *longP = bltl(*longP) ;
285            break;
286
287          default:
288            fprintf(stderr, "can't happen" );
289          }
290      bits_used = 0;
291
292//      if ( bit_order == MSBFirst )
293        bit_shift = bits_per_item - bits_per_pixel;
294//      else
295//      bit_shift = 0;
296    }
297
298  switch ( bits_per_item )
299    {
300    case 8:
301      p = ( *byteP >> bit_shift) & pixel_mask;
302      break;
303
304    case 16:
305      p = ( *shortP >> bit_shift) & pixel_mask;
306      break;
307
308    case 32:
309      p = ( *longP >> bit_shift) & pixel_mask;
310      break;
311
312    default:
313      fprintf(stderr, "can't happen" );
314    }
315
316//  if ( bit_order == MSBFirst )
317    bit_shift -= bits_per_pixel;
318//  else
319//    bit_shift += bits_per_pixel;
320  bits_used += bits_per_pixel;
321
322  return p;
323}
324
325
326short bs_int16(short s )
327{
328  short ss;
329  unsigned char *bp, t;
330
331  ss = s;
332  bp = (unsigned char *) &ss;
333  t = bp[0];
334  bp[0] = bp[1];
335  bp[1] = t;
336  return ss;
337}
338
339int32_t bs_int32(int32_t l )
340{
341  int32_t ii;
342  uint8_t *bp, t;
343
344  ii = i;
345  bp = (uint8_t *) &ii;
346  t = bp[0];
347  bp[0] = bp[3];
348  bp[3] = t;
349  t = bp[1];
350  bp[1] = bp[2];
351  bp[2] = t;
352  return ii;
353}
354
355struct BMP_header
356{
357  char id[2];
358  long filesize;
359  int reserved[2];
360  long headersize,infosize,width,height;
361  int biplanes,bits;
362  long bicompression, bisizeimage, bixpelspermeter, biypelspermeter,
363       biclrused,biclrimportant;
364} bmp;
365
366void write_bmp(image *im, palette *pal, char *filename)
367{
368  FILE *fp;
369  int i,bytes;
370  uint8_t pal_quad[4];
371//  fp=fopen("d:\\windows\\256color.bmp","rb");
372//  fread(&bmp,1,sizeof(bmp),fp);
373//  fclose(fp);
374  fp=fopen(filename,"wb");
375  if (!fp)
376  { printf("Error : unable to open %s for writing!\n");
377    exit(0);
378  }
379  bytes=(im->width()+3)/4;
380  memset((char *)&bmp,0,sizeof(bmp));
381  memcpy(bmp.id,"BM",2);
382  bmp.width=im->width();
383  bmp.height=im->height();
384  bmp.bits=8;
385  bmp.infosize=0x28L;
386  bmp.biplanes=1;
387  bmp.headersize=1078;
388  bmp.filesize=bmp.headersize+bytes*im->height()*4;
389  bmp.bisizeimage=im->width()*im->height();
390  bmp.biclrused=256;
391  bmp.biclrimportant=256;
392  fwrite(&bmp,1,sizeof(bmp),fp);
393  pal_quad[3]=0;
394  for (i=0;i<256;i++)
395  {
396    pal->get(i,pal_quad[2],pal_quad[1],pal_quad[0]);
397    fwrite(pal_quad,1,4,fp);
398  }
399  for (i=im->height();i;i--)
400    fwrite(im->scan_line(i-1),1,bytes*4,fp);
401  fclose(fp);
402}
403
404image *image24(image *im, palette *pal, int rev)
405{
406  image *ni;
407  uint8_t *sl1,*sl2;
408  int i,x;
409  uint8_t r,g,b;
410  printf("Creating image size (%d, %d)\n",im->width()*3,im->height());
411  ni=new image(im->width()*3,im->height());
412  printf("Image created\n");
413  for (i=0;i<im->height();i++)
414  {
415    if (i%50==0)
416      printf("Line %d of %d\n",i+1,im->height());
417
418    sl1=   sl2[x*3]=r; sl2[x*3+1]=g; sl2[x*3+2]=b;
419    }
420    im->set_page_swapable();
421  }
422  return ni;
423}
424
425uint8_t addb(int n1, int n2)
426{ int n3;
427  n3=n1+n2;
428  return n3>255 ? 255 : (n3<0 ? 0 : n3);
429}
430
431// this function takes an image min 8 bit format, converts it to 24 bit
432// color and dithers it so that it can be printed on an deskjet
433/// (i.e it reduces it down to 8 colors)
434image *color_dither(image *im, palette *pal, int rev)
435{
436  image *i24;
437  uint8_t min[3],max[3],mid[3],*ad,*sl,*sl2,crimp;
438  int i,j,x,y,delta;
439  (void *)ad=pal->addr();
440
441  // find the minimum and maximum  red green and blue in the image
442  memset(min,0xff,3); memset(max,0,3);
443  for (j=0;j<3;j++,ad++)
444    for (y=0;y<im->height();y++)
445    { sl2=im->scan_line(y);
446      for (x=0;x<im->width();x++)
447      {
448        if (ad[sl2[x]*3]<min[j]) min[j]=ad[i*3];
449        if (ad[sl2[x]*3]>max[j]) max[j]=ad[i*3];
450      }
451    }
452  // find the middle color used for red green and blue
453  for (i=0;i<3;i++)
454    mid[i]=(int)((int)max[i]+(int)min[i])/2;
455  // convert the image to 24 bit color.
456  printf("Converting to 24 bit color...\n");
457  i24=image24(im,pal,rev);
458  printf("Dithering using flyod stienberg algorithm\n");
459  for (y=0;y<im->height();y++)
460  { if (y%20==0)
461      printf("Line %d of %d\n",y+1,im->height());
462    sl=i24->scan_line(y);
463    i24->set_page_unswapable();
464
465    if (y+1<im->height())
466      sl2=i24->scan_line(y+1);  // get the scan line below this one
467    for (x=0;x<im->width();x++)
468    {
469      // diffuse the colors using flyod stienburg dithering algorithm
470      for (j=0;j<3;j++)
471      {
472        crimp = sl[x*3+j]>mid[j] ? 255 : 0;
473        delta=sl[x*3+j]-crimp;
474        sl[x*3+j]=crimp;
475        if (x+1<im->width())
476        { sl[(x+1)*3+j]=addb(sl[(x+1)*3+j],delta*7/16);
477          if (y+1<im->height())
478            sl2[(x+1)*3+j]=addb(sl2[(x+1)*3+j],delta*1/16);
479        }
480        if (y+1<im->height())
481        { if (x>0)
482            sl2[(x-1)*3+j]=addb(sl2[(x-1)*3+j],delta*3/16);
483          sl2[(x)*3+j]=addb(sl2[(x)*3+j],delta*5/16);
484        }
485      }
486    }
487    sl=i24->scan_line(y);
488    i24->set_page_swapable();
489
490  }
491  return i24;
492}
493
494image *rotate90(image *im)
495{
496  image *i;
497  int x,y,w,h;
498  w=im->width();
499  h=im->height();
500  printf("Rotating image 90 deg\n");
501  i=new image(im->height(),im->width());
502  for (x=0;x<w;x++)
503  {
504    if (x%20==0)
505      printf("Row %d of %d\n",x,im->width());
506    for (y=0;y<h;y++)
507      i->putpixel(y,w-x-1,im->pixel(x,y));
508  }
509  return i;
510}
511
512void deskjet_print(int argc, char **argv)
513{
514  int i,dpi=100;
515  int y,x,byteo,bito,outc,outy,outm,outcv, outyv,outmv, w,rev,inten,val,
516      display=0,bad=0,bmp=0,land=0,ch,xo=0,yo=0;
517  image *im,*i24;
518  palette *pal;
519  uint8_t *sl;
520  FILE *fp;
521  char def_name[10],*dev_name,*fname=NULL;
522  uint8_t cp[500],mp[500],yp[500],kp[500];
523  strcpy(def_name,"\\dev\\lp");  // set the default output device to /dev/lp
524                // since we are in vpix, however we will use the backslash
525  dev_name=def_name; rev=0;
526  for (i=1;i<argc;i++)
527    if (!strcmp(argv[i],"-dpi"))
528    { i++; dpi=atoi(argv[i]);
529      if (dpi!=75 && dpi!=100 && dpi!=150 && dpi!=300) bad=1; }
530    else if (!strcmp(argv[i],"-dev"))
531    { i++; dev_name=argv[i]; }
532    else if (!strcmp(argv[i],"-rev"))
533    { rev=1; }
534    else if (!strcmp(argv[i],"-land"))
535    { land=1; }
536    else if (!strcmp(argv[i],"-2bmp"))
537    { bmp=1; }
538    else if (!strcmp(argv[i],"-display"))
539    { display=1; }
540    else fname=argv[i];
541
542  if (!fname || bad)
543  { printf("usage : %s [-dev device] [-dpi 75,100,150,300]\n"
544           "     [-rev] [-display] [-2bmp] [-land] filename\n\n"
545           "  default dpi is 100 (possible are 75/100/150/300)\n"
546           "  default printer is /dev/lp\n"
547           "  -rev, reverse black and white on the print out\n"
548           "  -display only displays the image to the screen and does not print it\n"
549           "    all ither options will be ignored\n"
550           "  -2bmp converts the image X window dump to a MicroSoft Windows bitmap (BMP)\n"
551           "    the file written to must be specified by -dev [filename]\n"
552           "    all other options will be ignored\n"
553           "  -land prints the image in landscape mode (sideways)\n"
554           "  filename is the name of the dump created by xwd\n"
555           "  Using Dos, the command [%s -dev lpt1] should be used\n",argv[0],argv[0]);
556    exit(0);
557  }
558  im=readxwd(fname,pal);
559  if (!im || !pal)
560  { printf("failed to read the image or the palette!\n");
561    exit(0);
562  }
563  if (display)
564  {
565    set_mode(19,argc,argv);
566    pal->load();                         // set the palette for the image we are going to print
567    im->put_image(screen,0,0);          // put the image on thge söööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööö<0) yo+=10; break;
568      }
569    } while (ch!=' ' && ch!='q' && ch!=13);
570    close_graphics();
571  }
572  else if (bmp)
573    write_bmp(im,pal,dev_name);
574  else
575  {
576    fp=fopen(dev_name,"wb");  // open the output device for printing
577    if (!fp)
578    { printf("Unable to open %s for writing, make sure the path exsist and you\n"
579             "have write permission to the file\n",dev_name);
580      exit(0);
581    }
582    if (land)
583      im=rotate90(im);
584
585    w=im->width()+7; w/=8; w*=8;
586    fprintf(fp,"E"           // reset the printer
587               "&l%dO"      // portrait/landscape mode
588               "*rbC"        // reset graphics
589               "*t%dR"        // set the resolution
590               "*r%dS"       // set the image width
591               "*r1A"        // start raster graphics at left edge
592               "*r-4U"         // set to CYM mode
593               ,land,dpi,w);
594  // now loop through all the scan lines of the image and pcik out the planes
595  // we need
596    i24=color_dither(im,pal,rev);
597    rev=0;  // turn off the revser option because the conversion to 24 bit takes care of it
598    printf("Printing...");
599    for (y=0;y<im->height();y++)
600    {
601      if (y%20==0)
602        printf(".");
603
604      sl=i24->scan_line(y);
605  //initally set all the planes to clear, this should leave the paper white
606      memset(cp,0,500);  memset(mp,0,500);  memset(yp,0,500); memset(kp,0,500);
607  // now scan through the cyan plane of this scan line and pick out the bits
608      for (x=0,bito=7;x<im->width();x++)
609      {
610        outcv=RGB2C(sl[x*3],sl[x*3+1],sl[x*3+2]);
611        outyv=RGB2Y(sl[x*3],sl[x*3+1],sl[x*3+2]);
612        outmv=RGB2M(sl[x*3],sl[x*3+1],sl[x*3+2]);
613        if (outcv==outyv && outyv==outmv)
614        {
615          if ((rev && !outcv) || (!rev && outcv))
616            kp[x/8]^=(1<<bito);
617        } else
618        {
619          cp[x/8]^=(outcv<<bito);
620          yp[x/8]^=(outyv<<bito);
621          mp[x/8]^=(outmv<<bito);
622        }
623        if ((bito--)==0)
624          bito=7;
625      }
626      fprintf(fp,"%c*b%dV",27,w/8);  // print out the black plane first
627      fwrite(kp,1,w/8,fp);
628      fprintf(fp,"%c*b%dV",27,w/8);  // now the cyan plane
629      fwrite(cp,1,w/8,fp);
630      fprintf(fp,"%c*b%dV",27,w/8);  // now the yellow plane
631      fwrite(yp,1,w/8,fp);
632      fprintf(fp,"%c*b%dW",27,w/8);  // now the magenta plane
633      fwrite(mp,1,w/8,fp);
634    }
635    fprintf(fp,"%c*rbC%c",27,12);  // end graphics, switch everthing back to defaults
636                                   // and print a form feed to eject the paper.
637    fclose(fp); // flush out anything in the buffers and close the file
638    delete i24;  // clean up the memory that we allocated to the image and the palette
639  }
640  printf("\n");
641  delete im;
642  delete pal;
643}
644
645main(int argc, char **argv)
646{
647  setcbrk(1);  // set the control break on, so that printing can be interrupted
648  deskjet_print(argc,argv);
Note: See TracBrowser for help on using the repository browser.