home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume34 / imagemagick / part11 < prev    next >
Text File  |  1992-12-14  |  59KB  |  1,807 lines

  1. Newsgroups: comp.sources.misc
  2. From: cristy@eplrx7.es.duPont.com (John Cristy)
  3. Subject:  v34i039:  imagemagick - X11 image processing and display v2.2, Part11/26
  4. Message-ID: <1992Dec15.035050.21467@sparky.imd.sterling.com>
  5. X-Md4-Signature: b792d10602d944a256778af349aeed98
  6. Date: Tue, 15 Dec 1992 03:50:50 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: cristy@eplrx7.es.duPont.com (John Cristy)
  10. Posting-number: Volume 34, Issue 39
  11. Archive-name: imagemagick/part11
  12. Environment: UNIX, VMS, X11, SGI, DEC, Cray, Sun, Vax
  13.  
  14. #!/bin/sh
  15. # this is Part.11 (part 11 of a multipart archive)
  16. # do not concatenate these parts, unpack them in order with /bin/sh
  17. # file ImageMagick/display.c continued
  18. #
  19. if test ! -r _shar_seq_.tmp; then
  20.     echo 'Please unpack part 1 first!'
  21.     exit 1
  22. fi
  23. (read Scheck
  24.  if test "$Scheck" != 11; then
  25.     echo Please unpack part "$Scheck" next!
  26.     exit 1
  27.  else
  28.     exit 0
  29.  fi
  30. ) < _shar_seq_.tmp || exit 1
  31. if test ! -f _shar_wnt_.tmp; then
  32.     echo 'x - still skipping ImageMagick/display.c'
  33. else
  34. echo 'x - continuing file ImageMagick/display.c'
  35. sed 's/^X//' << 'SHAR_EOF' >> 'ImageMagick/display.c' &&
  36. %  its documentation for any purpose is hereby granted without fee,           %
  37. %  provided that the above Copyright notice appear in all copies and that     %
  38. %  both that Copyright notice and this permission notice appear in            %
  39. %  supporting documentation, and that the name of E. I. du Pont de Nemours    %
  40. %  & Company not be used in advertising or publicity pertaining to            %
  41. %  distribution of the software without specific, written prior               %
  42. %  permission.  E. I. du Pont de Nemours & Company makes no representations   %
  43. %  about the suitability of this software for any purpose.  It is provided    %
  44. %  "as is" without express or implied warranty.                               %
  45. %                                                                             %
  46. %  E. I. du Pont de Nemours & Company disclaims all warranties with regard    %
  47. %  to this software, including all implied warranties of merchantability      %
  48. %  and fitness, in no event shall E. I. du Pont de Nemours & Company be       %
  49. %  liable for any special, indirect or consequential damages or any           %
  50. %  damages whatsoever resulting from loss of use, data or profits, whether    %
  51. %  in an action of contract, negligence or other tortious action, arising     %
  52. %  out of or in connection with the use or performance of this software.      %
  53. %                                                                             %
  54. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  55. %
  56. %  Display is a machine architecture independent image processing
  57. %  and display program.  It can display any image in the MIFF format on
  58. %  any workstation display running X.  Display first determines the
  59. %  hardware capabilities of the workstation.  If the number of unique
  60. %  colors in the image is less than or equal to the number the workstation
  61. %  can support, the image is displayed in an X window.  Otherwise the
  62. %  number of colors in the image is first reduced to match the color
  63. %  resolution of the workstation before it is displayed.
  64. %
  65. %  This means that a continuous-tone 24 bits-per-pixel image can display on a
  66. %  8 bit pseudo-color device or monochrome device.  In most instances the
  67. %  reduced color image closely resembles the original.  Alternatively, a
  68. %  monochrome or pseudo-color image can display on a continuous-tone 24
  69. %  bits-per-pixel device.
  70. %
  71. %  The Display program command syntax is:
  72. %
  73. %  Usage: display [options ...] file [ [options ...] file ...]
  74. %
  75. %  Where options include:
  76. %    -backdrop           display image centered on a backdrop
  77. %    -clip geometry      preferred size and location of the clipped image
  78. %    -colormap type      Shared or Private
  79. %    -colors value       preferred number of colors in the image
  80. %    -colorspace type    GRAY, RGB, XYZ, YIQ, or YUV
  81. %    -compress type      RunlengthEncoded or QEncoded
  82. %    -delay seconds      display the next image after pausing
  83. %    -density geometry   vertical and horizonal density of the image
  84. %    -display server     display image to this X server
  85. %    -dither             apply Floyd/Steinberg error diffusion to image
  86. %    -enhance            apply a digital filter to enhance a noisy image
  87. %    -gamma value        level of gamma correction
  88. %    -geometry geometry  preferred size and location of the image window
  89. %    -inverse            apply color inversion to image
  90. %    -map type           display image using this Standard Colormap
  91. %    -monochrome         transform image to black and white
  92. %    -noise              reduce noise with a noise peak elimination filter
  93. %    -normalize          tranform image to span the full the range of colors
  94. %    -print filename     write image as Postscript to a file
  95. %    -reflect            reverse image scanlines
  96. %    -rotate degrees     apply Paeth rotation to the image
  97. %    -scale geometry     preferred size factors of the image
  98. %    -scene value        image scene number
  99. %    -treedepth value    depth of the color classification tree
  100. %    -verbose            print detailed information about the image
  101. %    -visual type        display image using this visual type
  102. %    -window id          display image to background of this window
  103. %    -write filename     write image to a file
  104. %
  105. %  In addition to those listed above, you can specify these standard X
  106. %  resources as command line options:  -background, -bordercolor,
  107. %  -borderwidth, -font, -foreground, -iconGeometry, -iconic, -name, or
  108. %  -title.
  109. %
  110. %  Change '-' to '+' in any option above to reverse its effect.  For
  111. %  example, specify +compress to store the image as uncompressed.
  112. %
  113. %  By default, the image format of `file' is determined by its magic
  114. %  number.  To specify a particular image format, precede the filename
  115. %  with an image format name and a colon (i.e. mtv:image) or specify the
  116. %  image type as the filename suffix (i.e. image.mtv).  Specify 'file' as
  117. %  '-' for standard input or output.
  118. %
  119. %  Buttons:
  120. %    1    press and drag to select a command from a pop-up menu
  121. %    2    press and drag to define a region of the image to clip
  122. %    3    press and drag to define a region of the image to magnify
  123. %
  124. %  Keyboard accelerators:
  125. %    i    display information about the image
  126. %    r    reflect the image scanlines
  127. %    /    rotate the image 90 degrees clockwise
  128. %    \    rotate the image 90 degrees counter-clockwise
  129. %    <    half the image size
  130. %    >    double the image size
  131. %    o    restore the image to its original size
  132. %    a    annotate the image with text
  133. %    c    composite image with another
  134. %    w    write the image to a file
  135. %    p    print the image to a file
  136. %    n    display the next image
  137. %    l    display the last image
  138. %    q    discard all images and exit program
  139. %    1-9  change the level of magnification
  140. %
  141. %
  142. */
  143. X
  144. /*
  145. X  Include declarations.
  146. */
  147. #include "display.h"
  148. #include "image.h"
  149. #include "alien.h"
  150. #include "X.h"
  151. X
  152. /*
  153. X  State declarations.
  154. */
  155. #define ControlState  0x0001
  156. #define DefaultState  0x0000
  157. #define EscapeState  0x0002
  158. #define ExitState  0x0004
  159. #define ImageMappedState  0x0008
  160. #define InfoMappedState  0x0010
  161. #define LastImageState  0x0020
  162. #define MagnifyMappedState  0x0040
  163. #define NextImageState  0x0080
  164. #define PanIconMappedState  0x0100
  165. #define ReconfigureImageState  0x0200
  166. #define TileImageState  0x0400
  167. #define UpdateColormapState  0x0800
  168. #define UpdateConfigurationState  0x1000
  169. X
  170. /*
  171. X  Global declarations.
  172. */
  173. char
  174. X  *application_name;
  175. X
  176. /*
  177. X  Forward declarations.
  178. */
  179. static Cursor
  180. X  XMakeCursor _Declare((Display *,Colormap,Window,char *,char *));
  181. X
  182. static Image
  183. X  *XTileImageWindow _Declare((Display *,XResourceInfo *,XWindows *,Image *,
  184. X    XEvent *));
  185. X
  186. static unsigned int
  187. X  XAnnotateImageWindow _Declare((Display *,XResourceInfo *,XWindows *,Image *)),
  188. X  XCompositeImageWindow _Declare((Display *,XResourceInfo *,XWindows *,
  189. X    Image **)),
  190. X  XConfigureImageWindow _Declare((Display *,XResourceInfo *,XWindows *,
  191. X    unsigned int,unsigned int,Image *)),
  192. X  XReflectImageWindow _Declare((Display *,XWindows *,Image **)),
  193. X  XRotateImageWindow _Declare((Display *,XWindows *,unsigned int,Image **));
  194. X
  195. static void
  196. X  XDrawPanRectangle _Declare((Display *,XWindows *)),
  197. X  XMagnifyImageWindow _Declare((Display *,XResourceInfo *,XWindows *,XEvent *)),
  198. X  XMakeMagnifyImage _Declare((Display *,XResourceInfo *,XWindows *)),
  199. X  XPanImageWindow _Declare((Display *,XWindows *,XEvent *));
  200. X
  201. /*
  202. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  203. %                                                                             %
  204. %                                                                             %
  205. %                                                                             %
  206. %   E r r o r                                                                 %
  207. %                                                                             %
  208. %                                                                             %
  209. %                                                                             %
  210. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  211. %
  212. %  Function Error displays an error message and then terminates the program.
  213. %
  214. %  The format of the Error routine is:
  215. %
  216. %      Error(message,qualifier)
  217. %
  218. %  A description of each parameter follows:
  219. %
  220. %    o message: Specifies the message to display before terminating the
  221. %      program.
  222. %
  223. %    o qualifier: Specifies any qualifier to the message.
  224. %
  225. %
  226. */
  227. void Error(message,qualifier)
  228. char
  229. X  *message,
  230. X  *qualifier;
  231. {
  232. X  (void) fprintf(stderr,"%s: %s",application_name,message);
  233. X  if (qualifier != (char *) NULL)
  234. X    (void) fprintf(stderr," (%s)",qualifier);
  235. X  (void) fprintf(stderr,".\n");
  236. X  exit(1);
  237. }
  238. X
  239. /*
  240. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  241. %                                                                             %
  242. %                                                                             %
  243. %                                                                             %
  244. %   U s a g e                                                                 %
  245. %                                                                             %
  246. %                                                                             %
  247. %                                                                             %
  248. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  249. %
  250. %  Function Usage displays the program command syntax.
  251. %
  252. %  The format of the Usage routine is:
  253. %
  254. %      Usage(terminate)
  255. %
  256. %  A description of each parameter follows:
  257. %
  258. %    o terminate: A value other than zero is returned if the program is to
  259. %      terminate immediately.
  260. %
  261. */
  262. static void Usage(terminate)
  263. unsigned int
  264. X  terminate;
  265. {
  266. X  char
  267. X    **p;
  268. X
  269. X  static char
  270. X    *buttons[]=
  271. X    {
  272. X      "1    press and drag to select a command from a pop-up menu",
  273. X      "2    press and drag to define a region of the image to clip",
  274. X      "3    press and drag to define a region of the image to magnify",
  275. X      (char *) NULL
  276. X    },
  277. X    *keys[]=
  278. X    {
  279. X      "i    display information about the image",
  280. X      "r    reflect the image scanlines",
  281. X      "/    rotate the image 90 degrees clockwise",
  282. X      "\\    rotate the image 90 degrees counter-clockwise",
  283. X      "<    half the image size",
  284. X      ">    double the image size",
  285. X      "o    restore the image to its original size",
  286. X      "a    annotate the image with text",
  287. X      "c    composite image with another",
  288. X      "w    write the image to a file",
  289. X      "p    print the image to a file",
  290. X      "n    display the next image",
  291. X      "l    display the last image",
  292. X      "q    discard all images and exit program",
  293. X      "1-9  change the level of magnification",
  294. X      (char *) NULL
  295. X    },
  296. X    *options[]=
  297. X    {
  298. X      "-backdrop           display image centered on a backdrop",
  299. X      "-clip geometry      preferred size and location of the clipped image",
  300. X      "-colormap type      Shared or Private",
  301. X      "-colors value       preferred number of colors in the image",
  302. X      "-colorspace type    GRAY, RGB, XYZ, YIQ, or YUV",
  303. X      "-compress type      RunlengthEncoded or QEncoded",
  304. X      "-delay seconds      display the next image after pausing",
  305. X      "-density geometry   vertical and horizonal density of the image",
  306. X      "-display server     display image to this X server",
  307. X      "-dither             apply Floyd/Steinberg error diffusion to image",
  308. X      "-enhance            apply a digital filter to enhance a noisy image",
  309. X      "-gamma value        level of gamma correction",
  310. X      "-geometry geometry  preferred size and location of the image window",
  311. X      "-inverse            apply color inversion to image",
  312. X      "-map type           display image using this Standard Colormap",
  313. X      "-monochrome         transform image to black and white",
  314. X      "-noise              reduce noise with a noise peak elimination filter",
  315. X      "-normalize          tranform image to span the full range of colors",
  316. X      "-print filename     write image as Postscript to a file",
  317. X      "-reflect            reflect the image scanlines",
  318. X      "-rotate degrees     apply Paeth rotation to the image",
  319. X      "-scale geometry     preferred size factors of the image",
  320. X      "-scene value        image scene number",
  321. X      "-treedepth value    depth of the color classification tree",
  322. X      "-verbose            print detailed information about the image",
  323. X      "-visual type        display image using this visual type",
  324. X      "-window id          display image to background of this window",
  325. X      "-write filename     write image to a file",
  326. X      (char *) NULL
  327. X    };
  328. X  (void) fprintf(stderr,
  329. X    "Usage: %s [-options ...] file [ [-options ...] file ...]\n",
  330. X    application_name);
  331. X  (void) fprintf(stderr,"\nWhere options include: \n");
  332. X  for (p=options; *p != (char *) NULL; p++)
  333. X    (void) fprintf(stderr,"  %s\n",*p);
  334. X  (void) fprintf(stderr,
  335. X    "\nIn addition to those listed above, you can specify these standard X\n");
  336. X  (void) fprintf(stderr,
  337. X    "resources as command line options:  -background, -bordercolor,\n");
  338. X  (void) fprintf(stderr,
  339. X    "-borderwidth, -font, -foreground, -iconGeometry, -iconic, -name, or\n");
  340. X  (void) fprintf(stderr,"-title.\n");
  341. X  (void) fprintf(stderr,
  342. X    "\nChange '-' to '+' in any option above to reverse its effect.  For\n");
  343. X  (void) fprintf(stderr,
  344. X    "example, specify +compress to store the image as uncompressed.\n");
  345. X  (void) fprintf(stderr,
  346. X    "\nBy default, the image format of `file' is determined by its magic\n");
  347. X  (void) fprintf(stderr,
  348. X    "number.  To specify a particular image format, precede the filename\n");
  349. X  (void) fprintf(stderr,
  350. X    "with an image format name and a colon (i.e. mtv:image) or specify the\n");
  351. X  (void) fprintf(stderr,
  352. X    "image type as the filename suffix (i.e. image.mtv).  Specify 'file' as\n");
  353. X  (void) fprintf(stderr,"'-' for standard input or output.\n");
  354. X  (void) fprintf(stderr,"\nButtons: \n");
  355. X  for (p=buttons; *p != (char *) NULL; p++)
  356. X    (void) fprintf(stderr,"  %s\n",*p);
  357. X  (void) fprintf(stderr,"\nKeyboard accelerators: \n");
  358. X  for (p=keys; *p != (char *) NULL; p++)
  359. X    (void) fprintf(stderr,"  %s\n",*p);
  360. X  if (terminate)
  361. X    exit(1);
  362. }
  363. X
  364. /*
  365. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  366. %                                                                             %
  367. %                                                                             %
  368. %                                                                             %
  369. %   U s e r C o m m a n d                                                     %
  370. %                                                                             %
  371. %                                                                             %
  372. %                                                                             %
  373. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  374. %
  375. %  Function UserCommand makes a transform to the image or image window as
  376. %  specified by a user menu button or keyboard command.
  377. %
  378. %  The format of the UserCommand routine is:
  379. %
  380. %    UserCommand(display,resource_info,window,command,image,state)
  381. %
  382. %  A description of each parameter follows:
  383. %
  384. %    o display: Specifies a connection to an X server; returned from
  385. %      XOpenDisplay.
  386. %
  387. %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
  388. %
  389. %    o window: Specifies a pointer to a XWindows structure.
  390. %
  391. %    o command: Specifies a command to perform.
  392. %
  393. %    o image: Specifies a pointer to a Image structure;  UserCommand
  394. %      may transform the image and return a new image pointer.
  395. %
  396. %    o state: Specifies an unsigned int;  UserCommand may return a
  397. %      modified state.
  398. %
  399. %
  400. */
  401. static void UserCommand(display,resource_info,window,command,image,state)
  402. Display
  403. X  *display;
  404. X
  405. XXResourceInfo
  406. X  *resource_info;
  407. X
  408. XXWindows
  409. X  *window;
  410. X
  411. char
  412. X  command;
  413. X
  414. Image
  415. X  **image;
  416. X
  417. unsigned long int
  418. X  *state;
  419. {
  420. X  char
  421. X    text[2048];
  422. X
  423. X  unsigned int
  424. X    height,
  425. X    status,
  426. X    width;
  427. X
  428. X  XEvent
  429. X    event;
  430. X
  431. X  if (*state & InfoMappedState)
  432. X    XWithdrawWindow(display,window->info.id,window->info.screen);
  433. X  XSync(display,False);
  434. X  while (XCheckTypedWindowEvent(display,window->image.id,Expose,&event))
  435. X    XRefreshWindow(display,&window->image,&event);
  436. X  /*
  437. X    Process user command.
  438. X  */
  439. X  width=0;
  440. X  height=0;
  441. X  switch (command)
  442. X  {
  443. X    case ' ':
  444. X    case '\0':
  445. X      break;
  446. X    case '<':
  447. X    {
  448. X      /*
  449. X        Half image size.
  450. X      */
  451. X      width=window->image.ximage->width >> 1;
  452. X      height=window->image.ximage->height >> 1;
  453. X      break;
  454. X    }
  455. X    case '>':
  456. X    {
  457. X      /*
  458. X        Double the image size.
  459. X      */
  460. X      width=window->image.ximage->width << 1;
  461. X      height=window->image.ximage->height << 1;
  462. X      break;
  463. X    }
  464. X    case '/':
  465. X    case '\\':
  466. X    {
  467. X      /*
  468. X        Rotate image 90 degrees to clockwise or counter-clockwise.
  469. X      */
  470. X      status=XRotateImageWindow(display,window,(unsigned int)
  471. X        (command == '/' ? 90 : 270),image);
  472. X      if (status == False)
  473. X        {
  474. X          XPopupAlert(display,&window->popup,"unable to rotate X image",
  475. X            window->image.name);
  476. X          break;
  477. X        }
  478. X      width=window->image.ximage->height;
  479. X      height=window->image.ximage->width;
  480. X      break;
  481. X    }
  482. X    case 'a':
  483. X    {
  484. X      /*
  485. X        Annotate the image with text.
  486. X      */
  487. X      status=XAnnotateImageWindow(display,resource_info,window,*image);
  488. X      if (status == False)
  489. X        {
  490. X          XPopupAlert(display,&window->popup,"unable to annotate X image",
  491. X            window->image.name);
  492. X          break;
  493. X        }
  494. X      width=window->image.ximage->width;
  495. X      height=window->image.ximage->height;
  496. X      break;
  497. X    }
  498. X    case 'c':
  499. X    {
  500. X      /*
  501. X        Composite image.
  502. X      */
  503. X      status=XCompositeImageWindow(display,resource_info,window,image);
  504. X      if (status == False)
  505. X        {
  506. X          XPopupAlert(display,&window->popup,"unable to composite X image",
  507. X            window->image.name);
  508. X          break;
  509. X        }
  510. X      XMakeStandardColormap(display,window->image.visual_info,resource_info,
  511. X        window->image.pixel_info,*image,window->image.map_info);
  512. X      width=window->image.ximage->width;
  513. X      height=window->image.ximage->height;
  514. X      *state|=UpdateColormapState;
  515. X      break;
  516. X    }
  517. X    case 'i':
  518. X    {
  519. X      /*
  520. X        Display information about the image in the info window.
  521. X      */
  522. X      (void) sprintf(text," [%u] %s %dx%d %s \0",(*image)->scene,
  523. X        (*image)->filename,window->image.ximage->width,
  524. X        window->image.ximage->height,
  525. X        XVisualClassName(window->info.visual_info));
  526. X      if ((*image)->colors > 0)
  527. X        (void) sprintf(text,"%s%uc \0",text,(*image)->colors);
  528. X      (void) strcat(text,(*image)->magick);
  529. X      XSetWindowExtents(window->info,text,2);
  530. X      XMapWindow(display,window->info.id);
  531. X      XDrawImageString(display,window->info.id,window->info.graphic_context,2,
  532. X        window->info.font_info->ascent+2,text,strlen(text));
  533. X      break;
  534. X    }
  535. X    case 'l':
  536. X    case '\b':
  537. X    {
  538. X      /*
  539. X        Display last image.
  540. X      */
  541. X      *state|=LastImageState | ExitState;
  542. X      break;
  543. X    }
  544. X    case 'n':
  545. X    case '\r':
  546. X    {
  547. X      /*
  548. X        Display next image.
  549. X      */
  550. X      *state|=NextImageState | ExitState;
  551. X      break;
  552. X    }
  553. X    case 'o':
  554. X    {
  555. X      /*
  556. X        Restore image window to its original size.
  557. X      */
  558. X      if (window->image.clip_geometry != (char *) NULL)
  559. X        {
  560. X          (void) free((char *) window->image.clip_geometry);
  561. X          window->image.clip_geometry=(char *) NULL;
  562. X          window->image.x=0;
  563. X          window->image.y=0;
  564. X        }
  565. X      width=(*image)->columns;
  566. X      height=(*image)->rows;
  567. X      break;
  568. X    }
  569. X    case 'p':
  570. X    case 'w':
  571. X    {
  572. X      char
  573. X        filename[2048];
  574. X
  575. X      Image
  576. X        *output_image;
  577. X
  578. X      /*
  579. X        Write or print image to file.
  580. X      */
  581. X      (void) strcpy(filename,(*image)->filename);
  582. X      if (command == 'p')
  583. X        {
  584. X          (void) strcpy(text," Printing image... ");
  585. X          if (resource_info->print_filename != (char *) NULL)
  586. X            (void) strcpy(filename,resource_info->print_filename);
  587. X        }
  588. X      else
  589. X        {
  590. X          (void) strcpy(text," Writing image... ");
  591. X          if (resource_info->write_filename != (char *) NULL)
  592. X            (void) strcpy(filename,resource_info->write_filename);
  593. X        }
  594. X      XPopupQuery(display,&window->popup,"File name:",filename);
  595. X      if (*filename == '\0')
  596. X        break;
  597. X      /*
  598. X        Alert user we are busy.
  599. X      */
  600. X      XDefineCursor(display,window->image.id,window->image.busy_cursor);
  601. X      XSetWindowExtents(window->info,text,2);
  602. X      XMapWindow(display,window->info.id);
  603. X      XDrawImageString(display,window->info.id,window->info.graphic_context,2,
  604. X        window->info.font_info->ascent+2,text,strlen(text));
  605. X      XFlush(display);
  606. X      /*
  607. X        Copy image before applying image transforms.
  608. X      */
  609. X      output_image=CopyImage(*image,(*image)->columns,(*image)->rows,True);
  610. X      if (output_image == (Image *) NULL)
  611. X        {
  612. X          XPopupAlert(display,&window->popup,"unable to output image",
  613. X            window->image.name);
  614. X          break;
  615. X        }
  616. X      if ((window->image.clip_geometry != (char *) NULL) ||
  617. X         (output_image->columns != window->image.ximage->width) ||
  618. X         (output_image->rows != window->image.ximage->height))
  619. X        {
  620. X          char
  621. X            image_geometry[2048];
  622. X
  623. X          /*
  624. X            Clip and/or scale image.
  625. X          */
  626. X          (void) sprintf(image_geometry,"%dx%d\0",window->image.ximage->width,
  627. X            window->image.ximage->height);
  628. X          TransformImage(&output_image,window->image.clip_geometry,
  629. X            image_geometry,(char *) NULL);
  630. X        }
  631. X      if (resource_info->colorspace == GRAYColorspace)
  632. X        QuantizeImage(output_image,256,8,resource_info->dither,GRAYColorspace,
  633. X          True);
  634. X      if (resource_info->monochrome)
  635. X        QuantizeImage(output_image,2,8,resource_info->dither,GRAYColorspace,
  636. X          True);
  637. X      if (resource_info->number_colors > 0)
  638. X        if ((output_image->class == DirectClass) ||
  639. X            (output_image->colors > resource_info->number_colors))
  640. X          QuantizeImage(output_image,resource_info->number_colors,
  641. X            resource_info->tree_depth,resource_info->dither,
  642. X            resource_info->colorspace,True);
  643. X      (void) strcpy(output_image->filename,filename);
  644. X      if (command == 'p')
  645. X        (void) PrintImage(output_image,resource_info->image_geometry);
  646. X      else
  647. X        (void) WriteAlienImage(output_image);
  648. X      DestroyImage(output_image);
  649. X      XDefineCursor(display,window->image.id,window->image.cursor);
  650. X      XWithdrawWindow(display,window->info.id,window->info.screen);
  651. X      break;
  652. X    }
  653. X    case 'q':
  654. X    {
  655. X      /*
  656. X        Exit program
  657. X      */
  658. X      *state|=ExitState;  /* exit program */
  659. X      break;
  660. X    }
  661. X    case 'r':
  662. X    {
  663. X      /*
  664. X        Reflect image scanlines.
  665. X      */
  666. X      status=XReflectImageWindow(display,window,image);
  667. X      if (status == False)
  668. X        {
  669. X          XPopupAlert(display,&window->popup,"unable to reflect X image",
  670. X            window->image.name);
  671. X          break;
  672. X        }
  673. X      width=window->image.ximage->width;
  674. X      height=window->image.ximage->height;
  675. X      break;
  676. X    }
  677. X    default:
  678. X    {
  679. X      XBell(display,0);
  680. X      break;
  681. X    }
  682. X  }
  683. X  if ((width > 0) && (height > 0))
  684. X    {
  685. X      unsigned int
  686. X        mask;
  687. X
  688. X      XWindowChanges
  689. X        window_changes;
  690. X
  691. X      /*
  692. X        Image configuration has changed.
  693. X      */
  694. X      status=XConfigureImageWindow(display,resource_info,window,width,height,
  695. X        *image);
  696. X      if (status == False)
  697. X        XPopupAlert(display,&window->popup,"unable to configure X image",
  698. X          window->image.name);
  699. X      /*
  700. X        Window size must not exceed that of the X server screen.
  701. X      */
  702. X      if (width > XDisplayWidth(display,window->image.screen))
  703. X        width=(XDisplayWidth(display,window->image.screen)*7) >> 3;
  704. X      if (height > XDisplayHeight(display,window->image.screen))
  705. X        height=(XDisplayHeight(display,window->image.screen)*7) >> 3;
  706. X      if ((width == window->image.width) && (height == window->image.height))
  707. X        {
  708. X          *state|=UpdateConfigurationState;
  709. X          return;
  710. X        }
  711. X      /*
  712. X        Notify window manager of the new configuration.
  713. X      */
  714. X      window_changes.width=width;
  715. X      window_changes.height=height;
  716. X      mask=CWWidth | CWHeight;
  717. X      if (resource_info->backdrop)
  718. X        {
  719. X          window_changes.x=
  720. X            XDisplayWidth(display,window->image.screen)/2-width/2;
  721. X          window_changes.y=
  722. X            XDisplayHeight(display,window->image.screen)/2-height/2;
  723. X          mask|=CWX | CWY;
  724. X        }
  725. X      XReconfigureWMWindow(display,window->image.id,window->image.screen,mask,
  726. X        &window_changes);
  727. X      *state|=ReconfigureImageState;
  728. X    }
  729. }
  730. X
  731. /*
  732. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  733. %                                                                             %
  734. %                                                                             %
  735. %                                                                             %
  736. %   X A n n o t a t e I m a g e W i n d o w                                   %
  737. %                                                                             %
  738. %                                                                             %
  739. %                                                                             %
  740. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  741. %
  742. %  Function XAnnotateImageWindow annotates the image with text.
  743. %
  744. %  The format of the XAnnotateImageWindow routine is:
  745. %
  746. %    XAnnotateImageWindow(display,resource_info,window,image)
  747. %
  748. %  A description of each parameter follows:
  749. %
  750. %    o display: Specifies a connection to an X server;  returned from
  751. %      XOpenDisplay.
  752. %
  753. %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
  754. %
  755. %    o window: Specifies a pointer to a XWindows structure.
  756. %
  757. %    o image: Specifies a pointer to a Image structure; returned from
  758. %      ReadImage.
  759. %
  760. */
  761. static unsigned int XAnnotateImageWindow(display,resource_info,window,image)
  762. Display
  763. X  *display;
  764. X
  765. XXResourceInfo
  766. X  *resource_info;
  767. X
  768. XXWindows
  769. X  *window;
  770. X
  771. Image
  772. X  *image;
  773. {
  774. X  char
  775. X    *p,
  776. X    text[2048];
  777. X
  778. X  Cursor
  779. X    cursor;
  780. X
  781. X  GC
  782. X    graphic_context;
  783. X
  784. X  int
  785. X    i,
  786. X    x,
  787. X    y;
  788. X
  789. X  static unsigned int
  790. X    font_id=0,
  791. X    pen_id=0;
  792. X
  793. X  unsigned int
  794. X    height,
  795. X    mask,
  796. X    status,
  797. X    width;
  798. X
  799. X  unsigned long int
  800. X    state,
  801. X    x_factor,
  802. X    y_factor;
  803. X
  804. X  Window
  805. X    xwindow;
  806. X
  807. X  XAnnotateInfo
  808. X    *annotate_info,
  809. X    *previous_info;
  810. X
  811. X  XColor
  812. X    pen_color;
  813. X
  814. X  XFontStruct
  815. X    *font_info;
  816. X
  817. X  XEvent
  818. X    event,
  819. X    text_event;
  820. X
  821. X  XGCValues
  822. X    graphic_context_value;
  823. X
  824. X  /*
  825. X    Map info window.
  826. X  */
  827. X  state=DefaultState;
  828. X  (void) sprintf(text," %+u%+u  \0",window->image.width,window->image.height);
  829. X  XSetWindowExtents(window->info,text,2);
  830. X  XMapWindow(display,window->info.id);
  831. X  state|=InfoMappedState;
  832. X  /*
  833. X    Track pointer until button 1 is pressed.
  834. X  */
  835. X  XQueryPointer(display,window->image.id,&xwindow,&xwindow,&i,&i,&x,&y,&mask);
  836. X  XSelectInput(display,window->image.id,window->image.attributes.event_mask |
  837. X    PointerMotionMask);
  838. X  do
  839. X  {
  840. X    if (state & InfoMappedState)
  841. X      {
  842. X        /*
  843. X          Display pointer position.
  844. X        */
  845. X        (void) sprintf(text," %+d%+d \0",x-window->image.x,y-window->image.y);
  846. X        XClearWindow(display,window->info.id);
  847. X        XDrawImageString(display,window->info.id,window->info.graphic_context,2,
  848. X          window->info.font_info->ascent+2,text,strlen(text));
  849. X      }
  850. X    /*
  851. X      Wait for next event.
  852. X    */
  853. X    XWindowEvent(display,window->image.id,ButtonPressMask | ButtonReleaseMask |
  854. X      ExposureMask | KeyPressMask | PointerMotionMask,&event);
  855. X    switch (event.type)
  856. X    {
  857. X      case ButtonPress:
  858. X      {
  859. X        if ((event.xbutton.button == Button3) &&
  860. X            (event.xbutton.state & Mod1Mask))
  861. X          {
  862. X            /* 
  863. X              Convert Alt-Button3 to Button2.
  864. X            */
  865. X            event.xbutton.button=Button2;
  866. X            event.xbutton.state&=(~Mod1Mask);
  867. X          }
  868. X        switch (event.xbutton.button)
  869. X        {
  870. X          case Button1:
  871. X          {
  872. X            /*
  873. X              Change to text entering mode.
  874. X            */
  875. X            x=event.xbutton.x;
  876. X            y=event.xbutton.y;
  877. X            state|=ExitState;
  878. X            break;
  879. X          }
  880. X          case Button2:
  881. X          {
  882. X            char
  883. X              font_name[2048],
  884. X              *MenuSelections[MaxNumberFonts];
  885. X
  886. X            int
  887. X              font_number;
  888. X
  889. X            /*
  890. X              Initialize menu selections.
  891. X            */
  892. X            for (i=0; i < MaxNumberFonts; i++)
  893. X              MenuSelections[i]=resource_info->font_name[i];
  894. X            /*
  895. X              Select a font name from the pop-up menu.
  896. X            */
  897. X            font_number=XPopupMenu(display,&window->popup,event.xbutton.x_root,
  898. X              event.xbutton.y_root,"Pen Fonts",MenuSelections,MaxNumberFonts,
  899. X              font_name);
  900. X            if (*font_name != '\0')
  901. X              {
  902. X                /*
  903. X                  Initialize font info.
  904. X                */
  905. X                font_info=XLoadQueryFont(display,font_name);
  906. X                if (font_info == (XFontStruct *) NULL)
  907. X                  XPopupAlert(display,&window->popup,"unable to load font",
  908. X                    font_name);
  909. X                else
  910. X                  {
  911. X                    font_id=font_number;
  912. X                    XFreeFont(display,font_info);
  913. X                  }
  914. X              }
  915. X            break;
  916. X          }
  917. X          case Button3:
  918. X          {
  919. X            char
  920. X              color_name[2048],
  921. X              *MenuSelections[MaxNumberPens];
  922. X
  923. X            int
  924. X              pen_number;
  925. X
  926. X            /*
  927. X              Initialize menu selections.
  928. X            */
  929. X            for (i=0; i < MaxNumberPens; i++)
  930. X              MenuSelections[i]=resource_info->pen_color[i];
  931. X            /*
  932. X              Select a font color from the pop-up menu.
  933. X            */
  934. X            pen_number=XPopupMenu(display,&window->popup,event.xbutton.x_root,
  935. X              event.xbutton.y_root,"Pen Colors",MenuSelections,MaxNumberPens,
  936. X              color_name);
  937. X            if (*color_name != '\0')
  938. X              pen_id=pen_number;
  939. X            break;
  940. X          }
  941. X        }
  942. X        break;
  943. X      }
  944. X      case KeyPress:
  945. X      {
  946. X        static char
  947. X          command[2048];
  948. X
  949. X        static KeySym
  950. X          key_symbol;
  951. X
  952. X        /*
  953. X          Respond to a user key press.
  954. X        */
  955. X        *command='\0';
  956. X        XLookupString((XKeyEvent *) &event.xkey,command,sizeof(command),
  957. X          &key_symbol,(XComposeStatus *) NULL);
  958. X        if (key_symbol == XK_Escape)
  959. X          {
  960. X            /*
  961. X              Prematurely exit.
  962. X            */
  963. X            state|=EscapeState;
  964. X            state|=ExitState;
  965. X            break;
  966. X          }
  967. X        break;
  968. X      }
  969. X      case Expose:
  970. X      {
  971. X        /*
  972. X          Refresh image window.
  973. X        */
  974. X        XRefreshWindow(display,&window->image,&event);
  975. X        break;
  976. X      }
  977. X      case MotionNotify:
  978. X      {
  979. X        /*
  980. X          Discard pending pointer motion events.
  981. X        */
  982. X        while (XCheckMaskEvent(display,PointerMotionMask,&event));
  983. X        x=event.xmotion.x;
  984. X        y=event.xmotion.y;
  985. X        /*
  986. X          Map and unmap info window as cursor crosses its boundaries.
  987. X        */
  988. X        if (state & InfoMappedState)
  989. X          {
  990. X            if ((x < (window->info.x+window->info.width)) &&
  991. X                (y < (window->info.y+window->info.height)))
  992. X              {
  993. X                XWithdrawWindow(display,window->info.id,window->info.screen);
  994. X                state&=(~InfoMappedState);
  995. X              }
  996. X          }
  997. X        else
  998. X          if ((x > (window->info.x+window->info.width)) ||
  999. X              (y > (window->info.y+window->info.height)))
  1000. X            {
  1001. X              XMapWindow(display,window->info.id);
  1002. X              state|=InfoMappedState;
  1003. X            }
  1004. X        break;
  1005. X      }
  1006. X      default:
  1007. X        break;
  1008. X    }
  1009. X  } while (!(state & ExitState));
  1010. X  XSelectInput(display,window->image.id,window->image.attributes.event_mask);
  1011. X  if (state & InfoMappedState)
  1012. X    XWithdrawWindow(display,window->info.id,window->info.screen);
  1013. X  XFlush(display);
  1014. X  if (state & EscapeState)
  1015. X    return(True);
  1016. X  /*
  1017. X    Set font info and pen color.
  1018. X  */
  1019. X  font_info=XLoadQueryFont(display,resource_info->font_name[font_id]);
  1020. X  if (font_info == (XFontStruct *) NULL)
  1021. X    {
  1022. X      XPopupAlert(display,&window->popup,"unable to load font",
  1023. X        resource_info->font_name[font_id]);
  1024. X      font_info=window->image.font_info;
  1025. X    }
  1026. X  /*
  1027. X    Initialize graphic context.
  1028. X  */
  1029. X  pen_color=window->image.pixel_info->pen_color[pen_id];
  1030. X  graphic_context_value.background=
  1031. X    window->image.pixel_info->background_color.pixel;
  1032. X  graphic_context_value.foreground=pen_color.pixel;
  1033. X  graphic_context_value.font=font_info->fid;
  1034. X  graphic_context_value.function=GXcopy;
  1035. X  graphic_context_value.line_width=WindowBorderWidth;
  1036. X  graphic_context_value.plane_mask=AllPlanes;
  1037. X  graphic_context=XCreateGC(display,window->image.id,GCBackground |
  1038. X    GCFont | GCForeground | GCFunction | GCLineWidth | GCPlaneMask,
  1039. X    &graphic_context_value);
  1040. X  if (graphic_context == (GC) NULL)
  1041. X    return(False);
  1042. X  /*
  1043. X    Check boundary conditions.
  1044. X  */
  1045. X  if ((x+font_info->max_bounds.width) >= window->image.width)
  1046. X    x=window->image.width-font_info->max_bounds.width;
  1047. X  if (y < (font_info->ascent+font_info->descent))
  1048. X    y=font_info->ascent+font_info->descent;
  1049. X  if ((font_info->max_bounds.width > window->image.width) ||
  1050. X      ((font_info->ascent+font_info->descent) >= window->image.height))
  1051. X    return(False);
  1052. X  /*
  1053. X    Initialize annotate structure.
  1054. X  */
  1055. X  annotate_info=(XAnnotateInfo *) malloc(sizeof(XAnnotateInfo));
  1056. X  if (annotate_info == (XAnnotateInfo *) NULL)
  1057. X    return(False);
  1058. X  XGetAnnotateInfo(annotate_info);
  1059. X  annotate_info->x=x;
  1060. X  annotate_info->y=y;
  1061. X  annotate_info->height=font_info->ascent+font_info->descent;
  1062. X  annotate_info->font_info=font_info;
  1063. X  annotate_info->text=(char *) malloc(
  1064. X    (window->image.width/Max(font_info->min_bounds.width,1)+2)*sizeof(char));
  1065. X  if (annotate_info->text == (char *) NULL)
  1066. X    return(False);
  1067. X  /*
  1068. X    Begin annotating the image with text.
  1069. X  */
  1070. X  state=DefaultState;
  1071. X  cursor=XCreateFontCursor(display,XC_pencil);
  1072. X  XRecolorCursor(display,cursor,&window->image.pixel_info->background_color,
  1073. X    &window->image.pixel_info->foreground_color);
  1074. X  XDefineCursor(display,window->image.id,cursor);
  1075. X  XDrawString(display,window->image.id,graphic_context,x,y,"_",1);
  1076. X  text_event.xexpose.width=(unsigned int) font_info->max_bounds.width;
  1077. X  text_event.xexpose.height=annotate_info->height;
  1078. X  p=annotate_info->text;
  1079. X  *p='\0';
  1080. X  do
  1081. X  {
  1082. X    /*
  1083. X      Wait for next event.
  1084. X    */
  1085. X    XWindowEvent(display,window->image.id,ExposureMask | KeyPressMask,&event);
  1086. X    switch (event.type)
  1087. X    {
  1088. X      case Expose:
  1089. X      {
  1090. X        if (event.xexpose.count == 0)
  1091. X          {
  1092. X            /*
  1093. X              Refresh image window.
  1094. X            */
  1095. X            XRefreshWindow(display,&window->image,(XEvent *) NULL);
  1096. X            XDrawString(display,window->image.id,graphic_context,
  1097. X              annotate_info->x,annotate_info->y,annotate_info->text,
  1098. X              strlen(annotate_info->text));
  1099. X            XDrawString(display,window->image.id,graphic_context,x,y,"_",1);
  1100. X          }
  1101. X        break;
  1102. X      }
  1103. X      case KeyPress:
  1104. X      {
  1105. X        static char
  1106. X          command[2048];
  1107. X
  1108. X        static KeySym
  1109. X          key_symbol;
  1110. X
  1111. X        /*
  1112. X          Erase text cursor.
  1113. X        */
  1114. X        text_event.xexpose.x=x;
  1115. X        text_event.xexpose.y=y-font_info->max_bounds.ascent;
  1116. X        XRefreshWindow(display,&window->image,&text_event);
  1117. X        /*
  1118. X          Respond to a user key press.
  1119. X        */
  1120. X        *command='\0';
  1121. X        XLookupString((XKeyEvent *) &event.xkey,command,sizeof(command),
  1122. X          &key_symbol,(XComposeStatus *) NULL);
  1123. X        if (key_symbol == XK_Control_L)
  1124. X          {
  1125. X            state|=ControlState;
  1126. X            break;
  1127. X          }
  1128. X        if (state & ControlState)
  1129. X          switch (key_symbol)
  1130. X          {
  1131. X            case XK_u:
  1132. X            case XK_U:
  1133. X            {
  1134. X              key_symbol=XK_Delete;
  1135. X              break;
  1136. X            }
  1137. X            default:
  1138. X              break;
  1139. X          }
  1140. X        switch (key_symbol)
  1141. X        {
  1142. X          case XK_BackSpace:
  1143. X          {
  1144. X            /*
  1145. X              Erase one character.
  1146. X            */
  1147. X            if (p == annotate_info->text)
  1148. X              if (annotate_info->previous == (XAnnotateInfo *) NULL)
  1149. X                break;
  1150. X              else
  1151. X                {
  1152. X                  /*
  1153. X                    Go to end of the previous line of text.
  1154. X                  */
  1155. X                  annotate_info=annotate_info->previous;
  1156. X                  p=annotate_info->text;
  1157. X                  x=annotate_info->x+annotate_info->width;
  1158. X                  y=annotate_info->y;
  1159. X                  if (annotate_info->width > 0)
  1160. X                    p+=strlen(annotate_info->text);
  1161. X                  break;
  1162. X                }
  1163. X            p--;
  1164. X            x-=XTextWidth(font_info,p,1);
  1165. X            text_event.xexpose.x=x;
  1166. X            text_event.xexpose.y=y-font_info->max_bounds.ascent;
  1167. X            XRefreshWindow(display,&window->image,&text_event);
  1168. X            break;
  1169. X          }
  1170. X          case XK_Delete:
  1171. X          {
  1172. X            /*
  1173. X              Erase the entire line of text.
  1174. X            */
  1175. X            while (p != annotate_info->text)
  1176. X            {
  1177. X              p--;
  1178. X              x-=XTextWidth(font_info,p,1);
  1179. X              text_event.xexpose.x=x;
  1180. X              XRefreshWindow(display,&window->image,&text_event);
  1181. X            }
  1182. X            break;
  1183. X          }
  1184. X          case XK_Escape:
  1185. X          {
  1186. X            /*
  1187. X              Finished annotating.
  1188. X            */
  1189. X            annotate_info->width=XTextWidth(font_info,annotate_info->text,
  1190. X              strlen(annotate_info->text));
  1191. X            XRefreshWindow(display,&window->image,&text_event);
  1192. X            state|=ExitState;
  1193. X            break;
  1194. X          }
  1195. X          default:
  1196. X          {
  1197. X            /*
  1198. X              Draw a single character on the image window.
  1199. X            */
  1200. X            if (*command == '\0')
  1201. X              break;
  1202. X            *p=(*command);
  1203. X            XDrawString(display,window->image.id,graphic_context,x,y,p,1);
  1204. X            x+=XTextWidth(font_info,p,1);
  1205. X            p++;
  1206. X            if ((x+font_info->max_bounds.width) < window->image.width)
  1207. X              break;
  1208. X          }
  1209. X          case XK_Return:
  1210. X          {
  1211. X            /*
  1212. X              Advance to the next line of text.
  1213. X            */
  1214. X            *p='\0';
  1215. X            annotate_info->width=XTextWidth(font_info,annotate_info->text,
  1216. X              strlen(annotate_info->text));
  1217. X            if (annotate_info->next != (XAnnotateInfo *) NULL)
  1218. X              {
  1219. X                /*
  1220. X                  Line of text already exists.
  1221. X                */
  1222. X                annotate_info=annotate_info->next;
  1223. X                x=annotate_info->x;
  1224. X                y=annotate_info->y;
  1225. X                p=annotate_info->text;
  1226. X                break;
  1227. X              }
  1228. X            annotate_info->next=(XAnnotateInfo *) malloc(sizeof(XAnnotateInfo));
  1229. X            if (annotate_info->next == (XAnnotateInfo *) NULL)
  1230. X              return(False);
  1231. X            *annotate_info->next=(*annotate_info);
  1232. X            annotate_info->next->previous=annotate_info;
  1233. X            annotate_info=annotate_info->next;
  1234. X            annotate_info->text=(char *) malloc((window->image.width/
  1235. X              Max(font_info->min_bounds.width,1)+2)*sizeof(char));
  1236. X            if (annotate_info->text == (char *) NULL)
  1237. X              return(False);
  1238. X            annotate_info->y+=annotate_info->height;
  1239. X            if (annotate_info->y > window->image.height)
  1240. X              annotate_info->y=annotate_info->height;
  1241. X            annotate_info->next=(XAnnotateInfo *) NULL;
  1242. X            x=annotate_info->x;
  1243. X            y=annotate_info->y;
  1244. X            p=annotate_info->text;
  1245. X            break;
  1246. X          }
  1247. X        }
  1248. X        /*
  1249. X          Display text cursor.
  1250. X        */
  1251. X        *p='\0';
  1252. X        XDrawString(display,window->image.id,graphic_context,x,y,"_",1);
  1253. X        break;
  1254. X      }
  1255. X      case KeyRelease:
  1256. X      {
  1257. X        static char
  1258. X          command[2048];
  1259. X
  1260. X        static KeySym
  1261. X          key_symbol;
  1262. X
  1263. X        /*
  1264. X          Respond to a user key release.
  1265. X        */
  1266. X        *command='\0';
  1267. X        XLookupString((XKeyEvent *) &event.xkey,command,sizeof(command),
  1268. X          &key_symbol,(XComposeStatus *) NULL);
  1269. X        if (key_symbol == XK_Control_L)
  1270. X          state&=(~ControlState);
  1271. X        break;
  1272. X      }
  1273. X      default:
  1274. X        break;
  1275. X    }
  1276. X  } while (!(state & ExitState));
  1277. X  XDefineCursor(display,window->image.id,window->image.busy_cursor);
  1278. X  XFreeCursor(display,cursor);
  1279. X  XFlush(display);
  1280. X  /*
  1281. X    Annotation is relative to image configuration.
  1282. X  */
  1283. X  x=0;
  1284. X  y=0;
  1285. X  width=image->columns;
  1286. X  height=image->rows;
  1287. X  if (window->image.clip_geometry != (char *) NULL)
  1288. X    (void) XParseGeometry(window->image.clip_geometry,&x,&y,&width,&height);
  1289. X  /*
  1290. X    Initialize annotated image.
  1291. X  */
  1292. X  while (annotate_info != (XAnnotateInfo *) NULL)
  1293. X  {
  1294. X    if (annotate_info->width == 0)
  1295. X      {
  1296. X        /*
  1297. X          No text on this line--  go to the next line of text.
  1298. X        */
  1299. X        previous_info=annotate_info->previous;
  1300. X        (void) free((char *) annotate_info->text);
  1301. X        (void) free((char *) annotate_info);
  1302. X        annotate_info=previous_info;
  1303. X        continue;
  1304. X      }
  1305. X    /*
  1306. X      Determine foreground pixel index for font color.
  1307. X    */
  1308. X    window->image.pixel_info->annotate_color=pen_color;
  1309. X    window->image.pixel_info->annotate_index=0;
  1310. X    if (window->image.pixel_info->colors > 0)
  1311. X      for (i=0; i < window->image.pixel_info->colors; i++)
  1312. X        if (window->image.pixel_info->pixels[i] == pen_color.pixel)
  1313. X          {
  1314. X            window->image.pixel_info->annotate_index=i;
  1315. X            break;
  1316. X          }
  1317. X    /*
  1318. X      Define the annotate geometry string.
  1319. X    */
  1320. X    x_factor=UpShift(width)/window->image.ximage->width;
  1321. X    annotate_info->x+=window->image.x;
  1322. X    annotate_info->x=DownShift(annotate_info->x*x_factor);
  1323. X    y_factor=UpShift(height)/window->image.ximage->height;
  1324. X    annotate_info->y+=(window->image.y-font_info->ascent);
  1325. X    annotate_info->y=DownShift(annotate_info->y*y_factor);
  1326. X    (void) sprintf(annotate_info->geometry,"%ux%u%+d%+d\0",
  1327. X      (unsigned int) DownShift(annotate_info->width*x_factor),
  1328. X      (unsigned int) DownShift(annotate_info->height*y_factor),
  1329. X      annotate_info->x+x,annotate_info->y+y);
  1330. X    /*
  1331. X      Annotate image with text.
  1332. X    */
  1333. X    status=XAnnotateImage(display,&window->image,annotate_info,False,image);
  1334. X    if (status == 0)
  1335. X      return(False);
  1336. X    /*
  1337. X      Free up memory.
  1338. X    */
  1339. X    previous_info=annotate_info->previous;
  1340. X    (void) free((char *) annotate_info->text);
  1341. X    (void) free((char *) annotate_info);
  1342. X    annotate_info=previous_info;
  1343. X  }
  1344. X  XDefineCursor(display,window->image.id,window->image.cursor);
  1345. X  /*
  1346. X    Free up memory.
  1347. X  */
  1348. X  if (font_info != window->image.font_info)
  1349. X    XFreeFont(display,font_info);
  1350. X  XFreeGC(display,graphic_context);
  1351. X  return(True);
  1352. }
  1353. X
  1354. /*
  1355. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1356. %                                                                             %
  1357. %                                                                             %
  1358. %                                                                             %
  1359. %   X C l i p I m a g e W i n d o w                                           %
  1360. %                                                                             %
  1361. %                                                                             %
  1362. %                                                                             %
  1363. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1364. %
  1365. %  Function XClipImageWindow displays a rectangle whose sizes changes as the
  1366. %  pointer moves.  When the mouse button is released, the geometry of the image
  1367. %  region defined within the rectangle is returned.
  1368. %
  1369. %  The format of the XClipImageWindow routine is:
  1370. %
  1371. %    XClipImageWindow(display,resource_info,window,event,image,state)
  1372. %
  1373. %  A description of each parameter follows:
  1374. %
  1375. %    o display: Specifies a connection to an X server; returned from
  1376. %      XOpenDisplay.
  1377. %
  1378. %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
  1379. %
  1380. %    o window: Specifies a pointer to a XWindows structure.
  1381. %
  1382. %    o event: Specifies a pointer to a XEvent structure.  If it is NULL,
  1383. %      the entire image is refreshed.
  1384. %
  1385. %    o image: Specifies a pointer to a Image structure.
  1386. %
  1387. %    o state: Specifies an unsigned int;  XClipImageWindow may return a
  1388. %      modified state.
  1389. %
  1390. %
  1391. */
  1392. static void XClipImageWindow(display,resource_info,window,event,image,state)
  1393. Display
  1394. X  *display;
  1395. X
  1396. XXResourceInfo
  1397. X  *resource_info;
  1398. X
  1399. XXWindows
  1400. X  *window;
  1401. X
  1402. XXEvent
  1403. X  *event;
  1404. X
  1405. Image
  1406. X  *image;
  1407. X
  1408. unsigned long int
  1409. X  *state;
  1410. {
  1411. #define ClipRectangle(clip_info)  \
  1412. {  \
  1413. X  if ((clip_info.width*clip_info.height) >= MinimumClipArea) \
  1414. X    {  \
  1415. X      XSetFunction(display,window->image.graphic_context,GXinvert);  \
  1416. X      XDrawRectangle(display,window->image.id,window->image.graphic_context,  \
  1417. X        clip_info.x,clip_info.y,clip_info.width-1,clip_info.height-1);  \
  1418. X      XSetFunction(display,window->image.graphic_context,GXcopy);  \
  1419. X    }  \
  1420. }
  1421. #define MinimumClipArea  (unsigned int) 9
  1422. X
  1423. X  char
  1424. X    text[2048];
  1425. X
  1426. X  int
  1427. X    x_offset,
  1428. X    y_offset;
  1429. X
  1430. X  XRectangle
  1431. X    clip_info;
  1432. X
  1433. X  unsigned int
  1434. X    status;
  1435. X
  1436. X  /*
  1437. X    Set the width of info window.
  1438. X  */
  1439. X  (void) sprintf(text," %ux%u%+u%+u \0",window->image.width,
  1440. X    window->image.height,window->image.width,window->image.height);
  1441. X  XSetWindowExtents(window->info,text,2);
  1442. X  /*
  1443. X    Size rectangle as pointer moves until the mouse button is released.
  1444. X  */
  1445. X  x_offset=event->xbutton.x;
  1446. X  y_offset=event->xbutton.y;
  1447. X  clip_info.x=x_offset;
  1448. X  clip_info.y=y_offset;
  1449. X  clip_info.width=0;
  1450. X  clip_info.height=0;
  1451. X  do
  1452. X  {
  1453. X    if ((clip_info.width*clip_info.height) >= MinimumClipArea)
  1454. X      {
  1455. X        /*
  1456. X          Display info and draw clipping rectangle.
  1457. X        */
  1458. X        if (!(*state & InfoMappedState))
  1459. X          {
  1460. X            XMapWindow(display,window->info.id);
  1461. X            *state|=InfoMappedState;
  1462. X          }
  1463. X        (void) sprintf(text," %ux%u%+d%+d\0",clip_info.width,clip_info.height,
  1464. X          clip_info.x,clip_info.y);
  1465. X        XClearWindow(display,window->info.id);
  1466. X        XDrawImageString(display,window->info.id,window->info.graphic_context,2,
  1467. X          window->info.font_info->ascent+2,text,strlen(text));
  1468. X        ClipRectangle(clip_info);
  1469. X      }
  1470. X    else
  1471. X      if (*state & InfoMappedState)
  1472. X        {
  1473. X          /*
  1474. X            Clipping rectangle is too small;  withdraw info window.
  1475. X          */
  1476. X          XWithdrawWindow(display,window->info.id,window->info.screen);
  1477. X          *state&=(~InfoMappedState);
  1478. X        }
  1479. X    /*
  1480. X      Wait for next event.
  1481. X    */
  1482. X    XWindowEvent(display,window->image.id,ButtonPressMask | ButtonMotionMask |
  1483. X      ButtonReleaseMask | ExposureMask,event);
  1484. X    ClipRectangle(clip_info);
  1485. X    switch (event->type)
  1486. X    {
  1487. X      case ButtonPress:
  1488. X        break;
  1489. X      case ButtonRelease:
  1490. X      {
  1491. X        /*
  1492. X          User has committed to clipping rectangle.
  1493. X        */
  1494. X        clip_info.x=event->xbutton.x;
  1495. X        clip_info.y=event->xbutton.y;
  1496. X        *state|=ExitState;
  1497. X        break;
  1498. X      }
  1499. X      case Expose:
  1500. X      {
  1501. X        /*
  1502. X          Refresh image window.
  1503. X        */
  1504. X        XRefreshWindow(display,&window->image,event);
  1505. X        break;
  1506. X      }
  1507. X      case MotionNotify:
  1508. X      {
  1509. X        /*
  1510. X          Discard pending button motion events.
  1511. X        */
  1512. X        while (XCheckMaskEvent(display,ButtonMotionMask,event));
  1513. X        clip_info.x=event->xmotion.x;
  1514. X        clip_info.y=event->xmotion.y;
  1515. X      }
  1516. X      default:
  1517. X        break;
  1518. X    }
  1519. X    /*
  1520. X      Check boundary conditions.
  1521. X    */
  1522. X    if (clip_info.x < 0)
  1523. X      clip_info.x=0;
  1524. X    else
  1525. X      if (clip_info.x > window->image.width)
  1526. X        clip_info.x=window->image.width-1;
  1527. X    if (clip_info.x < x_offset)
  1528. X      clip_info.width=(unsigned int) (x_offset-clip_info.x);
  1529. X    else
  1530. X      {
  1531. X        clip_info.width=(unsigned int) (clip_info.x-x_offset);
  1532. X        clip_info.x=x_offset;
  1533. X      }
  1534. X    if (clip_info.y < 0)
  1535. X      clip_info.y=0;
  1536. X    else
  1537. X      if (clip_info.y > window->image.height)
  1538. X        clip_info.y=window->image.height-1;
  1539. X    if (clip_info.y < y_offset)
  1540. X      clip_info.height=(unsigned int) (y_offset-clip_info.y);
  1541. X    else
  1542. X      {
  1543. X        clip_info.height=(unsigned int) (clip_info.y-y_offset);
  1544. X        clip_info.y=y_offset;
  1545. X      }
  1546. X  } while (!(*state & ExitState));
  1547. X  *state&=(~ExitState);
  1548. X  ClipRectangle(clip_info);
  1549. X  ClipRectangle(clip_info);
  1550. X  if (*state & InfoMappedState)
  1551. X    XWithdrawWindow(display,window->info.id,window->info.screen);
  1552. X  if ((clip_info.width*clip_info.height) >= MinimumClipArea)
  1553. X    {
  1554. X      int
  1555. X        x,
  1556. X        y;
  1557. X
  1558. X      unsigned int
  1559. X        height,
  1560. X        width;
  1561. X
  1562. X      unsigned long
  1563. X        scale_factor;
  1564. X
  1565. X      XWindowChanges
  1566. X        window_changes;
  1567. X
  1568. X      /*
  1569. X        Clipping geometry is relative to any previous clip geometry.
  1570. X      */
  1571. X      x=0;
  1572. X      y=0;
  1573. X      width=image->columns;
  1574. X      height=image->rows;
  1575. X      if (window->image.clip_geometry != (char *) NULL)
  1576. X        (void) XParseGeometry(window->image.clip_geometry,&x,&y,&width,&height);
  1577. X      else
  1578. X        {
  1579. X          /*
  1580. X            Allocate clip geometry string.
  1581. X          */
  1582. X          window->image.clip_geometry=(char *) malloc(2048*sizeof(char));
  1583. X          if (window->image.clip_geometry == (char *) NULL)
  1584. X            Error("unable to clip X image",window->image.name);
  1585. X        }
  1586. X      /*
  1587. X        Define the clip geometry string from the clipping rectangle.
  1588. X      */
  1589. X      scale_factor=UpShift(width)/window->image.ximage->width;
  1590. X      clip_info.x+=window->image.x;
  1591. X      if (clip_info.x > 0)
  1592. X        x+=DownShift(clip_info.x*scale_factor);
  1593. X      width=DownShift(clip_info.width*scale_factor);
  1594. X      if (width == 0)
  1595. X        width=1;
  1596. X      scale_factor=UpShift(height)/window->image.ximage->height;
  1597. X      clip_info.y+=window->image.y;
  1598. X      if (clip_info.y > 0)
  1599. X        y+=DownShift(clip_info.y*scale_factor);
  1600. X      height=DownShift(clip_info.height*scale_factor);
  1601. X      if (height == 0)
  1602. X        height=1;
  1603. X      (void) sprintf(window->image.clip_geometry,"%ux%u%+d%+d\0",width,height,
  1604. X        x,y);
  1605. X      /*
  1606. X        Image configuration has changed.
  1607. X      */
  1608. X      status=XConfigureImageWindow(display,resource_info,window,clip_info.width,
  1609. X        clip_info.height,image);
  1610. X      if (status == False)
  1611. X        XPopupAlert(display,&window->popup,"unable to configure X image",
  1612. X          window->image.name);
  1613. X      /*
  1614. X        Reconfigure image window as defined by clipping rectangle.
  1615. X      */
  1616. X      window_changes.width=clip_info.width;
  1617. X      window_changes.height=clip_info.height;
  1618. X      XReconfigureWMWindow(display,window->image.id,window->image.screen,
  1619. X        CWWidth | CWHeight,&window_changes);
  1620. X      *state|=ReconfigureImageState;
  1621. X    }
  1622. }
  1623. X
  1624. /*
  1625. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1626. %                                                                             %
  1627. %                                                                             %
  1628. %                                                                             %
  1629. %   X C o m p o s i t e I m a g e W i n d o w                                 %
  1630. %                                                                             %
  1631. %                                                                             %
  1632. %                                                                             %
  1633. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1634. %
  1635. %  Function XCompositeImageWindow requests an image name from the user, reads
  1636. %  the image and composites it with the X window image at a location the user
  1637. %  chooses with the pointer.
  1638. %
  1639. %  The format of the XCompositeImageWindow routine is:
  1640. %
  1641. %    XCompositeImageWindow(display,resource_info,window,image)
  1642. %
  1643. %  A description of each parameter follows:
  1644. %
  1645. %    o display: Specifies a connection to an X server;  returned from
  1646. %      XOpenDisplay.
  1647. %
  1648. %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
  1649. %
  1650. %    o window: Specifies a pointer to a XWindows structure.
  1651. %
  1652. %    o image: Specifies a pointer to a Image structure; returned from
  1653. %      ReadImage.
  1654. %
  1655. */
  1656. static unsigned int XCompositeImageWindow(display,resource_info,window,image)
  1657. Display
  1658. X  *display;
  1659. X
  1660. XXResourceInfo
  1661. X  *resource_info;
  1662. X
  1663. XXWindows
  1664. X  *window;
  1665. X
  1666. Image
  1667. X  **image;
  1668. {
  1669. #define CompositeRectangle(composite_info)  \
  1670. {  \
  1671. X  if ((composite_info.width*composite_info.height) > (unsigned int) 0) \
  1672. X    {  \
  1673. X      XSetFunction(display,window->image.graphic_context,GXinvert);  \
  1674. X      XDrawRectangle(display,window->image.id,window->image.graphic_context,  \
  1675. X        composite_info.x,composite_info.y,composite_info.width-1,  \
  1676. X        composite_info.height-1);  \
  1677. X      XSetFunction(display,window->image.graphic_context,GXcopy);  \
  1678. X    }  \
  1679. }
  1680. X
  1681. X  AlienInfo
  1682. X    alien_info;
  1683. X
  1684. X  char
  1685. X    filename[2048],
  1686. X    text[2048];
  1687. X
  1688. X  Cursor
  1689. X    cursor;
  1690. X
  1691. X  Image
  1692. X    *composite_image;
  1693. X
  1694. X  int
  1695. X    i,
  1696. X    x,
  1697. X    y;
  1698. X
  1699. X  static unsigned int
  1700. X    operator = OverCompositeOp;
  1701. X
  1702. X  unsigned int
  1703. X    height,
  1704. X    mask,
  1705. X    width;
  1706. X
  1707. X  unsigned long int
  1708. X    scale_factor,
  1709. X    state;
  1710. X
  1711. X  Window
  1712. X    xwindow;
  1713. X
  1714. X  XEvent
  1715. X    event;
  1716. X
  1717. X  XRectangle
  1718. X    composite_info;
  1719. X
  1720. X  /*
  1721. X    Request image file name from user.
  1722. X  */
  1723. X  *filename='\0';
  1724. X  XPopupQuery(display,&window->popup,"File name:",filename);
  1725. X  XFlush(display);
  1726. X  if (*filename == '\0')
  1727. X    return(True);
  1728. X  /*
  1729. X    Read image.
  1730. X  */
  1731. X  XDefineCursor(display,window->image.id,window->image.busy_cursor);
  1732. X  XFlush(display);
  1733. X  GetAlienInfo(&alien_info);
  1734. X  (void) strcpy(alien_info.filename,filename);
  1735. X  alien_info.server_name=resource_info->server_name;
  1736. X  alien_info.font=resource_info->font;
  1737. X  composite_image=ReadAlienImage(&alien_info);
  1738. X  XDefineCursor(display,window->image.id,window->image.cursor);
  1739. X  if (composite_image == (Image *) NULL)
  1740. X    {
  1741. X      XPopupAlert(display,&window->popup,"unable to read image",filename);
  1742. X      return(False);
  1743. X    }
  1744. X  /*
  1745. X    Map info window.
  1746. X  */
  1747. X  state=DefaultState;
  1748. X  (void) sprintf(text," %+u%+u  \0",window->image.width,window->image.height);
  1749. X  XSetWindowExtents(window->info,text,2);
  1750. X  XMapWindow(display,window->info.id);
  1751. X  state|=InfoMappedState;
  1752. X  /*
  1753. X    Track pointer until button 1 is pressed.
  1754. X  */
  1755. X  XQueryPointer(display,window->image.id,&xwindow,&xwindow,&i,&i,&x,&y,&mask);
  1756. X  composite_info.x=x;
  1757. X  composite_info.y=y;
  1758. X  composite_info.width=0;
  1759. X  composite_info.height=0;
  1760. X  XSelectInput(display,window->image.id,window->image.attributes.event_mask |
  1761. X    PointerMotionMask);
  1762. X  do
  1763. X  {
  1764. X    if (state & InfoMappedState)
  1765. X      {
  1766. X        /*
  1767. X          Display pointer position.
  1768. X        */
  1769. X        (void) sprintf(text," %+d%+d \0",x-window->image.x,y-window->image.y);
  1770. X        XClearWindow(display,window->info.id);
  1771. X        XDrawImageString(display,window->info.id,window->info.graphic_context,2,
  1772. X          window->info.font_info->ascent+2,text,strlen(text));
  1773. X      }
  1774. X    CompositeRectangle(composite_info);
  1775. X    /*
  1776. X      Wait for next event.
  1777. X    */
  1778. X    XWindowEvent(display,window->image.id,ButtonPressMask | ButtonReleaseMask |
  1779. X      ExposureMask | KeyPressMask | PointerMotionMask,&event);
  1780. X    CompositeRectangle(composite_info);
  1781. X    switch (event.type)
  1782. X    {
  1783. X      case ButtonPress:
  1784. X      {
  1785. X        if ((event.xbutton.button == Button3) &&
  1786. X            (event.xbutton.state & Mod1Mask))
  1787. X          {
  1788. X            /* 
  1789. X              Convert Alt-Button3 to Button2.
  1790. X            */
  1791. X            event.xbutton.button=Button2;
  1792. X            event.xbutton.state&=(~Mod1Mask);
  1793. X          }
  1794. X        switch (event.xbutton.button)
  1795. X        {
  1796. X          case Button1:
  1797. X          {
  1798. X            composite_info.width=composite_image->columns;
  1799. SHAR_EOF
  1800. true || echo 'restore of ImageMagick/display.c failed'
  1801. fi
  1802. echo 'End of  part 11'
  1803. echo 'File ImageMagick/display.c is continued in part 12'
  1804. echo 12 > _shar_seq_.tmp
  1805. exit 0
  1806. exit 0 # Just in case...
  1807.