#include #include #include #include #include #include #include #include "ml.h" #include "kbd_keys.h" #include "ml_mouse.h" #define INTERFACE(call,pars) ((*(cur_intf->call))pars) #define INTERFACE_VOID(call) ((*(cur_intf->call))()) #define absx(x) ((x)+cur_win->x1) #define absy(y) ((y)+cur_win->y1) #define PRINTF if(__debug) printf static window_t *cur_win=NULL; video_interface_t *cur_intf=NULL; static boolean field_was_changed=0; static boolean was_mouse=0; static boolean __debug=FALSE; static FILE *demo_keys=NULL; static demo_mode current_demo_mode=NO_DEMO; static unsigned demo_delay; static boolean mouse_event=FALSE; static unsigned button, x_event, y_event; static ml_retcode_t mouse_retcode; void chkinit(void) { if(!cur_intf) error("Interface is not initialised yet"); } void win_check(int x1, int y1, int x2, int y2) { if(x1 < 0 || y1 < 0 || x2 <= x1 || y2 < y1 || x2 >= INTERFACE_VOID(getmaxX)+1 || y2 >= INTERFACE_VOID(getmaxY)+1) error("Bad window bounds"); } void hide_cursor(void) { chkinit(); INTERFACE_VOID(hide_cursor); } void show_cursor(void) { chkinit(); INTERFACE_VOID(show_cursor); } int getwidth(char *str) { return INTERFACE(getwidth,(str)); } int getheight(char *str) { return INTERFACE(getheight,(str)); } void absfwritexy(int x, int y, int color, char *str) { chkinit(); INTERFACE(absfwritexy,(x,y,color,str)); } static char *saveframe(int x1, int y1, int x2, int y2) { chkinit(); return INTERFACE(saveframe,(x1,y1,x2,y2)); } static void restoreframe(char *fr, int x1, int y1, int x2, int y2) { chkinit(); INTERFACE(restoreframe,(fr,x1,y1,x2,y2)); } static void draw_window(window_t *wnd, int x1, int y1, int x2, int y2, int col, int bor_col, border_t border, char *up_name, char *down_name) { chkinit(); INTERFACE(draw_window,(wnd,x1,y1,x2,y2,col,bor_col,border,up_name,down_name)); } int getcurcolor(void) { return cur_win->act_col; } void winfwritexy(int x, int y, int color, char *str) { char buf[128]; if(absx(x) < cur_win->x1 || absx(x)+strlen(str) > cur_win->x2+1 || absy(y) < cur_win->y1 || absy(y) > cur_win->y2) { sprintf(buf,"Bad string coordinates:x=%d,y=%d,str=%s,cw=%Fp," "x1=%d,y1=%d,x2=%d,y2=%d", x,y,str,cur_win,cur_win->x1,cur_win->y1,cur_win->x2,cur_win->y2); error(buf); } absfwritexy(absx(x),absy(y),color,str); cur_win->xpos=x+getwidth(str); cur_win->ypos=y; } void writelongstrxy(int x, int y, char *str) { char *p, buf[256],*bp; for(p=str; *p; ) { for(bp=buf; *p && *p != '\n'; ) *bp++=*p++; if(*p=='\n') p++; if(*p=='\r') p++; *bp='\0'; winfwritexy(x,y,cur_win->act_col,buf); y+=1; } } boolean mouse_in_bar(int x1, int y1, int x2, int y2) { int x,y; /* string buf; void my_debug(int,int,char *); */ chkinit(); INTERFACE(mouse2text,(&x,&y)); return x >= x1 && y >= y1 && x <= x2 && y <= y2; } int text2scrX(int x) { return INTERFACE(text2scrX,(x)); } int text2scrY(int y) { return INTERFACE(text2scrY,(y)); } void mk_w_str(int x1, int x2, char *buf, char *name) { int k; strcpy(buf,name); k=x2-x1-2; if(k > 0) buf[k]=0; else buf[0]=0; } void set_active_window(window_t *wnd) { if(cur_win && cur_intf->video_mode==VID_TEXT_MODE) { /* gettextinfo(&(cur_win->textinfo)); */ } cur_win=wnd; if(wnd->active_now) INTERFACE(set_scr_state,(cur_win)); } void show_window(window_t *wnd, int x1, int y1, int x2, int y2, int col, int bor_col, border_t border, char *up_name, char *down_name) { chkinit(); wnd->frame=saveframe(x1,y1,x2,y2); draw_window(wnd,x1,y1,x2,y2,col,bor_col,border,up_name,down_name); } void show_window_bar(window_t *wnd, int x1, int y1, int x2, int y2, int col, int bor_col, border_t border, char *up_name, char *down_name) { chkinit(); wnd->frame=NULL; draw_window(wnd,x1,y1,x2,y2,col,bor_col,border,up_name,down_name); } void show_subwindow(window_t *wnd, int x1, int y1, int x2, int y2, int col, int bor_col, border_t border, char *up_name, char *down_name) { show_window(wnd,cur_win->x1+x1,cur_win->y1+y1,cur_win->x1+x2,cur_win->y1+y2, col,bor_col,border,up_name,down_name); } void clear_window(void) { INTERFACE_VOID(clear_window); } void erase_window(window_t *wnd) { chkinit(); if(cur_win==wnd) cur_win=NULL; if(wnd->border != NO_BORDER) restoreframe(wnd->frame,wnd->x1-1,wnd->y1-1,wnd->x2+1,wnd->y2+1); else restoreframe(wnd->frame,wnd->x1,wnd->y1,wnd->x2,wnd->y2); wnd->frame=NULL; } window_t *getcurwin(void) { return cur_win; } void message_box(int x, int y, char *msg, int border_col, int text_col) { window_t wnd, *old_win; ml_retcode_t ch; old_win=getcurwin(); show_window(&wnd,x,y,x+strlen(msg)+2,y+2, text_col,border_col,DOUBLE_BORDER, "",""); while(ml_issignal()) wait(); winfwritexy(0,0,getcurcolor(),msg); do { ch=wait(); } while(ch==RC_MOUSEMOTION || ch==RC_MOUSERELEASE); erase_window(&wnd); set_active_window(old_win); } ml_retcode_t get_answer(int x, int y, char *msg, char *ans, char *ans0, int border_col, int text_col) { window_t wnd, *old_win; ml_retcode_t ch; old_win=cur_win; show_window(&wnd,x,y,x+strlen(msg)+2,y+2, text_col,border_col,DOUBLE_BORDER, "",""); while(kbhit()) wait(); winfwritexy(0,0,getcurcolor(),msg); do{ ch=wait(); } while(!in_str(ch,ans) && !in_str(GETK0(ch),ans0)); erase_window(&wnd); set_active_window(old_win); return ch; } void ml_gotoxy(int x, int y) { window_t *w=cur_win; w->xpos=x; w->ypos=y; } int ml_wherex(void) { return cur_win->xpos; } int ml_wherey(void) { return cur_win->ypos; } static void set_mouse_event(int btn, ml_retcode_t retcode) { unsigned mask; button=btn; mouse_event=TRUE; mouse_retcode=retcode; ms_read(&x_event,&y_event,&mask); } int ask_mouse_event(unsigned *x, unsigned *y) /* Возвращает button */ { if(x) *x=x_event; if(y) *y=y_event; return button; } int ask_mouse_xy(unsigned *x, unsigned *y) /* Возвращает button */ { int x1,y1; chkinit(); INTERFACE(mouse2text,(&x1,&y1)); if(x) *x=x1; if(y) *y=y1; return button; } boolean ml_issignal(void) { unsigned n,x,y; if(mouse_present) { if(mouse_event) return TRUE; ms_get_b(0,&n,&x,&y); if(n) { set_mouse_event(0,RC_MOUSEBUTTON); return TRUE; } ms_get_b(1,&n,&x,&y); if(n) { set_mouse_event(1,RC_MOUSEBUTTON); return TRUE; } ms_get_b(2,&n,&x,&y); if(n) { set_mouse_event(2,RC_MOUSEBUTTON); return TRUE; } ms_get_b_release(0,&n,&x,&y); if(n) { set_mouse_event(0,RC_MOUSERELEASE); return TRUE; } ms_get_b_release(1,&n,&x,&y); if(n) { set_mouse_event(1,RC_MOUSERELEASE); return TRUE; } ms_get_b_release(2,&n,&x,&y); if(n) { set_mouse_event(2,RC_MOUSERELEASE); return TRUE; } ms_read_motion(&x,&y); if(x || y) { set_mouse_event(0,RC_MOUSEMOTION); return TRUE; } } if(current_demo_mode==RUN_DEMO || kbhit()) { mouse_event=FALSE; return TRUE; } return FALSE; } void set_demo_mode(demo_mode mode, char *fname, unsigned del_time) { current_demo_mode = mode; demo_delay = del_time; switch(mode) { case NO_DEMO : break; case PREPARE_DEMO : demo_keys=Fopen(fname,"wb"); break; case RUN_DEMO : demo_keys=Fopen(fname,"rb"); } } demo_mode get_demo_mode(void) { return current_demo_mode; } void close_demo_mode(void) { if(current_demo_mode != NO_DEMO) fclose(demo_keys); } char ml_getch(void) { char ch; if(current_demo_mode == RUN_DEMO) { ch=fgetc(demo_keys); delay(demo_delay); } else ch=getch(); if(current_demo_mode == PREPARE_DEMO) fputc(ch,demo_keys); return ch; } ml_retcode_t wait(void) { unsigned ch; int i; if(mouse_present) ms_show(); INTERFACE(emulate_cursor,(cur_win->xpos,cur_win->ypos)); while(current_demo_mode != RUN_DEMO && !ml_issignal()); if(mouse_present) ms_hide(); if(mouse_event) { ch=mouse_retcode; for(i=0; i < 5; i++) { mouse_event=FALSE; ml_issignal(); /* Сброс сигналов мыши */ } mouse_event=FALSE; return ch; } if((ch=ml_getch()) == 0) ch = ml_getch() << 8; return (ml_retcode_t) ch; } static ml_retcode_t edit_str_buf( int x, int y, char *str0, char *str1, int maxlen, int pos, char *prompt, int pr_col, int str_col, char *ord_exits, char *ext_exits, int show_only) /* x, y - begin of string position str0 - string to edit str1 - result string maxlen - max length of the result *endchar - last char before exit from function pos - starting position prompt - prompt pr_col - color of the prompt str_col - color of the string ord_exits - string of key codes to exit (ordinary keys) ending by '\0' ext_exits - string of key codes to exit (extended keys) ending by '\0' show_only - don't get characters, exit after printing whether 1 is set */ { int len,stop,i,x0,y0; char ch; ml_retcode_t wt; static int insert=1; store_scr_state(); strcpy(str1,str0); len=strlen(str1); if(!show_only)PRINTF("3.1:x=%d;"); winfwritexy(x,y,pr_col,prompt); x0=x+strlen(prompt); y0=y; winfwritexy(x0,y0,str_col,str1); stop=0; wt=0; if(!show_only) show_cursor(); do{ ml_gotoxy(x0,y0); if(wt!=RC_MOUSEMOTION) { /* С прошлого прохода цикла */ for(i=0; i <= maxlen; i++) winfwritexy(x0+i,y0,str_col," "); ml_gotoxy(x0,y0); winfwritexy(x0,y0,str_col,str1); if(show_only) break; ml_gotoxy(x0+pos,y0); } wt=wait(); if(MOUSE(wt)) { if(wt != RC_MOUSEMOTION) stop=1; } else if(SPEC(wt)) { ch=wt >> 8; if(ch == _LEFT) { if(pos > 0) pos--; } else if(ch == _RIGHT) { if(pos < len) pos++; } /* else if(ch == _INS) insert = !insert; */ else if(ch == _DEL) { if(pos != len) { for(i=pos; i <= len; i++) str1[i]=str1[i+1]; len--; } } else if(in_str(ch,ext_exits)) stop=1; } else { /* ch != 0 */ if(wt >= 32 /* ' ' буква */){ if(insert) if(len < maxlen) for(i=len+1; i >= pos; i--) str1[i+1]=str1[i]; if(pos != maxlen) str1[pos]=wt; if(len < maxlen) { if(pos <= len ) pos++; len++; } else if(pos < len) pos++; } else if(wt == _BACKSPACE) { if(pos != 0) { for(i=pos-1; i <= len; i++) str1[i]=str1[i+1]; pos--; len--; } } else if(in_str(wt,ord_exits)) stop=1; } } while(!stop); restore_scr_state(); return wt; } static ml_retcode_t edit_enum( int x, int y, int val, char **strings, int *ival2, int maxlen, char *prompt, int prcol, int acol, char *hk, char *hk0, int show_only) { string s; ml_retcode_t ch; int x0,y0; winfwritexy(x,y,prcol,prompt); x0=x+strlen(prompt); y0=y; do{ sprintf(s,"%*s",maxlen,strings[val]); winfwritexy(x0,y0,acol,s); if(show_only) return _ESC; if(was_mouse && mouse_retcode==RC_MOUSEBUTTON) ch=_ENTER; else ch=wait(); was_mouse=FALSE; *ival2=val; if(MOUSE(ch)) { if(ch != RC_MOUSEMOTION) return ch; } else if(SPEC(ch)) { if(in_str(GETK0(ch),hk0)) return ch; } else if(ch==_ENTER || was_mouse) { if(strings[++val]==NULL) val=0; } else if(in_str(ch,hk)) return ch; } while(1); } static ml_retcode_t edit_real_int_string(int x, int y, int maxlen, int prcol, int acol, char *prompt, char *hk, char *hk0, void *val, int type, int show_only, int (*valid)(void *)) { double val2; int k,ival2,good,stop; ml_retcode_t ch; char c; ENUM_def_t *Edp; char str[100],str1[100]; switch(type){ case DOUBLE: sprintf(str,"%+f",*(double *)val); str[maxlen]='\0'; break; case INT : sprintf(str,"%+d",*(int *)val); str[maxlen]='\0'; break; case STRING: strcpy(str,(char *) val); str[maxlen]='\0'; break; case ENUM : Edp= (ENUM_def_t *) val; } /* maxlen=fmax(maxlen,strlen(str)+5); */ do{ if(type==INT || type==STRING || type==DOUBLE) ch=edit_str_buf(x,y,str,str1,maxlen,0,prompt, prcol,acol, /* ord_exits, ext_exits, */ hk, hk0, show_only); else if(type==ENUM) ch=edit_enum(x,y,*Edp->variable,Edp->names,&ival2, maxlen,prompt,prcol,acol,hk,hk0,show_only); if(show_only) return _ESC; switch(type) { case DOUBLE: if(good=sscanf(str1,"%lf",&val2) && (k=sscanf(str1,"%lf%c",&val2,&c)) == 1) if(valid) good=(*valid)(&val2); if(good) *(double *)val=val2; else beep(); break; case INT : if(good=sscanf(str1,"%d",&ival2) && (k=sscanf(str1,"%d%c",&ival2,&c)) == 1) if(valid) good=(*valid)(&ival2); if(good) *(int *)val=ival2; else beep(); break; case STRING: k=1; if(valid) { good=(*valid)(str1); k=good==1; } else good=1; if(good) strcpy((char *)val,str1); else beep(); break; case ENUM: k=1; if(valid) { good=(*valid)(&ival2); k=good==1; } else good=1; if(good) *Edp->variable=ival2; else beep(); break; } if(good) field_was_changed=1; if(MOUSE(ch)) stop=1; else stop=in_str(ch,hk) || in_str(GETK0(ch),hk0); } while(k!=1 || !stop); return ch; } void show_edf(edit_field_t *ef, int col) { edit_real_int_string(ef->x,ef->y,ef->maxlen,0,col,ef->prompt,ef->hk,ef->hk0, ef->variable,ef->type,1,NULL); } ml_retcode_t edit_value(edit_field_t *ef) { int ch; ch=edit_real_int_string(ef->x,ef->y,ef->maxlen,0,ef->act_col,ef->prompt,ef->hk,ef->hk0, ef->variable,ef->type,0,ef->valid); return ch; } void edit_values(int n, edit_field_t *fields) { int i; edit_field_t *ef; char ch; for(i=0; i < n; i++) { ef=fields+i; show_edf(ef,ef->pas_col); } i=ch=0; do{ ef=fields+i; edit_value(ef); if(ch==_TAB) i=(i+1) % n; }while(ch != _ESC); } void paste_comm(menu_t *mnu, menu_item_t *item, int active) { int x,y,ac; x=mnu->winx+item->menx; y=mnu->winy+item->meny; winfwritexy(x,y,item->pas_col,item->s); if(item->edf){ item->edf->prompt=""; gotoxy((item->edf->x=x+strlen(item->s))+1, (item->edf->y=y)+1); show_edf(item->edf,item->pas_col); } if(active) { ac=cur_win->act_col; winfwritexy(mnu->comwx,mnu->comwy, (ac >> 4)+(ac & 0xF0), item->comment); } } static void show_item(menu_t *mnu, menu_item_t *item, int x, int y, int active) { string buf; if(absx(x) < cur_win->x1 || absx(x) > cur_win->x2 || absy(y) < cur_win->y1 || absy(y) > cur_win->y2) { sprintf(buf,"Bad item coordinates:x=%d,y=%d",x,y); error(buf); } if(active) PRINTF("si:x=%d;",x); winfwritexy(x,y, item->enabled_now ? (active ? item->act_col : item->pas_col) : item->disabled_col, item->s); if(active) winfwritexy(mnu->comwx,mnu->comwy,item->act_col,item->comment); if(item->edf){ item->edf->prompt=""; ml_gotoxy((item->edf->x=x+strlen(item->s)), (item->edf->y=y)); show_edf(item->edf,item->pas_col); } } static void loop_dec(int *i, int upb) { if(!(*i)) *i=upb-1; else (*i)--; } static void loop_inc(int *i, int upb) { if(*i >= upb-1) *i=0; else (*i)++; } /* Функции для скроллинга */ static int _shift_x(window_t *wnd, menu_t *mnu, int citem) { int d,x,width; menu_item_t *p_mi; d=wnd->x2 - wnd->x1 + 1; p_mi=mnu->items+citem; x=mnu->winx+p_mi->menx; width=strlen(p_mi->s); if(p_mi->edf) width += p_mi->edf->maxlen; if(x < 0) return -x; else if(x+width > d) return d-x-width; else return 0; } static int shift_x(menu_t *mnu) /* Определяет значение сдвига меню по горизонтали, то есть величину, прибавляемую к mnu->winx. Если 0, то сдвигать не надо */ { return _shift_x(cur_win,mnu,mnu->cur_item); } static int _shift_y(window_t *wnd, menu_t *mnu, int citem) { int d,y; d=wnd->y2 - wnd->y1 + 1; y=mnu->winy+mnu->items[citem].meny; if(y < 0) return -y; else if(y >= d) return d-y-1; else return 0; } static int shift_y(menu_t *mnu) /* Определяет значение сдвига меню по вертикали, то есть величину, прибавляемую к mnu->winy. Если 0, то сдвигать не надо */ { return _shift_y(cur_win,mnu,mnu->cur_item); } static void show_menu_wt_scroll(menu_t *mnu) { int i,k,p; for(i=0; i < mnu->nitems; i++){ k=_shift_x(cur_win,mnu,i); p=_shift_y(cur_win,mnu,i); if((k==0) && (p==0)) show_item(mnu,mnu->items+i,mnu->winx+mnu->items[i].menx, mnu->winy+mnu->items[i].meny,0); } } void wipe_item(menu_t *mnu, int citem) { int width,x,y; menu_item_t *p_mi; string buf; p_mi=mnu->items+citem; width=strlen(p_mi->s); if(p_mi->edf) width += p_mi->edf->maxlen+1; x=mnu->winx+p_mi->menx; y=mnu->winy+mnu->items[citem].meny; winfwritexy(x,y,cur_win->act_col,fillchar(buf,width,' ')); } void wipe_menu(menu_t *mnu) { int i; for(i=0; i < mnu->nitems; i++){ if(_shift_x(cur_win,mnu,i)==0 && _shift_y(cur_win,mnu,i)==0) wipe_item(mnu,i); } } static void activate_scroll(menu_t *mnu, int menu_on_screen) { int shiftx,shifty; shiftx=shift_x(mnu); shifty=shift_y(mnu); if((shiftx || shifty) && menu_on_screen) wipe_menu(mnu); mnu->winx+=shiftx; mnu->winy+=shifty; if(!menu_on_screen || shiftx!=0 || shifty!=0) show_menu_wt_scroll(mnu); } void show_menu(menu_t *mnu, int winx, int winy, int comwx, int comwy, int cur_item, menu_item_t *items, int nitems, char *hotkeys, char *hotkeys0) { chkinit(); if(winx < 0 || winx > (cur_win->x2-cur_win->x1) || winy < 0 || winy > (cur_win->y2-cur_win->y1)) error("Bad menu coordinates"); mnu->winx=winx; mnu->winy=winy; mnu->comwx=comwx; mnu->comwy=comwy; mnu->active_now=1; mnu->items=items; mnu->nitems=nitems; mnu->cur_item=cur_item; mnu->mode=ML_STANDARD_MODE; strcpy(mnu->hotkeys,hotkeys); strcpy(mnu->hotkeys0,hotkeys0); if(cur_item < 0 || cur_item >= nitems) error("Bad current item"); activate_scroll(mnu,0); /* hide_current_item(mnu); */ } void set_menu_mode(menu_t *mnu, unsigned mode) { mnu->mode=mode; } void hide_current_item(menu_t *mnu) { paste_comm(mnu,mnu->items+mnu->cur_item,1); } void menu_next(menu_t *mnu) { menu_item_t *citem=mnu->items+mnu->cur_item; paste_comm(mnu,citem,1); if(!(mnu->mode & ML_NOLOOPS) || ((mnu->mode & ML_NOLOOPS) && mnu->cur_item < mnu->nitems-1) ) loop_inc(&(mnu->cur_item),mnu->nitems); } void menu_down(menu_t *mnu) { menu_item_t *citem=mnu->items+mnu->cur_item; int x,y,x0,y0,cx,cy,i0,i; paste_comm(mnu,citem,1); if(!(mnu->mode & ML_4DIRECT)) { menu_next(mnu); return; } cx=citem->menx; cy=citem->meny; x0=-1000; y0=1000; i0=-1; for(i=0; i < mnu->nitems; i++){ citem=mnu->items+i; x=citem->menx; y=citem->meny; if(y > cy && y <= y0 && abs(x-cx) <= abs(x0-cx) && (x != cx || y != cy)) { i0=i; x0=x; y0=y; } } if(i0 != -1) mnu->cur_item=i0; } void menu_pred(menu_t *mnu) { menu_item_t *citem=mnu->items+mnu->cur_item; paste_comm(mnu,citem,1); if(!(mnu->mode & ML_NOLOOPS) || ((mnu->mode & ML_NOLOOPS) && mnu->cur_item > 0) ) loop_dec(&(mnu->cur_item),mnu->nitems); } void menu_up(menu_t *mnu) { menu_item_t *citem=mnu->items+mnu->cur_item; int x,y,x0,y0,cx,cy,i0,i; paste_comm(mnu,citem,1); if(!(mnu->mode & ML_4DIRECT)) { menu_pred(mnu); return; } cx=citem->menx; cy=citem->meny; x0=-1000; y0=-1000; i0=-1; for(i=0; i < mnu->nitems; i++){ citem=mnu->items+i; x=citem->menx; y=citem->meny; if(y < cy && y >= y0 && abs(x-cx) <= abs(x0-cx) && (x != cx || y != cy)) { i0=i; x0=x; y0=y; } } if(i0 != -1) mnu->cur_item=i0; } void set_item(window_t *wnd, menu_t *mnu, int item, boolean show) { window_t *old_win=getcurwin(); menu_item_t *citem; if(item < 0 || item >= mnu->nitems) error("Wrong item number"); set_active_window(wnd); hide_current_item(mnu); if(mnu->mode & ML_NOHIDE && show) { citem=mnu->items+item; show_item(mnu,citem,mnu->winx+citem->menx,mnu->winy+citem->meny,1); } mnu->cur_item=item; set_active_window(old_win); } int mouse_in_menu(window_t *wnd, menu_t *mnu, int show) /* Возвращает N пункта меню, иначе -1 */ { int i,x1,y1,xm1,ym1,dxy=0; if(wnd->border != NO_BORDER) dxy=1; if(!mouse_in_bar((x1=wnd->x1)-dxy,(y1=wnd->y1)-dxy,wnd->x2+dxy,wnd->y2+dxy)) return -1; if(!mnu) return 1; /* Просто проверка, что мышь в окне */ for(i=0; i < mnu->nitems; i++) if(!_shift_x(wnd,mnu,i) && !_shift_x(wnd,mnu,i)) { xm1=x1+mnu->winx+mnu->items[i].menx; ym1=y1+mnu->winy+mnu->items[i].meny; if(mouse_in_bar(xm1,ym1, xm1+strlen(mnu->items[i].s) +(mnu->items[i].edf ? mnu->items[i].edf->maxlen : 0),ym1) ) { set_item(wnd,mnu,i,show); return i; } } return -1; } static ml_retcode_t _choose_from_menu(menu_t *mnu) { int i,m; ml_retcode_t ch; menu_item_t *citem; int x,y; ch=0; was_mouse=FALSE; do{ activate_scroll(mnu,1); citem=&(mnu->items[mnu->cur_item]); x=mnu->winx+citem->menx; y=mnu->winy+citem->meny; if(ch != RC_MOUSEMOTION || !was_mouse) /* Символ с прошлого прохода цикла */ show_item(mnu,citem,x,y,1); if(citem->edf){ citem->edf->prompt=""; citem->edf->x=x+strlen(citem->s); citem->edf->y=y; ch=edit_value(citem->edf); hide_cursor(); } else { if(was_mouse && ch==0) /* Символ с прошлого прохода цикла */ ch=_ENTER; /* Чтобы "нажать" этот пункт меню */ else ch=wait(); } was_mouse=MOUSE(ch); if(ch==RC_MOUSEBUTTON || ch==RC_MOUSERELEASE && !in_str(CH_MOUSERELEASE,mnu->hotkeys0)) { if((m=mouse_in_menu(getcurwin(),mnu,FALSE)) != -1) { hide_current_item(mnu); mnu->cur_item=m; ch=0; } else if(ch == RC_MOUSEBUTTON && !(mnu->mode & ML_NOMOUSEEXTESC) && mouse_in_menu(getcurwin(),NULL,FALSE) == -1) return _ESC; } /* else was_mouse=FALSE; */ if(ch) { if(in_str(ch,mnu->hotkeys)) return ch; else if(in_str(GETK0(ch),mnu->hotkeys0)) return ch; else if(ch==_ENTER && citem->enabled_now) return citem->retcode; else if(GETK0(ch)==_UP) menu_up(mnu); else if(GETK0(ch)==_LEFT) menu_pred(mnu); else if(GETK0(ch)==_RIGHT) menu_next(mnu); else if(GETK0(ch)==_DOWN) menu_down(mnu); else for(i=0,citem=mnu->items; i < mnu->nitems; i++,citem++) if((in_str(ch,citem->hotkeys) || in_str(GETK0(ch),citem->hotkeys0)) && citem->enabled_now) return citem->retcode; } if(ch != 0 && ch != RC_MOUSEMOTION) was_mouse=FALSE; } while(1); } ml_retcode_t choose_from_menu(menu_t *mnu) { ml_retcode_t ch; ch=_choose_from_menu(mnu); if(!(mnu->mode & ML_NOHIDE)) hide_current_item(mnu); return ch; } boolean check_field_changed(void) { boolean b; b=field_was_changed; field_was_changed=0; return b; } boolean set_video_interface(video_interface_t *interface, boolean do_close_old, void *close_old_par, boolean do_init, void *init_par) { boolean good; video_interface_t *old_int; chkinit(); if(do_close_old) good=INTERFACE(close,(close_old_par)); else good=TRUE; if(good) { old_int=cur_intf; cur_intf=interface; if(do_init) if((good=INTERFACE(initialize,(init_par)))==FALSE) cur_intf=old_int; } return good; } video_interface_t *get_cur_interface(void) { return cur_intf; } boolean set_start_interface(video_interface_t *interface, boolean do_init, void *init_par) { cur_intf=interface; mouse_init(); if(do_init) return INTERFACE(initialize,(init_par)); return TRUE; } boolean close_video_interface(boolean do_close_old, void *close_old_par) { boolean good=TRUE; chkinit(); if(do_close_old) good=INTERFACE(close,(close_old_par)); cur_intf=NULL; return good; }