00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 #include <string.h>
00052
00053 #include "contiki.h"
00054
00055 #include "ctk/ctk.h"
00056 #include "ctk/ctk-draw.h"
00057 #include "ctk/ctk-mouse.h"
00058
00059 static unsigned char height, width;
00060
00061 static unsigned char mode;
00062
00063 static struct ctk_window desktop_window;
00064 static struct ctk_window *windows;
00065 static struct ctk_window *dialog;
00066
00067 #if CTK_CONF_MENUS
00068 static struct ctk_menus menus;
00069 static struct ctk_menu *lastmenu;
00070 static struct ctk_menu desktopmenu;
00071 #endif
00072
00073 #ifndef NULL
00074 #define NULL (void *)0
00075 #endif
00076
00077 #define REDRAW_NONE 0
00078 #define REDRAW_ALL 1
00079 #define REDRAW_FOCUS 2
00080 #define REDRAW_WIDGETS 4
00081 #define REDRAW_MENUS 8
00082 #define REDRAW_MENUPART 16
00083
00084 #define MAX_REDRAWWIDGETS 4
00085 static unsigned char redraw;
00086 static struct ctk_widget *redraw_widgets[MAX_REDRAWWIDGETS];
00087 static unsigned char redraw_widgetptr;
00088 static unsigned char maxnitems;
00089
00090 static unsigned char iconx, icony;
00091 #define ICONX_START (width - 6)
00092 #define ICONY_START (height - 7)
00093 #define ICONX_DELTA -16
00094 #define ICONY_DELTA -5
00095 #define ICONY_MAX height
00096 #define ICONY_MIN 0
00097
00098 #ifndef ctk_arch_isprint
00099 unsigned char ctk_arch_isprint(char c);
00100 #endif
00101
00102
00103 PROCESS(ctk_process, "CTK Contiki GUI");
00104
00105
00106
00107
00108
00109 process_event_t
00110
00111
00112
00113
00114
00115 ctk_signal_keypress,
00116
00117
00118
00119 ctk_signal_widget_activate,
00120
00121
00122 ctk_signal_button_activate,
00123
00124
00125
00126 ctk_signal_widget_select,
00127
00128
00129 ctk_signal_button_hover,
00130
00131
00132
00133 ctk_signal_hyperlink_activate,
00134
00135
00136 ctk_signal_hyperlink_hover,
00137
00138
00139
00140 ctk_signal_menu_activate,
00141
00142
00143
00144 ctk_signal_window_close,
00145
00146
00147
00148
00149 ctk_signal_pointer_move,
00150
00151
00152
00153 ctk_signal_pointer_button;
00154
00155 #if CTK_CONF_SCREENSAVER
00156
00157
00158 process_event_t ctk_signal_screensaver_stop,
00159
00160
00161 ctk_signal_screensaver_start;
00162 #endif
00163
00164
00165
00166
00167 #if CTK_CONF_MOUSE_SUPPORT
00168 unsigned short mouse_x, mouse_y, mouse_button;
00169 #endif
00170
00171 static unsigned short screensaver_timer = 0;
00172 unsigned short ctk_screensaver_timeout = (5*60);
00173 static struct timer timer;
00174
00175 static void CC_FASTCALL
00176 textentry_input(ctk_arch_key_t c,
00177 CC_REGISTER_ARG struct ctk_textentry *t);
00178 #if CTK_CONF_MENUS
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188 static void
00189 make_desktopmenu(void)
00190 {
00191 struct ctk_window *w;
00192
00193 desktopmenu.nitems = 0;
00194
00195 if(windows == NULL) {
00196 ctk_menuitem_add(&desktopmenu, "(No windows)");
00197 } else {
00198 for(w = windows; w != NULL; w = w->next) {
00199 ctk_menuitem_add(&desktopmenu, w->title);
00200 }
00201 }
00202 }
00203 #endif
00204
00205 static void
00206 arrange_icons(void)
00207 {
00208 struct ctk_widget *icon;
00209
00210 iconx = ICONX_START;
00211 icony = ICONY_START;
00212
00213 for(icon = desktop_window.active; icon != NULL; icon = icon->next) {
00214
00215 icon->x = iconx;
00216 icon->y = icony;
00217
00218 icony += ICONY_DELTA;
00219 if(icony >= ICONY_MAX ||
00220 icony < ICONY_MIN) {
00221 icony = ICONY_START;
00222 iconx += ICONX_DELTA;
00223 }
00224 }
00225 }
00226
00227 void
00228 ctk_restore(void)
00229 {
00230 ctk_draw_init();
00231
00232 height = ctk_draw_height();
00233 width = ctk_draw_width();
00234
00235 arrange_icons();
00236
00237 redraw = REDRAW_ALL;
00238 }
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263 void
00264 ctk_mode_set(unsigned char m) {
00265 mode = m;
00266 }
00267
00268
00269
00270
00271
00272
00273
00274 unsigned char
00275 ctk_mode_get(void) {
00276 return mode;
00277 }
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 void
00288 ctk_icon_add(CC_REGISTER_ARG struct ctk_widget *icon, struct process *p)
00289 {
00290 #if CTK_CONF_ICONS
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300 icon->widget.icon.owner = p;
00301 ctk_widget_add(&desktop_window, icon);
00302 arrange_icons();
00303 #endif
00304 }
00305
00306
00307
00308
00309
00310
00311
00312 void
00313 ctk_dialog_open(struct ctk_window *d)
00314 {
00315 dialog = d;
00316 redraw |= REDRAW_FOCUS;
00317 }
00318
00319
00320
00321
00322
00323
00324 void
00325 ctk_dialog_close(void)
00326 {
00327 dialog = NULL;
00328 redraw |= REDRAW_ALL;
00329 }
00330
00331
00332
00333
00334
00335
00336
00337 void
00338 ctk_window_open(CC_REGISTER_ARG struct ctk_window *w)
00339 {
00340 struct ctk_window *w2;
00341
00342
00343 for(w2 = windows; w2 != w && w2 != NULL; w2 = w2->next);
00344 if(w2 == NULL) {
00345
00346
00347 w->next = windows;
00348 if(windows != NULL) {
00349 windows->prev = w;
00350 }
00351 windows = w;
00352 w->prev = NULL;
00353 } else {
00354
00355
00356 if(w != windows) {
00357 if(w->next != NULL) {
00358 w->next->prev = w->prev;
00359 }
00360 if(w->prev != NULL) {
00361 w->prev->next = w->next;
00362 }
00363 w->next = windows;
00364 windows->prev = w;
00365 windows = w;
00366 w->prev = NULL;
00367 }
00368 }
00369
00370 #if CTK_CONF_MENUS
00371
00372 make_desktopmenu();
00373 #endif
00374
00375 redraw |= REDRAW_ALL;
00376 }
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386 void
00387 ctk_window_close(struct ctk_window *w)
00388 {
00389 static struct ctk_window *w2;
00390
00391 if(w == NULL) {
00392 return;
00393 }
00394
00395
00396
00397 if(w == windows) {
00398 windows = w->next;
00399 if(windows != NULL) {
00400 windows->prev = NULL;
00401 }
00402 w->next = w->prev = NULL;
00403 } else {
00404
00405
00406
00407 for(w2 = windows; w2 != NULL && w2->next != w; w2 = w2->next);
00408
00409 if(w2 == NULL) {
00410
00411
00412 return;
00413 }
00414
00415 if(w->next != NULL) {
00416 w->next->prev = w->prev;
00417 }
00418 w2->next = w->next;
00419
00420 w->next = w->prev = NULL;
00421 }
00422
00423 #if CTK_CONF_MENUS
00424
00425 make_desktopmenu();
00426 #endif
00427 redraw |= REDRAW_ALL;
00428 }
00429
00430
00431
00432
00433
00434 static void
00435 make_windowbuttons(CC_REGISTER_ARG struct ctk_window *window)
00436 {
00437 unsigned char placement;
00438
00439 if(ctk_draw_windowtitle_height >= 2) {
00440 placement = -1 - ctk_draw_windowtitle_height/2;
00441 } else {
00442 placement = -1;
00443 }
00444 #if CTK_CONF_WINDOWMOVE
00445 CTK_BUTTON_NEW(&window->titlebutton, 0, placement,
00446 window->titlelen, window->title);
00447 #else
00448 CTK_LABEL_NEW(&window->titlebutton, 0, placement,
00449 window->titlelen, 1, window->title);
00450 #endif
00451 CTK_WIDGET_ADD(window, &window->titlebutton);
00452
00453
00454 #if CTK_CONF_WINDOWCLOSE
00455 CTK_BUTTON_NEW(&window->closebutton, window->w - 3, placement,
00456 1, "x");
00457 #else
00458 CTK_LABEL_NEW(&window->closebutton, window->w - 4, placement,
00459 3, 1, " ");
00460 #endif
00461 CTK_WIDGET_ADD(window, &window->closebutton);
00462 }
00463
00464
00465
00466
00467
00468
00469
00470 void
00471 ctk_window_clear(struct ctk_window *w)
00472 {
00473 w->active = w->inactive = w->focused = NULL;
00474
00475 make_windowbuttons(w);
00476 }
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487 void
00488 ctk_menu_add(struct ctk_menu *menu)
00489 {
00490 #if CTK_CONF_MENUS
00491 struct ctk_menu *m;
00492
00493 if(lastmenu == NULL) {
00494 lastmenu = menu;
00495 }
00496
00497 for(m = menus.menus; m->next != NULL; m = m->next) {
00498 if(m == menu) {
00499 return;
00500 }
00501 }
00502 m->next = menu;
00503 menu->next = NULL;
00504
00505 redraw |= REDRAW_MENUPART;
00506 #endif
00507 }
00508
00509
00510
00511
00512
00513
00514
00515 void
00516 ctk_menu_remove(struct ctk_menu *menu)
00517 {
00518 #if CTK_CONF_MENUS
00519 struct ctk_menu *m;
00520
00521 for(m = menus.menus; m->next != NULL; m = m->next) {
00522 if(m->next == menu) {
00523 m->next = menu->next;
00524 if(menu == lastmenu) {
00525 lastmenu = NULL;
00526 }
00527 redraw |= REDRAW_MENUPART;
00528 return;
00529 }
00530 }
00531 #endif
00532 }
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542 static void CC_FASTCALL
00543 do_redraw_all(unsigned char clipy1, unsigned char clipy2)
00544 {
00545 struct ctk_window *w;
00546 static struct ctk_widget *widget;
00547 unsigned char focus;
00548
00549 if(mode != CTK_MODE_NORMAL &&
00550 mode != CTK_MODE_WINDOWMOVE) {
00551 return;
00552 }
00553
00554 ctk_draw_clear(clipy1, clipy2);
00555
00556
00557 for(widget = desktop_window.active;
00558 widget != NULL; widget = widget->next) {
00559 ctk_draw_widget(widget, windows != NULL? 0: CTK_FOCUS_WINDOW, clipy1, clipy2);
00560 }
00561
00562
00563 if(windows != NULL) {
00564
00565 for(w = windows; w->next != NULL; w = w->next);
00566
00567
00568 for(; w != windows; w = w->prev) {
00569 ctk_draw_clear_window(w, 0, clipy1, clipy2);
00570 ctk_draw_window(w, 0, clipy1, clipy2, 1);
00571 }
00572
00573
00574 focus = mode == CTK_MODE_WINDOWMOVE?
00575 CTK_FOCUS_WIDGET|CTK_FOCUS_WINDOW:
00576 CTK_FOCUS_WINDOW;
00577 ctk_draw_clear_window(windows, focus, clipy1, clipy2);
00578 ctk_draw_window(windows, focus, clipy1, clipy2, 1);
00579 }
00580
00581
00582 if(dialog != NULL) {
00583 ctk_draw_dialog(dialog);
00584 }
00585
00586 #if CTK_CONF_MENUS
00587 ctk_draw_menus(&menus);
00588 #endif
00589 }
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601 void
00602 ctk_desktop_redraw(struct ctk_desktop *d)
00603 {
00604 if(PROCESS_CURRENT() == &ctk_process) {
00605 if(mode == CTK_MODE_NORMAL ||
00606 mode == CTK_MODE_WINDOWMOVE) {
00607
00608 do_redraw_all(1, height);
00609 }
00610 } else {
00611 height = ctk_draw_height();
00612 width = ctk_draw_width();
00613
00614 redraw |= REDRAW_ALL;
00615 }
00616 }
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627 void
00628 ctk_window_redraw(struct ctk_window *w)
00629 {
00630
00631
00632 if(mode != CTK_MODE_NORMAL) {
00633 return;
00634 }
00635
00636 if(w == dialog) {
00637 ctk_draw_dialog(w);
00638 } else if(dialog == NULL &&
00639 #if CTK_CONF_MENUS
00640 menus.open == NULL &&
00641 #endif
00642 windows == w) {
00643 ctk_draw_window(w, CTK_FOCUS_WINDOW,
00644 0, height, 0);
00645 }
00646 }
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657 static void
00658 window_new(CC_REGISTER_ARG struct ctk_window *window,
00659 unsigned char w, unsigned char h,
00660 char *title)
00661 {
00662
00663 if(w >= width - 2) {
00664 window->x = 0;
00665 } else {
00666 window->x = (width - w - 2) / 2;
00667 }
00668 if(h >= height - 2 - ctk_draw_windowtitle_height) {
00669 window->y = 0;
00670 } else {
00671 window->y = (height - h - 2 - ctk_draw_windowtitle_height) / 2;
00672 }
00673
00674 window->w = w;
00675 window->h = h;
00676 window->title = title;
00677 if(title != NULL) {
00678 window->titlelen = strlen(title);
00679 } else {
00680 window->titlelen = 0;
00681 }
00682 window->next = window->prev = NULL;
00683
00684 window->owner = PROCESS_CURRENT();
00685 window->active = window->inactive = window->focused = NULL;
00686 }
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706 void
00707 ctk_window_new(struct ctk_window *window,
00708 unsigned char w, unsigned char h,
00709 char *title)
00710 {
00711 window_new(window, w, h, title);
00712
00713 make_windowbuttons(window);
00714 }
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728 void
00729 ctk_dialog_new(CC_REGISTER_ARG struct ctk_window *dialog,
00730 unsigned char w, unsigned char h)
00731 {
00732 window_new(dialog, w, h, NULL);
00733 }
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746 void
00747 ctk_menu_new(CC_REGISTER_ARG struct ctk_menu *menu,
00748 char *title)
00749 {
00750 #if CTK_CONF_MENUS
00751 menu->next = NULL;
00752 menu->title = title;
00753 menu->titlelen = strlen(title);
00754 menu->active = 0;
00755 menu->nitems = 0;
00756 #endif
00757 }
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772 unsigned char
00773 ctk_menuitem_add(CC_REGISTER_ARG struct ctk_menu *menu,
00774 char *name)
00775 {
00776 #if CTK_CONF_MENUS
00777 if(menu->nitems == CTK_CONF_MAXMENUITEMS) {
00778 return 0;
00779 }
00780 menu->items[menu->nitems].title = name;
00781 menu->items[menu->nitems].titlelen = strlen(name);
00782 return menu->nitems++;
00783 #else
00784 return 0;
00785 #endif
00786 }
00787
00788
00789
00790
00791
00792
00793
00794
00795 static void CC_FASTCALL
00796 add_redrawwidget(struct ctk_widget *w)
00797 {
00798 static unsigned char i;
00799
00800 if(redraw_widgetptr == MAX_REDRAWWIDGETS) {
00801 redraw |= REDRAW_FOCUS;
00802 } else {
00803 redraw |= REDRAW_WIDGETS;
00804
00805
00806 for(i = 0; i < redraw_widgetptr; ++i) {
00807 if(redraw_widgets[i] == w) {
00808 return;
00809 }
00810 }
00811 redraw_widgets[redraw_widgetptr++] = w;
00812 }
00813 }
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826 static void
00827 widget_redraw(struct ctk_widget *widget)
00828 {
00829 struct ctk_window *window;
00830
00831 if(mode != CTK_MODE_NORMAL || widget == NULL) {
00832 return;
00833 }
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843 #if CTK_CONF_MENUS
00844 if(menus.open == NULL)
00845 #endif
00846 {
00847 window = widget->window;
00848 if(window == dialog) {
00849 ctk_draw_widget(widget, CTK_FOCUS_DIALOG, 0, height);
00850 } else if(dialog == NULL &&
00851 (window == windows ||
00852 window == &desktop_window)) {
00853 ctk_draw_widget(widget, CTK_FOCUS_WINDOW, 0, height);
00854 }
00855 }
00856 }
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872 void
00873 ctk_widget_redraw(struct ctk_widget *widget)
00874 {
00875 if(mode != CTK_MODE_NORMAL || widget == NULL) {
00876 return;
00877 }
00878
00879
00880
00881 add_redrawwidget(widget);
00882 }
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895 void CC_FASTCALL
00896 ctk_widget_add(CC_REGISTER_ARG struct ctk_window *window,
00897 CC_REGISTER_ARG struct ctk_widget *widget)
00898 {
00899 if(widget->type == CTK_WIDGET_LABEL ||
00900 widget->type == CTK_WIDGET_SEPARATOR) {
00901 widget->next = window->inactive;
00902 window->inactive = widget;
00903 widget->window = window;
00904 } else {
00905 widget->next = window->active;
00906 window->active = widget;
00907 widget->window = window;
00908
00909
00910
00911 }
00912 }
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923 unsigned char
00924 ctk_desktop_width(struct ctk_desktop *d)
00925 {
00926 return ctk_draw_width();
00927 }
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938 unsigned char
00939 ctk_desktop_height(struct ctk_desktop *d)
00940 {
00941 return ctk_draw_height();
00942 }
00943
00944
00945
00946
00947
00948
00949
00950 static void CC_FASTCALL
00951 select_widget(struct ctk_widget *focus)
00952 {
00953 struct ctk_window *window;
00954
00955 window = focus->window;
00956
00957 if(focus != window->focused) {
00958 window->focused = focus;
00959
00960
00961
00962 if(window->focused->type == CTK_WIDGET_HYPERLINK) {
00963 process_post(window->owner, ctk_signal_hyperlink_hover, window->focused);
00964 } else if(window->focused->type == CTK_WIDGET_BUTTON) {
00965 process_post(window->owner, ctk_signal_button_hover, window->focused);
00966 }
00967
00968 add_redrawwidget(window->focused);
00969
00970 process_post(focus->window->owner, ctk_signal_widget_select, focus);
00971
00972 }
00973
00974 }
00975
00976 #define UP 0
00977 #define DOWN 1
00978 #define LEFT 2
00979 #define RIGHT 3
00980 static void CC_FASTCALL
00981 switch_focus_widget(unsigned char direction)
00982 {
00983 register struct ctk_window *window;
00984 register struct ctk_widget *focus;
00985 struct ctk_widget *widget;
00986
00987
00988 if(dialog != NULL) {
00989 window = dialog;
00990 } else {
00991 window = windows;
00992 }
00993
00994
00995
00996 if(window == NULL) {
00997 window = &desktop_window;
00998 }
00999
01000 focus = window->focused;
01001 if(focus == NULL) {
01002 focus = window->active;
01003 if(focus == NULL) {
01004 return;
01005 }
01006 }
01007 add_redrawwidget(focus);
01008
01009 if((direction & 1) == 0) {
01010
01011 focus = focus->next;
01012 } else {
01013
01014 for(widget = window->active;
01015 widget != NULL; widget = widget->next) {
01016 if(widget->next == focus) {
01017 break;
01018 }
01019 }
01020 focus = widget;
01021 if(focus == NULL) {
01022 if(window->active != NULL) {
01023 for(focus = window->active;
01024 focus->next != NULL; focus = focus->next);
01025 }
01026 }
01027 }
01028 if(focus == NULL) {
01029 focus = window->active;
01030 }
01031
01032 select_widget(focus);
01033 }
01034
01035 #if CTK_CONF_MENUS
01036 static void
01037 switch_open_menu(unsigned char rightleft)
01038 {
01039 struct ctk_menu *menu;
01040
01041 if(rightleft == 0) {
01042
01043 for(menu = menus.menus; menu != NULL; menu = menu->next) {
01044 if(menu->next == menus.open) {
01045 break;
01046 }
01047 }
01048 lastmenu = menus.open;
01049 menus.open = menu;
01050 if(menus.open == NULL) {
01051 for(menu = menus.menus;
01052 menu->next != NULL; menu = menu->next);
01053 menus.open = menu;
01054 }
01055 } else {
01056
01057 lastmenu = menus.open;
01058 menus.open = menus.open->next;
01059 if(menus.open == NULL) {
01060 menus.open = menus.menus;
01061 }
01062 }
01063
01064 menus.open->active = 0;
01065
01066
01067
01068
01069
01070
01071 }
01072
01073 static void
01074 switch_menu_item(unsigned char updown)
01075 {
01076 register struct ctk_menu *m;
01077
01078 m = menus.open;
01079
01080 if(updown == 0) {
01081
01082 if(m->active == 0) {
01083 m->active = m->nitems - 1;
01084 } else {
01085 --m->active;
01086 if(m->items[m->active].title[0] == '-') {
01087 --m->active;
01088 }
01089 }
01090 } else {
01091
01092 if(m->active >= m->nitems - 1) {
01093 m->active = 0;
01094 } else {
01095 ++m->active;
01096 if(m->items[m->active].title[0] == '-') {
01097 ++m->active;
01098 }
01099 }
01100 }
01101
01102 }
01103 #endif
01104
01105 static unsigned char CC_FASTCALL
01106 activate(CC_REGISTER_ARG struct ctk_widget *w)
01107 {
01108 if(w->type == CTK_WIDGET_BUTTON) {
01109 if(w == (struct ctk_widget *)&windows->closebutton) {
01110 #if CTK_CONF_WINDOWCLOSE
01111 process_post(w->window->owner, ctk_signal_window_close, windows);
01112 ctk_window_close(windows);
01113 return REDRAW_ALL;
01114 #endif
01115 } else if(w == (struct ctk_widget *)&windows->titlebutton) {
01116 #if CTK_CONF_WINDOWMOVE
01117 mode = CTK_MODE_WINDOWMOVE;
01118 return REDRAW_ALL;
01119 #endif
01120 } else {
01121 process_post(w->window->owner, ctk_signal_widget_activate, w);
01122 }
01123 #if CTK_CONF_ICONS
01124 } else if(w->type == CTK_WIDGET_ICON) {
01125 if(w->widget.icon.owner != PROCESS_NONE) {
01126 process_post(w->widget.icon.owner, ctk_signal_widget_activate, w);
01127 } else {
01128 process_post(w->window->owner, ctk_signal_widget_activate, w);
01129 }
01130 #endif
01131 } else if(w->type == CTK_WIDGET_HYPERLINK) {
01132 process_post(PROCESS_BROADCAST, ctk_signal_hyperlink_activate, w);
01133 } else if(w->type == CTK_WIDGET_TEXTENTRY) {
01134 if(w->widget.textentry.state == CTK_TEXTENTRY_NORMAL) {
01135 w->widget.textentry.state = CTK_TEXTENTRY_EDIT;
01136 textentry_input(0, (struct ctk_textentry *)w);
01137 } else {
01138 w->widget.textentry.state = CTK_TEXTENTRY_NORMAL;
01139 process_post(w->window->owner, ctk_signal_widget_activate, w);
01140 }
01141 add_redrawwidget(w);
01142 return REDRAW_WIDGETS;
01143 } else {
01144 process_post(w->window->owner, ctk_signal_widget_activate, w);
01145 }
01146 return REDRAW_NONE;
01147 }
01148
01149 static void CC_FASTCALL
01150 textentry_input(ctk_arch_key_t c,
01151 CC_REGISTER_ARG struct ctk_textentry *t)
01152 {
01153 register char *cptr, *cptr2;
01154 static unsigned char len, txpos, typos, tlen;
01155
01156 if(t->input != NULL && t->input(c, t)) {
01157 return;
01158 }
01159
01160 txpos = t->xpos;
01161 typos = t->ypos;
01162 tlen = t->len;
01163
01164 cptr = &t->text[txpos + typos * (tlen + 1)];
01165
01166 switch(c) {
01167 case CH_CURS_LEFT:
01168 if(txpos > 0) {
01169 --txpos;
01170 }
01171 break;
01172
01173 case CH_CURS_RIGHT:
01174 if(txpos < tlen - 1 && *cptr != 0) {
01175 ++txpos;
01176 }
01177 break;
01178
01179 case CH_CURS_UP:
01180 txpos = 0;
01181 break;
01182
01183 case 0:
01184 case CH_CURS_DOWN:
01185 txpos = strlen(t->text);
01186 if(txpos == tlen) {
01187 --txpos;
01188 }
01189 break;
01190
01191 case CH_ENTER:
01192
01193 activate((struct ctk_widget *)t);
01194 switch_focus_widget(DOWN);
01195 break;
01196
01197 case CTK_CONF_WIDGETDOWN_KEY:
01198 t->state = CTK_TEXTENTRY_NORMAL;
01199 switch_focus_widget(DOWN);
01200 break;
01201 case CTK_CONF_WIDGETUP_KEY:
01202 t->state = CTK_TEXTENTRY_NORMAL;
01203 switch_focus_widget(UP);
01204 break;
01205
01206 default:
01207 len = tlen - txpos;
01208 if(c == CH_DEL) {
01209 if(len == 1 && *cptr != 0) {
01210 *cptr = 0;
01211 } else {
01212 if(txpos > 0) {
01213 --txpos;
01214 strcpy(cptr - 1, cptr);
01215 }
01216 }
01217 } else {
01218 if(ctk_arch_isprint(c)) {
01219 if(len > 1) {
01220 cptr2 = cptr + len - 1;
01221 while(cptr2 > cptr) {
01222 *cptr2 = *(cptr2 - 1);
01223 --cptr2;
01224 }
01225 ++txpos;
01226 }
01227 *cptr = c;
01228 }
01229 }
01230 break;
01231 }
01232
01233 t->xpos = txpos;
01234 t->ypos = typos;
01235 }
01236
01237 #if CTK_CONF_MENUS
01238 static unsigned char
01239 activate_menu(void)
01240 {
01241 struct ctk_window *w;
01242
01243 lastmenu = menus.open;
01244 if(menus.open == &desktopmenu) {
01245 for(w = windows; w != NULL; w = w->next) {
01246 if(w->title == desktopmenu.items[desktopmenu.active].title) {
01247 ctk_window_open(w);
01248 menus.open = NULL;
01249 return REDRAW_ALL;
01250 }
01251 }
01252 } else {
01253 process_post(PROCESS_BROADCAST, ctk_signal_menu_activate, menus.open);
01254 }
01255 menus.open = NULL;
01256 return REDRAW_MENUPART;
01257 }
01258
01259 static unsigned char
01260 menus_input(ctk_arch_key_t c)
01261 {
01262
01263 if(menus.open->nitems > maxnitems) {
01264 maxnitems = menus.open->nitems;
01265 }
01266
01267
01268 switch(c) {
01269 case CH_CURS_RIGHT:
01270 switch_open_menu(1);
01271
01272 return REDRAW_MENUPART;
01273
01274 case CH_CURS_DOWN:
01275 switch_menu_item(1);
01276 return REDRAW_MENUS;
01277
01278 case CH_CURS_LEFT:
01279 switch_open_menu(0);
01280 return REDRAW_MENUPART;
01281
01282 case CH_CURS_UP:
01283 switch_menu_item(0);
01284 return REDRAW_MENUS;
01285
01286 case CH_ENTER:
01287 return activate_menu();
01288
01289 case CTK_CONF_MENU_KEY:
01290 lastmenu = menus.open;
01291 menus.open = NULL;
01292 return REDRAW_MENUPART;
01293 }
01294
01295 return REDRAW_NONE;
01296 }
01297 #endif
01298
01299 static void
01300 handle_timer(void)
01301 {
01302 if(mode == CTK_MODE_NORMAL) {
01303 ++screensaver_timer;
01304 if(screensaver_timer >= ctk_screensaver_timeout) {
01305 #if CTK_CONF_SCREENSAVER
01306 process_post(PROCESS_BROADCAST, ctk_signal_screensaver_start, NULL);
01307 #ifdef CTK_SCREENSAVER_INIT
01308 CTK_SCREENSAVER_INIT();
01309 #endif
01310
01311 #endif
01312 screensaver_timer = 0;
01313 }
01314 }
01315 }
01316
01317 static void
01318 unfocus_widget(CC_REGISTER_ARG struct ctk_widget *w)
01319 {
01320 if(w != NULL) {
01321 redraw |= REDRAW_WIDGETS;
01322 add_redrawwidget(w);
01323 if(CTK_WIDGET_TYPE(w) == CTK_WIDGET_TEXTENTRY) {
01324 ((struct ctk_textentry *)w)->state =
01325 CTK_TEXTENTRY_NORMAL;
01326 }
01327 w->window->focused = NULL;
01328 }
01329 }
01330
01331 PROCESS_THREAD(ctk_process, ev, data)
01332 {
01333 static ctk_arch_key_t c;
01334 static unsigned char i;
01335 register struct ctk_window *window;
01336 register struct ctk_widget *widget;
01337 register struct ctk_widget **widgetptr;
01338 #if CTK_CONF_MOUSE_SUPPORT
01339 static unsigned char mxc, myc, mouse_button_changed, mouse_moved,
01340 mouse_clicked;
01341 static unsigned char menux;
01342 register struct ctk_menu *menu;
01343
01344 #endif
01345
01346
01347 PROCESS_BEGIN();
01348
01349 windows = NULL;
01350 dialog = NULL;
01351
01352 #if CTK_CONF_MENUS
01353 ctk_menu_new(&desktopmenu, "Desktop");
01354 make_desktopmenu();
01355 menus.menus = menus.desktopmenu = &desktopmenu;
01356 #endif
01357
01358 #if CTK_CONF_MOUSE_SUPPORT
01359 ctk_mouse_init();
01360 ctk_mouse_show();
01361 #endif
01362
01363 ctk_draw_init();
01364
01365 height = ctk_draw_height();
01366 width = ctk_draw_width();
01367
01368 desktop_window.active = NULL;
01369 desktop_window.owner = &ctk_process;
01370
01371 ctk_signal_keypress = process_alloc_event();
01372
01373 ctk_signal_button_activate =
01374 ctk_signal_widget_activate = process_alloc_event();
01375
01376 ctk_signal_button_hover =
01377 ctk_signal_hyperlink_hover =
01378 ctk_signal_widget_select = process_alloc_event();
01379
01380 ctk_signal_hyperlink_activate = process_alloc_event();
01381
01382 ctk_signal_menu_activate = process_alloc_event();
01383 ctk_signal_window_close = process_alloc_event();
01384
01385 ctk_signal_pointer_move = process_alloc_event();
01386 ctk_signal_pointer_button = process_alloc_event();
01387
01388
01389 #if CTK_CONF_SCREENSAVER
01390 ctk_signal_screensaver_start = process_alloc_event();
01391 ctk_signal_screensaver_stop = process_alloc_event();
01392 #endif
01393
01394
01395 mode = CTK_MODE_NORMAL;
01396
01397 iconx = ICONX_START;
01398 icony = ICONY_START;
01399
01400 redraw = REDRAW_ALL;
01401
01402 timer_set(&timer, CLOCK_SECOND);
01403
01404 while(1) {
01405 process_poll(&ctk_process);
01406 PROCESS_WAIT_EVENT();
01407
01408 if(timer_expired(&timer)) {
01409 timer_reset(&timer);
01410 handle_timer();
01411 }
01412
01413 #if CTK_CONF_MENUS
01414 if(menus.open != NULL) {
01415 maxnitems = menus.open->nitems;
01416 } else {
01417 maxnitems = 0;
01418 }
01419 #endif
01420
01421 #if CTK_CONF_MOUSE_SUPPORT
01422 mouse_button_changed = mouse_moved = mouse_clicked = 0;
01423
01424
01425 if(ctk_mouse_button() != mouse_button) {
01426 mouse_button = ctk_mouse_button();
01427 mouse_button_changed = 1;
01428 if(mouse_button == 0) {
01429 mouse_clicked = 1;
01430 }
01431 }
01432
01433
01434 if(ctk_mouse_x() != mouse_x ||
01435 ctk_mouse_y() != mouse_y) {
01436 mouse_x = ctk_mouse_x();
01437 mouse_y = ctk_mouse_y();
01438 mouse_moved = 1;
01439 }
01440
01441 mxc = ctk_mouse_xtoc(mouse_x);
01442 myc = ctk_mouse_ytoc(mouse_y);
01443 #endif
01444
01445
01446 #if CTK_CONF_SCREENSAVER
01447 if(mode == CTK_MODE_SCREENSAVER) {
01448 if(ctk_arch_keyavail()
01449 #if CTK_CONF_MOUSE_SUPPORT
01450 || mouse_moved || mouse_button_changed
01451 #endif
01452 ) {
01453 process_post(PROCESS_BROADCAST, ctk_signal_screensaver_stop, NULL);
01454 mode = CTK_MODE_NORMAL;
01455 }
01456 } else
01457 #endif
01458 if(mode == CTK_MODE_NORMAL) {
01459 #if CTK_CONF_MOUSE_SUPPORT
01460
01461
01462
01463 if(mouse_moved || mouse_button_changed) {
01464 ctk_mouse_show();
01465 screensaver_timer = 0;
01466
01467 if(myc == 0) {
01468
01469
01470 if(mouse_clicked) {
01471 static unsigned char titlelen;
01472
01473
01474
01475
01476
01477
01478 menux = 1;
01479 for(menu = menus.menus->next;
01480 menu != NULL; menu = menu->next) {
01481 titlelen = menu->titlelen;
01482 if(mxc >= menux && mxc <= menux + titlelen) {
01483 break;
01484 }
01485 menux += titlelen;
01486 }
01487
01488
01489 if(mxc >= width - 7 &&
01490 mxc <= width - 1) {
01491 menu = &desktopmenu;
01492 }
01493
01494 menus.open = menu;
01495 redraw |= REDRAW_MENUPART;
01496 }
01497 } else {
01498 --myc;
01499
01500 if(menus.open != NULL) {
01501 static unsigned char nitems;
01502
01503
01504
01505
01506
01507 if(menus.open == &desktopmenu) {
01508 menux = width - CTK_CONF_MENUWIDTH;
01509 } else {
01510 menux = 1;
01511 for(menu = menus.menus->next; menu != menus.open;
01512 menu = menu->next) {
01513 menux += menu->titlelen;
01514 }
01515 }
01516
01517 nitems = menus.open->nitems;
01518
01519
01520 if(mxc >= menux && mxc <= menux + CTK_CONF_MENUWIDTH) {
01521 if(myc <= nitems) {
01522 menus.open->active = myc;
01523 } else {
01524 menus.open->active = nitems - 1;
01525 }
01526 }
01527
01528 if(mouse_clicked) {
01529 if(mxc >= menux && mxc <= menux + CTK_CONF_MENUWIDTH &&
01530 myc <= nitems) {
01531 redraw |= activate_menu();
01532 } else {
01533 lastmenu = menus.open;
01534 menus.open = NULL;
01535 redraw |= REDRAW_MENUPART;
01536 }
01537 } else {
01538 redraw |= REDRAW_MENUS;
01539 }
01540 } else {
01541
01542
01543
01544 if(dialog != NULL) {
01545 window = dialog;
01546 } else {
01547 for(window = windows; window != NULL;
01548 window = window->next) {
01549
01550
01551 if(mxc >= window->x &&
01552 mxc <= window->x + window->w +
01553 2 * ctk_draw_windowborder_width &&
01554 myc >= window->y &&
01555 myc <= window->y + window->h +
01556 ctk_draw_windowtitle_height +
01557 ctk_draw_windowborder_height) {
01558 break;
01559 }
01560 }
01561 }
01562
01563
01564
01565
01566
01567 if(window == NULL) {
01568 window = &desktop_window;
01569 }
01570
01571
01572
01573
01574
01575 if(windows != NULL &&
01576 window != windows &&
01577 windows->focused != NULL){
01578
01579
01580
01581 unfocus_widget(windows->focused);
01582 }
01583
01584 if(window != NULL) {
01585
01586
01587 if(dialog == NULL &&
01588 window != &desktop_window &&
01589 window != windows &&
01590 mouse_clicked) {
01591
01592 ctk_window_open(window);
01593 redraw |= REDRAW_ALL;
01594 } else {
01595
01596
01597
01598
01599 mxc = mxc - window->x - ctk_draw_windowborder_width;
01600 myc = myc - window->y - ctk_draw_windowtitle_height;
01601
01602
01603
01604
01605 for(widget = window->active; widget != NULL;
01606 widget = widget->next) {
01607
01608 if(mxc >= widget->x &&
01609 mxc <= widget->x + widget->w &&
01610 (myc == widget->y ||
01611 ((widget->type == CTK_WIDGET_BITMAP ||
01612
01613 widget->type == CTK_WIDGET_ICON) &&
01614 (myc >= widget->y &&
01615 myc <= widget->y +
01616 ((struct ctk_bitmap *)widget)->h)))) {
01617 break;
01618 }
01619 }
01620
01621
01622
01623
01624
01625 if(mouse_moved &&
01626 (window != &desktop_window ||
01627 windows == NULL)) {
01628
01629 process_post(window->owner, ctk_signal_pointer_move, NULL);
01630
01631
01632
01633
01634 if(window->focused != NULL &&
01635 widget != window->focused) {
01636
01637
01638
01639
01640
01641
01642
01643 unfocus_widget(window->focused);
01644 }
01645 redraw |= REDRAW_WIDGETS;
01646 if(widget != NULL) {
01647 select_widget(widget);
01648 }
01649 }
01650
01651 if(mouse_button_changed) {
01652 process_post(window->owner, ctk_signal_pointer_button,
01653 (process_data_t)mouse_button);
01654 if(mouse_clicked && widget != NULL) {
01655 select_widget(widget);
01656 redraw |= activate(widget);
01657 }
01658 }
01659 }
01660 }
01661 }
01662 }
01663 }
01664 #endif
01665
01666 while(ctk_arch_keyavail()) {
01667
01668 ctk_mouse_hide();
01669
01670 screensaver_timer = 0;
01671
01672 c = ctk_arch_getkey();
01673
01674 if(dialog != NULL) {
01675 window = dialog;
01676 } else if(windows != NULL) {
01677 window = windows;
01678 } else {
01679 window = &desktop_window;
01680 }
01681
01682 widget = window->focused;
01683
01684 if(widget != NULL &&
01685 widget->type == CTK_WIDGET_TEXTENTRY &&
01686 widget->widget.textentry.state == CTK_TEXTENTRY_EDIT) {
01687 textentry_input(c, (struct ctk_textentry *)widget);
01688 add_redrawwidget(widget);
01689 #if CTK_CONF_MENUS
01690 } else if(menus.open != NULL) {
01691 redraw |= menus_input(c);
01692 #endif
01693 } else {
01694 switch(c) {
01695 case CTK_CONF_WIDGETDOWN_KEY:
01696 switch_focus_widget(DOWN);
01697 break;
01698 case CTK_CONF_WIDGETUP_KEY:
01699 switch_focus_widget(UP);
01700 break;
01701 #if CTK_CONF_MENUS
01702 case CTK_CONF_MENU_KEY:
01703 if(dialog == NULL) {
01704 if(lastmenu == NULL) {
01705 menus.open = menus.menus;
01706 } else {
01707 menus.open = lastmenu;
01708 }
01709 menus.open->active = 0;
01710 redraw |= REDRAW_MENUS;
01711 }
01712 break;
01713 #endif
01714 case CTK_CONF_WINDOWSWITCH_KEY:
01715 if(windows != NULL) {
01716 for(window = windows; window->next != NULL;
01717 window = window->next);
01718 ctk_window_open(window);
01719 }
01720 break;
01721 default:
01722
01723 if(c == CH_ENTER &&
01724 widget != NULL) {
01725 redraw |= activate(widget);
01726 } else {
01727 if(widget != NULL &&
01728 widget->type == CTK_WIDGET_TEXTENTRY) {
01729 if(widget->widget.textentry.state == CTK_TEXTENTRY_NORMAL) {
01730 widget->widget.textentry.state = CTK_TEXTENTRY_EDIT;
01731 textentry_input(0, (struct ctk_textentry *)widget);
01732 }
01733 textentry_input(c, (struct ctk_textentry *)widget);
01734 add_redrawwidget(widget);
01735 } else {
01736
01737 unfocus_widget(window->focused);
01738 process_post_synch(window->owner, ctk_signal_keypress,
01739 (process_data_t)c);
01740 }
01741 }
01742 break;
01743 }
01744 }
01745
01746 #if 0
01747 if(redraw & REDRAW_WIDGETS) {
01748 widgetptr = redraw_widgets;
01749 for(i = 0; i < MAX_REDRAWWIDGETS; ++i) {
01750 widget_redraw(*widgetptr);
01751 *widgetptr = NULL;
01752 ++widgetptr;
01753 }
01754 redraw &= ~REDRAW_WIDGETS;
01755 redraw_widgetptr = 0;
01756 }
01757 #endif
01758 }
01759 #if CTK_CONF_WINDOWMOVE
01760 } else if(mode == CTK_MODE_WINDOWMOVE) {
01761
01762 redraw = 0;
01763
01764 window = windows;
01765
01766 #if CTK_CONF_MOUSE_SUPPORT
01767
01768
01769 if(mouse_moved) {
01770
01771 if(window->w + mxc + 2 >= width) {
01772 window->x = width - 2 - window->w;
01773 } else {
01774 window->x = mxc;
01775 }
01776
01777 if(window->h + myc + ctk_draw_windowtitle_height +
01778 ctk_draw_windowborder_height >= height) {
01779 window->y = height - window->h -
01780 ctk_draw_windowtitle_height - ctk_draw_windowborder_height;
01781 } else {
01782 window->y = myc;
01783 }
01784 if(window->y > 0) {
01785 --window->y;
01786 }
01787
01788 redraw = REDRAW_ALL;
01789 }
01790
01791
01792
01793 if(mouse_button_changed &&
01794 mouse_button == 0) {
01795 mode = CTK_MODE_NORMAL;
01796 redraw = REDRAW_ALL;
01797 }
01798 #endif
01799
01800 while(mode == CTK_MODE_WINDOWMOVE && ctk_arch_keyavail()) {
01801
01802 screensaver_timer = 0;
01803
01804 c = ctk_arch_getkey();
01805
01806 switch(c) {
01807 case CH_CURS_RIGHT:
01808 ++window->x;
01809 if(window->x + window->w + 1 >= width) {
01810 --window->x;
01811 }
01812 redraw = REDRAW_ALL;
01813 break;
01814 case CH_CURS_LEFT:
01815 if(window->x > 0) {
01816 --window->x;
01817 }
01818 redraw = REDRAW_ALL;
01819 break;
01820 case CH_CURS_DOWN:
01821 ++window->y;
01822 if(window->y + window->h + 2 >= height) {
01823 --window->y;
01824 }
01825 redraw = REDRAW_ALL;
01826 break;
01827 case CH_CURS_UP:
01828 if(window->y > 0) {
01829 --window->y;
01830 }
01831 redraw = REDRAW_ALL;
01832 break;
01833 default:
01834 mode = CTK_MODE_NORMAL;
01835 redraw = REDRAW_ALL;
01836 break;
01837 }
01838 }
01839 #endif
01840 }
01841
01842 if(redraw & REDRAW_ALL) {
01843 do_redraw_all(1, height);
01844 #if CTK_CONF_MENUS
01845 } else if(redraw & REDRAW_MENUPART) {
01846 do_redraw_all(1, maxnitems + 1);
01847 } else if(redraw & REDRAW_MENUS) {
01848 ctk_draw_menus(&menus);
01849 #endif
01850 } else if(redraw & REDRAW_FOCUS) {
01851 if(dialog != NULL) {
01852 ctk_window_redraw(dialog);
01853 } else if(windows != NULL) {
01854 ctk_window_redraw(windows);
01855 } else {
01856 ctk_window_redraw(&desktop_window);
01857 }
01858 } else if(redraw & REDRAW_WIDGETS) {
01859 widgetptr = redraw_widgets;
01860 for(i = 0; i < MAX_REDRAWWIDGETS; ++i) {
01861 widget_redraw(*widgetptr);
01862 *widgetptr = NULL;
01863 ++widgetptr;
01864 }
01865 }
01866 redraw = 0;
01867 redraw_widgetptr = 0;
01868 }
01869
01870 PROCESS_END();
01871 }
01872
01873
01874