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