#include #include #include "diadef.h" #include "dialog.h" #include "internal.h" PRIVATE void DIALOG::showtimeout(WINDOW *win) { int t = dialog_getcurtimeout(); if (t > 0){ wmove(win, internal->height-1,internal->width-6); wattrset(win, dialog_attr); char buf[10]; sprintf (buf,"%3d ",t); waddstr (win,buf); } } PRIVATE void DIALOG::showterm (int &nof, int but_options) { if (internal->cursw == NULL){ internal->cursw = dialog_openwin (internal->height,internal->width); } // We ajust the current field so it is visible and valid // This may happen because the application is allowed to change the // current field (nof) as needed. if (nof >= getnb()) nof = getnb()-1; if (nof < 0) nof = 0; if (nof < internal->offset){ setoffset (nof); }else{ // We must make sure nof sits between the first visible field // and the last one. We know how many fields are visible // but there are hidden fields (newlines, gui fields) which are // not displayed in text mode. So we have to count int size = 0; for (int i=internal->offset; i= internal->nbvisible){ // Ok, we are at the end of the page and the current // field is still not visible. int newoff = nof; // The first visible field become // the current one // But is this acceptable. We must no scroll past the // last field. size = 0; for (int j=getnb()-1; j>=0; j--){ size += getitem(j)->vsize; if (size >= internal->nbvisible){ if (j < newoff) newoff = j; break; } } setoffset (newoff); break; }else if (i== nof){ // Ok, the current field is visible break; }else{ size += getitem(i)->vsize; } } } draw(internal->cursw); wrefresh(internal->cursw); } PRIVATE MENU_STATUS DIALOG::editterm( int &nof, int but_options) { MENU_STATUS ret = MENU_NULL; WINDOW *dialog = internal->cursw; skipprotect (nof,KEY_DOWN,dialog); dialog_starttimeout(); showtimeout(dialog); int last_nof = nof; bool arrow_up = false; bool arrow_down = false; bool grab = false; diagui_resetmsg(); while (ret == MENU_NULL) { drawarrow_if (dialog,internal->offset>0,arrow_up,true,ACS_UARROW); drawarrow_if (dialog,internal->offset+internal->nbvisiblebuttons->draw (dialog,internal->button); if (internal->button == -1){ if (last_nof != nof && last_nof >= internal->offset && last_nof < internal->offset + internal->nbvisible){ getitem(last_nof)->unselect(dialog,internal->hoffset); } if (nof >= 0 && nof < getnb()){ getitem(nof)->setcursor (dialog,internal->hoffset); } last_nof = nof; } int key = dialog_wgetch(internal->cursw,ret); /* #Specification: F3 key / escape F3 was not used in Linuxconf and some people claims it is fairly common as an equivalent for the escape key. So linuxconf support both! Comments are welcome. */ bool let_field = false; // Let the field process the key INTERCEPT *inter = NULL; for (int i=0; iintercepts.size(); i++){ INTERCEPT *s = internal->intercepts.getitem(i); if (s->key == key){ inter = s; break; } } if (grab){ if (key == ESC){ grab = false; }else{ let_field = true; } }else if (inter != NULL){ dialog_sendmessage (*inter->msg); ret = MENU_MESSAGE; break; }else if (key == ESC || key == KEY_F(3)){ ret = MENU_ESCAPE; break; }else if (key == KEY_LEFT && internal->waitprivmsg.lookup (&dialog_keyleft) != -1){ // This is a hack to allow some dialog control over the left // key. Same thing for the right key. So far, used by the // treemenu module. dialog_sendmessage(dialog_keyleft); ret = MENU_MESSAGE; }else if (key == KEY_RIGHT && internal->waitprivmsg.lookup (&dialog_keyright) != -1){ dialog_sendmessage(dialog_keyright); ret = MENU_MESSAGE; }else if (key == CTRLC){ dialog_sendmessage(dialog_controlc); if (internal->waitprivmsg.lookup (&dialog_controlc) != -1){ ret = MENU_MESSAGE; // Ok the caller expect this message }else{ ret = MENU_ESCAPE; // Hack. We really want the application // to end } break; }else if (ret == MENU_INTERNAL_TIMEOUT){ // Update the timeout counter at the bottom showtimeout(dialog); ret = MENU_NULL; }else if (ret != MENU_NULL){ break; }else if (internal->button != -1 || key == KEY_F(1)){ ret = internal->buttons->dokey (dialog,key,internal->button ,getnb()>0); }else if (keymove(dialog,key,nof)==-1){ switch (key) { case TAB: internal->button = 0; internal->buttons->draw(dialog,internal->button); break; case '\n': if (but_options & MENUBUT_OK){ ret = MENU_OK; }else if (getnb()==1){ /* #Specification: dialogue / single field case A in a dialogue with a single field exit as the first button was selected (Generally ) If the dialog contain a button it does the same whatever the number of fields. This is a special case for menu dialog. */ internal->button = 0; ret = internal->buttons->dokey (dialog,key ,internal->button,1); }else{ keymove (dialog,KEY_DOWN,nof); } break; default: let_field = true; } } if (let_field){ if (nof < getnb() && nof > -1) { FIELD_MSG msg; ret = getitem(nof)->dokey (dialog,key,msg,grab); if (msg.is_loaded) processmsg(dialog,msg); } } } attr_clear(stdscr, LINES, COLS, screen_attr); wnoutrefresh(stdscr); #if 0 fprintf (stderr,"Leaving nof=%d offset=%d\n",nof,internal->offset); for (int i=0; ibox.y); } #endif return ret; } PUBLIC INTERCEPT::INTERCEPT(int _key, PRIVATE_MESSAGE &_msg) { key = _key; msg = &_msg; } PUBLIC void DIALOG::add_intercept (int key, PRIVATE_MESSAGE &msg) { internal->intercepts.add (new INTERCEPT(key,msg)); }