#include #include #include #include #include #include "../framework/framework.h" #include "tlmpmail.h" #include "tlmpmail.m" #include "keys.h" class VIRTUAL_VIEW: public ARRAY_OBJ{ public: SSTRING name; SSTRING desc; // Description of this view SSTRING expr; // Expression describing the view /*~PROTOBEG~ VIRTUAL_VIEW */ public: VIRTUAL_VIEW (const char *_name); VIRTUAL_VIEW (void); void del (void); int edit (void); int eval (bool test, FOLDER_VIEWS&folds); void save (void); /*~PROTOEND~ VIRTUAL_VIEW */ }; PUBLIC VIRTUAL_VIEW::VIRTUAL_VIEW() { } PUBLIC VIRTUAL_VIEW::VIRTUAL_VIEW(const char *_name) { name.setfrom (_name); SSTRING tmp; tmp.setfromf ("%s-%s",K_VIRTUAL,_name); const char *ptkey = tmp.get(); desc.setfrom (linuxconf_getval(ptkey,K_DESC)); expr.setfrom (linuxconf_getval(ptkey,K_EXPR)); } /* Save/update the record in the configuration file */ PUBLIC void VIRTUAL_VIEW::save() { SSTRING tmp; tmp.setfromf ("%s-%s",K_VIRTUAL,name.get()); const char *ptkey = tmp.get(); linuxconf_replace (ptkey,K_DESC,desc); linuxconf_replace (ptkey,K_EXPR,expr); } /* Delete the record from the configuration file */ PUBLIC void VIRTUAL_VIEW::del() { SSTRING tmp; tmp.setfromf ("%s-%s",K_VIRTUAL,name.get()); const char *ptkey = tmp.get(); linuxconf_removeall (ptkey,K_DESC); linuxconf_removeall (ptkey,K_EXPR); } /* The syntax goes like this def : ( def ) : views views : view : views , view view : folder : def : filterexpr filterexpr : filter : ! filter The expression may define several views, which will all be presented. If one want to combine several views into on, he must uses parentheses. */ static void virtual_eval ( const char *&s, bool test, SSTRING &errs, FOLDER_VIEWS &views) { views.neverdelete(); bool seen_folder = false; while (*s != '\0' && *s != ')'){ if (*s == '('){ s++; FOLDER_VIEWS tmp; virtual_eval (s,test,errs,tmp); if (*s != ')'){ errs.append (MSG_U(E_MISSPAR ,"Missing closing parenthese\n")); test = true; }else{ s++; seen_folder = true; int n = tmp.getnb(); if (n==0){ if (!test){ errs.append (MSG_U(E_EMPTYSET ,"No folder defined in parentheses\n")); test = true; } }else if (n==1){ views.add (tmp.getitem(0)); }else if (n > 1){ FOLDER_MULTI *multi = new FOLDER_MULTI; for (int i=0; iadd (tmp.getitem(i)); folders_register(multi); views.add (multi); } } }else{ char tmp[strlen(s)+1]; char *dst = tmp; while (*s != '\0' && *s != ')' && *s != ',' && *s != ':') *dst++ = *s++; *dst = '\0'; if (!seen_folder){ if (!folders_exist (tmp)){ errs.appendf (MSG_U(E_NOFOLDER,"Folder %s does not exist\n") ,tmp); test = true; }else if (!test){ FOLDER_VIEW *v = folders_alloc (tmp); views.add (v); } seen_folder = true; }else{ // Ok, tmp is a filter bool neg = false; const char *filter = tmp; if (tmp[0] == '!'){ neg = true; filter++; } if (!filter_exist(filter)){ errs.appendf (MSG_U(E_NOFILTER,"Filter %s does not exist\n") ,filter); test = true; }else if (!test){ int last = views.getnb()-1; FOLDER_VIEW *v = views.getitem(last); FOLDER_FILTER *f = new FOLDER_FILTER (v); f->setmode (neg); f->loaddef (filter); folders_register (f); views.remove (last); views.add (f); } } } if (*s == ','){ s++; seen_folder = false; }else if (*s == ':'){ s++; } } } /* Parse the definition of the virtual folder and create all the intermediate FOLDER_VIEW/FILTER. In test mode, report any error, but do not create any object */ static int virtual_eval (const char *expr, bool test, FOLDER_VIEWS &folds) { int ret = 0; SSTRING errs; virtual_eval (expr,test,errs,folds); if (errs.is_filled()){ xconf_error ("%s",errs.get()); ret = -1; } return ret; } /* Parse the definition of a virtual folder and place in folds all the views. */ int virtual_eval (const char *expr, FOLDER_VIEWS &folds) { return virtual_eval (expr,false,folds); } /* Parse the definition of the virtual folder and create all the intermediate FOLDER_VIEW/FILTER. In test mode, report any error, but do not create any object */ PUBLIC int VIRTUAL_VIEW::eval (bool test, FOLDER_VIEWS &folds) { return virtual_eval (expr.get(),test,folds); } /* Edit the virtual folder Return 0 if the changes were accepted, 1 if the record must be deleted */ PUBLIC int VIRTUAL_VIEW::edit() { int ret = -1; DIALOG dia; dia.newf_str (MSG_U(F_VIEWNAME,"Virtual view name"),name); dia.newf_str (MSG_U(F_DESCRIPTION,"Description"),desc,60); dia.newf_str (MSG_U(F_VIEWDEF,"View definition"),expr,60); int nof = 0; while (1){ MENU_STATUS code = dia.edit (MSG_U(T_VIRTUAL_VIEW,"Virtual view"),"" ,help_nil,nof ,MENUBUT_CANCEL|MENUBUT_ACCEPT|MENUBUT_DEL); if (code == MENU_ESCAPE || code == MENU_CANCEL){ dia.restore(); break; }else if (code == MENU_DEL){ ret = 1; break; }else if (name.is_empty()){ xconf_error (MSG_U(E_NONAME,"Specify a name for the view")); nof = 0; }else if (name.strchr(' ')!=NULL){ xconf_error (MSG_U(E_NOSPACE,"No space allowed in name")); }else if (expr.is_empty()){ xconf_error (MSG_U(E_NOEXPR,"You must specify the view definition")); nof = 2; }else{ FOLDER_VIEWS v; if (eval(true,v)!=-1){ ret = 0; break; } } } return ret; } class VIRTUAL_VIEWS: public ARRAY{ /*~PROTOBEG~ VIRTUAL_VIEWS */ public: VIRTUAL_VIEWS (void); VIRTUAL_VIEW *editpick (bool pick); VIRTUAL_VIEW *getitem (int no)const; /*~PROTOEND~ VIRTUAL_VIEWS */ }; PUBLIC VIRTUAL_VIEWS::VIRTUAL_VIEWS() { SSTRINGS tb; linuxconf_getall (K_VIRTUAL,K_INDEX,tb,false); for (int i=0; iget()); add (v); } } PUBLIC VIRTUAL_VIEW *VIRTUAL_VIEWS::getitem(int no) const { return (VIRTUAL_VIEW*)ARRAY::getitem(no); } /* Edit the views or pick one */ PUBLIC VIRTUAL_VIEW *VIRTUAL_VIEWS::editpick(bool pick) { VIRTUAL_VIEWS *views; VIRTUAL_VIEW *ret; OBJECTSUB *sub; bool pick; glocal.ret = NULL; glocal.views = this; glocal.pick = pick; // A sub-routing to sync updates (); linuxconf_removeall (K_VIRTUAL,K_INDEX); for (int i=0; igetnb(); i++){ linuxconf_add (K_VIRTUAL,K_INDEX ,glocal.views->getitem(i)->name.get()); } linuxconf_save(); glocal.sub = ⊂ (MSG_U(T_VIRTUALS,"Virtual folders"),"",help_nil); newf_head (MSG_U(H_VIRTUALS,"Id\tDescription")); if (!glocal.pick){ addwhat (MSG_U(I_ADDVDEF,"Add a virtual folder definition")); }else{ settype (DIATYPE_POPUP); } sortable(); sortpolicy ("aa"); for (int i=0; igetnb(); i++){ VIRTUAL_VIEW *v = glocal.views->getitem(i); new_menuitem (v->name.get(),v->desc.get()); } VIRTUAL_VIEW *v = glocal.views->getitem(no); if (glocal.pick){ glocal.ret = v; endedit(); }else{ if (v->edit()==1){ glocal.views->remove_del(v); v->del(); }else{ v->save(); } glocal.sub->exec(); } VIRTUAL_VIEW *v = new VIRTUAL_VIEW; if (v->edit()==0){ glocal.views->add (v); v->save(); glocal.sub->exec(); }else{ delete v; } return glocal.ret; } void virtual_edit() { VIRTUAL_VIEWS vviews; vviews.editpick(false); } int virtual_pick(FOLDER_VIEWS &views) { VIRTUAL_VIEWS vviews; VIRTUAL_VIEW *v = vviews.editpick(true); int ret = -1; if (v != NULL){ ret = v->eval (false,views); } return ret; }