/* Project: Terminality * File: dlgc.cpp * Author: Michal Safranek * Description: Form editor */ const char dlgc_rcsid[] = "$Id: dlgc.cpp,v 1.4 2002/07/26 01:39:44 darkmoon Exp $"; #include #include #include #include #include #include #include /* Define if you have old list.c that doesn't support elem removal: */ /*#define NO_LIST_DELETE*/ /* elements: */ #define ELEM_NONE 0 #define ELEM_FORM 1 #define ELEM_MENU 2 #define ELEM_HMENU 3 #define ELEM_CHECKBOX 4 #define ELEM_RADIO 5 #define ELEM_TEXTBOX 6 #define ELEM_TEXTAREA 7 #define ELEM_BUTTON 8 #define ELEM_LABEL 9 #define ELEM_LISTING 10 #define ELEM_PBAR 11 /* struct for keeping element's address and type: */ struct elem_struct { int type; void *elem; int x,y,w,h; }; /* global vars: */ int ch, die = 0, hdie = 0, no_y_resize = 0, no_x_resize = 0; int base_element = ELEM_NONE; int current_element = ELEM_NONE, current_id = -1; hMenu *myhMenu = NULL; menu *myMenu = NULL; tn_list *elements = NULL; char *filename = NULL; int filesave_dlg(void){ button *b = new button(43, 12, 6, 1, " Save ", 2); form *fsForm = new form(21, 8, 36, 6); textbox *tb = new textbox(33,10,filename?filename:"", 21, 100); fsForm->addstatic(new staticLabel(23, 8, " Save file ")); fsForm->addstatic(new staticLabel(23, 10, "Filename:")); fsForm->addobject(tb); b->dflt = true; fsForm->addobject(b); if(!fsForm->run()){ delete fsForm; return 0;} while(*(tb->buf) == 0){ beep(); if(!fsForm->run()){ delete fsForm; return 0;} } if(filename){ xfree(filename); filename = NULL; } filename = (char *) xmalloc(strlen(tb->buf) + 1); sprintf(filename, "%s", tb->buf); delete fsForm; return 1; } int hilite_selected(void){ elem_struct *tmp; if(current_id == -1){ return 0; }else{ tmp = (elem_struct *) tn_list_getdata(elements, current_id); gotoxy(tmp->x, tmp->y); setcolor(LightRed, DarkGray); printw("."); update(); } return 1; } void del_elem(void *elem, int type){ switch(type){ case ELEM_NONE: beep(); break; case ELEM_FORM: delete (form *) elem; break; case ELEM_MENU: delete (menu *) elem; break; case ELEM_HMENU: delete (hMenu *) elem; break; case ELEM_LABEL: case ELEM_PBAR: delete (formStatic *) elem; break; case ELEM_CHECKBOX: case ELEM_RADIO: case ELEM_TEXTBOX: case ELEM_TEXTAREA: case ELEM_BUTTON: delete (formObject *) elem; break; case ELEM_LISTING: delete (listing *) elem; break; } } int delete_elements(void){ int i; elem_struct *es; assert(elements != NULL); for(i = 0; i < tn_list_size(elements); i++){ es = (elem_struct *) tn_list_getdata(elements, i); del_elem(es->elem, es->type); xfree(es); } tn_list_free(elements); tn_list_kill(elements); elements = NULL; return 1; } int draw_elements(void){ int i; elem_struct *es; assert(elements != NULL); for(i = 0; i < tn_list_size(elements); i++){ es = (elem_struct *) tn_list_getdata(elements, i); switch(es->type){ case ELEM_NONE: beep(); break; case ELEM_FORM: ((form *) es->elem)->draw(); break; case ELEM_MENU: ((menu *) es->elem)->draw(); break; case ELEM_HMENU: ((hMenu *) es->elem)->draw(); break; case ELEM_LABEL: case ELEM_PBAR: ((formStatic *)es->elem)->draw(); break; case ELEM_LISTING: ((listing *)es->elem)->draw(); break; case ELEM_CHECKBOX: case ELEM_RADIO: case ELEM_TEXTBOX: case ELEM_TEXTAREA: case ELEM_BUTTON: ((formObject *)es->elem)->draw(); break; } } hilite_selected(); return 1; } void *create_element(int elem, int x, int y, int w, int h){ void *fo; switch(elem){ default: case ELEM_NONE: beep(); fo = NULL; break; case ELEM_FORM: fo = new form(x, y, w, h); ((form *)fo)->visible = true; break; case ELEM_MENU: fo = (menu *) new menu( new menuItem("test", 1), new menuItem("menu", 2), new menuItem("...1", 3), new menuItem("...2", 4), new menuItem("...3", 5), new menuItem("...4", 6), new menuItem("...5", 7), new menuItem("...6", 8), new menuItem("...7", 9), new menuItem("...8", 10), new menuItem("...9", 11), new menuItem("..10", 12), new menuItem("..11", 13), new menuItem("..12", 14), new menuItem("..13", 15), new menuItem("..14", 16), new menuItem("..15", 17), new menuItem("..16", 18), new menuItem("..17", 19), new menuItem("..18", 20), new menuItem("..19", 21), new menuItem("..20", 22), new menuItem("..21", 23), new menuItem("..22", 24), new menuItem("..23", 25), new menuItem("..24", 26), NULL); ((menu *)fo)->x = x; ((menu *)fo)->y = y; ((menu *)fo)->setheight(h); ((menu *)fo)->visible = true; break; case ELEM_HMENU: fo = new hMenu( new hMenuItem("test", 1, 1), new hMenuItem("hMenu", 6, 2), NULL); ((hMenu *)fo)->y = y; ((hMenu *)fo)->visible = true; break; case ELEM_CHECKBOX: fo = new checkbox(x, y, 0, "check", w); break; case ELEM_RADIO: fo = new radio(NULL, 0, x, y, 0, "radio", w); break; case ELEM_TEXTBOX: fo = new textbox(x, y, "textb", w, w); break; case ELEM_TEXTAREA: fo = new textarea(x, y, w, h, "textarea"); break; case ELEM_BUTTON: fo = new button(x, y, w, h, "button", 1); break; case ELEM_PBAR: fo = new progressBar(x, y, w, h); ((progressBar *) fo)->setcur(50); ((progressBar *) fo)->show_perc = true; break; case ELEM_LABEL: fo = new staticLabel(x, y, "Label", COLOR_SLABEL_FG, COLOR_SLABEL_BG); break; case ELEM_LISTING: fo = new listing(x, y, w, h, new listingSeparator(x), new listingItem(x+1, w>0 ? w : 1, "test listing", NULL), new listingSeparator(x+1+w), NULL); ((listing *)fo)->visible = true; break; } return fo; } int element_to_list(int pos, int type, int x, int y, int w, int h){ elem_struct *es, *tmp; assert(type != ELEM_NONE); es = (elem_struct *) xmalloc(sizeof(elem_struct)); es->type = type; if(pos == -1){ x = 1; y = 2; w = 5; h = (type==ELEM_BUTTON || type == ELEM_PBAR)?1:2; } if((es->elem = create_element(type, x, y, w, h)) == NULL){ xfree(es); return 0; } es->x = x; es->y = y; es->w = w; es->h = h; if(pos == -1){ if(elements) tn_list_add(elements, es); else elements = tn_list_new(es); current_id = tn_list_size(elements) - 1; current_element = es->type; }else{ if(tn_list_size(elements) <= pos){ tn_list_add(elements, es); }else{ tmp = (elem_struct *) tn_list_getdata(elements, pos); del_elem(tmp->elem, tmp->type); memcpy(tmp, es, sizeof(elem_struct)); xfree(es); } } return 1; } #define CREATE(type) element_to_list(-1, type, -1, -1, -1, -1) int main(int argc, char **argv){ key k; int tx, ty, tw, th; elem_struct *tmp; #ifdef NO_LIST_DELETE list *temp_list; #endif int temp_elem, temp_id; int i; FILE *fd; if(argc > 1) xmem_want_debug = 1; // init console initcons(); set_cursor(none); clrscr(); myhMenu = new hMenu( new hMenuItem("Create", 0, 1), new hMenuItem("Move", 0, 2), new hMenuItem("Resize", 0, 3), new hMenuItem("Select", 0, 4), new hMenuItem("Deselect", 0, 8), new hMenuItem("Delete", 0, 5), new hMenuItem("Save", 0, 6), new hMenuItem("Reset", 0, 7), new hMenuItem("GrpMove", 0, 9), new hMenuItem("Exit", 76, 0), NULL); myhMenu->y = 1; do{ clrscr(); if(elements) draw_elements(); ch = myhMenu->getchoice(); switch(ch){ case -1:/* ESC */ beep(); break; case 1:/* Create */ hdie = 0; myMenu = new menu( new menuItem("Form", 1), new menuItem("Menu", 2), new menuItem("hMenu", 3), new menuItem("listing", 10), new menuSeparator(), new menuItem("checkbox", 4), new menuItem("radio", 5), new menuItem("textbox", 6), new menuItem("textarea", 7), new menuItem("button", 8), new menuItem("label", 9), new menuItem("pr. bar", 11), NULL); myMenu->x = 1; myMenu->y = 2; while(!hdie){ ch = myMenu->getchoice(); switch(ch){ case -1:/* ESC */ hdie = 1; break; case 1:/* Form */ if(base_element){ beep(); }else{ current_element = base_element = ELEM_FORM; CREATE(ELEM_FORM); hdie = 1; } break; case 2:/* Menu */ if(base_element){ beep(); }else{ current_element = base_element = ELEM_MENU; CREATE(ELEM_MENU); hdie = 1; } break; case 3:/* hMenu */ if(base_element){ beep(); }else{ current_element = base_element = ELEM_HMENU; CREATE(ELEM_HMENU); hdie = 1; } break; case 4:/* checkbox */ if(base_element != ELEM_FORM){ beep(); }else{ current_element = ELEM_CHECKBOX; CREATE(ELEM_CHECKBOX); hdie = 1; } break; case 5:/* radio */ if(base_element != ELEM_FORM){ beep(); }else{ current_element = ELEM_RADIO; CREATE(ELEM_RADIO); hdie = 1; } break; case 6:/* textbox */ if(base_element != ELEM_FORM){ beep(); }else{ current_element = ELEM_TEXTBOX; CREATE(ELEM_TEXTBOX); hdie = 1; } break; case 7:/* textarea */ if(base_element != ELEM_FORM){ beep(); }else{ current_element = ELEM_TEXTAREA; CREATE(ELEM_TEXTAREA); hdie = 1; } break; case 8:/* button */ if(base_element != ELEM_FORM){ beep(); }else{ current_element = ELEM_BUTTON; CREATE(ELEM_BUTTON); hdie = 1; } break; case 9:/* label */ if(base_element != ELEM_FORM){ beep(); }else{ current_element = ELEM_LABEL; CREATE(ELEM_LABEL); hdie = 1; } break; case 10:/* listing */ if(base_element != ELEM_NONE){ beep(); }else{ base_element = current_element = ELEM_LISTING; CREATE(ELEM_LISTING); hdie = 1; } break; case 11:/* progressBar */ if(base_element != ELEM_FORM){ beep(); }else{ current_element = ELEM_PBAR; CREATE(ELEM_PBAR); hdie = 1; } default: break; } } delete myMenu; break; case 2:/* Move */ if(current_element == ELEM_NONE){ beep(); }else{ hdie = 0; /* backup vals ... */ tmp = (elem_struct *) tn_list_getdata(elements, current_id); tx = tmp->x; ty = tmp->y; tw = tmp->w; th = tmp->h; while(!hdie){ tmp = (elem_struct *) tn_list_getdata(elements, current_id); clrscr(); if(elements) draw_elements(); k = readkey(); switch(k){ case KEY_TAB: if(tmp->x + tmp->w + 8 < CON_COLS){ tmp->x += 8; }else{ if(tmp->x + tmp->w == CON_COLS - 1){ beep(); }else{ tmp->x = CON_COLS - tmp->w - 1; } } break; case KEY_UP: if(tmp->y > 1) tmp->y--; else beep(); break; case KEY_DOWN: if(tmp->y + tmp->h + 1< CON_ROWS) tmp->y++; else beep(); break; case KEY_LEFT: if(tmp->x > 1) tmp->x--; else beep(); break; case KEY_RIGHT: if(tmp->x + tmp->w + 1 < CON_COLS) tmp->x++; else beep(); break; case KEY_ESC: hdie = 1; tmp->x = tx; tmp->y = ty; break; case KEY_ENTER: hdie = 1; break; default: beep(); break; } element_to_list(current_id, current_element, tmp->x, tmp->y, tmp->w, tmp->h); } } break; case 3:/* Resize */ hdie = 0; no_x_resize = 0; switch(current_element){ default: case ELEM_NONE: case ELEM_HMENU: case ELEM_LABEL: beep(); hdie = 1; break; case ELEM_TEXTBOX: case ELEM_RADIO: case ELEM_CHECKBOX: no_y_resize = 1; break; case ELEM_MENU: no_x_resize = 1; case ELEM_TEXTAREA: case ELEM_BUTTON: case ELEM_FORM: case ELEM_LISTING: case ELEM_PBAR: no_y_resize = 0; break; } if(hdie) break; /* backup vals ... */ tmp = (elem_struct *) tn_list_getdata(elements, current_id); tx = tmp->x; ty = tmp->y; tw = tmp->w; th = tmp->h; hdie = 0; while(!hdie){ clrscr(); if(elements) draw_elements(); k = readkey(); tmp = (elem_struct *) tn_list_getdata(elements, current_id); switch(k){ case KEY_UP: if(no_y_resize){ beep(); break; } if(tmp->h > 1) tmp->h--; else beep(); break; case KEY_DOWN: if(no_y_resize){ beep(); break; } if(tmp->type == ELEM_LISTING || tmp->type == ELEM_TEXTAREA || tmp->type == ELEM_PBAR){ if(tmp->y + tmp->h -1 < CON_ROWS) tmp->h++; else beep(); }else{ if(tmp->y + tmp->h + 1< CON_ROWS) tmp->h++; else beep(); } break; case KEY_LEFT: if(no_x_resize){ beep(); break; } if(tmp->w > 1) tmp->w--; else beep(); break; case KEY_RIGHT: if(no_x_resize){ beep(); break; } if(tmp->x + tmp->w + 1 < CON_COLS) tmp->w++; else beep(); break; case KEY_ESC: hdie = 1; break; case KEY_ENTER: hdie = 1; break; default: beep(); break; } element_to_list(current_id, current_element, tmp->x, tmp->y, tmp->w, tmp->h); } break; case 4:/* Select */ if(base_element == ELEM_NONE){ beep(); break;} temp_elem = current_element; temp_id = current_id; if(current_id != -1) i = current_id; else i = 0; if(current_id == -1) current_id = 0; hdie = 0; while(!hdie){ clrscr(); if(elements) draw_elements(); k = readkey(); switch(k){ case KEY_LEFT: case KEY_UP: if(current_id > 0){ current_id--; }else beep(); break; case KEY_RIGHT: case KEY_DOWN: if(current_id < tn_list_size(elements) - 1){ current_id++; }else beep(); break; break; case KEY_ESC: hdie = 1; current_id = i; break; case KEY_ENTER: hdie = 1; break; default: beep(); break; } current_element = ((elem_struct*)tn_list_getdata(elements,current_id))->type; } break; case 5:/* Delete */ if(current_element == ELEM_NONE){ beep(); }else{ if(current_id == -1){ beep(); break; } if(current_element == base_element && tn_list_size(elements) != 1){ beep(); break; } #ifdef NO_LIST_DELETE /* This solution is REALLY ugly, but i don't have enough * time to improve Emil's code (add tn_list_del support) * meybe later ... :( */ temp_list = NULL; for(i = 0; i < tn_list_size(elements); i++){ if(i != current_id){ if(temp_list) tn_list_add(temp_list, tn_list_getdata(elements, i)); else temp_list = tn_list_new(tn_list_getdata(elements, i)); }else{ tmp = (elem_struct *) tn_list_getdata(elements, i); del_elem(tmp->elem, tmp->type); xfree(tmp); tmp = NULL; } } tn_list_free(elements); elements = temp_list; temp_list = NULL; #else tmp = (elem_struct *) tn_list_getdata(elements, current_id); del_elem(tmp->elem, tmp->type); xfree(tmp); tmp = NULL; tn_list_delete(elements, current_id); #endif current_id = -1; if(base_element == current_element) base_element = ELEM_NONE; current_element = ELEM_NONE; } break; case 6:/* Save */ if(tn_list_size(elements) == 0){ beep(); }else{ if(!filesave_dlg()) break; if((fd = fopen(filename, "w")) == NULL){ beep(); break; } /* beep() 's NOT enough, but ... who cares? */ for(i = 0; i < tn_list_size(elements); i++){ tmp = (elem_struct *) tn_list_getdata(elements, i); switch(tmp->type){ case ELEM_NONE: break; case ELEM_FORM: fprintf(fd, "new form(%d, %d, %d, %d);\n", tmp->x, tmp->y, tmp->w, tmp->h); break; case ELEM_MENU: fprintf(fd, "myMenu = new menu(flds, NULL);\n" "myMenu->x = %d\nmyMenu->y = %d\n" "myMenu->setheight(%d);\n", tmp->x, tmp->y, tmp->h); break; case ELEM_HMENU: fprintf(fd, "myHMenu = new hMenu(flds, NULL);\n" "myHMenu->y = %d\n", tmp->y); break; case ELEM_CHECKBOX: fprintf(fd, "new checkbox(%d, %d, sel, label," " %d)\n", tmp->x, tmp->y, tmp->w); break; case ELEM_RADIO: fprintf(fd, "new radio(rGrp, id, %d, %d, sel," " label, %d);\n", tmp->x, tmp->y, tmp->w); break; case ELEM_TEXTBOX: fprintf(fd, "new textbox(%d, %d, buff, %d," " maxlen);\n", tmp->x, tmp->y, tmp->w); break; case ELEM_TEXTAREA: fprintf(fd, "new textarea(%d, %d, %d, %d," " content);\n", tmp->x, tmp->y, tmp->w, tmp->h); break; case ELEM_BUTTON: fprintf(fd, "new button(%d, %d, %d, %d, lbl," " id);\n", tmp->x, tmp->y, tmp->w, tmp->h); break; case ELEM_LABEL: fprintf(fd, "new staticLabel(%d, %d, str," " [f, b]);\n", tmp->x, tmp->y); break; case ELEM_LISTING: fprintf(fd, "new listing(%d, %d, %d, %d," " fields, NULL);\n", tmp->x, tmp->y, tmp->w, tmp->h); break; case ELEM_PBAR: fprintf(fd,"new progressBar(%d, %d, %d, %d);\n", tmp->x, tmp->y, tmp->w, tmp->h); break; } } fclose(fd); } break; case 0:/* Exit */ die = 1; if(base_element == ELEM_NONE) break; if(filename){ xfree(filename); filename = NULL; } case 7:/* Reset */ if(base_element == ELEM_NONE){ beep(); }else{ current_element = base_element = ELEM_NONE; if(elements){ delete_elements(); elements = NULL; } } break; case 8:/* Deselect */ if(current_element == ELEM_NONE){ beep(); }else{ current_element = ELEM_NONE; current_id = -1; } break; case 9:/* GrpMove */ if(base_element != ELEM_FORM){ beep(); }else{ hdie = 0; while(!hdie){ tx = 0; ty = 0; tmp = (elem_struct *) tn_list_getdata(elements, 0); clrscr(); if(elements) draw_elements(); k = readkey(); switch(k){ case KEY_TAB: if(tmp->x + tmp->w + 8 < CON_COLS){ tx += 8; }else{ if(tmp->x + tmp->w == CON_COLS - 1){ beep(); }else{ tx = (CON_COLS - tmp->w - 1) - tmp->x; } } break; case KEY_UP: if(tmp->y > 1) ty--; else beep(); break; case KEY_DOWN: if(tmp->y + tmp->h + 1< CON_ROWS) ty++; else beep(); break; case KEY_LEFT: if(tmp->x > 1) tx--; else beep(); break; case KEY_RIGHT: if(tmp->x + tmp->w + 1 < CON_COLS) tx++; else beep(); break; case KEY_ESC: hdie = 1; break; case KEY_ENTER: hdie = 1; break; default: beep(); break; } for(i = 0; i < tn_list_size(elements); i++){ tmp = (elem_struct *) tn_list_getdata(elements, i); tmp->x += tx; tmp->y += ty; element_to_list(i, tmp->type, tmp->x, tmp->y, tmp->w, tmp->h); } } } break; default: break; }; }while(die != 1); delete myhMenu; set_cursor(line); // finish up donecons(); return 0; }