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