00001
00012 #define GITK_RENDERER_C
00013 #define GITKR_EVENTLOOP_C
00014
00015 #include "gitkrincludes.h"
00016
00019 GitkDialogPtr cur_context;
00020
00025 void gitkr_event_loop_start(void) {
00026 GitkrTextLayoutPtr layout;
00027
00028 gitk_log_intro();
00029
00030 restart_event_loop=TRUE;
00031
00032 while(restart_event_loop) {
00033 run=TRUE;
00034 restart_event_loop=FALSE;
00035
00036
00037
00038
00039 if(!(cur_context=gitk_context_get_current())) { gitk_log("no current context");return; }
00040 if(!(layout=(GitkrTextLayoutPtr)cur_context->layout)) { gitk_log("current context without layout");return; }
00041
00042 switch(layout->focus) {
00043 case GITK_FOCUS_TYPE_MAIN: handle_dialog_main_widgets(layout);break;
00044 case GITK_FOCUS_TYPE_CTRL: handle_dialog_ctrl_widgets(layout);break;
00045 default:
00046 gitk_log1("unexpected default : %d",layout->focus);
00047 }
00048 gitk_log("leaving event-loop");
00049 if(restart_event_loop) gitk_relayout();
00050 }
00051 gitk_log_outro();
00052 }
00053
00058 void gitkr_event_loop_end(void) {
00059 gitk_log_intro();
00060
00061 run=FALSE;
00062 gitk_log_outro();
00063 }
00064
00069 void gitkr_event_loop_restart(void) {
00070 gitk_log_intro();
00071 restart_event_loop=TRUE;
00072 gitkr_event_loop_end();
00073 }
00074
00075
00076
00080 void next_widget(GitkrTextLayoutPtr layout) {
00081 GitkrTextWidgetPtr old_widget,new_widget;
00082
00083 old_widget=&layout->pages[layout->currentPage].widgets[layout->currentWidget];
00084
00085
00086 if(layout->currentWidget<((layout->pages[layout->currentPage].widgetsPerPage)-1)) {
00087 layout->currentWidget++;
00088 }
00089 else {
00090 layout->currentWidget=0;
00091
00092 }
00093 new_widget=&layout->pages[layout->currentPage].widgets[layout->currentWidget];
00094 gitk_dialog_move_focus((GitkWidgetPtr)old_widget,(GitkWidgetPtr)new_widget);
00095 gitkr_dialog_output_layout(cur_context);
00096 }
00097
00101 void prev_widget(GitkrTextLayoutPtr layout) {
00102 GitkrTextWidgetPtr old_widget,new_widget;
00103
00104 old_widget=&layout->pages[layout->currentPage].widgets[layout->currentWidget];
00105 if(layout->currentWidget>0) {
00106 layout->currentWidget--;
00107 }
00108 else {
00109 layout->currentWidget=(layout->pages[layout->currentPage].widgetsPerPage)-1;
00110
00111 }
00112 new_widget=&layout->pages[layout->currentPage].widgets[layout->currentWidget];
00113 gitk_dialog_move_focus((GitkWidgetPtr)old_widget,(GitkWidgetPtr)new_widget);
00114 gitkr_dialog_output_layout(cur_context);
00115 }
00116
00117
00121 void next_page(GitkrTextLayoutPtr layout) {
00122 if(layout->currentPage<(layout->numberOfPages-1)) {
00123 layout->currentPage++;
00124 layout->currentWidget=0;
00125 gitkr_dialog_output_layout(cur_context);
00126 }
00127 else { beep();refresh(); }
00128 }
00129
00133 void prev_page(GitkrTextLayoutPtr layout) {
00134 if(layout->currentPage>0) {
00135 layout->currentPage--;
00136 layout->currentWidget=0;
00137 gitkr_dialog_output_layout(cur_context);
00138 }
00139 else { beep();refresh(); }
00140 }
00141
00142
00146 void handle_dialog_main_widgets(GitkrTextLayoutPtr layout) {
00147 gint key;
00148 GitkEvent event;
00149 GitkrTextWidgetPtr widget;
00150
00151 gitk_log_intro();
00152
00153
00155 widget=&layout->pages[layout->currentPage].widgets[layout->currentWidget];
00156 gitk_dialog_move_focus(NULL,(GitkWidgetPtr)widget);
00157
00158
00159 while(run) {
00160 if((key=gitkr_event_loop_getkey())==ERR) continue;
00161
00162 switch(key) {
00163
00164 case KEY_F10:
00165 case 'x':
00166 case 'X':
00167 event.type=GITK_EVENT_TYPE_ON_CLOSE;
00168 event.data=NULL;
00169 if(gitk_dialog_process_event(NULL,NULL,&event)) run=FALSE;
00170 break;
00171 case KEY_F1:
00172 break;
00173 case KEY_F2:
00174 handle_dialog_ctrl_widgets(layout);
00175 break;
00176
00177 case KEY_DOWN:
00178 case KEY_TAB:
00179 next_widget(layout);
00180
00181 break;
00182 case KEY_UP:
00184 prev_widget(layout);
00185
00186 break;
00187 case KEY_NPAGE:
00188 next_page(layout);
00189
00190 break;
00191 case KEY_PPAGE:
00192 prev_page(layout);
00193
00194 break;
00195
00196 case KEY_RETURN:
00197 case KEY_ENTER:
00198 if((widget=gitkr_layout_get_current_widget(layout))) {
00199 switch(widget->type) {
00200 case GITK_WIDGET_TYPE_ACTION:
00201 if(widget->handle && widget->handle(widget,gitkr_layout_get_current_widget_line(layout))) {
00202 event.type=GITK_EVENT_TYPE_ON_CLICKED;
00203 event.data=NULL;
00204 gitk_dialog_process_event(widget->dialog,widget->id,&event);
00205 next_widget(layout);
00206 }
00207 break;
00208 case GITK_WIDGET_TYPE_CHARACTERINPUT:
00209 case GITK_WIDGET_TYPE_CHARACTERINPUT_ALPHABETIC:
00210 case GITK_WIDGET_TYPE_OPTIONCHOICE:
00211 case GITK_WIDGET_TYPE_OPTIONCHOICE_SINGLE:
00212 case GITK_WIDGET_TYPE_OPTIONCHOICE_SINGLE_COMPACT:
00213 case GITK_WIDGET_TYPE_OPTIONCHOICE_BOOLEAN:
00214 if(widget->handle && widget->handle(widget,gitkr_layout_get_current_widget_line(layout))) {
00215 event.type=GITK_EVENT_TYPE_ON_CHANGED;
00216 event.data=NULL;
00217 gitk_dialog_process_event(widget->dialog,widget->id,&event);
00218 next_widget(layout);
00219 }
00220 break;
00221 default:
00222 gitk_log2("!!!!!!!!!!! unhandled widget_type %d (widget_id=\"%s\")",widget->type,widget->id);
00223 break;
00224 }
00225 }
00226
00227 break;
00228
00229
00230 case KEY_LEFT: gitk_log3("KEY_LEFT : %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));break;
00231 case KEY_RIGHT: gitk_log3("KEY_RIGHT : %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));break;
00232 case KEY_HOME: gitk_log3("KEY_HOME : %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));break;
00233 case KEY_BEG: gitk_log3("KEY_BEG : %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));break;
00234 case KEY_END: gitk_log3("KEY_END : %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));break;
00235 case KEY_BREAK: gitk_log3("KEY_BREAK : %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));break;
00236 case KEY_BACKSPACE: gitk_log3("KEY_BACKSPACE : %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));break;
00237 case KEY_INS: gitk_log3("KEY_INS : %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));break;
00238 case KEY_DEL: gitk_log3("KEY_DEL : %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));break;
00239 default:
00240 if(key) {
00241
00242 gitk_log3("? : %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
00243 }
00244 }
00245 }
00246
00247 gitk_log_outro();
00248 }
00249
00253 void handle_dialog_ctrl_widgets(GitkrTextLayoutPtr layout) {
00254 gint currentWidget;
00255 GitkrTextWidgetPtr widget;
00256
00257 gitk_log_intro();
00258
00259 currentWidget=layout->currentWidget;
00260 layout->currentWidget=GITKR_TEXT_NAVIGATION;
00261 gitkr_dialog_output_layout(cur_context);
00262 widget=&layout->ctrl.widgets[0];
00263 if(widget && widget->handle && widget->handle(widget,LINES-1)) {
00264 gchar *value=gitkr_widget_get_value(widget->dialog,widget->id,"value");
00265 gint cur_value=(value?atoi(value):0);
00266 GList *ids=gitkr_widget_optionchoice_get_ids(widget);
00267 gchar *id=g_list_nth_data(ids,cur_value);
00268
00269 gitk_log1("dialog control : id=\"%s\"",id);
00270
00271 if(!strncmp(id,"Prev",4)) prev_page(layout);
00272 else if(!strncmp(id,"Next",4)) next_page(layout);
00273 else {
00274 GitkEvent event;
00275
00276 event.type=GITK_EVENT_TYPE_ON_CLICKED;
00277 event.data=NULL;
00278 gitk_dialog_process_event(widget->dialog,id,&event);
00279 if(run) {
00280 gitk_log1("dialogcontrol [%s] not yet implemented",id);
00281 layout->currentWidget=currentWidget;
00282 gitkr_dialog_output_layout(cur_context);
00283 }
00284 }
00285 gitkr_widget_optionchoice_free_ids(ids);
00286 }
00287 else {
00288 layout->currentWidget=currentWidget;
00289 gitkr_dialog_output_layout(cur_context);
00290 }
00291 gitk_log_outro();
00292 }
00293
00294
00295
00300 gint gitkr_event_loop_getkey(void) {
00301 gint key=ERR;
00302
00303
00304 nodelay(stdscr, TRUE);
00305 while(run && (key==ERR)) {
00306 key=getch();
00308 }
00309 nodelay(stdscr, FALSE);
00310
00311 if(key==KEY_ESCAPE) key=gitkr_event_loop_unescape_key();
00312
00313 gitk_log1("got key %d",key);
00314
00315 return(key);
00316 }
00317
00322 gint gitkr_event_loop_unescape_key(void) {
00323 gint key,sub1,sub2,sub3;
00324
00325 nodelay(stdscr, TRUE);
00326 sub1=getch();
00327 nodelay(stdscr, FALSE);
00328 switch(sub1) {
00329 case ERR:
00330 key=KEY_BREAK;
00331 gitk_log("key-event : ESCAPE");
00332 break;
00333 case KEYSEQ_2BYTES:
00334 sub2=getch();
00335 gitk_log3("key-event : FUNCTION_KEY2a : %4d 0x%03x '%c'",sub1,sub1,KEYCODE_TO_ASCII(sub1));
00336 gitk_log3("key-event : FUNCTION_KEY2b : %4d 0x%03x '%c'",sub2,sub2,KEYCODE_TO_ASCII(sub2));
00337 switch(sub2) {
00338 case 0x48: key=KEY_HOME;break;
00339 case 0x46: key=KEY_END;break;
00340 case 0x50: key=KEY_F(1);break;
00341 case 0x51: key=KEY_F(2);break;
00342 case 0x52: key=KEY_F(3);break;
00343 case 0x53: key=KEY_F(4);break;
00344 case 0x54: key=KEY_F(5);break;
00345 case 0x55: key=KEY_F(6);break;
00346 case 0x56: key=KEY_F(7);break;
00347 case 0x57: key=KEY_F(8);break;
00348 case 0x58: key=KEY_F(9);break;
00349 default: key=0;
00350 }
00351 break;
00352 case KEYSEQ_3BYTES:
00353 sub2=getch();sub3=getch();
00354 gitk_log3("key-event : FUNCTION_KEY3a : %4d 0x%03x '%c'",sub1,sub1,KEYCODE_TO_ASCII(sub1));
00355 gitk_log3("key-event : FUNCTION_KEY3b : %4d 0x%03x '%c'",sub2,sub2,KEYCODE_TO_ASCII(sub2));
00356 gitk_log3("key-event : FUNCTION_KEY3c : %4d 0x%03x '%c'",sub3,sub3,KEYCODE_TO_ASCII(sub3));
00357 switch(sub2) {
00358 case 0x32: key=KEY_INS;break;
00359 case 0x33: key=KEY_DEL;break;
00360 case 0x35: key=KEY_PPAGE;break;
00361 case 0x36: key=KEY_NPAGE;break;
00362 default:key=0;
00363 }
00364 break;
00365 default:
00366 key=sub1;
00367 break;
00368 }
00369 return(key);
00370 }
00371
00372
00373
00377 void sighandler_on_sigint(int sig) {
00378 GitkEvent event;
00379
00380
00381 signal(SIGINT, sighandler_on_sigint);
00382 gitk_log("! on_sigint");
00383 run=FALSE;
00384 event.type=GITK_EVENT_TYPE_ON_CLOSE;
00385 event.data=NULL;
00386 if(gitk_dialog_process_event(NULL,NULL,&event)) gitk_event_loop_end();
00387 }
00388
00392 void sighandler_on_sighup(int sig) {
00393 GitkEvent event;
00394
00395
00396 signal(SIGHUP, sighandler_on_sigint);
00397 gitk_log("! on_sighup");
00398 run=FALSE;
00399 event.type=GITK_EVENT_TYPE_ON_CLOSE;
00400 event.data=NULL;
00401 if(gitk_dialog_process_event(NULL,NULL,&event)) gitk_event_loop_end();
00402 }
00403
00407 void sighandler_on_sigwinch(int sig) {
00408 struct winsize size;
00409
00410
00411 signal(SIGWINCH, sighandler_on_sigwinch);
00412 gitk_log("! on_sigwinch");
00413 if((ioctl(fileno(stdout), TIOCGWINSZ, &size)!=-1) ||
00414 (ioctl(fileno(stderr), TIOCGWINSZ, &size)!=-1) ||
00415 (ioctl(fileno(stdin), TIOCGWINSZ, &size)!=-1)) {
00416 gitk_log2("new size is : %3d x %3d",size.ws_row, size.ws_col);
00417 resizeterm(size.ws_row, size.ws_col);
00418 if(cur_context && run) {
00420 gitkr_dialog_output_layout(cur_context);refresh();
00421 }
00422 }
00423 else {
00424 gitk_log2("ioctrl() failed : errno=%d : \"%s\"",errno,strerror(errno));
00425 }
00426 }
00427