1 #include <stdlib.h>
2 #include <string.h>
3 #include "xglk.h"
4 #include "xg_internal.h"
5 #include "xg_win_graphics.h"
6 
7 struct window_graphics_struct {
8   window_t *owner;
9   XRectangle bbox;
10 
11   XRectangle winbox;
12   XPoint dirtyul, dirtylr;
13 
14   XColor background;
15   GC gcfill;
16 
17   Pixmap world;
18 
19   int drag_mouseevent;
20   XPoint drag_pt;
21 };
22 
win_graphics_create(window_t * win)23 window_graphics_t *win_graphics_create(window_t *win)
24 {
25   XRectangle box;
26   XGCValues gcvalues;
27   int jx;
28   window_graphics_t *res =
29     (window_graphics_t *)malloc(sizeof(window_graphics_t));
30   if (!res)
31     return NULL;
32 
33   res->owner = win;
34 
35   res->winbox.x = 0;
36   res->winbox.y = 0;
37   res->winbox.width = 0;
38   res->winbox.height = 0;
39 
40   res->dirtyul.x = 0;
41   res->dirtyul.y = 0;
42   res->dirtylr.x = 0;
43   res->dirtylr.y = 0;
44 
45   res->world = 0;
46 
47   UnpackRGBColor(&res->background, 0xFFFFFF);
48   XAllocColor(xiodpy, xiomap, &res->background);
49 
50   gcvalues.function = GXcopy;
51   gcvalues.foreground = res->background.pixel;
52   gcvalues.background = res->background.pixel;
53   res->gcfill = XCreateGC(xiodpy, xiowin,
54     GCForeground|GCBackground, &gcvalues);
55 
56   return res;
57 }
58 
win_graphics_destroy(window_graphics_t * dwin)59 void win_graphics_destroy(window_graphics_t *dwin)
60 {
61   dwin->owner = NULL;
62 
63   if (dwin->world) {
64     XFreePixmap(xiodpy, dwin->world);
65     dwin->world = 0;
66   }
67   if (dwin->gcfill) {
68     XFreeGC(xiodpy, dwin->gcfill);
69     dwin->gcfill = 0;
70   }
71 
72   free(dwin);
73 }
74 
win_graphics_rearrange(window_t * win,XRectangle * box)75 void win_graphics_rearrange(window_t *win, XRectangle *box)
76 {
77   window_graphics_t *dwin = win->data;
78   Pixmap newpixmap = 0;
79   int bothwid, bothhgt;
80 
81   if (box->width <= 0 || box->height <= 0) {
82     if (dwin->world) {
83       XFreePixmap(xiodpy, dwin->world);
84       dwin->world = 0;
85     }
86     dwin->winbox = (*box);
87     return;
88   }
89 
90   bothwid = dwin->winbox.width;
91   if (box->width < bothwid)
92     bothwid = box->width;
93   bothhgt = dwin->winbox.height;
94   if (box->height < bothhgt)
95     bothhgt = box->height;
96 
97   newpixmap = XCreatePixmap(xiodpy, xiowin, box->width, box->height,
98     xiodepth);
99 
100   if (dwin->world && bothwid && bothhgt) {
101     XCopyArea(xiodpy, dwin->world, newpixmap, gcfore,
102       0, 0, bothwid, bothhgt, 0, 0);
103   }
104 
105   if (dwin->world) {
106     XFreePixmap(xiodpy, dwin->world);
107     dwin->world = 0;
108   }
109 
110   dwin->world = newpixmap;
111 
112   if (box->width > dwin->winbox.width) {
113     win_graphics_erase_rect(dwin, FALSE, dwin->winbox.width, 0,
114       box->width-dwin->winbox.width, box->height);
115   }
116   if (box->height > dwin->winbox.height) {
117     win_graphics_erase_rect(dwin, FALSE, 0, dwin->winbox.height,
118       box->width, box->height-dwin->winbox.height);
119   }
120 
121   dwin->winbox = (*box);
122   dwin->winbox.x = 0;
123   dwin->winbox.y = 0;
124   dwin->bbox = (*box);
125   dwin->dirtyul.x = 0;
126   dwin->dirtyul.y = 0;
127   dwin->dirtylr.x = box->width;
128   dwin->dirtylr.y = box->height;
129 }
130 
win_graphics_get_rect(window_t * win)131 XRectangle *win_graphics_get_rect(window_t *win)
132 {
133   window_graphics_t *dwin = win->data;
134   return &dwin->bbox;
135 }
136 
win_graphics_figure_size(window_t * win,long size,int vertical)137 long win_graphics_figure_size(window_t *win, long size, int vertical)
138 {
139   window_graphics_t *dwin = win->data;
140 
141   if (vertical) {
142     return size;
143   }
144   else {
145     return size;
146   }
147 }
148 
win_graphics_get_size(window_t * win,glui32 * width,glui32 * height)149 void win_graphics_get_size(window_t *win, glui32 *width, glui32 *height)
150 {
151   window_graphics_t *dwin = win->data;
152   *width = dwin->winbox.width;
153   *height = dwin->winbox.height;
154 }
155 
win_graphics_redraw(window_t * win)156 void win_graphics_redraw(window_t *win)
157 {
158   window_graphics_t *dwin = win->data;
159 
160   dwin->dirtyul.x = dwin->winbox.width;
161   dwin->dirtyul.y = dwin->winbox.height;
162   dwin->dirtylr.x = 0;
163   dwin->dirtylr.y = 0;
164 
165   gli_draw_window_outline(&dwin->bbox);
166 
167   if (!dwin->world) {
168     win_graphics_erase_rect(dwin, TRUE, 0, 0, 0, 0);
169     if (!eventloop_isevent())
170       eventloop_setevent(evtype_Redraw, NULL, 0, 0);
171     return;
172   }
173 
174   XCopyArea(xiodpy, dwin->world, xiowin, gcfore,
175     0, 0, dwin->winbox.width, dwin->winbox.height,
176     dwin->bbox.x, dwin->bbox.y);
177 }
178 
win_graphics_flush(window_t * win)179 void win_graphics_flush(window_t *win)
180 {
181   window_graphics_t *dwin = win->data;
182   XPoint boxul, boxlr;
183   int width, height;
184 
185   boxul = dwin->dirtyul;
186   boxlr = dwin->dirtylr;
187 
188   dwin->dirtyul.x = dwin->winbox.width;
189   dwin->dirtyul.y = dwin->winbox.height;
190   dwin->dirtylr.x = 0;
191   dwin->dirtylr.y = 0;
192 
193   if (boxul.x < 0)
194     boxul.x = 0;
195   if (boxul.y < 0)
196     boxul.y = 0;
197   if (boxlr.x >= dwin->winbox.width)
198     boxlr.x = dwin->winbox.width;
199   if (boxlr.y >= dwin->winbox.height)
200     boxlr.y = dwin->winbox.height;
201 
202   if (boxul.x >= boxlr.x || boxul.y >= boxlr.y) {
203     return;
204   }
205 
206   width = boxlr.x - boxul.x;
207   height = boxlr.y - boxul.y;
208 
209   if (!dwin->world) {
210     return;
211   }
212 
213   XCopyArea(xiodpy, dwin->world, xiowin, gcfore,
214     boxul.x, boxul.y, width, height,
215     dwin->bbox.x+boxul.x, dwin->bbox.y+boxul.y);
216 }
217 
win_graphics_perform_click(window_t * win,int dir,XPoint * pt,int butnum,int clicknum,unsigned int state)218 void win_graphics_perform_click(window_t *win, int dir, XPoint *pt,
219   int butnum, int clicknum, unsigned int state)
220 {
221   window_graphics_t *dwin = win->data;
222   long pos;
223   long px, px2;
224 
225   if (dir == mouse_Down) {
226     dwin->drag_mouseevent = FALSE;
227     if (dwin->owner->mouse_request) {
228       dwin->drag_mouseevent = TRUE;
229       dwin->drag_pt.x = pt->x - dwin->bbox.x;
230       dwin->drag_pt.y = pt->y - dwin->bbox.y;
231     }
232   }
233   else if (dir == mouse_Up) {
234     if (dwin->drag_mouseevent) {
235       dwin->owner->mouse_request = FALSE;
236       eventloop_setevent(evtype_MouseInput, dwin->owner,
237 	dwin->drag_pt.x, dwin->drag_pt.y);
238     }
239   }
240 }
241 
dirty_rect(XPoint * ul,XPoint * lr,int x,int y,int width,int height)242 static void dirty_rect(XPoint *ul, XPoint *lr,
243   int x, int y, int width, int height)
244 {
245   if (ul->x > x)
246     ul->x = x;
247   if (ul->y > y)
248     ul->y = y;
249   if (lr->x < x+width)
250     lr->x = x+width;
251   if (lr->y < y+height)
252     lr->y = y+height;
253 }
254 
win_graphics_draw_picture(window_graphics_t * dwin,glui32 image,glsi32 xpos,glsi32 ypos,int scale,glui32 imagewidth,glui32 imageheight)255 glui32 win_graphics_draw_picture(window_graphics_t *dwin, glui32 image,
256   glsi32 xpos, glsi32 ypos,
257   int scale, glui32 imagewidth, glui32 imageheight)
258 {
259   picture_t *pic = picture_find(image);
260 
261   if (!pic) {
262     return FALSE;
263   }
264 
265   if (!scale) {
266     imagewidth = pic->width;
267     imageheight = pic->height;
268   }
269 
270   if (dwin->world) {
271     picture_draw(pic, dwin->world, xpos, ypos, imagewidth, imageheight, NULL);
272     dirty_rect(&dwin->dirtyul, &dwin->dirtylr,
273       xpos, ypos, imagewidth, imageheight);
274   }
275   else {
276     picture_draw(pic, xiowin, dwin->bbox.x+xpos, dwin->bbox.y+ypos,
277       imagewidth, imageheight, NULL);
278   }
279 
280   picture_release(pic);
281   return TRUE;
282 }
283 
win_graphics_erase_rect(window_graphics_t * dwin,int whole,glsi32 left,glsi32 top,glui32 width,glui32 height)284 void win_graphics_erase_rect(window_graphics_t *dwin, int whole,
285   glsi32 left, glsi32 top, glui32 width, glui32 height)
286 {
287   XGCValues gcvalues;
288 
289   if (whole) {
290     left = 0;
291     top = 0;
292     width = dwin->winbox.width;
293     height = dwin->winbox.height;
294   }
295 
296   if (width == 0 || height == 0)
297     return;
298 
299   gcvalues.foreground = dwin->background.pixel;
300   XChangeGC(xiodpy, dwin->gcfill, GCForeground, &gcvalues);
301 
302   if (!dwin->world) {
303     XFillRectangle(xiodpy, xiowin, dwin->gcfill,
304       dwin->bbox.x+left, dwin->bbox.y+top, width, height);
305     return;
306   }
307 
308   dirty_rect(&dwin->dirtyul, &dwin->dirtylr,
309     left, top, (glsi32)width, (glsi32)height);
310 
311   XFillRectangle(xiodpy, dwin->world, dwin->gcfill,
312     left, top, width, height);
313 }
314 
win_graphics_fill_rect(window_graphics_t * dwin,glui32 color,glsi32 left,glsi32 top,glui32 width,glui32 height)315 void win_graphics_fill_rect(window_graphics_t *dwin, glui32 color,
316   glsi32 left, glsi32 top, glui32 width, glui32 height)
317 {
318   XGCValues gcvalues;
319   XColor col;
320 
321   if (width == 0 || height == 0)
322     return;
323 
324   UnpackRGBColor(&col, color);
325   XAllocColor(xiodpy, xiomap, &col);
326 
327   gcvalues.foreground = col.pixel;
328   XChangeGC(xiodpy, dwin->gcfill, GCForeground, &gcvalues);
329 
330   if (!dwin->world) {
331     XFillRectangle(xiodpy, xiowin, dwin->gcfill,
332       dwin->bbox.x+left, dwin->bbox.y+top, width, height);
333     return;
334   }
335 
336   dirty_rect(&dwin->dirtyul, &dwin->dirtylr,
337     left, top, (glsi32)width, (glsi32)height);
338 
339   XFillRectangle(xiodpy, dwin->world, dwin->gcfill,
340     left, top, width, height);
341 }
342 
win_graphics_set_background_color(window_graphics_t * dwin,glui32 color)343 void win_graphics_set_background_color(window_graphics_t *dwin,
344   glui32 color)
345 {
346   UnpackRGBColor(&dwin->background, color);
347   XAllocColor(xiodpy, xiomap, &dwin->background);
348 }
349 
350 
351