home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume8 / wscrawl / part05 < prev    next >
Text File  |  1990-07-15  |  55KB  |  1,684 lines

  1. Path: uunet!samsung!munnari.oz.au!metro!sunaus.oz!newstop!sun!hpcvlx.cv.hp.com
  2. From: brianw@hpcvlx.cv.hp.com (Brian Wilson)
  3. Newsgroups: comp.sources.x
  4. Subject: v08i057: wscrawl, Part05/05
  5. Message-ID: <138942@sun.Eng.Sun.COM>
  6. Date: 15 Jul 90 18:57:36 GMT
  7. Sender: news@sun.Eng.Sun.COM
  8. Lines: 1673
  9. Approved: argv@sun.com
  10.  
  11. Submitted-by: Brian Wilson <brianw@hpcvlx.cv.hp.com>
  12. Posting-number: Volume 8, Issue 57
  13. Archive-name: wscrawl/part05
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then feed it
  17. # into a shell via "sh file" or similar.  To overwrite existing files,
  18. # type "sh file -c".
  19. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  20. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  21. # If this archive is complete, you will see the following message at the end:
  22. #        "End of archive 5 (of 5)."
  23. # Contents:  wscrawl/image_f_io.c wscrawl/xab
  24. # Wrapped by argv@turnpike on Sun Jul 15 11:47:13 1990
  25. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  26. if test -f 'wscrawl/image_f_io.c' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'wscrawl/image_f_io.c'\"
  28. else
  29. echo shar: Extracting \"'wscrawl/image_f_io.c'\" \(17959 characters\)
  30. sed "s/^X//" >'wscrawl/image_f_io.c' <<'END_OF_FILE'
  31. X/*
  32. X * This file: image_f_io.c (part of the WSCRAWL program)
  33. X *
  34. X * This file contains the "Image File I/O" package for wscrawl (or anything
  35. X * for that matter.)  The format used is the standard X-Window Dump form
  36. X * that the MIT client "xwd" uses.  This File I/O was made possible by the 
  37. X * help and extensive source code of Mark Cook of Hewlett-Packard, who I 
  38. X * bothered endlessly to get this working.  
  39. X * 
  40. X * I tried to make this file of routines as self-contained and portable as
  41. X * possible.  Please feel free to use this file as is, or with modifications,
  42. X * for any and all applications.  -- Brian Wilson
  43. X *
  44. X * This file was last modified: 7/14/90
  45. X */
  46. X
  47. X#define TRUE                    1
  48. X#define FALSE                   0
  49. X#define BAD_CHOICE        -1
  50. X#define NO_DUPLICATE           -1
  51. X#define UNALLOCATED            -1
  52. X
  53. X#include <X11/Xos.h>
  54. X#include <X11/XWDFile.h>
  55. X#include <X11/Xlib.h>
  56. X#include <stdio.h>
  57. X
  58. Xextern char *malloc();
  59. XXImage *read_image_from_disk();
  60. X
  61. X
  62. X/*
  63. X * save_image_on_disk - this routine saves the region specified by the various
  64. X *               parameters out to disk in the "defacto standard" (xwd) format.
  65. X */
  66. Xsave_image_on_disk(disp, win_id, x, y, width, height, name_of_file)
  67. XDisplay *disp;
  68. XWindow win_id;
  69. Xint x, y, width, height;
  70. Xchar *name_of_file;
  71. X{
  72. X    unsigned long swaptest = TRUE;
  73. X    XRectangle box2;
  74. X    XRectangle *box;
  75. X    FILE *out_file_ptr;
  76. X    XColor *colors;
  77. X    unsigned buffer_size;
  78. X    int win_name_size;
  79. X    int header_size;
  80. X    int format=ZPixmap;
  81. X    int ncolors, i;
  82. X    XWindowAttributes win_info;
  83. X    XImage *ImagePix;
  84. X    XWDFileHeader header;
  85. X
  86. X    /*
  87. X     * convert to form this code understands (I got code from Mark Cook)
  88. X     */
  89. X    box = &box2;
  90. X    box->x = x;
  91. X    box->y = y;
  92. X    box->width = width;
  93. X    box->height = height;
  94. X
  95. X    /*
  96. X     * Open the file in which the image is to be stored
  97. X     */
  98. X    if ((out_file_ptr = fopen(name_of_file, "w")) == NULL) 
  99. X    {
  100. X        printf("ERROR: Could not open file %s.\n", name_of_file);
  101. X        return(0);
  102. X    }
  103. X    else
  104. X    {         /* Dump the image to the specified file */
  105. X    
  106. X        if (!XGetWindowAttributes(disp, win_id, &win_info)) 
  107. X        {
  108. X            printf("Can't get window attributes.\n");
  109. X            return(0);
  110. X        }
  111. X    
  112. X        /*
  113. X         * sizeof(char) is included for the null string terminator. 
  114. X         */
  115. X        win_name_size = strlen(name_of_file) + sizeof(char);
  116. X    
  117. X        ImagePix = XGetImage(disp, win_id, box->x, box->y, box->width,
  118. X                               box->height, AllPlanes, format); 
  119. X        XFlush(disp);
  120. X    
  121. X        if (ImagePix == NULL) 
  122. X        {
  123. X            printf("GetImage failed.\n");
  124. X            return(0);
  125. X        }
  126. X    
  127. X        buffer_size = Image_Size(ImagePix,format);/*determines size of pixmap*/
  128. X    
  129. X        /*
  130. X         * Get the RGB values for the current color cells
  131. X         */
  132. X        if ((ncolors = Get_Colors(&colors, disp)) == 0) 
  133. X        {
  134. X            printf("Cannot alloc memory for color structs.\n");
  135. X            return(0);
  136. X        }
  137. X        XFlush(disp);
  138. X    
  139. X        header_size = sizeof(header) +win_name_size; /*Calculates header size*/
  140. X    
  141. X        /*
  142. X         * Assemble the file header information
  143. X         */
  144. X        header.header_size = (xwdval) header_size;
  145. X        header.file_version = (xwdval) XWD_FILE_VERSION;
  146. X        header.pixmap_format = (xwdval) format;
  147. X        header.pixmap_depth = (xwdval) ImagePix->depth;
  148. X
  149. X        header.pixmap_width = (xwdval) ImagePix->width;
  150. X        header.pixmap_height = (xwdval) ImagePix->height;
  151. X        header.xoffset = (xwdval) ImagePix->xoffset;
  152. X        header.byte_order = (xwdval) ImagePix->byte_order;
  153. X        header.bitmap_unit = (xwdval) ImagePix->bitmap_unit;
  154. X        header.bitmap_bit_order = (xwdval) ImagePix->bitmap_bit_order;
  155. X        header.bitmap_pad = (xwdval) ImagePix->bitmap_pad;
  156. X        header.bits_per_pixel = (xwdval) ImagePix->bits_per_pixel;
  157. X        header.bytes_per_line = (xwdval) ImagePix->bytes_per_line;
  158. X        header.visual_class = (xwdval) win_info.visual->class;
  159. X        header.red_mask = (xwdval) win_info.visual->red_mask;
  160. X        header.green_mask = (xwdval) win_info.visual->green_mask;
  161. X        header.blue_mask = (xwdval) win_info.visual->blue_mask;
  162. X        header.bits_per_rgb = (xwdval) win_info.visual->bits_per_rgb;
  163. X        header.colormap_entries = (xwdval) win_info.visual->map_entries;
  164. X        header.ncolors = ncolors;
  165. X        header.window_width = (xwdval) ImagePix->width;
  166. X        header.window_height = (xwdval) ImagePix->height;
  167. X        header.window_x = (xwdval) 0;
  168. X        header.window_y = (xwdval) 0;
  169. X        header.window_bdrwidth = (xwdval) 0;
  170. X      
  171. X        if (*(char *) &swaptest) 
  172. X        {
  173. X            _swaplong((char *) &header, sizeof(header));
  174. X            for (i = 0; i < ncolors; i++) 
  175. X        {
  176. X                _swaplong((char *) &colors[i].pixel, sizeof(long));
  177. X                _swapshort((char *) &colors[i].red, 3 * sizeof(short));
  178. X            }
  179. X        }
  180. X    
  181. X        /*
  182. X         * Write out the file header information
  183. X         */
  184. X        (void) fwrite((char *)&header, sizeof(header), 1, out_file_ptr);
  185. X        (void) fwrite(name_of_file, win_name_size, 1, out_file_ptr);
  186. X    
  187. X        /*
  188. X         * Write out the color cell RGB values
  189. X         */
  190. X        (void) fwrite((char *) colors, sizeof(XColor), ncolors, out_file_ptr);
  191. X    
  192. X        /*
  193. X         * Write out the buffer
  194. X         */
  195. X        (void) fwrite(ImagePix->data, (int) buffer_size, 1, out_file_ptr);
  196. X    
  197. X        if(ncolors > 0) 
  198. X            free(colors);    /*free the color buffer*/
  199. X    
  200. X        fclose(out_file_ptr);
  201. X        XFlush(disp);
  202. X    }
  203. X}
  204. X
  205. X
  206. X/*
  207. X * Image_Size - this routine takes an XImage and returns it's total byte count
  208. X */
  209. Xint Image_Size(image, format)
  210. XXImage *image;
  211. Xint format;
  212. X{
  213. X    if (format != ZPixmap)
  214. X        return(image->bytes_per_line * image->height * image->depth);
  215. X    else
  216. X        return(image->bytes_per_line * image->height);
  217. X}
  218. X
  219. X
  220. X/*
  221. X * Get_Colors - takes a pointer to an XColor struct and returns the total
  222. X *            number of cells in the current colormap, plus all of their
  223. X *            RGB values.
  224. X */
  225. XGet_Colors(colors, disp)
  226. XXColor **colors;
  227. XDisplay *disp;
  228. X{
  229. X    int i, ncolors;
  230. X
  231. X    ncolors = DisplayCells(disp, DefaultScreen(disp));
  232. X
  233. X    if ((*colors = (XColor *) malloc (sizeof(XColor) * ncolors)) == NULL)
  234. X        return(FALSE);
  235. X
  236. X    for (i=0; i<ncolors; i++)
  237. X        (*colors)[i].pixel = i;
  238. X
  239. X    XQueryColors(disp, XDefaultColormapOfScreen(XDefaultScreenOfDisplay(disp)),
  240. X         *colors, ncolors);
  241. X    return(ncolors);
  242. X}
  243. X
  244. X
  245. X/*
  246. X * _swapshort - this routine is stolen, and I don't know what it does
  247. X */
  248. X_swapshort (bp, n)
  249. Xregister char *bp;
  250. Xregister unsigned n;
  251. X{
  252. X    register char c;
  253. X    /* register char *ep = bp + n; */
  254. X    register char *ep;
  255. X
  256. X    ep = bp + n;
  257. X    while (bp < ep) 
  258. X    {
  259. X        c = *bp;
  260. X        *bp = *(bp + 1);
  261. X        bp++;
  262. X        *bp++ = c;
  263. X    }
  264. X}
  265. X
  266. X
  267. X/*
  268. X * _swaplong - this routine is stolen, and I don't know what it does
  269. X */
  270. X_swaplong (bp, n)
  271. Xregister char *bp;
  272. Xregister unsigned n;
  273. X{
  274. X    register char c;
  275. X    /* register char *ep = bp + n; */
  276. X    register char *sp;
  277. X    register char *ep;
  278. X
  279. X    ep = bp + n;
  280. X    while (bp < ep) 
  281. X    {
  282. X        sp = bp + 3;
  283. X        c = *sp;
  284. X        *sp = *bp;
  285. X        *bp++ = c;
  286. X        sp = bp + 1;
  287. X        c = *sp;
  288. X        *sp = *bp;
  289. X        *bp++ = c;
  290. X        bp += 2;
  291. X    }
  292. X}
  293. X
  294. X
  295. X/*
  296. X * read_image_from_disk - this routine reads the file indicated and allocates
  297. X *               and loads up and then finally returns the XImage structure
  298. X *               ready to blow out to the indicated display.  If at all
  299. X *               possible, it attempts to return an image with the
  300. X *               depth equalling the depth of the disp passed in.  Either
  301. X *               way, it will return the depth it managed to get.
  302. X */
  303. XXImage *read_image_from_disk(disp, win_id, name_of_file, width, height, depth)
  304. XDisplay *disp;
  305. XWindow win_id;
  306. Xchar *name_of_file;
  307. Xint *width, *height, *depth;
  308. X{
  309. X    XImage *ImagePix;
  310. X    unsigned long swaptest = TRUE;
  311. X    unsigned buffer_size;
  312. X    char *buffer;
  313. X    char *win_name;
  314. X    int format;
  315. X    int i, name_size, ncolors;
  316. X    XColor *colors;
  317. X    FILE *in_file;
  318. X    XWDFileHeader header;
  319. X
  320. X    if ((in_file = fopen(name_of_file, "r")) == NULL)  /*open file for read*/
  321. X    {
  322. X    printf("ERROR: could not open file %s.\n", name_of_file);
  323. X        return(0);
  324. X    }
  325. X  
  326. X    if(fread((char *)&header, sizeof(header), 1, in_file) != 1) /*read header*/
  327. X    {
  328. X    printf("ERROR: unable to read imagefile header.\n");
  329. X        return(0);
  330. X    }
  331. X
  332. X    if (*(char *) &swaptest)
  333. X        _swaplong((char *) &header, sizeof(header));
  334. X
  335. X    /*
  336. X     * check to see if the dump file is in the proper format 
  337. X     */
  338. X    if (header.file_version != XWD_FILE_VERSION) 
  339. X    {
  340. X    printf("ERROR: Imagefile format version mismatch.\n");
  341. X        return(0);
  342. X    }
  343. X
  344. X    if (header.header_size < sizeof(header)) 
  345. X    {
  346. X    printf("ERROR: Imagefile header is too small.\n");
  347. X        return(0);
  348. X    }
  349. X
  350. X    name_size = (header.header_size - sizeof(header)); /*space for window name*/
  351. X
  352. X    if((win_name = malloc((unsigned) name_size*sizeof(char))) == NULL) 
  353. X    {
  354. X        printf("ERROR: Can't malloc window name storage.\n");
  355. X        return(0);
  356. X    }
  357. X
  358. X    /*
  359. X     * Read in window name
  360. X     */
  361. X    if(fread(win_name, sizeof(char), name_size, in_file) != name_size) 
  362. X    {
  363. X        printf("ERROR: Unable to read window name from file.\n");
  364. X        return(0);
  365. X    }
  366. X
  367. X    /*
  368. X     * Malloc the image data space and initialize it 
  369. X     */
  370. X    if((ImagePix = (XImage *) malloc(sizeof(XImage))) == NULL) 
  371. X    {
  372. X    printf("ERROR: Can't malloc space for the image.\n");
  373. X        return(0);
  374. X    }
  375. X
  376. X    ImagePix->width = (int) header.pixmap_width;
  377. X    ImagePix->height = (int) header.pixmap_height;
  378. X    ImagePix->xoffset = (int) header.xoffset;
  379. X    ImagePix->format = (int) header.pixmap_format;
  380. X    ImagePix->byte_order = (int) header.byte_order;
  381. X    ImagePix->bitmap_unit = (int) header.bitmap_unit;
  382. X    ImagePix->bitmap_bit_order = (int) header.bitmap_bit_order;
  383. X    ImagePix->bitmap_pad = (int) header.bitmap_pad;
  384. X    ImagePix->depth = (int) header.pixmap_depth;
  385. X    ImagePix->bits_per_pixel = (int) header.bits_per_pixel;
  386. X    ImagePix->bytes_per_line = (int) header.bytes_per_line;
  387. X    ImagePix->red_mask = header.red_mask;
  388. X    ImagePix->green_mask = header.green_mask;
  389. X    ImagePix->blue_mask = header.blue_mask;
  390. X    ImagePix->obdata = NULL;
  391. X    _XInitImageFuncPtrs(ImagePix);
  392. X
  393. X    format = ImagePix->format;
  394. X
  395. X    /* malloc memory for the RGB values from the old colormap and read 
  396. X     * in the values
  397. X     */
  398. X    if (ncolors = header.ncolors) 
  399. X    {
  400. X        if ((colors = (XColor *) malloc(ncolors * sizeof(XColor))) == NULL) 
  401. X    {
  402. X        printf("ERROR: Can't malloc space for the image cmap.\n");
  403. X            if (win_name) 
  404. X        free(win_name);
  405. X            if (ImagePix) 
  406. X        XDestroyImage(ImagePix);
  407. X            return(0);
  408. X        }
  409. X
  410. X        if (fread((char *)colors, sizeof(XColor), ncolors, in_file) != ncolors)
  411. X    {
  412. X        printf("ERROR: Unable to read cmap from imagefile.\n");
  413. X            if (win_name) 
  414. X        free(win_name);
  415. X            if (ImagePix) 
  416. X        XDestroyImage(ImagePix);
  417. X            if (colors) 
  418. X        free((char *) colors);
  419. X            return(0);
  420. X        }
  421. X
  422. X        if (*(char *) &swaptest) 
  423. X    {
  424. X            for (i = 0; i < ncolors; i++) 
  425. X        {
  426. X                _swaplong((char *) &colors[i].pixel, sizeof(long));
  427. X                _swapshort((char *) &colors[i].red, 3 * sizeof(short));
  428. X            }
  429. X        }
  430. X    }
  431. X
  432. X    buffer_size = Image_Size(ImagePix, format);   /*malloc the pixel buffer*/
  433. X    if ((buffer = malloc(buffer_size * sizeof(char))) == NULL) 
  434. X    {
  435. X        printf("ERROR: Can't malloc the data buffer.\n");
  436. X        if (win_name) 
  437. X            free(win_name);
  438. X        if(ImagePix) 
  439. X        XDestroyImage(ImagePix);
  440. X        if (colors) 
  441. X        free((char *) colors);
  442. X        return(0);
  443. X    }
  444. X    ImagePix->data = buffer;
  445. X
  446. X    /*
  447. X     * Read in the pixmap buffer
  448. X     */
  449. X    if(fread(buffer, sizeof(char), (int)buffer_size, in_file) != buffer_size) 
  450. X    {
  451. X        printf("ERROR: Unable to read pixmap from imagefile.\n");
  452. X        if (win_name) 
  453. X        free(win_name);
  454. X        if(ImagePix) 
  455. X        XDestroyImage(ImagePix);
  456. X        if (colors) 
  457. X        free((char *) colors);
  458. X        if (buffer) 
  459. X        free((char *) buffer);
  460. X        return(0);
  461. X    }
  462. X
  463. X    (void) fclose(in_file);   /*we are done with the infile*/
  464. X
  465. X    *depth = ImagePix->depth; /*even if the rest fails, return the dimensions*/
  466. X    *width = ImagePix->width;
  467. X    *height = ImagePix->height;
  468. X
  469. X    if (win_name && (name_size > 0)) 
  470. X        free(win_name);
  471. X    if (allocate_colors_and_assign_em(disp, win_id, &ImagePix, colors)
  472. X    != TRUE) 
  473. X    {
  474. X        /* the above
  475. X         * converts the pixels in the xwd file over to the current colormap,
  476. X         * and also swaps the image to a new depth if the depth the
  477. X         * image was stored on disk as disagrees with the depth of the window
  478. X         * it is to be blasted into.  This block is if that fails.
  479. X         */
  480. X        printf("ERROR: Can't convert xwd file to usuable format.\n");
  481. X        printf("       Probably because the display is a wimpy non-HP.\n");
  482. X        if(ImagePix) 
  483. X        XDestroyImage(ImagePix);
  484. X        if (colors) 
  485. X        free((char *) colors);
  486. X        return(0);
  487. X    }
  488. X    else if (colors) 
  489. X    free((char *) colors);
  490. X
  491. X    *depth = ImagePix->depth;    /*the depth may have changed*/
  492. X    return(ImagePix);
  493. X}
  494. X
  495. X
  496. X/*
  497. X * allocate_colors_and_assign_em - this function takes an XImage and it's 
  498. X *            colormap as it was at the time the image was created, and 
  499. X *            allocates cells in the system colormap matching those old colors 
  500. X *            and shuffles the pixels in the image to point to our new color
  501. X *            cells instead of those old color cells.
  502. X */
  503. Xallocate_colors_and_assign_em(disp, win_id, image_ptr, cells)
  504. XDisplay *disp;
  505. XWindow win_id;
  506. XXImage **image_ptr;
  507. XXColor *cells;
  508. X{
  509. X    int width, height, i, j, num_cells_in_colormap;
  510. X    unsigned long *opv, *npv;      /*old and new pixel values*/
  511. X    unsigned long tmp_pixel_value;
  512. X    XColor screen_in_out;
  513. X    XImage *diff_depth_im, *image;
  514. X    XWindowAttributes win_attr;
  515. X    int buffer_size;
  516. X    char *buffer;
  517. X
  518. X    image = *image_ptr;    /*for my sanity*/
  519. X    height    = image->height;
  520. X    width     = image->width;
  521. X
  522. X    /*
  523. X     * determine the number of cells in the colormap by taking 2 to the power
  524. X     * of the number of bits of depth this display has.
  525. X     */
  526. X    for (i=0, num_cells_in_colormap=1; i<(*image_ptr)->depth; i++)
  527. X    num_cells_in_colormap *= 2;
  528. X
  529. X    if (num_cells_in_colormap > 256)
  530. X    {
  531. X        printf("WARNING: This is a monster deep display image, dude.  This "); 
  532. X    printf("image\n");
  533. X    printf("         will take %d mega-bytes of free memory to process.\n", 
  534. X           ((num_cells_in_colormap * sizeof(unsigned long))/1024)/1024);
  535. X    }
  536. X
  537. X    /*
  538. X     * set up temporary storage for the old and new pixel values
  539. X     */
  540. X    opv = (unsigned long *) malloc(num_cells_in_colormap*sizeof(unsigned long));
  541. X    npv = (unsigned long *) malloc(num_cells_in_colormap*sizeof(unsigned long));
  542. X
  543. X    if (!opv || !npv) 
  544. X    {
  545. X    printf("ERROR: unable to malloc the temporary pixel storage.\n");
  546. X        if (opv) 
  547. X        free((char *) opv);
  548. X        if (npv) 
  549. X        free((char *) npv);
  550. X        return(0);
  551. X    }
  552. X
  553. X    /* 
  554. X     * Each opv value is a flag indicating whether or not that pixel is
  555. X     * present in the image.  Each npv value is it's replacement value. 
  556. X     */
  557. X    for (i=0; i<num_cells_in_colormap; i++) 
  558. X    {
  559. X        opv[i] = FALSE;
  560. X        npv[i] = UNALLOCATED;
  561. X    }
  562. X
  563. X    for (i=0; i<height;i++) /*examine each pxl in image; recrd all used values*/
  564. X         for (j=0; j<width; j++)
  565. X     {
  566. X         tmp_pixel_value = XGetPixel(image, j, i);
  567. X         if (tmp_pixel_value >= num_cells_in_colormap)
  568. X         {
  569. X             printf("ERROR: Bad pixel value at x=%d, y=%d, pixel=%ld\n", 
  570. X             j, i, tmp_pixel_value);
  571. X         }
  572. X             else
  573. X         opv[tmp_pixel_value] = TRUE;
  574. X         }
  575. X
  576. X    /*
  577. X     * For each TRUE opv allocate the colors
  578. X     */
  579. X    for (i=0; i<num_cells_in_colormap; i++)
  580. X    {
  581. X        if (opv[i])
  582. X        {
  583. X            screen_in_out.red   = cells[i].red;
  584. X            screen_in_out.green = cells[i].green;
  585. X            screen_in_out.blue  = cells[i].blue;
  586. X            screen_in_out.flags = DoRed | DoGreen | DoBlue;
  587. X
  588. X            if (XAllocColor(disp, 
  589. X              XDefaultColormapOfScreen(XDefaultScreenOfDisplay(disp)),
  590. X              &screen_in_out) == 0)
  591. X        {
  592. X            printf("ERROR: out of colors on this display. ");
  593. X            printf("Cannot import image.\n");
  594. X            return(0);
  595. X        }
  596. X            else 
  597. X                npv[i] = screen_in_out.pixel;
  598. X        }
  599. X    }
  600. X
  601. X    XGetWindowAttributes(disp, win_id, &win_attr);
  602. X
  603. X    if (win_attr.depth == image->depth)    /*cool, this is easy*/
  604. X    {
  605. X        for (i=0; i<height; i++)
  606. X            for (j=0; j<width; j++)
  607. X                XPutPixel(image, j, i, npv[XGetPixel(image, j, i)]);
  608. X    }
  609. X    else                                   /*oh darn it, this is tough*/
  610. X    {
  611. X    /*
  612. X     * the concept here is to creat a new image that IS the correct
  613. X     * depth and then do "PutPixel" into it, filling it with the correct
  614. X     * color pixels.
  615. X     */
  616. X        diff_depth_im = XCreateImage(disp, win_attr.visual, win_attr.depth, 
  617. X                  image->format, image->xoffset, NULL, width, 
  618. X              height, image->bitmap_pad, 0);
  619. X
  620. X        buffer_size = Image_Size(diff_depth_im, 
  621. X                  diff_depth_im->format);  /*malloc pixel buffer*/
  622. X        if ((buffer = malloc(buffer_size * sizeof(char))) == NULL) 
  623. X        {
  624. X            printf("ERROR: Can't malloc data buffer for differing depth.\n");
  625. X            return(0);
  626. X        }
  627. X        diff_depth_im->data = buffer;
  628. X
  629. X        for (i=0; i<height; i++)
  630. X            for (j=0; j<width; j++)
  631. X                XPutPixel(diff_depth_im, j, i, 
  632. X              npv[XGetPixel(image, j, i)]);
  633. X
  634. X    *image_ptr = diff_depth_im;
  635. X        XDestroyImage(image);   /*free up space of wrong depth image*/
  636. X    }
  637. X
  638. X    if (opv) 
  639. X    free((char *) opv);
  640. X    if (npv) 
  641. X    free((char *) npv);
  642. X
  643. X    return(1);
  644. X}
  645. X
  646. END_OF_FILE
  647. if test 17959 -ne `wc -c <'wscrawl/image_f_io.c'`; then
  648.     echo shar: \"'wscrawl/image_f_io.c'\" unpacked with wrong size!
  649. fi
  650. # end of 'wscrawl/image_f_io.c'
  651. fi
  652. if test -f 'wscrawl/xab' -a "${1}" != "-c" ; then 
  653.   echo shar: Will not clobber existing file \"'wscrawl/xab'\"
  654. else
  655. echo shar: Extracting \"'wscrawl/xab'\" \(33168 characters\)
  656. sed "s/^X//" >'wscrawl/xab' <<'END_OF_FILE'
  657. X                (*num_people_drawing)++;        /*another dude is now drawing*/
  658. X        return(1);
  659. X    } 
  660. X    else if ((the_event->window == disp_info[disp_num].status_win_id) ||
  661. X             (the_event->window == disp_info[disp_num].eraser_win_id) ||
  662. X             (the_event->window == disp_info[disp_num].dialog_win_id))
  663. X    {                                       /*it is in the status window*/
  664. X            return(1);    /*no action taken*/
  665. X    }
  666. X    else     /*it is in a menu, determine which menu*/
  667. X    {
  668. X        for (i=0, menu_num = -1; i<NUM_OF_MENUS; i++)
  669. X            if (the_event->window == disp_info[disp_num].menu[i].win_id)
  670. X        {
  671. X            menu_num = i;
  672. X            break;
  673. X        }
  674. X        if (menu_num == -1)
  675. X        {
  676. X        printf("\nSome error occured.  ButtonPress in WHAT window?\n");
  677. X        return(0);
  678. X            }
  679. X
  680. X        /*if we got this far, the button press is in a menu*/
  681. X            disp_info[disp_num].current_menu = menu_num;
  682. X            disp_info[disp_num].pointer_state = IN_MENU;
  683. X        disp_info[disp_num].menu[menu_num].item_selected = 0;
  684. X        if (disp_info[disp_num].scrawl_mode != TYPING)
  685. X                (*num_people_drawing)++;  /*another dude is now drawing*/
  686. X        draw_menu(disp_num);          /*draw the menus with this new info*/
  687. X    }
  688. X    }
  689. X}
  690. X
  691. X
  692. X/*
  693. X * handle_Expose_event - this function handles an Expose event in any window.
  694. X *               The most important windows are the menu and status windows,
  695. X *               which contain text that must always be there.  Therefore,
  696. X *               this preserves that text.
  697. X */
  698. Xhandle_Expose_event(our_event, disp_num)
  699. XXEvent *our_event;
  700. Xint disp_num;
  701. X{
  702. X    XExposeEvent *the_event;
  703. X    int menu_num;
  704. X
  705. X    the_event = (XExposeEvent *) our_event;
  706. X   
  707. X    if ((the_event->window == disp_info[disp_num].win_id) ||
  708. X        (the_event->window == disp_info[disp_num].eraser_win_id))
  709. X    {
  710. X        return(1);      /*we don't care about these window expose events*/
  711. X    }
  712. X    else if (the_event->window == disp_info[disp_num].dialog_win_id)
  713. X    {
  714. X    draw_dialog_win_message(disp_num);
  715. X        return(1);
  716. X    }
  717. X    else if (the_event->window == disp_info[disp_num].status_win_id)
  718. X    {
  719. X    draw_status_win_message(disp_num);
  720. X        return(1);
  721. X    }
  722. X    else  /*It must be in a menu.  Determine which menu and draw text.*/
  723. X    {
  724. X        for (menu_num=0; menu_num<NUM_OF_MENUS; menu_num++)
  725. X        {
  726. X            if (the_event->window == disp_info[disp_num].menu[menu_num].win_id)
  727. X            break;
  728. X        }
  729. X    
  730. X        if (menu_num >= NUM_OF_MENUS)
  731. X        {
  732. X            printf("\nERROR: unknown window in handle_Expose_event().\n");
  733. X        exit(0);
  734. X        }
  735. X    
  736. X        draw_menu_text(disp_num, menu_num);          /*draw the menu text*/
  737. X    }
  738. X}
  739. X
  740. X
  741. X/*
  742. X * handle_KeyPress_event - this function handles a KeyPress event in
  743. X *                   this particular scrawler's window. 
  744. X */
  745. Xhandle_KeyPress_event(our_event, disp_num)
  746. XXEvent *our_event;
  747. Xint disp_num;
  748. X{
  749. X    XKeyPressedEvent *the_event;
  750. X
  751. X    the_event = (XKeyPressedEvent *) our_event;
  752. X   
  753. X    if ((disp_info[disp_num].scrawl_mode == TYPING) &&
  754. X        (disp_info[disp_num].pointer_state != IN_MENU))
  755. X    {
  756. X         XPutBackEvent(disp_info[disp_num].disp, (XEvent *) the_event);
  757. X    }
  758. X    else if ((disp_info[disp_num].scrawl_mode == RESPONDING_TO_DIALOG) &&
  759. X        (the_event->window == disp_info[disp_num].dialog_win_id))
  760. X    {
  761. X         XPutBackEvent(disp_info[disp_num].disp, (XEvent *) the_event);
  762. X    }
  763. X}
  764. X
  765. X
  766. X/*
  767. X * handle_ConfigureNotify_event - this function handles the resizing of a
  768. X *                   window.  If a person resizes their window, it resizes
  769. X *                   ALL the windows associated with this session.  In this
  770. X *                   way, the scrawlers share the size of their window.
  771. X *                   NOTE: This routine is not full proof.  I never figured
  772. X *                   out how to remove all contention problems.  For instance,
  773. X *                   if two people resize their windows simultaneously, there
  774. X *                   occurs this wierd bouncing action.  If you can figure 
  775. X *                   something better than this out, you're a stud.  As for
  776. X *                   me, it's 3am and I'm going home now.
  777. X */
  778. Xhandle_ConfigureNotify_event(our_event, disp_num)
  779. XXEvent *our_event;
  780. Xint disp_num;
  781. X{
  782. X    XConfigureEvent *the_event, *tmp_event, *(event_history[50]);
  783. X    XEvent *the_new_event;
  784. X    int i, history_index;
  785. X
  786. X    the_event = (XConfigureEvent *) our_event;
  787. X   
  788. X    if ((the_event->window != disp_info[disp_num].win_id) ||
  789. X    (disp_info[disp_num].in_session_bool == FALSE))
  790. X    {
  791. X    return(0);    /*we are not interested in this event*/
  792. X    }
  793. X    
  794. X    if ((the_event->width == disp_info[disp_num].win_width) &&
  795. X        (the_event->height == disp_info[disp_num].win_height))
  796. X    {
  797. X    return(0);    /*we are not interested in this event*/
  798. X    }
  799. X    else
  800. X    {
  801. X        disp_info[disp_num].win_width = the_event->width;   /*the new height*/
  802. X        disp_info[disp_num].win_height = the_event->height;
  803. X    }
  804. X
  805. X    /*
  806. X     * first go through ALL the resize events for ALL scrawl windows and
  807. X     * throw away all that do not agree exactly with this one.  Put the
  808. X     * ones that do agree back on the queue, as those are for other windows.
  809. X     *
  810. X     * this was necessary to avoid a perpetual loop that occurs if two people
  811. X     * try to resize at the same time.
  812. X     */
  813. X    the_new_event = (XEvent *) malloc (sizeof(XEvent));
  814. X
  815. X    for (i=0; i<num_of_disps; i++)
  816. X    {
  817. X    history_index=0;
  818. X
  819. X    if (disp_info[i].in_session_bool == TRUE)
  820. X    {
  821. X            while (XCheckTypedWindowEvent(disp_info[i].disp, 
  822. X                          disp_info[i].win_id,
  823. X                          ConfigureNotify, the_new_event))
  824. X            {
  825. X                tmp_event = (XConfigureEvent *) the_new_event;
  826. X
  827. X        if ((the_event->width == tmp_event->width) &&
  828. X            (the_event->height == tmp_event->height))
  829. X        {
  830. X            event_history[history_index] = tmp_event;
  831. X            history_index++;
  832. X                    the_new_event = (XEvent *) malloc (sizeof(XEvent));
  833. X        }
  834. X            }
  835. X
  836. X        /*put all the events back onto the queue*/
  837. X        for (history_index--; history_index>=0; history_index--)
  838. X        {
  839. X                XPutBackEvent(disp_info[i].disp, 
  840. X                  (XEvent *) event_history[history_index]);
  841. X            free(event_history[history_index]);
  842. X        }
  843. X    }
  844. X    }
  845. X
  846. X
  847. X    for (i=0; i<num_of_disps; i++)
  848. X    {
  849. X    if (disp_info[i].in_session_bool == TRUE)
  850. X    {
  851. X        if ((disp_info[i].win_width != the_event->width) ||
  852. X            (disp_info[i].win_height != the_event->height))
  853. X        {
  854. X                XResizeWindow(disp_info[i].disp, disp_info[i].win_id, 
  855. X              the_event->width, the_event->height);
  856. X            disp_info[i].win_width = the_event->width;
  857. X            disp_info[i].win_height = the_event->height;
  858. X
  859. X                XSync(disp_info[i].disp, False);
  860. X        }
  861. X    }
  862. X    }
  863. X
  864. X    for (i=0; i<num_of_disps; i++)
  865. X    {
  866. X    if (disp_info[i].in_session_bool == TRUE)
  867. X    {
  868. X            XSync(disp_info[i].disp, False);
  869. X        /*
  870. X        XClearWindow(disp_info[i].disp, disp_info[i].win_id);
  871. X        */
  872. X            XFlush(disp_info[i].disp);
  873. X
  874. X        if (disp_info[i].cursor_on == TRUE)
  875. X        {    /*then turn it BACK on from the "clear window turnoff"*/
  876. X                 XDrawLine(disp_info[i].disp, 
  877. X                 disp_info[i].win_id,
  878. X                 disp_info[i].cursor_gc, 
  879. X                 disp_info[i].cur_pos.x, 
  880. X                 disp_info[i].cur_pos.y, 
  881. X                 disp_info[i].cur_pos.x + 
  882. X                 disp_info[i].prompt_width, 
  883. X                 disp_info[i].cur_pos.y);
  884. X            }
  885. X            XSync(disp_info[i].disp, False);   /*all the XSyncs are trying*/
  886. X    }                        /*to avoid a bad timing prob*/
  887. X    }                                         
  888. X
  889. X    for (i=0; i<num_of_disps; i++)
  890. X    {
  891. X    if (disp_info[i].in_session_bool == TRUE)
  892. X    {
  893. X            XSync(disp_info[i].disp, False);
  894. X            place_and_draw_status_win(i);
  895. X    }
  896. X    }
  897. X    /*
  898. X    NOTHING_DRAWN_YET = TRUE;
  899. X     */
  900. X}
  901. X
  902. X
  903. X/*
  904. X * handle_ButtonRelease_event - this function handles a ButtonRelease event in
  905. X *                  this particular scrawler's window.  It is probably a
  906. X *                  scrawler stopping drawing, but it could be a menu selection
  907. X *                  or a "select area" finishing, so those are checked for 
  908. X *                  also.
  909. X */
  910. Xhandle_ButtonRelease_event(our_event, disp_num, num_people_drawing)
  911. XXEvent *our_event;
  912. Xint disp_num, *num_people_drawing;
  913. X{
  914. X    XButtonPressedEvent *the_event;
  915. X    int menu_num, item_selected, tot_num_items, i;
  916. X    int start_x, start_y, last_x, last_y, temp, oldleft, oldtop;
  917. X
  918. X    the_event = (XButtonPressedEvent *) our_event;
  919. X
  920. X    if (disp_info[disp_num].scrawl_mode == RESPONDING_TO_DIALOG)
  921. X    return(0);    /*not allowed to do anything else*/
  922. X
  923. X    if (the_event->button == Button1)
  924. X    {
  925. X    if (the_event->window == disp_info[disp_num].win_id)
  926. X    {
  927. X            disp_info[disp_num].pointer_state = NOT_PRESSED;
  928. X        if (disp_info[disp_num].scrawl_mode != TYPING)
  929. X                (*num_people_drawing)--;    /*a dude has stopped drawing*/
  930. X
  931. X        if (disp_info[disp_num].scrawl_mode == ERASING)
  932. X        {
  933. X                XUnmapWindow(disp_info[disp_num].disp, 
  934. X               disp_info[disp_num].eraser_win_id);
  935. X        } 
  936. X        else if (disp_info[disp_num].scrawl_mode == RUBBER_POINTING)
  937. X        {
  938. X        /*erase last pointer*/
  939. X            oldleft = disp_info[disp_num].last_point.x;
  940. X            oldtop = disp_info[disp_num].last_point.y -
  941. X                  disp_info[disp_num].rubber_pointer.height;
  942. X                disp_info[disp_num].rubber_pointer.is_mapped_bool = FALSE;
  943. X                for (i=0; i<num_of_disps; i++)
  944. X                {
  945. X                if (disp_info[i].in_session_bool)
  946. X                    {
  947. X                XCopyArea(disp_info[i].disp, 
  948. X               disp_info[disp_num].rubber_pointer.rubber_pointer_pix[i],
  949. X                   disp_info[i].win_id, disp_info[disp_num].win_gc[i],
  950. X                   0, 0, disp_info[disp_num].rubber_pointer.width, 
  951. X                   disp_info[disp_num].rubber_pointer.height, oldleft, 
  952. X                   oldtop);
  953. X                        XFlush(disp_info[i].disp);
  954. X            }
  955. X        }
  956. X        }
  957. X        else if ((disp_info[disp_num].scrawl_mode == PLACING_A_BITMAP) ||
  958. X                 (disp_info[disp_num].scrawl_mode == PLACING_AN_IMAGE) ||
  959. X                 (disp_info[disp_num].scrawl_mode == PLACING_A_TEXTFILE))
  960. X        {
  961. X        if (disp_info[disp_num].just_placed_something_bool == TRUE)
  962. X        {
  963. X            disp_info[disp_num].just_placed_something_bool = FALSE;
  964. X                    return(0);   /*throw this event away*/
  965. X        }
  966. X        }
  967. X        else if (disp_info[disp_num].scrawl_mode == SELECTING_AN_AREA)
  968. X        {
  969. X            /*erase select rectangle*/
  970. X            start_x = disp_info[disp_num].select_start_pos.x;
  971. X            start_y = disp_info[disp_num].select_start_pos.y;
  972. X            last_x = disp_info[disp_num].cur_pos.x;
  973. X            last_y = disp_info[disp_num].cur_pos.y;
  974. X        
  975. X                if (start_x > last_x)  /*switch so lesser coordinate is first*/
  976. X                {
  977. X                    temp = start_x;
  978. X                start_x = last_x;
  979. X                last_x = temp;
  980. X            }
  981. X            if (start_y > last_y)  /*switch so lesser coordinate is first*/
  982. X            {
  983. X                    temp = start_y;
  984. X                start_y = last_y;
  985. X                last_y = temp;
  986. X            }
  987. X                XDrawRectangle(disp_info[disp_num].disp, 
  988. X               disp_info[disp_num].win_id,
  989. X                   disp_info[disp_num].rubber_band_gc,
  990. X               start_x, start_y, last_x - start_x,  last_y - start_y);
  991. X               
  992. X        /*
  993. X         * shapes was really hacked in here. This is a kludge. 
  994. X         */
  995. X        if (disp_info[disp_num].dialog_what == DRAW_SHAPE)
  996. X        {
  997. X                start_x = disp_info[disp_num].select_start_pos.x;
  998. X                start_y = disp_info[disp_num].select_start_pos.y;
  999. X                last_x = disp_info[disp_num].cur_pos.x;
  1000. X                last_y = disp_info[disp_num].cur_pos.y;
  1001. X            draw_shape(disp_num, start_x, start_y, last_x, last_y);
  1002. X            return(1);
  1003. X        }
  1004. X        
  1005. X        if (start_x > last_x)  /*switch so lesser coordinate is first*/
  1006. X        {
  1007. X                    temp = start_x;
  1008. X            start_x = last_x;
  1009. X            last_x = temp;
  1010. X        }
  1011. X        if (start_y > last_y)  /*switch so lesser coordinate is first*/
  1012. X        {
  1013. X                    temp = start_y;
  1014. X            start_y = last_y;
  1015. X            last_y = temp;
  1016. X        }
  1017. X        if (disp_info[disp_num].dialog_what == SAVE_BITMAP)
  1018. X        {
  1019. X            disp_info[disp_num].dialog_text_prompt =
  1020. X                            "File To Save Bitmap To:";
  1021. X        }
  1022. X        else if (disp_info[disp_num].dialog_what == SAVE_IMAGE)
  1023. X        {
  1024. X            disp_info[disp_num].dialog_text_prompt =
  1025. X                            "File To Save Image To:";
  1026. X        }
  1027. X        disp_info[disp_num].dialog_text_return[0] = '\0';
  1028. X        disp_info[disp_num].dialog_reply_index = 0;
  1029. X        put_up_dialog(disp_num);
  1030. X        disp_info[disp_num].scrawl_mode = RESPONDING_TO_DIALOG;
  1031. X        }
  1032. X        return(1);
  1033. X    } 
  1034. X    else if ((the_event->window == disp_info[disp_num].status_win_id) ||
  1035. X             (the_event->window == disp_info[disp_num].eraser_win_id) ||
  1036. X             (the_event->window == disp_info[disp_num].dialog_win_id))
  1037. X    {                                       /*it is in a boring window*/
  1038. X            return(1);    /*no action taken*/
  1039. X    }
  1040. X    else     /*it is in a menu*/
  1041. X    {
  1042. X        menu_num = disp_info[disp_num].current_menu;
  1043. X        item_selected = disp_info[disp_num].menu[menu_num].item_selected;
  1044. X            tot_num_items = disp_info[disp_num].menu[menu_num].num_items;
  1045. X
  1046. X        if (disp_info[disp_num].scrawl_mode != TYPING)
  1047. X                (*num_people_drawing)--;  /*a dude has stopped input for now*/
  1048. X
  1049. X            if ((item_selected > 0) && (item_selected < tot_num_items))
  1050. X        {
  1051. X                menu_selection(disp_num, menu_num, num_people_drawing, 
  1052. X                   item_selected);
  1053. X        }
  1054. X
  1055. X            disp_info[disp_num].pointer_state = NOT_PRESSED;
  1056. X        if (disp_info[disp_num].in_session_bool)
  1057. X            draw_menu(disp_num);      /*draw the menus with this new info*/
  1058. X    }
  1059. X    }
  1060. X}
  1061. X
  1062. X
  1063. X/*
  1064. X * get_dimensions_of_text_file - this function finds and returns the 
  1065. X *              dimensions (in in screen pixels) of the text file that 
  1066. X *              is passed in as an argument.
  1067. X */
  1068. Xget_dimensions_of_text_file(disp_num, text_file_ptr, width, height)
  1069. Xint disp_num;
  1070. XFILE *text_file_ptr;
  1071. Xint *width, *height;
  1072. X{
  1073. X    int c, length, current_width, current_height, max_width_found;
  1074. X    char current_line[512];
  1075. X   
  1076. X    disp_info[disp_num].char_height =
  1077. X           (disp_info[disp_num].the_font_struct)->max_bounds.ascent +
  1078. X               (disp_info[disp_num].the_font_struct)->max_bounds.descent;
  1079. X
  1080. X    for (max_width_found=0, current_height=0; (c=getc(text_file_ptr)) != EOF;)
  1081. X    {
  1082. X        ungetc(c, text_file_ptr);
  1083. X        fgets(current_line, 510, text_file_ptr);       /*get the line*/
  1084. X        for (length=0; current_line[length] != '\n'; length++)
  1085. X            ;
  1086. X
  1087. X    current_height += disp_info[disp_num].char_height;
  1088. X
  1089. X    if ((current_width = XTextWidth(disp_info[disp_num].the_font_struct,
  1090. X                   current_line, length)) > max_width_found)
  1091. X    {
  1092. X            max_width_found = current_width;
  1093. X    }
  1094. X    }
  1095. X
  1096. X    *width = max_width_found;
  1097. X    *height = current_height;
  1098. X}
  1099. X
  1100. X
  1101. X/*
  1102. X * draw_dialog_win_message - this function draws the contents of the 
  1103. X *                 dialog box in case of expose event, etc.
  1104. X */
  1105. Xdraw_dialog_win_message(disp_num)
  1106. X{
  1107. X    int i;
  1108. X    char the_char[10];
  1109. X
  1110. X    XDrawString(disp_info[disp_num].disp, disp_info[disp_num].dialog_win_id,
  1111. X        disp_info[disp_num].fg_menu_gc, 8, 14, 
  1112. X        disp_info[disp_num].dialog_text_prompt, 
  1113. X        strlen(disp_info[disp_num].dialog_text_prompt));
  1114. X    XDrawRectangle(disp_info[disp_num].disp,disp_info[disp_num].dialog_win_id,
  1115. X            disp_info[disp_num].fg_menu_gc, 8, 20, DIALOG_WIN_WIDTH - 15,
  1116. X        DIALOG_WIN_HEIGHT - 24);
  1117. X
  1118. X    for (i=0; i<disp_info[disp_num].dialog_reply_index; i++)
  1119. X    { 
  1120. X     the_char[0] = disp_info[disp_num].dialog_text_return[i];
  1121. X
  1122. X     XDrawString(disp_info[disp_num].disp, 
  1123. X            disp_info[disp_num].dialog_win_id,
  1124. X            disp_info[disp_num].fg_menu_gc, 
  1125. X            14 + i*FIXED_CHAR_WIDTH, DIALOG_WIN_HEIGHT - 12,
  1126. X            the_char, 1);
  1127. X    } 
  1128. X    XFlush(disp_info[disp_num].disp);
  1129. X}
  1130. X
  1131. X
  1132. X/*
  1133. X * put_up_dialog - this function displays the dialog box with the text
  1134. X *                 passed in.  The text is usually something like:
  1135. X *                 "Enter the file name:".
  1136. X */
  1137. Xput_up_dialog(disp_num)
  1138. Xint disp_num;
  1139. X{
  1140. X    XMapWindow(disp_info[disp_num].disp, disp_info[disp_num].dialog_win_id);
  1141. X    XFlush(disp_info[disp_num].disp);
  1142. X    draw_dialog_win_message(disp_num);
  1143. X}
  1144. X
  1145. X
  1146. X/*
  1147. X * do_dialog_action - this is called when a dialog is finally unmapped.  This
  1148. X *                    then takes the appropriate action.
  1149. X */
  1150. Xdo_dialog_action(disp_num)
  1151. Xint disp_num;
  1152. X{
  1153. X    int width, height, depth, xhr, yhr;
  1154. X    Pixmap the_pixmap;
  1155. X    int temp, start_x, start_y, last_x, last_y;
  1156. X    FILE *fp;
  1157. X    XImage *the_image;
  1158. X
  1159. X    switch(disp_info[disp_num].dialog_what)
  1160. X    { 
  1161. X    case SAVE_BITMAP:
  1162. X        if (disp_info[disp_num].dialog_reply_index == 0)
  1163. X            printf("Bitmap Save was canceled.\n");
  1164. X        else
  1165. X        {
  1166. X                start_x = disp_info[disp_num].select_start_pos.x;
  1167. X                start_y = disp_info[disp_num].select_start_pos.y;
  1168. X                last_x = disp_info[disp_num].cur_pos.x;
  1169. X                last_y = disp_info[disp_num].cur_pos.y;
  1170. X                if (start_x > last_x)  /*switch so lesser coordinate is first*/
  1171. X                {
  1172. X                    temp = start_x;
  1173. X                start_x = last_x;
  1174. X                last_x = temp;
  1175. X            }
  1176. X            if (start_y > last_y)  /*switch so lesser coordinate is first*/
  1177. X            {
  1178. X                    temp = start_y;
  1179. X                start_y = last_y;
  1180. X                last_y = temp;
  1181. X            }
  1182. X
  1183. X                set_paused_cursors();   /*this may take a while*/
  1184. X                save_bitmap_on_disk(disp_num, start_x, start_y, 
  1185. X                   last_x - start_x, last_y - start_y, 
  1186. X                   disp_info[disp_num].dialog_text_return);
  1187. X                unset_paused_cursors(); /*done*/
  1188. X        }
  1189. X        /*simulate choosing the "scrawl" menu selection*/
  1190. X        menu_selection(disp_num, 0, &num_people_drawing, 
  1191. X                   disp_info[disp_num].previous_scrawl_mode);
  1192. X            break;
  1193. X    case READ_IN_BITMAP:
  1194. X        if (disp_info[disp_num].dialog_reply_index == 0)
  1195. X        {
  1196. X            printf("Bitmap Read In was canceled.\n");
  1197. X            /*simulate choosing the "scrawl" menu selection*/
  1198. X            menu_selection(disp_num, 0, &num_people_drawing, 
  1199. X                   disp_info[disp_num].previous_scrawl_mode);
  1200. X                return(0);
  1201. X        }
  1202. X            else if (XReadBitmapFile(disp_info[disp_num].disp, 
  1203. X             disp_info[disp_num].win_id,
  1204. X                 disp_info[disp_num].dialog_text_return, 
  1205. X             &width, &height, &the_pixmap, &xhr, &yhr)==BitmapSuccess)
  1206. X        {
  1207. X        disp_info[disp_num].rubber_band_width = width;
  1208. X        disp_info[disp_num].rubber_band_height = height;
  1209. X        disp_info[disp_num].first_point_bool = TRUE;
  1210. X        disp_info[disp_num].scrawl_mode = PLACING_A_BITMAP;
  1211. X        }
  1212. X        else
  1213. X        {
  1214. X            printf("ERROR: Not a valid bitmap file.\n");
  1215. X            /*simulate choosing the "scrawl" menu selection*/
  1216. X            menu_selection(disp_num, 0, &num_people_drawing, 
  1217. X                   disp_info[disp_num].previous_scrawl_mode);
  1218. X        }
  1219. X        break;
  1220. X    case ADD_A_DISPLAY:
  1221. X        if (disp_info[disp_num].dialog_reply_index == 0)
  1222. X        {
  1223. X            printf("Add Display was canceled.\n");
  1224. X            menu_selection(disp_num, 0, &num_people_drawing, 
  1225. X                   disp_info[disp_num].previous_scrawl_mode);
  1226. X                return(0);
  1227. X        }
  1228. X            else 
  1229. X        {
  1230. X                add_a_new_display(disp_info[disp_num].dialog_text_return);
  1231. X        /*go back to whatever you were doing before*/
  1232. X            menu_selection(disp_num, 0, &num_people_drawing, 
  1233. X                   disp_info[disp_num].previous_scrawl_mode);
  1234. X        }
  1235. X        break;
  1236. X    case READ_TEXTFILE:
  1237. X        if (disp_info[disp_num].dialog_reply_index == 0)
  1238. X        {
  1239. X            printf("Read In Textfile was canceled.\n");
  1240. X            menu_selection(disp_num, 0, &num_people_drawing, 
  1241. X                   disp_info[disp_num].previous_scrawl_mode);
  1242. X                return(0);
  1243. X        }
  1244. X            else if ((fp = fopen(disp_info[disp_num].dialog_text_return,"r")) 
  1245. X             != NULL)
  1246. X        {
  1247. X                set_paused_cursors();   /*this may take a while*/
  1248. X        get_dimensions_of_text_file(disp_num, fp, &width, &height);
  1249. X        fclose(fp);
  1250. X                unset_paused_cursors(); /*done*/
  1251. X        disp_info[disp_num].rubber_band_width = width;
  1252. X        disp_info[disp_num].rubber_band_height = height;
  1253. X        disp_info[disp_num].first_point_bool = TRUE;
  1254. X        disp_info[disp_num].scrawl_mode = PLACING_A_TEXTFILE;
  1255. X        XDefineCursor(disp_info[disp_num].disp,
  1256. X                     disp_info[disp_num].win_id,
  1257. X                     XCreateFontCursor(disp_info[disp_num].disp, 
  1258. X                           XC_xterm));
  1259. X        }
  1260. X        else
  1261. X        {
  1262. X            printf("ERROR: Not a valid text file.\n");
  1263. X            /*simulate choosing the "scrawl" menu selection*/
  1264. X            menu_selection(disp_num, 0, &num_people_drawing, 
  1265. X                   disp_info[disp_num].previous_scrawl_mode);
  1266. X        }
  1267. X        break;
  1268. X    case SAVE_IMAGE:
  1269. X        if (disp_info[disp_num].dialog_reply_index == 0)
  1270. X            printf("Image Save was canceled.\n");
  1271. X        else
  1272. X        {
  1273. X                start_x = disp_info[disp_num].select_start_pos.x;
  1274. X                start_y = disp_info[disp_num].select_start_pos.y;
  1275. X                last_x = disp_info[disp_num].cur_pos.x;
  1276. X                last_y = disp_info[disp_num].cur_pos.y;
  1277. X                if (start_x > last_x)  /*switch so lesser coordinate is first*/
  1278. X                {
  1279. X                    temp = start_x;
  1280. X                start_x = last_x;
  1281. X                last_x = temp;
  1282. X            }
  1283. X            if (start_y > last_y)  /*switch so lesser coordinate is first*/
  1284. X            {
  1285. X                    temp = start_y;
  1286. X                start_y = last_y;
  1287. X                last_y = temp;
  1288. X            }
  1289. X                set_paused_cursors();   /*this may take a while*/
  1290. X                save_image_on_disk(disp_info[disp_num].disp, 
  1291. X               disp_info[disp_num].win_id, start_x, start_y, 
  1292. X                   last_x - start_x, last_y - start_y, 
  1293. X                   disp_info[disp_num].dialog_text_return);
  1294. X                unset_paused_cursors();   /*done*/
  1295. X        }
  1296. X        /*simulate choosing the "scrawl" menu selection*/
  1297. X        menu_selection(disp_num, 0, &num_people_drawing, 
  1298. X                   disp_info[disp_num].previous_scrawl_mode);
  1299. X            break;
  1300. X    case READ_IN_IMAGE:
  1301. X        if (disp_info[disp_num].dialog_reply_index == 0)
  1302. X        {
  1303. X            printf("Image Read In was canceled.\n");
  1304. X            /*simulate choosing the "scrawl" menu selection*/
  1305. X            menu_selection(disp_num, 0, &num_people_drawing, 
  1306. X                   disp_info[disp_num].previous_scrawl_mode);
  1307. X                return(0);
  1308. X        }
  1309. X            else 
  1310. X        {
  1311. X        set_paused_cursors();     /*this may take a while*/
  1312. X                if ((fp = fopen(disp_info[disp_num].dialog_text_return,"r")) 
  1313. X                != NULL)
  1314. X        {
  1315. X            fclose(fp);
  1316. X            depth = -1;   /*to see if it actually worked at all*/
  1317. X            the_image = read_image_from_disk(disp_info[disp_num].disp,
  1318. X                   disp_info[disp_num].win_id,
  1319. X                   disp_info[disp_num].dialog_text_return, &width,
  1320. X                        &height, &depth);
  1321. X
  1322. X            unset_paused_cursors();   /*done*/
  1323. X            if ((depth == -1) || (the_image == NULL))  /*it failed*/
  1324. X            {
  1325. X                    printf("ERROR: Something went wrong with the ");
  1326. X            printf("Read Image.\n");
  1327. X                    /*simulate choosing the "scrawl" menu selection*/
  1328. X                    menu_selection(disp_num, 0, &num_people_drawing, 
  1329. X                   disp_info[disp_num].previous_scrawl_mode);
  1330. X                return(0);
  1331. X            }
  1332. X            else
  1333. X            {
  1334. X                XDestroyImage(the_image);
  1335. X                disp_info[disp_num].rubber_band_width = width;
  1336. X                disp_info[disp_num].rubber_band_height = height;
  1337. X                disp_info[disp_num].first_point_bool = TRUE;
  1338. X                disp_info[disp_num].scrawl_mode = PLACING_AN_IMAGE;
  1339. X            }
  1340. X        }
  1341. X        else
  1342. X        {
  1343. X                printf("ERROR: Not a valid file.\n");
  1344. X                /*simulate choosing the "scrawl" menu selection*/
  1345. X                menu_selection(disp_num, 0, &num_people_drawing, 
  1346. X                   disp_info[disp_num].previous_scrawl_mode);
  1347. X            unset_paused_cursors();   /*done*/
  1348. X            return(0);
  1349. X        }
  1350. X        }
  1351. X        break;
  1352. X    default:
  1353. X        printf("ERROR: unknown action in do_dialog_action().\n");
  1354. X        break;
  1355. X    } 
  1356. X}
  1357. X
  1358. X
  1359. X/*
  1360. X * draw_shape - this function draws the current shape on all displays with
  1361. X *              dimensions indicated
  1362. X */
  1363. Xdraw_shape(disp_num, start_x, start_y, last_x, last_y)
  1364. Xint disp_num, start_x, start_y, last_x, last_y;
  1365. X{
  1366. X    int i, temp, width, height;
  1367. X
  1368. X    if (disp_info[disp_num].current_shape != STRAIGHT_LINE)
  1369. X    {
  1370. X        if (start_x > last_x)  /*switch so lesser coordinate is first*/
  1371. X        {
  1372. X            temp = start_x;
  1373. X        start_x = last_x;
  1374. X        last_x = temp;
  1375. X    }
  1376. X    if (start_y > last_y)  /*switch so lesser coordinate is first*/
  1377. X    {
  1378. X            temp = start_y;
  1379. X        start_y = last_y;
  1380. X        last_y = temp;
  1381. X    }
  1382. X    }
  1383. X
  1384. X    width = last_x - start_x;
  1385. X    height = last_y - start_y;
  1386. X
  1387. X    switch(disp_info[disp_num].current_shape)
  1388. X    {
  1389. X    case STRAIGHT_LINE:
  1390. X        for (i=0; i < num_of_disps; i++)
  1391. X                if (disp_info[i].in_session_bool)
  1392. X                    XDrawLine(disp_info[i].disp, disp_info[i].win_id,
  1393. X                  disp_info[disp_num].win_gc[i], start_x, start_y, 
  1394. X              last_x, last_y);
  1395. X        break;
  1396. X    case OUTLINE_RECT:
  1397. X        for (i=0; i < num_of_disps; i++)
  1398. X                if (disp_info[i].in_session_bool)
  1399. X                    XDrawRectangle(disp_info[i].disp, disp_info[i].win_id,
  1400. X                  disp_info[disp_num].win_gc[i], start_x, start_y, 
  1401. X              width, height);
  1402. X        break;
  1403. X    case FILLED_RECT:
  1404. X        for (i=0; i < num_of_disps; i++)
  1405. X                if (disp_info[i].in_session_bool)
  1406. X                    XFillRectangle(disp_info[i].disp, disp_info[i].win_id,
  1407. X                  disp_info[disp_num].win_gc[i], start_x, start_y, 
  1408. X              width, height);
  1409. X        break;
  1410. X    case OUTLINE_OVAL:
  1411. X        for (i=0; i < num_of_disps; i++)
  1412. X                if (disp_info[i].in_session_bool)
  1413. X                    XDrawArc(disp_info[i].disp, disp_info[i].win_id,
  1414. X                  disp_info[disp_num].win_gc[i], start_x, start_y, 
  1415. X              width, height, 0, 23040);
  1416. X        break;
  1417. X    case FILLED_OVAL:
  1418. X        for (i=0; i < num_of_disps; i++)
  1419. X                if (disp_info[i].in_session_bool)
  1420. X                    XFillArc(disp_info[i].disp, disp_info[i].win_id,
  1421. X                  disp_info[disp_num].win_gc[i], start_x, start_y, 
  1422. X              width, height, 0, 23040);
  1423. X        break;
  1424. X    default:
  1425. X        printf("ERROR: in draw_shape routine.\n");
  1426. X        break;
  1427. X    }
  1428. X}
  1429. X
  1430. X
  1431. X/*
  1432. X * read_in_and_place_bitmap - this function reads the bitmap named in the 
  1433. X *                  second parameter and puts it at the indicated spot on
  1434. X *                  all the displays.  It does this in a hokey way, reading
  1435. X *                  it from the file for every display.  It is a bit slow,
  1436. X *                  but is short and easy for me.
  1437. X */
  1438. Xread_in_and_place_bitmap(disp_num, bitmap_filename, x, y)
  1439. Xint disp_num;
  1440. Xchar *bitmap_filename;
  1441. Xint x, y;
  1442. X{
  1443. X    int width, height, xhr, yhr, i;
  1444. X
  1445. X    Pixmap the_pixmap;
  1446. X
  1447. X    set_paused_cursors();                     /*this may take a while*/
  1448. X
  1449. X    for (i=0; i<num_of_disps; i++)
  1450. X    {
  1451. X        if (disp_info[i].in_session_bool)
  1452. X        {
  1453. X            if (XReadBitmapFile(disp_info[i].disp, disp_info[i].win_id,
  1454. X           bitmap_filename, &width, &height, &the_pixmap, &xhr, &yhr) ==
  1455. X           BitmapSuccess)        
  1456. X            {                           /*we got it! run with it!*/
  1457. X                XCopyPlane(disp_info[i].disp, the_pixmap, disp_info[i].win_id, 
  1458. X          disp_info[disp_num].win_gc[i], 0, 0, width, height, x, y, 1);
  1459. X                XFlush(disp_info[i].disp);
  1460. X        }
  1461. X            else
  1462. X        {
  1463. X            printf("ERROR: Not a valid bitmap file.\n");
  1464. X            break;
  1465. X        }
  1466. X        }
  1467. X    }
  1468. X
  1469. X    unset_paused_cursors();                     /*this may take a while*/
  1470. X    /*simulate choosing the "scrawl" menu selection*/
  1471. X    menu_selection(disp_num, 0, &num_people_drawing, 
  1472. X                   disp_info[disp_num].previous_scrawl_mode);
  1473. X}
  1474. X
  1475. X
  1476. X/*
  1477. X * save_bitmap_on_disk - this routine saves the region selected as a bitmap
  1478. X *                   on the disk.  The background is saved as a 0, and any
  1479. X *                   and all foreground colors (anything different from the
  1480. X *                   background) is stored as a 1.
  1481. X */
  1482. Xsave_bitmap_on_disk(disp_num, x, y, width, height, bitmap_name)
  1483. Xint disp_num, x, y, width, height;
  1484. Xchar *bitmap_name;
  1485. X{
  1486. X    XImage *the_image;
  1487. X    int x_cord, y_cord, cur_left_byte, cur_right_byte;
  1488. X    int num_on_this_line, done, i;
  1489. X    FILE *bitmap_file;
  1490. X
  1491. X    /*
  1492. X     * the width must be an even multiple of 8 for a standard bitmap file
  1493. X     */
  1494. X    width = ((width/8) + 1) * 8;
  1495. X
  1496. X    if ((the_image = XGetImage(disp_info[disp_num].disp, 
  1497. X                  disp_info[disp_num].win_id, x, y, width, height,
  1498. X              (~0), ZPixmap)) == NULL)
  1499. X    {
  1500. X         printf("ERROR: XGetImage failed.\n");
  1501. X     return(0);
  1502. X    }
  1503. X    else if ((bitmap_file = fopen(bitmap_name, "w")) == NULL) 
  1504. X    {
  1505. X         /*fopen failed*/
  1506. X     XDestroyImage(the_image);
  1507. X         printf("ERROR: attempt to save bitmap to a file failed.\n");
  1508. X     return(0);
  1509. X    }
  1510. X
  1511. X    fprintf(bitmap_file, "#define %s_width %d\n", bitmap_name, width);
  1512. X    fprintf(bitmap_file, "#define %s_height %d\n", bitmap_name, height);
  1513. X    fprintf(bitmap_file, "static char %s_bits[] = {\n", bitmap_name);
  1514. X    fprintf(bitmap_file, "   ");
  1515. X
  1516. X    /*
  1517. X     * the following blows the data out to the file on disk
  1518. X     */
  1519. X    num_on_this_line = 0;
  1520. X    for (y_cord=0, done=FALSE; done==FALSE; y_cord++)
  1521. X    {
  1522. X        for (x_cord=0; x_cord < width; x_cord+=8)
  1523. X        {
  1524. X        cur_right_byte = 0;
  1525. X        cur_left_byte = 0;
  1526. X    
  1527. X        for (i=0; i<4; i++)
  1528. X        {
  1529. X                if (XGetPixel(the_image, x_cord+i, y_cord) != 
  1530. X                disp_info[disp_num].background)
  1531. X            { 
  1532. X                cur_right_byte |= 1<<i;
  1533. X            }
  1534. X            }
  1535. X        for (i=0; i<4; i++)
  1536. X        {
  1537. X                if (XGetPixel(the_image, x_cord+i+4, y_cord) != 
  1538. X                disp_info[disp_num].background)
  1539. X            { 
  1540. X                cur_left_byte |= 1<<i;
  1541. X            }
  1542. X            }
  1543. X            fprintf(bitmap_file, "0x%x%x", cur_left_byte, cur_right_byte);
  1544. X        num_on_this_line++;
  1545. X    
  1546. X        if ((y_cord == height-1) && (x_cord == (width-8)))
  1547. X        {
  1548. X                fprintf(bitmap_file, "};\n");
  1549. X            done = TRUE;
  1550. X            break;
  1551. X        }
  1552. X        else if (num_on_this_line == 12)
  1553. X        {
  1554. X                fprintf(bitmap_file, ",\n");
  1555. X                fprintf(bitmap_file, "   ");
  1556. X            num_on_this_line = 0;
  1557. X        }
  1558. X            else
  1559. X                fprintf(bitmap_file, ", ");
  1560. X        }
  1561. X    }
  1562. X    fclose(bitmap_file);
  1563. X    XDestroyImage(the_image);
  1564. X}
  1565. X
  1566. X
  1567. X/*
  1568. X * handle_SelectionNotify_event - this function handles a SelectionNotify event
  1569. X *                   in this particular scrawler's window.  It is probably a
  1570. X *                   "paste" of characters from the window manager.
  1571. X */
  1572. Xhandle_SelectionNotify_event(the_event, disp_num)
  1573. XXEvent *the_event;
  1574. Xint disp_num;
  1575. X{
  1576. X    XSelectionEvent *temp_event;
  1577. X    int i, alive;
  1578. X
  1579. X    temp_event = (XSelectionEvent *) the_event;
  1580. X    printf("Hey!  We just got a Selection Notify event!\n");
  1581. X}
  1582. X
  1583. X
  1584. X/*
  1585. X * handle_ClientMessage_event - this function handles a ClientMessage event in
  1586. X *                   this particular scrawler's window.  It is probably a
  1587. X *                   a "WM_DESTROY" from the window manager.
  1588. X */
  1589. Xhandle_ClientMessage_event(the_event, disp_num)
  1590. XXEvent *the_event;
  1591. Xint disp_num;
  1592. X{
  1593. X    XClientMessageEvent *temp_event;
  1594. X    int i, alive;
  1595. X
  1596. X    temp_event = (XClientMessageEvent *) the_event;
  1597. X    if (temp_event->data.l[0] == disp_info[disp_num].xa_WM_DELETE_WINDOW)
  1598. X    {
  1599. X        XDestroyWindow(disp_info[disp_num].disp, disp_info[disp_num].win_id);
  1600. X        disp_info[disp_num].in_session_bool = FALSE; /*no window*/
  1601. X        XCloseDisplay(disp_info[disp_num].disp);
  1602. X
  1603. X        for (i=alive=0; i< num_of_disps; i++)
  1604. X        {
  1605. X           if (disp_info[i].in_session_bool)
  1606. X       {
  1607. X           alive = TRUE;
  1608. X           break;
  1609. X       }
  1610. X    }
  1611. X    if (alive)
  1612. X    {
  1613. X            for (i=0; i<num_of_disps; i++)
  1614. X            place_and_draw_status_win(i);
  1615. X    }
  1616. X    else
  1617. X       exit(0);/*if no one is still in session, stop running*/
  1618. X    }
  1619. X    else
  1620. X        printf("ERROR: in handle_ClientMessage_event.\n");
  1621. X}
  1622. X
  1623. X
  1624. X/*
  1625. X * load_moron_fonts - this function loads fonts for real morons and owners
  1626. X *              of Sun workstations.  The thing is, both morons and
  1627. X *              owners of Sun workstations have systems that are so screwed
  1628. X *              up, they can't find R4 fonts when you try to allocate them 
  1629. X *              using the font name.  Therefore, this is a really, really ugly
  1630. X *              hack to allow their systems to find ONLY MY default fonts 
  1631. X *              using xlfd strings.  This will work with NO OTHER fonts.  
  1632. X *              This function returns TRUE if it allocated a font, and FALSE
  1633. X *              if not.  Hopefully this function will keep 90% of the Sun
  1634. X *              users happy, and thinking they got their moneys worth when
  1635. X *              buying Sun, when actually they made a drastic mistake.
  1636. X */
  1637. Xload_moron_fonts(disp_num, i, font_file_name)
  1638. Xint disp_num, i;
  1639. Xchar *font_file_name;
  1640. X{
  1641. X    char xlfd_string[512];
  1642. X    XFontStruct *the_font_struct;
  1643. X
  1644. X    if (strcmp(font_file_name, "fixed") == 0)
  1645. X    strcpy(xlfd_string, "fixed");
  1646. X    else if (strcmp(font_file_name, "variable") == 0)
  1647. X    strcpy(xlfd_string, "-*-helvetica-bold-r-normal-*-*-120-*-*-*-*-*-*");
  1648. X    else if (strcmp(font_file_name, "timR12") == 0)
  1649. X    strcpy(xlfd_string, 
  1650. X           "-adobe-times-medium-r-normal--12-120-75-75-p-64-iso8859-1");
  1651. X    else if (strcmp(font_file_name, "helvO12") == 0)
  1652. X    strcpy(xlfd_string, 
  1653. X           "-adobe-helvetica-medium-o-normal--12-120-75-75-p-67-iso8859-1");
  1654. X    else if (strcmp(font_file_name, "courR12") == 0)
  1655. X    strcpy(xlfd_string, 
  1656. END_OF_FILE
  1657. if test 33168 -ne `wc -c <'wscrawl/xab'`; then
  1658.     echo shar: \"'wscrawl/xab'\" unpacked with wrong size!
  1659. fi
  1660. # end of 'wscrawl/xab'
  1661. fi
  1662. echo shar: End of archive 5 \(of 5\).
  1663. cp /dev/null ark5isdone
  1664. MISSING=""
  1665. for I in 1 2 3 4 5 ; do
  1666.     if test ! -f ark${I}isdone ; then
  1667.     MISSING="${MISSING} ${I}"
  1668.     fi
  1669. done
  1670. if test "${MISSING}" = "" ; then
  1671.     echo You have unpacked all 5 archives.
  1672.     rm -f ark[1-9]isdone
  1673. else
  1674.     echo You still need to unpack the following archives:
  1675.     echo "        " ${MISSING}
  1676. fi
  1677. ##  End of shell archive.
  1678. exit 0
  1679. dan
  1680. ----------------------------------------------------
  1681. O'Reilly && Associates   argv@sun.com / argv@ora.com
  1682. Opinions expressed reflect those of the author only.
  1683.