gitkreventloop.c

Go to the documentation of this file.
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   //-- start the event-loop
00032   while(restart_event_loop) {
00033     run=TRUE;
00034     restart_event_loop=FALSE;
00035 
00036     //-- render initial screen
00037     //gitkr_render();
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     //-- depending on initial focus settings, call handle_dialog_ctrl_widgets instead
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   //-- quits the keyboard-input-main loop 
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 //-- event sub routines
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   //if(((layout->currentPage<(layout->numberOfPages-1)) && (layout->currentWidget<layout->widgetsPerPage))
00085   // || (layout->currentWidget<((layout->numberOfWidgets-1)-((layout->numberOfPages-1)*layout->widgetsPerPage)))) {
00086   if(layout->currentWidget<((layout->pages[layout->currentPage].widgetsPerPage)-1)) {
00087     layout->currentWidget++;
00088   }
00089   else {
00090     layout->currentWidget=0;
00091     //beep();refresh();
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     //beep();refresh();
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   //-- set focus to current widget
00155   widget=&layout->pages[layout->currentPage].widgets[layout->currentWidget];
00156   gitk_dialog_move_focus(NULL,(GitkWidgetPtr)widget);
00157   
00158   //-- now run the event-loop
00159   while(run) {
00160     if((key=gitkr_event_loop_getkey())==ERR) continue;
00161     //-- process the key-code
00162     switch(key) {
00163       //-- global behaviour
00164       case KEY_F10:    // exit main-loop
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:    // activate help
00172         break;
00173       case KEY_F2:    // activate dialog navigation
00174         handle_dialog_ctrl_widgets(layout);
00175         break;
00176       //-- navigation
00177       case KEY_DOWN: // go to the previous widget
00178       case KEY_TAB:
00179         next_widget(layout);
00180         //gitk_log3("KEY_DOWN      : %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
00181         break;
00182       case KEY_UP: // go to the next widget
00184         prev_widget(layout);
00185         //gitk_log3("KEY_UP        : %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
00186         break;
00187       case KEY_NPAGE:
00188         next_page(layout);
00189         //gitk_log3("KEY_NPAGE     : %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
00190         break;
00191       case KEY_PPAGE:
00192         prev_page(layout);
00193         //gitk_log3("KEY_PPAGE     : %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
00194         break;
00195       //-- activation
00196       case KEY_RETURN: // activate widget
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         //gitk_log3("KEY_ENTER/RET : %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
00227         break;
00228     
00229       //-- keys which are still unhandled
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           //gitkr_dialog_output_layout(cur_context);refresh();
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);  //-- determine selected entry
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       // trigger on_click for Okay, Cancel
00276       event.type=GITK_EVENT_TYPE_ON_CLICKED;
00277       event.data=NULL;
00278       gitk_dialog_process_event(widget->dialog,id,&event);
00279       if(run) { // do not redraw on Okay, Cancel
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 {  // in case of cancel editing
00288       layout->currentWidget=currentWidget;
00289       gitkr_dialog_output_layout(cur_context);
00290   }
00291   gitk_log_outro();
00292 }
00293 
00294 //-- ncurses key-processing
00295 
00300 gint gitkr_event_loop_getkey(void) {
00301   gint key=ERR;
00302   
00303   //-- accept single keystroke of input (is defined as wgetch(stdsrc))
00304   nodelay(stdscr, TRUE);
00305   while(run && (key==ERR)) {
00306     key=getch();
00308   }
00309   nodelay(stdscr, FALSE);
00310   //-- pre-process escape keys
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);  /* are the more keycodes waiting ? */
00326   sub1=getch();
00327   nodelay(stdscr, FALSE);
00328   switch(sub1) {
00329     case ERR:             /* no, just use the key as a single key-press */
00330       key=KEY_BREAK;
00331       gitk_log("key-event : ESCAPE");
00332       break;
00333     case KEYSEQ_2BYTES:       /* yes, it's a 2 byte sequence */
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:       /* yes, it's a 3 byte sequence */
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:              /* keep the keycode */
00366       key=sub1;
00367       break;
00368   }
00369   return(key);
00370 }
00371 
00372 //-- signal handler
00373 
00377 void sighandler_on_sigint(int sig) {
00378   GitkEvent event;
00379 
00380   //-- some versions of UNIX will reset signal to default after each call. So for portability reset signal each time
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   //-- some versions of UNIX will reset signal to default after each call. So for portability reset signal each time
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   //-- some versions of UNIX will reset signal to default after each call. So for portability reset signal each time
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 

Generated on Thu Oct 28 10:59:10 2004 for gitk by doxygen 1.3.6