#include #include #include #include #include #include #include #define Uses_XtIntrinsic #include "diawxxt.h" #include "protowx.h" #include "../diajava/protorev.h" #include #include #include #include #include #include FILE *ftty = NULL; class ICON_XPM{ public: wxBitmap *bitmap; ICON_XPM *next; char *name; /*~PROTOBEG~ ICON_XPM */ public: ICON_XPM (char **tbstr, int nbstr, const char *_name); void donothing (void); /*~PROTOEND~ ICON_XPM */ }; static ICON_XPM *first=NULL; static int mform_fdin; FILE *mform_fout; PUBLIC ICON_XPM::ICON_XPM(char **tbstr, int nbstr, const char *_name) { /* 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; 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; iname,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]; BOOK *tbbk[20]; wxMenu *tbmn[20]; wxMenuBar *menubar; int level; SETVAL_INFO info; /*~PROTOBEG~ MFORMSCRIPT_CTX */ public: MFORMSCRIPT_CTX (void); void newlevel (BOOK *bk); void newlevel (MFORM *fl); void newlevel (MFORM *fl, BOOK *bk); private: void newlevel (void); public: void newlevel (wxMenu *mn); void newlevel (wxMenuBar *bar); 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; 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; } PUBLIC void MFORMSCRIPT_CTX::newlevel (MFORM *fl, BOOK *bk) { newlevel(); tbfl[level] = fl; tbbk[level] = bk; } PUBLIC void MFORMSCRIPT_CTX::newlevel (MFORM *fl) { newlevel(); tbfl[level] = fl; } PUBLIC void MFORMSCRIPT_CTX::newlevel (BOOK *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::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=false; 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'; } BOOK *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 void remadmin_fctmenu (wxObject &, wxCommandEvent &) { fprintf (stderr,"fctmenu\n"); } 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; } static char *popupid = NULL; static wxMenu *currentpopup = NULL; static void popup_func(wxObject &, wxCommandEvent &c) { // fprintf (stderr,"func :%s: %d %ld :%s: :%s:\n",c.commandString // ,c.commandInt,c.extraLong,c.labelString,c.clientData); remadmin_setcursor (cursor_wait); fprintf (mform_fout,"menubar %s %d\n",popupid,c.commandInt); fflush (mform_fout); free (popupid); popupid = NULL; } 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; BOOK *bk = NULL; static bool html_collect = false; // Collecting an html page static int tree_collect = 0; // Collecting a tree menu if (ctx.level >= 0){ fl = ctx.tbfl[ctx.level]; bk = ctx.tbbk[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.\n",arg); } } 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; iNewline(); 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_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: { MFORM *gr = new TREEMENU(fl,args[1]); fl->New_form(gr); ctx.newlevel (gr); } break; case PROTO_Treeelem: { wxBitmap *icon = args[1][0] != '\0' ? icon_xpm_locate(args[1]) : NULL; ((TREEMENU*)fl)->addelm (icon,args[2]); } break; case PROTO_Treesub: { wxBitmap *icon = args[2][0] != '\0' ? icon_xpm_locate(args[2]) : NULL; ((TREEMENU*)fl)->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,id); bk->New_page(gr,args[2]); ctx.newlevel (gr); } } break; case PROTO_Book: { BOOK *b = new BOOK(fl,args[1]); fl->New_book(b); ctx.newlevel (b); } break; case PROTO_MainForm: { const char *id = args[1]; if (fl != NULL){ MFORM *gr; BOOK *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; BOOK *dummy; bk->locate (id,gr,dummy); if (gr == NULL){ gr = new MFORM(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 (html_collect){ html_collect = false; }else if (tree_collect){ ((TREEMENU*)fl)->endsub (); tree_collect--; }else{ wxMenu *mn = ctx.tbmn[ctx.level]; if (mn == NULL && ctx.menubar != NULL){ ctx.menubar = NULL; } 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 (rem_getvarval("nopopup")!=1){ if (mn != NULL){ // Trigger a popup PopupMenu (NULL,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{ // wxXt 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){ FORMBASE *mf = ctx.tbfl[ctx.level]; if (mf == NULL) mf = ctx.tbbk[ctx.level]; if (mf != NULL){ mf->report_button (args[2],true,NULL,""); } ctx.poplevel(); }else{ fprintf (stderr,"Dump unknown form %s\n",args[1]); } } break; case PROTO_Sidetitle: fl->setsidetitle (args[1]); break; case PROTO_Html: html_collect = true; 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: { free (popupid); popupid = strdup(args[1]); // We delete the last popup delete currentpopup; currentpopup = new wxMenu (args[2][0] != '\0' ? args[2] : (char*)NULL ,popup_func); ctx.newlevel (currentpopup); } break; case PROTO_Submenu: { wxMenu *mn = new wxMenu(NULL,remadmin_fctmenu); 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]; BOOK *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: wxFrame *OnInit(void); Bool OnCharHook(wxKeyEvent& event); }; Bool MyApp::OnCharHook(wxKeyEvent&) { printf ("OnCharHook\n"); return FALSE; } static MFORMSCRIPT *sc; void remadmin_setcursor (wxCursor *cur) { sc->setcursor (cur); } static Bool mformscript_readone (XtPointer , int *, XtInputId *) { sc->readone(); return 1; } /* 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 wxFrame *startup() { //fprintf (stderr,"Start\n"); // Send our preference fprintf (mform_fout,"prefer %s %s %s %s reconfdia slider gauge setval alive context menu listen clistdel\n" ,pref_modal ? "modal" : "" ,pref_nogfx ? "nogfx" : "" ,pref_notree ? "" : "treemenu" ,pref_html ? "html" : ""); fflush (mform_fout); sc = new MFORMSCRIPT (true); sc->run(); xtid = XtAppAddInput (wxAPP_CONTEXT, mform_fdin , (XtPointer *) XtInputReadMask , (XtInputCallbackProc) mformscript_readone , (XtPointer) NULL); wxFrame *ret = NULL; if (sc->tbmain[0] != NULL){ ret = sc->tbmain[0]->getframe(); } return ret; } static wxFrame *remadmin_usage() { 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); } 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. */ wxFrame *MyApp::OnInit(void) { wxFrame *ret = NULL; defs_init(); //ftty = fopen ("/dev/tty","w"); int arg; for (arg=1; arg