1 /*
2    Copyright (C) 1996 Scott W. Sadler
3    All rights reserved.
4 */
5 
6 /*
7    XsOutline.C
8 
9    History
10       03-Mar-96 1.0; Scott W. Sadler (ssadler@cisco.com)
11                      Created
12 */
13 
14 // Includes
15 
16 #include <assert.h>
17 #include <X11/StringDefs.h>
18 #include "XsOutline.h"
19 
20 // Constructor
21 
XsOutline(Widget w)22 XsOutline::XsOutline (Widget w)
23 {
24    assert (w != 0);
25 
26 // Initialize
27 
28    _w = w;
29 
30 // Get window dimensions
31 
32    unsigned int moreJunk;
33    unsigned int uw, uh;
34    Window   junk;
35 
36    XGetGeometry (XtDisplay (_w), XtWindow (_w), &junk, &_x, &_y, &uw, &uh, &moreJunk, &moreJunk);
37 
38    _width = uw;
39    _height = uh;
40 
41 // Get initial settings
42 
43    _savedX = _x;
44    _savedY = _y;
45    _savedH = _savedW = 0;
46 
47 // Create the graphics context
48 
49    XGCValues   values;
50    unsigned long valuemask;
51 
52    Display *dpy = XtDisplay (_w);
53 
54    valuemask = GCFunction | GCLineWidth | GCSubwindowMode;
55    values.function = GXinvert;
56    values.line_width = 0;
57    values.subwindow_mode = IncludeInferiors;
58 
59    _gc = XCreateGC (dpy, XtWindow (_w), valuemask, &values);
60 }
61 
62 // Destructor
63 
~XsOutline()64 XsOutline::~XsOutline ( )
65 {
66    XFreeGC (XtDisplay (_w), _gc);
67 }
68 
69 // go
70 
go(Boolean drawInitial)71 Boolean XsOutline::go (Boolean drawInitial)
72 {
73    XtAppContext appContext = XtWidgetToApplicationContext (_w);
74    XEvent event;
75    int   done = 0;
76 
77 // Grab the pointer
78 
79    if (_grabPointer ( ) == False)
80       return (False);
81 
82 // Draw the initial box (if requested)
83 
84    if (drawInitial)
85       _drawOutline (False);
86 
87 // Process the events locally
88 
89    while (!done)
90    {
91       XtAppNextEvent (appContext, &event);
92 
93       switch (event.type)
94       {
95          case ButtonRelease:
96          {
97 
98 // Clear the outline and break
99 
100             _drawOutline (True);
101             done = 1;
102             break;
103          }
104          case MotionNotify:
105          {
106             XEvent next;
107 
108 // Process only the last motion event
109 
110             while (XPending (XtDisplay (_w)) > 0)
111             {
112                XPeekEvent (XtDisplay (_w), &next);
113                if (next.type != MotionNotify)
114                   break;
115                XtAppNextEvent (appContext, &event);
116             }
117 
118 // Send this event
119 
120             _motionHandler (&event);
121 
122             break;
123          }
124          default:
125          {
126             XtDispatchEvent (&event);
127             break;
128          }
129       }
130    }
131 
132 // Ungrab the pointer
133 
134    _ungrabPointer ( );
135 
136    return (True);
137 }
138 
139 // _drawOutline
140 
_drawOutline(Boolean clear)141 void XsOutline::_drawOutline (Boolean clear)
142 {
143 
144 // Clear the current outline
145 
146    if (_savedH || _savedW)
147       _drawIt (_savedX, _savedY, _savedW, _savedH);
148 
149 // Save current values
150 
151    _savedX = _x; _savedY = _y;
152    _savedW = _width; _savedH = _height;
153 
154 // Draw the new outline (unless flagged to just clear)
155 
156    if (!clear)
157       _drawIt (_x, _y, _width, _height);
158 }
159 
160 // _getCursor
161 
_getCursor()162 Cursor XsOutline::_getCursor ( ) const
163 {
164    return (None);
165 }
166 
167 // _grabPointer
168 
_grabPointer()169 Boolean XsOutline::_grabPointer ( )
170 {
171 
172 // Sync everything up before being grabby
173 
174    XSync (XtDisplay (_w), False);
175 
176 // Grab the pointer
177 
178    if (XGrabPointer (XtDisplay (_w), XtWindow (_w), False, GrabEventMask,
179       GrabModeAsync, GrabModeAsync, XtWindow (XtParent (_w)), _getCursor ( ),
180       CurrentTime) != GrabSuccess)
181    {
182       XBell (XtDisplay (_w), 100);
183       return (False);
184    }
185 
186    return (True);
187 }
188 
189 // _ungrabPointer
190 
_ungrabPointer()191 void XsOutline::_ungrabPointer ( )
192 {
193 
194 // Ungrab the pointer
195 
196    XUngrabPointer (XtDisplay (_w), CurrentTime);
197 }
198 
199 // _drawIt
200 
_drawIt(int x,int y,int w,int h)201 void XsOutline::_drawIt (int x, int y, int w, int h)
202 {
203    const int nsegs = 8;
204    XSegment    segs[nsegs];
205 
206 // Across the top
207 
208    segs[0].x1 = x; segs[0].y1 = y;
209    segs[0].x2 = x + w - 1; segs[0].y2 = y;
210 
211    segs[1].x1 = x + BorderSize; segs[1].y1 = y + BorderSize;
212    segs[1].x2 = x + w - BorderSize - 1; segs[1].y2 = y + BorderSize;
213 
214 // Down the left
215 
216    segs[2].x1 = x + w - 1; segs[2].y1 = y + 1;
217    segs[2].x2 = x + w - 1; segs[2].y2 = y + h - 1;
218 
219    segs[3].x1 = x + w - BorderSize - 1; segs[3].y1 = y + BorderSize + 1;
220    segs[3].x2 = x + w - BorderSize - 1; segs[3].y2 = y + h - BorderSize - 1;
221 
222 // Across the bottom
223 
224    segs[4].x1 = x + 1; segs[4].y1 = y + h - 1;
225    segs[4].x2 = x + w - 2; segs[4].y2 = y + h - 1;
226 
227    segs[5].x1 = x + BorderSize + 1; segs[5].y1 = y + h - BorderSize - 1;
228    segs[5].x2 = x + w - BorderSize - 2; segs[5].y2 = y + h - BorderSize - 1;
229 
230 // Up the left
231 
232    segs[6].x1 = x; segs[6].y1 = y + h - 1;
233    segs[6].x2 = x; segs[6].y2 = y + 1;
234 
235    segs[7].x1 = x + BorderSize; segs[7].y1 = y + h - BorderSize - 1;
236    segs[7].x2 = x + BorderSize; segs[7].y2 = y + BorderSize + 1;
237 
238 // Draw the segments
239 
240    XDrawSegments (XtDisplay (_w), XtWindow (XtParent (_w)), _gc, segs, nsegs);
241 }
242