home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #30 / NN_1992_30.iso / spool / comp / sources / misc / 4179 < prev    next >
Encoding:
Text File  |  1992-12-14  |  57.5 KB  |  1,813 lines

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