Line data Source code
1 : /* Copyright (C) 2000-2012 by George Williams */
2 : /*
3 : * Redistribution and use in source and binary forms, with or without
4 : * modification, are permitted provided that the following conditions are met:
5 :
6 : * Redistributions of source code must retain the above copyright notice, this
7 : * list of conditions and the following disclaimer.
8 :
9 : * Redistributions in binary form must reproduce the above copyright notice,
10 : * this list of conditions and the following disclaimer in the documentation
11 : * and/or other materials provided with the distribution.
12 :
13 : * The name of the author may not be used to endorse or promote products
14 : * derived from this software without specific prior written permission.
15 :
16 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 : * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 : * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 : * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 : * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 : * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 : * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 : * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : */
27 : #include <basics.h>
28 : #include <stdlib.h>
29 : #include "utype.h"
30 : #include "gdraw.h"
31 : #include "ggadgetP.h"
32 : #include "gresource.h"
33 : #include "gwidget.h"
34 : #include "gkeysym.h"
35 : #include "ustring.h"
36 :
37 : GBox _ggadget_Default_Box = { bt_raised, bs_rect, 2, 2, 0, 0,
38 : COLOR_CREATE(0xd8,0xd8,0xd8), /* border left */ /* brightest */
39 : COLOR_CREATE(0xd0,0xd0,0xd0), /* border top */
40 : COLOR_CREATE(0x80,0x80,0x80), /* border right */
41 : COLOR_CREATE(0x66,0x66,0x66), /* border bottom */ /* darkest */
42 : COLOR_DEFAULT, /* normal background */
43 : COLOR_DEFAULT, /* normal foreground */
44 : COLOR_CREATE(0xd8,0xd8,0xd8), /* disabled background */
45 : COLOR_CREATE(0x66,0x66,0x66), /* disabled foreground */
46 : COLOR_CREATE(0xff,0xff,0x00), /* active border */
47 : COLOR_CREATE(0xa0,0xa0,0xa0), /* pressed background */
48 : COLOR_CREATE(0x00,0x00,0x00), /* gradient bg end */
49 : COLOR_CREATE(0x00,0x00,0x00), /* border inner */
50 : COLOR_CREATE(0x00,0x00,0x00), /* border outer */
51 : };
52 : GBox _GListMark_Box = GBOX_EMPTY; /* Don't initialize here */
53 : FontInstance *_ggadget_default_font = NULL;
54 : static FontInstance *popup_font = NULL;
55 : int _GListMarkSize = 12;
56 : GResImage *_GListMark_Image = NULL, *_GListMark_DisImage;
57 : static int _GGadget_FirstLine = 6;
58 : static int _GGadget_LeftMargin = 6;
59 : static int _GGadget_LineSkip = 3;
60 : int _GGadget_Skip = 6;
61 : int _GGadget_TextImageSkip = 4;
62 : char *_GGadget_ImagePath = NULL;
63 : static int _ggadget_inited=0;
64 : static Color popup_foreground=0, popup_background=COLOR_CREATE(0xff,0xff,0xc0);
65 : static int popup_delay=1000, popup_lifetime=20000;
66 :
67 : static GResInfo popup_ri;
68 : static struct resed ggadget_re[] = {
69 : {N_("Text Image Skip"), "TextImageSkip", rt_int, &_GGadget_TextImageSkip, N_("Space (in points) left between images and text in labels, buttons, menu items, etc. which have both"), NULL, { 0 }, 0, 0 },
70 : {N_("Image Path"), "ImagePath", rt_stringlong, &_GGadget_ImagePath, N_("List of directories to search for images, separated by colons"), NULL, { 0 }, 0, 0 },
71 : RESED_EMPTY
72 : };
73 : GResInfo ggadget_ri = {
74 : &listmark_ri, NULL,NULL, NULL,
75 : &_ggadget_Default_Box,
76 : &_ggadget_default_font,
77 : NULL,
78 : ggadget_re,
79 : N_("GGadget"),
80 : N_("This is an \"abstract\" gadget. It will never appear on the screen\nbut it is the root of gadget tree from which all others inherit"),
81 : "GGadget",
82 : "Gdraw",
83 : false,
84 : 0,
85 : NULL,
86 : GBOX_EMPTY,
87 : NULL,
88 : NULL,
89 : NULL
90 : };
91 : static struct resed popup_re[] = {
92 : {N_("Color|Foreground"), "Foreground", rt_color, &popup_foreground, N_("Text color for popup windows"), NULL, { 0 }, 0, 0 },
93 : {N_("Color|Background"), "Background", rt_color, &popup_background, N_("Background color for popup windows"), NULL, { 0 }, 0, 0 },
94 : {N_("Delay"), "Delay", rt_int, &popup_delay, N_("Delay (in milliseconds) before popup windows appear"), NULL, { 0 }, 0, 0 },
95 : {N_("Life Time"), "LifeTime", rt_int, &popup_lifetime, N_("Time (in milliseconds) that popup windows remain visible"), NULL, { 0 }, 0, 0 },
96 : RESED_EMPTY
97 : };
98 : static void popup_refresh(void);
99 : static GResInfo popup_ri = {
100 : &ggadget_ri, NULL, NULL,NULL,
101 : NULL, /* No box */
102 : &popup_font,
103 : NULL,
104 : popup_re,
105 : N_("Popup"),
106 : N_("Popup windows"),
107 : "GGadget.Popup",
108 : "Gdraw",
109 : false,
110 : omf_refresh,
111 : NULL,
112 : GBOX_EMPTY,
113 : popup_refresh,
114 : NULL,
115 : NULL
116 : };
117 : static struct resed listmark_re[] = {
118 : { N_("Image"), "Image", rt_image, &_GListMark_Image, N_("Image used for enabled listmarks (overrides the box)"), NULL, { 0 }, 0, 0 },
119 : { N_("Disabled Image"), "DisabledImage", rt_image, &_GListMark_DisImage, N_("Image used for disabled listmarks (overrides the box)"), NULL, { 0 }, 0, 0 },
120 : { N_("Width"), "Width", rt_int, &_GListMarkSize, N_("Size of the list mark"), NULL, { 0 }, 0, 0 },
121 : RESED_EMPTY
122 : };
123 : static GTextInfo list_choices[] = {
124 : { (unichar_t *) "1", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
125 : { (unichar_t *) "2", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
126 : { (unichar_t *) "3", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
127 : GTEXTINFO_EMPTY
128 : };
129 : static GGadgetCreateData droplist_gcd[] = {
130 : { GListFieldCreate, { {0, 0, 80, 0 }, NULL, 0, 0, 0, 0, 0, &list_choices[0], { list_choices }, gg_visible, NULL, NULL }, NULL, NULL },
131 : { GListFieldCreate, { {0, 0, 80, 0 }, NULL, 0, 0, 0, 0, 0, &list_choices[1], { list_choices }, gg_visible|gg_enabled, NULL, NULL }, NULL, NULL }
132 : };
133 : static GGadgetCreateData *dlarray[] = { GCD_Glue, &droplist_gcd[0], GCD_Glue, &droplist_gcd[1], GCD_Glue, NULL, NULL };
134 : static GGadgetCreateData droplistbox =
135 : { GHVGroupCreate, { { 2, 2, 0, 0 }, NULL, 0, 0, 0, 0, 0, NULL, { (GTextInfo *) dlarray }, gg_visible|gg_enabled, NULL, NULL }, NULL, NULL };
136 : GResInfo listmark_ri = {
137 : NULL, &ggadget_ri, NULL,NULL,
138 : &_GListMark_Box, /* No box */
139 : NULL,
140 : &droplistbox,
141 : listmark_re,
142 : N_("List Mark"),
143 : N_("This is the mark that differentiates ComboBoxes and ListButtons\n"
144 : "from TextFields and normal Buttons." ),
145 : "GListMark",
146 : "Gdraw",
147 : false,
148 : omf_border_width|omf_padding,
149 : NULL,
150 : GBOX_EMPTY,
151 : NULL,
152 : NULL,
153 : NULL
154 : };
155 :
156 :
157 : static GWindow popup;
158 : static GTimer *popup_timer, *popup_vanish_timer;
159 : static int popup_visible = false;
160 : static GRect popup_within;
161 :
162 0 : static int match(char **list, char *val) {
163 : int i;
164 :
165 0 : for ( i=0; list[i]!=NULL; ++i )
166 0 : if ( strmatch(val,list[i])==0 )
167 0 : return( i );
168 :
169 0 : return( -1 );
170 : }
171 :
172 0 : static void *border_type_cvt(char *val, void *def) {
173 : static char *types[] = { "none", "box", "raised", "lowered", "engraved",
174 : "embossed", "double", NULL };
175 0 : int ret = match(types,val);
176 0 : if ( ret== -1 )
177 0 : return( def );
178 0 : return( (void *) (intpt) ret );
179 : }
180 :
181 0 : static void *border_shape_cvt(char *val, void *def) {
182 : static char *shapes[] = { "rect", "roundrect", "elipse", "diamond", NULL };
183 0 : int ret = match(shapes,val);
184 0 : if ( ret== -1 )
185 0 : return( def );
186 0 : return( (void *) (intpt) ret );
187 : }
188 :
189 : /* font name may be something like:
190 : bold italic extended 12pt courier
191 : 400 10pt small-caps
192 : family name comes at the end, size must have "pt" after it
193 : */
194 0 : void *GResource_font_cvt(char *val, void *def) {
195 : static char *styles[] = { "normal", "italic", "oblique", "small-caps",
196 : "bold", "light", "extended", "condensed", NULL };
197 : FontRequest rq;
198 : FontInstance *fi;
199 : char *pt, *end, ch;
200 : int ret;
201 0 : char *freeme=NULL;
202 :
203 0 : memset(&rq,0,sizeof(rq));
204 0 : rq.utf8_family_name = SANS_UI_FAMILIES;
205 0 : rq.point_size = 10;
206 0 : rq.weight = 400;
207 0 : rq.style = 0;
208 0 : if ( def!=NULL )
209 0 : GDrawDecomposeFont((FontInstance *)def, &rq);
210 0 : else if ( _ggadget_default_font!=NULL )
211 0 : GDrawDecomposeFont(_ggadget_default_font, &rq);
212 :
213 0 : for ( pt=val; *pt && *pt!='"'; ) {
214 0 : for ( end=pt; *end!=' ' && *end!='\0'; ++end );
215 0 : ch = *end; *end = '\0';
216 0 : ret = match(styles,pt);
217 0 : if ( ret==-1 && isdigit(*pt)) {
218 : char *e;
219 0 : ret = strtol(pt,&e,10);
220 0 : if ( strmatch(e,"pt")==0 )
221 0 : rq.point_size = ret;
222 0 : else if ( *e=='\0' )
223 0 : rq.weight = ret;
224 : else {
225 0 : *end = ch;
226 0 : break;
227 : }
228 0 : } else if ( ret==-1 ) {
229 0 : *end = ch;
230 0 : break;
231 0 : } else if ( ret==0 )
232 : /* Do Nothing */;
233 0 : else if ( ret==1 || ret==2 )
234 0 : rq.style |= fs_italic;
235 0 : else if ( ret==3 )
236 0 : rq.style |= fs_smallcaps;
237 0 : else if ( ret==4 )
238 0 : rq.weight = 700;
239 0 : else if ( ret==5 )
240 0 : rq.weight = 300;
241 0 : else if ( ret==6 )
242 0 : rq.style |= fs_extended;
243 : else
244 0 : rq.style |= fs_condensed;
245 0 : *end = ch;
246 0 : pt = end;
247 0 : while ( *pt==' ' ) ++pt;
248 : }
249 :
250 0 : if ( *pt!='\0' )
251 0 : rq.utf8_family_name = freeme = copy(pt);
252 :
253 0 : fi = GDrawInstanciateFont(NULL,&rq);
254 :
255 0 : free(freeme);
256 :
257 0 : if ( fi==NULL )
258 0 : return( def );
259 0 : return( (void *) fi );
260 : }
261 :
262 0 : FontInstance *GResourceFindFont(char *resourcename,FontInstance *deffont) {
263 0 : char *val = GResourceFindString(resourcename);
264 0 : if ( val==NULL )
265 0 : return( deffont );
266 :
267 0 : return( GResource_font_cvt(val,deffont));
268 : }
269 :
270 0 : void _GGadgetCopyDefaultBox(GBox *box) {
271 0 : *box = _ggadget_Default_Box;
272 0 : }
273 :
274 0 : FontInstance *_GGadgetInitDefaultBox(char *class,GBox *box, FontInstance *deffont) {
275 0 : GResStruct bordertype[] = {
276 : { "Box.BorderType", rt_string, NULL, border_type_cvt, 0 },
277 : GRESSTRUCT_EMPTY
278 : };
279 0 : GResStruct boxtypes[] = {
280 : { "Box.BorderType", rt_string, NULL, border_type_cvt, 0 },
281 : { "Box.BorderShape", rt_string, NULL, border_shape_cvt, 0 },
282 : { "Box.BorderWidth", rt_int, NULL, NULL, 0 },
283 : { "Box.Padding", rt_int, NULL, NULL, 0 },
284 : { "Box.Radius", rt_int, NULL, NULL, 0 },
285 : { "Box.BorderInner", rt_bool, NULL, NULL, 0 },
286 : { "Box.BorderOuter", rt_bool, NULL, NULL, 0 },
287 : { "Box.ActiveInner", rt_bool, NULL, NULL, 0 },
288 : { "Box.DoDepressedBackground", rt_bool, NULL, NULL, 0 },
289 : { "Box.DrawDefault", rt_bool, NULL, NULL, 0 },
290 : { "Box.BorderBrightest", rt_color, NULL, NULL, 0 },
291 : { "Box.BorderBrighter", rt_color, NULL, NULL, 0 },
292 : { "Box.BorderDarkest", rt_color, NULL, NULL, 0 },
293 : { "Box.BorderDarker", rt_color, NULL, NULL, 0 },
294 : { "Box.NormalBackground", rt_color, NULL, NULL, 0 },
295 : { "Box.NormalForeground", rt_color, NULL, NULL, 0 },
296 : { "Box.DisabledBackground", rt_color, NULL, NULL, 0 },
297 : { "Box.DisabledForeground", rt_color, NULL, NULL, 0 },
298 : { "Box.ActiveBorder", rt_color, NULL, NULL, 0 },
299 : { "Box.PressedBackground", rt_color, NULL, NULL, 0 },
300 : { "Box.BorderLeft", rt_color, NULL, NULL, 0 },
301 : { "Box.BorderTop", rt_color, NULL, NULL, 0 },
302 : { "Box.BorderRight", rt_color, NULL, NULL, 0 },
303 : { "Box.BorderBottom", rt_color, NULL, NULL, 0 },
304 : { "Font", rt_string, NULL, GResource_font_cvt, 0 },
305 : { "Box.GradientBG", rt_bool, NULL, NULL, 0 },
306 : { "Box.GradientStartCol", rt_color, NULL, NULL, 0 },
307 : { "Box.ShadowOuter", rt_bool, NULL, NULL, 0 },
308 : { "Box.BorderInnerCol", rt_color, NULL, NULL, 0 },
309 : { "Box.BorderOuterCol", rt_color, NULL, NULL, 0 },
310 : GRESSTRUCT_EMPTY
311 : };
312 : intpt bt, bs;
313 : int bw, pad, rr, inner, outer, active, depressed, def, grad, shadow;
314 0 : FontInstance *fi=deffont;
315 :
316 0 : if ( !_ggadget_inited )
317 0 : GGadgetInit();
318 0 : if ( fi==NULL )
319 0 : fi = _ggadget_default_font;
320 0 : bt = box->border_type;
321 0 : bs = box->border_shape;
322 0 : bw = box->border_width;
323 0 : pad = box->padding;
324 0 : rr = box->rr_radius;
325 0 : inner = box->flags & box_foreground_border_inner;
326 0 : outer = box->flags & box_foreground_border_outer;
327 0 : active = box->flags & box_active_border_inner;
328 0 : depressed = box->flags & box_do_depressed_background;
329 0 : def = box->flags & box_draw_default;
330 0 : grad = box->flags & box_gradient_bg;
331 0 : shadow = box->flags & box_foreground_shadow_outer;
332 :
333 0 : bordertype[0].val = &bt;
334 0 : boxtypes[0].val = &bt;
335 0 : boxtypes[1].val = &bs;
336 0 : boxtypes[2].val = &bw;
337 0 : boxtypes[3].val = &pad;
338 0 : boxtypes[4].val = &rr;
339 0 : boxtypes[5].val = &inner;
340 0 : boxtypes[6].val = &outer;
341 0 : boxtypes[7].val = &active;
342 0 : boxtypes[8].val = &depressed;
343 0 : boxtypes[9].val = &def;
344 0 : boxtypes[10].val = &box->border_brightest;
345 0 : boxtypes[11].val = &box->border_brighter;
346 0 : boxtypes[12].val = &box->border_darkest;
347 0 : boxtypes[13].val = &box->border_darker;
348 0 : boxtypes[14].val = &box->main_background;
349 0 : boxtypes[15].val = &box->main_foreground;
350 0 : boxtypes[16].val = &box->disabled_background;
351 0 : boxtypes[17].val = &box->disabled_foreground;
352 0 : boxtypes[18].val = &box->active_border;
353 0 : boxtypes[19].val = &box->depressed_background;
354 0 : boxtypes[20].val = &box->border_brightest;
355 0 : boxtypes[21].val = &box->border_brighter;
356 0 : boxtypes[22].val = &box->border_darkest;
357 0 : boxtypes[23].val = &box->border_darker;
358 0 : boxtypes[24].val = &fi;
359 0 : boxtypes[25].val = &grad;
360 0 : boxtypes[26].val = &box->gradient_bg_end;
361 0 : boxtypes[27].val = &shadow;
362 0 : boxtypes[28].val = &box->border_inner;
363 0 : boxtypes[29].val = &box->border_outer;
364 :
365 0 : GResourceFind( bordertype, class);
366 : /* for a plain box, default to all borders being the same. they must change*/
367 : /* explicitly */
368 0 : if ( bt==bt_box || bt==bt_double )
369 0 : box->border_brightest = box->border_brighter = box->border_darker = box->border_darkest;
370 0 : GResourceFind( boxtypes, class);
371 :
372 0 : box->border_type = bt;
373 0 : box->border_shape = bs;
374 0 : box->border_width = bw;
375 0 : box->padding = pad;
376 0 : box->rr_radius = rr;
377 0 : box->flags=0;
378 0 : if ( inner )
379 0 : box->flags |= box_foreground_border_inner;
380 0 : if ( outer )
381 0 : box->flags |= box_foreground_border_outer;
382 0 : if ( active )
383 0 : box->flags |= box_active_border_inner;
384 0 : if ( depressed )
385 0 : box->flags |= box_do_depressed_background;
386 0 : if ( def )
387 0 : box->flags |= box_draw_default;
388 0 : if ( grad )
389 0 : box->flags |= box_gradient_bg;
390 0 : if ( shadow )
391 0 : box->flags |= box_foreground_shadow_outer;
392 :
393 0 : if ( fi==NULL ) {
394 : FontRequest rq;
395 0 : memset(&rq,0,sizeof(rq));
396 0 : rq.utf8_family_name = SANS_UI_FAMILIES;
397 0 : rq.point_size = 10;
398 0 : rq.weight = 400;
399 0 : rq.style = 0;
400 0 : fi = GDrawInstanciateFont(NULL,&rq);
401 0 : if ( fi==NULL )
402 0 : GDrawFatalError("Cannot find a default font for gadgets");
403 : }
404 0 : return( fi );
405 : }
406 :
407 0 : static int localeptsize(void) {
408 : /* smaller point size to squeeze these languages in */
409 0 : const char *loc = getenv("LC_ALL");
410 0 : if ( loc==NULL ) loc = getenv("LC_CTYPE");
411 0 : if ( loc==NULL ) loc = getenv("LANG");
412 : /* if ( loc==NULL ) loc = getenv("LC_MESSAGES"); */
413 :
414 0 : if ( loc!=NULL && ( \
415 0 : strncmp(loc,"ja",2)==0 || \
416 0 : strncmp(loc,"zh",2)==0 || \
417 0 : strncmp(loc,"ko",2)==0) )
418 0 : return( -16 );
419 :
420 0 : return( -10 );
421 : }
422 :
423 0 : void GGadgetInit(void) {
424 : static GResStruct res[] = {
425 : { "Font", rt_string, NULL, GResource_font_cvt, 0 },
426 : GRESSTRUCT_EMPTY
427 : };
428 0 : if ( !_ggadget_inited ) {
429 0 : _ggadget_inited = true;
430 0 : GGadgetSetImagePath(GResourceFindString("GGadget.ImagePath"));
431 0 : _ggadget_Default_Box.main_background = GDrawGetDefaultBackground(NULL);
432 0 : _ggadget_Default_Box.main_foreground = GDrawGetDefaultForeground(NULL);
433 0 : _ggadget_default_font = _GGadgetInitDefaultBox("GGadget.",&_ggadget_Default_Box,NULL);
434 0 : _GGadgetCopyDefaultBox(&_GListMark_Box);
435 0 : _GListMark_Box.border_width = _GListMark_Box.padding = 1;
436 : /*_GListMark_Box.flags = 0;*/
437 0 : _GGadgetInitDefaultBox("GListMark.",&_GListMark_Box,NULL);
438 0 : _GListMarkSize = GResourceFindInt("GListMark.Width", _GListMarkSize);
439 0 : _GListMark_Image = GGadgetResourceFindImage("GListMark.Image", NULL);
440 0 : _GListMark_DisImage = GGadgetResourceFindImage("GListMark.DisabledImage", NULL);
441 0 : if ( _GListMark_Image!=NULL && _GListMark_Image->image!=NULL ) {
442 0 : int size = GDrawPixelsToPoints(NULL,GImageGetWidth(_GListMark_Image->image));
443 0 : if ( size>_GListMarkSize )
444 0 : _GListMarkSize=size;
445 : }
446 0 : _GGadget_FirstLine = GResourceFindInt("GGadget.FirstLine", _GGadget_FirstLine);
447 0 : _GGadget_LeftMargin = GResourceFindInt("GGadget.LeftMargin", _GGadget_LeftMargin);
448 0 : _GGadget_LineSkip = GResourceFindInt("GGadget.LineSkip", _GGadget_LineSkip);
449 0 : _GGadget_Skip = GResourceFindInt("GGadget.Skip", _GGadget_Skip);
450 0 : _GGadget_TextImageSkip = GResourceFindInt("GGadget.TextImageSkip", _GGadget_TextImageSkip);
451 :
452 0 : popup_foreground = GResourceFindColor("GGadget.Popup.Foreground",popup_foreground);
453 0 : popup_background = GResourceFindColor("GGadget.Popup.Background",popup_background);
454 0 : popup_delay = GResourceFindInt("GGadget.Popup.Delay",popup_delay);
455 0 : popup_lifetime = GResourceFindInt("GGadget.Popup.LifeTime",popup_lifetime);
456 0 : res[0].val = &popup_font;
457 0 : GResourceFind( res, "GGadget.Popup.");
458 0 : if ( popup_font==NULL ) {
459 : FontRequest rq;
460 0 : memset(&rq,0,sizeof(rq));
461 0 : rq.utf8_family_name = SANS_UI_FAMILIES;
462 0 : rq.point_size = localeptsize();
463 0 : rq.weight = 400;
464 0 : rq.style = 0;
465 0 : popup_font = GDrawInstanciateFont(NULL,&rq);
466 0 : if ( popup_font==NULL )
467 0 : popup_font = _ggadget_default_font;
468 : }
469 : }
470 0 : }
471 :
472 0 : void GListMarkDraw(GWindow pixmap,int x, int y, int height, enum gadget_state state ) {
473 : GRect r, old;
474 0 : int marklen = GDrawPointsToPixels(pixmap,_GListMarkSize);
475 :
476 0 : if ( state == gs_disabled &&
477 0 : _GListMark_DisImage!=NULL && _GListMark_DisImage->image!=NULL) {
478 0 : GDrawDrawScaledImage(pixmap,_GListMark_DisImage->image,x,
479 0 : y + (height-GImageGetScaledHeight(pixmap,_GListMark_DisImage->image))/2);
480 0 : } else if ( _GListMark_Image!=NULL && _GListMark_Image->image!=NULL ) {
481 0 : GDrawDrawScaledImage(pixmap,_GListMark_Image->image,x,
482 0 : y + (height-GImageGetScaledHeight(pixmap,_GListMark_Image->image))/2);
483 : } else {
484 0 : r.x = x; r.width = marklen;
485 0 : r.height = 2*GDrawPointsToPixels(pixmap,_GListMark_Box.border_width) +
486 0 : GDrawPointsToPixels(pixmap,3);
487 0 : r.y = y + (height-r.height)/2;
488 0 : GDrawPushClip(pixmap,&r,&old);
489 :
490 0 : GBoxDrawBackground(pixmap,&r,&_GListMark_Box, state,false);
491 0 : GBoxDrawBorder(pixmap,&r,&_GListMark_Box,state,false);
492 0 : GDrawPopClip(pixmap,&old);
493 : }
494 0 : }
495 :
496 : static struct popup_info {
497 : const unichar_t *msg;
498 : GImage *img;
499 : const void *data;
500 : GImage *(*get_image)(const void *data);
501 : void (*free_image)(const void *data,GImage *img);
502 : } popup_info;
503 :
504 0 : void GGadgetEndPopup() {
505 0 : if ( popup_visible ) {
506 0 : GDrawSetVisible(popup,false);
507 0 : popup_visible = false;
508 : }
509 0 : if ( popup_timer!=NULL ) {
510 0 : GDrawCancelTimer(popup_timer);
511 0 : popup_timer = NULL;
512 : }
513 0 : if ( popup_vanish_timer!=NULL ) {
514 0 : GDrawCancelTimer(popup_vanish_timer);
515 0 : popup_vanish_timer = NULL;
516 : }
517 0 : if ( popup_info.img!=NULL ) {
518 0 : if ( popup_info.free_image!=NULL )
519 0 : (popup_info.free_image)(popup_info.data,popup_info.img);
520 : else
521 0 : GImageDestroy(popup_info.img);
522 : }
523 :
524 0 : memset(&popup_info,0,sizeof(popup_info));
525 0 : }
526 :
527 0 : void GGadgetPopupExternalEvent(GEvent *e) {
528 : /* Depress control key to keep popup alive */
529 0 : if ( e->type == et_char &&
530 0 : ( e->u.chr.keysym == GK_Control_L || e->u.chr.keysym == GK_Control_R )) {
531 0 : if ( popup_vanish_timer!=NULL ) {
532 0 : GDrawCancelTimer(popup_vanish_timer);
533 0 : popup_vanish_timer = NULL;
534 : }
535 0 : return;
536 : }
537 0 : if ( e->type==et_char || e->type==et_charup || e->type==et_mousemove ||
538 0 : e->type == et_mousedown || e->type==et_mouseup ||
539 0 : e->type==et_destroy || (e->type==et_create && popup!=e->w))
540 0 : GGadgetEndPopup();
541 : }
542 :
543 0 : static int GGadgetPopupTest(GEvent *e) {
544 : unichar_t *msg;
545 : int lines, temp, width;
546 0 : GWindow root = GDrawGetRoot(GDrawGetDisplayOfWindow(popup));
547 : GRect pos, size;
548 : unichar_t *pt, *ept;
549 0 : int as, ds, ld, img_height=0;
550 : GEvent where;
551 :
552 0 : if ( e->type!=et_timer || e->u.timer.timer!=popup_timer || popup==NULL )
553 0 : return( false );
554 0 : popup_timer = NULL;
555 :
556 : /* Is the cursor still in the original window? */
557 0 : GDrawGetPointerPosition(root,&where);
558 0 : if ( where.u.mouse.x<popup_within.x || where.u.mouse.y<popup_within.y ||
559 0 : where.u.mouse.x>popup_within.x+popup_within.width ||
560 0 : where.u.mouse.y>popup_within.y+popup_within.height )
561 0 : return( true );
562 :
563 0 : lines = 0; width = 1;
564 0 : if ( popup_info.img==NULL && popup_info.get_image!=NULL ) {
565 0 : popup_info.img = (popup_info.get_image)(popup_info.data);
566 0 : popup_info.get_image = NULL;
567 : }
568 0 : if ( popup_info.img!=NULL ) {
569 0 : img_height = GImageGetHeight(popup_info.img);
570 0 : width = GImageGetWidth(popup_info.img);
571 : }
572 0 : pt = msg = (unichar_t *) popup_info.msg;
573 0 : if ( msg!=NULL ) {
574 0 : GDrawSetFont(popup,popup_font);
575 : do {
576 0 : temp = -1;
577 0 : if (( ept = u_strchr(pt,'\n'))!=NULL )
578 0 : temp = ept-pt;
579 0 : temp = GDrawGetTextWidth(popup,pt,temp);
580 0 : if ( temp>width ) width = temp;
581 0 : ++lines;
582 0 : pt = ept+1;
583 0 : } while ( ept!=NULL && *pt!='\0' );
584 : }
585 0 : GDrawWindowFontMetrics(popup,popup_font,&as, &ds, &ld);
586 0 : pos.width = width+2*GDrawPointsToPixels(popup,2);
587 0 : pos.height = lines*(as+ds) + img_height + 2*GDrawPointsToPixels(popup,2);
588 :
589 0 : pos.x = where.u.mouse.x+10; pos.y = where.u.mouse.y+10;
590 0 : GDrawGetSize(root,&size);
591 0 : if ( pos.x + pos.width > size.width )
592 0 : pos.x = (pos.x - 20 - pos.width );
593 0 : if ( pos.x<0 ) pos.x = 0;
594 0 : if ( pos.y + pos.height > size.height )
595 0 : pos.y = (pos.y - 20 - pos.height );
596 0 : if ( pos.y<0 ) pos.y = 0;
597 0 : GDrawMoveResize(popup,pos.x,pos.y,pos.width,pos.height);
598 0 : GDrawSetVisible(popup,true);
599 0 : GDrawRaise(popup);
600 0 : GDrawSetUserData(popup,msg);
601 0 : popup_vanish_timer = GDrawRequestTimer(popup,popup_lifetime,0,NULL);
602 0 : return( true );
603 : }
604 :
605 0 : static int msgpopup_eh(GWindow popup,GEvent *event) {
606 0 : if ( event->type == et_expose ) {
607 : unichar_t *msg, *pt, *ept;
608 : int x,y, fh, temp;
609 : int as, ds, ld;
610 :
611 0 : popup_visible = true;
612 0 : pt = msg = (unichar_t *) popup_info.msg;
613 0 : if ( (pt==NULL || *pt=='\0') && popup_info.img==NULL ) {
614 0 : GGadgetEndPopup();
615 0 : return( true );
616 : }
617 0 : y = x = GDrawPointsToPixels(popup,2);
618 0 : if ( popup_info.img!=NULL ) {
619 0 : GDrawDrawImage(popup,popup_info.img,NULL,x,y);
620 0 : y += GImageGetHeight(popup_info.img);
621 : }
622 0 : if ( pt!=NULL ) {
623 0 : GDrawWindowFontMetrics(popup,popup_font,&as, &ds, &ld);
624 0 : fh = as+ds;
625 0 : y += as;
626 0 : while ( *pt!='\0' ) {
627 : /* Find end of this line, if multiline text */
628 0 : if (( ept = u_strchr(pt,'\n'))!=NULL )
629 0 : temp = ept-pt; /* display next segment of multiline text */
630 : else
631 0 : temp = -1; /* last line, so display remainder of text */
632 0 : GDrawDrawText(popup,x,y,pt,temp,popup_foreground);
633 0 : y += fh;
634 0 : pt = ept+1;
635 0 : if ( ept==NULL )
636 0 : break;
637 : }
638 : }
639 0 : } else if ( event->type == et_timer && event->u.timer.timer==popup_timer ) {
640 0 : GGadgetPopupTest(event);
641 0 : } else if ( event->type == et_mousemove || event->type == et_mouseup ||
642 0 : event->type == et_mousedown || event->type == et_char ||
643 0 : event->type == et_timer || event->type == et_crossing ) {
644 0 : GGadgetEndPopup();
645 : }
646 0 : return( true );
647 : }
648 :
649 0 : void GGadgetPreparePopupImage(GWindow base,const unichar_t *msg, const void *data,
650 : GImage *(*get_image)(const void *data),
651 : void (*free_image)(const void *data,GImage *img)) {
652 : GPoint pt;
653 :
654 0 : GGadgetEndPopup();
655 0 : if ( msg==NULL && get_image==NULL )
656 0 : return;
657 :
658 0 : memset(&popup_info,0,sizeof(popup_info));
659 0 : popup_info.msg = msg;
660 0 : popup_info.data = data;
661 0 : popup_info.get_image = get_image;
662 0 : popup_info.free_image = free_image;
663 :
664 0 : if ( popup==NULL ) {
665 : GWindowAttrs pattrs;
666 : GRect pos;
667 :
668 0 : pattrs.mask = wam_events|wam_nodecor|wam_positioned|wam_cursor|wam_backcol/*|wam_transient*/;
669 0 : pattrs.event_masks = -1;
670 0 : pattrs.nodecoration = true;
671 0 : pattrs.positioned = true;
672 0 : pattrs.cursor = ct_pointer;
673 0 : pattrs.background_color = popup_background;
674 : /*pattrs.transient = GWidgetGetTopWidget(base);*/
675 0 : pos.x = pos.y = 0; pos.width = pos.height = 1;
676 0 : popup = GDrawCreateTopWindow(GDrawGetDisplayOfWindow(base),&pos,
677 : msgpopup_eh,NULL,&pattrs);
678 0 : GDrawSetFont(popup,popup_font);
679 : }
680 0 : GDrawGetSize(base,&popup_within);
681 0 : pt.x = pt.y = 0;
682 0 : GDrawTranslateCoordinates(base,GDrawGetRoot(GDrawGetDisplayOfWindow(popup)), &pt);
683 0 : popup_within.x = pt.x; popup_within.y = pt.y;
684 0 : popup_timer = GDrawRequestTimer(popup,popup_delay,0,(void *) msg);
685 : }
686 :
687 0 : static void popup_refresh(void) {
688 0 : if ( popup!=NULL ) {
689 0 : GDrawSetWindowBackground(popup,popup_background);
690 : }
691 0 : }
692 :
693 0 : void GGadgetPreparePopup(GWindow base,const unichar_t *msg) {
694 0 : GGadgetPreparePopupImage(base,msg,NULL,NULL,NULL);
695 0 : }
696 :
697 0 : void GGadgetPreparePopupR(GWindow base,int msg) {
698 0 : GGadgetPreparePopupImage(base,GStringGetResource(msg,NULL),NULL,NULL,NULL);
699 0 : }
700 :
701 0 : void GGadgetPreparePopup8(GWindow base, const char *msg) {
702 : static unichar_t popup_msg[500];
703 0 : utf82u_strncpy(popup_msg,msg,sizeof(popup_msg)/sizeof(popup_msg[0]));
704 0 : popup_msg[sizeof(popup_msg)/sizeof(popup_msg[0])-1]=0;
705 0 : GGadgetPreparePopupImage(base,popup_msg,NULL,NULL,NULL);
706 0 : }
707 :
708 0 : void _ggadget_redraw(GGadget *g) {
709 0 : GDrawRequestExpose(g->base, &g->r, false);
710 0 : }
711 :
712 0 : int _ggadget_noop(GGadget *g, GEvent *event) {
713 0 : return( false );
714 : }
715 :
716 0 : static void GBoxFigureRect(GWindow gw, GBox *design, GRect *r, int isdef) {
717 0 : int scale = GDrawPointsToPixels(gw,1);
718 0 : int bp = GDrawPointsToPixels(gw,design->border_width)+
719 0 : GDrawPointsToPixels(gw,design->padding)+
720 0 : ((design->flags & box_foreground_border_outer)?scale:0)+
721 0 : ((design->flags &
722 0 : (box_foreground_border_inner|box_active_border_inner))?scale:0)+
723 0 : (isdef && (design->flags & box_draw_default)?scale+GDrawPointsToPixels(gw,2):0);
724 0 : r->width += 2*bp;
725 0 : r->height += 2*bp;
726 0 : }
727 :
728 0 : static void GBoxFigureDiamond(GWindow gw, GBox *design, GRect *r, int isdef) {
729 0 : int scale = GDrawPointsToPixels(gw,1);
730 0 : int p = GDrawPointsToPixels(gw,design->padding);
731 0 : int b = GDrawPointsToPixels(gw,design->border_width)+
732 0 : ((design->flags & box_foreground_border_outer)?scale:0)+
733 0 : ((design->flags &
734 0 : (box_foreground_border_inner|box_active_border_inner))?scale:0)+
735 0 : (isdef && (design->flags & box_draw_default)?scale+GDrawPointsToPixels(gw,2):0);
736 0 : int xoff = r->width/2, yoff = r->height/2;
737 :
738 0 : if ( xoff<2*p ) xoff = 2*p;
739 0 : if ( yoff<2*p ) yoff = 2*p;
740 0 : r->width += 2*b+xoff;
741 0 : r->height += 2*b+yoff;
742 0 : }
743 :
744 0 : void _ggadgetFigureSize(GWindow gw, GBox *design, GRect *r, int isdef) {
745 : /* given that we want something with a client rectangle as big as r */
746 : /* Then given the box shape, figure out how much of a rectangle we */
747 : /* need around it */
748 :
749 0 : if ( r->width<=0 ) r->width = 1;
750 0 : if ( r->height<=0 ) r->height = 1;
751 :
752 0 : switch ( design->border_shape ) {
753 : case bs_rect:
754 0 : GBoxFigureRect(gw,design,r,isdef);
755 0 : break;
756 : case bs_roundrect:
757 0 : GBoxFigureRect(gw,design,r,isdef);
758 0 : break;
759 : case bs_elipse:
760 0 : GBoxFigureDiamond(gw,design,r,isdef);
761 0 : break;
762 : case bs_diamond:
763 0 : GBoxFigureDiamond(gw,design,r,isdef);
764 0 : break;
765 : }
766 0 : }
767 :
768 0 : void _ggadgetSetRects(GGadget *g, GRect *outer, GRect *inner, int xjust, int yjust) {
769 0 : int bp = GBoxBorderWidth(g->base,g->box);
770 :
771 :
772 0 : if ( g->r.width==0 )
773 0 : g->r.width = outer->width;
774 0 : if ( g->r.height==0 )
775 0 : g->r.height = outer->height;
776 :
777 0 : if ( g->inner.width==0 ) {
778 0 : if ( inner->width<g->r.width ) {
779 0 : g->inner.width = g->r.width - 2*bp;
780 0 : if ( xjust==-1 )
781 0 : g->inner.x = g->r.x + bp;
782 0 : else if ( xjust==0 ) {
783 0 : g->inner.x = g->r.x + (g->r.width-inner->width)/2;
784 0 : g->inner.width = inner->width;
785 : } else
786 0 : g->inner.x = g->r.x + (g->r.width-bp-g->inner.width);
787 : } else {
788 0 : g->inner.x = g->r.x;
789 0 : g->inner.width = g->r.width;
790 : }
791 : }
792 0 : if ( g->inner.height==0 ) {
793 0 : if ( inner->height<g->r.height ) {
794 0 : if ( yjust==-1 )
795 0 : g->inner.y = g->r.y + bp;
796 0 : else if ( yjust==0 )
797 0 : g->inner.y = g->r.y + (g->r.height-inner->height)/2;
798 : else
799 0 : g->inner.y = g->r.y + (g->r.height-bp-inner->height);
800 0 : g->inner.height = inner->height;
801 : } else {
802 0 : g->inner.y = g->r.y;
803 0 : g->inner.height = g->r.height;
804 : }
805 : }
806 0 : }
807 :
808 0 : static GGadget *GGadgetFindLastOpenGroup(GGadget *g) {
809 0 : for ( g=g->prev; g!=NULL && !g->opengroup; g = g->prev );
810 0 : return( g );
811 : }
812 :
813 0 : static int GGadgetLMargin(GGadget *sigh, GGadget *lastOpenGroup) {
814 0 : if ( lastOpenGroup==NULL )
815 0 : return( GDrawPointsToPixels(sigh->base,_GGadget_LeftMargin));
816 : else
817 0 : return( lastOpenGroup->r.x + GDrawPointsToPixels(lastOpenGroup->base,_GGadget_Skip));
818 : }
819 :
820 0 : int GGadgetScale(int xpos) {
821 0 : return( xpos*GIntGetResource(_NUM_ScaleFactor)/100 );
822 : }
823 :
824 0 : GGadget *_GGadget_Create(GGadget *g, struct gwindow *base, GGadgetData *gd,void *data, GBox *def) {
825 : GGadget *last, *lastopengroup;
826 :
827 0 : g->desired_width = g->desired_height = -1;
828 0 : _GWidget_AddGGadget(base,g);
829 0 : g->r = gd->pos;
830 0 : if ( !(gd->flags&gg_pos_in_pixels) ) {
831 0 : g->r.x = GDrawPointsToPixels(base,g->r.x);
832 0 : g->r.y = GDrawPointsToPixels(base,g->r.y);
833 0 : if ( g->r.width!=-1 )
834 0 : g->r.width = GDrawPointsToPixels(base,g->r.width);
835 0 : if ( !(gd->flags&gg_pos_use0)) {
836 0 : g->r.x = GGadgetScale(g->r.x);
837 0 : if ( g->r.width!=-1 )
838 0 : g->r.width = GGadgetScale(g->r.width);
839 : }
840 0 : g->r.height = GDrawPointsToPixels(base,g->r.height);
841 : }
842 0 : if ( gd->pos.width>0 ) g->desired_width = g->r.width;
843 0 : if ( gd->pos.height>0 ) g->desired_height = g->r.height;
844 0 : last = g->prev;
845 0 : lastopengroup = GGadgetFindLastOpenGroup(g);
846 0 : if ( g->r.y==0 && !(gd->flags & gg_pos_use0)) {
847 0 : if ( last==NULL ) {
848 0 : g->r.y = GDrawPointsToPixels(base,_GGadget_FirstLine);
849 0 : if ( g->r.x==0 )
850 0 : g->r.x = GGadgetLMargin(g,lastopengroup);
851 0 : } else if ( gd->flags & gg_pos_newline ) {
852 0 : int temp, y = last->r.y, nexty = last->r.y+last->r.height;
853 0 : while ( last!=NULL && last->r.y==y ) {
854 0 : temp = last->r.y+last->r.height;
855 0 : if ( temp>nexty ) nexty = temp;
856 0 : last = last->prev;
857 : }
858 0 : g->r.y = nexty + GDrawPointsToPixels(base,_GGadget_LineSkip);
859 0 : if ( g->r.x==0 )
860 0 : g->r.x = GGadgetLMargin(g,lastopengroup);
861 : } else {
862 0 : g->r.y = last->r.y;
863 : }
864 : }
865 0 : if ( g->r.x == 0 && !(gd->flags & gg_pos_use0)) {
866 0 : last = g->prev;
867 0 : if ( last==NULL )
868 0 : g->r.x = GGadgetLMargin(g,lastopengroup);
869 0 : else if ( gd->flags & gg_pos_under ) {
870 0 : int onthisline=0, onprev=0, i;
871 : GGadget *prev, *prevline;
872 : /* see if we can find a gadget on the previous line that has the */
873 : /* same number of gadgets between it and the start of the line */
874 : /* as this one has from the start of its line, then put at the */
875 : /* same x offset */
876 0 : for ( prev = last; prev!=NULL && prev->r.y==g->r.y; prev = prev->prev )
877 0 : ++onthisline;
878 0 : prevline = prev;
879 0 : for ( ; prev!=NULL && prev->r.y==prevline->r.y ; prev = prev->prev )
880 0 : onprev++;
881 0 : for ( prev = prevline, i=0; prev!=NULL && i<onprev-onthisline; prev = prev->prev);
882 0 : if ( prev!=NULL )
883 0 : g->r.x = prev->r.x;
884 : }
885 0 : if ( g->r.x==0 )
886 0 : g->r.x = last->r.x + last->r.width + GDrawPointsToPixels(base,_GGadget_Skip);
887 : }
888 :
889 0 : g->mnemonic = islower(gd->mnemonic)?toupper(gd->mnemonic):gd->mnemonic;
890 0 : g->shortcut = islower(gd->shortcut)?toupper(gd->shortcut):gd->shortcut;
891 0 : g->short_mask = gd->short_mask;
892 0 : g->cid = gd->cid;
893 0 : g->data = data;
894 0 : g->popup_msg = (gd->flags&gg_utf8_popup)
895 0 : ? utf82u_copy((char *) gd->popup_msg)
896 0 : : u_copy(gd->popup_msg);
897 0 : g->handle_controlevent = gd->handle_controlevent;
898 0 : if ( gd->box == NULL )
899 0 : g->box = def;
900 0 : else if ( gd->flags & gg_dontcopybox )
901 0 : g->box = gd->box;
902 : else {
903 0 : g->free_box = true;
904 0 : g->box = malloc(sizeof(GBox));
905 0 : *g->box = *gd->box;
906 : }
907 0 : g->state = !(gd->flags&gg_visible) ? gs_invisible :
908 0 : !(gd->flags&gg_enabled) ? gs_disabled :
909 : gs_enabled;
910 0 : if ( !(gd->flags&gg_enabled) ) g->was_disabled = true;
911 0 : return( g );
912 : }
913 :
914 0 : void _GGadget_FinalPosition(GGadget *g, struct gwindow *base, GGadgetData *gd) {
915 0 : if ( g->r.x<0 && !(gd->flags&gg_pos_use0)) {
916 : GRect size;
917 0 : GDrawGetSize(base,&size);
918 0 : g->r.x += size.width-g->r.width;
919 0 : g->inner.x += size.width-g->r.width;
920 : }
921 0 : }
922 :
923 0 : void _ggadget_destroy(GGadget *g) {
924 0 : if ( g==NULL )
925 0 : return;
926 0 : _GWidget_RemoveGadget(g);
927 0 : GGadgetEndPopup();
928 0 : if ( g->free_box )
929 0 : free( g->box );
930 0 : free(g->popup_msg);
931 0 : free(g);
932 : }
933 :
934 0 : void _GGadgetCloseGroup(GGadget *g) {
935 0 : GGadget *group = GGadgetFindLastOpenGroup(g);
936 : GGadget *prev;
937 0 : int maxx=0, maxy=0, temp;
938 0 : int bp = GBoxBorderWidth(g->base,g->box);
939 :
940 0 : if ( group==NULL )
941 0 : return;
942 0 : for ( prev=g ; prev!=group; prev = prev->prev ) {
943 0 : temp = prev->r.x + prev->r.width;
944 0 : if ( temp>maxx ) maxx = temp;
945 0 : temp = prev->r.y + prev->r.height;
946 0 : if ( temp>maxy ) maxy = temp;
947 : }
948 0 : if ( group->prevlabel ) {
949 0 : prev = group->prev;
950 0 : temp = prev->r.x + prev->r.width;
951 0 : if ( temp>maxx ) maxx = temp;
952 0 : temp = prev->r.y + prev->r.height/2 ;
953 0 : if ( temp>maxy ) maxy = temp;
954 : }
955 0 : maxx += GDrawPointsToPixels(g->base,_GGadget_Skip);
956 0 : maxy += GDrawPointsToPixels(g->base,_GGadget_LineSkip);
957 :
958 0 : if ( group->r.width==0 ) {
959 0 : group->r.width = maxx - group->r.x;
960 0 : group->inner.width = group->r.width - 2*bp;
961 : }
962 0 : if ( group->r.height==0 ) {
963 0 : group->r.height = maxy - group->r.y;
964 0 : group->inner.height = group->r.y + group->r.height - bp -
965 0 : group->inner.y;
966 : }
967 0 : group->opengroup = false;
968 : }
969 :
970 0 : int GGadgetWithin(GGadget *g, int x, int y) {
971 0 : register GRect *r = &g->r;
972 :
973 0 : if ( x<r->x || y<r->y || x>=r->x+r->width || y>=r->y+r->height )
974 0 : return( false );
975 :
976 0 : return( true );
977 : }
978 :
979 0 : int GGadgetInnerWithin(GGadget *g, int x, int y) {
980 0 : register GRect *r = &g->inner;
981 :
982 0 : if ( x<r->x || y<r->y || x>=r->x+r->width || y>=r->y+r->height )
983 0 : return( false );
984 :
985 0 : return( true );
986 : }
987 :
988 0 : void _ggadget_underlineMnemonic(GWindow gw,int32 x,int32 y,unichar_t *label,
989 : unichar_t mnemonic, Color fg, int maxy) {
990 0 : int point = GDrawPointsToPixels(gw,1);
991 : int width;
992 : /*GRect clip;*/
993 :
994 0 : if ( mnemonic=='\0' )
995 0 : return;
996 0 : char *ctext = u2utf8_copy(label);
997 0 : char *cpt = utf8_strchr(ctext,mnemonic);
998 : GRect space;
999 0 : if ( cpt==NULL && isupper(mnemonic))
1000 0 : cpt = strchr(ctext,tolower(mnemonic));
1001 0 : if ( cpt==NULL )
1002 0 : return;
1003 0 : GDrawLayoutInit(gw,ctext,-1,NULL);
1004 0 : GDrawLayoutIndexToPos(gw, cpt-ctext, &space);
1005 0 : free(ctext);
1006 0 : x += space.x;
1007 0 : width = space.width;
1008 0 : GDrawSetLineWidth(gw,point);
1009 0 : y += 2*point;
1010 0 : if ( y+point-1 >= maxy )
1011 0 : y = maxy-point;
1012 0 : GDrawDrawLine(gw,x,y,x+width,y,fg);
1013 0 : GDrawSetLineWidth(gw,0);
1014 : }
1015 :
1016 0 : void _ggadget_move(GGadget *g, int32 x, int32 y ) {
1017 0 : g->inner.x = x+(g->inner.x-g->r.x);
1018 0 : g->inner.y = y+(g->inner.y-g->r.y);
1019 0 : g->r.x = x;
1020 0 : g->r.y = y;
1021 0 : }
1022 :
1023 0 : void _ggadget_resize(GGadget *g, int32 width, int32 height ) {
1024 0 : g->inner.width = width-(g->r.width-g->inner.width);
1025 0 : g->inner.height = height-(g->r.height-g->inner.height);
1026 0 : g->r.width = width;
1027 0 : g->r.height = height;
1028 0 : }
1029 :
1030 0 : void _ggadget_getDesiredSize(GGadget *g, GRect *outer, GRect *inner) {
1031 :
1032 0 : if ( inner!=NULL ) {
1033 0 : inner->x = inner->y = 0;
1034 0 : inner->width = g->desired_width;
1035 0 : inner->height = g->desired_height;
1036 : }
1037 0 : if ( outer!=NULL ) {
1038 0 : outer->x = outer->y = 0;
1039 0 : outer->width = g->desired_width;
1040 0 : outer->height = g->desired_height;
1041 : }
1042 0 : }
1043 :
1044 0 : void _ggadget_setDesiredSize(GGadget *g,GRect *outer, GRect *inner) {
1045 0 : int bp = GBoxBorderWidth(g->base,g->box);
1046 :
1047 0 : if ( outer!=NULL ) {
1048 0 : g->desired_width = outer->width;
1049 0 : g->desired_height = outer->height;
1050 0 : } else if ( inner!=NULL ) {
1051 0 : g->desired_width = inner->width<=0 ? -1 : inner->width+2*bp;
1052 0 : g->desired_height = inner->height<=0 ? -1 : inner->height+2*bp;
1053 : }
1054 0 : }
1055 :
1056 0 : GRect *_ggadget_getsize(GGadget *g,GRect *rct) {
1057 0 : *rct = g->r;
1058 0 : return( rct );
1059 : }
1060 :
1061 0 : GRect *_ggadget_getinnersize(GGadget *g,GRect *rct) {
1062 0 : *rct = g->inner;
1063 0 : return( rct );
1064 : }
1065 :
1066 0 : void _ggadget_setvisible(GGadget *g,int visible) {
1067 0 : g->state = !visible ? gs_invisible :
1068 0 : g->was_disabled ? gs_disabled :
1069 : gs_enabled;
1070 : /* Make sure it isn't the focused _ggadget in the container !!!! */
1071 0 : _ggadget_redraw(g);
1072 0 : }
1073 :
1074 0 : void _ggadget_setenabled(GGadget *g,int enabled) {
1075 0 : g->was_disabled = !enabled;
1076 0 : if ( g->state!=gs_invisible ) {
1077 0 : g->state = enabled? gs_enabled : gs_disabled;
1078 0 : _ggadget_redraw(g);
1079 : }
1080 : /* Make sure it isn't the focused _ggadget in the container !!!! */
1081 0 : }
1082 :
1083 0 : void GGadgetDestroy(GGadget *g) {
1084 0 : (g->funcs->destroy)(g);
1085 0 : }
1086 :
1087 0 : void GGadgetRedraw(GGadget *g) {
1088 0 : (g->funcs->redraw)(g);
1089 0 : }
1090 :
1091 0 : void GGadgetMove(GGadget *g,int32 x, int32 y ) {
1092 0 : (g->funcs->move)(g,x,y);
1093 0 : }
1094 :
1095 0 : void GGadgetMoveAddToY(GGadget *g, int32 yoffset )
1096 : {
1097 : GRect sz;
1098 0 : GGadgetGetSize( g, &sz );
1099 0 : GGadgetMove( g, sz.x, sz.y + yoffset );
1100 0 : }
1101 :
1102 :
1103 :
1104 0 : int32 GGadgetGetX(GGadget *g)
1105 : {
1106 0 : return g->r.x;
1107 : }
1108 :
1109 0 : int32 GGadgetGetY(GGadget *g)
1110 : {
1111 0 : return g->r.y;
1112 : }
1113 :
1114 0 : void GGadgetSetY(GGadget *g, int32 y )
1115 : {
1116 0 : int32 x = GGadgetGetX(g);
1117 0 : GGadgetMove( g, x, y );
1118 0 : }
1119 :
1120 :
1121 :
1122 0 : void GGadgetResize(GGadget *g,int32 width, int32 height ) {
1123 0 : (g->funcs->resize)(g,width,height);
1124 0 : }
1125 :
1126 0 : GRect *GGadgetGetSize(GGadget *g,GRect *rct) {
1127 0 : return( (g->funcs->getsize)(g,rct) );
1128 : }
1129 :
1130 0 : void GGadgetSetSize(GGadget *g,GRect *rct)
1131 : {
1132 0 : GGadgetResize(g,rct->width,rct->height);
1133 0 : }
1134 :
1135 :
1136 0 : int GGadgetContainsEventLocation(GGadget *g, GEvent* e )
1137 : {
1138 0 : switch( e->type )
1139 : {
1140 : case et_mousemove:
1141 : case et_mouseup: case et_mousedown:
1142 0 : return( GGadgetContains( g, e->u.mouse.x, e->u.mouse.y ));
1143 : }
1144 :
1145 0 : return 0;
1146 : }
1147 :
1148 0 : int GGadgetContains(GGadget *g, int x, int y )
1149 : {
1150 : GRect r;
1151 0 : GGadgetGetSize( g, &r );
1152 0 : return r.x < x && r.x+r.width > x
1153 0 : && r.y < y && r.y+r.height > y;
1154 : }
1155 :
1156 0 : GRect *GGadgetGetInnerSize(GGadget *g,GRect *rct) {
1157 0 : return( (g->funcs->getinnersize)(g,rct) );
1158 : }
1159 :
1160 0 : void GGadgetSetVisible(GGadget *g,int visible) {
1161 0 : (g->funcs->setvisible)(g,visible);
1162 0 : }
1163 :
1164 0 : int GGadgetIsVisible(GGadget *g) {
1165 0 : return( g->state!=gs_invisible );
1166 : }
1167 :
1168 0 : void GGadgetSetEnabled(GGadget *g,int enabled) {
1169 0 : if(g)
1170 0 : (g->funcs->setenabled)(g,enabled);
1171 0 : }
1172 :
1173 0 : int GGadgetIsEnabled(GGadget *g) {
1174 0 : if ( g->state==gs_invisible )
1175 0 : return( !g->was_disabled );
1176 0 : return( g->state==gs_enabled );
1177 : }
1178 :
1179 0 : void GGadgetSetUserData(GGadget *g,void *data) {
1180 0 : g->data = data;
1181 0 : }
1182 :
1183 0 : void GGadgetSetPopupMsg(GGadget *g,const unichar_t *msg) {
1184 0 : free(g->popup_msg);
1185 0 : g->popup_msg = u_copy(msg);
1186 0 : }
1187 :
1188 0 : GWindow GGadgetGetWindow(GGadget *g) {
1189 0 : return( g->base );
1190 : }
1191 :
1192 0 : int GGadgetGetCid(GGadget *g) {
1193 0 : return( g->cid );
1194 : }
1195 :
1196 0 : void *GGadgetGetUserData(GGadget *g) {
1197 0 : return( g->data );
1198 : }
1199 :
1200 0 : int GGadgetEditCmd(GGadget *g,enum editor_commands cmd) {
1201 0 : if ( g->funcs->handle_editcmd!=NULL )
1202 0 : return(g->funcs->handle_editcmd)(g,cmd);
1203 0 : return( false );
1204 : }
1205 :
1206 0 : void GGadgetSetTitle(GGadget *g,const unichar_t *title) {
1207 0 : if ( g->funcs->set_title!=NULL )
1208 0 : (g->funcs->set_title)(g,title);
1209 0 : }
1210 :
1211 0 : void GGadgetSetTitle8(GGadget *g,const char *title) {
1212 0 : if ( g->funcs->set_title!=NULL ) {
1213 0 : unichar_t *temp = utf82u_copy(title);
1214 0 : (g->funcs->set_title)(g,temp);
1215 0 : free(temp);
1216 : }
1217 0 : }
1218 :
1219 0 : void GGadgetSetTitle8WithMn(GGadget *g,const char *title) {
1220 0 : char *pt = strchr(title,'_');
1221 0 : char *freeme=NULL;
1222 : int mnc;
1223 :
1224 0 : if ( pt!=NULL ) {
1225 0 : char *pos = pt+1;
1226 0 : mnc = utf8_ildb((const char **) &pos);
1227 0 : g->mnemonic = mnc;
1228 0 : freeme = copy(title);
1229 0 : for ( pt = freeme + (pt-title); *pt; ++pt )
1230 0 : *pt = pt[1];
1231 0 : title = freeme;
1232 : } else
1233 0 : g->mnemonic = 0;
1234 0 : GGadgetSetTitle8(g,title);
1235 0 : free(freeme);
1236 0 : }
1237 :
1238 0 : const unichar_t *_GGadgetGetTitle(GGadget *g) {
1239 0 : if ( g && g->funcs->_get_title!=NULL ) return( (g->funcs->_get_title)(g) );
1240 :
1241 0 : return( NULL );
1242 : }
1243 :
1244 0 : unichar_t *GGadgetGetTitle(GGadget *g) {
1245 0 : if ( g ) {
1246 0 : if ( g->funcs->get_title!=NULL )
1247 0 : return( (g->funcs->get_title)(g) );
1248 0 : else if ( g->funcs->_get_title!=NULL )
1249 0 : return( u_copy( (g->funcs->_get_title)(g) ));
1250 : }
1251 :
1252 0 : return( NULL );
1253 : }
1254 :
1255 0 : char *GGadgetGetTitle8(GGadget *g) {
1256 0 : if ( g->funcs->_get_title!=NULL )
1257 0 : return( u2utf8_copy( (g->funcs->_get_title)(g) ));
1258 0 : else if ( g->funcs->get_title!=NULL ) {
1259 0 : unichar_t *temp = (g->funcs->get_title)(g);
1260 0 : char *ret = u2utf8_copy(temp);
1261 0 : free(temp);
1262 0 : return( ret );
1263 : }
1264 :
1265 0 : return( NULL );
1266 : }
1267 :
1268 0 : void GGadgetSetFont(GGadget *g,GFont *font) {
1269 0 : if ( g->funcs->set_font!=NULL )
1270 0 : (g->funcs->set_font)(g,font);
1271 0 : }
1272 :
1273 0 : GFont *GGadgetGetFont(GGadget *g) {
1274 0 : if ( g==NULL )
1275 0 : return( _ggadget_default_font );
1276 0 : if ( g->funcs->get_font!=NULL )
1277 0 : return( (g->funcs->get_font)(g) );
1278 :
1279 0 : return( NULL );
1280 : }
1281 :
1282 0 : void GGadgetSetHandler(GGadget *g, GGadgetHandler handler) {
1283 0 : g->handle_controlevent = handler;
1284 0 : }
1285 :
1286 0 : GGadgetHandler GGadgetGetHandler(GGadget *g) {
1287 0 : return( g->handle_controlevent );
1288 : }
1289 :
1290 0 : void GGadgetClearList(GGadget *g) {
1291 0 : if ( g->funcs->clear_list!=NULL )
1292 0 : (g->funcs->clear_list)(g);
1293 0 : }
1294 :
1295 0 : void GGadgetSetList(GGadget *g, GTextInfo **ti, int32 copyit) {
1296 0 : if ( g->funcs->set_list!=NULL )
1297 0 : (g->funcs->set_list)(g,ti,copyit);
1298 0 : }
1299 :
1300 0 : GTextInfo **GGadgetGetList(GGadget *g,int32 *len) {
1301 0 : if ( g->funcs->get_list!=NULL )
1302 0 : return((g->funcs->get_list)(g,len));
1303 :
1304 0 : if ( len!=NULL ) *len = 0;
1305 0 : return( NULL );
1306 : }
1307 :
1308 0 : GTextInfo *GGadgetGetListItem(GGadget *g,int32 pos) {
1309 0 : if ( g->funcs->get_list_item!=NULL )
1310 0 : return((g->funcs->get_list_item)(g,pos));
1311 :
1312 0 : return( NULL );
1313 : }
1314 :
1315 0 : GTextInfo *GGadgetGetListItemSelected(GGadget *g) {
1316 0 : int pos = GGadgetGetFirstListSelectedItem(g);
1317 :
1318 0 : if ( pos!=-1 && g->funcs->get_list_item!=NULL )
1319 0 : return((g->funcs->get_list_item)(g,pos));
1320 :
1321 0 : return( NULL );
1322 : }
1323 :
1324 0 : void GGadgetSelectListItem(GGadget *g,int32 pos,int32 sel) {
1325 0 : if ( g->funcs->select_list_item!=NULL )
1326 0 : (g->funcs->select_list_item)(g,pos,sel);
1327 0 : }
1328 :
1329 0 : void GGadgetSelectOneListItem(GGadget *g,int32 pos) {
1330 0 : if ( g->funcs->select_one_list_item!=NULL )
1331 0 : (g->funcs->select_one_list_item)(g,pos);
1332 0 : }
1333 :
1334 0 : int32 GGadgetIsListItemSelected(GGadget *g,int32 pos) {
1335 0 : if ( g->funcs->is_list_item_selected!=NULL )
1336 0 : return((g->funcs->is_list_item_selected)(g,pos));
1337 :
1338 0 : return( 0 );
1339 : }
1340 :
1341 0 : int32 GGadgetGetFirstListSelectedItem(GGadget *g) {
1342 0 : if ( g->funcs->get_first_selection!=NULL )
1343 0 : return((g->funcs->get_first_selection)(g));
1344 0 : return( -1 );
1345 : }
1346 :
1347 0 : void GGadgetScrollListToPos(GGadget *g,int32 pos) {
1348 0 : if ( g->funcs->scroll_list_to_pos!=NULL )
1349 0 : (g->funcs->scroll_list_to_pos)(g,pos);
1350 0 : }
1351 :
1352 0 : void GGadgetScrollListToText(GGadget *g,const unichar_t *lab,int32 sel) {
1353 0 : if ( g->funcs->scroll_list_to_text!=NULL )
1354 0 : (g->funcs->scroll_list_to_text)(g,lab,sel);
1355 0 : }
1356 :
1357 0 : void GGadgetSetListOrderer(GGadget *g,int (*orderer)(const void *, const void *)) {
1358 0 : if ( g->funcs->set_list_orderer!=NULL )
1359 0 : (g->funcs->set_list_orderer)(g,orderer);
1360 0 : }
1361 :
1362 0 : void GGadgetGetDesiredSize(GGadget *g,GRect *outer, GRect *inner) {
1363 0 : if ( g->state==gs_invisible ) {
1364 0 : if ( outer!=NULL )
1365 0 : memset(outer,0,sizeof(*outer));
1366 0 : if ( inner!=NULL )
1367 0 : memset(inner,0,sizeof(*inner));
1368 0 : } else if ( ((char *) &g->funcs->get_desired_size) - ((char *) g->funcs) < g->funcs->size &&
1369 0 : g->funcs->get_desired_size!=NULL )
1370 0 : (g->funcs->get_desired_size)(g,outer,inner);
1371 : else {
1372 0 : if ( outer!=NULL )
1373 0 : *outer = g->r;
1374 0 : if ( inner!=NULL )
1375 0 : *inner = g->inner;
1376 : }
1377 0 : }
1378 :
1379 0 : void GGadgetGetDesiredVisibleSize(GGadget *g,GRect *outer, GRect *inner) {
1380 0 : if ( ((char *) &g->funcs->get_desired_size) - ((char *) g->funcs) < g->funcs->size &&
1381 0 : g->funcs->get_desired_size!=NULL )
1382 0 : (g->funcs->get_desired_size)(g,outer,inner);
1383 : else {
1384 0 : if ( outer!=NULL )
1385 0 : *outer = g->r;
1386 0 : if ( inner!=NULL )
1387 0 : *inner = g->inner;
1388 : }
1389 0 : }
1390 :
1391 0 : void GGadgetSetDesiredSize(GGadget *g,GRect *outer, GRect *inner) {
1392 0 : if ( ((char *) &g->funcs->set_desired_size) - ((char *) g->funcs) < g->funcs->size &&
1393 0 : g->funcs->set_desired_size!=NULL )
1394 0 : (g->funcs->set_desired_size)(g,outer,inner);
1395 0 : }
1396 :
1397 0 : int GGadgetFillsWindow(GGadget *g) {
1398 0 : if ( ((char *) &g->funcs->fills_window) - ((char *) g->funcs) < g->funcs->size &&
1399 0 : g->funcs->fills_window!=NULL )
1400 0 : return( (g->funcs->fills_window)(g) );
1401 :
1402 0 : return( false );
1403 : }
1404 :
1405 0 : int GGadgetIsDefault(GGadget *g) {
1406 0 : if ( ((char *) &g->funcs->is_default) - ((char *) g->funcs) < g->funcs->size &&
1407 0 : g->funcs->is_default!=NULL )
1408 0 : return( (g->funcs->is_default)(g) );
1409 :
1410 0 : return( false );
1411 : }
1412 :
1413 0 : void GGadgetsCreate(GWindow base, GGadgetCreateData *gcd) {
1414 : int i;
1415 :
1416 0 : for ( i=0; gcd[i].creator!=NULL; ++i )
1417 0 : gcd[i].ret = (gcd[i].creator)(base,&gcd[i].gd,gcd[i].data);
1418 0 : }
1419 :
1420 0 : int GGadgetDispatchEvent(GGadget *g, GEvent *event) {
1421 :
1422 0 : if ( g==NULL || event==NULL )
1423 0 : return( false );
1424 0 : switch ( event->type ) {
1425 : case et_expose:
1426 0 : if ( g->funcs->handle_expose )
1427 0 : return( (g->funcs->handle_expose)(g->base,g,event) );
1428 0 : break;
1429 : case et_mouseup: case et_mousedown: case et_mousemove: case et_crossing:
1430 0 : if ( g->funcs->handle_mouse )
1431 0 : return( (g->funcs->handle_mouse)(g,event) );
1432 0 : break;
1433 : case et_char: case et_charup:
1434 0 : if ( g->funcs->handle_key ) {
1435 : int ret;
1436 0 : int old = g->takes_keyboard;
1437 0 : g->takes_keyboard = true;
1438 0 : ret =(g->funcs->handle_key)(g,event);
1439 0 : g->takes_keyboard = old;
1440 0 : return( ret );
1441 : }
1442 0 : break;
1443 : case et_drag: case et_dragout: case et_drop: case et_selclear:
1444 0 : if ( g->funcs->handle_sel )
1445 0 : return( (g->funcs->handle_sel)(g,event) );
1446 0 : break;
1447 : case et_timer:
1448 0 : if ( g->funcs->handle_timer )
1449 0 : return( (g->funcs->handle_timer)(g,event) );
1450 0 : break;
1451 : case et_controlevent:
1452 0 : if ( g->handle_controlevent!=NULL )
1453 0 : return( (g->handle_controlevent)(g,event) );
1454 : else
1455 0 : GDrawPostEvent(event);
1456 0 : return( true );
1457 : }
1458 0 : return( false );
1459 : }
1460 :
1461 0 : void GGadgetTakesKeyboard(GGadget *g, int takes_keyboard) {
1462 0 : g->takes_keyboard = takes_keyboard;
1463 0 : }
1464 :
1465 0 : GResInfo *_GGadgetRIHead(void) {
1466 :
1467 0 : if ( !_ggadget_inited )
1468 0 : GGadgetInit();
1469 0 : return( &popup_ri );
1470 : }
1471 :
1472 0 : void GGadgetSetSkipHotkeyProcessing( GGadget *g, int v )
1473 : {
1474 0 : if( !g )
1475 0 : return;
1476 :
1477 0 : printf("GGadgetSetSkipHotkeyProcessing1 %d\n", g->state );
1478 0 : g->gg_skip_hotkey_processing = v;
1479 0 : printf("GGadgetSetSkipHotkeyProcessing2 %d\n", g->state );
1480 : }
1481 :
1482 0 : int GGadgetGetSkipHotkeyProcessing( GGadget *g )
1483 : {
1484 0 : if( !g )
1485 0 : return 0;
1486 :
1487 0 : return (g->gg_skip_hotkey_processing);
1488 : }
1489 :
1490 0 : void GGadgetSetSkipUnQualifiedHotkeyProcessing( GGadget *g, int v )
1491 : {
1492 0 : if( !g )
1493 0 : return;
1494 0 : g->gg_skip_unqualified_hotkey_processing = v;
1495 : }
1496 :
1497 0 : int GGadgetGetSkipUnQualifiedHotkeyProcessing( GGadget *g )
1498 : {
1499 0 : if( !g )
1500 0 : return 0;
1501 :
1502 0 : return (g->gg_skip_unqualified_hotkey_processing);
1503 : }
1504 :
|