Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
getx11.c
Go to the documentation of this file.
1 /*
2  * This software is copyrighted as noted below. It may be freely copied,
3  * modified, and redistributed, provided that the copyright notices are
4  * preserved on all copies.
5  *
6  * There is no warranty or other guarantee of fitness for this software,
7  * it is provided solely "as is". Bug reports or fixes may be sent
8  * to the author, who may or may not act on them as he desires.
9  *
10  * You may not include this software in a program or other software product
11  * without supplying the source, or without informing the end-user that the
12  * source is available for no extra charge.
13  *
14  * If you modify this software, you should include a notice giving the
15  * name of the person performing the modification, the date of modification,
16  * and the reason for such modification.
17  */
18 
19 /*
20  * getx11.c - Put RLE images on X display.
21  *
22  * Author: Spencer W. Thomas (x10)
23  * Computer Science Dept.
24  * University of Utah
25  * Date: Thu Feb 20 1986
26  * Copyright (c) 1986, University of Utah
27  *
28  * Modified: Andrew F. Vesper (x 11)
29  * High Performance Workstations
30  * Digital Equipment Corp
31  * Date: Fri, Aug 7, 1987
32  * Thu, Jan 14, 1988
33  * Copyright (c) 1987,1988, Digital Equipment Corporation
34  *
35  * Modified: Martin R. Friedmann (better X11, flipbook, mag, pix_info)
36  * Dept of Electrical Engineering and Computer Science
37  * University of Michigan
38  * Date: Tue, Nov 14, 1989
39  * Copyright (c) 1989, University of Michigan
40  */
41 
42 #include <unistd.h>
43 #include "getx11.h"
44 
45 /* Make Sys V macros map to BSD macros */
46 #ifndef _tolower
47 #define _tolower tolower
48 #define _toupper toupper
49 #endif
50 
51 
52 /* must be able to fit 3 * log2 (MAXIMUM_LEVELS) bits in a 32 bit word */
53 
54 #define DEFAULT_LEVELS 240
55 #define MAXIMUM_LEVELS 1024
56 
57 static int get_pic ();
58 static void update_pic();
59 
60 /*
61  * Global variables
62  */
63 
64 double display_gamma = 2.5; /* default gamma for display */
65 int iflag = 0;
73 
74 char *progname = NULL;
75 Display *dpy = NULL;
76 Window root_window = NULL;
77 int screen = 0;
78 
79 Boolean debug_flag = False; /* set if debug mode -D */
80 Boolean verbose_flag = False; /* set if verbose mode -v */
81 int jump_flag = 0, jump_scans = 0, stingy_flag = 0;
83 #ifdef X_SHARED_MEMORY
87 #endif
88 Boolean no_color_ref_counts; /* X11/NeWS 2.0 server BUG */
89 
90 static struct {
91  CONST_DECL char *string;
92  int type;
93 } visual_type_table[] = {
94 
95 { "staticgray", StaticGray},
96 { "grayscale", GrayScale},
97 { "staticgrey", StaticGray},
98 { "greyscale", GrayScale},
99 { "staticcolor", StaticColor},
100 { "pseudocolor", PseudoColor},
101 { "truecolor", TrueColor},
102 { "directcolor", DirectColor}
103 };
104 
105 
106 image_information *img_info = NULL;
108 image_information *i;
109 {
110  i->window = i->icn_window = NULL;
111  i->pixmap = i->icn_pixmap = NULL;
112  i->pix_info_window = NULL;
113  i->gc = i->icn_gc = NULL;
114  i->image = i->icn_image = NULL;
115  i->colormap = NULL;
116  i->visual_class = -1;
117  i->pixmap_failed = False;
118 
119  i->filename = NULL;
120  i->img_num = 0;
121  i->title = NULL;
122  i->fd = stdin;
123  i->img_channels = 0;
124  i->dpy_channels = 0;
125  i->scan_data = NULL;
126  i->map_scanline = NULL;
127  i->MAG_scanline = NULL;
128  i->gamma = 0.0;
129 
130  i->x = i->y = 0;
131  i->xo = i->yo = 0;
132  i->w = i->h = 0;
133  i->win_w = i->win_h = 0;
134  i->icn_w = i->icn_h = 0;
135  i->pix_w = i->pix_h = 0;
136  i->icn_factor = 1;
137 
138  i->pan_x = i->pan_x = 0;
139  i->pan_w = i->pan_h = 0;
140  i->mag_fact = 1;
141  i->save_mag_fact = 1;
142  i->mag_mode = False;
143 
144  i->binary_img = False;
145  i->dither_img = False;
146  i->mono_img = False;
147  i->rw_cmap = False;
148  i->sep_colors = False;
149  i->mono_color = False;
150  i->color_dpy = True;
151 
152  i->in_cmap = NULL;
153  i->ncmap = 0;
154  i->cmlen = 0;
155  i->modN = NULL;
156  i->divN = NULL;
157  i->dm16 = NULL;
158  i->pixel_table = NULL;
161  i->x_cmap.pixel_base = 0;
162  i->black_pixel = 0;
163  i->white_pixel = 1;
164 #ifdef X_SHARED_MEMORY
165  i->shm_img.shmid = -1;
166  i->shm_pix.shmid = -1;
167 #endif
168 }
169 
170 
171 /*****************************************************************
172  * TAG( main )
173  *
174  * usage : getx11 [-= window-geometry] [-a] [-d display] [-D] [-f] [-T]
175  * [-g gamma] [-{iI} gamma] [-j [jump-scans]]
176  * [-m [maxframes/sec]] [-n levels]
177  * [-s] [-t title] [-v] [-{wW}] [-x visual] [file ...]
178  * Inputs:
179  * -f: Dont fork after putting image on screen.
180  * -D: Debug mode: print input file as read.
181  * -W: bitonal; binary black and white
182  * -w: Black & white: reduce color images to monochrome before
183  * display. Advantage is that smoother shading can
184  * be achieved.
185  * -v: Print verbose window type information.
186  * -d display: Specify display name.
187  * -= window_geometry:
188  * Specify window geometry (but min size set by file).
189  * -i gamma: Specify gamma of image. (default 1.0)
190  * -I gamma: Specify gamma of display image was computed for.
191  * -g gamma: Specify gamma of display. (default 2.5)
192  * -x vis_type: Specify visual type to be used (string or int, 0 to 5)
193  * -n levels: number of levels to display of each color
194  * -a: Do not dither
195  * -s: Be stingy about memory/pixmap usage.
196  * -S: Don't share memory, even if it can.
197  * -j: Display every jump-scans scanlines.
198  * -m: Use movie mode. flip_book frames per second
199  * -T: Use TV mode... (like movie mode but no playback)
200  *
201  * file: Input Run Length Encoded file. Uses stdin if not
202  * specified.
203  *
204  * getx11 will also read picture comments from the input file to determine
205  * the image gamma. These are
206  *
207  * image_gamma= gamma of image (equivalent to -i)
208  * display_gamma= gamma of display image was computed for.
209  * image_title= title to name images X window.
210  * title = same...
211  *
212  * Any command line arguments override the values in the file.
213  *
214  * Outputs:
215  * Puts image on X11 screen.
216  * Assumptions:
217  * Input file is in RLE format.
218  * Algorithm:
219  * [None]
220  */
221 
222 void
224 int argc;
225 char ** argv;
226 {
227  char ** infnames = NULL;
228  char * display_name = NULL;
229  char * window_geometry = NULL;
230  int n_malloced, num_imgs = 0, using_stdin;
231  int levels;
232  int nfile = 0, forkflg = 0, dflag = 0, gflag = 0, wflag = 0;
233  int vflag = 0, aflag = 0, bin_flag = 0, mono_flag = 0;
234  int quit_flag = 0, tflag = 0, TVflag = 0;
235  int flip_book = 0;
236  int flip_book_frams_sec = 30;
237  int sharing_flag = False;
238  int tv_delay = 0;
239  char *tv_command = NULL;
240  char *vis_type = NULL, *title_string = NULL;
241  int visual_type = -1;
242  int status, done = 0, rle_cnt = -1;
243  image_information *img, *previous_img;
244  double image_gamma = 0.0; /* default gamma for image */
245 
246  progname = argv[0];
247 
248  if ( scanargs( argc, argv,
249  "% =%-window-geometry!s a%- d%-display!s D%- f%- \n\
250  g%-gamma!F iI%-gamma!F j%-jump-scans%d m%-maxframes/sec%d n%-levels!d \n\
251  q%- s%- S%- t%-title!s T%-delay%dcommand%s v%- wW%- x%-visual!s file%*s",
252  &wflag, &window_geometry,
253  &aflag,
254  &dflag, &display_name,
255  &debug_flag,
256  &forkflg,
257  &gflag, &display_gamma,
258  &iflag, &image_gamma,
260  &flip_book, &flip_book_frams_sec,
262  &quit_flag,
263  &stingy_flag,
264  &sharing_flag,
265  &tflag, &title_string,
266  &TVflag, &tv_delay, &tv_command,
268  &bin_flag,
269  &vflag, &vis_type,
270  &nfile, &infnames ) == 0 )
271  exit(1);
272 
273  if (TVflag && flip_book) {
274  fprintf(stderr, "%s: -T and -m cannot be used together\n", progname);
275  exit(1);
276  }
277 
278  /* -S means don't share */
279 #ifdef X_SHARED_MEMORY
280  if ( !sharing_flag )
281  do_sharing = False;
282 #endif
283 
284  /* Check for -w instead of -W. */
285  if ( bin_flag == 2 )
286  {
287  bin_flag = 0;
288  mono_flag = 1;
289  }
290 
291  using_stdin = ( nfile ? False : True );
292  n_malloced = ( using_stdin ? 1 : nfile );
293 
294  img_info = (image_information *)malloc(n_malloced *
295  sizeof(image_information) );
296 
297  if ( img_info == NULL ){
298  perror("malloc returned NULL");
299  exit (1);
300  }
301 
302  if ( vflag != 0) {
303  if (isdigit (vis_type[0]) ) {
304  visual_type = atoi (vis_type);
305  }
306  else {
307  register char *ptr;
308  register int i;
309  visual_type = 9999;
310 
311  for (ptr = vis_type; *ptr != '\0'; ptr++) {
312  if (isupper(*ptr)) *ptr = _tolower(*ptr);
313  }
314 
315  for (i = 0; i < COUNT_OF (visual_type_table); i++) {
316  if (strcmp (visual_type_table[i].string, vis_type) == 0) {
317  visual_type = visual_type_table[i].type;
318  break;
319  }
320  }
321  }
322 
323  if ( visual_type < 0 || visual_type > 5 ) {
324  fprintf ( stderr, "Bad visual type %s, ignoring request\n",
325  vis_type);
326  visual_type = -1;
327  }
328  }
329 
330  levels = specified_levels;
331  if (levels == 0) levels = DEFAULT_LEVELS; /* default starting point */
332  if (levels > MAXIMUM_LEVELS) levels = MAXIMUM_LEVELS;
333 
334  /*
335  * open the display
336  */
337 
338  open_x_display ( display_name );
339 
340  /*
341  * For each file, display it.
342  */
343 
344  do {
345  /* get more space, but in TV mode get only two img_infos */
346  if ( num_imgs >= n_malloced && (! TVflag || num_imgs == 1) )
347  img_info = (image_information *)
348  realloc( img_info,
349  ++n_malloced * sizeof(image_information) );
350  if ( img_info == 0 )
351  {
352  fprintf(stderr, "%s: Out of memory!\n", progname);
353  exit( RLE_NO_SPACE );
354  }
355  if ( TVflag && num_imgs > 0 )
356  img = &img_info[1];
357  else
358  img = &img_info[num_imgs];
359 
360  init_img_info( img );
361 
362  /* we need pixmaps for movie mode... */
363  if ( stingy_flag && !flip_book )
364  img_info[0].pixmap_failed = True;
365 
366  if ( iflag == 2 && image_gamma != 0.0 ) img->gamma = 1.0 / image_gamma;
367  else if ( iflag == 1 ) img->gamma = image_gamma;
368 
369  img->binary_img = ( bin_flag ? True : False );
370  img->mono_img = ( mono_flag || bin_flag ? True : False );
371  if ( img->mono_img )
372  img->color_dpy = False;
373  img->dither_img = ( aflag == 0 );
374  img->visual_class = visual_type;
375  img->lvls = levels;
376  img->lvls_squared = levels * levels;
377 
378  if ( img->mono_img )
379  img->dpy_channels = 1;
380 
381  if ( (flip_book || TVflag) && img != &img_info[0] )
382  {
383  previous_img = img - 1;
384 #define INHERIT( thing ) img->thing = previous_img->thing
385  INHERIT(window);
386  INHERIT(win_w);
387  INHERIT(win_h);
388  if (TVflag)
389  {
390  INHERIT(pixmap);
391 #ifdef X_SHARED_MEMORY
392  if ( use_shared_pixmaps )
393  INHERIT(shm_pix);
394 #endif
395  }
396  if (previous_img->pixmap || TVflag)
397  {
398  INHERIT(image);
399 #ifdef X_SHARED_MEMORY
400  if ( use_shared_pixmaps )
401  INHERIT(shm_pix);
402 #endif
403  }
406  INHERIT(gc);
407  INHERIT(icn_gc);
409  INHERIT(divN);
410  INHERIT(modN);
411  INHERIT(dm16);
413  INHERIT(lvls);
415  INHERIT(colormap);
420  INHERIT(rw_cmap);
423  INHERIT(mono_img);
425  INHERIT(x_cmap);
428 #undef INHERIT
429  }
430  else previous_img = NULL;
431 
432  if ( !using_stdin ) {
433  /* rle_cnt will be set to -1 when it is time to open a new
434  * file.
435  */
436  if ( rle_cnt < 0 )
437  {
438  if ( strcmp( *infnames, "-" ) == 0 )
439  {
440  img->filename = "Standard Input";
441  img->fd = stdin;
442  }
443  else
444  {
445  img->filename = *infnames;
446 
447  img->fd = rle_open_f_noexit( "getx11", img->filename, "r");
448 
449  if (img->fd == NULL) {
450  if ( nfile == 1 )
451  exit (1);
452  else {
453  nfile--; infnames++;
454  continue;
455  }
456  }
457  }
458  rle_cnt = 0;
459  }
460  else
461  {
462  /* Safe to copy from previous image because this is at
463  * least the second one in this file.
464  */
465  img->filename = img[-1].filename;
466  img->fd = img[-1].fd;
467  }
468  }
469  else {
470  img->filename = "Standard Input";
471  img->fd = stdin;
472  if ( rle_cnt < 0 )
473  rle_cnt = 0;
474  }
475  img->img_num = rle_cnt;
476 
477  if ( tflag && title_string )
478  img->title = title_string;
479 
480  status = get_pic( img, window_geometry, previous_img );
481 
482  switch (status){
483  case SUCCESS:
484  num_imgs++;
485  rle_cnt++;
486  break;
487 
488  case MALLOC_FAILURE:
489  case RLE_NO_SPACE:
490  fprintf(stderr,"%s: Out of Memory! Trying to continue\n",progname);
491  if ( !using_stdin )
492  {
493  fclose( img->fd );
494  nfile--;
495  infnames++;
496  }
497  rle_cnt = -1;
498  break;
499 
500  case RLE_EMPTY:
501  case RLE_EOF:
502  case RLE_NOT_RLE:
503  if ( status == RLE_NOT_RLE || rle_cnt == 0 )
505  if ( using_stdin )
506  done = 1;
507  else
508  {
509  fclose( img->fd );
510  nfile--;
511  infnames++;
512  if ( nfile == 0 )
513  done = 1;
514  }
515  rle_cnt = -1;
516  break;
517 
518  case FATAL_FAILURE:
519  if ( flip_book )
520  fprintf(stderr,"%s: Cannot flip-book, sorry...\n", progname);
521  exit(1);
522  break;
523  }
524  if ( TVflag && !done ) {
525  if ( tv_command ) {
526  system( tv_command );
527  }
528  if ( tv_delay ) {
529  sleep( tv_delay );
530  }
531  }
532  } while( !done );
533 
534  if ( TVflag ) {
535  if ( img_info->scan_data ) {
536  free( img_info->scan_data );
537  img_info->scan_data = NULL;
538  }
539  num_imgs = 1;
540  flip_book = False;
541  }
542 
543  /* Quit flag means quit after displaying all the images. */
544  if ( quit_flag )
545  {
546  XCloseDisplay( dpy );
547  exit( 0 );
548  }
549 
550 #ifdef unix
551  if ( ! forkflg ) {
552 
553  fflush( stderr );
554  if ( fork() == 0 ) {
555  close( 0 );
556  close( 1 );
557  close( 2 );
558  /* Set process group to avoid signals under sh. */
559 #ifdef SYS_V_SETPGRP
560  (void)setpgrp();
561 #else
562  (void)setpgrp( 0, getpid() );
563 #endif
564  update_pic ( img_info, num_imgs, flip_book, flip_book_frams_sec );
565  }
566  else exit( 0 );
567  }
568  else
569 #endif
570  update_pic ( img_info, num_imgs, flip_book, flip_book_frams_sec );
571 
572  XCloseDisplay( dpy );
573  exit (0);
574 }
575 
576 void
578 register image_information *img;
579 int x, y, width, height, img_h;
580 {
581  /* imaged width and imaged height... May be less that windows size */
582  int iw, ih;
583  int xo = img->xo;
584  int yo = img->yo;
585 
586  iw = img->w * img->mag_fact;
587  ih = img->h * img->mag_fact;
588 
589  /* clear left side */
590  if ( xo && (x < xo) && width > 0 && height > 0) {
591  int w = xo - x;
592  w = Min(width, w);
593  XClearArea( dpy, img->window, x, y, w, height, False );
594  x = xo;
595  width -= w;
596  }
597 
598  /* Clear Top part */
599  if ( yo && (y < yo) && width > 0 && height > 0) {
600  int h = yo - y;
601  h = Min(height, h);
602  XClearArea( dpy, img->window, x, y, width, h, False );
603  y = yo;
604  height -= h;
605  }
606 
607  /* Clear right side */
608  if ( iw < img->win_w )
609  if (x + width > xo + iw && height > 0) {
610  int w = x + width - xo - iw;
611  XClearArea( dpy, img->window, xo + iw, y, w, height, False );
612  width -= w;
613  }
614 
615  /* Clear Bottom side */
616  if ( ih < img->win_h )
617  if (y + height > yo + ih && width > 0) {
618  int h = y + height - yo - ih;
619  XClearArea( dpy, img->window, x, yo + ih, width, h, False );
620  height -= h;
621  }
622 
623  if ( width <= 0 || height <= 0 )
624  return;
625 
626  ih = Min( img->win_h, img->h );
627 
628  /* HACK if the image has not yet read itself in, dont blit any of it */
629  /* instead clear out that top portion of the window(not needed oh well) */
630  if (!img->mag_mode)
631  if (y - yo < ih - img_h && width > 0) {
632  int h = (ih - img_h) - ( y - yo );
633  XClearArea( dpy, img->window, x, y, width, h, False );
634  height -= h;
635  y = ih - img_h + yo;
636  }
637 
638  /*
639  * if bitmap, round beginning pixel to beginning of word
640  */
641 
642  if ( img->binary_img ) {
643  int offset = x % BitmapPad (dpy);
644  x -= offset;
645  width += offset;
646  }
647 
648  if ( width <= 0 || height <= 0 )
649  return;
650 
651  if ( img->pixmap )
652  XCopyArea(dpy, img->pixmap, img->window, img->gc,
653  x-xo, y-yo, width, height, x, y );
654  else
656  x-xo, y-yo, x, y, width, height );
657  return;
658 }
659 
660 /*
661  * Read an image from the input file and display it.
662  */
663 static int
664 get_pic( img, window_geometry, previous_img )
665 register image_information *img, *previous_img;
666 char *window_geometry;
667 {
668  int image_xmax, image_ymax;
669  int x11_y, scan_y, view_w, view_h;
670  unsigned char *save_scan[3], *read_scan[3];
671  register int i;
672  register int image_y;
673  register int y_base, lines_buffered, lines_blitted;
674  int rle_err;
675  int buffer_scans = jump_scans;
676  rle_hdr img_hdr;
677 
678  /*
679  * Read setup info from file.
680  */
681  img_hdr = *rle_hdr_init( (rle_hdr *)NULL );
682  img_hdr.rle_file = img->fd;
683 
684  rle_names( &img_hdr, "getx11", img->filename, 0 );
685  if ( (rle_err = rle_get_setup(&img_hdr)) < 0)
686  return ( rle_err );
687 
688  image_xmax = img_hdr.xmax;
689  image_ymax = img_hdr.ymax;
690 
691  img->x = img_hdr.xmin;
692  img->y = img_hdr.ymin;
693  img->w = image_xmax - img_hdr.xmin + 1;
694  img->h = image_ymax - img_hdr.ymin + 1;
695 
696  img_hdr.xmin = 0;
697  img_hdr.xmax = img->w - 1;
698 
699  /* Were only interested in R, G, & B */
700 
701  RLE_CLR_BIT(img_hdr, RLE_ALPHA);
702  for (i = 3; i < img_hdr.ncolors; i++)
703  RLE_CLR_BIT(img_hdr, i);
704 
705  img->dpy_channels = img->img_channels = (img_hdr.ncolors > 3 ) ?
706  3 : img_hdr.ncolors;
707 
708  if ( img->img_channels == 1 )
709  img->mono_img = True;
710  if ( img->mono_img )
711  img->dpy_channels = 1;
712 
713  check_mono_color( img, &img_hdr );
714 
715  /* jump/buffer scans according to the -j flag and to img->fd == sdtin */
716  buffer_scans = (jump_flag ?
717  ((jump_scans > 0) ? jump_scans : img->h) :
718  ((img->fd == stdin) ? 1 : img->h));
719 
720  if ( !previous_img )
721  /* find a suitable visual for the image */
723 
724  if ( img->img_channels < img->dpy_channels )
725  fprintf(stderr, "%s: dpy_channels > img_channels, %d > %d\n", progname,
727 
728  get_dither_colors( img, &img_hdr );
729 
730  if ( !previous_img )
731  /* Get X color map */
732  init_color( img );
733 
734  if ( !img->title )
735  if ( (img->title = rle_getcom("image_title", &img_hdr )) == NULL &&
736  (img->title = rle_getcom("IMAGE_TITLE", &img_hdr )) == NULL &&
737  (img->title = rle_getcom("title", &img_hdr )) == NULL &&
738  (img->title = rle_getcom("TITLE", &img_hdr )) == NULL )
739  {
740  if ( img->img_num > 0 )
741  {
742  char *buf = (char *)malloc( strlen( img->filename ) + 8 );
743  sprintf( buf, "%s(%d)", img->filename,
744  img->img_num + 1 );
745  img->title = buf;
746  }
747  else
748  img->title = img->filename;
749  }
750 
751  /*
752  * Here if we are flip_booking we gotta get nasty here... img->w, img->h
753  * and img->img_channels must match for well surely be screwed if they
754  * dont match up and we flip_book
755  */
756  if ( previous_img )
757  {
758  if ( img->w != previous_img->w || img->h != previous_img->h ||
759  img->img_channels != previous_img->img_channels )
760  {
761  fprintf( stderr,
762  "%s: Images %s and %s dont match in size or channels\n",
763  progname, previous_img->title, img->title );
764  return( FATAL_FAILURE );
765  }
766  if ((img->mono_color &&
767  !eq_cmap(previous_img->in_cmap, previous_img->cmlen,
768  img->in_cmap, img->cmlen)))
769  {
770  fprintf( stderr, "%s: Images %s and %s have different colormaps\n",
771  progname, previous_img->title, img->title );
772  return( FATAL_FAILURE );
773  }
774  }
775 
776 
777  /* only dick with the icon if we are not flip_booking */
778  if ( !previous_img ) {
780  &img->icn_factor);
781 
782  if ( !img->icn_image )
783  img->icn_image = get_X_image( img, img->icn_w, img->icn_h, False );
784 
785  if ( img->icn_image == NULL ) {
786  perror("malloc for fancy icon");
787  return ( MALLOC_FAILURE );
788  }
789  }
790 
791  /*
792  * Get image and icon windows of the right size
793  */
794 
795  create_windows( img, window_geometry );
797 
798  /*
799  * If we did not inherit the image from the previous image,
800  * allocate it now.
801  */
802  if ( !previous_img || previous_img->pixmap == NULL )
803  {
804  if (!allocate_ximage( img, True ))
805  return( MALLOC_FAILURE );
806  }
807 
808  /*
809  * Choose a scanline converter... Here we know the image display makeup,
810  * the XImage type and other things...
811  */
812 
813  if ( !img->map_scanline )
815 
816  /*
817  * If we are going to display a 2 or 3 channel image in one channel (-w)
818  * we have to copy the data anyway, so we will always read it into the
819  * same spot, and map it into a saved_data array with only one color per
820  * scanline this saves memory.
821  *
822  * read_scan[] is the scan data that we read into with rle_getrow. If the
823  * number of image channels is equal to that which is displayed, we will
824  * not mallocate new memory for it, but we will move it throughout the
825  * saved_data along with save_scan.
826  *
827  * save_scan[] is the pointer to the current line in img->saved_data that
828  * we are saving rle_getrows into.
829  *
830  * If we cant malloc the memory for the save_scan[] or we are doing
831  * flip_book, then we dont want to malloc the memory for this thing.
832  */
833 
834  /*
835  * Set up for rle_getrow. Pretend image x origin is 0.
836  */
837 
838  /* get img->h rows mem. SAVED_RLE_ROW uses scan_data to calc address!! */
839  img->scan_data = NULL;
840 
841  /* if we are flip_booking dont mess with this one huh? */
842  if ( !previous_img ) {
843  img->scan_data =
844  (unsigned char *) malloc ( (img->h + 1) * img->w *
845  (img->dpy_channels) );
846 
847  if (img->scan_data == NULL)
848  perror ("malloc for scanline buffer failed");
849 
850  /* use the macro to point us to the last line... start saving here */
851  save_scan[0] = SAVED_RLE_ROW( img, img->h - 1 );
852  for (i = 1; i < img->img_channels; i++)
853  save_scan[i] = save_scan[i - 1] + img->w;
854  }
855 
856  /* get one line of scan data for reading if we are doing monochrome */
857  if ( img->mono_img || img->scan_data == NULL ) {
858  read_scan[0] = (unsigned char *) malloc ( img->w * img->img_channels );
859  if ( read_scan[0] == NULL ) {
860  perror ("malloc for read_scan buffer failed");
861  return ( MALLOC_FAILURE );
862  }
863  for (i = 1; i < img->img_channels; i++)
864  read_scan[i] = read_scan[i - 1] + img->w;
865  }
866  else
867  read_scan[0] = save_scan[0],
868  read_scan[1] = save_scan[1],
869  read_scan[2] = save_scan[2];
870 
871  if (img->scan_data == NULL)
872  save_scan[0] = read_scan[0],
873  save_scan[1] = read_scan[1],
874  save_scan[2] = read_scan[2];
875 
876  /*
877  * For each scan line, read it, save it, dither it and display it.
878  */
879 
880  view_w = Min(img->w, img->win_w);
881  view_h = Min(img->h, img->win_h);
882  y_base = view_h - 1;
883  img->pan_x = 0;
884  img->pan_y = Max(0, img->h - img->win_h );
885  img->pan_w = Min(img->w, img->win_w);
886  img->pan_h = Min(img->h, img->win_h);
887 
888  lines_buffered = 0;
889  lines_blitted = 0;
890 
891  while ((image_y = rle_getrow(&img_hdr, read_scan)) <=
892  img_hdr.ymax ) {
893  XEvent event;
894 
895  x11_y = view_h - (image_y - img_hdr.ymin) - 1;
896  scan_y = image_ymax - image_y;
897 
898  if ( img->mono_img )
899  map_rgb_to_bw ( img, read_scan, save_scan[0] );
900  else
901  map_rgb_to_rgb ( img, read_scan, save_scan );
902 
903  if ( x11_y >= 0 && x11_y < img->h ) {
904  (*img->map_scanline) (img, save_scan, img->dpy_channels,
905  view_w, 1, x11_y, img->image);
906  lines_buffered++;
907  }
908  /* Subsample image to create icon */
909 
910  if ( !previous_img && scan_y % img->icn_factor == 0 )
911  (*img->map_scanline)( img, save_scan, img->dpy_channels,
912  img->icn_w, img->icn_factor,
913  scan_y / img->icn_factor, img->icn_image);
914 
915  while ( XCheckTypedEvent( dpy, Expose, &event ) ) {
916  image_information *eimg;
917 
918  /* get the right window bro.... */
919  for (eimg = img_info; eimg <= img; eimg++ )
920  if ( eimg->window == event.xany.window )
921  break;
922  if (previous_img) { /*flip_book override */
923  if ( img > img_info && lines_blitted == 0 )
924  eimg = img - 1;
925  else
926  eimg = img;
927  }
928  if (eimg <= img) /* protect against screwy window */
929  handle_exposure(eimg, event.xexpose.x, event.xexpose.y,
930  event.xexpose.width, event.xexpose.height,
931  (eimg == img) ? lines_blitted : eimg->h );
932  XFlush(dpy);
933  }
934 
935  if (lines_buffered >= buffer_scans) {
936  y_base -= lines_buffered - 1;
937  if ( img->pixmap )
939  0, y_base, 0, y_base, view_w,
940  lines_buffered);
941 
942  lines_blitted += lines_buffered;
943  handle_exposure(img, img->xo, y_base + img->yo, view_w,
944  lines_buffered, lines_blitted );
945 
946  y_base = x11_y - 1;
947  lines_buffered = 0;
948  }
949 
950  if ( img->scan_data ) {
951  /* move scan up one line */
952  save_scan[0] = SAVED_RLE_ROW ( img, scan_y - 1 );
953  for( i = 1; i < img->img_channels; i++ )
954  save_scan[i] = save_scan[i - 1] + img->w;
955  }
956  /*
957  * remember? if were saving more than one channel then we dont need
958  * to move the data after we read it... So kludge read_scan ...
959  */
960  if ( !img->mono_img && img->scan_data )
961  read_scan[0] = save_scan[0], read_scan[1] = save_scan[1],
962  read_scan[2] = save_scan[2];
963  if ( img->scan_data == NULL)
964  save_scan[0] = read_scan[0], save_scan[1] = read_scan[1],
965  save_scan[2] = read_scan[2];
966  }
967 
968  if ( lines_buffered > 0 ) {
969  y_base -= lines_buffered - 1;
970  if ( img->pixmap )
972  0, y_base, 0, y_base, view_w,
973  lines_buffered );
974 
975  lines_blitted += lines_buffered;
976  handle_exposure(img, img->xo, img->yo, view_w,
977  lines_buffered, img->h );
978 
979  }
980 
981  if ( !previous_img && img->icn_pixmap ) {
982  XPutImage( dpy, img->icn_pixmap, img->icn_gc, img->icn_image,
983  0, 0, 0, 0, img->icn_w, img->icn_h );
984  XClearWindow( dpy, img->icn_window );
985  }
986 
988 
989  /* free this if we mallocated it */
990  if ( img->mono_img )
991  free ( read_scan[0] );
992 
993  if ( previous_img && img->scan_data ) {
994  free( img->scan_data );
995  img->scan_data = NULL;
996  }
997 
998  XSync( dpy, False );
999  return (SUCCESS);
1000 }
1001 
1002 /*
1003  * Track events & redraw image when necessary.
1004  */
1005 
1006 /* now thats my kinda action! */
1007 #define ACTION_MAGNIFY 0
1008 #define ACTION_UNMAGNIFY 1
1009 #define ACTION_PAN 2
1010 #define ACTION_SWITCH_MAG_MODE 3
1011 #define ACTION_FLIP_FORWARD 4
1012 #define ACTION_FLIP_STEP 5
1013 #define ACTION_FLIP_BACKWARD 6
1014 #define ACTION_FLIP_SPEED 7
1015 #define ACTION_PIXEL_INFO 8
1016 #define ACTION_CYCLE 9
1017 #define ACTION_CYCLE_TO_AND_FRO 10
1018 #define ACTION_RESIZE 11
1019 #define ACTION_DEFAULT ACTION_PAN
1020 
1021 /* define what to do on mouse buttons */
1022 static int button_action[3][2] = {
1026  };
1027 
1028 /* define what to do on flip_book mouse buttons */
1029 static int flip_action[3][2] = {
1033  };
1034 
1035 static
1036 void mag_pan( img, action, bx, by, new_mag_fact )
1037 image_information *img;
1038 int action, bx, by, new_mag_fact;
1039 {
1040  Boolean fast_pan = False;
1041  Boolean redraw = False;
1042  Boolean redither = False;
1043  int ix = img->pan_x + bx / img->mag_fact;
1044  int iy = img->pan_y + by / img->mag_fact;
1045  int opan_x = 0, opan_y = 0;
1046  int blit_w = 0, blit_h = 0;
1047 
1048 
1049  /* perhaps we could re-open the img->filename to do this... */
1050  /* but NAHHHHHHH */
1051  if ( img->scan_data == NULL )
1052  return;
1053 
1054  switch ( action ) {
1055  /*
1056  * Normalize has to switch the current mag factor with 1 if they
1057  * differ... It also remembers the old pan_x and pan_y and stuff. It
1058  * should use the pixmaps to refresh, so that it will be fast when
1059  * toggeling in this mode...
1060  */
1062  if ( img->mag_fact == img->save_mag_fact )
1063  return;
1064  else {
1065  if ( img->mag_fact == 1 ) {
1066  img->mag_mode = True;
1067  img->mag_fact = img->save_mag_fact;
1068 
1069  img->save_pan_x = img->pan_x; img->save_pan_y = img->pan_y;
1070  img->save_pan_w = img->pan_w; img->save_pan_h = img->pan_h;
1071  img->save_mag_fact = 1;
1072 
1073  img->pan_x = ix - ((img->win_w / 2)/img->mag_fact);
1074  img->pan_y = iy - ((img->win_h / 2)/img->mag_fact);
1075 
1076  img->pan_w = img->win_w/img->mag_fact;
1077  img->pan_h = img->win_h/img->mag_fact;
1078 
1079  } else {
1080 #define SWAP(v1, v2) { int tmp = (v1); (v1) = (v2); (v2) = tmp; }
1081  img->mag_mode = False;
1082 
1083  SWAP( img->save_pan_x, img->pan_x );
1084  SWAP( img->save_pan_y, img->pan_y );
1085  SWAP( img->save_pan_w, img->pan_w );
1086  SWAP( img->save_pan_h, img->pan_h );
1087 #undef SWAP
1088  img->save_mag_fact = img->mag_fact;
1089 
1090  img->mag_fact = 1;
1091  }
1092 
1093  if (img->save_win_w != img->win_w ||
1094  img->save_win_h != img->win_h )
1095  {
1096  img->pan_w = img->win_w/img->mag_fact;
1097  img->pan_h = img->win_h/img->mag_fact;
1098 
1099  allocate_ximage( img, False );
1100  allocate_pixmap( img, False );
1101  }
1102 
1103  img->save_win_w = img->win_w; img->save_win_h = img->win_h;
1104  redraw = True;
1105  redither = True;
1106  }
1107  break;
1108  case ACTION_MAGNIFY:
1109  case ACTION_UNMAGNIFY:
1110  if (img->mag_fact == 1 && new_mag_fact > img->mag_fact)
1111  {
1112  img->save_pan_x = img->pan_x; img->save_pan_y = img->pan_y;
1113  img->save_pan_w = img->pan_w; img->save_pan_h = img->pan_h;
1114  img->save_win_w = img->win_w; img->save_win_h = img->win_h;
1115  img->save_mag_fact = 1;
1116  }
1117 
1118  if (img->mag_fact == 1 && new_mag_fact < img->mag_fact){
1119  mag_pan( img, ACTION_PAN, bx, by, img->mag_fact );
1120  return;
1121  }
1122 
1123  img->mag_fact = new_mag_fact;
1124 
1125  if ( img->mag_fact <= 1 ) {
1126  img->mag_fact = 1;
1127  if ( img->mag_mode )
1128  redraw = True;
1129  img->mag_mode = False;
1130  } else img->mag_mode = True;
1131 
1132  img->pan_x = ix - ((img->win_w / 2)/img->mag_fact);
1133  img->pan_y = iy - ((img->win_h / 2)/img->mag_fact);
1134 
1135  img->pan_w = img->win_w/img->mag_fact;
1136  img->pan_h = img->win_h/img->mag_fact;
1137 
1138  allocate_ximage( img, False );
1139  allocate_pixmap( img, False );
1140 
1141  redither = True;
1142  redraw = True;
1143  break;
1144 
1145  case ACTION_PAN:
1146  fast_pan = 1; /* are we REALLY just panning around? */
1147  opan_x = img->pan_x;
1148  opan_y = img->pan_y;
1149 
1150  img->mag_mode = ( img->mag_fact > 1 );
1151 
1152  img->pan_x = ix - ((img->win_w / 2)/img->mag_fact);
1153  img->pan_y = iy - ((img->win_h / 2)/img->mag_fact);
1154 
1155  /* Isnt this always like this? */
1156  img->pan_w = img->win_w/img->mag_fact;
1157  img->pan_h = img->win_h/img->mag_fact;
1158 
1159  redither = True;
1160  redraw = True;
1161  break;
1162  case ACTION_RESIZE:
1163  img->pan_x = ix - ((img->win_w / 2)/img->mag_fact);
1164  img->pan_y = iy - ((img->win_h / 2)/img->mag_fact);
1165 
1166  /* Isnt this always like this? */
1167  img->pan_w = img->win_w/img->mag_fact;
1168  img->pan_h = img->win_h/img->mag_fact;
1169 
1170  redither = True;
1171  redraw= True;
1172  break;
1173  }
1174 
1175  if (redraw == True)
1176  calc_view_origin( img );
1177 
1178  /* check bounds */
1179  if ( img->pan_x < 0 )
1180  img->pan_x = 0;
1181  if ( img->pan_y < 0 )
1182  img->pan_y = 0;
1183 
1184  if ( img->pan_w > img->w )
1185  img->pan_w = img->w;
1186  if ( img->pan_h > img->h )
1187  img->pan_h = img->h;
1188 
1189  if ( img->pan_x + img->pan_w >= img->w )
1190  {
1191  img->pan_x = img->w - img->pan_w;
1192  if ( img->pan_w * img->mag_fact < img->win_w )
1193  img->pan_x -= 1;
1194  }
1195  if ( img->pan_y + img->pan_h >= img->h )
1196  {
1197  img->pan_y = img->h - img->pan_h;
1198  if ( img->pan_h * img->mag_fact < img->win_h )
1199  img->pan_y -= 1;
1200  }
1201 
1202  /* check bounds */
1203  if ( img->pan_x < 0 )
1204  img->pan_x = 0;
1205  if ( img->pan_y < 0 )
1206  img->pan_y = 0;
1207 
1208  blit_w = img->w * img->mag_fact;
1209  blit_h = img->h * img->mag_fact;
1210 
1211  blit_w = (blit_w < img->win_w) ? blit_w : img->win_w;
1212  blit_h = (blit_h < img->win_h) ? blit_h : img->win_h;
1213 
1214  /* let the suckers know that we are thinking */
1216 
1217  /*
1218  * Some could argue that this fast_pan shit is a waste of time, but it
1219  * does speed things up a bunch, and its really hard to understand.
1220  * Sorry, no fancy pictures in the comments. Just code. We figure out
1221  * which rectangle is blt-able. We blt it on the server side, and on the
1222  * client side (my fancy XCopyImage) and then MAG_scanline the exposed
1223  * area and XPutImage that stuff too... Dont change it cuz its right.
1224  */
1225  if ( fast_pan )
1226  {
1227  int width, hight;
1228  int src_x, src_y, dst_x, dst_y;
1229  int pwidth = opan_x - img->pan_x;
1230  int phight = opan_y - img->pan_y;
1231 
1232  pwidth = img->pan_w - (( pwidth < 0 ) ? - pwidth : pwidth);
1233  phight = img->pan_h - (( phight < 0 ) ? - phight : phight);
1234 
1235  /*
1236  * pwidth and phight now contain the size of the non-changing
1237  * (BLT-able) portion of the viewport in rle_pixel space.
1238  */
1239  width = pwidth * img->mag_fact + (blit_w - img->pan_w * img->mag_fact);
1240  hight = phight * img->mag_fact + (blit_h - img->pan_h * img->mag_fact);
1241 
1242  /* Now we compute the src_xy and dst_xy for the pixel copy */
1243  if ( opan_x < img->pan_x )
1244  {
1245  dst_x = 0; src_x = blit_w - width;}
1246  else
1247  {
1248  src_x = 0; dst_x = blit_w - width;}
1249 
1250  if ( opan_y < img->pan_y )
1251  {
1252  dst_y = 0; src_y = blit_h - hight;}
1253  else
1254  {
1255  src_y = 0; dst_y = blit_h - hight;}
1256 
1257  /* subtract partial pixels if we are going right */
1258  if ( opan_x < img->pan_x )
1259  width -= blit_w - img->pan_w * img->mag_fact;
1260 
1261  /* subtract partial pixels if we are going down */
1262  if ( opan_y < img->pan_y )
1263  hight -= blit_h - img->pan_h * img->mag_fact;
1264 
1265  if ( src_x == dst_x && src_y == dst_y )
1266  {
1267  redraw = action != ACTION_PAN;
1268  redither = False;
1269  }
1270  else {
1271  /* XCopyImage is only implemented for 8 and 32 bit image pixels */
1272  if (redither && img->pixmap &&
1273  XCopyImage(img->image, src_x, src_y, width, hight,
1274  dst_x, dst_y))
1275  {
1276  XCopyArea ( dpy, img->pixmap, img->pixmap,
1277  img->gc, src_x, src_y, width, hight, dst_x, dst_y );
1278 
1279  if ( dst_y ) {
1280  (*img->MAG_scanline)(img, img->pan_x, img->pan_y,
1281  img->mag_fact, 0, 0,
1282  blit_w, dst_y, img->image );
1283 
1284  put_X_image( img, img->pixmap, img->gc, img->image,
1285  0, 0, 0, 0, blit_w, dst_y);
1286  }
1287  else {
1288  if (hight < blit_h) {
1289  (*img->MAG_scanline)
1290  (img, img->pan_x, img->pan_y + phight,
1291  img->mag_fact, 0, hight,
1292  blit_w, blit_h - hight, img->image );
1293  put_X_image(img, img->pixmap, img->gc,
1294  img->image, 0, hight, 0, hight,
1295  blit_w, blit_h - hight );
1296  }
1297  }
1298 
1299  if ( dst_x ) {
1300  if (hight && width < img->win_w) {
1301  (*img->MAG_scanline)
1302  (img, img->pan_x, img->pan_y +
1303  ((dst_y) ? img->pan_h - phight: 0), img->mag_fact,
1304  0, dst_y, blit_w - width, hight, img->image );
1305 
1307  0, dst_y, 0, dst_y, blit_w - width, hight );
1308  }
1309  }
1310  else {
1311  if (hight && width < blit_w) {
1312  (*img->MAG_scanline)
1313  (img, img->pan_x + pwidth, img->pan_y +
1314  ((dst_y) ? img->pan_h - phight: 0), img->mag_fact,
1315  width, dst_y, blit_w - width, hight, img->image );
1316 
1317  put_X_image(img, img->pixmap, img->gc,
1318  img->image, width, dst_y, width, dst_y,
1319  blit_w - width, hight );
1320  }
1321  }
1322 
1323  /*
1324  * We already redithered... If XCopyImage failed we arent
1325  * here and we have to redither the whole thing below.
1326  */
1327  redither = False;
1328  }
1329  }
1330  }
1331 
1332  /* redither the whole thing */
1333  if ( redither || ( redraw && !img->pixmap ) )
1334  {
1335  (*img->MAG_scanline)(img, img->pan_x, img->pan_y,
1336  img->mag_fact, 0, 0, blit_w, blit_h,
1337  img->image );
1338 
1339  if (img->pixmap)
1341  0, 0, 0, 0, blit_w, blit_h );
1342  }
1343 
1344 
1345  if ( redraw )
1346  handle_exposure(img, 0, 0, img->win_w, img->win_h, img->h);
1348 }
1349 
1351  mask, event, found_event )
1352 image_information *img, *img_info;
1353 int flip_book_udelay, n;
1354 unsigned long mask;
1355 XEvent *event;
1356 Boolean *found_event;
1357 {
1358  if (mask) *found_event = False;
1359 
1360  if ( img == &img_info[n - 1] )
1361  img = &img_info[0];
1362  for ( ; img < &img_info[n]; img++ ) {
1363  set_timer( flip_book_udelay );
1364  handle_exposure(img, 0, 0, img->w, img->h, img->h);
1365  XFlush( dpy );
1366  if (mask && XCheckMaskEvent(dpy, mask, event )){
1367  *found_event = True;
1368  break;
1369  }
1370  wait_timer();
1371  }
1372  if (mask && *found_event)
1373  return img;
1374  else return img - 1;
1375 }
1376 
1378  mask, event, found_event )
1379 image_information *img, *img_info;
1380 int flip_book_udelay, n;
1381 unsigned long mask;
1382 XEvent *event;
1383 Boolean *found_event;
1384 {
1385  if (mask) *found_event = False;
1386 
1387  if ( img == img_info )
1388  img = &img_info[n - 1];
1389  for ( ; img >= &img_info[0]; img-- ) {
1390  set_timer( flip_book_udelay );
1391  handle_exposure(img, 0, 0, img->w, img->h, img->h);
1392  XFlush( dpy );
1393  if (mask && XCheckMaskEvent(dpy, mask, event )){
1394  *found_event = True;
1395  break;
1396  }
1397  wait_timer();
1398  }
1399  if (mask && *found_event)
1400  return img;
1401  else return img + 1;
1402 }
1403 
1406 image_information *img, *img_info;
1407 int n, flip_book_udelay;
1408 Boolean flip_forward;
1409 {
1410  int found_event;
1411  XEvent event;
1412 
1413  do {
1414  img = (* (flip_forward ? action_flip_forward : action_flip_backward))
1415  (img, img_info, flip_book_udelay, n, ButtonPressMask|KeyPressMask,
1416  &event, &found_event);
1417  XSync(dpy, False);
1418  } while ( !found_event );
1419  return img;
1420 }
1421 
1422 /* returns whether or not we should redither and redraw */
1423 int
1425 image_information *img;
1426 int new_w, new_h;
1427 {
1428  int old_w = img->win_w;
1429  int old_h = img->win_h;
1430  int iw = img->w * img->mag_fact;
1431  int ih = img->h * img->mag_fact;
1432  int retval = 0;
1433 
1434  img->win_w = new_w;
1435  img->win_h = new_h;
1436  calc_view_origin( img );
1437 
1438  if ( old_w < iw || new_w < iw || old_h < ih || new_h < ih ) {
1439  allocate_ximage( img, True );
1440  if (img->pixmap)
1441  allocate_pixmap( img, True );
1442  retval = 1;
1443  }
1444 
1445  return retval;
1446 }
1447 
1448 static void
1449 update_pic( img_info, n, flip_book, flip_book_frams_sec )
1450 image_information *img_info;
1451 int n, flip_book_frams_sec;
1452 Boolean flip_book;
1453 {
1454  int i;
1455  XEvent event;
1456  int action;
1457  register image_information *img;
1458  int found_event;
1459 
1460  /* variables to use for flip_book mode */
1461  image_information *flip_frame = NULL;
1462  Boolean flip_forward = True;
1463  Window dead_window;
1464  int flip_book_udelay = 0;
1465 
1466  if ( flip_book ) {
1467  img = flip_frame = img_info;
1468  handle_exposure(img, 0, 0, img->w, img->h, img->h);
1469  XStoreName(dpy, img->window, img->title);
1470  }
1471 
1472  while (n) {
1473 
1474  XNextEvent(dpy, &event);
1475 
1476  if ( flip_book ){ /* all windows are the same! */
1477  flip_book_udelay =
1478  (flip_book_frams_sec) ? 1000000 / flip_book_frams_sec : 0;
1479  img = flip_frame;
1480  } else
1481  for ( img = img_info; img < &img_info[n]; img++ )
1482  if ( img->window == event.xany.window )
1483  break;
1484 
1485  switch (event.type) {
1486 
1487  case ButtonPress:
1488  i = event.xbutton.button - Button1;
1489  if (i < 0 || i > COUNT_OF(button_action) )
1490  action = ACTION_DEFAULT;
1491  else
1492  if ( flip_book )
1493  action = flip_action[i][event.xbutton.state & ShiftMask];
1494  else
1495  action = button_action[i][event.xbutton.state & ShiftMask];
1496 
1497  switch (action) {
1498 
1499  case ACTION_PIXEL_INFO:
1500  if ( img->scan_data ) do
1501  {/* X calls by John Bradley, U of Penn, hacked up by mrf.... */
1502  Boolean first = 1;
1503  int lx = 0, ly = 0;
1504  int xo = Max(0, (img->win_w - (img->w * img->mag_fact))/2);
1505  int yo = Max(0, (img->win_h - (img->h * img->mag_fact))/2);
1506 
1508  MapPixWindow ( img, (event.xbutton.y > img->win_h/2));
1509  while (1) { /* loop until button released */
1510  Window foo,poo;
1511  int rx, ry, x, y;
1512  unsigned int mask;
1513 
1514  if (XQueryPointer(dpy, img->window, &foo, &poo,
1515  &rx, &ry, &x, &y, &mask))
1516  {
1517  if (!(mask&(Button1Mask|Button2Mask|Button3Mask)))
1518  break; /* released */
1519 
1520  x -= xo; y -= yo;
1521  x /= img->mag_fact; y /= img->mag_fact;
1522  x += img->pan_x; y += img->pan_y;
1523 
1524  /* wait for new pixel */
1525  if ((first || x != lx || y != ly) &&
1526  (x >= 0 && x < img->w &&
1527  y >= 0 && y < img->h)) {
1528  DrawPixWindow( img, x, y );
1529  first = 0; lx = x; ly = y;
1530  }
1531  } else
1532  break;
1533  }
1535  UnmapPixWindow ( img );
1536  } while (0);
1537  continue;
1538 
1539  case ACTION_FLIP_SPEED:
1540  if (flip_book) do
1541  {/* X calls by John Bradley, U of Penn, hacked up by mrf.... */
1542  Boolean first = 1, ly = 0;
1543  int height = DisplayHeight(dpy, screen)/4; /* use DH/4 */
1544  int s;
1545 
1546  s = flip_book_frams_sec;
1547  MapPixWindow ( img, True );
1548 
1549  while (1) { /* loop until button released */
1550  Window foo,poo;
1551  int rx, ry, x, y, inc;
1552  unsigned int mask;
1553 
1554  if (XQueryPointer(dpy, img->window, &foo, &poo,
1555  &rx, &ry, &x, &y, &mask)) {
1556  if (!(mask&(Button1Mask|Button2Mask|Button3Mask)))
1557  break; /* released */
1558 
1559  if ( first )
1560  ly = y;
1561  inc = (ly - y) * 100 / height;
1562 
1563  /* wait for new pixel */
1564  if ((first || flip_book_frams_sec + inc != s ) ) {
1565  s = flip_book_frams_sec + inc;
1566  s = (s < 0) ? 0 : s;
1567  s = (s > 100) ? 100 : s;
1568  DrawSpeedWindow( img, s );
1569  first = 0;
1570  }
1571  }
1572  else
1573  break;
1574  }
1575  flip_book_frams_sec = s;
1576  UnmapPixWindow ( img );
1577  } while (0);
1578  continue;
1579 
1580  case ACTION_FLIP_BACKWARD:
1581  if ( flip_book ) {
1582  img = action_flip_backward(img, img_info, flip_book_udelay,
1583  n, ButtonPressMask|KeyPressMask,
1584  &event, &found_event);
1585  flip_frame = img;
1586  /* Restore title after flipping has stopped. */
1587  XStoreName(dpy, img->window, img->title);
1588  flip_forward = False;
1589  }
1590  continue;
1591 
1592  case ACTION_FLIP_FORWARD:
1593  if ( flip_book ) {
1594  img = action_flip_forward (img, img_info, flip_book_udelay,
1595  n, ButtonPressMask|KeyPressMask,
1596  &event, &found_event);
1597  flip_frame = img;
1598  /* Restore title after flipping has stopped. */
1599  XStoreName(dpy, img->window, img->title);
1600  flip_forward = True;
1601  }
1602  continue;
1603 
1604  case ACTION_FLIP_STEP:
1605  /* step flip_book in current direction. */
1606  if ( flip_book ) {
1607  if ( flip_forward ) {
1608  if ( flip_frame == &img_info[n-1] )
1609  img = flip_frame = img_info;
1610  else
1611  img = flip_frame = flip_frame + 1;
1612  }
1613  else {
1614  if ( flip_frame == img_info )
1615  img = flip_frame = &img_info[n-1];
1616  else
1617  img = flip_frame = flip_frame - 1;
1618  }
1619  handle_exposure(img, 0, 0, img->w, img->h, img->h);
1620  XStoreName(dpy, img->window, img->title);
1621  }
1622  continue;
1623 
1624  /* cycle in the current (flip_forward) direction */
1625  case ACTION_CYCLE:
1626  if ( flip_book ) {
1627  flip_frame = img = action_flip_book_cycle
1628  ( img, img_info, n, flip_forward, flip_book_udelay );
1629  /* Restore title after flipping has stopped. */
1630  XStoreName(dpy, img->window, img->title);
1631  }
1632  continue;
1634  if ( flip_book ) {
1635  do {
1636  img = (* (flip_forward ?
1639  (img, img_info, flip_book_udelay,
1640  n, ButtonPressMask |KeyPressMask,
1641  &event, &found_event);
1642  if (!found_event){
1643  flip_forward = !flip_forward;
1644  if ( n > 1 )
1645  img = (flip_forward) ? img + 1 : img - 1;
1646  }
1647  XSync(dpy, False);
1648  } while( !found_event );
1649  flip_frame = img;
1650  /* Restore title after flipping has stopped. */
1651  XStoreName(dpy, img->window, img->title);
1652  }
1653  continue;
1654 
1655  case ACTION_MAGNIFY:
1656  mag_pan ( img, action, event.xbutton.x, event.xbutton.y,
1657  img->mag_fact + 1 );
1658  continue;
1659  case ACTION_UNMAGNIFY:
1660  mag_pan ( img, action, event.xbutton.x, event.xbutton.y,
1661  img->mag_fact - 1 );
1662  continue;
1664  mag_pan ( img, action, event.xbutton.x, event.xbutton.y,
1665  img->mag_fact );
1666  continue;
1667 
1668  case ACTION_PAN:
1669  mag_pan ( img, action, event.xbutton.x, event.xbutton.y,
1670  img->mag_fact );
1671  continue;
1672 
1673  default:
1674  continue;
1675  }
1676 
1677  break; /* not reached */
1678 
1679  case Expose:
1680  handle_exposure(img, event.xexpose.x, event.xexpose.y,
1681  event.xexpose.width, event.xexpose.height,
1682  img->h );
1683 
1684  continue;
1685 
1686  case ConfigureNotify:
1687  {
1688  int new_w = event.xconfigure.width;
1689  int new_h = event.xconfigure.height;
1690 
1691  if ( !flip_book && (img->win_w != new_w || img->win_h != new_h )) {
1692  if (resize_window( img, new_w, new_h ))
1693  mag_pan (img, ACTION_RESIZE, img->win_w/2, img->win_h/2,
1694  img->mag_fact );
1695  }
1696  }
1697  continue;
1698 
1699  case NoExpose:
1700  continue;
1701 
1702  case KeyPress:
1703  {
1704  char string[256];
1705  char *symstr, *XKeysymToString( );
1706  KeySym keysym;
1707  int length;
1708  XComposeStatus stat;
1709  Boolean handled_key = True;
1710  Boolean shifted_key;
1711 
1712  length = XLookupString( (XKeyEvent *)&event, string, 256, &keysym, &stat );
1713  string [length] = '\0';
1714  symstr = XKeysymToString( keysym );
1715  shifted_key = event.xkey.state & ShiftMask;
1716 
1717  if ( length == 1 && (string[0] == 'q' || string[0] == 'Q' ||
1718  string[0] == '\003' )) /* q, Q or ^C */
1719  break;
1720 
1721  if ( length == 1 )
1722  switch (string[0])
1723  {
1724  case '1': case '2': case '3': case '4':
1725  case '5': case '6': case '7': case '8':
1726  case '9':
1727  mag_pan ( img, ACTION_MAGNIFY, img->win_w/2, img->win_h/2,
1728  atoi(string));
1729  break;
1730 
1731  /* back and forth mode */
1732  case 'b':
1733  if ( flip_book ) {
1734  do {
1735  img = (* (flip_forward ?
1738  (img, img_info, flip_book_udelay,
1739  n, ButtonPressMask |KeyPressMask,
1740  &event, &found_event);
1741  if (!found_event){
1742  flip_forward = !flip_forward;
1743  if ( n > 1 )
1744  img = (flip_forward) ? img + 1 : img - 1;
1745  }
1746  XSync(dpy, False);
1747  } while( !found_event );
1748  flip_frame = img;
1749  }
1750  break;
1751 
1752  case 'c':
1753  case 'C':
1754  if ( flip_book ) {
1755  flip_forward = (string[0] == 'c');
1756  flip_frame = img = action_flip_book_cycle
1757  (img, img_info, n, flip_forward, flip_book_udelay);
1758  }
1759  break;
1760 
1761  case 's':
1762  XDrawString ( dpy, img->window, img->gc,
1763  4, 20, "hi there", strlen ("hi there") );
1764 
1765  break;
1766 
1767  case 'r':
1768  case 'R':
1769  /* remove a frame from flip book */
1770  if (flip_book ) {
1771  n--;
1772  if ( n ) /* pack imgs in there good */
1773  for (img = flip_frame; img < &img_info[n]; img++ )
1774  *img = *(img+1);
1775  else exit(0);
1776  if ( flip_forward ) {
1777  if ( flip_frame == &img_info[n] )
1778  img = flip_frame = img_info;
1779  else
1780  img = flip_frame;
1781  }
1782  else {
1783  if ( flip_frame == img_info )
1784  img = flip_frame = &img_info[n-1];
1785  else
1786  img = flip_frame = flip_frame - 1;
1787  }
1788  handle_exposure(img, 0, 0, img->w, img->h, img->h);
1789  XStoreName(dpy, img->window, img->title);
1790  }
1791  break;
1792  case ' ':
1793  /* step flip_book in current direction. */
1794  if ( flip_book ) {
1795  if ( flip_forward ) {
1796  if ( flip_frame == &img_info[n-1] )
1797  img = flip_frame = img_info;
1798  else
1799  img = flip_frame = flip_frame + 1;
1800  }
1801  else {
1802  if ( flip_frame == img_info )
1803  img = flip_frame = &img_info[n-1];
1804  else
1805  img = flip_frame = flip_frame - 1;
1806  }
1807  handle_exposure(img, 0, 0, img->w, img->h, img->h);
1808  XStoreName(dpy, img->window, img->title);
1809  }
1810  break;
1811 
1812  case '\010':
1813  case '\177':
1814  /* step flip_book opposite to current direction. */
1815  if ( flip_book ) {
1816  if ( !flip_forward ) {
1817  if ( flip_frame == &img_info[n-1] )
1818  img = flip_frame = img_info;
1819  else
1820  img = flip_frame = flip_frame + 1;
1821  }
1822  else {
1823  if ( flip_frame == img_info )
1824  img = flip_frame = &img_info[n-1];
1825  else
1826  img = flip_frame = flip_frame - 1;
1827  }
1828  handle_exposure(img, 0, 0, img->w, img->h, img->h);
1829  XStoreName(dpy, img->window, img->title);
1830  }
1831  break;
1832 
1833  case 'i':
1834  case 'I':
1835  /* Install/deinstall colormap.
1836  * Should only do this if no window manager
1837  * running, but that's hard to tell. Let user
1838  * deal with it...
1839  */
1840  if ( img->colormap )
1841  if ( string[0] == 'i' )
1842  XInstallColormap( dpy, img->colormap );
1843  else
1844  XUninstallColormap( dpy, img->colormap );
1845  break;
1846 
1847  default:
1848  handled_key = False;
1849  }
1850  else handled_key = False;
1851 
1852  DPRINTF(stderr, "%s %x, %s String '%s' - %d\n", symstr, keysym,
1853  ( shifted_key )? "shifted":"unshifted", string, length );
1854 
1855  if ( !handled_key )
1856  {
1857  /* GACK! the F28-34 keysyms are for the suns! */
1858  /* on the DECs they are Left Right Up and Down w/ShiftMask */
1859  /* on the ardent they are KP_4 KP_6 KP_8 KP_2 w/ShiftMask */
1860  /* insert your favorite shifted arrow keysyms here! */
1861 
1862  if ( !strcmp( symstr, "Left" ) || !strcmp( symstr, "F30" ) )
1863  mag_pan( img, ACTION_PAN, (shifted_key ? 0 : img->win_w/4),
1864  img->win_h/2, img->mag_fact);
1865  if ( !strcmp( symstr, "Up" ) || !strcmp( symstr, "F28" ) )
1866  mag_pan( img, ACTION_PAN, img->win_w/2,
1867  (shifted_key ? 0 : img->win_h/4), img->mag_fact);
1868  if ( !strcmp( symstr, "Right" ) || !strcmp( symstr, "F32" ) )
1869  mag_pan( img, ACTION_PAN,
1870  (shifted_key ? img->win_w-1 :
1871  img->win_w/2 + img->win_w/4),
1872  img->win_h/2, img->mag_fact);
1873  if ( !strcmp( symstr, "Down" ) || !strcmp( symstr, "F34" ) )
1874  mag_pan( img, ACTION_PAN, img->w/2,
1875  (shifted_key ? img->win_h-1 :
1876  img->win_h/2 + img->win_h/4),
1877  img->mag_fact);
1878  }
1879  continue;
1880  }
1881 
1882  case VisibilityNotify:
1883  case CreateNotify:
1884  case DestroyNotify:
1885  case UnmapNotify:
1886  case MapNotify:
1887  case MapRequest:
1888  case ReparentNotify:
1889  case ConfigureRequest:
1890  continue;
1891 
1892  case MappingNotify:
1893  XRefreshKeyboardMapping( &event.xmapping );
1894  continue;
1895 
1896  default:
1897  fprintf(stderr, "%s: Event type %x?\n", progname, event.type);
1898  continue;
1899 
1900  }
1901 
1902  /* exit this window */
1903 
1904  if (img->scan_data)
1905  free ( img->scan_data );
1906  if (img->icn_image)
1908  if (img->image)
1909  destroy_X_image( img, img->image );
1910  if (img->pixmap)
1911  free_X_pixmap( img, img->pixmap );
1912  if (img->colormap != DefaultColormap( dpy, screen ))
1913  XFreeColormap( dpy, img->colormap );
1914  else
1915  free_image_colors( img );
1916  if (img->icn_pixmap)
1918  if (img->icn_gc)
1919  XFreeGC( dpy, img->icn_gc );
1920  if (img->gc)
1921  XFreeGC( dpy, img->gc );
1922  if (img->icn_window)
1923  XDestroyWindow ( dpy, img->icn_window );
1924 
1925  dead_window = img->window;
1926  if (img->window)
1927  XDestroyWindow ( dpy, img->window );
1928 
1929  n--;
1930  if ( n ) /* pack imgs in there good */
1931  for ( ; img < &img_info[n]; img++ )
1932  *img = *(img+1);
1933  else break;
1934 
1935  /* flipbook only has one window, so if its dead_window then die too */
1936  if ( img_info[0].window == dead_window )
1937  {
1938 #ifdef X_SHARED_MEMORY
1939  for ( img = &img_info[0] ; img < &img_info[n]; img++ )
1940  {
1941  if ( img->shm_pix.shmid >= 0 )
1942  free_X_pixmap( img, img->pixmap );
1943  if ( img->shm_img.shmid >= 0 && img->image )
1944  destroy_X_image( img, img->image );
1945  }
1946 #endif
1947  break;
1948  }
1949  }
1950 }
unsigned char * scan_data
Definition: getx11.h:140
Boolean use_shared_pixmaps
Definition: getx11.c:85
#define ACTION_FLIP_BACKWARD
Definition: getx11.c:1013
int Boolean
Definition: getx11.h:53
cmap_info x_cmap
Definition: getx11.h:178
Pixel blue_mask
Definition: getx11.h:119
int xmin
Definition: rle.h:100
void allocate_pixmap(image_information *img, Boolean reallocate)
Definition: x11_stuff.c:325
void MapPixWindow(image_information *img, int use_top)
Definition: x11_stuff.c:1962
#define ACTION_MAGNIFY
Definition: getx11.c:1007
int red_shift
Definition: getx11.c:66
Boolean rw_cmap
Definition: getx11.h:166
int XCopyImage(XImage *image, int src_x, int src_y, int width, int height, int dst_x, int dst_y)
Definition: XCopyImg.c:35
void free_X_pixmap(image_information *img, Pixmap pix)
Definition: x11_stuff.c:429
int stingy_flag
Definition: getx11.c:81
#define ACTION_CYCLE_TO_AND_FRO
Definition: getx11.c:1017
Pixel green_mask
Definition: getx11.h:118
Boolean pixmap_failed
Definition: getx11.h:134
int no_color_ref_counts
Definition: getx11.c:88
void UnmapPixWindow(image_information *img)
Definition: x11_stuff.c:2080
#define Max(x, y)
Definition: getx11.h:76
void rle_names(rle_hdr *the_hdr, const char *pgmname, const char *fname, int img_num)
Definition: rle_hdr.c:48
int eq_cmap(register rle_pixel **cm1, int len1, register rle_pixel **cm2, int len2)
Boolean mag_mode
Definition: getx11.h:158
void check_mono_color(image_information *img, rle_hdr *img_hdr)
Definition: in_cmap.c:32
XShmSegmentInfo shm_img
Definition: getx11.h:183
#define RLE_EMPTY
Definition: rle.h:73
Boolean debug_flag
Definition: get_orion.c:79
void choose_scanline_converter(image_information *img)
Definition: map_scan.c:77
#define SYS_V_SETPGRP
Definition: rle_config.h:21
Display * dpy
Definition: getx10.c:94
static int flip_action[3][2]
Definition: getx11.c:1029
Pixel pixel_base
Definition: getx11.c:72
Pixel red_mask
Definition: getx11.h:117
void main(int argc, char **argv)
Definition: aliastorle.c:121
int jump_flag
Definition: getx11.c:81
void open_x_display(char *display_name)
Definition: x11_stuff.c:532
int specified_levels
Definition: getx11.c:82
int rle_get_setup(rle_hdr *the_hdr)
Definition: rle_getrow.c:74
int jump_scans
Definition: getx11.c:81
image_information * action_flip_forward(image_information *img, image_information *img_info, int flip_book_udelay, int n, unsigned long mask, XEvent *event, Boolean *found_event)
Definition: getx11.c:1350
#define FATAL_FAILURE
Definition: getx11.h:58
Boolean no_shared_space
Definition: getx11.c:86
int rle_getrow(rle_hdr *the_hdr, scanline)
Definition: rle_getrow.c:333
void calc_view_origin(image_information *img)
Definition: x11_stuff.c:575
const char * title
Definition: getx11.h:137
#define RLE_NOT_RLE
Definition: rle.h:71
int ymin
Definition: rle.h:100
XShmSegmentInfo shm_pix
Definition: getx11.h:184
int rle_get_error(int code, const char *pgmname, const char *fname)
Definition: rle_error.c:76
char * progname
Definition: unslice.c:51
Pixel pixel_base
Definition: getx11.h:120
#define ACTION_PAN
Definition: getx11.c:1009
#define ACTION_CYCLE
Definition: getx11.c:1016
short verbose_flag
Definition: qcr.c:17
void init_img_info(image_information *i)
Definition: getx11.c:107
const char * filename
Definition: getx11.h:136
int blue_shift
Definition: getx11.c:68
int scanargs(int argc, char **argv, const char *format,...)
Definition: scanargs.c:94
Boolean mono_color
Definition: getx11.h:168
void init_color(register image_information *img)
#define ACTION_DEFAULT
Definition: getx11.c:1019
void find_appropriate_visual(register image_information *img)
void map_rgb_to_rgb(image_information *img, rle_pixel **in_rows, rle_pixel **out_rows)
Definition: map_scan.c:2139
#define DEFAULT_LEVELS
Definition: getx11.c:54
#define SWAP(v1, v2)
int green_shift
Definition: getx11.c:67
Window icn_window
Definition: getx11.h:125
int screen
Definition: show3.c:29
int xmax
Definition: rle.h:100
Pixel green_mask
Definition: getx11.c:70
Pixel * pixel_table
Definition: getx11.h:179
Window root_window
Definition: getx11.c:76
#define RLE_NO_SPACE
Definition: rle.h:72
#define X_SHARED_MEMORY
Definition: rle_config.h:30
int iflag
Definition: getsun.c:80
void wait_timer(void)
Definition: timer.c:72
static int button_action[3][2]
Definition: getx11.c:1022
Pixel blue_mask
Definition: getx11.c:71
#define ACTION_FLIP_SPEED
Definition: getx11.c:1014
#define RLE_EOF
Definition: rle.h:74
Boolean color_dpy
Definition: getx11.h:169
#define CONST_DECL
Definition: rle_config.h:42
Pixel red_mask
Definition: getx11.c:69
void create_windows(register image_information *img, char *window_geometry)
void handle_exposure(register image_information *img, int x, int y, int width, int height, int img_h)
Boolean binary_img
Definition: getx11.h:163
FILE * rle_open_f_noexit(char *prog_name, char *file_name, char *mode)
Definition: rle_open_f.c:57
void set_timer(unsigned n)
Definition: timer.c:46
char * rle_getcom(char *name, rle_hdr *the_hdr) const
Definition: rle_getcom.c:81
Boolean sep_colors
Definition: getx11.h:167
#define ACTION_PIXEL_INFO
Definition: getx11.c:1015
#define ACTION_SWITCH_MAG_MODE
Definition: getx11.c:1010
#define SAVED_RLE_ROW(img, y)
Definition: getx11.h:192
#define DPRINTF
Definition: getx11.h:62
#define RLE_CLR_BIT(glob, bit)
Definition: rle.h:124
void destroy_X_image(image_information *img, XImage *image)
Definition: x11_stuff.c:238
void get_dither_colors(register image_information *img, rle_hdr *img_hdr)
int ymax
Definition: rle.h:100
void set_circle_cursor(Window window)
Definition: x11_stuff.c:70
Pixmap icn_pixmap
Definition: getx11.h:127
XImage * image
Definition: getx11.h:129
XImage * icn_image
Definition: getx11.h:129
void set_watch_cursor(Window window)
Definition: x11_stuff.c:63
void determine_icon_size(int image_width, int image_height, int *icon_width, int *icon_height, int *icon_factor)
Definition: x11_stuff.c:466
#define ACTION_RESIZE
Definition: getx11.c:1018
Boolean mono_img
Definition: getx11.h:164
rle_pixel ** in_cmap
Definition: getx11.h:171
#define RLE_ALPHA
Definition: rle.h:65
void map_rgb_to_bw(image_information *img, rle_pixel **rows, register rle_pixel *bw_row)
Pixel black_pixel
Definition: getx11.h:180
#define ACTION_UNMAGNIFY
Definition: getx11.c:1008
#define ACTION_FLIP_FORWARD
Definition: getx11.c:1011
VOID_FUNCTION * MAG_scanline
Definition: getx11.h:144
Window pix_info_window
Definition: getx11.h:126
void DrawSpeedWindow(image_information *img, int s)
Definition: x11_stuff.c:2062
#define MAXIMUM_LEVELS
Definition: getx11.c:55
#define MALLOC_FAILURE
Definition: getx11.h:56
image_information * img_info
Definition: getx11.c:106
#define INHERIT(thing)
image_information * action_flip_book_cycle(image_information *img, image_information *img_info, int n, Boolean flip_forward, int flip_book_udelay)
Definition: getx11.c:1404
#define COUNT_OF(_array_)
Definition: getx11.h:50
void put_X_image(image_information *img, Drawable d, GC gc, XImage *image, int src_x, int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height)
Definition: x11_stuff.c:446
Colormap colormap
Definition: getx11.h:130
Boolean dither_img
Definition: getx11.h:165
int allocate_ximage(image_information *img, Boolean reallocate)
Definition: x11_stuff.c:301
image_information * action_flip_backward(image_information *img, image_information *img_info, int flip_book_udelay, int n, unsigned long mask, XEvent *event, Boolean *found_event)
Definition: getx11.c:1377
double display_gamma
Definition: getx11.c:64
#define Min(x, y)
Definition: getx11.h:75
VOID_FUNCTION * map_scanline
Definition: getx11.h:143
rle_hdr * rle_hdr_init(rle_hdr *the_hdr)
Definition: rle_hdr.c:267
void DrawPixWindow(image_information *img, int x, int y)
Definition: x11_stuff.c:1997
#define SUCCESS
Definition: getx11.h:59
void free_image_colors(image_information *img)
Definition: x11_stuff.c:1679
XImage * get_X_image(image_information *img, int width, int height, Boolean share)
Definition: x11_stuff.c:135
int resize_window(image_information *img, int new_w, int new_h)
Definition: getx11.c:1424
FILE * rle_file
Definition: rle.h:114
array16 * dm16
Definition: getx11.h:177
Pixel white_pixel
Definition: getx11.h:180
#define ACTION_FLIP_STEP
Definition: getx11.c:1012
Boolean do_sharing
Definition: getx11.c:84
int ncolors
Definition: rle.h:100
unsigned long Pixel
Definition: getx11.h:54
void set_left_ptr_cursor(Window window)
Definition: x11_stuff.c:77