File indexing completed on 2024-03-24 04:05:28

0001 //
0002 // Description: All core internal macros and functions.
0003 //     Also includes (un)registerInternalMacros
0004 //
0005 /*
0006 Copyright 2005-2011 Tomas Mecir <kmuddy@kmuddy.com>
0007 
0008 This program is free software; you can redistribute it and/or
0009 modify it under the terms of the GNU General Public License as
0010 published by the Free Software Foundation; either version 2 of 
0011 the License, or (at your option) any later version.
0012 
0013 This program is distributed in the hope that it will be useful,
0014 but WITHOUT ANY WARRANTY; without even the implied warranty of
0015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0016 GNU General Public License for more details.
0017 
0018 You should have received a copy of the GNU General Public License
0019 along with this program.  If not, see <http://www.gnu.org/licenses/>.
0020 */
0021 
0022 #include "cmacromanager.h"
0023 #include "cactionmanager.h"
0024 #include "ccmdqueue.h"
0025 #include "ccmdprocessor.h"
0026 #include "clist.h"
0027 #include "clistgroup.h"
0028 #include "clistmanager.h"
0029 #include "ctimer.h"
0030 #include "cvariablelist.h"
0031 
0032 #include <KLocalizedString>
0033 
0034 using namespace std;
0035 
0036 class cMacroSet : public cMacro {
0037 public:
0038   cMacroSet () : cMacro ("set") {}
0039   void eval (const QString &params, int sess, cCmdQueue *) override {
0040     QString varname = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0041     QString value = params.section (' ', 1, -1, QString::SectionSkipEmpty);
0042     //no variable expansion for our parameter, to allow various tricks :)
0043     varList(sess)->set (varname, value);
0044   }
0045 };
0046 
0047 class cMacroUnset : public cMacro {
0048 public:
0049   cMacroUnset () : cMacro ("unset") {}
0050   void eval (const QString &params, int sess, cCmdQueue *) override {
0051     QString varname = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0052     varList(sess)->unset (varname);
0053   }
0054 };
0055 
0056 class cMacroSetVal : public cMacro {
0057   public:
0058     cMacroSetVal () : cMacro ("setval") {}
0059     void eval (const QString &params, int sess, cCmdQueue *queue) override {
0060       // this is like /set, but the value gets parsed using as expression
0061       cCmdProcessor *cmdproc = dynamic_cast<cCmdProcessor *>(am->object ("cmdprocessor", sess));
0062       QString varname = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0063       QString value = params.section (' ', 1, -1, QString::SectionSkipEmpty);
0064       bool ok;
0065       cValue val = cmdproc->eval (value, queue, ok);
0066       if (!ok) {
0067         am->invokeEvent ("message", sess, i18n ("/setval: Expression parsing failed."));
0068         return;
0069       }
0070       varList(sess)->set (varname, &val);
0071     }
0072 };
0073 
0074 class cMacroLSet : public cMacro {
0075   public:
0076     cMacroLSet () : cMacro ("lset") {}
0077     void eval (const QString &params, int, cCmdQueue *queue) override {
0078       QString varname = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0079       QString value = params.section (' ', 1, -1, QString::SectionSkipEmpty);
0080       //no variable expansion for our parameter, to allow various tricks :)
0081       queue->setValue (varname, value);
0082     }
0083 };
0084 
0085 class cMacroLUnset : public cMacro {
0086   public:
0087     cMacroLUnset () : cMacro ("lunset") {}
0088     void eval (const QString &params, int, cCmdQueue *queue) override {
0089       QString varname = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0090       queue->delValue (varname);
0091     }
0092 };
0093 
0094 class cMacroInc : public cMacro {
0095 public:
0096   cMacroInc () : cMacro ("inc") {}
0097   void eval (const QString &params, int sess, cCmdQueue *) override {
0098     QString varname = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0099     QString value = params.section (' ', 1, 1, QString::SectionSkipEmpty);
0100     bool ok = false;
0101     double val = value.toDouble(&ok);
0102     if (ok) varList(sess)->inc (varname, val);
0103   }
0104 };
0105 
0106 class cMacroDec : public cMacro {
0107 public:
0108   cMacroDec () : cMacro ("dec") {}
0109   void eval (const QString &params, int sess, cCmdQueue *) override {
0110     QString varname = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0111     QString value = params.section (' ', 1, 1, QString::SectionSkipEmpty);
0112     bool ok = false;
0113     double val = value.toDouble(&ok);
0114     if (ok) varList(sess)->dec (varname, val);
0115   }
0116 };
0117 
0118 class cMacroLInc : public cMacro {
0119   public:
0120     cMacroLInc () : cMacro ("linc") {}
0121     void eval (const QString &params, int, cCmdQueue *queue) override {
0122       QString varname = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0123       QString value = params.section (' ', 1, 1, QString::SectionSkipEmpty);
0124       bool ok = false;
0125       double val = value.toDouble(&ok);
0126       if (ok) {
0127         cValue *v = queue->value (varname);
0128         if (!v)  // no such variable ?
0129           queue->setValue (varname, cValue (val));
0130         else
0131           queue->setValue (varname, cValue (v->asDouble() + val));
0132       }
0133     }
0134 };
0135 
0136 class cMacroLDec : public cMacro {
0137   public:
0138     cMacroLDec () : cMacro ("ldec") {}
0139     void eval (const QString &params, int, cCmdQueue *queue) override {
0140       QString varname = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0141       QString value = params.section (' ', 1, 1, QString::SectionSkipEmpty);
0142       bool ok = false;
0143       double val = value.toDouble(&ok);
0144       if (ok) {
0145         cValue *v = queue->value (varname);
0146         if (!v)  // no such variable ?
0147           queue->setValue (varname, cValue (-val));
0148         else
0149           queue->setValue (varname, cValue (v->asDouble() - val));
0150       }
0151     }
0152 };
0153 
0154 class cMacroProvideRes : public cMacro {
0155 public:
0156   cMacroProvideRes () : cMacro ("provide-res") {}
0157   void eval (const QString &params, int sess, cCmdQueue *) override {
0158     QString varname = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0159     varList(sess)->provideResource (varname);
0160   }
0161 };
0162 
0163 class cMacroRequestRes : public cMacro {
0164 public:
0165   cMacroRequestRes () : cMacro ("request-res") {}
0166   void eval (const QString &params, int sess, cCmdQueue *) override {
0167     QString varname = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0168     bool ret = varList(sess)->requestResource (varname);
0169     if (!ret)
0170       am->invokeEvent ("message", sess, i18n ("No free resources of that type."));
0171   }
0172 };
0173 
0174 class cMacroEcho : public cMacro {
0175 public:
0176   cMacroEcho () : cMacro ("echo") {}
0177   void eval (const QString &params, int sess, cCmdQueue *queue) override {
0178     if( !params.isEmpty() )
0179     {
0180       QString txt = expandVariables (params, sess, queue);
0181       am->invokeEvent ("user-message", sess, txt);
0182     }
0183   }
0184 };
0185 
0186 class cMacroTick : public cMacro {
0187 public:
0188   cMacroTick () : cMacro ("tick") {}
0189   void eval (const QString &params, int sess, cCmdQueue *) override {
0190     QString objName = params;
0191     if (!objName.length()) {
0192       am->invokeEvent ("message", sess, i18n ("/tick: syntax: /tick timer-name"));
0193       return;
0194     }
0195     cList *list = cListManager::self()->getList (sess, "timers");
0196     if (!list) return;  // should never happen
0197     // get the timer object
0198     cTimer *timer = dynamic_cast<cTimer *>(list->getObject (objName));
0199     if (!timer) {
0200       am->invokeEvent ("message", sess, i18n ("/tick: a timer with that name does not exist."));
0201       return;
0202     }
0203     if (!timer->enabled()) {
0204       am->invokeEvent ("message", sess, i18n ("/tick: this timer is currently disabled."));
0205       return;
0206     }
0207     int time = timer->tickTimeout ();
0208     if (time > 0)
0209       am->invokeEvent ("message", sess, i18np ("Timer ticks in 1 second.", "Timer ticks in %1 seconds.", QString::number(time)));
0210     else
0211       am->invokeEvent ("message", sess, i18n ("Timer ticks right now."));
0212   }
0213 };
0214 
0215 class cMacroTickNow : public cMacro {
0216 public:
0217   cMacroTickNow () : cMacro ("ticknow") {}
0218   void eval (const QString &params, int sess, cCmdQueue *) override {
0219     QString objName = params;
0220     if (!objName.length()) {
0221       am->invokeEvent ("message", sess, i18n ("/ticknow: syntax: /ticknow timer-name"));
0222       return;
0223     }
0224     cList *list = cListManager::self()->getList (sess, "timers");
0225     if (!list) return;  // should never happen
0226     // get the timer object
0227     cTimer *timer = dynamic_cast<cTimer *>(list->getObject (objName));
0228     if (!timer) {
0229       am->invokeEvent ("message", sess, i18n ("/tick: a timer with that name does not exist."));
0230       return;
0231     }
0232     if (!timer->enabled()) {
0233       am->invokeEvent ("message", sess, i18n ("/tick: this timer is currently disabled."));
0234       return;
0235     }
0236     timer->execute ();
0237   }
0238 };
0239 
0240 class cMacroAddItem : public cMacro {
0241   public:
0242     cMacroAddItem () : cMacro ("additem") {}
0243     void eval (const QString &params, int sess, cCmdQueue *queue) override {
0244       QString varname = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0245       QString value = params.section (' ', 1, -1, QString::SectionSkipEmpty);
0246       varList(sess)->valueNotEmpty(varname, queue)->addToList (value);
0247       // TODO: report variable change ... same for the next three macros ...
0248     }
0249 };
0250 
0251 class cMacroDelItem : public cMacro {
0252   public:
0253     cMacroDelItem () : cMacro ("delitem") {}
0254     void eval (const QString &params, int sess, cCmdQueue *queue) override {
0255       QString varname = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0256       QString value = params.section (' ', 1, -1, QString::SectionSkipEmpty);
0257       cValue *val = varList(sess)->value(varname, queue);
0258       if (val) val->removeFromList (value);
0259     }
0260 };
0261 
0262 class cMacroArraySet : public cMacro {
0263   public:
0264     cMacroArraySet () : cMacro ("arrayset") {}
0265     void eval (const QString &params, int sess, cCmdQueue *queue) override {
0266       QString varname = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0267       QString index = params.section (' ', 1, 1, QString::SectionSkipEmpty);
0268       QString value = params.section (' ', 2, -1, QString::SectionSkipEmpty);
0269       bool ok;
0270       int idx = index.toInt (&ok);
0271       if (!ok) return;
0272       varList(sess)->valueNotEmpty(varname, queue)->setItem(idx, value);
0273     }
0274 };
0275 
0276 class cMacroArrayDel : public cMacro {
0277   public:
0278     cMacroArrayDel () : cMacro ("arraydel") {}
0279     void eval (const QString &params, int sess, cCmdQueue *queue) override {
0280       QString varname = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0281       QString index = params.section (' ', 1, 1, QString::SectionSkipEmpty);
0282       bool ok;
0283       int idx = index.toInt (&ok);
0284       if (!ok) return;
0285       cValue *val = varList(sess)->value(varname, queue);
0286       if (val) val->removeItem (idx);
0287     }
0288 };
0289 
0290 
0291 class cMacroIf : public cMacro {
0292 public:
0293   cMacroIf () : cMacro ("if") {}
0294   void eval (const QString &params, int sess, cCmdQueue *queue) override
0295   {
0296     // we should perform matching (else preproc would fail) - true if non-zero
0297     QString par1 = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0298     par1 = expandVariables (par1, sess, queue);
0299     bool match = (cValue(par1).asInteger () != 0);
0300     
0301     cExecStack *es = queue->execStack ("if");
0302     
0303     // first /if ? register as preproc command
0304     if (es->empty())
0305       queue->addPreprocessMacro (this);
0306 
0307     // put value to the exec-stack
0308     cExecStackItem item;
0309     item.setAttrib ("match", match ? 1 : 0);
0310     es->push (item);
0311   }
0312 
0313   bool preprocess (cCmdQueue *queue, cCmdQueueEntry *qe) override
0314   {
0315     cExecStack *es = queue->execStack ("if");
0316     
0317     // do nothing if the stack is empty
0318     if (es->empty()) return true;
0319 
0320     // if the top value on the stack has non-zero match, we should execute the command
0321     cExecStackItem item = es->top ();
0322     if (item.attrib ("match")) return true;
0323     
0324     // match is 0, we (probably) won't execute ...
0325     // we need to check for nested if-s first
0326     // anything else than if, else, endif - simply return false
0327     if (!qe->isMacro) return false;
0328     cExecStack *es2 = queue->execStack ("if-ignore");
0329     cExecStackItem item2;
0330     if (qe->macroName == "if")
0331     {
0332       // nested ignored if
0333       // put a value to if-ignore stack
0334       es2->push (item2);
0335       return false;
0336     }
0337     else if (qe->macroName == "else")
0338     {
0339       // End of if branch, execute this command, unless the if-ignore stack is non-empty.
0340       // If the if-ignore stack is empty, we want to exec /else.
0341       return es2->empty();
0342     }
0343     else if (qe->macroName == "endif")
0344     {
0345       // If we ignore some if (if-ignore stack is not empty), we pop one item from there
0346       // and return false. Otherwise, we return true - want to exec /endif.
0347       if (es2->empty())
0348         return true;
0349       es2->pop ();
0350       return false;
0351     }
0352     else return false;   // ignoring all other macros
0353   };
0354 };
0355 
0356 class cMacroElse : public cMacro {
0357 public:
0358   cMacroElse () : cMacro ("else") {}
0359   void eval (const QString &, int sess, cCmdQueue *queue) override {
0360     cExecStack *es = queue->execStack ("if");
0361     // display some error if the stack is empty
0362     if (es->empty()) {
0363       am->invokeEvent ("message", sess, i18n ("/else: called without the matching /if."));
0364       return;
0365     }
0366     // remove one if from the stack, switch its "match" value and push it back
0367     cExecStackItem item = es->pop ();
0368     item.setAttrib ("match", !(item.attrib ("match")));
0369     es->push (item);
0370   }
0371 };
0372 
0373 class cMacroEndIf : public cMacro {
0374 public:
0375   cMacroEndIf () : cMacro ("endif") {}
0376   void eval (const QString &, int sess, cCmdQueue *queue) override {
0377     cExecStack *es = queue->execStack ("if");
0378     // display some error if the stack is empty
0379     if (es->empty()) {
0380       am->invokeEvent ("message", sess, i18n ("/endif: called without the matching /if."));
0381       return;
0382     }
0383     // remove one if from the stack
0384     es->pop ();
0385     // unregister the if preprocess macro, if we're not in any /if (ie., stack empty)
0386     if (es->empty ())
0387       queue->removePreprocessMacro (cMacroManager::self()->macro ("if"));
0388   }
0389 };
0390 
0391 class cMacroOAdd : public cMacro {
0392 public:
0393   cMacroOAdd () : cMacro ("oadd") {}
0394   void eval (const QString &params, int sess, cCmdQueue *) override {
0395     QString par1 = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0396     QString par2 = params.section (' ', 1, -1, QString::SectionSkipEmpty);
0397     if (par1.isEmpty() || par2.isEmpty()) {
0398       am->invokeEvent ("message", sess, i18n ("/oadd: syntax: /oadd parent name"));
0399       return;
0400     }
0401 
0402     cListManager *lm = cListManager::self();
0403     int objId = cValue (par1).asInteger();
0404     cListObject *group = lm->object (objId);
0405     if (!group) {
0406       am->invokeEvent ("message", sess, i18n ("/oadd: parent group does not exist."));
0407       return;
0408     }
0409     if (!group->isGroup()) {
0410       am->invokeEvent ("message", sess, i18n ("/oadd: parent must be a group."));
0411       return;
0412     }
0413     cList *list = group->list ();
0414     if (list->getObject (par2)) {
0415       am->invokeEvent ("message", sess, i18n ("/oadd: object with this name already exists."));
0416       return;
0417     }
0418     
0419     cListObject *obj = list->newObject();
0420     list->addToGroup ((cListGroup *) group, obj);
0421     list->setObjectName (obj, par2);
0422   }
0423 };
0424 
0425 class cMacroGAdd : public cMacro {
0426 public:
0427   cMacroGAdd () : cMacro ("gadd") {}
0428   void eval (const QString &params, int sess, cCmdQueue *) override {
0429     QString par1 = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0430     QString par2 = params.section (' ', 1, -1, QString::SectionSkipEmpty);
0431     if (par2.isEmpty()) {
0432       am->invokeEvent ("message", sess, i18n ("/gadd: syntax: /gadd parent name"));
0433       return;
0434     }
0435     int objId = cValue (par1).asInteger();
0436     cListManager *lm = cListManager::self();
0437     cListObject *obj = lm->object (objId);
0438     if (!obj) {
0439       am->invokeEvent ("message", sess, i18n ("/gadd: parent group does not exist."));
0440       return;
0441     }
0442     if (!obj->isGroup()) {
0443       am->invokeEvent ("message", sess, i18n ("/gadd: the parent must be a group"));
0444       return;
0445     }
0446 
0447     cList *list = obj->list();
0448     if (list->group (par2)) {
0449       am->invokeEvent ("message", sess, i18n ("/gadd: such group already exists in that list"));
0450       return;
0451     }
0452     list->addGroup ((cListGroup *) obj, par2);
0453   }
0454 };
0455 
0456 class cMacroODel : public cMacro {
0457 public:
0458   cMacroODel () : cMacro ("odel") {}
0459   void eval (const QString &params, int sess, cCmdQueue *) override {
0460     QString par1 = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0461     int objId = cValue (par1).asInteger();
0462     cListManager *lm = cListManager::self();
0463     cListObject *obj = lm->object (objId);
0464     if (!obj) {
0465       am->invokeEvent ("message", sess, i18n ("/odel: object does not exist."));
0466       return;
0467     }
0468     cList *list = obj->list();
0469     if (obj == list->rootGroup()) {
0470       am->invokeEvent ("message", sess, i18n ("/odel: root group may not be deleted."));
0471       return;
0472     }
0473     if (obj->isGroup())
0474       list->removeGroup ((cListGroup *) obj);
0475     else
0476       list->deleteObject (obj);
0477   }
0478 };
0479 
0480 class cMacroOMove : public cMacro {
0481 public:
0482   cMacroOMove () : cMacro ("omove") {}
0483   void eval (const QString &params, int sess, cCmdQueue *) override {
0484     QString par1 = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0485     QString par2 = params.section (' ', 1, 1, QString::SectionSkipEmpty);
0486     QString par3 = params.section (' ', 2, 2, QString::SectionSkipEmpty);
0487     if (par2.isEmpty()) {
0488       am->invokeEvent ("message", sess, i18n ("/omove: syntax: /omove object group [position]"));
0489       return;
0490     }
0491     int objId = cValue (par1).asInteger();
0492     cListManager *lm = cListManager::self();
0493     cListObject *obj = lm->object (objId);
0494     if (!obj) {
0495       am->invokeEvent ("message", sess, i18n ("/omove: object does not exist."));
0496       return;
0497     }
0498     if (obj == obj->list()->rootGroup()) {
0499       am->invokeEvent ("message", sess, i18n ("/omove: root group may not be moved."));
0500       return;
0501     }
0502     objId = cValue (par2).asInteger();
0503     cListObject *group = lm->object (objId);
0504     if (!group) {
0505       am->invokeEvent ("message", sess, i18n ("/omove: group does not exist."));
0506       return;
0507     }
0508     if (!group->isGroup()) {
0509       am->invokeEvent ("message", sess, i18n ("/omove: target must be a group."));
0510       return;
0511     }
0512     if (obj->list() != group->list()) {
0513       am->invokeEvent ("message", sess, i18n ("/omove: object and target must be in the same list."));
0514       return;
0515     }
0516 
0517     cList *list = obj->list();
0518     list->addToGroup ((cListGroup *) group, obj);
0519 
0520     if (!par3.isEmpty()) {
0521       // position is given
0522       int pos = cValue (par3).asInteger();
0523       cListGroup *g = (cListGroup *) group;
0524       if ((pos < 1) || (pos > g->objectCount())) {
0525         am->invokeEvent ("message", sess, i18n ("/omove: position out of range"));
0526         return;
0527       }
0528       g->moveObjectToPosition (obj, pos - 1);
0529     }
0530   }
0531 };
0532 
0533 class cMacroORen : public cMacro {
0534 public:
0535   cMacroORen () : cMacro ("oren") {}
0536   void eval (const QString &params, int sess, cCmdQueue *) override {
0537     QString par1 = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0538     QString par2 = params.section (' ', 1, -1, QString::SectionSkipEmpty);
0539     if (par2.isEmpty()) {
0540       am->invokeEvent ("message", sess, i18n ("/oren: syntax: /oren object new-name"));
0541       return;
0542     }
0543     int objId = cValue (par1).asInteger();
0544     cListManager *lm = cListManager::self();
0545     cListObject *obj = lm->object (objId);
0546     if (!obj) {
0547       am->invokeEvent ("message", sess, i18n ("/oren: object does not exist."));
0548       return;
0549     }
0550 
0551     cList *list = obj->list();
0552     if (obj == list->rootGroup()) {
0553       am->invokeEvent ("message", sess, i18n ("/oren: root group cannot be renamed."));
0554       return;
0555     }
0556     if (obj->isGroup()) {
0557       cListGroup *g = list->group (par2);
0558       if (g && (g != obj)) {
0559         am->invokeEvent ("message", sess, i18n ("/oren: a group with this name already exists."));
0560         return;
0561       }
0562       list->renameGroup ((cListGroup *) obj, par2);
0563     } else {
0564       cListObject *o = list->getObject (par2);
0565       if (o && (o != obj)) {
0566         am->invokeEvent ("message", sess, i18n ("/oren: an object with this name already exists."));
0567         return;
0568       }
0569       list->setObjectName (obj, par2);
0570     }
0571   }
0572 };
0573 
0574 class cMacroOPriority : public cMacro {
0575 public:
0576   cMacroOPriority () : cMacro ("opriority") {}
0577   void eval (const QString &params, int sess, cCmdQueue *) override {
0578     QString par1 = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0579     QString par2 = params.section (' ', 1, 1, QString::SectionSkipEmpty);
0580     if (par2.isEmpty()) {
0581       am->invokeEvent ("message", sess, i18n ("/opriority: syntax: /opriority object priority"));
0582       return;
0583     }
0584     int objId = cValue (par1).asInteger();
0585     cListManager *lm = cListManager::self();
0586     cListObject *obj = lm->object (objId);
0587     if (!obj) {
0588       am->invokeEvent ("message", sess, i18n ("/opriority: object does not exist."));
0589       return;
0590     }
0591 
0592     int priority = cValue (par2).asInteger();
0593     if ((priority < 1) || (priority > 1000)) {
0594       am->invokeEvent ("message", sess, i18n ("/opriority: priority must be in the 1-1000 range."));
0595       return;
0596     }
0597     obj->setPriority (priority);
0598   }
0599 };
0600 
0601 class cMacroOEnable : public cMacro {
0602 public:
0603   cMacroOEnable () : cMacro ("oenable") {}
0604   void eval (const QString &params, int sess, cCmdQueue *) override {
0605     QString par1 = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0606     int objId = cValue (par1).asInteger();
0607     cListManager *lm = cListManager::self();
0608     cListObject *obj = lm->object (objId);
0609     if (!obj) {
0610       am->invokeEvent ("message", sess, i18n ("/oenable: object does not exist."));
0611       return;
0612     }
0613     obj->setEnabled (true);
0614   }
0615 };
0616 
0617 class cMacroODisable : public cMacro {
0618 public:
0619   cMacroODisable () : cMacro ("odisable") {}
0620   void eval (const QString &params, int sess, cCmdQueue *) override {
0621     QString par1 = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0622     int objId = cValue (par1).asInteger();
0623     cListManager *lm = cListManager::self();
0624     cListObject *obj = lm->object (objId);
0625     if (!obj) {
0626       am->invokeEvent ("message", sess, i18n ("/odisable: object does not exist."));
0627       return;
0628     }
0629     obj->setEnabled (false);
0630   }
0631 };
0632 
0633 class cMacroOSetBAttr : public cMacro {
0634 public:
0635   cMacroOSetBAttr () : cMacro ("osetbattr") {}
0636   void eval (const QString &params, int sess, cCmdQueue *) override {
0637     QString par1 = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0638     QString par2 = params.section (' ', 1, 1, QString::SectionSkipEmpty);
0639     QString par3 = params.section (' ', 2, 2, QString::SectionSkipEmpty);
0640     if (par2.isEmpty() || par3.isEmpty()) {
0641       am->invokeEvent ("message", sess, i18n ("/osetbattr: syntax: /osetbattr object parameter value"));
0642       return;
0643     }
0644     int objId = cValue (par1).asInteger();
0645     cListManager *lm = cListManager::self();
0646     cListObject *obj = lm->object (objId);
0647     if (!obj) {
0648       am->invokeEvent ("message", sess, i18n ("/osetbattr: object does not exist."));
0649       return;
0650     }
0651 
0652     bool val = (cValue (par3).asInteger() != 0);
0653     obj->setBool (par2, val);
0654   }
0655 };
0656 
0657 class cMacroOSetIAttr : public cMacro {
0658 public:
0659   cMacroOSetIAttr () : cMacro ("osetiattr") {}
0660   void eval (const QString &params, int sess, cCmdQueue *) override {
0661     QString par1 = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0662     QString par2 = params.section (' ', 1, 1, QString::SectionSkipEmpty);
0663     QString par3 = params.section (' ', 2, 2, QString::SectionSkipEmpty);
0664     if (par2.isEmpty() || par3.isEmpty()) {
0665       am->invokeEvent ("message", sess, i18n ("/osetiattr: syntax: /osetbattr object parameter value"));
0666       return;
0667     }
0668     int objId = cValue (par1).asInteger();
0669     cListManager *lm = cListManager::self();
0670     cListObject *obj = lm->object (objId);
0671     if (!obj) {
0672       am->invokeEvent ("message", sess, i18n ("/osetiattr: object does not exist."));
0673       return;
0674     }
0675 
0676     int val = cValue (par3).asInteger();
0677     obj->setInt (par2, val);
0678   }
0679 };
0680 
0681 class cMacroOSetSAttr : public cMacro {
0682 public:
0683   cMacroOSetSAttr () : cMacro ("osetsattr") {}
0684   void eval (const QString &params, int sess, cCmdQueue *) override {
0685     QString par1 = params.section (' ', 0, 0, QString::SectionSkipEmpty);
0686     QString par2 = params.section (' ', 1, 1, QString::SectionSkipEmpty);
0687     QString par3 = params.section (' ', 2, -1, QString::SectionSkipEmpty);
0688     if (par2.isEmpty() || par3.isEmpty()) {
0689       am->invokeEvent ("message", sess, i18n ("/osetiattr: syntax: /osetbattr object parameter value"));
0690       return;
0691     }
0692     int objId = cValue (par1).asInteger();
0693     cListManager *lm = cListManager::self();
0694     cListObject *obj = lm->object (objId);
0695     if (!obj) {
0696       am->invokeEvent ("message", sess, i18n ("/osetsattr: object does not exist."));
0697       return;
0698     }
0699 
0700     obj->setStr (par2, par3);
0701   }
0702 };
0703 
0704 class cMacroTGroupOn : public cMacro {
0705 public:
0706   cMacroTGroupOn () : cMacro ("tgroupon") {}
0707   void eval (const QString &params, int sess, cCmdQueue *) override {
0708     cListManager *lm = cListManager::self();
0709     cList *list = lm->getList (sess, "triggers");
0710     if (!list) return;
0711     cListGroup *group = list->group (params);
0712     if (!group) {
0713       am->invokeEvent ("message", sess, i18n ("/tgroupon: group does not exist."));
0714       return;
0715     }
0716     group->setEnabled (true);
0717   }
0718 };
0719 class cMacroTGroupOff : public cMacro {
0720 public:
0721   cMacroTGroupOff () : cMacro ("tgroupoff") {}
0722   void eval (const QString &params, int sess, cCmdQueue *) override {
0723     cListManager *lm = cListManager::self();
0724     cList *list = lm->getList (sess, "triggers");
0725     if (!list) return;
0726     cListGroup *group = list->group (params);
0727     if (!group) {
0728       am->invokeEvent ("message", sess, i18n ("/tgroupoff: group does not exist."));
0729       return;
0730     }
0731     group->setEnabled (false);
0732   }
0733 };
0734 
0735 class cMacroAGroupOn : public cMacro {
0736 public:
0737   cMacroAGroupOn () : cMacro ("agroupon") {}
0738   void eval (const QString &params, int sess, cCmdQueue *) override {
0739     cListManager *lm = cListManager::self();
0740     cList *list = lm->getList (sess, "aliases");
0741     if (!list) return;
0742     cListGroup *group = list->group (params);
0743     if (!group) {
0744       am->invokeEvent ("message", sess, i18n ("/agroupon: group does not exist."));
0745       return;
0746     }
0747     group->setEnabled (true);
0748   }
0749 };
0750 
0751 class cMacroAGroupOff : public cMacro {
0752 public:
0753   cMacroAGroupOff () : cMacro ("agroupoff") {}
0754   void eval (const QString &params, int sess, cCmdQueue *) override {
0755     cListManager *lm = cListManager::self();
0756     cList *list = lm->getList (sess, "aliases");
0757     if (!list) return;
0758     cListGroup *group = list->group (params);
0759     if (!group) {
0760       am->invokeEvent ("message", sess, i18n ("/agroupoff: group does not exist."));
0761       return;
0762     }
0763     group->setEnabled (false);
0764   }
0765 };
0766 
0767 
0768 class cFunctionContains: public cFunction {
0769 public:
0770   cFunctionContains () : cFunction ("contains") {}
0771   cValue eval (std::list<cValue> &params, int, cCmdQueue *) override {
0772     if (params.size() < 2) return cValue::empty();
0773     std::list<cValue>::iterator it = params.begin();
0774     cValue lst = *it;
0775     ++it;
0776     cValue val = *it;
0777     if (lst.isList())
0778       return cValue (lst.contains (val.asString()) ? 1 : 0);
0779     // not a list ? Doesn't contain it then !
0780     return cValue::empty();
0781   }
0782 };
0783 
0784 class cFunctionItem: public cFunction {
0785 public:
0786   cFunctionItem () : cFunction ("item") {}
0787   cValue eval (std::list<cValue> &params, int, cCmdQueue *) override {
0788     if (params.size() < 2) return cValue::empty();
0789     std::list<cValue>::iterator it = params.begin();
0790     cValue lst = *it;
0791     ++it;
0792     cValue val = *it;
0793     if (lst.isArray())
0794       return cValue (lst.item (val.asInteger()));
0795     // not an array ? Not applicable then !
0796     return cValue::empty();
0797   }
0798 };
0799 
0800 class cFunctionCount: public cFunction {
0801   public:
0802     cFunctionCount () : cFunction ("count") {}
0803     cValue eval (std::list<cValue> &params, int, cCmdQueue *) override {
0804       int count = 0;
0805       std::list<cValue>::iterator it = params.begin();
0806       for (; it != params.end(); ++it) {
0807         count += (*it).size();
0808       }
0809       return cValue (count);
0810     }
0811 };
0812 
0813 class cFunctionGlobal: public cFunction {
0814   public:
0815     cFunctionGlobal () : cFunction ("global") {}
0816     cValue eval (std::list<cValue> &params, int sess, cCmdQueue *) override {
0817       if (params.size() == 0) return cValue::empty();
0818       QString varName = (*params.begin()).asString();
0819       cValue *val = varList(sess)->value (varName, nullptr);
0820       if (val) return *val;
0821       return cValue::empty();
0822     }
0823 };
0824 
0825 class cFunctionLocal: public cFunction {
0826   public:
0827     cFunctionLocal () : cFunction ("local") {}
0828     cValue eval (std::list<cValue> &params, int, cCmdQueue *queue) override {
0829       if ((params.size() == 0) || (!queue)) return cValue::empty();
0830       QString varName = (*params.begin()).asString();
0831       cValue *val = queue->value (varName);
0832       if (val) return *val;
0833       return cValue::empty();
0834     }
0835 };
0836 
0837 class cFunctionAttrib: public cFunction {
0838   public:
0839     cFunctionAttrib () : cFunction ("attrib") {}
0840     cValue eval (std::list<cValue> &params, int sess, cCmdQueue *) override {
0841       if (params.size() < 2) return cValue::empty();
0842       std::list<cValue>::iterator it = params.begin();
0843       QString object = (*it).asString();
0844       ++it;
0845       QString attrib = (*it).asString();
0846       return cValue (am->object (object, sess)->attrib (attrib));
0847     }
0848 };
0849 
0850 class cFunctionStrAttrib: public cFunction {
0851   public:
0852     cFunctionStrAttrib () : cFunction ("strattrib") {}
0853     cValue eval (std::list<cValue> &params, int sess, cCmdQueue *) override {
0854       if (params.size() < 2) return cValue::empty();
0855       std::list<cValue>::iterator it = params.begin();
0856       QString object = (*it).asString();
0857       ++it;
0858       QString attrib = (*it).asString();
0859       return cValue (am->object (object, sess)->strAttrib (attrib));
0860     }
0861 };
0862 
0863 class cFunctionObject: public cFunction {
0864   public:
0865     cFunctionObject () : cFunction ("object") {}
0866     cValue eval (std::list<cValue> &params, int sess, cCmdQueue *) override {
0867       if (params.size() < 2) return cValue::empty();
0868       std::list<cValue>::iterator it = params.begin();
0869       QString listName = (*it).asString();
0870       ++it;
0871       QString objName = (*it).asString();
0872 
0873       cListManager *lm = cListManager::self();
0874       cList *list = lm->getList (sess, listName);
0875       if (!list) return cValue(0);
0876       cListObject *obj = list->getObject (objName);
0877       if (!obj) return cValue(0);
0878       return cValue (lm->objectId (obj));
0879     }
0880 };
0881 
0882 class cFunctionGroup: public cFunction {
0883   public:
0884     cFunctionGroup () : cFunction ("group") {}
0885     cValue eval (std::list<cValue> &params, int sess, cCmdQueue *) override {
0886       if (params.size() < 2) return cValue::empty();
0887       std::list<cValue>::iterator it = params.begin();
0888       QString listName = (*it).asString();
0889       ++it;
0890       QString objName = (*it).asString();
0891 
0892       cListManager *lm = cListManager::self();
0893       cList *list = lm->getList (sess, listName);
0894       if (!list) return cValue(0);
0895       cListObject *obj = list->group (objName);
0896       if (!obj) return cValue(0);
0897       return cValue (lm->objectId (obj));
0898     }
0899 };
0900 
0901 class cFunctionOBAttr: public cFunction {
0902   public:
0903     cFunctionOBAttr () : cFunction ("obattr") {}
0904     cValue eval (std::list<cValue> &params, int, cCmdQueue *) override {
0905       if (params.size() < 2) return cValue::empty();
0906       std::list<cValue>::iterator it = params.begin();
0907       int id = (*it).asInteger();
0908       ++it;
0909       QString attrName = (*it).asString();
0910 
0911       cListManager *lm = cListManager::self();
0912       cListObject *obj = lm->object (id);
0913       if (!obj) return cValue::empty();
0914       return cValue (obj->boolVal (attrName));
0915     }
0916 };
0917 
0918 class cFunctionOIAttr: public cFunction {
0919   public:
0920     cFunctionOIAttr () : cFunction ("oiattr") {}
0921     cValue eval (std::list<cValue> &params, int, cCmdQueue *) override {
0922       if (params.size() < 2) return cValue::empty();
0923       std::list<cValue>::iterator it = params.begin();
0924       int id = (*it).asInteger();
0925       ++it;
0926       QString attrName = (*it).asString();
0927 
0928       cListManager *lm = cListManager::self();
0929       cListObject *obj = lm->object (id);
0930       if (!obj) return cValue::empty();
0931       return cValue (obj->intVal (attrName));
0932     }
0933 };
0934 
0935 class cFunctionOSAttr: public cFunction {
0936   public:
0937     cFunctionOSAttr () : cFunction ("osattr") {}
0938     cValue eval (std::list<cValue> &params, int, cCmdQueue *) override {
0939       if (params.size() < 2) return cValue::empty();
0940       std::list<cValue>::iterator it = params.begin();
0941       int id = (*it).asInteger();
0942       ++it;
0943       QString attrName = (*it).asString();
0944 
0945       cListManager *lm = cListManager::self();
0946       cListObject *obj = lm->object (id);
0947       if (!obj) return cValue::empty();
0948       return cValue (obj->strVal (attrName));
0949     }
0950 };
0951 
0952 
0953 /*************************************************************/
0954 /***    registerInternalMacros, unregisterInternalMacros   ***/
0955 /*************************************************************/
0956 
0957 
0958 static cMacroSet *mset;
0959 static cMacroUnset *munset;
0960 static cMacroSetVal *msetval;
0961 static cMacroLSet *mlset;
0962 static cMacroLUnset *mlunset;
0963 static cMacroInc *minc;
0964 static cMacroDec *mdec;
0965 static cMacroLInc *mlinc;
0966 static cMacroLDec *mldec;
0967 static cMacroProvideRes *mprovideres;
0968 static cMacroRequestRes *mrequestres;
0969 static cMacroEcho *mecho;
0970 static cMacroTick *mtick;
0971 static cMacroTickNow *mticknow;
0972 static cMacroAddItem *madditem;
0973 static cMacroDelItem *mdelitem;
0974 static cMacroArraySet *marrayset;
0975 static cMacroArrayDel *marraydel;
0976 static cMacroIf *mif;
0977 static cMacroElse *melse;
0978 static cMacroEndIf *mendif;
0979 static cMacroTGroupOn *mtgroupon;
0980 static cMacroTGroupOff *mtgroupoff;
0981 static cMacroAGroupOn *magroupon;
0982 static cMacroAGroupOff *magroupoff;
0983 
0984 static cMacroOAdd *moadd;
0985 static cMacroGAdd *mgadd;
0986 static cMacroODel *model;
0987 static cMacroOMove *momove;
0988 static cMacroORen *moren;
0989 static cMacroOPriority *mopriority;
0990 static cMacroOEnable *moenable;
0991 static cMacroODisable *modisable;
0992 static cMacroOSetBAttr *mosetbattr;
0993 static cMacroOSetIAttr *mosetiattr;
0994 static cMacroOSetSAttr *mosetsattr;
0995 
0996 static cFunctionContains *fcontains;
0997 static cFunctionItem *fitem;
0998 static cFunctionCount *fcount;
0999 static cFunctionGlobal *fglobal;
1000 static cFunctionLocal *flocal;
1001 static cFunctionAttrib *fattrib;
1002 static cFunctionStrAttrib *fstrattrib;
1003 
1004 static cFunctionObject *fobject;
1005 static cFunctionGroup *fgroup;
1006 static cFunctionOBAttr *fobattr;
1007 static cFunctionOIAttr *foiattr;
1008 static cFunctionOSAttr *fosattr;
1009 
1010 void registerInternalMacros ()
1011 {
1012   mset = new cMacroSet;
1013   munset = new cMacroUnset;
1014   msetval = new cMacroSetVal;
1015   mlset = new cMacroLSet;
1016   mlunset = new cMacroLUnset;
1017   minc = new cMacroInc;
1018   mdec = new cMacroDec;
1019   mlinc = new cMacroLInc;
1020   mldec = new cMacroLDec;
1021   mprovideres = new cMacroProvideRes;
1022   mrequestres = new cMacroRequestRes;
1023   mecho = new cMacroEcho;
1024   mtick = new cMacroTick;
1025   mticknow = new cMacroTickNow;
1026   madditem = new cMacroAddItem;
1027   mdelitem = new cMacroDelItem;
1028   marrayset = new cMacroArraySet;
1029   marraydel = new cMacroArrayDel;
1030   mif = new cMacroIf;
1031   melse = new cMacroElse;
1032   mendif = new cMacroEndIf;
1033 
1034   moadd = new cMacroOAdd;
1035   mgadd = new cMacroGAdd;
1036   model = new cMacroODel;
1037   momove = new cMacroOMove;
1038   moren = new cMacroORen;
1039   mopriority = new cMacroOPriority;
1040   moenable = new cMacroOEnable;
1041   modisable = new cMacroODisable;
1042   mosetbattr = new cMacroOSetBAttr;
1043   mosetiattr = new cMacroOSetIAttr;
1044   mosetsattr = new cMacroOSetSAttr;
1045 
1046   mtgroupon = new cMacroTGroupOn;
1047   mtgroupoff = new cMacroTGroupOff;
1048   magroupon = new cMacroAGroupOn;
1049   magroupoff = new cMacroAGroupOff;
1050 
1051   fcontains = new cFunctionContains;
1052   fitem = new cFunctionItem;
1053   fcount = new cFunctionCount;
1054   fglobal = new cFunctionGlobal;
1055   flocal = new cFunctionLocal;
1056   fattrib = new cFunctionAttrib;
1057   fstrattrib = new cFunctionStrAttrib;
1058 
1059   fobject = new cFunctionObject;
1060   fgroup = new cFunctionGroup;
1061   fobattr = new cFunctionOBAttr;
1062   foiattr = new cFunctionOIAttr;
1063   fosattr = new cFunctionOSAttr;
1064 
1065 }
1066 
1067 void unregisterInternalMacros ()
1068 {
1069   delete mset;
1070   delete munset;
1071   delete msetval;
1072   delete mlset;
1073   delete mlunset;
1074   delete minc;
1075   delete mdec;
1076   delete mlinc;
1077   delete mldec;
1078   delete mprovideres;
1079   delete mrequestres;
1080   delete mecho;
1081   delete mtick;
1082   delete mticknow;
1083   delete madditem;
1084   delete mdelitem;
1085   delete marrayset;
1086   delete marraydel;
1087   delete mif;
1088   delete melse;
1089   delete mendif;
1090 
1091   delete moadd;
1092   delete mgadd;
1093   delete model;
1094   delete momove;
1095   delete moren;
1096   delete moenable;
1097   delete modisable;
1098   delete mopriority;
1099   delete mosetbattr;
1100   delete mosetiattr;
1101   delete mosetsattr;
1102 
1103   delete mtgroupon;
1104   delete mtgroupoff;
1105   delete magroupon;
1106   delete magroupoff;
1107 
1108   delete fcontains;
1109   delete fitem;
1110   delete fcount;
1111   delete fglobal;
1112   delete flocal;
1113   delete fattrib;
1114   delete fstrattrib;
1115 
1116   delete fobject;
1117   delete fgroup;
1118   delete fobattr;
1119   delete foiattr;
1120   delete fosattr;
1121 }
1122