/** $Id: gitkreventloop.c,v 1.8 2005/01/04 16:24:29 ensonic Exp $
*
* @file gitk-renderer-phone/gitkreventloop.c
* @author Steffen Ast <sast@users.sf.net>
* @date Thu Oct 09 09:43:54 2003
*
* @brief gitk renderer event loop
* @ingroup gitkrendererphone
*
*/
#define GITK_RENDERER_C
#define GITKR_EVENTLOOP_C
#include "gitkrincludes.h"
/** @brief current context handle
*/
GitkDialogPtr cur_context;
/** @brief curses based event-loop
* @see gitkr_event_loop_end
* @ingroup gitkrendererphone
*/
void gitkr_event_loop_start(void) {
GitkrPhoneLayoutPtr layout;
gitk_log_intro();
restart_event_loop=TRUE;
//-- start the event-loop
while(restart_event_loop) {
run=TRUE;
restart_event_loop=FALSE;
while(!capi_incoming_connected) {
#ifdef HAVE_CAPI20
capi_wait_for_incoming_calls(capiinfo);
#endif //HAVE_CAPI20
capi_incoming_connected = (TRUE);
gitk_log("incoming call detected");
//-- render initial screen
capi_text_output(capiinfo,welcome,ftinfo);
//-- play help if the user wish it
gitkr_welcome_help();
}
if(!(cur_context=gitk_context_get_current())) {
gitk_log("no current context");
return;
}
if(!(layout=(GitkrPhoneLayoutPtr)cur_context->layout)) {
gitk_log("current context without layout");
return;
}
//-- depending on initial focus settings, call handle_dialog_ctrl_widgets instead
switch(layout->focus) {
case GITK_FOCUS_TYPE_MAIN:
handle_dialog_main_widgets(layout);
gitk_log("layout->focus=handle_dialog_main_widgets");
break;
case GITK_FOCUS_TYPE_CTRL:
handle_dialog_ctrl_widgets(layout);
gitk_log("layout->focus=handle_dialog_crtl_widgets");
break;
default:
gitk_log1("unexpected default : %d",layout->focus);
}
gitk_log("leaving event-loop");
if(restart_event_loop) gitk_relayout();
}
gitk_log_outro();
}
/** @brief terminates the event-loop
* @see gitkr_event_loop_start
* @ingroup gitkrendererphone
*/
void gitkr_event_loop_end(void) {
gitk_log_intro();
//-- quits the keyboard-input-main loop
run=FALSE;
gitk_log_outro();
}
/** @brief terminates the event-loop so that it will be restarted after relayouting the dialogs
* @see gitkr_event_loop_start, gitkr_event_loop_end
* @ingroup gitkrenderertext
*/
void gitkr_event_loop_restart(void) {
gitk_log_intro();
restart_event_loop=TRUE;
gitkr_event_loop_end();
}
//-- event sub routines
/** @brief switch to next widget
* @internal
*/
void next_widget(GitkrPhoneLayoutPtr layout) {
GitkrPhoneWidgetPtr old_widget,new_widget;
old_widget=&layout->pages[layout->currentPage].widgets[layout->currentWidget];
if(layout->currentWidget<((layout->pages[layout->currentPage].widgetsPerPage)-1)) {
layout->currentWidget++;
}
else {
layout->currentWidget=0;
}
new_widget=&layout->pages[layout->currentPage].widgets[layout->currentWidget];
gitk_dialog_move_focus((GitkWidgetPtr)old_widget,(GitkWidgetPtr)new_widget);
//gitkr_dialog_output_layout(cur_context);
}
/** @brief switch to previous widget
* @internal
*/
void prev_widget(GitkrPhoneLayoutPtr layout) {
GitkrPhoneWidgetPtr old_widget,new_widget;
old_widget=&layout->pages[layout->currentPage].widgets[layout->currentWidget];
if(layout->currentWidget>0) {
layout->currentWidget--;
}
else {
layout->currentWidget=(layout->pages[layout->currentPage].widgetsPerPage)-1;
}
new_widget=&layout->pages[layout->currentPage].widgets[layout->currentWidget];
gitk_dialog_move_focus((GitkWidgetPtr)old_widget,(GitkWidgetPtr)new_widget);
//gitkr_dialog_output_layout(cur_context);
}
/** @brief switch to next page
* @internal
*/
void next_page(GitkrPhoneLayoutPtr layout) {
if(layout->currentPage<(layout->numberOfPages-1)) {
layout->currentPage++;
layout->currentWidget=0;
//gitkr_dialog_output_layout(cur_context);
}
else capi_sound_beep(capiinfo, ftinfo);
}
/** @brief switch to previous page
* @internal
*/
void prev_page(GitkrPhoneLayoutPtr layout) {
if(layout->currentPage>0) {
layout->currentPage--;
layout->currentWidget=0;
//gitkr_dialog_output_layout(cur_context);
}
else capi_sound_beep(capiinfo, ftinfo);
}
/** @brief run the event loop for the main dialog widgets
* @param layout the layout handle of the displayed dialog
*/
void handle_dialog_main_widgets(GitkrPhoneLayoutPtr layout) {
gint key;
GitkEvent event;
GitkrPhoneWidgetPtr widget;
gchar res[10];
gitk_log_intro();
//-- now run the event-loop
while(run) {
capi_text_output(capiinfo,_("content"),ftinfo);
#ifdef HAVE_CAPI20
key=capi_dtmf_input_arrow(capiinfo, res);
gitk_log1("handle_dialog_main_widgets() res=%c", key);
//-- pre-process escape keys
//if(key==KEY_ESCAPE) key=gitkr_event_loop_unescape_key();
//-- process the key-code
switch(key) {
//-- global behaviour
case Key_Escape: //ESC
gitk_log3("Key_Escape: %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
event.type=GITK_EVENT_TYPE_ON_CLOSE;
event.data=NULL;
if(gitk_dialog_process_event(NULL,NULL,&event)) run=FALSE;
break;
case Key_F2: //SEL
gitk_log3("Key_F2/KEY_SELECT: %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
handle_dialog_ctrl_widgets(layout);
break;
//-- navigation
case Key_Down: // go to the previous widget
case Key_Right:
gitk_log3("Key_Down/Right: %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
next_widget(layout);
break;
case Key_Up: // go to the next widget
case Key_Left:
gitk_log3("Key_Up/Left: %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
prev_widget(layout);
break;
case Key_PageDown:
gitk_log3("Key_PageDown: %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
next_page(layout);
break;
case Key_PageUp:
gitk_log3("Key_PageUp: %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
prev_page(layout);
break;
case Key_Home: //Pos1
gitk_log3("Key_Home: %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
break;
case Key_End: //End
gitk_log3("Key_End: %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
break;
case Key_Backspace:
case Key_Delete: //DEL
gitk_log3("Key_Delete/Backspace: %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
break;
//-- activation
case Key_Return: // activate widget
case Key_Enter: //Enter
gitk_log3("Key_Enter/Return : %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
if((widget=gitkr_layout_get_current_widget(layout))) {
switch(widget->type) {
case GITK_WIDGET_TYPE_ACTION:
if(widget->handle && widget->handle(widget)) {
event.type=GITK_EVENT_TYPE_ON_INVOKED;
event.data=NULL;
gitk_dialog_process_event(widget->dialog,widget->id,&event);
next_widget(layout);
}
break;
case GITK_WIDGET_TYPE_CHARACTERINPUT:
case GITK_WIDGET_TYPE_CHARACTERINPUT_ALPHABETIC:
case GITK_WIDGET_TYPE_OPTIONCHOICE:
case GITK_WIDGET_TYPE_OPTIONCHOICE_SINGLE:
case GITK_WIDGET_TYPE_OPTIONCHOICE_SINGLE_COMPACT:
case GITK_WIDGET_TYPE_OPTIONCHOICE_BOOLEAN:
if(widget->handle && widget->handle(widget)) {
event.type=GITK_EVENT_TYPE_ON_CHANGED;
event.data=NULL;
gitk_dialog_process_event(widget->dialog,widget->id,&event);
next_widget(layout);
}
break;
default:
gitk_log2("!!!!!!!!!!! unhandled widget_type %d (widget_id=\"%s\")",widget->type,widget->id);
break;
}
}
break;
//-- keys which are still unhandled
default:
if(key) {
gitk_log3("? : %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
gitkr_dialog_output_layout(cur_context);
}
}
}
#else
if((key=gitkr_event_loop_getkey())==ERR) continue;
gitk_log1("handle_dialog_main_widgets() res=%c", key);
//-- pre-process escape keys
//if(key==KEY_ESCAPE) key=gitkr_event_loop_unescape_key();
//-- process the key-code
switch(key) {
//-- global behaviour
case '0': //ESC
gitk_log3("Key_Escape: %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
event.type=GITK_EVENT_TYPE_ON_CLOSE;
event.data=NULL;
if(gitk_dialog_process_event(NULL,NULL,&event)) run=FALSE;
break;
case '5': //SEL
gitk_log3("Key_F2/KEY_SELECT: %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
handle_dialog_ctrl_widgets(layout);
//run = FALSE;
break;
//-- navigation
case '2': // go to the previous widget
case '6':
gitk_log3("Key_Down/Right: %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
next_widget(layout);
break;
case '8': // go to the next widget
case '4':
gitk_log3("Key_Up/Left: %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
prev_widget(layout);
break;
case '3':
gitk_log3("Key_PageDown: %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
next_page(layout);
break;
case '9':
gitk_log3("Key_PageUp: %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
prev_page(layout);
break;
case '7': //Pos1
gitk_log3("Key_Home: %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
break;
case '1': //End
gitk_log3("Key_End: %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
break;
case ',':
//case Key_Delete: //DEL
gitk_log3("Key_Delete/Backspace: %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
break;
//-- activation
case 13: // activate widget
case '\n': //Enter
gitk_log3("Key_Enter/Return : %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
if((widget=gitkr_layout_get_current_widget(layout))) {
switch(widget->type) {
case GITK_WIDGET_TYPE_ACTION:
if(widget->handle && widget->handle(widget)) {
event.type=GITK_EVENT_TYPE_ON_INVOKED;
event.data=NULL;
gitk_dialog_process_event(widget->dialog,widget->id,&event);
next_widget(layout);
}
break;
case GITK_WIDGET_TYPE_CHARACTERINPUT:
case GITK_WIDGET_TYPE_CHARACTERINPUT_ALPHABETIC:
case GITK_WIDGET_TYPE_OPTIONCHOICE:
case GITK_WIDGET_TYPE_OPTIONCHOICE_SINGLE:
case GITK_WIDGET_TYPE_OPTIONCHOICE_SINGLE_COMPACT:
case GITK_WIDGET_TYPE_OPTIONCHOICE_BOOLEAN:
if(widget->handle && widget->handle(widget)) {
event.type=GITK_EVENT_TYPE_ON_CHANGED;
event.data=NULL;
gitk_dialog_process_event(widget->dialog,widget->id,&event);
next_widget(layout);
}
break;
default:
gitk_log2("!!!!!!!!!!! unhandled widget_type %d (widget_id=\"%s\")",widget->type,widget->id);
break;
}
}
break;
//-- keys which are still unhandled
default:
if(key) {
gitk_log3("? : %4d 0x%03x '%c'",key,key,KEYCODE_TO_ASCII(key));
//gitkr_dialog_output_layout(cur_context);
capi_text_output(capiinfo, _("unhandled key"), ftinfo);
}
}
}
#endif //HAVE_CAPI20
gitk_log_outro();
}
/** @brief run the event loop for the dialog control widgets
* @param layout the layout handle of the displayed dialog
*/
void handle_dialog_ctrl_widgets(GitkrPhoneLayoutPtr layout) {
gint currentWidget;
GitkrPhoneWidgetPtr widget;
gitk_log_intro();
capi_text_output(capiinfo,_("control"),ftinfo);
currentWidget=layout->currentWidget;
layout->currentWidget=GITKR_TEXT_NAVIGATION;
//gitkr_dialog_output_layout(cur_context);
widget=&layout->ctrl.widgets[0];
if(widget && widget->handle && widget->handle(widget)) {
gchar *value=gitkr_widget_get_value(widget->dialog,widget->id,"value");
gint cur_value=(value?atoi(value):0); //-- determine selected entry
GList *ids=gitkr_widget_optionchoice_get_ids(widget);
gchar *id=g_list_nth_data(ids,cur_value);
gitk_log1("dialog control : id=\"%s\"",id);
if(!strncmp(id,"Prev",4)) prev_page(layout);
else if(!strncmp(id,"Next",4)) next_page(layout);
else {
GitkEvent event;
// trigger on_click for Okay, Cancel
event.type=GITK_EVENT_TYPE_ON_INVOKED;
event.data=NULL;
gitk_dialog_process_event(widget->dialog,id,&event);
if(run) { // do not redraw on Okay, Cancel
gitk_log1("dialogcontrol [%s] not yet implemented",id);
layout->currentWidget=currentWidget;
gitkr_dialog_output_layout(cur_context);
}
}
gitkr_widget_optionchoice_free_ids(ids);
}
else { // in case of cancel editing
layout->currentWidget=currentWidget;
gitkr_dialog_output_layout(cur_context);
}
gitk_log_outro();
}
//-- ncurses key-processing
/** @brief read a keycode from keyboard
* @internal
* @return the keycode
*/
gint gitkr_event_loop_getkey(void) {
gint key=ERR;
gitk_log_intro();
//-- accept single keystroke of input (is defined as wgetch(stdsrc))
nodelay(stdscr, TRUE);
while(run && (key==ERR)) {
key=getch();
/** @todo sleep a bit */
}
nodelay(stdscr, FALSE);
//-- pre-process escape keys
//if(key==KEY_ESCAPE) key=gitkr_event_loop_unescape_key();
//gitk_log1("got key %d",key);
gitk_log_outro();
return(key);
}
void gitkr_welcome_help() {
gitk_log_intro();
gitk_log_outro();
}