/* MikMod example player (c) 1999 Miodrag Vallat and others - see file AUTHORS for complete list. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*============================================================================== $Id: mwidget.c,v 1.1.1.1 2003/09/19 13:16:01 raph Exp $ Widget and Dialog creation functions ==============================================================================*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "display.h" #include #include "player.h" #include "mwindow.h" #include "mwidget.h" static void label_free(WID_LABEL *w) { free(w->msg); free(w); } static void label_paint(DIALOG *d,WID_LABEL *w) { char *start,*pos; int y=w->w.y; win_attrset(A_REVERSE); start=w->msg; for (pos=w->msg;*pos;pos++) { if (*pos=='\n') { *pos='\0'; win_print(w->w.x,y,start); *pos='\n'; start=pos+1; y++; } } win_print(w->w.x,y,start); win_attrset(A_NORMAL); } static int label_handle_event(DIALOG *d,WID_LABEL *w,WID_EVENT event,int ch) { return 0; } static void label_get_size(WID_LABEL *w,int *width,int *height) { char *pos; int x=0; *width=0; *height=0; for (pos=w->msg;*pos;pos++) { if (*pos=='\n') { (*height)++; if (x>*width) *width=x; x=-1; } x++; } if (x>*width) *width=x; (*height)++; } static void str_free(WID_STR *w) { free(w->input); free(w); } static void str_paint(DIALOG *d,WID_STR *w) { char hl[2]=" ",ch=' ',*pos=&w->input[w->start]; int dx=0,len; if (w->w.has_focus) { hl[0]=ch=w->input[w->cur_pos]; if (!hl[0]) hl[0]=' '; w->input[w->cur_pos]='\0'; if (*pos) win_print(w->w.x,w->w.y,pos); dx=strlen(pos); win_attrset(A_REVERSE); win_print(w->w.x+dx,w->w.y,hl); win_attrset(A_NORMAL); pos+=dx; dx++; *pos=ch; if (*pos) pos++; } len=strlen(pos); if (len+dx>w->width) { ch=w->input[w->width+w->start]; w->input[w->width+w->start]='\0'; } win_print(w->w.x+dx,w->w.y,pos); if (len+dx>w->width) w->input[w->width+w->start]=ch; else if (len+dxwidth) { dx+=len; for (len=0;lenwidth-dx;len++) storage[len]=' '; storage[len]='\0'; win_print(w->w.x+dx,w->w.y,storage); } } static int check_input(DIALOG *d,WID_INT *w,int ret) { if (ret &&(ret!=EVENT_HANDLED)&& w->w.handle_focus) { return w->w.handle_focus(d,(WIDGET*)w,ret); } else { if (ret==FOCUS_ACTIVATE) ret=FOCUS_NEXT; return ret; } } static int input_handle_event(DIALOG *d,WID_STR *w,WID_EVENT event,int ch,BOOL int_input) { char *pos; int i; if (event==WID_HOTKEY) return 0; if (event==WID_GET_FOCUS) return EVENT_HANDLED; if ((event==WID_KEY) && w->w.handle_key) { i=w->w.handle_key(d,(WIDGET*)w,ch); if (i) return i; } switch (ch) { case KEY_UP: return check_input(d,(WID_INT*)w,FOCUS_PREV); case '\t': case KEY_DOWN: return check_input(d,(WID_INT*)w,FOCUS_NEXT); case KEY_LEFT: case CTRL_B: if (w->cur_pos>0) w->cur_pos--; break; case KEY_RIGHT: case CTRL_F: if (w->cur_posinput)) w->cur_pos++; break; case KEY_PPAGE: case CTRL_A: w->cur_pos=0; break; case KEY_NPAGE: case CTRL_E: w->cur_pos=strlen(w->input); break; case CTRL_K: w->input[w->cur_pos]='\0'; break; case CTRL_U: w->cur_pos=0; w->input[w->cur_pos]='\0'; break; case KEY_DC: case CTRL_D: #if !defined(__OS2__)&&!defined(__EMX__) case KEY_ASCII_DEL: #endif if (w->cur_pos < strlen(w->input)) for (pos=&w->input[w->cur_pos];*pos;pos++) *pos=*(pos+1); break; case KEY_BACKSPACE: #if !defined(__OS2__)&&!defined(__EMX__) case '\b': #endif if (w->cur_pos>0) { for (pos=&w->input[w->cur_pos-1];*pos;pos++) *pos=*(pos+1); w->cur_pos--; } break; case KEY_ENTER: case '\r': return check_input(d,(WID_INT*)w,FOCUS_ACTIVATE); default: if (ch>=256 || !isprint(ch)) return 0; if ((int_input && isdigit(ch)) || (!int_input && isprint(ch))) { i=strlen(w->input); if (ilength) { for (;i>=w->cur_pos;i--) w->input[i+1]=w->input[i]; w->input[w->cur_pos]=ch; w->cur_pos++; } } } if (w->cur_posstart) w->start=w->cur_pos; if (w->cur_pos>=w->start+w->width) w->start=w->cur_pos-w->width+1; str_paint(d,w); return EVENT_HANDLED; } static int str_handle_event(DIALOG *d,WID_STR *w,WID_EVENT event,int ch) { return input_handle_event(d,w,event,ch,0); } static void str_get_size(WID_STR *w,int *width,int *height) { *width=w->width; *height=1; } static void int_free(WID_INT *w) { free(w->input); free(w); } static void int_paint(DIALOG *d,WID_INT *w) { str_paint(d,(WID_STR*)w); } static BOOL int_handle_event(DIALOG *d,WID_INT *w,WID_EVENT event,int ch) { return input_handle_event(d,(WID_STR*)w,event,ch,1); } static void int_get_size(WID_INT *w,int *width,int *height) { *width=w->width; *height=1; } static void button_free(WID_BUTTON *w) { free(w->button); free(w); } static void button_paint(DIALOG *d,WID_BUTTON *w) { int cur,x,cnt_hl=0; char *pos,*hl_pos,*start,hl[2]; BOOL end; for (pos=w->button;*pos;pos++) if (*pos=='&') cnt_hl++; x=(d->win->width-1-w->w.x-(strlen(w->button)+5*w->cnt-1-cnt_hl))/2; cur=0; hl_pos=NULL;hl[1]='\0'; start=w->button; end=0; for (pos=w->button;!end;pos++) { end=!(*pos); if ((*pos == '|')||(*pos=='\0')) { *pos='\0'; if ((w->active!=cur)||(!w->w.has_focus)) win_attrset(A_REVERSE); win_print(w->w.x+x,w->w.y,"[ "); win_print(w->w.x+x+2,w->w.y,start); x+=strlen(start)+2; if (hl_pos) { if ((w->active!=cur)||(!w->w.has_focus)) win_attrset(A_NORMAL); else win_attrset(A_REVERSE); win_print(w->w.x+x,w->w.y,hl); if ((w->active!=cur)||(!w->w.has_focus)) win_attrset(A_REVERSE); else win_attrset(A_NORMAL); win_print(w->w.x+x+1,w->w.y,hl_pos); *(hl_pos-2)='&'; x+=strlen(hl_pos)+1; hl_pos=NULL; } win_print(w->w.x+x,w->w.y," ]"); if ((w->active!=cur)||(!w->w.has_focus)) win_attrset(A_NORMAL); x+=4; *pos='|'; start=pos+1; cur++; } if (*pos=='&') { *pos='\0'; pos++; hl_pos=pos+1; hl[0]=*pos; } } *(pos-1)='\0'; } static int focus_button(DIALOG *d,WID_BUTTON *w,int ret) { if (ret &&(ret!=EVENT_HANDLED) && w->w.handle_focus) { return w->w.handle_focus(d,(WIDGET*)w,ret); } else { if (ret==FOCUS_ACTIVATE) { dialog_close(d); return EVENT_HANDLED; } return ret; } } static BOOL button_handle_event(DIALOG *d,WID_BUTTON *w,WID_EVENT event,int ch) { int cur; char *pos; if (event==WID_GET_FOCUS) { if (ch<0) w->active=w->cnt-1; else w->active=0; return EVENT_HANDLED; } if ((event==WID_KEY)&&(w->w.handle_key)) { cur=w->w.handle_key(d,(WIDGET*)w,ch); if (cur) return cur; } if ((ch<256) &&(isalpha(ch))) ch=toupper(ch); switch (ch) { case KEY_UP: case KEY_LEFT: if (event==WID_KEY) { w->active--; if (w->active<0) return focus_button(d,w,FOCUS_PREV); button_paint(d,w); } break; case KEY_DOWN: case KEY_RIGHT: case '\t': if (event==WID_KEY) { w->active++; if (w->active>=w->cnt) return focus_button(d,w,FOCUS_NEXT); button_paint(d,w); } break; case KEY_ENTER: case '\r': if (event==WID_KEY) return focus_button(d,w,FOCUS_ACTIVATE); break; default: cur=0; for (pos=w->button; *pos; pos++) { if (*pos=='|') cur++; if (*pos=='&' && (*(pos+1)==ch)) { w->active=cur; button_paint(d,w); return focus_button(d,w,FOCUS_ACTIVATE); } } return 0; } return EVENT_HANDLED; } static void button_get_size(WID_BUTTON *w,int *width,int *height) { char *pos; int hl_cnt=0; w->cnt=1; for (pos=w->button;*pos;pos++) { if (*pos=='&') hl_cnt++; if (*pos=='|') w->cnt++; } *width=strlen(w->button)+5*w->cnt-1-hl_cnt; *height=1; } static void dialog_add(DIALOG *d,WIDGET *w) { d->widget=realloc(d->widget,(d->cnt+1)*sizeof(WIDGET*)); d->widget[d->cnt]=w; d->cnt++; } static void widget_init(WIDGET *w,BOOL focus,int spacing) { w->x=1; w->y=spacing; w->can_focus=focus; w->has_focus=0; w->handle_key=w->handle_focus=NULL; w->data=NULL; } WIDGET* wid_label_add(DIALOG *d,int spacing,char *msg) { WID_LABEL *w=malloc(sizeof(WID_LABEL)); widget_init((WIDGET*)w,0,spacing); w->w.type=TYPE_LABEL; w->w.w_free=(freeFunc)label_free; w->w.w_paint=(paintFunc)label_paint; w->w.w_handle_event=(handleEventFunc)label_handle_event; w->w.w_get_size=(getSizeFunc)label_get_size; w->msg=strdup(msg); dialog_add(d,(WIDGET*)w); return(WIDGET*)w; } #define STR_WIDTH 60 WIDGET* wid_str_add(DIALOG *d,int spacing,char *input,int length) { int i; WID_STR *w=malloc(sizeof(WID_STR)); widget_init((WIDGET*)w,1,spacing); w->w.type=TYPE_STR; w->w.w_free=(freeFunc)str_free; w->w.w_paint=(paintFunc)str_paint; w->w.w_handle_event=(handleEventFunc)str_handle_event; w->w.w_get_size=(getSizeFunc)str_get_size; w->width=STR_WIDTH; w->length=length; if (w->width>w->length) w->width=w->length+1; if (w->width<10) w->width=10; w->input=malloc(length+1); i=MIN(strlen(input),length); strncpy(w->input,input,i); w->input[i]='\0'; w->cur_pos=strlen(w->input); w->start=w->cur_pos-w->width+1; if (w->start<0) w->start=0; dialog_add(d,(WIDGET*)w); return(WIDGET*)w; } #define INT_WIDTH 11 WIDGET* wid_int_add(DIALOG *d,int spacing,int value,int length) { WID_INT *w=malloc(sizeof(WID_INT)); widget_init((WIDGET*)w,1,spacing); w->w.type=TYPE_INT; w->w.w_free=(freeFunc)int_free; w->w.w_paint=(paintFunc)int_paint; w->w.w_handle_event=(handleEventFunc)int_handle_event; w->w.w_get_size=(getSizeFunc)int_get_size; w->width=INT_WIDTH; w->start=0; w->length=length; w->input=malloc(w->length+1); sprintf(w->input,"%d",value); w->cur_pos=strlen(w->input); dialog_add(d,(WIDGET*)w); return(WIDGET*)w; } WIDGET* wid_button_add(DIALOG *d,int spacing,char *button,int active) { WID_BUTTON *w=malloc(sizeof(WID_BUTTON)); widget_init((WIDGET*)w,1,spacing); w->w.type=TYPE_BUTTON; w->w.w_free=(freeFunc)button_free; w->w.w_paint=(paintFunc)button_paint; w->w.w_handle_event=(handleEventFunc)button_handle_event; w->w.w_get_size=(getSizeFunc)button_get_size; w->button=strdup(button); w->active=active; dialog_add(d,(WIDGET*)w); return(WIDGET*)w; } void wid_set_func(WIDGET *w,handleKeyFunc key,handleFocusFunc focus,void *data) { w->handle_key=key; w->handle_focus=focus; w->data=data; } BOOL dialog_repaint(MWINDOW *win) { DIALOG *d=win->data; int i=0; win_attrset(A_REVERSE); win_clear(); win_attrset(A_NORMAL); for (i=0;icnt;i++) d->widget[i]->w_paint(d,d->widget[i]); return 1; } void dialog_close(DIALOG *d) { int i; for (i=0;icnt;i++) d->widget[i]->w_free(d->widget[i]); if (d->cnt) free(d->widget); win_close_win(d->win); free(d); } static BOOL dialog_handle_key(MWINDOW *win,int ch) { DIALOG *d=win->data; int ret,i; ret=d->widget[d->active]->w_handle_event(d,d->widget[d->active],WID_KEY,ch); if (!ret) { for (i=0;icnt && !ret;i++) { ret=d->widget[i]->w_handle_event(d,d->widget[i],WID_HOTKEY,ch); if (ret == FOCUS_ACTIVATE) { d->widget[d->active]->has_focus=0; d->widget[i]->has_focus=1; d->active=i; d->widget[d->active]->w_handle_event(d,d->widget[d->active], WID_GET_FOCUS,ret); dialog_repaint(win); } } } else if (retwidget[d->active]->has_focus=0; do { d->active+=ret; if (d->active<0) d->active=d->cnt-1; else if (d->active>=d->cnt) d->active=0; } while (!d->widget[d->active]->can_focus); d->widget[d->active]->has_focus=1; d->widget[d->active]->w_handle_event(d,d->widget[d->active], WID_GET_FOCUS,ret); dialog_repaint(win); } return !!ret; } void dialog_open(DIALOG *d,char *title) { int m_y,m_width=0,m_height=0,i,x,y,width=0,height=0; BOOL focus=1; i=0; while (icnt) { /* Init all widgets(position and focus) */ m_height+=d->widget[i]->y; width=1; height=0; do { /* widgets in one row */ d->widget[i]->w_get_size(d->widget[i],&x,&y); d->widget[i]->x=width; d->widget[i]->y=m_height; width += x+1; if (y>height) height=y; if (d->widget[i]->can_focus) { d->widget[i]->has_focus=focus; if (focus) d->active=i; focus=0; } else d->widget[i]->has_focus=0; i++; } while ((icnt) &&(d->widget[i]->y==-1)); if (width>m_width) m_width=width; m_height+=height; } width=m_width; height=m_height; win_get_size_max(&m_y,&m_width,&m_height); x=(m_width-width)/2; if (x<0) x=0; y=(m_height-height)/2+m_y; if (ywin=win_get_window(); dialog_repaint(d->win); } DIALOG* dialog_new(void) { DIALOG *d=malloc(sizeof(DIALOG)); d->active=0; d->cnt=0; d->win=NULL; d->widget=NULL; return d; } /* ex:set ts=4: */