home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / gwm18a.zip / wl_pixmap.c < prev    next >
C/C++ Source or Header  |  1996-05-23  |  20KB  |  661 lines

  1. /* Copyright 1989 GROUPE BULL -- See license conditions in file COPYRIGHT
  2.  * Copyright 1989 Massachusetts Institute of Technology
  3.  */
  4. /***********************\
  5. *                 *
  6. *  WOOL_OBJECT: Pixmap  *
  7. *  BODY                *
  8. *                 *
  9. \***********************/
  10.  
  11. #define INCLUDE_PIXMAP_H
  12. #include "EXTERN.h"
  13. #include <stdio.h>
  14. #include <X11/xpm.h>
  15. #include "wool.h"
  16. #include "wl_string.h"
  17. #include "wl_atom.h"
  18. #include "wl_pointer.h"
  19. #include "wl_active.h"
  20. #include "wl_number.h"
  21. #include "wl_label.h"
  22. #include "wl_list.h"
  23. #include "gwm.h"
  24. #include <X11/Xatom.h>
  25. #include <X11/Xutil.h>
  26. #include "INTERN.h"
  27. #undef INCLUDE_PIXMAP_H
  28. #include "wl_pixmap.h"
  29. #include "def_bitmap.h"
  30.  
  31. /* local prototyping */
  32.  
  33. WOOL_OBJECT     wool_default_bitmap_make();
  34. WOOL_OBJECT     wool_default_pixmap_make();
  35.  
  36. /* when debugging, maintain the screen to which belongs the pixmap */
  37.  
  38. #ifdef DEBUG
  39. #define StorePixmapScreen(pixmap, root) \
  40.     pixmap -> screen = ScreenOfRoot(root)
  41. #else
  42. #define StorePixmapScreen(pixmap, root)
  43. #endif /* DEBUG */
  44.  
  45. /*
  46.  * makes a WOOL pixmap out of a X11 bitmap (or appropriate depth pixmap)
  47.  */
  48.  
  49. WOOL_Pixmap
  50. WLPixmap_make(pixmap)
  51. Pixmap    pixmap;
  52. {
  53.     WOOL_Pixmap     object = (WOOL_Pixmap)
  54.     Malloc(sizeof(struct _WOOL_Pixmap));
  55.     unsigned int    bw, depth;
  56.     Window          root;
  57.  
  58.     zrt_put(object);
  59.     object -> type = WLPixmap;
  60.     object->mask = 0;
  61.     XGetGeometry(dpy, pixmap, &root, &object -> x_hot, &object -> y_hot,
  62.          &object -> width, &object -> height, &bw, &depth);
  63.  
  64.     if (!object -> width || !object -> height || !depth) {    /* ERROR */
  65.     wool_default_pixmap_make(object, "invalid pixmap %s", "size");
  66.     } else if (depth == 1) {    /* BITMAP */
  67.     object -> pixmap = XCreatePixmap(dpy, Context->root, object -> width,
  68.                        object -> height, Context->depth);
  69.     XSetForeground(dpy, Context->gc.Work, Context -> pixel.Back);
  70.     XFillRectangle(dpy, object -> pixmap, Context->gc.Work, 0, 0,
  71.                object -> width, object -> height);
  72.     XSetForeground(dpy, Context->gc.Set, Context -> pixel.Fore);
  73.     XSetStipple(dpy, Context->gc.Set, pixmap);
  74.     XFillRectangle(dpy, object -> pixmap, Context->gc.Set, 0, 0,
  75.                object -> width, object -> height);
  76.     } else if (depth == Context->depth) {    /* PIXMAP */
  77.      object -> pixmap = XCreatePixmap(dpy, Context->root, object -> width,
  78.                         object -> height, Context->depth);
  79.      XCopyArea(dpy, pixmap, object->pixmap, Context->gc.Work, 0, 0,
  80.            object->width, object->height, 0, 0);
  81.     } else {            /* ERROR */
  82.     wool_default_pixmap_make(object, "Pixmap is of depth %d", depth);
  83.     }
  84.     StorePixmapScreen(object, root);
  85.     return object;
  86. }
  87.  
  88. /*
  89.  * the physical reading of a bitmap. Used for bitmaps & cursors
  90.  * if parameter is a label returns it!
  91.  */
  92.  
  93. WOOL_OBJECT
  94. wool_raw_bitmap_make(filename)
  95. WOOL_String    filename;
  96. {
  97.     char           *name;
  98.     WOOL_Pixmap     object;
  99.     char            temp_filename[MAX_TEMP_STRING_SIZE];
  100.  
  101.     must_be_string(filename, 0);
  102.     object = (WOOL_Pixmap) Malloc(sizeof(struct _WOOL_Pixmap));
  103.     zrt_put(object);
  104.     object -> type = WLPixmap;
  105.     object->mask = 0;
  106.     name = (char *) file_in_path(filename -> string,
  107.                  BITMAP_EXTENSION, wool_path, temp_filename);
  108.     if (!name) {
  109.     return wool_default_bitmap_make(object,
  110.               "GWM: Cannot find Bitmap %s", filename -> string);
  111.     }
  112.     switch (XReadBitmapFile(dpy, Context->root, name,
  113.              &object -> width, &object -> height, &object -> pixmap,
  114.                 &object -> x_hot, &object -> y_hot)) {
  115.     case BitmapOpenFailed:
  116.     return wool_default_bitmap_make(object,
  117.                     "Cannot open file %s", name);
  118.     case BitmapFileInvalid:
  119.     return wool_default_bitmap_make(object,
  120.                     "File %s is not a bitmap", name);
  121.     case BitmapNoMemory:
  122.     wool_error("No memory to load file %s", name);
  123.     break;
  124.     }
  125.     return (WOOL_OBJECT) object;
  126. }
  127.  
  128. /* Given a pre-allocated WOOL_Pixmap, fill it with  the default
  129.  * bitmap or pixmap, rexpectively
  130.  */
  131.  
  132. WOOL_OBJECT
  133. wool_default_bitmap_make(object, reason_format, reason)
  134. WOOL_Pixmap object;            /* empty wool structure */
  135. char *reason_format;            /* text of the error message or 0 */
  136. char *reason;                /* data for %s in reason format */
  137. {
  138.     if (reason_format) {
  139.     wool_printf(reason_format, reason);
  140.     wool_puts(", using default instead\n");
  141.     }
  142.     object -> width = def_bitmap_width;
  143.     object -> height = def_bitmap_height;
  144.     object -> x_hot = def_bitmap_x_hot;
  145.     object -> y_hot = def_bitmap_y_hot;
  146.     object -> pixmap = Context -> DefaultBitmap;
  147.     return (WOOL_OBJECT) object;
  148. }
  149.  
  150. WOOL_OBJECT
  151. wool_default_pixmap_make(object, reason_format, reason)
  152. WOOL_Pixmap object;                     /* empty wool structure */
  153. char *reason_format;                    /* text of the error message or 0 */
  154. char *reason;                           /* data for %s in reason format */
  155. {
  156.     if (reason_format) {
  157.         wool_printf(reason_format, reason);
  158.         wool_puts(", using default instead\n");
  159.     }
  160.     object -> width = def_bitmap_width;
  161.     object -> height = def_bitmap_height;
  162.  
  163.     XSetForeground(dpy, Context->gc.Work, Context -> pixel.Back);
  164.     object -> pixmap = XCreatePixmap(dpy, Context->root,
  165.                      object -> width, object -> height,
  166.                      Context->depth);
  167.     XFillRectangle(dpy, object -> pixmap, Context->gc.Work, 0, 0,
  168.            object -> width, object -> height);
  169.     XSetForeground(dpy, Context->gc.Set, Context -> pixel.Fore);
  170.     XSetStipple(dpy, Context->gc.Set, Context -> DefaultBitmap);
  171.     XFillRectangle(dpy, object -> pixmap, Context->gc.Set, 0, 0,
  172.            object -> width, object -> height);
  173.     StorePixmapScreen(object, Context -> root);
  174.     return (WOOL_OBJECT) object;
  175. }
  176.  
  177. /*
  178.  * to overlay bitmaps:
  179.  * (layered-bitmap-make back "file1" color1 "file2" color2 ...)
  180.  * filenames can be active-labels
  181.  */
  182.  
  183. WOOL_Pixmap
  184. wool_layered_bitmap_make(argc, argv)
  185. int argc;
  186. WOOL_Pixmap argv[];
  187. {
  188.     Pixmap          pix;
  189.     int             i;
  190.     unsigned int    width = 0, height = 0;
  191.     WOOL_Pixmap     object;
  192.     struct _Box     box;
  193.     WOOL_Label      label;
  194.     Graphic_desc   *graphics;
  195.  
  196.     if ((argc == 0) || (argc > 2 && (argc % 2 == 0)))
  197.     wool_error(BAD_NUMBER_OF_ARGS, argc);
  198.     if (argc == 1) {        /* one args re-calls with default colors */
  199.     WOOL_Number     new_argv[3];
  200.  
  201.     new_argv[0] = WLNumber_make(Context -> pixel.Back);
  202.     new_argv[2] = WLNumber_make(Context -> pixel.Fore);
  203.     new_argv[1] = (WOOL_Number) argv[0];
  204.     return (WOOL_Pixmap) wool_layered_bitmap_make(3, new_argv);
  205.     }
  206.     if (argc == 2) {        /* two args make a blank bitmaps */
  207.     return wool_make_blank_bitmap(argv[0], argv[1]);
  208.     }
  209.     /* multi-args form */
  210.     must_be_number(argv[0], 0);
  211.     must_be_number(argv[2], 2);
  212.     graphics = (Graphic_desc *) Malloc(sizeof(Graphic_desc) * argc);
  213.     
  214.     /* first determine the size of the final pixmap and load the bitmaps */
  215.     for (i = 1; i < argc; i += 2) {
  216.     if (is_a_string(argv[i])) {
  217.         graphics[i].is_bitmap = 1;
  218.         argv[i] = (WOOL_Pixmap) wool_raw_bitmap_make(argv[i]);
  219.     } else {
  220.         graphics[i].is_bitmap = 0;
  221.     }
  222.     WOOL_send(WOOL_get_dimensions, argv[i], (argv[i], &box));
  223.     graphics[i].width = box.width;
  224.     graphics[i].height = box.height;
  225.     width = Max(width, box.width);
  226.     height = Max(height, box.height);
  227.     }
  228.  
  229.     /* then lay the graphics one on top of another */
  230.     XSetForeground(dpy, Context->gc.Work, ((WOOL_Number) argv[0]) -> number);
  231.     pix = XCreatePixmap(dpy, Context->root, width, height, Context->depth);
  232.     XFillRectangle(dpy, pix, Context->gc.Work, 0, 0, width, height);
  233.     for (i = 1; i < argc; i += 2) {
  234.     must_be_number(argv[i + 1], i + 1);
  235.     if (graphics[i].is_bitmap) {
  236.         XSetForeground(dpy, Context->gc.Set,
  237.             ((WOOL_Number) argv[i + 1]) -> number);
  238.         XSetStipple(dpy, Context->gc.Set, argv[i] -> pixmap);
  239.         XSetTSOrigin(dpy, Context->gc.Set, (width - argv[i] -> width) / 2, (height - argv[i] -> height) / 2);
  240.         XFillRectangle(dpy, pix, Context->gc.Set,
  241.         (width - argv[i] -> width) / 2, (height - argv[i] -> height) / 2,
  242.                argv[i] -> width, argv[i] -> height);
  243.         XSetTSOrigin(dpy, Context->gc.Set, 0, 0);
  244.     } else if (argv[i] -> type == WLPixmap) {
  245.         XCopyArea(dpy, argv[i] -> pixmap, pix, Context->gc.Work, 0, 0,
  246.               argv[i] -> width, argv[i] -> height,
  247.               (width - argv[i] -> width) / 2,
  248.               (height - argv[i] -> height) / 2);
  249.     } else if (argv[i] -> type == WLLabel) {    /* label */
  250.         label = (WOOL_Label) argv[i];
  251.         XSetFont(dpy, Context->gc.Work, label -> font);
  252.         XSetForeground(dpy, Context->gc.Work,
  253.                ((WOOL_Number) argv[i + 1]) -> number);
  254.         XDrawString(dpy, pix, Context->gc.Work,
  255.             label -> x, label -> y, label -> label -> string,
  256.             strlen(label -> label -> string));
  257.     }
  258.     }
  259.  
  260.     /* then creates the WOOL_Pixmap */
  261.     object = (WOOL_Pixmap) Malloc(sizeof(struct _WOOL_Pixmap));
  262.     zrt_put(object);
  263.     object -> type = WLPixmap;
  264.     object->mask = 0;
  265.     object -> pixmap = pix;
  266.     object -> x_hot = object -> y_hot = 0;
  267.     object -> width = width;
  268.     object -> height = height;
  269.     Free(graphics);
  270.     StorePixmapScreen(object, Context -> root);
  271.     return object;
  272. }
  273.  
  274. /*
  275.  * makes a pixmap of "foreground" color of a given size
  276.  */
  277.  
  278. WOOL_Pixmap
  279. wool_make_blank_bitmap(width, height)
  280. WOOL_Number width;
  281. WOOL_Number height;
  282. {
  283.     WOOL_Pixmap     object;
  284.     Pixmap          pix;
  285.     WOOL_Pixmap     tile;
  286.  
  287.     get_val_from_context(tile, WA_tile);
  288.  
  289.     pix = XCreatePixmap(dpy, Context->root,
  290.             width -> number, height -> number, Context->depth);
  291.     if (tile->type != WLPixmap) {
  292.     /* no tile = use solid color */
  293.     XSetForeground(dpy, Context->gc.Work, Context -> pixel.Fore);
  294.     XFillRectangle(dpy, pix, Context->gc.Work, 0, 0,
  295.                width -> number, height -> number);
  296.     } else {
  297.     /* tile overrides color */
  298.     XSetTile(dpy, Context->gc.Tile, tile->pixmap);
  299.     XFillRectangle(dpy, pix, Context->gc.Tile, 0, 0,
  300.                width -> number, height -> number);
  301.     }
  302.     object = (WOOL_Pixmap) Malloc(sizeof(struct _WOOL_Pixmap));
  303.     zrt_put(object);
  304.     object -> type = WLPixmap;
  305.     object->mask = 0;
  306.     object -> pixmap = pix;
  307.     object -> x_hot = object -> y_hot = 0;
  308.     object -> width = width -> number;
  309.     object -> height = height -> number;
  310.     StorePixmapScreen(object, Context -> root);
  311.     return object;
  312. }
  313.  
  314. /*
  315.  * A stamp is a string "stamped" on the background to yield a bitmap
  316.  */
  317.  
  318. WOOL_OBJECT
  319. wool_stamp_make(argc, argv)
  320. int             argc;
  321. WOOL_String     argv[];
  322. {
  323.     int             up, down, dir, x, y, width, height, font;
  324.     XCharStruct     extent;
  325.     WOOL_Pixmap     object;
  326.  
  327.     if (argc == 0 || argc > 2)
  328.         return wool_error(BAD_NUMBER_OF_ARGS, argc);
  329.     must_be_string(argv[0], 0);
  330.     if (argc == 2) {
  331.         must_be_number(argv[1], 1);
  332.         font = ((WOOL_Number) argv[1]) -> number;
  333.     } else
  334.         font = DefaultFont;
  335.     object  = (WOOL_Pixmap) Malloc(sizeof(struct _WOOL_Pixmap));
  336.     XQueryTextExtents(dpy, font,
  337.               argv[0] -> string, strlen(argv[0] -> string),
  338.               &dir, &up, &down, &extent);
  339.     x = DefaultLabelHorizontalMargin - extent.lbearing;
  340.     y = DefaultLabelVerticalMargin + up;
  341.     width = Max(1, extent.width + 2 * DefaultLabelHorizontalMargin);
  342.     height = Max(1, up + down + 2 * DefaultLabelVerticalMargin);
  343.  
  344.     zrt_put(object);
  345.     object -> type = WLPixmap;
  346.     object->mask = 0;
  347.     object -> pixmap = XCreatePixmap(dpy, Context->root, width, height, 
  348.     Context->depth);
  349.     object -> x_hot = object -> y_hot = 0;
  350.     object -> width = width;
  351.     object -> height = height;
  352.  
  353.     XSetForeground(dpy, Context->gc.Work, Context -> pixel.Back);
  354.     XFillRectangle(dpy, object -> pixmap, Context->gc.Work,
  355.            0, 0, width, height);
  356.     XSetFont(dpy, Context->gc.Work, font);
  357.     XSetForeground(dpy, Context->gc.Work, Context -> pixel.Fore);
  358.     XDrawString(dpy, object -> pixmap, Context->gc.Work,
  359.         x, y, argv[0] -> string,
  360.         strlen(argv[0] -> string));
  361.     StorePixmapScreen(object, Context -> root);
  362.     return (WOOL_OBJECT) object;
  363. }
  364.  
  365. /*
  366.  * WLPixmap_print:
  367.  * a /  bitmap prints as [PIXMAP widthxheight id]
  368.  */
  369.  
  370. WOOL_OBJECT 
  371. WLPixmap_print(obj)
  372. WOOL_Pixmap     obj;
  373. {
  374.     wool_printf("{PIXMAP %dx", obj -> width);
  375.     wool_printf("%d", obj -> height);
  376.     wool_printf(" 0x%x", obj -> pixmap);
  377. #ifdef DEBUG
  378.     wool_printf(", on screen %d", obj -> screen);
  379. #endif /* DEBUG */
  380.     wool_puts("}");
  381.     return (WOOL_OBJECT) obj;
  382. }
  383.  
  384. /*
  385.  * WLPixmap_free:
  386.  * The structure is just freed, and string released.
  387.  */
  388.  
  389. WOOL_OBJECT 
  390. WLPixmap_free(obj)
  391. WOOL_Pixmap     obj;
  392. {
  393.     if (obj->pixmap != Context -> DefaultBitmap)
  394.         XFreePixmap(dpy, obj->pixmap);
  395.     if (obj->mask)
  396.         XFreePixmap(dpy, obj->mask);
  397.     Free(obj);
  398.     return NULL;
  399. }
  400.  
  401. /*
  402.  * returns the dimensions of the strings in the font + margins
  403.  * x,y is the start of the string (baseline) in the box.
  404.  */
  405.  
  406. WOOL_OBJECT
  407. WLPixmap_get_dimensions(bitmap, box)
  408. WOOL_Pixmap bitmap;
  409. Box    box;                 /* RETURN the dimensions */
  410. {
  411.     box -> x = 0;
  412.     box -> y = 0;
  413.     box -> width = bitmap -> width;
  414.     box -> height = bitmap -> height;
  415.     box -> shape = bitmap -> mask;
  416.     return NULL;
  417. }
  418.  
  419. /*
  420.  * opening a bitmap is putting it in backgroud
  421.  */
  422.  
  423. WOOL_OBJECT
  424. WLPixmap_open(bitmap, wob)
  425. WOOL_Pixmap    bitmap;
  426. Wob wob;
  427. {
  428.     XSetWindowBackgroundPixmap(dpy, wob -> hook, bitmap -> pixmap);
  429.     XClearWindow(dpy,  wob -> hook);
  430.     return NULL;        /* 0 means no exposure necessary */
  431. }
  432.  
  433. /*
  434.  * drawing a bitmap  (not needed ?)
  435.  */
  436.  
  437. WOOL_OBJECT
  438. WLPixmap_draw(bitmap, wob)
  439. WOOL_Pixmap    bitmap;
  440. Wob        wob;
  441. {
  442.     XClearWindow(dpy, wob -> hook);
  443.     return NULL;
  444. }
  445.  
  446. /*
  447.  * Reading of a Pixmap file (xpm v3 format)
  448.  */
  449.  
  450. WOOL_OBJECT
  451. wool_xpm_pixmap_make(argc, argv)
  452. int     argc;
  453. WOOL_String argv[];
  454. {
  455.     char           *name;
  456.     WOOL_Pixmap     object;
  457.     char            temp_filename[MAX_TEMP_STRING_SIZE];
  458.     unsigned int    npixels_return;
  459.     unsigned long   *pixels_return;
  460.     WOOL_String    filename;
  461.     XpmAttributes xpmatt;
  462.     XpmColorSymbol     *colorsymbols = 0;
  463.     int             ncolorsymbols = 0;
  464.     Pixmap pixmapshape;
  465.     int i;
  466.     int res;
  467.  
  468.     if ((argc == 0) || (argc > 2 && (argc % 2 == 0)))
  469.     wool_error(BAD_NUMBER_OF_ARGS, argc);
  470.     filename = argv[0];
  471.     must_be_string(filename, 0);
  472.     
  473.     if (argc > 1) {
  474.     ncolorsymbols = (argc-1)/2;
  475.     colorsymbols = (XpmColorSymbol *) Malloc(sizeof(XpmColorSymbol)
  476.                          * ncolorsymbols);
  477.     for (i=0; i<ncolorsymbols; i++) {
  478.         must_be_string(argv[i*2+1], i*2+1);
  479.         colorsymbols[i].name = argv[i*2+1] -> string;
  480.         if (argv[i*2+2]->type == WLNumber) {
  481.         colorsymbols[i].value = 0;
  482.         colorsymbols[i].pixel = ((WOOL_Number) argv[i*2+2])->number;
  483.         } else {
  484.         must_be_string(argv[i*2+2], i*2+2);
  485.         colorsymbols[i].value = argv[i*2+2] -> string;
  486.         }
  487.     }
  488.     }
  489.     object = (WOOL_Pixmap) Malloc(sizeof(struct _WOOL_Pixmap));
  490.     zrt_put(object);
  491.     object -> type = WLPixmap;
  492.     object -> x_hot = 0;
  493.     object -> y_hot = 0;
  494.     object -> mask = 0;
  495.     name = (char *) file_in_path(filename -> string,
  496.                  PIXMAP_EXTENSION, wool_path, temp_filename);
  497.     if (!name) {
  498.     return wool_default_pixmap_make(object,
  499.                     "GWM: Cannot find Pixmap %s", filename -> string);
  500.     }
  501.  
  502.     xpmatt.valuemask = XpmVisual|XpmColormap|XpmDepth|XpmColorSymbols;
  503.     xpmatt.visual = DefaultVisual(dpy, Context->screen);
  504.     xpmatt.colormap = DefaultColormap(dpy, Context->screen);
  505.     xpmatt.depth = Context->depth;
  506.     xpmatt.colorsymbols = colorsymbols;
  507.     xpmatt.numsymbols = ncolorsymbols;
  508.     if (GWM_xpm_closeness) {
  509.     xpmatt.closeness = GWM_xpm_closeness;
  510.     xpmatt.valuemask |= XpmCloseness;
  511.     }
  512.  
  513.     switch (
  514.     res = XpmReadFileToPixmap(dpy, Context->root, name,
  515.                       &object -> pixmap, &pixmapshape, &xpmatt),
  516.     (colorsymbols ? (Free(colorsymbols), 0) : 0),
  517.     res
  518.     ) {
  519.     case PixmapSuccess:
  520.         break;
  521.     case PixmapOpenFailed:
  522.         return wool_default_pixmap_make(object,
  523.                         "Cannot open file %s", name);
  524.     case PixmapFileInvalid:
  525.         return wool_default_pixmap_make(object,
  526.                         "File %s is not a XPM pixmap", name);
  527.     case PixmapNoMemory:
  528.         wool_error("No memory to load file %s", name);
  529.         break;
  530.     default:
  531.         wool_error("Error while reading pixmap %s", name);
  532.         break;
  533.     }
  534.     if (pixmapshape)
  535.     object->mask = pixmapshape;
  536.     object->width = xpmatt.width;
  537.     object->height = xpmatt.height;
  538.     return (WOOL_OBJECT) object;
  539. }
  540.  
  541. MakeDefaultBitmap()
  542. {
  543.     if (!(Context -> DefaultBitmap = XCreateBitmapFromData(dpy, Context->root,
  544.              def_bitmap_bits, def_bitmap_width, def_bitmap_height)))
  545.     wool_error(NO_MEMORY, "");
  546. }
  547.  
  548. /* Graphical primitives
  549.  */
  550.  
  551. /* draws a line in a pixmap:
  552.  * syntax (draw-line pixmap x1 y1 x2 y2)
  553.  * uses "foreground" color
  554.  */
  555.  
  556. WOOL_OBJECT
  557. wool_draw_line(argc, argv)
  558. int     argc;
  559. WOOL_Number argv[];
  560. {
  561.     int             i;
  562.  
  563.     if (argc != 5)
  564.     wool_error(BAD_NUMBER_OF_ARGS, argc);
  565.     must_be(WLPixmap, argv[0], 0);
  566.     for (i = 1; i < 5; i++)
  567.     must_be(WLNumber, argv[i], i);
  568.  
  569.     XSetForeground(dpy, Context->gc.Work, Context -> pixel.Fore);
  570.     XDrawLine(dpy, ((WOOL_Pixmap) argv[0]) -> pixmap, Context->gc.Work,
  571.           argv[1] -> number, argv[2] -> number,
  572.           argv[3] -> number, argv[4] -> number);
  573.     return (WOOL_OBJECT) argv[0];
  574. }
  575.  
  576. /* draws a filled rectangle in a pixmap:
  577.  * syntax (draw-rectangle pixmap x1 y1 width height border style)
  578.  * uses "foreground" color for border
  579.  * uses "background" color for rectangle
  580.  * style: 0 = nothing, 1 = outline, 2 = filled, 3 = outline+filled 
  581.  */
  582.  
  583. WOOL_OBJECT
  584. wool_draw_rectangle(argc, argv)
  585. int     argc;
  586. WOOL_Number argv[];
  587. {
  588.     int             i;
  589.  
  590.     if (argc != 7)
  591.     wool_error(BAD_NUMBER_OF_ARGS, argc);
  592.     must_be(WLPixmap, argv[0], 0);
  593.     for (i = 1; i < 7; i++)
  594.     must_be(WLNumber, argv[i], i);
  595.  
  596.     if (argv[6] -> number & 2) {    /* inside rectangle */
  597.     XSetForeground(dpy, Context->gc.Work, Context -> pixel.Back);
  598.     XFillRectangle(dpy, ((WOOL_Pixmap) argv[0]) -> pixmap,
  599.                Context->gc.Work,
  600.                argv[1] -> number, argv[2] -> number,
  601.                argv[3] -> number, argv[4] -> number);
  602.     }
  603.     if (argv[6] -> number & 1) {    /* ouline rectangle */
  604.     int linewidth = argv[5] -> number ? argv[5] -> number : 1;
  605.     XPoint points[5];
  606.  
  607.     points[0].x = argv[1] -> number - 1;
  608.     points[0].y = argv[2] -> number - 1;
  609.     points[1].x = points[0].x + argv[3] -> number + 1;
  610.     points[1].y = points[0].y;
  611.     points[2].x = points[1].x;
  612.     points[2].y = points[0].y + argv[4] -> number + 1;
  613.     points[3].x = points[0].x;
  614.     points[3].y = points[2].y;
  615.     points[4].x = points[0].x;
  616.     points[4].y = points[0].y;
  617.  
  618.     XSetForeground(dpy, Context->gc.Work, Context -> pixel.Fore);
  619.     XDrawLines(dpy, ((WOOL_Pixmap) argv[0]) -> pixmap,
  620.            Context->gc.Work, points, 5, CoordModeOrigin);
  621.     for (i = 1; i < linewidth; i++) {
  622.         points[0].x -= 1; points[0].y -= 1;
  623.         points[1].x += 1; points[1].y -= 1;
  624.         points[2].x += 1; points[2].y += 1;
  625.         points[3].x -= 1; points[3].y += 1;
  626.         points[4].x -= 1; points[4].y -= 1;
  627.         XDrawLines(dpy, ((WOOL_Pixmap) argv[0]) -> pixmap,
  628.                Context->gc.Work, points, 5, CoordModeOrigin);
  629.     }
  630.     }
  631.     return (WOOL_OBJECT) argv[0];
  632. }
  633.  
  634. /* prints a text in a pixmap:
  635.  * syntax (draw-text pixmap x1 y1 font text)
  636.  * uses "foreground" color for text color
  637.  */
  638.  
  639. WOOL_OBJECT
  640. wool_draw_text(argc, argv)
  641. int     argc;
  642. WOOL_Number argv[];
  643. {
  644.     int             i;
  645.  
  646.     if (argc != 5)
  647.     wool_error(BAD_NUMBER_OF_ARGS, argc);
  648.     must_be(WLPixmap, argv[0], 0);
  649.     for (i = 1; i < 4; i++)
  650.     must_be(WLNumber, argv[i], i);
  651.     must_be_string(argv[4], 4);
  652.  
  653.     XSetForeground(dpy, Context->gc.Work, Context -> pixel.Fore);
  654.     XSetFont(dpy, Context->gc.Work, argv[3]->number);
  655.     XDrawString(dpy,  ((WOOL_Pixmap) argv[0]) -> pixmap, Context->gc.Work,
  656.         argv[1] -> number, argv[2] -> number,
  657.         ((WOOL_String) argv[4]) -> string,
  658.         strlen(((WOOL_String) argv[4]) -> string));
  659.     return (WOOL_OBJECT) argv[0];
  660. }
  661.