home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / yacl-012.zip / ui / dsplsurf.cxx < prev    next >
C/C++ Source or Header  |  1995-04-10  |  34KB  |  1,028 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6. /*
  7.  *
  8.  *          Copyright (C) 1994, M. A. Sridhar
  9.  *  
  10.  *
  11.  *     This software is Copyright M. A. Sridhar, 1994. You are free
  12.  *     to copy, modify or distribute this software  as you see fit,
  13.  *     and to use  it  for  any  purpose, provided   this copyright
  14.  *     notice and the following   disclaimer are included  with all
  15.  *     copies.
  16.  *
  17.  *                        DISCLAIMER
  18.  *
  19.  *     The author makes no warranties, either expressed or implied,
  20.  *     with respect  to  this  software, its  quality, performance,
  21.  *     merchantability, or fitness for any particular purpose. This
  22.  *     software is distributed  AS IS.  The  user of this  software
  23.  *     assumes all risks  as to its quality  and performance. In no
  24.  *     event shall the author be liable for any direct, indirect or
  25.  *     consequential damages, even if the  author has been  advised
  26.  *     as to the possibility of such damages.
  27.  *
  28.  */
  29.  
  30.  
  31. #if defined(__GNUC__)
  32. #pragma implementation
  33. #endif
  34.  
  35.  
  36. #include <iostream.h> // DEBUG
  37.  
  38. #include "base/bytstrng.h"
  39.  
  40. #include "ui/cntroler.h"
  41. #include "ui/bitmap.h"
  42. #include "ui/dsplsurf.h"
  43. #include "ui/visualob.h"
  44. #include "ui/color.h"
  45. #include "ui/arc.h"
  46. #include "ui/chord.h"
  47. #include "ui/ellipse.h"
  48. #include "ui/piewedge.h"
  49. #include "ui/containr.h"
  50. #include "ui/stencil.h"
  51.  
  52.  
  53. #if defined(__OS2__)
  54. static int _DrawMode [] = {
  55.     FM_ZERO,           //  GMode_Clear:        0
  56.     FM_AND,            //  GMode_And:          SRC & DEST
  57.     FM_MASKSRCNOT,     //  GMode_AndReverse:   SRC & ~DEST
  58.     FM_OVERPAINT,      //  GMode_Copy:         SRC
  59.     FM_SUBTRACT,       //  GMode_AndInverted:  ~SRC & DEST
  60.     FM_LEAVEALONE,     //  GMode_NoOp:         DEST
  61.     FM_XOR,            //  GMode_Xor:          SRC ^ DEST
  62.     FM_OR,             //  GMode_Or:           SRC | DEST
  63.     FM_NOTMERGESRC,    //  GMode_Nor:          ~(SRC | DEST)
  64.     FM_NOTXORSRC,      //  GMode_Equiv:        ~(SRC ^ DEST)
  65.     FM_INVERT,         //  GMode_Invert:       ~DEST
  66.     FM_MERGESRCNOT,    //  GMode_OrReverse:    SRC | ~DEST
  67.     FM_NOTCOPYSRC,     //  GMode_CopyInverted: ~SRC
  68.     FM_MERGENOTSRC,    //  GMode_OrInverted:   ~SRC | DEST
  69.     FM_NOTMASKSRC,     //  GMode_Nand:         ~(SRC & DEST)
  70.     FM_ONE             //  GMode_Set:          1
  71. };
  72. #elif defined(__MS_WINDOWS__)
  73. #include <windows.h>
  74. static int _DrawMode [] = {
  75.     R2_BLACK,          //  GMode_Clear = 0
  76.     R2_MASKPEN,        //  GMode_And
  77.     R2_MASKNOTPEN,     //  GMode_AndReverse
  78.     R2_COPYPEN,        //  GMode_Copy
  79.     R2_MASKPENNOT,     //  GMode_AndInverted
  80.     R2_NOP,            //  GMode_NoOp
  81.     R2_XORPEN,         //  GMode_Xor
  82.     R2_MERGEPEN,       //  GMode_Or
  83.     R2_NOTMERGEPEN,    //  GMode_Nor
  84.     R2_NOTXORPEN,      //  GMode_Equiv
  85.     R2_NOT,            //  GMode_Invert
  86.     R2_MERGENOTPEN,    //  GMode_OrReverse
  87.     R2_NOTCOPYPEN,     //  GMode_CopyInverted
  88.     R2_MERGEPENNOT,    //  GMode_OrInverted
  89.     R2_NOTMASKPEN,     //  GMode_Nand
  90.     R2_WHITE           //  GMode_Set
  91. };
  92.  
  93. #elif defined(__X_MOTIF__)
  94. #include <X11/Xatom.h>
  95. #include <X11/Xlib.h>
  96. #include <X11/Intrinsic.h>
  97. #include <X11/StringDefs.h>
  98.  
  99. static int _DrawMode [] = {
  100.     GXclear,                // 0 
  101.     GXand,                  // src AND dst
  102.     GXandReverse,           // src AND NOT dst
  103.     GXcopy,                 // src 
  104.     GXandInverted,          // NOT src AND dst 
  105.     GXnoop,                 // dst
  106.     GXxor,                  // src XOR dst
  107.     GXor,                   // src OR dst
  108.     GXnor,                  // NOT src AND NOT dst
  109.     GXequiv,                // NOT src XOR dst
  110.     GXinvert,               // NOT dst
  111.     GXorReverse,            // src OR NOT dst
  112.     GXcopyInverted,         // NOT src
  113.     GXorInverted,           // NOT src OR dst
  114.     GXnand,                 // NOT src OR NOT dst
  115.     GXset                   // 1
  116. }; 
  117.  
  118. #endif
  119.  
  120.  
  121. #if defined(__GNUC__) && __GNUC_MINOR__ >= 6
  122. template class CL_Binding<UI_DisplaySurface>;
  123. #endif
  124.  
  125.  
  126.  
  127.  
  128. UI_DisplaySurface::UI_DisplaySurface (UI_VisualObject* v)
  129.     : _client (*v)
  130. {
  131.     _Init ();
  132.     _ownFont = FALSE;
  133. }
  134.  
  135.  
  136. void UI_DisplaySurface::_Init ()
  137. {
  138.     _font = NULL;
  139. #if defined(__MS_WINDOWS__)
  140.     _handle  = GetDC (_client.ViewHandle ());
  141.     if (_handle) {
  142.         _horzPPM    = ((float) GetDeviceCaps (_handle, LOGPIXELSX)) / 25.4;
  143.         _vertPPM    = ((float) GetDeviceCaps (_handle, LOGPIXELSY)) / 25.4;
  144.         _horzPixels = GetDeviceCaps (_handle, HORZRES);
  145.         _vertPixels = GetDeviceCaps (_handle, VERTRES);
  146.     }
  147.     SetBkColor (_handle, _client.Background().NativeForm());
  148. #elif defined(__OS2__)
  149.     _handle = WinGetPS (_client.ViewHandle());
  150.     GpiCreateLogColorTable (_handle, LCOL_RESET, LCOLF_RGB, 0, 0, NULL);
  151.     // For the moment, we don't support colormaps under OS/2
  152.     Mode (GMode_Copy);
  153. #elif defined(__X_MOTIF__)
  154.     XGCValues xvalues;
  155.     Widget w = _client.ViewHandle ();
  156.     Display* dpy  = XtDisplay (w); 
  157.     short screen  = DefaultScreen (dpy);
  158.     XtVaGetValues (w, XtNbackground, &xvalues.background, XtNforeground,
  159.                    &xvalues.foreground, NULL);
  160.     _handle       = XCreateGC (dpy, XtWindow (w), GCForeground|GCBackground,
  161.                                &xvalues);
  162.     _horzPPM      = DisplayWidth (dpy, screen) / DisplayWidthMM(dpy, screen);
  163.     _vertPPM      = DisplayHeight (dpy, screen) / DisplayHeightMM(dpy, screen);
  164. #endif
  165.  
  166.     _brush  = new UI_Brush (this, UIColor_White, UIBrush_Hollow);
  167.     _pen    = new UI_Pen   (this);
  168.     // _colorMap = new UI_ColorMap (*this);
  169. }
  170.  
  171.  
  172.  
  173. typedef CL_Binding<UI_DisplaySurface> DSBind;
  174.  
  175. void UI_DisplaySurface::SetFont (UI_Font* fnt)
  176. {
  177.     if (fnt && fnt != _font) {
  178.         DSBind pre  (this, &UI_DisplaySurface::_FontWillChange);
  179.         fnt->AddPreChangeDependent (pre, 1);
  180.         DSBind post (this, &UI_DisplaySurface::_FontChanged);
  181.         fnt->AddDependent (post, 1);
  182.         if (_font) {
  183.             _font->RemoveDependent (post);
  184.             _font->RemovePreChangeDependent (pre);
  185.         }
  186.         _font = fnt;
  187.         _font->UseClient (this);
  188.  
  189. #if defined (__MS_WINDOWS__)
  190.         SelectObject (_handle, _font->Handle());
  191. #elif defined(__OS2__)
  192.         GpiSetCharSet (_handle, _font->Handle());
  193. #elif defined(__X_MOTIF__)
  194.         UI_ResourceHandle h = _font->Handle();
  195.         if (h) {
  196.             Display* dpy  = XtDisplay (_client.ViewHandle ()); 
  197.             XSetFont (dpy, _handle, h);
  198.         }
  199. #endif
  200.     }
  201. }
  202.  
  203.  
  204.  
  205. bool UI_DisplaySurface::_FontWillChange (CL_Object&, long)
  206. {
  207. #if defined (__MS_WINDOWS__)
  208.     SelectObject (_handle, GetStockObject (SYSTEM_FONT));
  209.  
  210. #elif defined (__X_MOTIF__)
  211.  
  212. #endif
  213.     return TRUE;
  214. }
  215.  
  216.  
  217. bool UI_DisplaySurface::_FontChanged (CL_Object& o, long)
  218. {
  219. #if defined (__MS_WINDOWS__)
  220.     SelectObject (_handle, ((UI_Font&) o).Handle ());
  221. #elif defined(__OS2__)
  222.     GpiSetCharSet (_handle, ((UI_Font&) o).Handle());
  223. #elif defined (__X_MOTIF__)
  224.     UI_ResourceHandle h = _font->Handle();
  225.     if (h) {
  226.         Display* dpy  = XtDisplay (_client.ViewHandle ()); 
  227.         XSetFont (dpy, _handle, h);
  228.     }
  229. #endif
  230.  
  231.     return TRUE;
  232. }
  233.  
  234.  
  235. UI_Point UI_DisplaySurface::_ProjectToCorner (UI_Rectangle &rect, UI_Point &p)
  236. {
  237.     short centerx = (rect.Right() - rect.Left  ()) /2;
  238.     short centery = (rect.Top  () - rect.Bottom()) /2;
  239.     long  xcoord  = 0, ycoord = 0;
  240.     
  241.     if (p.XCoord() >= centerx) xcoord = rect.Right();
  242.     else xcoord = rect.Left();
  243.     if (p.YCoord() >= centery) ycoord = rect.Bottom();
  244.     else ycoord = rect.Top();
  245.  
  246.     return UI_Point (xcoord, ycoord);
  247. }
  248.  
  249.  
  250. UI_DisplaySurface::~UI_DisplaySurface()
  251. {
  252.     if (_pen)
  253.         delete _pen;
  254.     if (_font) {
  255.         if (_ownFont)
  256.             delete _font;
  257.         else {
  258.             _font->UseClient (NULL);
  259.             DSBind pre  (this, &UI_DisplaySurface::_FontWillChange);
  260.             _font->RemovePreChangeDependent (pre);
  261.             DSBind post (this, &UI_DisplaySurface::_FontChanged);
  262.             _font->RemoveDependent (post);
  263.         }
  264.     }
  265.     if (_brush)
  266.         delete _brush;
  267. //     if (_colorMap)
  268. //         delete _colorMap;
  269. #if defined(__MS_WINDOWS__)
  270.     ReleaseDC (_client.ViewHandle (), _handle);
  271. #elif defined(__OS2__)
  272.     WinReleasePS (_handle);
  273. #elif defined(__X_MOTIF__)
  274.     XFreeGC (XtDisplay (_client), _handle);
  275.  
  276. #endif
  277. }
  278.  
  279.  
  280.  
  281. UI_Rectangle UI_DisplaySurface::DrawingArea () const
  282. {
  283. #if defined(__MS_WINDOWS__)
  284.     return UI_DrawingSurface::DrawingArea ();
  285. #elif defined(__X_MOTIF__) || defined(__OS2__)
  286.     return _client.ClientArea();
  287. #endif
  288. }
  289.  
  290.  
  291. UI_Rectangle UI_DisplaySurface::DrawingAreaInMM () const
  292. {
  293. #if defined(__MS_WINDOWS__) || defined(__OS2__)
  294.     return UI_DisplaySurface::DrawingAreaInMM ();
  295. #elif defined(__X_MOTIF__)
  296.     return _client.ClientArea();
  297. #endif
  298. }
  299.  
  300.  
  301. UI_DisplaySurface::GraphicsMode UI_DisplaySurface::Mode () const
  302. {
  303. #if defined(__MS_WINDOWS__)
  304.     int mode = GetROP2 (_handle);
  305.  
  306. #elif defined(__X_MOTIF__)
  307.     XGCValues xvalues;
  308.  
  309.     XGetGCValues (XtDisplay (_client), _handle, GCFunction, &xvalues);
  310.     int mode = xvalues.function;
  311.  
  312. #elif defined(__OS2__)
  313.     long mode = GpiQueryMix (_handle);
  314. #endif
  315.     for (short i = 0; i < sizeof (_DrawMode)/sizeof (int); i++) {
  316.         if (mode == _DrawMode [i])
  317.             return (GraphicsMode) i;
  318.     }
  319.     // Something wrong: it's not in the table!
  320.     return (GraphicsMode) 0;
  321. }
  322.  
  323.  
  324.  
  325. void UI_DisplaySurface::Mode (GraphicsMode mode)
  326. {
  327.     if (mode < GMode_Clear || mode > GMode_Set) {
  328.         CL_Error::Warning ("UI_DisplaySurface::Mode: invalid parameter %d",
  329.                            mode);
  330.         return;
  331.     }
  332. #if defined(__MS_WINDOWS__)
  333.     SetROP2 (_handle, _DrawMode [mode]);
  334. #elif defined(__OS2__)
  335.     GpiSetMix (_handle, _DrawMode[mode]);
  336. #elif defined (__X_MOTIF__)
  337.     XGCValues xvalues;
  338.     xvalues.function   = _DrawMode [mode];
  339.     XChangeGC (XtDisplay (_client), _handle, GCFunction, &xvalues);
  340. #endif
  341. }
  342.  
  343.  
  344.  
  345.  
  346. bool UI_DisplaySurface::DrawBitmap (const UI_Bitmap& b, const UI_Point& p)
  347. {
  348. #if defined (__MS_WINDOWS__) || defined(__OS2__)
  349.     return UI_DrawingSurface::DrawBitmap (b, p);
  350. #elif defined (__X_MOTIF__)
  351.     Widget     w  = _client;
  352.     Display* dpy  = XtDisplay (w);
  353.     Window    win = XtWindow  (w);
  354.     XPutImage (dpy, win, _handle, b.Handle(), 0, 0, p.XCoord(), p.YCoord(),
  355.                b.Width(), b.Height());
  356.     return TRUE;
  357. #else
  358.     NotImplemented ("DrawBitmap");
  359.     return FALSE;
  360. #endif
  361. }
  362.  
  363.  
  364. void UI_DisplaySurface::ClearDisplay ()
  365. {
  366. #if defined(__MS_WINDOWS__)
  367.     HANDLE hbr = CreateSolidBrush (_client.Background().NativeForm());
  368.     HANDLE old = SelectObject (_handle, hbr);
  369.     RECT rect = DrawingArea().AsMSRect();
  370.     FillRect (_handle, &rect, hbr);
  371.     if (old) 
  372.         SelectObject (_handle, old);
  373.     DeleteObject (hbr);
  374. #elif defined(__OS2__)
  375.     GpiErase (_handle);
  376. #elif defined(__X_MOTIF__)
  377.     Widget w = _client.ViewHandle ();
  378.     Display *dpy = XtDisplay (w);
  379.     XClearWindow (dpy, XtWindow (w));
  380. #endif
  381.  
  382. }
  383.  
  384.  
  385.  
  386.  
  387.  
  388. #if defined(__X_MOTIF__)
  389. class ColorSaver {
  390. public:
  391.     ColorSaver (UI_VisualObject& v, const UI_Color& c);
  392.     ~ColorSaver ();
  393.  
  394. protected:
  395.     UI_VisualObject& _vObj;
  396.     UI_Color         _tmpColor;
  397. };
  398.  
  399.  
  400. ColorSaver::ColorSaver (UI_VisualObject& v, const UI_Color& c)
  401. : _vObj (v)
  402. {
  403.     _tmpColor = v.Foreground();
  404.     v.Foreground (c);
  405. }
  406.  
  407.  
  408. ColorSaver::~ColorSaver ()
  409. {
  410.     _vObj.Foreground (_tmpColor);
  411. }
  412.  
  413. #endif
  414.  
  415.  
  416.  
  417.  
  418.  
  419. void UI_DisplaySurface::ColorRectangle (const UI_Rectangle& r,
  420.                                         const UI_Color& cs)
  421. {
  422. #if defined(__MS_WINDOWS__) || defined(__OS2__)
  423.     UI_DrawingSurface::ColorRectangle (r, cs);
  424.  
  425. #elif defined(__X_MOTIF__)
  426.     ColorSaver s (_client, cs);
  427.     Widget w = _client.ViewHandle ();
  428.     Display *dpy = XtDisplay (w);
  429.     XFillRectangle (dpy, XtWindow (w), _handle,
  430.                     r.Origin ().XCoord (), r.Origin ().YCoord (),
  431.                     r.Width (), r.Height ());
  432. #endif 
  433. }
  434.  
  435.  
  436.  
  437. void UI_DisplaySurface::DrawEllipse (const UI_Rectangle& r,
  438.                                      ushort opt)
  439. {
  440. #if defined(__MS_WINDOWS__) || defined(__OS2__)
  441.     UI_DrawingSurface::DrawEllipse (r, opt);
  442.  
  443. #elif defined(__X_MOTIF__)
  444.     Display *dpy = XtDisplay (_client);
  445.     if (opt & UID_Fill) {
  446.         ColorSaver save (_client, _brush->Color());
  447.         XFillArc (dpy, XtWindow (_client), _handle,  r.Origin ().XCoord (),
  448.                   r.Origin ().YCoord (), r.Width (), r.Height (), 0,
  449.                   64*360);
  450.     }
  451.     if (opt & UID_Outline) {
  452.         ColorSaver save (_client, _pen->Color());
  453.         XDrawArc (dpy, XtWindow (_client), _handle,
  454.                   r.Origin().XCoord (), r.Origin().YCoord (), r.Width (),
  455.                   r.Height (), 0, 64*360);
  456.     }
  457. #endif
  458. }
  459.  
  460.  
  461. void UI_DisplaySurface::DrawArc (const UI_Arc& arc)
  462. {
  463. #if defined (__MS_WINDOWS__) || defined(__OS2__)
  464.     UI_DrawingSurface::DrawArc (arc);
  465.     
  466. #elif defined (__X_MOTIF__)
  467.     UI_Rectangle  rect  = arc.Ellipse().BoundingRectangle();
  468.     long startAngle     = arc.StartAngle();
  469.     long subtAngle      = arc.SubtendedAngle();
  470.     Display *dpy        = _TheApplication->Controller().AppDisplay();
  471.  
  472.     ColorSaver save (_client, _pen->Color());
  473.     XDrawArc (dpy, XtWindow (Client()), Handle(), rect.Left(),
  474.               rect.Top(), rect.Width(), rect.Height(), startAngle,
  475.               subtAngle);
  476.  
  477. #endif
  478. }
  479.  
  480.  
  481.  
  482. void UI_DisplaySurface::DrawChord (const UI_Chord& chord,
  483.                                    ushort opt)
  484. {
  485. #if defined (__MS_WINDOWS__) || defined(__OS2__)
  486.     UI_DrawingSurface::DrawChord (chord, opt);
  487.     
  488. #elif defined (__X_MOTIF__)
  489.     UI_Rectangle  rect  = chord.Ellipse().BoundingRectangle();
  490.     long startAngle     = chord.StartAngle();
  491.     long subtAngle      = chord.SubtendedAngle();
  492.     Display *dpy        = _TheApplication->Controller().AppDisplay();
  493.     if (opt & UID_Fill) {
  494.         ColorSaver save (_client, _brush->Color());
  495.         XGCValues v;
  496.         v.arc_mode = ArcChord;
  497.         XChangeGC (dpy, Handle(), GCArcMode, &v);
  498.         XFillArc (dpy, XtWindow (Client()), Handle(), rect.Left(),
  499.                   rect.Top(), rect.Width(), rect.Height(), startAngle,
  500.                   subtAngle);
  501.     }
  502.     if (opt & UID_Outline) {
  503.         ColorSaver save (_client, _pen->Color());
  504.         UI_PointPair pp     = chord.EndPoints();
  505.         XDrawArc (dpy, XtWindow (Client()), Handle(), rect.Left(),
  506.                   rect.Top(), rect.Width(), rect.Height(), startAngle,
  507.                   subtAngle);
  508.         XDrawLine (dpy, XtWindow (Client()), Handle(),
  509.                    pp.p1.XCoord(), pp.p1.YCoord(),
  510.                    pp.p2.XCoord(), pp.p2.YCoord());
  511.     }
  512.     
  513. #endif
  514. }
  515.  
  516.  
  517. void UI_DisplaySurface::DrawPieWedge (const UI_PieWedge& pie,
  518.                                       ushort opt)
  519. {
  520. #if defined (__MS_WINDOWS__) || defined(__OS2__)
  521.     UI_DrawingSurface::DrawPieWedge (pie, opt);
  522.     
  523. #elif defined (__X_MOTIF__)
  524.     UI_Rectangle  rect  = pie.Ellipse().BoundingRectangle();
  525.     long startAngle     = pie.StartAngle();
  526.     long subtAngle      = pie.SubtendedAngle();
  527.     Display *dpy        = _TheApplication->Controller().AppDisplay();
  528.     if (opt & UID_Fill) {
  529.         ColorSaver save (_client, _brush->Color());
  530.         XGCValues v;
  531.         v.arc_mode = ArcPieSlice;
  532.         XChangeGC (dpy, Handle(), GCArcMode, &v);
  533.         XFillArc (dpy, XtWindow (Client()), Handle(), rect.Left(),
  534.                   rect.Top(), rect.Width(), rect.Height(), startAngle, 
  535.                   subtAngle);
  536.     }
  537.     if (opt & UID_Outline) {
  538.     UI_Rectangle rect  = pie.Ellipse().BoundingRectangle();
  539.     UI_PointPair pp    = pie.EndPoints();
  540.     ColorSaver save (_client, _pen->Color());
  541.     XDrawArc (dpy, XtWindow (Client()), Handle(),
  542.           rect.Left(), rect.Top(), rect.Width(),
  543.           rect.Height(), startAngle, subtAngle);
  544.     XDrawLine (dpy, XtWindow (Client()), Handle(), pp.p1.XCoord(),
  545.            pp.p1.YCoord(), rect.Left()+(rect.Width()/2),
  546.            rect.Top()+(rect.Height()/2));
  547.     XDrawLine (dpy, XtWindow (Client()), Handle(),
  548.            pp.p2.XCoord(), pp.p2.YCoord(),
  549.            rect.Left()+(rect.Width()/2),
  550.            rect.Top()+(rect.Height()/2));
  551.     }
  552.     
  553. #endif
  554. }
  555.  
  556.  
  557.  
  558. void UI_DisplaySurface::DrawPolygon (UI_Point parr[], short numpts,
  559.                                      ushort opt)
  560. {
  561. #if defined(__MS_WINDOWS__) || defined(__OS2__)
  562.     UI_DrawingSurface::DrawPolygon (parr, numpts, opt);
  563.  
  564. #elif defined(__X_MOTIF__)
  565.     if (numpts <= 1)
  566.         return;
  567.     Display *dpy = XtDisplay (_client);
  568.     if (opt & UID_Fill) {
  569.         Display *dpy = XtDisplay (_client);
  570.         ColorSaver save (_client, _brush->Color());
  571.         XPoint* xp = new XPoint [numpts];
  572.         for (long i = 0; i < numpts; i++) {
  573.             xp [i].x = parr [i].XCoord ();
  574.             xp [i].y = parr [i].YCoord ();
  575.         }
  576.         XFillPolygon (dpy, XtWindow (_client), _handle, xp, numpts,
  577.                       Complex, CoordModeOrigin);
  578.         delete [] xp;
  579.     }
  580.     if (opt & UID_Outline) {
  581.         DrawPolyLine (parr, numpts);
  582.         DrawLine (parr [numpts-1], parr [0]);
  583.     }
  584. #endif
  585. }
  586.  
  587. void UI_DisplaySurface::DrawRectangle (const UI_Rectangle& r,
  588.                                        ushort opt)
  589. {
  590. #if defined(__MS_WINDOWS__) || defined(__OS2__)
  591.     UI_DrawingSurface::DrawRectangle (r, opt);
  592.  
  593. #elif defined(__X_MOTIF__)
  594.     Display *dpy = XtDisplay (_client);
  595.     if (opt & UID_Fill) {
  596.         Display *dpy = XtDisplay (_client);
  597.         ColorSaver save (_client, _brush->Color());
  598.         XFillRectangle (dpy, XtWindow (_client), _handle,  r.Left (),
  599.                         r.Top (), r.Width (), r.Height ());
  600.     }
  601.     if (opt & UID_Outline) {
  602.         ColorSaver save (_client, _pen->Color());
  603.         XDrawRectangle (dpy, XtWindow (_client), _handle,
  604.                         r.Left (), r.Top (), r.Width (), r.Height ());
  605.     }
  606. #endif
  607. }
  608.  
  609.  
  610.  
  611. void UI_DisplaySurface::DrawPolyLine (UI_Point parr[], short numpts)
  612. {
  613. #if defined(__MS_WINDOWS__) || defined(__OS2__)
  614.     UI_DrawingSurface::DrawPolyLine (parr, numpts);
  615.  
  616. #elif defined(__X_MOTIF__)
  617.     if (numpts <= 1)
  618.         return;
  619.     Display *dpy = XtDisplay (_client);
  620.     for (long i = 1; i < numpts; i++)
  621.         DrawLine (parr[i-1], parr [i]);
  622. #endif
  623. }
  624.  
  625.  
  626. bool UI_DisplaySurface::DrawLine (const UI_Point& p, const UI_Point& q)
  627. {
  628. #if defined(__MS_WINDOWS__) || defined(__OS2__)
  629.     return UI_DrawingSurface::DrawLine (p, q);
  630. #elif defined(__X_MOTIF__)
  631.     ColorSaver save (_client, _pen->Color());
  632.     Display* dpy = XtDisplay (_TheApplication->Controller().ShellWidget());
  633.     XDrawLine (dpy, XtWindow (_client), Handle (),
  634.                p.XCoord(), p.YCoord(), q.XCoord(), q.YCoord());
  635. #endif
  636. }
  637.  
  638.  
  639.  
  640.  
  641.  
  642. #if defined(__X_MOTIF__)
  643.  
  644. // This is  a table of bytes with their bit reversals. Reverse[i] is the
  645. // value obtained by reading off the bits of i from right to left.
  646.  
  647. static uchar Reverse[] = {
  648. /* 00 */ 0x00, /* 01 */ 0x80, /* 02 */ 0x40, /* 03 */ 0xc0,
  649. /* 04 */ 0x20, /* 05 */ 0xa0, /* 06 */ 0x60, /* 07 */ 0xe0,
  650. /* 08 */ 0x10, /* 09 */ 0x90, /* 0a */ 0x50, /* 0b */ 0xd0,
  651. /* 0c */ 0x30, /* 0d */ 0xb0, /* 0e */ 0x70, /* 0f */ 0xf0,
  652. /* 10 */ 0x08, /* 11 */ 0x88, /* 12 */ 0x48, /* 13 */ 0xc8,
  653. /* 14 */ 0x28, /* 15 */ 0xa8, /* 16 */ 0x68, /* 17 */ 0xe8,
  654. /* 18 */ 0x18, /* 19 */ 0x98, /* 1a */ 0x58, /* 1b */ 0xd8,
  655. /* 1c */ 0x38, /* 1d */ 0xb8, /* 1e */ 0x78, /* 1f */ 0xf8,
  656. /* 20 */ 0x04, /* 21 */ 0x84, /* 22 */ 0x44, /* 23 */ 0xc4,
  657. /* 24 */ 0x24, /* 25 */ 0xa4, /* 26 */ 0x64, /* 27 */ 0xe4,
  658. /* 28 */ 0x14, /* 29 */ 0x94, /* 2a */ 0x54, /* 2b */ 0xd4,
  659. /* 2c */ 0x34, /* 2d */ 0xb4, /* 2e */ 0x74, /* 2f */ 0xf4,
  660. /* 30 */ 0x0c, /* 31 */ 0x8c, /* 32 */ 0x4c, /* 33 */ 0xcc,
  661. /* 34 */ 0x2c, /* 35 */ 0xac, /* 36 */ 0x6c, /* 37 */ 0xec,
  662. /* 38 */ 0x1c, /* 39 */ 0x9c, /* 3a */ 0x5c, /* 3b */ 0xdc,
  663. /* 3c */ 0x3c, /* 3d */ 0xbc, /* 3e */ 0x7c, /* 3f */ 0xfc,
  664. /* 40 */ 0x02, /* 41 */ 0x82, /* 42 */ 0x42, /* 43 */ 0xc2,
  665. /* 44 */ 0x22, /* 45 */ 0xa2, /* 46 */ 0x62, /* 47 */ 0xe2,
  666. /* 48 */ 0x12, /* 49 */ 0x92, /* 4a */ 0x52, /* 4b */ 0xd2,
  667. /* 4c */ 0x32, /* 4d */ 0xb2, /* 4e */ 0x72, /* 4f */ 0xf2,
  668. /* 50 */ 0x0a, /* 51 */ 0x8a, /* 52 */ 0x4a, /* 53 */ 0xca,
  669. /* 54 */ 0x2a, /* 55 */ 0xaa, /* 56 */ 0x6a, /* 57 */ 0xea,
  670. /* 58 */ 0x1a, /* 59 */ 0x9a, /* 5a */ 0x5a, /* 5b */ 0xda,
  671. /* 5c */ 0x3a, /* 5d */ 0xba, /* 5e */ 0x7a, /* 5f */ 0xfa,
  672. /* 60 */ 0x06, /* 61 */ 0x86, /* 62 */ 0x46, /* 63 */ 0xc6,
  673. /* 64 */ 0x26, /* 65 */ 0xa6, /* 66 */ 0x66, /* 67 */ 0xe6,
  674. /* 68 */ 0x16, /* 69 */ 0x96, /* 6a */ 0x56, /* 6b */ 0xd6,
  675. /* 6c */ 0x36, /* 6d */ 0xb6, /* 6e */ 0x76, /* 6f */ 0xf6,
  676. /* 70 */ 0x0e, /* 71 */ 0x8e, /* 72 */ 0x4e, /* 73 */ 0xce,
  677. /* 74 */ 0x2e, /* 75 */ 0xae, /* 76 */ 0x6e, /* 77 */ 0xee,
  678. /* 78 */ 0x1e, /* 79 */ 0x9e, /* 7a */ 0x5e, /* 7b */ 0xde,
  679. /* 7c */ 0x3e, /* 7d */ 0xbe, /* 7e */ 0x7e, /* 7f */ 0xfe,
  680. /* 80 */ 0x01, /* 81 */ 0x81, /* 82 */ 0x41, /* 83 */ 0xc1,
  681. /* 84 */ 0x21, /* 85 */ 0xa1, /* 86 */ 0x61, /* 87 */ 0xe1,
  682. /* 88 */ 0x11, /* 89 */ 0x91, /* 8a */ 0x51, /* 8b */ 0xd1,
  683. /* 8c */ 0x31, /* 8d */ 0xb1, /* 8e */ 0x71, /* 8f */ 0xf1,
  684. /* 90 */ 0x09, /* 91 */ 0x89, /* 92 */ 0x49, /* 93 */ 0xc9,
  685. /* 94 */ 0x29, /* 95 */ 0xa9, /* 96 */ 0x69, /* 97 */ 0xe9,
  686. /* 98 */ 0x19, /* 99 */ 0x99, /* 9a */ 0x59, /* 9b */ 0xd9,
  687. /* 9c */ 0x39, /* 9d */ 0xb9, /* 9e */ 0x79, /* 9f */ 0xf9,
  688. /* a0 */ 0x05, /* a1 */ 0x85, /* a2 */ 0x45, /* a3 */ 0xc5,
  689. /* a4 */ 0x25, /* a5 */ 0xa5, /* a6 */ 0x65, /* a7 */ 0xe5,
  690. /* a8 */ 0x15, /* a9 */ 0x95, /* aa */ 0x55, /* ab */ 0xd5,
  691. /* ac */ 0x35, /* ad */ 0xb5, /* ae */ 0x75, /* af */ 0xf5,
  692. /* b0 */ 0x0d, /* b1 */ 0x8d, /* b2 */ 0x4d, /* b3 */ 0xcd,
  693. /* b4 */ 0x2d, /* b5 */ 0xad, /* b6 */ 0x6d, /* b7 */ 0xed,
  694. /* b8 */ 0x1d, /* b9 */ 0x9d, /* ba */ 0x5d, /* bb */ 0xdd,
  695. /* bc */ 0x3d, /* bd */ 0xbd, /* be */ 0x7d, /* bf */ 0xfd,
  696. /* c0 */ 0x03, /* c1 */ 0x83, /* c2 */ 0x43, /* c3 */ 0xc3,
  697. /* c4 */ 0x23, /* c5 */ 0xa3, /* c6 */ 0x63, /* c7 */ 0xe3,
  698. /* c8 */ 0x13, /* c9 */ 0x93, /* ca */ 0x53, /* cb */ 0xd3,
  699. /* cc */ 0x33, /* cd */ 0xb3, /* ce */ 0x73, /* cf */ 0xf3,
  700. /* d0 */ 0x0b, /* d1 */ 0x8b, /* d2 */ 0x4b, /* d3 */ 0xcb,
  701. /* d4 */ 0x2b, /* d5 */ 0xab, /* d6 */ 0x6b, /* d7 */ 0xeb,
  702. /* d8 */ 0x1b, /* d9 */ 0x9b, /* da */ 0x5b, /* db */ 0xdb,
  703. /* dc */ 0x3b, /* dd */ 0xbb, /* de */ 0x7b, /* df */ 0xfb,
  704. /* e0 */ 0x07, /* e1 */ 0x87, /* e2 */ 0x47, /* e3 */ 0xc7,
  705. /* e4 */ 0x27, /* e5 */ 0xa7, /* e6 */ 0x67, /* e7 */ 0xe7,
  706. /* e8 */ 0x17, /* e9 */ 0x97, /* ea */ 0x57, /* eb */ 0xd7,
  707. /* ec */ 0x37, /* ed */ 0xb7, /* ee */ 0x77, /* ef */ 0xf7,
  708. /* f0 */ 0x0f, /* f1 */ 0x8f, /* f2 */ 0x4f, /* f3 */ 0xcf,
  709. /* f4 */ 0x2f, /* f5 */ 0xaf, /* f6 */ 0x6f, /* f7 */ 0xef,
  710. /* f8 */ 0x1f, /* f9 */ 0x9f, /* fa */ 0x5f, /* fb */ 0xdf,
  711. /* fc */ 0x3f, /* fd */ 0xbf, /* fe */ 0x7f, /* ff */ 0xff
  712. };
  713. #endif
  714.  
  715.  
  716. #if defined(__BORLANDC__) && defined(__OS2__)
  717. #pragma argsused // For the time being, for OS/2
  718. #endif
  719.  
  720. bool UI_DisplaySurface::Invert (const UI_Stencil& dataMask, const UI_Point& p)
  721. {
  722. #if defined(__MS_WINDOWS__)
  723.     HDC hMem  = CreateCompatibleDC (_handle);
  724.     short m = dataMask.Width(), n = dataMask.Height ();
  725.     HBITMAP mapHandle = CreateBitmap (m * 8, n, 1, 1,
  726.                                       dataMask.AsPtr());
  727.     HANDLE hOld = SelectObject (hMem, mapHandle);
  728.     BitBlt (_handle, p.XCoord(), p.YCoord(), m, n, hMem, 0, 0, SRCINVERT);
  729.     SelectObject (hMem, hOld);
  730.     DeleteObject (mapHandle);
  731.     DeleteDC (hMem);
  732. #elif defined(__X_MOTIF__)
  733.     Display *dpy  = XtDisplay (_client);
  734.     Window    win = XtWindow  (_client);
  735.     UI_Stencil data = dataMask;
  736.     short m = data.Width(), n = data.Height ();
  737.     if (BitmapBitOrder (dpy) == LSBFirst) {
  738.         // Reverse the bit order in each byte
  739.         for (short i = 0; i < m; i++)
  740.             for (short j = 0; j < n; j++) {
  741.                 char& c = data.Byte (j, i);
  742.                 c = Reverse [(uchar) c];
  743.             }
  744.     }
  745.     XGCValues values;
  746.     XtGCMask mask = GCForeground | GCBackground | GCFunction
  747.         | GCSubwindowMode | GCFillStyle;
  748.     GC gc = _handle;
  749.     XGCValues oldValues;
  750.     XGetGCValues   (dpy, gc, mask, &oldValues);
  751.  
  752.     Pixmap stipple = XCreateBitmapFromData (dpy, win, data.AsPtr(), m, n);
  753.     if (!stipple)
  754.         return FALSE;
  755.     values.foreground     = 1;
  756.     values.background     = 0;
  757.     values.function       = GXxor;
  758.     values.subwindow_mode = IncludeInferiors;
  759.     values.fill_style     = FillOpaqueStippled;
  760.     XChangeGC      (dpy, gc, mask, &values);
  761.     XSetStipple    (dpy, gc, stipple);
  762.     XSetTSOrigin   (dpy, gc, p.XCoord(), p.YCoord());
  763.     XFillRectangle (dpy, win, gc, p.XCoord(), p.YCoord(), m, n);
  764.     XChangeGC      (dpy, gc, mask, &oldValues);
  765.     XFreePixmap    (dpy, stipple);
  766. #else
  767.     NotImplemented ("Invert");
  768. #endif
  769.     return TRUE;
  770. }
  771.  
  772.  
  773. #if defined(__BORLANDC__)
  774. #pragma argsused // For the time being
  775. #endif
  776.  
  777. bool UI_DisplaySurface::Draw (const UI_Bitmap& map, const UI_Stencil& s,
  778.                               const UI_Point& p)
  779. {
  780. #if defined(__MS_WINDOWS__)
  781. #elif defined(__X_MOTIF__)
  782.     Display* dpy = XtDisplay (_client);
  783.     Window   win = XtWindow  (_client);
  784.     int format = DefaultDepth (dpy, DefaultScreen(dpy)) == 1 ? XYPixmap
  785.         : ZPixmap;
  786.     struct _XImage* r, *q;
  787.     long w = map.Width();
  788.     long h = map.Height();
  789.     r = XGetImage (dpy, win, p.XCoord(), p.YCoord(), w, h, AllPlanes, format);
  790.     q = map.Handle();
  791.     for (long i = 0; i < h; i++) {
  792.         for (long j = 0; j < w; j++)
  793.             if (s.Bit (i, j))
  794.                 XPutPixel (r, i, j, XGetPixel (q, i, j));
  795.     }
  796.     XPutImage (dpy, win, _handle, r, 0, 0, p.XCoord(), p.YCoord(), w, h);
  797. #else
  798.     NotImplemented ("Invert");
  799. #endif
  800.     return TRUE;
  801. }
  802.  
  803.  
  804. bool UI_DisplaySurface::InvertRectangle (const UI_Rectangle& r)
  805. {
  806. #if defined(__MS_WINDOWS__)
  807.     RECT rect =  r.AsMSRect ();
  808.     InvertRect (_handle, &rect);
  809.     return TRUE;
  810. #elif defined(__OS2__)
  811.     long height = DrawingArea ().Height();
  812.     RECTL rect;
  813.     rect.xLeft    = r.Left();
  814.     rect.yBottom  = height - r.Bottom () - 1;
  815.     rect.xRight   = r.Right();
  816.     rect.yTop     = height - 1 - r.Top ();
  817.     return WinInvertRect (_handle, &rect);
  818.         // There must be a Gpi function for this, but I don't know which.
  819. #elif defined(__X_MOTIF__)
  820.     Display *dpy  = XtDisplay (_client);
  821.     Window    win = XtWindow  (_client);
  822.     long width  = r.Width();
  823.     long height = r.Height();
  824.     long left   = r.Left ();
  825.     long right  = r.Right ();
  826.     long top    = r.Top  ();
  827.     long bottom = r.Bottom ();
  828.     
  829.     int  scr    = DefaultScreen(dpy);
  830.  
  831.     // This code is courtesy of Rajesh Chandran, Jan 25, 1995
  832.     XGCValues values;
  833.     XtGCMask mask = GCForeground|GCBackground|GCFunction|GCSubwindowMode;
  834.     GC gc;
  835.  
  836.     Region region;
  837.     XPoint points[5];
  838.  
  839.     points[0].x = left;
  840.     points[0].y = top;
  841.  
  842.     points[1].x = right - 1;
  843.     points[1].y = top;
  844.  
  845.     points[2].x = right - 1;
  846.     points[2].y = bottom;
  847.  
  848.     points[3].x = left;
  849.     points[3].y = bottom;
  850.  
  851.     points[4].x = left;
  852.     points[4].y = top;
  853.  
  854.     region = XPolygonRegion (points, 5, WindingRule);
  855.  
  856.     values.foreground     = 1;
  857.     values.background     = 0;
  858.     values.function       = GXxor;
  859.     values.subwindow_mode = IncludeInferiors;
  860.  
  861.     gc = _handle;
  862.     XGCValues oldValues;
  863.     XGetGCValues   (dpy, gc, mask, &oldValues);
  864.     XChangeGC      (dpy, gc, mask, &values);
  865.     XSetRegion     (dpy, gc, region);
  866.     XDestroyRegion (region);
  867.     XFillRectangle (dpy, win, gc, r.Left(), r.Top(), width, height);
  868.     XChangeGC      (dpy, gc, mask, &oldValues);
  869.     XSetClipMask   (dpy, gc, None);
  870.     
  871. // The following code uses a more elaborate approach of inverting the
  872. // image pixel by pixel. It is much slower, but illustrates the idea, so
  873. // is retained here but commented out.
  874. //     int format  = DefaultDepth (dpy, scr) == 1 ? XYPixmap : ZPixmap;
  875. //     XImage* handle = XGetImage (dpy, win, r.Left(), r.Top(), width, height,
  876. //                                 AllPlanes, format);
  877. //     // Now iterate over the image and complement all its cells
  878. // 
  879. //     CL_IntIntMap tmpColorMap;
  880. //     // This map is used to speed up the loops below, avoiding XQueryColor
  881. //     // and XAllocColor calls if we already know what the pixel values are.
  882. //     for (long i = 0; i < width; i++) {
  883. //         for (long j = 0; j < height; j++) {
  884. //             XColor xcolor;
  885. //             xcolor.pixel = XGetPixel (handle, i, j);
  886. //             long outputPixel = tmpColorMap[xcolor.pixel] - 1;
  887. //             // -----------------------------------------^^^^
  888. //             // We subtract one here, and add 1 below, because we want the
  889. //             // values of the map to be positive and nonzero. Otherwise a
  890. //             // lookup failure (which returns a 0) would be indistinguishable
  891. //             // from a zero pixel value for outputPixel. Of course, we could
  892. //             // use the Map's IncludesKey method, but that would call for two
  893. //             // map lookups instead of one.
  894. //             if (outputPixel < 0) { // Lookup failed
  895. //                 long inputPixel = xcolor.pixel;
  896. //                 XQueryColor (dpy, DefaultColormap (dpy, scr), &xcolor);
  897. //                 xcolor.green = 65535L - xcolor.green;
  898. //                 xcolor.blue  = 65535L - xcolor.blue;
  899. //                 xcolor.red   = 65535L - xcolor.red;
  900. //                 XAllocColor (dpy, DefaultColormap (dpy, scr), &xcolor);
  901. //                 outputPixel = xcolor.pixel;
  902. //                 tmpColorMap.Add (inputPixel, outputPixel + 1);
  903. //                 // --------------------------------------^^^ see above
  904. //                 //                                           comment
  905. //             }
  906. //             XPutPixel (handle, i, j, outputPixel);
  907. //         }
  908. //     }
  909. // 
  910. //     // Finally, output the image
  911. //     XPutImage (dpy, win, _handle, handle, 0, 0, r.Left(), r.Top(),
  912. //                width, height);
  913.  
  914.     return TRUE;
  915.  
  916. #endif
  917.     
  918. }
  919.  
  920.  
  921. #if defined(__X_MOTIF__)
  922. void UI_DisplaySurface::_DrawFontLine (const UI_Point& p1,
  923.                                        const UI_Point& p2)
  924. {
  925.     ColorSaver save (_client, _pen->Color());
  926.     short width = _pen->Thickness ();
  927.     _pen->Thickness (2);
  928.     DrawLine (p1, p2);
  929.     _pen->Thickness (width);
  930. }
  931.  
  932. #endif
  933.  
  934. void UI_DisplaySurface::DrawPoint (const UI_Point& p, const UI_Color& color)
  935. {
  936. #if defined(__MS_WINDOWS__) || defined(__OS2__)
  937.     UI_DrawingSurface::DrawPoint (p, color);
  938. #elif defined(__X_MOTIF__)
  939.     ColorSaver save (_client, color);
  940.     Display* dpy = XtDisplay (_TheApplication->Controller().ShellWidget());
  941.     XDrawPoint (dpy, XtWindow (_client), _handle, p.XCoord(), p.YCoord());
  942. #endif
  943. }
  944.  
  945.  
  946.  
  947.  
  948. void UI_DisplaySurface::WriteString
  949.     (const CL_String& str, const UI_Rectangle& tRect, UI_TextStyle tStyle)
  950. {
  951. #if defined (__MS_WINDOWS__) || defined(__OS2__)
  952.     UI_DrawingSurface::WriteString (str, tRect, tStyle);
  953.  
  954. #elif defined(__X_MOTIF__)
  955.     if (!_font)
  956.         return;
  957.     Display* dpy = XtDisplay (_client);
  958.     XFontStruct* fstr = (XFontStruct*) _font->NativeFontStruct ();
  959.     if (!fstr)
  960.         return; // Failed
  961.     ColorSaver save (_client, _pen->Color());
  962.     short width = _font->TextWidth (str);
  963.     UI_Point p;
  964.     switch (tStyle) {
  965.     case UIText_Center:
  966.         p = tRect.Origin() + UI_Point ((tRect.Width() - width)/2, 0);
  967.         break;
  968.  
  969.     case UIText_Left:
  970.         p = tRect.Origin ();
  971.         break;
  972.  
  973.     case UIText_Right:
  974.         p = tRect.TopRight() - UI_Point (width, 0);
  975.         break;
  976.     };
  977.     
  978.     XDrawString (dpy, XtWindow (_client), _handle, p.XCoord (),
  979.                  p.YCoord () + fstr->ascent,
  980.                  (const char*) str, str.Length ());
  981.     if (_font->Underline ()) {
  982.         // XGetFontProperty (fstr, XA_UNDERLINE_POSITION, &val); :-(
  983.         // Since the XA_UNDERLINE_POSITION property is not reliable, we
  984.         // resort to ad-hoc measures.
  985.         UI_Point leftEnd  = p + UI_Point (0, fstr->ascent + fstr->descent);
  986.         UI_Point rightEnd = leftEnd + UI_Point (width, 0);
  987.         _DrawFontLine (leftEnd, rightEnd);
  988.     }
  989.     if (_font->StrikeOut ()) {
  990.         int direction, ascent, descent;
  991.         XCharStruct cstr;
  992.         XTextExtents (fstr, "g", 1, &direction, &ascent, &descent, &cstr);
  993. //         XGetFontProperty (fstr, XA_STRIKEOUT_ASCENT,  &ascent);
  994. //         XGetFontProperty (fstr, XA_STRIKEOUT_DESCENT, &descent);
  995.         UI_Point leftEnd = p + UI_Point (0, fstr->ascent -  cstr.ascent/2);
  996.         UI_Point rightEnd = leftEnd + UI_Point (width, 0);
  997.         _DrawFontLine (leftEnd, rightEnd);
  998.     }
  999. #endif
  1000. }
  1001.  
  1002.  
  1003.  
  1004. short UI_DisplaySurface::TextWidth (const char* s) const
  1005. {
  1006.  
  1007. #if defined(__MS_WINDOWS__) || defined(__OS2__)
  1008.     return UI_DrawingSurface::TextWidth (s);
  1009.  
  1010. #elif defined (__X_MOTIF__)
  1011.     return _font ? _font->TextWidth (s) : 0;
  1012. #endif
  1013. }
  1014.  
  1015.  
  1016. UI_Font& UI_DisplaySurface::Font ()
  1017. {
  1018.     return _client.Font();
  1019. }
  1020.  
  1021.  
  1022. UI_VisualObject& UI_DisplaySurface::Client () const
  1023. {
  1024.     return _client;
  1025. }
  1026.  
  1027.  
  1028.