#include #include #include #include #include #include #include #include "diawxgtk.h" #include "../diawxxt/protowx.h" #include "../diajava/protorev.h" #include #include #include #include #include #include #include #include using namespace std; FILE *ftty = NULL; void BUG(const char *s) { fprintf (stderr,"BUG: %s\n",s); } enum ICON_FORMAT { ICON_F_XPM, ICON_F_JPG}; class ICON_XPM{ public: wxBitmap *bitmap; ICON_XPM *next; char *name; /*~PROTOBEG~ ICON_XPM */ public: ICON_XPM (char **tbstr, int nbstr, const char *_name, ICON_FORMAT format); void donothing (void); /*~PROTOEND~ ICON_XPM */ }; static ICON_XPM *first=NULL; static int mform_fdin; FILE *mform_fout = stdout; PUBLIC ICON_XPM::ICON_XPM( char **tbstr, int nbstr, const char *_name, ICON_FORMAT format) { /* We receive the full content of an XPM file. We must strip it somewhat so wxBitmap will use it as if it was compiled in the source. */ next = first; first = this; name = strdup(_name); if (format == ICON_F_XPM){ char *tb[nbstr+1]; int line = 0; for (int i=0; i 0) pt[len-2] = '\0'; tb[line++] = pt + 1; // Skip the " at the beginning // fprintf (stderr,"len %d\n",strlen(pt+1)); } } tb[line] = NULL; #if 0 { static int alloc = 0; char tmp[PATH_MAX]; sprintf (tmp,"/tmp/diawxxt.%d.xpm",alloc++); FILE *fout = fopen (tmp,"w"); if (fout != NULL){ for (int i=0; i '9' ? (h1 & 0x0f) + 9 : h1 - '0'; h2 = h2 > '9' ? (h2 & 0x0f) + 9 : h2 - '0'; *pt++ = (h1<<4)|h2; } } #if 0 { static int alloc = 0; char tmp[PATH_MAX]; sprintf (tmp,"/tmp/diawxgtk.%d.jpg",alloc++); FILE *fout = fopen (tmp,"w"); if (fout != NULL){ fwrite (buf,1,pt-buf,fout); fclose (fout); } } #endif static bool loaded = false; if (!loaded){ loaded = true; wxJPEGHandler *h = new wxJPEGHandler; wxImage::AddHandler(h); } wxMemoryInputStream inp (buf,(pt-buf)); wxImage img(inp); bitmap = new wxBitmap (img); } } /* Just so the compiler shut off */ PUBLIC void ICON_XPM::donothing() { } wxBitmap *icon_xpm_locate(const char *name) { wxBitmap *ret = NULL; ICON_XPM *x = first; while (x != NULL){ if (strcmp(x->name,name)==0){ ret = x->bitmap; break; } x = x->next; } if (ret == NULL) fprintf (stderr,"Unknown XPM icon %s\n",name); return ret; } class MFORMSCRIPT_CTX{ public: MFORM *tbfl[20]; wxBOOK *tbbk[20]; wxMenu *tbmn[20]; wxTREE *tbtr[20]; wxMenuBar *menubar; int level; SETVAL_INFO info; /*~PROTOBEG~ MFORMSCRIPT_CTX */ public: MFORMSCRIPT_CTX (void); void newlevel (MFORM *fl); void newlevel (MFORM *fl, wxBOOK *bk); private: void newlevel (void); public: void newlevel (wxBOOK *bk); void newlevel (wxMenu *mn); void newlevel (wxMenuBar *bar); void newlevel (wxTREE *tree); void poplevel (void); /*~PROTOEND~ MFORMSCRIPT_CTX */ }; class MFORMSCRIPT{ public: char buflines[10000]; int curlen; MAINFORM **tbmain; int maxmain; bool must_exit; char **tbstr; int nbstr; wxCursor *current; /*~PROTOBEG~ MFORMSCRIPT */ public: MFORMSCRIPT (bool _must_exit); MAINFORM *locate (const char *f); private: bool oneline (char *buf, MFORMSCRIPT_CTX&ctx); bool processbuf (bool firstmain); public: void readfromstdin (void); void readone (void); void run (void); private: int setcontext (MFORMSCRIPT_CTX&ctx, const char *id); public: void setcursor (wxCursor *cur); /*~PROTOEND~ MFORMSCRIPT */ }; PUBLIC MFORMSCRIPT::MFORMSCRIPT (bool _must_exit) { buflines[0] = '\0'; curlen = 0; // Obtient la définition must_exit = _must_exit; maxmain = 100; tbmain = new MAINFORM*[100]; for (int i=0; iid,f)==0){ ret = mf; break; } } if (ret == NULL && ftty != NULL){ fprintf (ftty,"Can't locate form %s\n",f); } return ret; } PUBLIC void MFORMSCRIPT::setcursor(wxCursor *cur) { if (current != cur){ current = cur; for (int i=0; isetcursor (cur); } } } static MAINFORM *remadmin_showerror (const char *ctl, ...) { va_list list; va_start (list,ctl); char buf[1000]; vsnprintf (buf,sizeof(buf)-1,ctl,list); MAINFORM *msg = new MAINFORM(""); msg->New_label (buf); va_end (list); msg->Newline(); FORMBUTTON *gr = new FORMBUTTON(msg,"but",0); msg->New_form(gr); gr->New_button ("badver",false,"quit"); msg->Popup(); return msg; } PUBLIC SETVAL_INFO::SETVAL_INFO() { tarea = NULL; thtml = NULL; tarea_buf = NULL; tarea_size = 0; tarea_pos = 0; combo = NULL; } /* Prepare the textarea append buffer, used by the Str primitive to collect the content of a textarea */ PUBLIC void SETVAL_INFO::initbuf() { free (tarea_buf); tarea_buf = (char*)malloc(10000); tarea_size = 10000; tarea_pos = 0; tarea_buf[0] = '\0'; } PUBLIC void SETVAL_INFO::freebuf() { free (tarea_buf); tarea_buf = NULL; } /* Append a line to the textarea buffer */ PUBLIC void SETVAL_INFO::append(const char *s) { int len = strlen(s); if (tarea_pos + len >= tarea_size){ tarea_size += 10000; tarea_buf = (char*)realloc (tarea_buf,tarea_size); assert (tarea_buf != NULL); } strcpy (tarea_buf+tarea_pos,s); tarea_pos += len; tarea_buf[tarea_pos++] = '\n'; tarea_buf[tarea_pos] = '\0'; } PUBLIC MFORMSCRIPT_CTX::MFORMSCRIPT_CTX() { level = -1; } PRIVATE void MFORMSCRIPT_CTX::newlevel () { ++level; tbfl[level] = NULL; tbbk[level] = NULL; tbmn[level] = NULL; tbtr[level] = NULL; } PUBLIC void MFORMSCRIPT_CTX::newlevel (MFORM *fl, wxBOOK *bk) { newlevel(); tbfl[level] = fl; tbbk[level] = bk; } PUBLIC void MFORMSCRIPT_CTX::newlevel (MFORM *fl) { newlevel(); tbfl[level] = fl; } PUBLIC void MFORMSCRIPT_CTX::newlevel (wxBOOK *bk) { newlevel(); tbbk[level] = bk; } PUBLIC void MFORMSCRIPT_CTX::newlevel (wxMenu *mn) { newlevel(); tbmn[level] = mn; } PUBLIC void MFORMSCRIPT_CTX::newlevel (wxMenuBar *bar) { newlevel(); menubar = bar; } PUBLIC void MFORMSCRIPT_CTX::newlevel (wxTREE *tree) { newlevel(); tbtr[level] = tree; } PUBLIC void MFORMSCRIPT_CTX::poplevel () { level--; if (level < -1){ remadmin_showerror ("poplevel %d (Too many End ?)\n",level); level = -1; } } static bool pref_modal=false; static bool pref_nogfx=false; static bool pref_html=true; static bool pref_notree=false; static const char GCONTENT[]="--gcontent--"; /* Set the context to the form or book pointed by ID. Return -1 if not found. */ PRIVATE int MFORMSCRIPT::setcontext ( MFORMSCRIPT_CTX &ctx, const char *id) { int oldlevel = ctx.level; char mainf[strlen(id)+1]; strcpy (mainf,id); char *pt = mainf; FORMBASE *parent = NULL; while (pt != NULL){ char *start = pt; pt = strchr(start,'.'); if (pt != NULL){ *pt++ = '\0'; } wxBOOK *book = NULL; MFORM *form = NULL; if (parent != NULL){ parent->locate(start,form,book); }else{ form = locate (start); } // fprintf (stderr,"start :%s: %p %p\n",start,form,book); if (form != NULL){ if (form->nbc == 1){ // Special case for Groups, see GCONTENT MFORM_C *c = form->tbc[0]; if (c->type == T_FORM){ MFORM *sub = (MFORM*)c->c; if (strcmp(sub->id,GCONTENT)==0){ form->resetlayout(); form=sub; } } } form->resetlayout(); parent = form; }else if (book != NULL){ book->resetlayout(); parent = book; }else{ break; } if (pt == NULL){ ctx.newlevel (form,book); } } return ctx.level > oldlevel ? 0 : -1; } struct TBVAR{ const char *name; const char *val; }; static TBVAR *tbvar; static int nbvar; /* Return the value of a named parameter ($name=val). Return NULL if this was not defined */ const char *rem_getvar (const char *name) { const char *ret = NULL; TBVAR *ptvar = tbvar; for (int i=0; iname,name)==0){ ret = ptvar->val; break; } } return ret; } /* Return the value of a variable or -1 of not defined */ int rem_getvarval (const char *name) { int ret = -1; const char *s = rem_getvar(name); if (s != NULL) ret = atoi(s); return ret; } static int last_mousex = 200; // Last position of the mouse static int last_mousey = 200; // for popup menus /* Record the position of the last click the mouse */ void rem_setlastmouse (int x, int y) { last_mousex = x; last_mousey = y; } void rem_getlastmouse (int &x, int &y) { x = last_mousex; y = last_mousey; } static POPUPMENU *currentpopup = NULL; PUBLIC POPUPMENU::POPUPMENU(const char *id, const char *title) : wxMenu(title,0) { popupid = id; event_sent = false; } PUBLIC void POPUPMENU::func(wxEvent &c) { remadmin_setcursor (cursor_wait); fprintf (mform_fout,"menubar %s %d\n",popupid.c_str(),c.m_id); fflush (mform_fout); event_sent = true; } PUBLIC void POPUPMENU::done() { if (!event_sent){ fprintf (mform_fout,"menubar %s -1\n",popupid.c_str()); fflush (mform_fout); } } #ifndef PROTO_SKIP BEGIN_EVENT_TABLE(POPUPMENU,wxMenu) EVT_MENU (-1,POPUPMENU::func) EVT_MENU_CLOSE(POPUPMENU::func) END_EVENT_TABLE() #endif struct ALIVE_EVENT { void (*f) (void *data); void *data; ALIVE_EVENT *next; }; static ALIVE_EVENT *event; /* Register a callback which will be executed when the Alive primitive is received. */ void remadmin_regalive (void (*f)(void *data), void *data) { // Check if the event is already there ALIVE_EVENT *pt = event; while (pt != NULL){ if (pt->f == f && pt->data == data) break; pt = pt->next; } if (pt == NULL){ ALIVE_EVENT *ev = new ALIVE_EVENT; ev->f = f; ev->data = data; ev->next = event; event = ev; } } /* Remove all event related to a given data */ void remadmin_delalive (void *data) { ALIVE_EVENT **ptpt = &event; while (*ptpt != NULL){ ALIVE_EVENT *pt = *ptpt; if (pt->data == data){ *ptpt = pt->next; delete pt; }else{ ptpt = &pt->next; } } } /* Process all alive event */ static void remadmin_doalive () { ALIVE_EVENT *pt = event; while (pt != NULL){ pt->f(pt->data); ALIVE_EVENT *next = pt->next; delete pt; pt = next; } event = NULL; } // Process one line // Return true if this was a End statement PRIVATE bool MFORMSCRIPT::oneline(char *buf, MFORMSCRIPT_CTX &ctx) { static bool do_nothing = false; if (do_nothing) return false; MFORM *fl = NULL; wxBOOK *bk = NULL; wxTREE *tr = NULL; static int tree_collect = 0; // Collecting a tree menu if (ctx.level >= 0){ fl = ctx.tbfl[ctx.level]; bk = ctx.tbbk[ctx.level]; tr = ctx.tbtr[ctx.level]; } // fprintf (stderr,"level %d %p %p :%s:\n",ctx.level,fl,bk,buf); bool end = false; if (buf[0] == '\0') return false; char args[20][1000]; const char *ptargs[20]; TBVAR vars[20]; nbvar = 0; tbvar = vars; int nbargs = 0; { for (int i=0; i<20; i++){ args[i][0] = '\0'; ptargs[i] = args[i]; } char *pt = str_skip(buf); if (pt[0]=='#') return false; bool in_variables = false; while (*pt != '\0'){ pt = str_skip(pt); if (*pt == '$'){ in_variables = true; pt = str_skip(pt+1); } if (*pt == '"'){ pt++; char *dst = args[nbargs]; while (*pt != '"' && *pt != '\0'){ if (*pt == '\\'){ pt++; } *dst++ = *pt++; } *dst = '\0'; if (*pt == '"') pt++; }else if (*pt > ' '){ pt = str_copyword (args[nbargs],pt,sizeof(args[nbargs])); } if (in_variables){ char *arg = args[nbargs]; char *eq = strchr(arg,'='); if (eq != NULL){ vars[nbvar].name = arg; *eq++ = '\0'; vars[nbvar].val = eq; nbvar++; }else{ fprintf (stderr,"variable %s without value, ignored: %s\n",arg,buf); } } nbargs++; } } char *verb = args[0]; int num=0; // The protocol is both ascii and numeric. This allow // simple test case to be written // The numeric protocol is normally used if (isdigit(verb[0])){ num = atoi(verb); }else{ for (int i=0; iAppendToPage (args[1]); ctx.info.thtml->AppendToPage ("\n"); }else if (ctx.info.tarea != NULL){ ctx.info.append (args[1]); }else{ tbstr[nbstr++] = strdup(args[1]); } return false; } if (ftty != NULL){ fprintf (ftty,"oneline :%s: level %d\n",buf,ctx.level); fflush (ftty); } switch (num){ case PROTO_Version: if (atoi(args[1])!=PROTOGUI_REV){ MAINFORM *msg = remadmin_showerror("%s",args[1]); do_nothing = true; tbmain[0] = msg; ctx.level = -1; end = true; } break; case PROTO_Newline: fl->Newline(); break; case PROTO_Skip: fl->Skip (atoi(args[1])); break; case PROTO_Fill: fl->Fill (); break; case PROTO_Hline: fl->New_hline (args[1]); break; case PROTO_Dispolast: fl->Dispolast (args[1][0] ,atoi(args[2]) ,args[3][0] ,atoi(args[4])); break; case PROTO_Setweightlast: fl->Setweightlast (atoi(args[1]),atoi(args[2])); break; case PROTO_Label: fl->New_label (args[1]); break; case PROTO_Richtext: fl->New_richtext (args[1]); break; case PROTO_String: fl->New_string (args[1],atoi(args[2]),args[3]); break; case PROTO_Password: fl->New_password (args[1],atoi(args[2])); break; case PROTO_Checkbox: fl->New_checkbox (args[1],atoi(args[2])!=0,args[3]); break; case PROTO_Radio: fl->New_radio (args[1],atoi(args[2]),atoi(args[3])!=0 ,args[4]); break; case PROTO_Button: fl->New_button (args[1],atoi(args[2])!=0,args[3]); break; case PROTO_Buttonfill: fl->New_buttonfill (args[1],args[2],0,NULL); break; case PROTO_Button_xpmf: //janne.New_button (fl,ex.nextword(),ex.nextword(),ex.getendskip()); break; case PROTO_Button_xpm: { wxBitmap *bitmap = icon_xpm_locate(args[2]); if (bitmap != NULL){ fl->New_button (args[1],bitmap); } } break; case PROTO_Enteraction: fl->gettop()->setenteraction(args[1]); break; case PROTO_Curfield: { //int level = ctx.level; // FORMBASE*mf = NULL; if (setcontext (ctx,args[1]) != -1){ FORMBASE *mf = ctx.tbfl[ctx.level]; if (mf == NULL) mf = ctx.tbbk[ctx.level]; // fprintf (stderr,"focus :%s: :%s: %p\n",args[1],args[2],mf); if (mf != NULL){ wxWindow *tbfocus[20]; int nbfocus = 0; mf->setcurfield (args[2],tbfocus,nbfocus); // fprintf (stderr,"nbfocus = %d\n",nbfocus); if (rem_getvarval("focus")!=0){ for (int f=nbfocus-1; f>=0; f--) tbfocus[f]->SetFocus(); } } ctx.poplevel(); }else{ fprintf (stderr,"curfield failed :%s:\n",args[1]); } } break; case PROTO_Alive: remadmin_doalive(); setcursor (cursor_normal); break; case PROTO_Icon_xpm: { wxBitmap *bitmap = icon_xpm_locate(args[1]); if (bitmap != NULL){ fl->New_icon_xpm (bitmap); } } break; case PROTO_Xfer_xpm: { //FILE *f = fopen ("/tmp/log.xpm","w"); //for (int i=0; idonothing(); } break; case PROTO_Xfer_jpg: { ICON_XPM *x = new ICON_XPM (tbstr,nbstr,args[1],ICON_F_JPG); x->donothing(); } break; case PROTO_Choice: ctx.info.combo = fl->New_choice (args[1],args[2]); break; case PROTO_Choice_item: { int no = atoi(args[2]+1); if (args[1][0] == '\0' && ctx.info.combo != NULL){ ctx.info.combo->setItem(no,args[3],args[4]); }else{ fl->New_choice_item (args[1],no,args[2],args[3]); } } break; case PROTO_List: fl->New_list (args[1],atoi(args[2]),args[3]); break; case PROTO_List_item: fl->New_list_item (args[1],args[2]); break; case PROTO_Combo: ctx.info.combo = fl->New_combo (args[1],atoi(args[2]),args[3]); break; case PROTO_Combo_item: { int no = atoi(args[2]+1); if (args[1][0] == '\0' && ctx.info.combo != NULL){ ctx.info.combo->setItem(no,args[3],args[4]); }else{ fl->New_combo_item (args[1],no,args[2],args[3]); } } break; case PROTO_Group: { GROUP *gr = new GROUP(fl,args[1],args[2]); fl->New_form(gr); // We "protect" the group by creating a subform in which // we place the various widgets MFORM *sub = gr->New_form(GCONTENT); ctx.newlevel (sub); } break; case PROTO_Groupfit: { GROUP *gr = new GROUP_FIT(fl,args[1],args[2]); fl->New_form(gr); MFORM *sub = gr->New_form(GCONTENT); ctx.newlevel (sub); } break; case PROTO_Formbutton: { FORMBUTTON *gr = new FORMBUTTON(fl,args[1],0); fl->New_form(gr); ctx.newlevel (gr); } break; case PROTO_Setcontext: // fprintf (stderr,"Setcontext :%s:\n",args[1]); setcontext (ctx,args[1]); break; case PROTO_Form: { const char *id = args[1]; if (fl == NULL){ remadmin_showerror ("A MainForm must be defined first : %s",id); }else{ MFORM *gr = new MFORM(fl,id); fl->New_form(gr); ctx.newlevel (gr); // fprintf (stderr,"Ctx level %d\n",ctx.level); } } break; case PROTO_Clist: { CLIST *cl = fl->New_clist(args[1],atoi(args[2]),ptargs+3); ctx.newlevel (cl); } break; case PROTO_Clist_item: if (fl != NULL){ if (args[1][0] == '\0'){ CLIST *cl = (CLIST*)fl; cl->New_item(args[2],ptargs+3); }else{ fl->New_clist_item (args[1],args[2],ptargs+3); } }else if (setcontext (ctx,args[1])!=-1){ CLIST *cl = (CLIST*)ctx.tbfl[ctx.level]; cl->Set_item(args[2],ptargs+3); ctx.poplevel(); } break; case PROTO_Sheet: fl->New_sheet (args[1],atoi(args[2]),ptargs+3); break; case PROTO_Sheet_item: fl->New_sheet_item (args[1],atoi(args[2]),atoi(args[3]),args[4]); break; case PROTO_Treemenu: { wxTREE *tr = fl->New_tree (args[1]); ctx.newlevel (tr); } break; case PROTO_Treeelem: { wxBitmap *icon = args[1][0] != '\0' ? icon_xpm_locate(args[1]) : NULL; tr->addelm (icon,args[2]); } break; case PROTO_Treesub: { wxBitmap *icon = args[2][0] != '\0' ? icon_xpm_locate(args[2]) : NULL; tr->addsub (atoi(args[1]),icon,args[3]); tree_collect++; } break; case PROTO_Page: { const char *id = args[1]; if (bk == NULL){ remadmin_showerror ("A book must be defined first : %s",id); }else{ MFORM *gr = new MFORM(bk,bk,id); bk->New_page(gr,args[2]); ctx.newlevel (gr); } } break; case PROTO_Book: { wxBOOK *b = new wxBOOK(fl,args[1]); fl->New_book(b); ctx.newlevel (b); } break; case PROTO_MainForm: { const char *id = args[1]; if (fl != NULL){ MFORM *gr; wxBOOK *dummy; fl->locate (id,gr,dummy); if (gr == NULL){ gr = new MFORM(fl,id); fl->New_form(gr); }else{ gr->delall(); } gr->logicaltop = true; //gr->max_width = 10000; ctx.newlevel (gr); }else if (bk != NULL){ MFORM *gr; wxBOOK *dummy; bk->locate (id,gr,dummy); if (gr == NULL){ gr = new MFORM(bk,bk,id); bk->New_page(gr,args[2]); }else{ gr->delall(); } bk->selpage (gr); gr->logicaltop = true; //gr->max_width = 10000; ctx.newlevel (gr); }else{ MAINFORM *gr = NULL; for (int i=0; iid,id)==0){ gr = tbmain[i]; gr->delall(); break; } } } if (gr == NULL){ gr = new MAINFORM(args[1],args[2],args[3]); for (int i=0; iSetValue (ctx.info.tarea_buf); ctx.info.freebuf(); ctx.info.tarea = NULL; }else if (ctx.info.combo != NULL){ ctx.info.combo = NULL; }else if (ctx.info.thtml != NULL){ ctx.info.thtml = NULL; }else if (tree_collect){ tr->endsub (); tree_collect--; }else{ wxMenu *mn = ctx.tbmn[ctx.level]; if (mn == NULL && ctx.menubar != NULL){ ctx.menubar = NULL; } if (fl != NULL){ fl->Fit(); if (strcmp(fl->id,GCONTENT)==0){ // Group and Groupfit are adding an extra form // inside (See PROTO_Group), so we must perform // the layout for the parent also. fl->getwxparent()->Fit(); } } if (bk != NULL) bk->Fit(); if (tr != NULL) tr->Fit(); if (ctx.level == 0){ // Normally, this is always the end of a mainform // except for a setcontext, where it can be the end of // a sub-form or a book if (fl != NULL){ fl->fit2top(); }else if (bk != NULL){ bk->fit2top(); } if (rem_getvarval("nopopup")!=1){ if (mn != NULL){ // Trigger a popup tbmain[0]->popupmenu (mn,last_mousex,last_mousey); }else if (fl != NULL){ fl->gettop()->Popup(); }else if (bk != NULL){ bk->gettop()->Popup(); } }else{ if (fl != NULL){ fl->gettop()->waitpopup(); } } } ctx.poplevel(); end = true; } break; case PROTO_Show: if (setcontext (ctx,args[1])!=-1){ MFORM *fl = ctx.tbfl[ctx.level]; MAINFORM *mf = fl->gettop(); if (strcmp(args[2],"1")==0){ mf->show(); }else{ mf->hide(); } ctx.poplevel(); } break; case PROTO_Delete: { const char *id = args[1]; if (strchr(id,'.')!=NULL){ if (setcontext (ctx,id) != -1){ MFORM *fl = ctx.tbfl[ctx.level]; FORMBASE *parent = fl->getparent(); parent->delform (fl); ctx.poplevel (); parent->gettop()->Popup(); } }else{ for (int i=0; iid,id)==0){ if (i != 0){ delete mf->getframe(); tbmain[i] = NULL; }else{ // wxWindows exit when the last window // is gone. When linuxconf ask for a password // it removes the password window and wxXt // exit before we have a chance to get in the // main screen of linuxconf. mf->hide(); } break; } } } } break; case PROTO_Deletechild: { const char *id = args[1]; if (setcontext (ctx,id) != -1){ MFORM *fl = ctx.tbfl[ctx.level]; if (fl != NULL){ fl->delchild(); } ctx.poplevel (); } } break; case PROTO_Dump: { int level = ctx.level; setcontext (ctx,args[1]); if (ctx.level > level){ wxFORMBASE *mf = ctx.tbfl[ctx.level]; //BUG("Dump"); //if (mf == NULL) mf = ctx.tbbk[ctx.level]; if (mf != NULL){ mf->report_button (args[2],true,NULL,"",0); } ctx.poplevel(); }else{ fprintf (stderr,"Dump unknown form %s\n",args[1]); } } break; case PROTO_Sidetitle: fl->setsidetitle (args[1]); break; case PROTO_Html: ctx.info.thtml = fl->New_html (args[1],atoi(args[2]),atoi(args[3])); break; case PROTO_Textarea: ctx.info.tarea = fl->New_text (args[1],atoi(args[2]),atoi(args[3])); fl->Setweightlast (1,1); ctx.info.initbuf(); break; case PROTO_Slider: fl->New_slider (args[1],atoi(args[2]),atoi(args[3]),atoi(args[4]) ,atoi(args[5])); break; case PROTO_Gauge: fl->New_gauge (args[1],atoi(args[2]),atoi(args[3]),atoi(args[4])); break; case PROTO_Setval: { int level = ctx.level; setcontext (ctx,args[1]); if (ctx.level > level){ FORMBASE *mf = ctx.tbfl[ctx.level]; if (mf == NULL) mf = ctx.tbbk[ctx.level]; mf->setval (args[2],(const char **)ptargs+3,ctx.info); ctx.poplevel(); }else{ fprintf (stderr,"Setval unknown field %s %s\n",args[1],args[2]); } } break; case 500: // Error reported by linuxconf when connecting to port 98 { MAINFORM *msg = remadmin_showerror(buf); do_nothing = true; tbmain[0] = msg; ctx.level = -1; end = true; } break; case PROTO_Defdc: defs_setdc (args[1]); break; case PROTO_Deffont: defs_setfont (args[1],atoi(args[2]),atoi(args[3]),atoi(args[4]) ,atoi(args[5]),atoi(args[6])!=0); break; case PROTO_Defpen: defs_setpen (args[1],args[2],atoi(args[3]),atoi(args[4])); break; case PROTO_Defbrush: defs_setbrush (args[1],args[2],atoi(args[3])); break; case PROTO_Drawline: fl->record_draw (PROTO_Drawline,atoi(args[1]),atoi(args[2]) ,atoi(args[3]),atoi(args[4])); break; case PROTO_Drawrect: fl->record_draw (PROTO_Drawrect,atoi(args[1]),atoi(args[2]) ,atoi(args[3]),atoi(args[4])); break; case PROTO_Fillrect: fl->record_draw (PROTO_Fillrect,atoi(args[1]),atoi(args[2]) ,atoi(args[3]),atoi(args[4])); break; case PROTO_Fillpolygon: { int tb[20]; int i; for (i=1; i<20; i++){ const char *arg = args[i]; if (!isdigit(arg[0])) break; tb[i-1] = atoi(arg); } fl->record_draw (PROTO_Fillpolygon,tb,i-1); } break; case PROTO_Fillarc: case PROTO_Drawarc: fl->record_draw (num,atoi(args[1]),atoi(args[2]) ,atoi(args[3]),atoi(args[4]) ,atoi(args[5]),atoi(args[6])); break; case PROTO_Clear: fl->record_draw (PROTO_Clear,0,0,0,0); break; case PROTO_Drawclip: fl->drawclip (atoi(args[1]),atoi(args[2]),atoi(args[3]),atoi(args[4])); break; case PROTO_Drawtext: fl->record_draw (PROTO_Drawtext,atoi(args[1]),atoi(args[2]),args[3]); break; case PROTO_Refresh: fl->do_drawing(); break; case PROTO_Blit: fl->blit (atoi(args[1]),atoi(args[2]) ,atoi(args[3]),atoi(args[4]) ,atoi(args[5]),atoi(args[6])); break; case PROTO_Menubar: { wxMenuBar *mn = new wxMenuBar; ctx.newlevel(mn); fl->getframe()->SetMenuBar(mn); } break; case PROTO_Popupmenu: { // We delete the last popup delete currentpopup; currentpopup = new POPUPMENU (args[1],args[2]); ctx.newlevel (currentpopup); } break; case PROTO_Submenu: { wxMenu *mn = new wxMenu("",0); wxMenu *cur = ctx.tbmn[ctx.level]; if (cur == NULL){ ctx.menubar->Append (mn,args[1]); ctx.newlevel (mn); }else{ cur->Append (0,args[1],mn); ctx.newlevel (mn); } } break; case PROTO_Menuentry: if (args[2][0] == '-'){ ctx.tbmn[ctx.level]->AppendSeparator(); }else{ ctx.tbmn[ctx.level]->Append (atoi(args[1]),args[2]); } break; case PROTO_Menutitle: if (currentpopup != NULL) currentpopup->SetTitle (args[1]); break; case PROTO_Setcursor: break; case PROTO_Listen: { int old_level = ctx.level; setcontext (ctx,args[1]); if (old_level == ctx.level){ fprintf (stderr,"Listen failed, missing dialog :%s: :%s:\n",args[1],args[2]); }else{ bool en = atoi(args[2]) != 0; MFORM *m = ctx.tbfl[ctx.level]; wxBOOK *b = ctx.tbbk[ctx.level]; if (m != NULL){ m->Enable(en); m->SetCursor (en ? *cursor_normal : *cursor_locked); }else if (b != NULL){ b->Enable(en); } ctx.poplevel(); } } break; case PROTO_Prefsubmenu: // Do nothing for now break; case PROTO_Inputgrid: fl->Inputgrid (args[1],atoi(args[2]),atoi(args[3]),atoi(args[4]) ,atoi(args[5]),atoi(args[6]),atoi(args[7])); break; case PROTO_Splash: break; case PROTO_Hidesplash: break; default: fprintf (stderr,"Unknown command %s\n",verb); } for (int i=0; i buflines){ int more = curlen - (int)(ptbuf-buflines); if (more > 0){ memmove (buflines,ptbuf,more); curlen = more; }else{ curlen = 0; } buflines[curlen] = '\0'; } //fprintf (ftty,"processbuf curlen = %d\n",curlen); //fflush (ftty); return done; } PUBLIC void MFORMSCRIPT::readfromstdin() { // Process the first MainForm while (1){ int n = read (mform_fdin,buflines+curlen,sizeof(buflines)-1-curlen); if (n <= 0) break; curlen += n; if (processbuf(true)) break; } // Process the rest of the buffer // and let Xt handle the rest processbuf(false); } //static XtInputId xtid; PUBLIC void MFORMSCRIPT::readone() { int n = read (mform_fdin,buflines+curlen,sizeof(buflines)-1-curlen); if (ftty != NULL){ fprintf (ftty,"readone curlen = %d n = %d\n",curlen,n); fflush (ftty); } if (n > 0){ curlen += n; processbuf(false); }else{ //XtRemoveInput(xtid); if (must_exit) exit(0); } if (ftty != NULL){ fprintf (ftty,"readone end curlen = %d\n",curlen); fflush (ftty); } } class MyApp: public wxApp{ public: bool OnInit(void); }; static MFORMSCRIPT *sc; void remadmin_setcursor (wxCursor *cur) { sc->setcursor (cur); } #if 0 static bool mformscript_readone (XtPointer , int *, XtInputId *) { sc->readone(); return 1; } #endif /* Translate an IP number (ascii) into four number Return -1 if the IP number is invalid. */ static int ipnum_aip24 (const char *aip, int num4[4]) { int ret = 0; for (int i=0; i<4; i++){ if (!isdigit(aip[0])){ ret = -1; break; }else{ int no = num4[i] = atoi(aip); if (no < 0 || no > 255) ret = -1; while (isdigit(*aip)) aip++; if (i < 3){ if (*aip != '.'){ ret = -1; break; } aip++; } } } if (*aip != '\0' && !isspace(*aip)) ret = -1; return ret; } /* Check is a string is valid IP number. if (ishost), check if the IP is not a broadcast or a network address. */ static bool ipnum_validip(const char *aip, bool ishost) { int num4[4]; bool ret = false; if (ipnum_aip24(aip,num4) != -1){ ret = true; if (ishost && (num4[3] == 0 || num4[3] == 255)){ ret = false; } } return ret; } /* Compute an IP number from a string. */ static unsigned long ipnum_aip2l (const char *aip) { unsigned long ret = 0xffffffffl; int n[4]; if (ipnum_aip24(aip,n) != -1){ ret = (n[0] << 24) + (n[1] << 16) + (n[2] << 8) + n[3]; } return ret; } static int cmdsock_sinconnect (struct sockaddr_in &sin, int nbretry) { int ret = -1; for (int i=0; i= 0) { if (connect (s, (struct sockaddr *) &sin, sizeof (sin)) == -1){ close (s); sleep(1); }else{ ret = s; break; } } } return ret; } /* Establish a socket with a server Return -1 if any error. */ static int cmdsock_connect ( const char *servname, int port, int nbretry, char *errorstr) { int ret = -1; struct sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(port); errorstr[0] = '\0'; if (ipnum_validip (servname,true)){ long addr = htonl(ipnum_aip2l (servname)); memcpy (&sin.sin_addr,&addr, sizeof(addr)); ret = cmdsock_sinconnect (sin,nbretry); }else{ struct hostent *h = (struct hostent *) gethostbyname(servname); if (h == NULL){ sprintf (errorstr,"No server \"%s\" defined",servname); }else{ memcpy (&sin.sin_addr,h->h_addr, h->h_length); ret = cmdsock_sinconnect (sin,nbretry); } } return ret; } static gint poll_func (GPollFD *fds, guint nfds, gint timeout) { //fprintf (stderr,"pollfunc %d %d\n",nfds,timeout); gint ret = -1; bool one = false; while (!one){ fd_set fdin; FD_ZERO (&fdin); guint maxfd = 0; for(guint i=0; i maxfd) maxfd = fd; } FD_SET (mform_fdin,&fdin); if ((guint)mform_fdin > maxfd) maxfd = mform_fdin; struct timeval tv; tv.tv_usec = 0; tv.tv_sec = timeout; if (select(maxfd+1,&fdin,NULL,NULL,timeout == -1 ? NULL : &tv)<=0){ break; }else{ if (FD_ISSET(mform_fdin,&fdin)){ sc->readone(); } for(guint i=0; irun(); #if 0 static GPollFD gp={mform_fdin,G_IO_IN | G_IO_HUP | G_IO_ERR,0); static GSourceFuncs funcs={ prepare: remadmin_prepare, check: remadmin_check, dispatch: remadmin_dispatch, destroy: NULL, }; GSource *s = g_source_new (funcs,sizeof(GSource)); g_main_add_poll(s,&gp); g_source_add (G_PRIORITY_DEFAULT,FALSE,&funcs,NULL,NULL,NULL); #endif g_main_set_poll_func (poll_func); wxFrame *ret = NULL; if (sc->tbmain[0] != NULL){ ret = sc->tbmain[0]->getframe(); } return ret; } static wxFrame *remadmin_usage() { return test_dialog(); #if 0 static const char *tb[]={ "Remote admin front-end for Linuxconf " PACKAGE_REV "", "Usage:", " ", " remadmin --pipe", " remadmin --exec command", " remadmin host_to_remote_admin", "", NULL }; return error (tb); #endif } static wxFrame *remadmin_exec (char *argv[]) { wxFrame *ret = NULL; int tbin[2]; int tbout[2]; if (pipe(tbin)!=-1 && pipe(tbout)!=-1){ if (fork()==0){ close (tbin[0]); close (tbout[1]); dup2 (tbin[1],1); dup2 (tbout[0],0); execvp (argv[0],argv); _exit (-1); }else{ close (tbin[1]); close (tbout[0]); mform_fdin = tbin[0]; mform_fout = fdopen (tbout[1],"w"); ret = startup(); if (ret == NULL){ char tmp[100]; sprintf (tmp,"can't execute %s\n",argv[0]); const char *tb[]={ tmp, NULL }; ret = error (tb); } } }else{ const char *tb[]={ "Missing resources", "", strerror(errno), NULL }; ret = error (tb); } return ret; } /* wxxt want a wxFrame to start normal operation. We create the frame normally by reading stdin. Once we have the frame, we install a callback with Xt and let wxxt process normally the other event. */ bool MyApp::OnInit(void) { wxFrame *ret = NULL; defs_init(); //ftty = fopen ("/dev/tty","w"); int arg; for (arg=1; arg