home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Libraries / stdwin / Ports / x11 / draw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-02-08  |  13.3 KB  |  625 lines  |  [TEXT/????]

  1. /* X11 STDWIN -- Drawing operations */
  2.  
  3. #include "x11.h"
  4.  
  5. /* Window ID and Graphics Context used implicitly by all drawing operations */
  6.  
  7. static Window wid;
  8. static GC gc;
  9. COLOR _w_fgcolor, _w_bgcolor;
  10.  
  11. /* Put the current font's ID in the current GC, if non-null.
  12.    Called by _wfontswitch. */
  13.  
  14. _wgcfontswitch()
  15. {
  16.     if (gc != 0) {
  17.         if (_wf->fid == 0)
  18.             XCopyGC(_wd, DefaultGCOfScreen(_ws), GCFont, gc);
  19.         else
  20.             XSetFont(_wd, gc, _wf->fid);
  21.     }
  22. }
  23.  
  24. /* Begin drawing in the given window.
  25.    All drawing must be executed bewteen a call to wbegindrawing
  26.    and one to wenddrawing; in between, no other calls to wbegindrawing
  27.    should occur. */
  28.  
  29. static TEXTATTR saveattr;
  30. static COLOR savefgcolor, savebgcolor;
  31.  
  32. void
  33. wbegindrawing(win)
  34.     WINDOW *win;
  35. {
  36.     _wtrace(4, "wbegindrawing(win = 0x%lx)", (long)win);
  37.     if (wid != 0)
  38.         _werror("recursive wbegindrawing");
  39.     savefgcolor = _w_fgcolor;
  40.     savebgcolor = _w_bgcolor;
  41.     saveattr= wattr;
  42.     wid = win->wa.wid;
  43.     gc = win->gca;
  44.     _w_fgcolor = win->fga;
  45.     _w_bgcolor = win->bga;
  46.     XSetForeground(_wd, gc, (unsigned long) _w_fgcolor);
  47.     XSetBackground(_wd, gc, (unsigned long) _w_bgcolor);
  48.     wsettextattr(&win->attr);
  49.     if (win->caretshown)
  50.         _winvertcaret(win); /* Hide caret temporarily */
  51. }
  52.  
  53. /* End drawing in the given window */
  54.  
  55. void
  56. wenddrawing(win)
  57.     WINDOW *win;
  58. {
  59.     _wtrace(4, "wenddrawing(win = 0x%lx)", (long)win);
  60.     if (wid != win->wa.wid)
  61.         _werror("wrong call to enddrawing");
  62.     else {
  63.         wnoclip();
  64.         if (win->caretshown)
  65.             _winvertcaret(win); /* Put it back on */
  66.         _w_fgcolor = savefgcolor;
  67.         _w_bgcolor = savebgcolor;
  68.         XSetForeground(_wd, gc, (unsigned long) _w_fgcolor);
  69.         XSetBackground(_wd, gc, (unsigned long) _w_bgcolor);
  70.         wid = 0;
  71.         gc = 0;
  72.         wsettextattr(&saveattr);
  73.         XFlush(_wd);
  74.     }
  75. }
  76.  
  77.  
  78. /* Text measurement functions */
  79.  
  80.  
  81. /* Compute the space taken by a string when drawn in the current font */
  82.  
  83. int
  84. wtextwidth(str, len)
  85.     char *str;
  86.     int len;
  87. {
  88.     if (len < 0)
  89.         len= strlen(str);
  90.     len= XTextWidth(_wf, str, len);
  91.     _wtrace(7, "wtextwidth: width=%d", len);
  92.     return len;
  93. }
  94.  
  95. /* Compute a character's width */
  96.  
  97. int
  98. wcharwidth(c)
  99.     int c;
  100. {
  101.     char buf[2];
  102.     
  103.     buf[0]= c;
  104.     return wtextwidth(buf, 1);
  105. }
  106.  
  107. /* Compute the right vertical spacing for the current font */
  108.  
  109. int
  110. wlineheight()
  111. {
  112.     return _wf->ascent + _wf->descent;
  113. }
  114.  
  115. /* Compute how much the baseline of the characters drawn lies below
  116.    the v coordinate passed to wdrawtext or wdrawchar */
  117.  
  118. int
  119. wbaseline()
  120. {
  121.     return _wf->ascent;
  122. }
  123.  
  124.  
  125. /* Text drawing functions */
  126.  
  127.  
  128. /* Draw a text string */
  129.  
  130. void
  131. wdrawtext(h, v, str, len)
  132.     int h, v;
  133.     char *str;
  134.     int len;
  135. {
  136.     int right;
  137.     int bottom= v + wlineheight();
  138.     
  139.     if (len < 0)
  140.         len= strlen(str);
  141.     _wtrace(5, "wdrawtext(%d, %d, \"%.*s%s\", %d)",
  142.         h, v, len>20 ? 17 : len, len>20 ? "..." : "", str, len);
  143.     if (wattr.style & (INVERSE|HILITE|UNDERLINE))
  144.         right = h + wtextwidth(str, len);
  145.     if (wattr.style & (INVERSE|HILITE))
  146.         werase(h, v, right, bottom);
  147.     XDrawString(_wd, wid, gc, h, v + _wf->ascent, str, len);
  148.     if (wattr.style & UNDERLINE) {
  149.         unsigned long ulpos, ulthick;
  150.         if (!XGetFontProperty(_wf, XA_UNDERLINE_POSITION, &ulpos))
  151.             ulpos= _wf->descent/2;
  152.         if (!XGetFontProperty(_wf, XA_UNDERLINE_THICKNESS, &ulthick)) {
  153.             ulthick= _wf->descent/3;
  154.             CLIPMIN(ulthick, 1);
  155.         }
  156.         ulpos += v + _wf->ascent;
  157.         winvert(h, (int)ulpos, right, (int)(ulpos + ulthick));
  158.     }
  159.     if (wattr.style & (INVERSE|HILITE))
  160.         winvert(h, v, right, bottom);
  161. }
  162.  
  163. void
  164. wdrawchar(h, v, c)
  165.     int h, v;
  166.     int c;
  167. {
  168.     char ch= c;
  169.     
  170.     if ((wattr.style & (INVERSE|HILITE|UNDERLINE)) == 0) {
  171. #ifdef __GNUC__
  172.         /* Work-around for GCC bug (1.31 or some such):
  173.            without the _wtrace, XdrawString is never called. */
  174.         _wtrace(5, "wdrawchar(%d, %d, '\\%03o')", h, v, c&0377);
  175. #endif
  176.         /* Optimize plain characters */
  177.         XDrawString(_wd, wid, gc, h, v + _wf->ascent, &ch, 1);
  178.     }
  179.     else {
  180.         /* Use wdrawtext for complicated cases */
  181.         wdrawtext(h, v, &ch, 1);
  182.     }
  183. }
  184.  
  185.  
  186. /* Manipulate text attribute structs */
  187.  
  188.  
  189. /* Get a window's text attributes */
  190.  
  191. void
  192. wgetwintextattr(win, pattr)
  193.     WINDOW *win;
  194.     TEXTATTR *pattr;
  195. {
  196.     *pattr= win->attr;
  197. }
  198.  
  199. /* Change a window's text attributes */
  200.  
  201. void
  202. wsetwintextattr(win, pattr)
  203.     WINDOW *win;
  204.     TEXTATTR *pattr;
  205. {
  206.     win->attr= *pattr;
  207. }
  208.  
  209.  
  210. /* Non-text drawing primitives */
  211.  
  212.  
  213. /* Draw a straight line */
  214.  
  215. void
  216. wdrawline(h1, v1, h2, v2)
  217. {
  218.     _wtrace(7, "wdrawline((h1,v1)=(%d,%d), (h2,v2)=(%d,%d))",
  219.         h1, v1, h2, v2);
  220.     XDrawLine(_wd, wid, gc, h1, v1, h2, v2);
  221. }
  222.  
  223. /* Draw a straight line in XOR mode */
  224.  
  225. void
  226. wxorline(h1, v1, h2, v2)
  227. {
  228.     _wtrace(7, "wxorline((h1,v1)=(%d,%d), (h2,v2)=(%d,%d))",
  229.         h1, v1, h2, v2);
  230.     XSetFunction(_wd, gc, GXinvert);
  231.     XSetPlaneMask(_wd, gc, _w_fgcolor ^ _w_bgcolor);
  232.     XDrawLine(_wd, wid, gc, h1, v1, h2, v2);
  233.     XSetFunction(_wd, gc, GXcopy);
  234.     XSetPlaneMask(_wd, gc, AllPlanes);
  235. }
  236.  
  237. /* Draw a rectangle *inside* the given coordinate box */
  238.  
  239. void
  240. wdrawbox(left, top, right, bottom)
  241. {
  242.     _wtrace(7, "wdrawbox(left=%d, top=%d, right=%d, bottom=%d)",
  243.         left, top, right, bottom);
  244.     XDrawRectangle(_wd, wid, gc, left, top, right-left-1, bottom-top-1);
  245. }
  246.  
  247. /* Erase the given rectangle */
  248.  
  249. void
  250. werase(left, top, right, bottom)
  251. {
  252.     _wtrace(7, "werase(left=%d, top=%d, right=%d, bottom=%d)",
  253.         left, top, right, bottom);
  254.     
  255.     if (left >= right || top >= bottom)
  256.         return;
  257.     
  258.     /* Can't use XClearArea here because it ignores the clipping region.
  259.        Can't set function to GXclear because it doesn't work
  260.        with color.  So we fill with the background color. */
  261.     
  262.     XSetForeground(_wd, gc, (unsigned long) _w_bgcolor);
  263.     XFillRectangle(_wd, wid, gc, left, top, right-left, bottom-top);
  264.     XSetForeground(_wd, gc, (unsigned long) _w_fgcolor);
  265. }
  266.  
  267. /* Invert the bits in the given rectangle.
  268.    (This uses _winvert because this function is often used internally.) */
  269.  
  270. void
  271. winvert(left, top, right, bottom)
  272. {
  273.     _wtrace(7, "winvert(left=%d, top=%d, right=%d, bottom=%d)",
  274.         left, top, right, bottom);
  275.     
  276.     if (left >= right || top >= bottom)
  277.         return;
  278.  
  279.     /* _winvert assumes the plane mask is the XOR of fg and bg color;
  280.        this is no longer standard now we support colors... */
  281.  
  282.     XSetPlaneMask(_wd, gc, _w_fgcolor ^ _w_bgcolor);
  283.     _winvert(wid, gc, left, top, right-left, bottom-top);
  284.     XSetPlaneMask(_wd, gc, AllPlanes);
  285. }
  286.  
  287. /* Paint a given rectangle black */
  288.  
  289. void
  290. wpaint(left, top, right, bottom)
  291. {
  292.     _wtrace(7, "wpaint(left=%d, top=%d, right=%d, bottom=%d)",
  293.         left, top, right, bottom);
  294.     
  295.     if (left >= right || top >= bottom)
  296.         return;
  297.     
  298.     XFillRectangle(_wd, wid, gc, left, top, right-left, bottom-top);
  299. }
  300.  
  301. /* Shade a given area; this should add a lighter or darker raster
  302.    depending on the darkness percentage (0 = no raster, 100 = black) */
  303.  
  304. void
  305. wshade(left, top, right, bottom, percent)
  306. {
  307.     _wtrace(7, "wshade(left=%d, top=%d, right=%d, bottom=%d, percent=%d)",
  308.         left, top, right, bottom, percent);
  309.     
  310.     if (left >= right || top >= bottom)
  311.         return;
  312.     
  313.     XSetStipple(_wd, gc, _w_raster(percent));
  314.     XSetFillStyle(_wd, gc, FillStippled);
  315.     XFillRectangle(_wd, wid, gc, left, top, right-left, bottom-top);
  316.     XSetFillStyle(_wd, gc, FillSolid);
  317. }
  318.  
  319. /* Draw a circle with given center and radius */
  320.  
  321. void
  322. wdrawcircle(h, v, radius)
  323.     int h, v;
  324.     int radius;
  325. {
  326.     _wtrace(7, "wdrawcircle(h=%d, v=%d, radius=%d)", h, v, radius);
  327.     XDrawArc(_wd, wid, gc, h-radius, v-radius, 2*radius-1, 2*radius-1,
  328.         0, 360*64);
  329. }
  330.  
  331. /* Fill a circle with given center and radius */
  332.  
  333. void
  334. wfillcircle(h, v, radius)
  335.     int h, v;
  336.     int radius;
  337. {
  338.     _wtrace(7, "wfillcircle(h=%d, v=%d, radius=%d)", h, v, radius);
  339.     XFillArc(_wd, wid, gc, h-radius, v-radius, 2*radius-1, 2*radius-1,
  340.         0, 360*64);
  341. }
  342.  
  343. /* Invert a circle with given center and radius */
  344.  
  345. void
  346. wxorcircle(h, v, radius)
  347.     int h, v;
  348.     int radius;
  349. {
  350.     _wtrace(7, "wfillcircle(h=%d, v=%d, radius=%d)", h, v, radius);
  351.     XSetFunction(_wd, gc, GXinvert);
  352.     XSetPlaneMask(_wd, gc, _w_fgcolor ^ _w_bgcolor);
  353.     XFillArc(_wd, wid, gc, h-radius, v-radius, 2*radius-1, 2*radius-1,
  354.         0, 360*64);
  355.     XSetFunction(_wd, gc, GXcopy);
  356.     XSetPlaneMask(_wd, gc, AllPlanes);
  357. }
  358.  
  359. /* Draw an elliptical arc.
  360.    The begin and end angles are specified in degrees (I'm not sure this
  361.    is a good idea, but I don't like X's degrees*64 either...).
  362.    The arc is drawn counter-clockwise; 0 degrees is 3 o'clock.
  363.    wdrawcircle is equivalent to wdrawarc(h, v, radius, radius, 0, 360). */
  364.  
  365. void
  366. wdrawelarc(h, v, hhalf, vhalf, angle1, angle2)
  367.     int h, v;        /* Center */
  368.     int hhalf, vhalf;    /* Half axes */
  369.     int angle1, angle2;    /* Begin, end angle */
  370. {
  371.     _wtrace(7, "wdrawelarc(%d, %d, %d, %d, %d, %d)",
  372.         h, v, hhalf, vhalf, angle1, angle2);
  373.     XDrawArc(_wd, wid, gc, h-hhalf, v-vhalf, 2*hhalf-1, 2*vhalf-1,
  374.         angle1*64, angle2*64);
  375. }
  376.  
  377. /* Fill an elliptical arc segment */
  378.  
  379. void
  380. wfillelarc(h, v, hhalf, vhalf, angle1, angle2)
  381.     int h, v;        /* Center */
  382.     int hhalf, vhalf;    /* Half axes */
  383.     int angle1, angle2;    /* Begin, end angle */
  384. {
  385.     _wtrace(7, "wfillelarc(%d, %d, %d, %d, %d, %d)",
  386.         h, v, hhalf, vhalf, angle1, angle2);
  387.     XFillArc(_wd, wid, gc, h-hhalf, v-vhalf, 2*hhalf-1, 2*vhalf-1,
  388.         angle1*64, angle2*64);
  389. }
  390.  
  391. /* Invert an elliptical arc segment */
  392.  
  393. void
  394. wxorelarc(h, v, hhalf, vhalf, angle1, angle2)
  395.     int h, v;        /* Center */
  396.     int hhalf, vhalf;    /* Half axes */
  397.     int angle1, angle2;    /* Begin, end angle */
  398. {
  399.     _wtrace(7, "wfillelarc(%d, %d, %d, %d, %d, %d)",
  400.         h, v, hhalf, vhalf, angle1, angle2);
  401.     XSetFunction(_wd, gc, GXinvert);
  402.     XSetPlaneMask(_wd, gc, _w_fgcolor ^ _w_bgcolor);
  403.     XFillArc(_wd, wid, gc, h-hhalf, v-vhalf, 2*hhalf-1, 2*vhalf-1,
  404.         angle1*64, angle2*64);
  405.     XSetFunction(_wd, gc, GXcopy);
  406.     XSetPlaneMask(_wd, gc, AllPlanes);
  407. }
  408.  
  409. /* Draw n-1 lines connecting n points */
  410.  
  411. void
  412. wdrawpoly(n, points)
  413.     int n;
  414.     POINT *points;
  415. {
  416.     _wtrace(7, "wdrawpoly(%d, ...)", n);
  417.     XDrawLines(_wd, wid, gc, (XPoint *)points, n, CoordModeOrigin);
  418. }
  419.  
  420. /* Fill a polygon given by n points (may be self-intersecting) */
  421.  
  422. void
  423. wfillpoly(n, points)
  424.     int n;
  425.     POINT *points;
  426. {
  427.     _wtrace(7, "wfillpoly(%d, ...)", n);
  428.     XFillPolygon(_wd, wid, gc, (XPoint *)points, n,
  429.              Complex, CoordModeOrigin);
  430. }
  431.  
  432. /* Invert a polygon given by n points (may be self-intersecting) */
  433.  
  434. void
  435. wxorpoly(n, points)
  436.     int n;
  437.     POINT *points;
  438. {
  439.     _wtrace(7, "wfillpoly(%d, ...)", n);
  440.     XSetFunction(_wd, gc, GXinvert);
  441.     XSetPlaneMask(_wd, gc, _w_fgcolor ^ _w_bgcolor);
  442.     XFillPolygon(_wd, wid, gc, (XPoint *)points, n,
  443.              Complex, CoordModeOrigin);
  444.     XSetFunction(_wd, gc, GXcopy);
  445.     XSetPlaneMask(_wd, gc, AllPlanes);
  446. }
  447.  
  448. /* Clip drawing output to a rectangle. */
  449.  
  450. void
  451. wcliprect(left, top, right, bottom)
  452.     int left, top, right, bottom;
  453. {
  454.     XRectangle clip;
  455.     
  456.     _wtrace(7, "wcliprect(%d, %d, %d, %d)", left, top, right, bottom);
  457.     clip.x = left;
  458.     clip.y = top;
  459.     clip.width = right-left;
  460.     clip.height = bottom-top;
  461.     XSetClipRectangles(_wd, gc, 0, 0, &clip, 1, Unsorted);
  462. }
  463.  
  464. /* Cancel any clipping in effect. */
  465.  
  466. void
  467. wnoclip()
  468. {
  469.     XSetClipMask(_wd, gc, None);
  470. }
  471.  
  472.  
  473. /* Color stuff. */
  474.  
  475. void
  476. _w_initcolors()
  477. {
  478.     _w_fgcolor = _wgetpixel("foreground", "Foreground",
  479.                         BlackPixelOfScreen(_ws));
  480.     _w_bgcolor = _wgetpixel("background", "Background",
  481.                         WhitePixelOfScreen(_ws));
  482.     
  483.     /* Swap the pixel values if 'reverse' specified */
  484.     if (_wgetbool("reverse", "Reverse", 0)) {
  485.         unsigned long temp= _w_fgcolor;
  486.         _w_fgcolor = _w_bgcolor;
  487.         _w_bgcolor = temp;
  488.     }
  489. }
  490.  
  491. COLOR
  492. wgetfgcolor()
  493. {
  494.     return _w_fgcolor;
  495. }
  496.  
  497. COLOR
  498. wgetbgcolor()
  499. {
  500.     return _w_bgcolor;
  501. }
  502.  
  503. void
  504. wsetfgcolor(color)
  505.     COLOR color;
  506. {
  507.     if (color != BADCOLOR)
  508.         _w_fgcolor = color;
  509.     if (gc != 0)
  510.         XSetForeground(_wd, gc, (unsigned long) _w_fgcolor);
  511. }
  512.  
  513. void
  514. wsetbgcolor(color)
  515.     COLOR color;
  516. {
  517.     if (color != BADCOLOR)
  518.         _w_bgcolor = color;
  519.     if (gc != 0)
  520.         XSetBackground(_wd, gc, (unsigned long) _w_bgcolor);
  521. }
  522.  
  523.  
  524. /* Bitmap stuff. */
  525.  
  526. BITMAP *
  527. wnewbitmap(width, height)
  528.     int width, height;
  529. {
  530.     char *data;
  531.     XImage *xim;
  532.  
  533.     data = calloc(height * (width+31)/32, 4);
  534.     if (data == NULL) {
  535.         _werror("wnewbitmap: no mem for data");
  536.         return NULL;
  537.     }
  538.     xim = XCreateImage(_wd, DefaultVisualOfScreen(_ws), 1, XYBitmap, 0,
  539.                    data, width, height, 32, 0);
  540.     if (xim == NULL) {
  541.         _werror("wnewbitmap: XCreateImage failed");
  542.         free(data);
  543.         return NULL;
  544.     }
  545.     return (BITMAP *)xim;
  546. }
  547.  
  548. void
  549. wfreebitmap(bp)
  550.     BITMAP *bp;
  551. {
  552.     if (bp)
  553.         XDestroyImage((XImage*)bp);
  554. }
  555.  
  556. void
  557. wgetbitmapsize(bp, p_width, p_height)
  558.     BITMAP *bp;
  559.     int *p_width;
  560.     int *p_height;
  561. {
  562.     XImage *xim = (XImage*)bp;
  563.     *p_width = xim->width;
  564.     *p_height = xim->height;
  565. }
  566.  
  567. void
  568. wsetbit(bp, h, v, bit)
  569.     BITMAP *bp;
  570.     int h, v;
  571.     int bit;
  572. {
  573.     XImage *xim = (XImage*)bp;
  574.     if (0 <= h && h < xim->width && 0 <= v && v < xim->height)
  575.         XPutPixel(xim, h, v, (unsigned long)bit);
  576. }
  577.  
  578. int
  579. wgetbit(bp, h, v)
  580.     BITMAP *bp;
  581.     int h, v;
  582. {
  583.     XImage *xim = (XImage*)bp;
  584.     if (0 <= h && h < xim->width && 0 <= v && v < xim->height)
  585.         return XGetPixel(xim, h, v);
  586.     else
  587.         return 0;
  588. }
  589.  
  590. void
  591. wdrawbitmap(h, v, bp, mask)
  592.     int h, v;
  593.     BITMAP *bp;
  594.     BITMAP *mask;
  595. {
  596.     XImage *xim = (XImage*)bp;
  597.     if (mask == ALLBITS) {
  598.         _wtrace(6, "wdrawbitmap(%d, %d, bp, ALLBITS)", h, v);
  599.         XPutImage(_wd, wid, gc, xim, 0, 0, h, v,
  600.               xim->width, xim->height);
  601.     }
  602.     else if (mask == bp) {
  603.         /* Create a bitmap in the server, fill it with our bits,
  604.            use it as a stipple, set the origin, and fill it */
  605.         Pixmap pm = XCreatePixmap(_wd, wid,
  606.                       xim->width, xim->height, 1);
  607.         GC gc1 = XCreateGC(_wd, pm, 0L, (XGCValues*)0);
  608.         _wtrace(6, "wdrawbitmap(%d, %d, bp, bp)", h, v);
  609.         XSetForeground(_wd, gc1, 1L);
  610.         XSetBackground(_wd, gc1, 0L);
  611.         XPutImage(_wd, pm, gc1, xim, 0, 0, 0, 0,
  612.               xim->width, xim->height);
  613.         XFreeGC(_wd, gc1);
  614.         XSetStipple(_wd, gc, pm);
  615.         XSetTSOrigin(_wd, gc, h, v);
  616.         XSetFillStyle(_wd, gc, FillStippled);
  617.         XFillRectangle(_wd, wid, gc, h, v, xim->width, xim->height);
  618.         XSetFillStyle(_wd, gc, FillSolid);
  619.         XFreePixmap(_wd, pm);
  620.     }
  621.     else {
  622.         _werror("wdrawbitmap with generalized mask not supported");
  623.     }
  624. }
  625.