#include #include #include "window.h" #include "standard.h" #include "input.h" #include "dialog.h" // // MEMBER FUNCTIONS OF THE BASE CLASS // ================================== BaseObject::BaseObject(int _x,int _y,int _w,int _h,color _fg,color _bg) { x=_x; y=_y; w=_w; h=_h; bg=_bg; fg=_fg; } // // MEMBER FUNCTIONS OF THE ROOT CLASS // ================================== RootObject::RootObject(int _x,int _y,int _w,int _h,color fg,color bg,frame_t fr,unsigned sz) :BaseObject(0,0,0,0,fg,bg) { window=new Window(_x,_y,_w,_h,fg,bg,fr); x=window->X(); y=window->Y(); w=window->W(); h=window->H(); first=last=NULL; size=sz; nextoffset=0; data=NULL; current=NULL; } RootObject::~RootObject() { delete window; } void RootObject::Draw() { DataObject *draw; window->Fill(bg); window->DrawFrames(); draw=first; do { draw->Draw(); draw=draw->next; } while(draw!=first); } RootObject& RootObject::operator+=(DataObject& add) { unsigned sz; if (first==NULL) { first=last=&add; add.root=this; add.prev=add.next=&add; } else { add.root=this; add.next=first; add.prev=last; last->next=&add; last=&add; first->prev=&add; } sz=add.offset; add.offset=this->nextoffset; this->nextoffset+=sz; return *this; } DataObject* RootObject::GetNext(DataObject *current) { DataObject *ret=current->next; while (! ret->IsSelectable()) { ret=ret->next; if (ret==current && !ret->IsSelectable()) {ret=NULL;break;} } return ret; } DataObject* RootObject::GetPrev(DataObject *current) { DataObject *ret=current->prev; while (! ret->IsSelectable()) { ret=ret->prev; if (ret==current && !ret->IsSelectable()) {ret=NULL;break;} } return ret; } int RootObject::Exec(void *data_adr) { DataObject *search,*lastdata; int key; int clean=1; if (first==NULL) error("Cannot execute an object, which do not have any members"); if (size!=nextoffset) error("Size of a data structure do not match with dialog members"); if (size && data_adr==NULL) error("The data address must be specified when calling non-empty Dialog"); data=(char*)data_adr; exit_code=-1; if((lastdata=search=GetNext(last))==NULL) { Draw(); window->HideCursor(); window->GetKey(); } else { do { search->data=search->ReadData(); search=GetNext(search); } while (search!=lastdata); Draw(); if (current==NULL) current=GetNext(last); current->HighLight(); // Read key from the window while(exit_code<0) { if (clean) window->HideCursor(); key=window->GetKey(); if (current->HandleKey(clean,key)) clean=0; else { // Handle Shortcut keys lastdata=search=GetNext(last); do { if (toupper(search->shortcut)==toupper(key)) { key=0; break; } search=GetNext(search); } while (search!=lastdata); if (key==0) (current=search)->HandleKey(0,ENTER); // Handle other keys else switch(key) { case ESC: exit_code=0; break; case ENTER: case TAB: case RIGHT: case DOWN: current->Draw(); current=GetNext(current); current->HighLight(); clean=1; break; case LEFT: case UP: current->Draw(); current=GetPrev(current); current->HighLight(); clean=1; break; } } } lastdata=search=GetNext(last); do { search->SaveData(); search=GetNext(search); } while (search!=lastdata); } return exit_code; } // // MEMBER FUNCTIONS OF THE DATA CLASS // ================================== DataObject::DataObject(int _x,int _y,int _w,int _h,color fg,color bg,unsigned sz,int key) :BaseObject(_x,_y,_w,_h,fg,bg) { root=NULL; next=prev=NULL; offset=sz; shortcut=key; } void DataObject::Draw() { int i,j; if (w && h) { if (bg==NO_COLOR) bg=root->bg; if (fg==NO_COLOR) fg=root->fg; set_colors(fg,bg); for(i=0;i=4) i-=4; else i+=4; bg=(color)i; Draw(); bg=savecol; } unsigned DataObject::StringLength(char *str) { unsigned len=0; if (str!=NULL) while(*str++) len++; return len; } unsigned DataObject::StringLines(char *str) { unsigned lines=1; if (str!=NULL) do if (*str=='\n') lines++; while (*str++); return lines; } char *DataObject::ReadData() { return NULL; } void DataObject::SaveData() {} // // MEMBER FUNCTIONS OF THE BOX CLASS // ================================= Box::Box(int _x,int _y,int _w,int _h,color fg,color bg,unsigned size) :RootObject(_x,_y,_w,_h,fg,bg,NO_FRAME,size) {} // // MEMBER FUNCTIONS OF THE FRAME CLASS // =================================== Frame::Frame(int _x,int _y,int _w,int _h,color fg,color bg,unsigned size,char *title) :RootObject(_x,_y,_w,_h,fg,bg,FRAME_222,size) { window->SetTitle(title); } // // MEMBER FUNCTIONS OF THE TEXT CLASS // ================================== Text::Text(int _x,int _y,int _w,format f,color fg,color bg,unsigned size) :DataObject(_x,_y,_w,1,fg,bg,size,0) { orientation=f; } void Text::Draw() { int len; char *txt; DataObject::Draw(); txt=ContentOf(); len=StringLength(txt); switch(orientation) { case Left: gotoxy(x,y); break; case Right: gotoxy(x+w-len,y); break; case Center: gotoxy(x+(w-len)/2,y); break; } print(txt); } // // MEMBER FUNCTIONS OF THE STATIC TEXT CLASS // ========================================= StaticText::StaticText(int x,int y,int w,char *txt,format f,color fg,color bg) :Text(x,y,w,f,fg,bg,0) { text=txt; } char *StaticText::ContentOf() { return text; } // // MEMBER FUNCTIONS OF THE STRING CLASS // ==================================== String::String(int x,int y,int w,format f,color fg,color bg) :Text(x,y,w,f,fg,bg,sizeof(char*)) {} char *String::ContentOf() { return *(char**)(root->data+offset); } // // MEMBER FUNCTIONS OF THE CHAR ARRAY CLASS // ======================================== CharArray::CharArray(int x,int y,int w,unsigned size,format f,color fg,color bg) :Text(x,y,w,f,fg,bg,size) {} char *CharArray::ContentOf() { return (char*)(root->data+offset); } // // MEMBER FUNCTIONS OF THE INTEGER CLASS // ===================================== Integer::Integer(int x,int y,int w,format f,color fg,color bg) :Text(x,y,w,f,fg,bg,sizeof(int)) {} char *Integer::ContentOf() { static char isave[20]; return itoa(*(int*)(root->data+offset),isave,10); } // // MEMBER FUNCTIONS OF THE FIELD CLASS // =================================== Field::Field(int _x,int _y,char *frm,color fg,color bg,unsigned size) :DataObject(_x,_y,0,1,fg,bg,size,0) { maxlen=StringLength(frm); w=maxlen+2; format=frm; } void Field::Draw() { DataObject::Draw(); printat(x+1,y,data); } int Field::HandleKey(int clean,int key) { int len,i; int valid=0; char *s,*d; // Where is a cursor ? len=StringLength(data); if (clean) { curx=len; if (len>maxlen) error("Initial value for EditField is too wide"); if (key>=32 && (key=ValidKey(0,key))) *data=len=curx=0; } // Handle a key key=ValidKey(curx,key); if (key>=32) { valid=1; if (lenwindow->Goto(x+curx+1,y); root->window->ShowCursor(); } return valid; } int Field::ValidKey(int x,int k) { char *str; if (k>=32) switch(format[x]) { case '\0': k=0; break; case 'x': if (k>=255) k=0; break; case '9': if (k<'0' || k>'9') k=0; break; case '+': if ((k<'0' || k>'9') && k!='+' && k!='-') k=0; break; case '0': if (k==',') k='.'; if (k=='.') { str=data; while (*str) if (*str++=='.') k=0; } else if (k<'0' || k>'9') k=0; break; case 'U': k=toupper(k); case 'u': if(x==0 || (unsigned char)*(data+x-1)<(unsigned char)'A') k=toupper(k); break; default: if (k != format[x]) k=0; } return k; } // // MEMBER FUNCTIONS OF THE INT FIELD CLASS // ======================================= IntField::IntField(int _x,int _y,char *frm,color fg,color bg) :Field(_x,_y,frm,fg,bg,sizeof(int)) {} char *IntField::ReadData() { return itoa(*(int *)(root->data+offset),new char[maxlen+1],10); } void IntField::SaveData() { *(int*)(root->data+offset)=atoi(data); } // // MEMBER FUNCTIONS OF THE CHAR FIELD CLASS // ======================================== CharField::CharField(int _x,int _y,char *frm,color fg,color bg) :Field(_x,_y,frm,fg,bg,StringLength(frm)+1) {} char *CharField::ReadData() { char *s,*d,*ret; d=ret=new char[maxlen+1]; s=root->data+offset; while((*d++=*s++)!='\0'); return ret; } void CharField::SaveData() { char *d,*s; d=root->data+offset; s=data; while((*d++=*s++)!='\0'); } // // MEMBER FUNCTIONS OF THE FLOAT FIELD CLASS // ========================================= FloatField::FloatField(int _x,int _y,char *frm,color fg,color bg) :Field(_x,_y,frm,fg,bg,sizeof(double)) {} char *FloatField::ReadData() { return NULL; // return gcvt(*(double*)(root->data+offset),maxlen,new char[maxlen+1]); } void FloatField::SaveData() { // *(double*)(root->data+offset)=atof(data); } // // MEMBER FUNCTIONS OF THE BUTTON CLASS // ==================================== Button::Button(int x,int y,char *txt,int key,color fg,color bg,unsigned size) :DataObject(x,y,StringLength(txt),1,fg,bg,size,key) { name=txt; } void Button::Draw() { int i,keyfound=0; color c; DataObject::Draw(); gotoxy(x+1,y+1); set_colors(BLACK,root->bg); for(i=w;i--;plot('ß')); gotoxy(x+w,y); plot('Ü'); set_colors(fg,bg); gotoxy(x,y); for(i=0;name[i];i++) if(!keyfound && toupper(name[i])==toupper(shortcut)) { if (fg==BLACK) c=WHITE; else c=BLACK; root->window->Fg(c); plot(name[i]); root->window->Fg(fg); keyfound=1; } else plot(name[i]); } void Button::HighLight() { bg++; Draw(); bg--; } // // MEMBER FUNCTIONS OF THE EXIT BUTTON CLASS // ========================================= ExitButton::ExitButton(int x,int y,char *txt,int ret,int key,color fg,color bg) :Button(x,y,txt,key,fg,bg,0) { value=ret; } int ExitButton::HandleKey(int,int key) { int valid=0; if (key==ENTER || key==32) { root->exit_code=value; valid=1; } return valid; } // // MEMBER FUNCTIONS OF THE COMMAND BUTTON CLASS // ============================================ CommandButton::CommandButton(int x,int y,char *txt,int key,void(*fn)(void*),unsigned size,color fg,color bg) :Button(x,y,txt,key,fg,bg,size) { function=fn; } int CommandButton::HandleKey(int,int key) { int valid=0; if (key==ENTER || key==32) { valid=1; root->Draw(); root->current->HighLight(); if (function) (*function)((void*)(root->data+offset)); root->Draw(); root->current->HighLight(); } return valid; } // // MEMBER FUNCTIONS OF THE NULL OBJECT CLASS // ========================================= NullObject::NullObject(unsigned size,int x,int y,int w,int h,color bg) :DataObject(x,y,w,h,NO_COLOR,bg,size,0) {} // // MEMBER FUNCTIONS OF THE USER OBBJECT CLASS // ========================================== UserObject::UserObject(int x,int y,int w,int h,void (*out)(Window *w),color fg,color bg) :DataObject(x,y,w,h,fg,bg,0,0) { output=out; } void UserObject::Draw() { DataObject::Draw(); root->window->Color(fg,bg); root->window->SetOrigin(x,y); root->window->Goto(0,0); (output)(root->window); root->window->SetOrigin(0,0); } ////////////////////////////////////////////////////////////////////////////// #if 0 void info(void *p) { char **str=(char**)p; Frame t(7,8,25,1,BLACK,RED,sizeof(char*)); t+=String(0,0,25); t.Exec(str); } void u_object(Window *w) { w->PrintAt(2,1,"OBJ"); } void main() { struct data { char a[27],b[27],c[27]; char f[9]; int n; char *null; char *info; }; data test={"Is this","Object","Oriented ?","0.1234",-201,"","That's info..."}; Frame dialog(15,4,30,12,WHITE,LIGHTGRAY,sizeof(data)); dialog+=StaticText(0,0,30,"Dialog",Center,RED); dialog+=StaticText(1,11,28,"F1=HELP",Right,RED); dialog+=CharField(1,3,"UUUUUUUUUUUUUUUUUUUUUUUUUU"); dialog+=CharField(1,5,"uuuuuuuuuuuuuuuuuuuuuuuuuu"); dialog+=CharField(1,7,"uuuuuuuuuuuuuuuuuuuuuuuuuu"); dialog+=CharField(1,9,"+0000000"); dialog+=IntField(1,11,"+999"); dialog+=ExitButton(12,10," OK ",1,'o'); dialog+=NullObject(sizeof(char*),0,1,30,1,RED); dialog+=CommandButton(20,9," Info ",'i',info,sizeof(char*)); dialog.Exec(&test); struct data2 { int i; char *str; }; data2 testdata2={1,"Tuesday 3:30 AM"}; Frame menu(30,14,20,15,WHITE,BLUE,sizeof(data2)); menu+=StaticText(0,0,20,"Menu",Center,YELLOW); menu+=IntField(1,0,"+",YELLOW,WHITE); menu+=String(0,14,20,Center); menu+=ExitButton(1,2," File ",1,'f'); menu+=ExitButton(1,4," Edit ",1,'e'); menu+=ExitButton(1,6," Search ",1,'s'); menu+=ExitButton(1,8," Run ",1,'r'); menu+=ExitButton(1,10," Compile ",1,'c'); menu+=ExitButton(1,12," Debug ",1,'d'); menu+=UserObject(13,2,5,4,u_object,YELLOW,GREEN); menu.Exec(&testdata2); } #endif