1 
2 #include "studiox_includes.h"
3 extern "C"{
4 #include "gx_utility.h"
5 }
6 
7 #ifdef _DEBUG
8 #define new DEBUG_NEW
9 #endif
10 
11 typedef struct {
12     USHORT widget_type;
13     char *event_process_name;
14 } event_process_entry;
15 
16 event_process_entry default_event_process_table [] = {
17     {GX_TYPE_WIDGET,                    "gx_widget_event_process"},
18     {GX_TYPE_BUTTON,                    "gx_button_event_process"},
19     {GX_TYPE_TEXT_BUTTON,               "gx_button_event_process"},
20     {GX_TYPE_MULTI_LINE_TEXT_BUTTON,    "gx_multi_line_text_button_event_process"},
21     {GX_TYPE_RADIO_BUTTON,              "gx_button_event_process"},
22     {GX_TYPE_CHECKBOX,                  "gx_checkbox_event_process"},
23     {GX_TYPE_PIXELMAP_BUTTON,           "gx_pixelmap_button_event_process"},
24     {GX_TYPE_SHADOW_BUTTON,             "gx_button_event_process"},
25     {GX_TYPE_ICON_BUTTON,               "gx_button_event_process"},
26     {GX_TYPE_SPIN_BUTTON,               "gx_button_event_process"},
27     {GX_TYPE_ICON,                      "gx_icon_event_process"},
28     {GX_TYPE_SPRITE,                    "gx_sprite_event_process"},
29     {GX_TYPE_CIRCULAR_GAUGE,            "gx_circular_gauge_event_process"},
30     {GX_TYPE_SLIDER,                    "gx_slider_event_process"},
31     {GX_TYPE_PIXELMAP_SLIDER,           "gx_pixelmap_slider_event_process"},
32     {GX_TYPE_VERTICAL_SCROLL,           "gx_scrollbar_event_process"},
33     {GX_TYPE_HORIZONTAL_SCROLL,         "gx_scrollbar_event_process"},
34     {GX_TYPE_PROGRESS_BAR,              "gx_progress_bar_event_process"},
35     {GX_TYPE_RADIAL_PROGRESS_BAR,       "gx_radial_progress_bar_event_process"},
36     {GX_TYPE_PROMPT,                    "gx_widget_event_process"},
37     {GX_TYPE_NUMERIC_PROMPT,            "gx_widget_event_process"},
38     {GX_TYPE_PIXELMAP_PROMPT,           "gx_widget_event_process"},
39     {GX_TYPE_NUMERIC_PIXELMAP_PROMPT,   "gx_widget_event_process"},
40     {GX_TYPE_SINGLE_LINE_TEXT_INPUT,    "gx_single_line_text_input_event_process"},
41     {GX_TYPE_PIXELMAP_TEXT_INPUT,       "gx_single_line_text_input_event_process"},
42     {GX_TYPE_DROP_LIST,                 "gx_drop_list_event_process"},
43     {GX_TYPE_MENU_LIST,                 "gx_widget_event_process"},
44     {GX_TYPE_MENU,                      "gx_menu_event_process"},
45     {GX_TYPE_ACCORDION_MENU,            "gx_accordion_menu_event_process"},
46     {GX_TYPE_WINDOW,                    "gx_window_event_process"},
47     {GX_TYPE_ROOT_WINDOW,               "gx_window_event_process"},
48     {GX_TYPE_VERTICAL_LIST,             "gx_vertical_list_event_process"},
49     {GX_TYPE_HORIZONTAL_LIST,           "gx_horizontal_list_event_process"},
50     {GX_TYPE_POPUP_LIST,                "gx_popup_list_event_process"},
51     {GX_TYPE_MULTI_LINE_TEXT_VIEW,      "gx_multi_line_text_view_event_process"},
52     {GX_TYPE_MULTI_LINE_TEXT_INPUT,     "gx_multi_line_text_input_event_process"},
53     {GX_TYPE_LINE_CHART,                "gx_window_event_process"},
54     {GX_TYPE_DIALOG,                    "gx_window_event_process"},
55     {GX_TYPE_KEYBOARD,                  "gx_window_event_process"},
56     {GX_TYPE_SCROLL_WHEEL,              "gx_scroll_wheel_event_process"},
57     {GX_TYPE_TEXT_SCROLL_WHEEL,         "gx_scroll_wheel_event_process"},
58     {GX_TYPE_STRING_SCROLL_WHEEL,       "gx_scroll_wheel_event_process"},
59     {GX_TYPE_NUMERIC_SCROLL_WHEEL,      "gx_scroll_wheel_event_process"},
60     {GX_TYPE_GENERIC_SCROLL_WHEEL,      "gx_generic_scroll_wheel_event_process"},
61     {GX_TYPE_TREE_VIEW,                 "gx_tree_view_event_process"},
62     {0, NULL}
63 };
64 
65 
66 ///////////////////////////////////////////////////////////////////////////////
widget_service_provider()67 widget_service_provider::widget_service_provider()
68 {
69 }
70 
71 ///////////////////////////////////////////////////////////////////////////////
GetVarDeclaration()72 CString widget_service_provider::GetVarDeclaration()
73 {
74     return CString("GX_WIDGET_MEMBERS_DECLARE");
75 }
76 
77 ///////////////////////////////////////////////////////////////////////////////
GetDefaultEventProcess(int widget_type)78 CString widget_service_provider::GetDefaultEventProcess(int widget_type)
79 {
80     event_process_entry *entry = default_event_process_table;
81     while(entry->widget_type)
82     {
83         if (entry->widget_type == widget_type)
84         {
85             return CString(entry->event_process_name);
86         }
87         entry++;
88     }
89     return CString("GX_NULL");
90 }
91 
92 ///////////////////////////////////////////////////////////////////////////////
GetCreateFromDefFunctionName()93 CString widget_service_provider::GetCreateFromDefFunctionName()
94 {
95     return CString("gx_studio_widget_create");
96 }
97 
MakeCreatePreamble(char * name,int version,CString & out)98 void widget_service_provider::MakeCreatePreamble(char *name, int version, CString &out)
99 {
100     CString string(name);
101 
102     if (version > 50)
103     {
104         out.Format(_T("\nUINT gx_studio_%s_create(GX_CONST GX_STUDIO_WIDGET *info, GX_WIDGET *control_block, GX_WIDGET *parent)\n"), string);
105     }
106     else
107     {
108         out.Format(_T("\nUINT gx_studio_%s_create(GX_STUDIO_WIDGET *info, GX_WIDGET *control_block, GX_WIDGET *parent)\n"), string);
109     }
110 }
111 
112 ///////////////////////////////////////////////////////////////////////////////
GetCreateFromDefFunction(int version)113 CString widget_service_provider::GetCreateFromDefFunction(int version)
114 {
115     CString out;
116     MakeCreatePreamble("widget", version, out);
117 
118     out += "{\n"
119         "    UINT status;\n"
120         "    GX_WIDGET *widget = (GX_WIDGET *) control_block;\n"
121         "    status = gx_widget_create(widget, info->widget_name, parent, info->style, info->widget_id, &info->size);\n"
122         "    if (status == GX_SUCCESS)\n"
123         "    {\n";
124 
125         if (project_lib_version() > 50401)
126         {
127             "#if defined(GUIX_5_4_0_COMPATIBILITY)\n"
128             "        gx_widget_fill_color_set(widget, info->normal_fill_color_id, info->selected_fill_color_id);\n"
129             "#else\n"
130             "        gx_widget_fill_color_set(widget, info->normal_fill_color_id, info->selected_fill_color_id, info->disabled_fill_color_id);\n"
131             "#endif\n";
132         }
133         else
134         {
135             out += "        gx_widget_fill_color_set(widget, info->normal_fill_color_id, info->selected_fill_color_id);\n";
136         }
137 
138     out += "    }\n"
139         "    return status;\n"
140         "}\n";
141 
142     return out;
143 }
144 
145 ///////////////////////////////////////////////////////////////////////////////
DeclarePropertiesStruct()146 CString widget_service_provider::DeclarePropertiesStruct()
147 {
148 // GX_BOOL accepts_focus;\n"
149     CString out;
150 
151     if (project_lib_version() > 50400)
152     {
153         out = ""
154             "typedef struct GX_STUDIO_WIDGET_STRUCT\n"
155             "{\n"
156             "   GX_CHAR *widget_name;\n"
157             "   USHORT  widget_type;\n"
158             "   USHORT  widget_id;\n"
159             "   #if defined(GX_WIDGET_USER_DATA)\n"
160             "   INT   user_data;\n"
161             "   #endif\n"
162             "   ULONG style;\n"
163             "   ULONG status;\n"
164             "   ULONG control_block_size;\n"
165             "   GX_RESOURCE_ID normal_fill_color_id;\n"
166             "   GX_RESOURCE_ID selected_fill_color_id;\n"
167             "   GX_RESOURCE_ID disabled_fill_color_id;\n";
168     }
169     else if (project_lib_version() > 50205)
170     {
171         out = ""
172             "typedef struct GX_STUDIO_WIDGET_STRUCT\n"
173             "{\n"
174             "   GX_CHAR *widget_name;\n"
175             "   USHORT  widget_type;\n"
176             "   USHORT  widget_id;\n"
177             "   #if defined(GX_WIDGET_USER_DATA)\n"
178             "   INT   user_data;\n"
179             "   #endif\n"
180             "   ULONG style;\n"
181             "   ULONG status;\n"
182             "   ULONG control_block_size;\n"
183             "   GX_RESOURCE_ID normal_fill_color_id;\n"
184             "   GX_RESOURCE_ID selected_fill_color_id;\n";
185 
186     }
187     else
188     {
189         out = ""
190             "typedef struct GX_STUDIO_WIDGET_STRUCT\n"
191             "{\n"
192             "   GX_CHAR *widget_name;\n"
193             "   USHORT  widget_type;\n"
194             "   USHORT  widget_id;\n"
195             "   ULONG style;\n"
196             "   ULONG status;\n"
197             "   ULONG control_block_size;\n"
198             "   GX_RESOURCE_ID normal_fill_color_id;\n"
199             "   GX_RESOURCE_ID selected_fill_color_id;\n";
200     }
201 
202     if (project_lib_version() < 50100)
203     {
204         out +=     "   UINT (*create_function) (struct GX_STUDIO_WIDGET_STRUCT *, GX_WIDGET *, GX_WIDGET *);\n";
205     }
206     else
207     {
208         out +=     "   UINT (*create_function) (GX_CONST struct GX_STUDIO_WIDGET_STRUCT *, GX_WIDGET *, GX_WIDGET *);\n";
209     }
210     out += "   void (*draw_function) (GX_WIDGET *);\n"
211     "   UINT (*event_function) (GX_WIDGET *, GX_EVENT *);\n"
212     "   GX_RECTANGLE size;\n";
213 
214     if (project_lib_version() < 50100)
215     {
216         out +=     "   struct GX_STUDIO_WIDGET_STRUCT *next_widget;\n"
217         "   struct GX_STUDIO_WIDGET_STRUCT *child_widget;\n";
218     }
219     else
220     {
221         out +=     "   GX_CONST struct GX_STUDIO_WIDGET_STRUCT *next_widget;\n"
222         "   GX_CONST struct GX_STUDIO_WIDGET_STRUCT *child_widget;\n";
223     }
224     out += "   ULONG control_block_offset;\n"
225            "   GX_CONST void *properties;\n"
226            "} GX_STUDIO_WIDGET;\n\n";
227 
228     out += "typedef struct\n"
229            "{\n"
230            "    GX_CONST GX_STUDIO_WIDGET *widget_information;\n"
231            "    GX_WIDGET        *widget;\n"
232            "} GX_STUDIO_WIDGET_ENTRY;\n\n";
233 
234     return out;
235 }
236 
237 
238 
239 ///////////////////////////////////////////////////////////////////////////////
InitWidgetInfo(GX_WIDGET * child)240 widget_info *widget_service_provider::InitWidgetInfo(GX_WIDGET *child)
241 {
242     widget_info *info = new widget_info(child->gx_widget_type);
243     info->widget = child;
244     info->app_name = CString(child->gx_widget_name);
245     widget_factory::CreateUniqueAppNames(info);
246 
247     info->style = child->gx_widget_style;
248     info->size = child->gx_widget_size;
249     if (child->gx_widget_status & GX_STATUS_ACCEPTS_FOCUS)
250     {
251         info->accepts_focus = TRUE;
252     }
253     else
254     {
255         info->accepts_focus = FALSE;
256     }
257     info->color_id[NORMAL_FILL_COLOR_INDEX] = child->gx_widget_normal_fill_color;
258     info->color_id[SELECTED_FILL_COLOR_INDEX] = child->gx_widget_selected_fill_color;
259     info->color_id[DISABLED_FILL_COLOR_INDEX] = child->gx_widget_disabled_fill_color;
260     return info;
261 }
262 
263 ///////////////////////////////////////////////////////////////////////////////
GetStringId(char * string)264 GX_RESOURCE_ID widget_service_provider::GetStringId(char *string)
265 {
266     GX_RESOURCE_ID string_id = 0;
267     studiox_project *project = GetOpenProject();
268 
269     if (project)
270     {
271         CString str(string);
272 
273         int display = GetProjectView()->GetActiveDisplay();
274         string_table *table = project->mDisplays[display].stable;
275 
276         if (table)
277         {
278             int string_index = table->CheckAddString(str);
279             CString id_name = table->GetStringId(string_index);
280             string_id = table->GetResourceId(id_name);
281         }
282     }
283     return string_id;
284 }
285 
286 ///////////////////////////////////////////////////////////////////////////////
GetStringText(char * put,int size,widget_info * info)287 void widget_service_provider::GetStringText(char *put, int size, widget_info *info)
288 {
289     CString val;
290     studiox_project *project = GetOpenProject();
291 
292     if (!project || !put || size <= 1)
293     {
294         return;
295     }
296     *put = 0;
297 
298     int display = project->GetDisplayIndex(info);
299 
300     if (display < 0)
301     {
302         display = GetProjectView()->GetActiveDisplay();
303     }
304 
305     if (display >= 0)
306     {
307         string_table *table = project->mDisplays[display].stable;
308 
309         if (table)
310         {
311             CString id_name = table->GetResourceIdName(info->string_id[0]);
312             val = table->GetString(id_name);
313             int char_count = val.GetLength();
314 
315             if (char_count)
316             {
317                 // The maximun UTF8 character is 6 bytes, calculate the maximun utf8 buffer size needed for the string.
318                 int buffer_size = char_count * 6 + 1;
319                 char *utf8buf = new char[buffer_size];
320                 strcpy_s(utf8buf, buffer_size, CT2A(val.GetString(), CP_UTF8));
321 
322                 int len = strlen(utf8buf);
323 
324                 if (len < size)
325                 {
326                     strcpy_s(put, size, utf8buf);
327                 }
328                 else
329                 {
330                     GX_STRING   string;
331                     INT                   index;
332                     INT                   glyph_len = 0;
333                     index = 0;
334                     string.gx_string_ptr = utf8buf;
335                     string.gx_string_length = len;
336 
337                     /* Calculate the maximum bytes that could be set. */
338                     while (index + glyph_len < size)
339                     {
340                         index += glyph_len;
341                         _gx_utility_utf8_string_character_get(&string, GX_NULL, (UINT *)&glyph_len);
342                     }
343                     size = index;
344 
345                     strncpy(put, utf8buf, size);
346                     put[size] = 0;
347                 }
348 
349                 delete[] utf8buf;
350             }
351         }
352     }
353 }
354 
355 
356 ///////////////////////////////////////////////////////////////////////////////
CreateNewInstance(GX_WIDGET * parent)357 widget_info *widget_service_provider::CreateNewInstance(GX_WIDGET *parent)
358 {
359     GX_RECTANGLE size;
360     gx_utility_rectangle_define(&size, 0, 0, 79, 23);
361     gx_utility_rectangle_center(&size, &parent->gx_widget_size);
362 
363     GX_WIDGET *widget = new GX_WIDGET;
364     gx_widget_create(widget, "widget", parent,
365         GX_STYLE_ENABLED, 0, &size);
366     widget_info *info = InitWidgetInfo(widget);
367     return info;
368 }
369 
370 ///////////////////////////////////////////////////////////////////////////////
GenerateFromInfo(GX_WIDGET * parent,widget_info * info)371 GX_WIDGET *widget_service_provider::GenerateFromInfo(GX_WIDGET *parent, widget_info *info)
372 {
373     GX_WIDGET *widget = new GX_WIDGET;
374 
375     gx_widget_create(widget,
376         (CHAR *) info->app_name.GetString(),
377         parent,
378         info->style,
379         0,
380         &info->size);
381 
382     gx_widget_fill_color_set(widget,
383         info->color_id[NORMAL_FILL_COLOR_INDEX],
384         info->color_id[SELECTED_FILL_COLOR_INDEX],
385         info->color_id[DISABLED_FILL_COLOR_INDEX]);
386     return widget;
387 }
388 
389 ///////////////////////////////////////////////////////////////////////////////
SaveToProject(xml_writer & writer,studiox_project * project,int display,widget_info * info)390 void widget_service_provider::SaveToProject(xml_writer &writer, studiox_project *project, int display, widget_info *info)
391 {
392     GX_WIDGET *widget = info->widget;
393 
394     writer.WriteString("type", GetShortName());
395     writer.WriteString("app_name", info->app_name);
396     writer.WriteRect("size", info->size);
397     writer.WriteUnsigned("style", info->style);
398     writer.WriteInt("allocation", info->allocation);
399     writer.WriteBool("accepts_focus", info->accepts_focus);
400 
401     WriteColorId(writer, project, display, "normal_fill_color", info->color_id[NORMAL_FILL_COLOR_INDEX]);
402     WriteColorId(writer, project, display, "selected_fill_color", info->color_id[SELECTED_FILL_COLOR_INDEX]);
403     WriteColorId(writer, project, display, "disabled_fill_color", info->color_id[DISABLED_FILL_COLOR_INDEX]);
404 
405     if (!info->event_func.IsEmpty())
406     {
407         writer.WriteString("event_handler", info->event_func);
408     }
409     if (!info->draw_func.IsEmpty())
410     {
411         writer.WriteString("draw_func", info->draw_func);
412     }
413     if (!info->id_name.IsEmpty())
414     {
415         writer.WriteString("id_name", info->id_name);
416     }
417     if (!info->custom_name.IsEmpty())
418     {
419         writer.WriteString("custom_name", info->custom_name);
420     }
421     if (!info->user_data.IsEmpty())
422     {
423         writer.WriteString("user_data", info->user_data);
424     }
425 
426     writer.WriteBool("template", info->is_template);
427     writer.WriteBool("visible_at_startup", info->visible_at_startup);
428 }
429 
430 ///////////////////////////////////////////////////////////////////////////////
431 #define GLOBAL_STYLES GX_STYLE_BORDER_MASK|GX_STYLE_TRANSPARENT|GX_STYLE_DRAW_SELECTED|GX_STYLE_ENABLED
ReadFromProject(xml_reader & reader,studiox_project * project,int display,widget_info * info,ULONG valid_styles)432 void widget_service_provider::ReadFromProject(xml_reader &reader, studiox_project *project, int display, widget_info *info, ULONG valid_styles)
433 {
434     GX_WIDGET *widget = info->widget;
435     info->base_name = GetShortName();
436     reader.ReadString("app_name", info->app_name);
437     reader.ReadRect("size", info->size);
438     reader.ReadUnsigned("style", info->style);
439     reader.ReadInt("allocation", info->allocation);
440 
441     valid_styles |= GLOBAL_STYLES;
442 
443     if ((info->style & valid_styles) != info->style)
444     {
445         ErrorMsg("Project contains invalid widget styles. Resetting to default.");
446         info->style &= valid_styles;
447     }
448 
449     if (!reader.ReadBool("accepts_focus", info->accepts_focus))
450     {
451         info->accepts_focus = TRUE;
452     }
453 
454     info->color_id[NORMAL_FILL_COLOR_INDEX] = ReadColorId(reader, project, display, "normal_fill_color");
455     info->color_id[SELECTED_FILL_COLOR_INDEX] = ReadColorId(reader, project, display, "selected_fill_color");
456 
457     if (project->mHeader.project_version > 54)
458     {
459         info->color_id[DISABLED_FILL_COLOR_INDEX] = ReadColorId(reader, project, display, "disabled_fill_color");
460     }
461     else
462     {
463         info->color_id[DISABLED_FILL_COLOR_INDEX] = info->color_id[NORMAL_FILL_COLOR_INDEX];
464     }
465 
466     reader.ReadString("event_handler", info->event_func);
467     reader.ReadString("draw_func", info->draw_func);
468     reader.ReadString("id_name", info->id_name);
469     reader.ReadString("custom_name", info->custom_name);
470     reader.ReadString("user_data", info->user_data);
471 
472     reader.ReadBool("template", info->is_template);
473     reader.ReadBool("visible_at_startup", info->visible_at_startup);
474 }
475 
476 ///////////////////////////////////////////////////////////////////////////////
AssignColor(widget_info * info,int index,GX_RESOURCE_ID color_id)477 void widget_service_provider::AssignColor(widget_info *info, int index, GX_RESOURCE_ID color_id)
478 {
479     int save_id;
480     GX_WIDGET *widget = info->widget;
481 
482     switch(index)
483     {
484     case NORMAL_FILL_COLOR_INDEX:
485         if (widget)
486         {
487             save_id = widget->gx_widget_selected_fill_color;
488             gx_widget_fill_color_set(widget, color_id, save_id, widget->gx_widget_disabled_fill_color);
489         }
490 
491         info->color_id[NORMAL_FILL_COLOR_INDEX] = color_id;
492         break;
493 
494     case SELECTED_FILL_COLOR_INDEX:
495         if (widget)
496         {
497             save_id = widget->gx_widget_normal_fill_color;
498             gx_widget_fill_color_set(widget, save_id, color_id, widget->gx_widget_disabled_fill_color);
499         }
500 
501         info->color_id[SELECTED_FILL_COLOR_INDEX] = color_id;
502         break;
503 
504     case DISABLED_FILL_COLOR_INDEX:
505         if (widget)
506         {
507             gx_widget_fill_color_set(widget, widget->gx_widget_normal_fill_color, widget->gx_widget_selected_fill_color, color_id);
508         }
509 
510         info->color_id[DISABLED_FILL_COLOR_INDEX] = color_id;
511         break;
512     }
513 }
514 
515 ///////////////////////////////////////////////////////////////////////////////
GetTextDimension(int base_type,GX_CONST GX_CHAR * text,GX_FONT * normal_font,GX_FONT * selected_font,INT & max_width,INT & max_height)516 void widget_service_provider::GetTextDimension(int base_type, GX_CONST GX_CHAR *text,
517     GX_FONT *normal_font, GX_FONT *selected_font, INT &max_width, INT &max_height)
518 {
519     GX_VALUE text_width = 0;
520     int text_height = 0;
521     GX_STRING string;
522 
523     if (base_type == GX_TYPE_MULTI_LINE_TEXT_BUTTON)
524     {
525         // handle multi line text button
526         GX_CONST GX_CHAR *buffer = text;
527         GX_CONST GX_CHAR *line = NULL;
528         int line_index = 0;
529         int byte_count = 0;
530 
531         while (buffer && (*buffer))
532         {
533             if ((*buffer == GX_KEY_CARRIAGE_RETURN) || (*buffer == GX_KEY_LINE_FEED))
534             {
535                 if ((*buffer == GX_KEY_CARRIAGE_RETURN) && (*(buffer + 1) == GX_KEY_LINE_FEED))
536                 {
537                     buffer += 2;
538                 }
539                 else
540                 {
541                     buffer++;
542                 }
543                 line_index++;
544 
545                 if (line_index >= GX_MULTI_LINE_TEXT_BUTTON_MAX_LINES)
546                 {
547                     break;
548                 }
549                 else
550                 {
551                     string.gx_string_ptr = line;
552                     string.gx_string_length = byte_count;
553 
554                     _gx_system_string_width_get_ext(normal_font, &string, &text_width);
555                     if (text_width > max_width)
556                     {
557                         max_width = text_width;
558                     }
559 
560                     text_height += normal_font->gx_font_line_height;
561 
562                     line = NULL;
563                     byte_count = 0;
564                 }
565             }
566             else
567             {
568                 if (line == GX_NULL)
569                 {
570                     line = buffer;
571                 }
572                 byte_count++;
573                 buffer++;
574             }
575         }
576 
577         if (line)
578         {
579             string.gx_string_ptr = line;
580             string.gx_string_length = byte_count;
581 
582             _gx_system_string_width_get_ext(normal_font, &string, &text_width);
583             if (text_width > max_width)
584             {
585                 max_width = text_width;
586             }
587 
588             text_height += normal_font->gx_font_line_height;
589         }
590 
591         if (text_height > max_height)
592         {
593             max_height = text_height;
594         }
595     }
596     else
597     {
598         string.gx_string_ptr = text;
599         string.gx_string_length = strlen(text);
600         _gx_system_string_width_get_ext(normal_font, &string, &text_width);
601         text_height = normal_font->gx_font_line_height;
602 
603         if (text_width > max_width)
604         {
605             max_width = text_width;
606         }
607 
608         if (text_height > max_height)
609         {
610             max_height = text_height;
611         }
612 
613         if (selected_font)
614         {
615             _gx_system_string_width_get_ext(selected_font, &string, &text_width);
616             text_height = selected_font->gx_font_line_height;
617 
618             if (text_width > max_width)
619             {
620                 max_width = text_width;
621             }
622 
623             if (text_height > max_height)
624             {
625                 max_height = text_height;
626             }
627         }
628     }
629 }
630 
631 ///////////////////////////////////////////////////////////////////////////////
632 /* KGM- this should be change to create an instance of a widget (at least once),
633    and retrieve the border width for each border style (one time) and save this
634    information to an static array. Otherwise the GUIX libary and Studio can
635    conflict about the border width for each style.
636 
637    This is a quick fix to get things working for now.
638 
639    TECH_DEBT
640 */
GetBorderWidth(DWORD style)641 int widget_service_provider::GetBorderWidth(DWORD style)
642 {
643     int width = 0;
644 
645     switch (style & GX_STYLE_BORDER_MASK)
646     {
647     case GX_STYLE_BORDER_RAISED:
648     case GX_STYLE_BORDER_RECESSED:
649         width = 2;
650         break;
651 
652     case GX_STYLE_BORDER_THIN:
653         width = 1;
654         break;
655 
656     case GX_STYLE_BORDER_THICK:
657         width = 5;
658         break;
659 
660     case GX_STYLE_BORDER_NONE:
661     default:
662         width = 0;
663         break;
664     }
665     return width;
666 }
667 
668 ///////////////////////////////////////////////////////////////////////////////
GetTextDrawDimension(widget_info * info,GX_DISPLAY * display,INT & draw_width,INT & draw_height)669 void widget_service_provider::GetTextDrawDimension(widget_info *info, GX_DISPLAY *display, INT &draw_width, INT &draw_height)
670 {
671     GX_VALUE border_width;
672 
673     //pick up widget border
674     border_width = GetBorderWidth(info->style);
675 
676     draw_width = (info->size.gx_rectangle_right - info->size.gx_rectangle_left + 1);
677     draw_width -= (border_width << 1);
678     draw_height = (info->size.gx_rectangle_bottom - info->size.gx_rectangle_top + 1);
679     draw_height -= (border_width << 1);
680 
681     switch(info->basetype)
682     {
683     case GX_TYPE_STRING_SCROLL_WHEEL:
684         draw_height = info->ewi.string_scroll_wheel.base.row_height;
685         break;
686 
687     case GX_TYPE_RADIO_BUTTON:
688     case GX_TYPE_CHECKBOX:
689         //for radio button and check box, removed pixemap draw area from client area
690         if (!(info->style & GX_STYLE_TEXT_CENTER))
691         {
692             GX_PIXELMAP *map = NULL;
693             UINT id;
694 
695             if (info->basetype == GX_TYPE_RADIO_BUTTON)
696             {
697                 id = info->pixelmap_id[RADIO_ON_PIXELMAP_INDEX];
698                 if (!id)
699                 {
700                     id = GX_PIXELMAP_RADIO_ON_ID;
701                 }
702             }
703             else
704             {
705                 id = info->pixelmap_id[CHECKED_PIXELMAP_INDEX];
706                 if (!id)
707                 {
708                     id = GX_PIXELMAP_CHECKBOX_ON_ID;
709                 }
710             }
711 
712             if (id < display->gx_display_pixelmap_table_size)
713             {
714                 map = display->gx_display_pixelmap_table[id];
715             }
716 
717             if (map)
718             {
719                 draw_width -= map->gx_pixelmap_width * 3 / 2;
720             }
721         }
722         break;
723 
724     case GX_TYPE_MENU:
725         draw_width -= info->ewi.menu.text_x_offset;
726         draw_height -= info->ewi.menu.text_y_offset;
727         break;
728 
729     default:
730         break;
731     }
732 
733     if (draw_width < 0)
734     {
735         draw_width = 0;
736     }
737 
738     if (draw_height < 0)
739     {
740         draw_height = 0;
741     }
742 }
743 
744 ///////////////////////////////////////////////////////////////////////////////
CalculateTextFitSize(widget_info * info,int display_index)745 GX_RECTANGLE widget_service_provider::CalculateTextFitSize(widget_info *info, int display_index)
746 {
747     studiox_project *project = GetOpenProject();
748     project_view *pview = GetProjectView();
749     GX_RECTANGLE newsize = info->size;
750 
751     if (!project || !pview)
752     {
753         return newsize;
754     }
755 
756     GX_DISPLAY *gx_display = get_target_view_display();
757     if (!gx_display)
758     {
759         return newsize;
760     }
761 
762     display_info *display = &project->mDisplays[display_index];
763     string_table *stable = display->stable;
764     int index;
765     GX_RESOURCE_ID *id_list;
766     int id_count;
767     UINT normal_font_id = info->font_id[NORMAL_FONT_INDEX];
768     UINT selected_font_id = info->font_id[SELECTED_FONT_INDEX];
769     GX_FONT *normal_font = NULL;
770     GX_FONT *selected_font = NULL;
771     int text_draw_width;
772     int text_draw_height;
773 
774     if (normal_font_id < gx_display->gx_display_font_table_size)
775     {
776         //pick up normal font
777         normal_font = gx_display->gx_display_font_table[normal_font_id];
778     }
779 
780     if (!normal_font)
781     {
782         return newsize;
783     }
784 
785     //calculate client width and height for text drawing
786     if (info->basetype == GX_TYPE_STRING_SCROLL_WHEEL)
787     {
788         // string scroll wheel haver selected font
789         id_list = info->ewi.string_scroll_wheel.string_id_list;
790         id_count = info->ewi.string_scroll_wheel.base.total_rows;
791 
792         if (selected_font_id < gx_display->gx_display_font_table_size)
793         {
794             selected_font = gx_display->gx_display_font_table[selected_font_id];
795         }
796 
797         if (!selected_font)
798         {
799             return newsize;
800         }
801     }
802     else
803     {
804         id_list = info->string_id;
805         id_count = NUM_WIDGET_STRINGS;
806     }
807 
808     if (!id_list)
809     {
810         return newsize;
811     }
812 
813     GetTextDrawDimension(info, gx_display, text_draw_width, text_draw_height);
814 
815     CString string;
816     int language_count;
817     int language_index;
818 
819     //calculate maximum text width and height
820     if ((info->basetype == GX_TYPE_NUMERIC_PIXELMAP_PROMPT) ||
821         (info->basetype == GX_TYPE_NUMERIC_PROMPT))
822     {
823         string.Format(_T("%d"), info->ewi.numeric_prompt_value);
824         id_count = 1;
825         language_count = 1;
826     }
827     else
828     {
829         language_count = stable->CountLanguages();
830     }
831 
832     int text_width = 0;
833     int text_height = 0;
834     CString id_name;
835 
836     for (language_index = 0; language_index < language_count; language_index++)
837     {
838         //calculate text dimension for one language
839         for (index = 0; index < id_count; index++)
840         {
841             if (id_list[index])
842             {
843                 id_name = stable->GetResourceIdName(id_list[index]);
844                 string = stable->GetString(id_name, language_index);
845                 language_count = stable->CountLanguages();
846             }
847 
848             if (!string.IsEmpty())
849             {
850                 int char_count;
851                 char *utf8buf;
852 
853                 // The maximun UTF8 character is 6 bytes, calculate the maximun utf8 buffer size needed for the string.
854                 char_count = string.GetLength() * 6 + 1;
855                 utf8buf = new char[char_count];
856                 strcpy_s(utf8buf, char_count, CT2A(string.GetString(), CP_UTF8));
857 
858                 GetTextDimension(info->basetype, utf8buf, normal_font, selected_font, text_width, text_height);
859 
860                 delete[]utf8buf;
861             }
862 
863             string.Empty();
864         }
865     }
866 
867     newsize.gx_rectangle_right += (text_width - text_draw_width);
868     newsize.gx_rectangle_bottom += (text_height - text_draw_height);
869 
870     return newsize;
871 }
872 
873 ///////////////////////////////////////////////////////////////////////////////
CheckResizeToText(widget_info * info,INT resize_mode)874 BOOL widget_service_provider::CheckResizeToText(widget_info *info, INT resize_mode)
875 {
876     studiox_project *project = GetOpenProject();
877 
878     if (!project || !info)
879     {
880         return FALSE;
881     }
882 
883     int display = project->GetDisplayIndex(info);
884 
885     if (display < 0)
886     {
887         return FALSE;
888     }
889 
890     GX_RECTANGLE newsize = info->size;
891     GX_RECTANGLE fitsize = CalculateTextFitSize(info, display);
892     GX_VALUE border_width;
893 
894     //pick up widget border
895     gx_widget_border_width_get(info->widget, &border_width);
896 
897     if (border_width)
898     {
899         fitsize.gx_rectangle_right += 2;
900         fitsize.gx_rectangle_bottom += 2;
901     }
902 
903     if (resize_mode == RESIZE_MODE_ALL ||
904         resize_mode == RESIZE_MODE_WIDTH)
905     {
906         newsize.gx_rectangle_right = fitsize.gx_rectangle_right;
907     }
908 
909     if (resize_mode == RESIZE_MODE_ALL ||
910         resize_mode == RESIZE_MODE_HEIGHT)
911     {
912         newsize.gx_rectangle_bottom = fitsize.gx_rectangle_bottom;
913     }
914 
915     if (!gx_utility_rectangle_compare(&newsize, &info->widget->gx_widget_size))
916     {
917         widget_factory::MoveWidget(info, newsize);
918         GetTargetScreen()->WidgetWasMoved(info);
919         GetPropsWin()->WidgetWasMoved();
920 
921         return TRUE;
922     }
923 
924     return FALSE;
925 }
926 
927 ///////////////////////////////////////////////////////////////////////////////
CheckResizeToPixelmap(widget_info * info,int resize_mode,BOOL DontShrink)928 BOOL widget_service_provider::CheckResizeToPixelmap(widget_info *info,
929          int resize_mode, BOOL DontShrink)
930 {
931     GX_PIXELMAP *map = NULL;
932     GX_VALUE border_width;
933     int map_index;
934 
935     int max_map_width = -1;
936     int max_map_height = -1;
937     studiox_project *project = GetOpenProject();
938 
939     if (!project || !info)
940     {
941         return FALSE;
942     }
943 
944     int display = project->GetDisplayIndex(info);
945     int active_theme = project->mDisplays[display].active_theme;
946 
947     if (display >= 0)
948     {
949         for (map_index = 0; map_index < NUM_WIDGET_PIXELMAPS; map_index++)
950         {
951             if (info->pixelmap_id[map_index])
952             {
953                 res_info *resource = project->FindResource(display, active_theme, RES_TYPE_PIXELMAP, info->pixelmap_id[map_index]);
954                 if (resource)
955                 {
956                     map = resource->GetPixelmap();
957                     if (map)
958                     {
959                         if (map->gx_pixelmap_width > max_map_width)
960                         {
961                             max_map_width = map->gx_pixelmap_width;
962                         }
963                         if (map->gx_pixelmap_height > max_map_height)
964                         {
965                             max_map_height = map->gx_pixelmap_height;
966                         }
967                     }
968                 }
969             }
970         }
971     }
972 
973     if (max_map_height <= 0 || max_map_width <= 0)
974     {
975         return FALSE;
976     }
977 
978     // check to see if new size if any different
979 
980     GX_RECTANGLE newsize = info->size;
981     //gx_widget_border_width_get(info->widget, &border_width);
982     border_width = GetBorderWidth(info->style);
983 
984     if (resize_mode == RESIZE_MODE_ALL ||
985         resize_mode == RESIZE_MODE_WIDTH)
986     {
987         newsize.gx_rectangle_right = newsize.gx_rectangle_left + max_map_width + (border_width * 2) - 1;
988     }
989 
990     if (resize_mode == RESIZE_MODE_ALL ||
991         resize_mode == RESIZE_MODE_HEIGHT)
992     {
993         newsize.gx_rectangle_bottom = newsize.gx_rectangle_top + max_map_height + (border_width * 2) - 1;
994     }
995 
996     if (DontShrink)
997     {
998         if (newsize.gx_rectangle_bottom < info->size.gx_rectangle_bottom)
999         {
1000             return FALSE;
1001         }
1002     }
1003 
1004     if (!gx_utility_rectangle_compare(&newsize, &info->widget->gx_widget_size))
1005     {
1006         if (info->widget)
1007         {
1008             gx_widget_resize(info->widget, &newsize);
1009         }
1010         info->size = newsize;
1011         GetPropsWin()->WidgetWasMoved();
1012         GetTargetScreen()->WidgetWasMoved(info);
1013         return TRUE;
1014     }
1015     return FALSE;
1016 }
1017 
1018 ///////////////////////////////////////////////////////////////////////////////
WriteStringId(xml_writer & writer,studiox_project * project,int display,char * tag,GX_RESOURCE_ID resid)1019 void widget_service_provider::WriteStringId(xml_writer &writer, studiox_project *project, int display, char *tag, GX_RESOURCE_ID resid)
1020 {
1021     string_table *table = project->mDisplays[display].stable;
1022     CString idName;
1023 
1024     if (!table)
1025     {
1026         return;
1027     }
1028 
1029     idName = table->GetResourceIdName(resid);
1030 
1031     if (!idName.IsEmpty())
1032     {
1033         writer.WriteString(tag, idName);
1034     }
1035 }
1036 
1037 ///////////////////////////////////////////////////////////////////////////////
WriteFontId(xml_writer & writer,studiox_project * project,int display,char * tag,GX_RESOURCE_ID resid)1038 void widget_service_provider::WriteFontId(xml_writer &writer, studiox_project *project, int display, char *tag, GX_RESOURCE_ID resid)
1039 {
1040     CString FontName;
1041 
1042     project->GetResourceName(display, RES_TYPE_FONT, resid, FontName);
1043 
1044     if (!FontName.IsEmpty())
1045     {
1046         writer.WriteString(tag, FontName);
1047     }
1048 }
1049 
1050 ///////////////////////////////////////////////////////////////////////////////
WritePixelmapId(xml_writer & writer,studiox_project * project,int display,char * tag,GX_RESOURCE_ID resid)1051 void widget_service_provider::WritePixelmapId(xml_writer &writer, studiox_project *project, int display, char *tag, GX_RESOURCE_ID resid)
1052 {
1053     CString PixName;
1054 
1055     project->GetResourceName(display, RES_TYPE_PIXELMAP, resid, PixName);
1056 
1057     if (!PixName.IsEmpty())
1058     {
1059         writer.WriteString(tag, PixName);
1060     }
1061 }
1062 
1063 ///////////////////////////////////////////////////////////////////////////////
WriteColorId(xml_writer & writer,studiox_project * project,int display,char * tag,GX_RESOURCE_ID resid)1064 void widget_service_provider::WriteColorId(xml_writer &writer, studiox_project *project, int display, char *tag, GX_RESOURCE_ID resid)
1065 {
1066     CString ColorName;
1067 
1068     project->GetResourceName(display, RES_TYPE_COLOR, resid, ColorName);
1069 
1070     if (!ColorName.IsEmpty())
1071     {
1072         writer.WriteString(tag, ColorName);
1073     }
1074 }
1075 
1076 ///////////////////////////////////////////////////////////////////////////////
ReadStringId(xml_reader & reader,studiox_project * project,int display,char * tag)1077 GX_RESOURCE_ID widget_service_provider::ReadStringId(xml_reader &reader, studiox_project *project, int display, char *tag)
1078 {
1079     ULONG res_id = 0;
1080     CString IdName;
1081 
1082     if (project->mHeader.project_version <= 52)
1083     {
1084         reader.ReadUnsigned(tag, res_id, 0);
1085     }
1086     else
1087     {
1088         string_table *table = project->mDisplays[display].stable;
1089 
1090         if (table)
1091         {
1092             reader.ReadString(tag, IdName);
1093             res_id = table->GetResourceId(IdName);
1094         }
1095     }
1096     return res_id;
1097 }
1098 
1099 ///////////////////////////////////////////////////////////////////////////////
ReadFontId(xml_reader & reader,studiox_project * project,int display,char * tag)1100 GX_RESOURCE_ID widget_service_provider::ReadFontId(xml_reader &reader, studiox_project *project, int display, char *tag)
1101 {
1102     ULONG res_id = 0;
1103     CString IdName;
1104 
1105     if (project->mHeader.project_version <= 52)
1106     {
1107         reader.ReadUnsigned(tag, res_id, 0);
1108 
1109         // sanity check
1110         if (res_id > 10000)
1111         {
1112             res_id = 0;
1113         }
1114     }
1115     else
1116     {
1117         reader.ReadString(tag, IdName);
1118         res_id = project->GetResourceId(display, RES_TYPE_FONT, IdName);
1119     }
1120     return res_id;
1121 }
1122 
1123 ///////////////////////////////////////////////////////////////////////////////
ReadPixelmapId(xml_reader & reader,studiox_project * project,int display,char * tag)1124 GX_RESOURCE_ID widget_service_provider::ReadPixelmapId(xml_reader &reader, studiox_project *project, int display, char *tag)
1125 {
1126     ULONG res_id = 0;
1127     CString IdName;
1128 
1129     if (project->mHeader.project_version <= 52)
1130     {
1131         reader.ReadUnsigned(tag, res_id, 0);
1132 
1133         // sanity check
1134         if (res_id > 10000)
1135         {
1136             res_id = 0;
1137         }
1138     }
1139     else
1140     {
1141         reader.ReadString(tag, IdName);
1142         res_id = project->GetResourceId(display, RES_TYPE_PIXELMAP, IdName);
1143     }
1144     return res_id;
1145 
1146 }
1147 
1148 ///////////////////////////////////////////////////////////////////////////////
ReadColorId(xml_reader & reader,studiox_project * project,int display,char * tag)1149 GX_RESOURCE_ID widget_service_provider::ReadColorId(xml_reader &reader, studiox_project *project, int display, char *tag)
1150 {
1151     ULONG res_id = 0;
1152     CString IdName;
1153 
1154     if (project->mHeader.project_version <= 52)
1155     {
1156         reader.ReadUnsigned(tag, res_id, 0);
1157 
1158         // sanity check
1159         if (res_id > 10000)
1160         {
1161             res_id = 0;
1162         }
1163     }
1164     else
1165     {
1166         reader.ReadString(tag, IdName);
1167         res_id = project->GetResourceId(display, RES_TYPE_COLOR, IdName);
1168     }
1169     return res_id;
1170 
1171 }
1172 
1173