File indexing completed on 2024-04-21 15:08:08

0001 //
0002 // C++ Implementation: cmxpmanager
0003 //
0004 // Description:
0005 //
0006 /*
0007 Copyright 2004-2011 Tomas Mecir <kmuddy@kmuddy.com>
0008 
0009 This program is free software; you can redistribute it and/or
0010 modify it under the terms of the GNU General Public License as
0011 published by the Free Software Foundation; either version 2 of 
0012 the License, or (at your option) any later version.
0013 
0014 This program is distributed in the hope that it will be useful,
0015 but WITHOUT ANY WARRANTY; without even the implied warranty of
0016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0017 GNU General Public License for more details.
0018 
0019 You should have received a copy of the GNU General Public License
0020 along with this program.  If not, see <http://www.gnu.org/licenses/>.
0021 */
0022 
0023 #include "cmxpmanager.h"
0024 
0025 #ifdef HAVE_MXP
0026 
0027 #include "cgaugelist.h"
0028 #include "cglobalsettings.h"
0029 #include "cprofilesettings.h"
0030 #include "cstatusvarlist.h"
0031 #include "ctelnet.h"
0032 #include "cvariablelist.h"
0033 #include "kmuddy-version.h"
0034 #include "cmxpconsole.h"
0035 
0036 #include <KLocalizedString>
0037 
0038 // from ctextchunk.h
0039 #define ATTRIB_BOLD 1
0040 #define ATTRIB_ITALIC 2
0041 #define ATTRIB_UNDERLINE 4
0042 #define ATTRIB_STRIKEOUT 8
0043 
0044 #endif
0045 
0046 cMXPManager::cMXPManager (int sess) : cActionBase ("mxpmanager", sess)
0047 {
0048 #ifdef HAVE_MXP
0049   havehandler = false;
0050   reset ();
0051   addEventHandler ("connected", 100, PT_NOTHING);
0052   addGlobalEventHandler ("global-settings-changed", 50, PT_NOTHING);
0053 #endif
0054 }
0055 
0056 cMXPManager::~cMXPManager ()
0057 {
0058 #ifdef HAVE_MXP
0059   removeEventHandler ("connected");
0060   removeGlobalEventHandler ("global-settings-changed");
0061 
0062   if (havehandler)
0063     mxpDestroyHandler (h);
0064   havehandler = false;
0065 #endif
0066 }
0067 
0068 #ifdef HAVE_MXP
0069 
0070 void cMXPManager::eventNothingHandler (QString event, int)
0071 {
0072   if (event == "connected")
0073     reset ();
0074   if (event == "global-settings-changed") {
0075     cGlobalSettings *gs = cGlobalSettings::self();
0076     setDefaultFont (gs->getFont ("console-font"),
0077         gs->getColor ("color-" + QString::number(gs->getInt ("fg-color"))),
0078         gs->getColor ("color-" + QString::number(gs->getInt ("bg-color"))));
0079   }
0080 }
0081 
0082 QString cMXPManager::actionIntHandler (QString action, int, int par1, int /*par2*/)
0083 {
0084   if (action == "set-active") {
0085     setMXPActive (par1 != 0);
0086   }
0087   return QString();
0088 }
0089 
0090 QString cMXPManager::actionNothingHandler (QString action, int)
0091 {
0092   if (action == "switch-open") switchToOpenMode ();
0093   return QString();
0094 }
0095 
0096 void cMXPManager::setMXPActive (bool active)
0097 {
0098   if (active == mxpactive)
0099     return;    //nothing to do
0100 
0101   if (active)
0102   {
0103     if (!havehandler)
0104       initLibrary ();
0105   }
0106 
0107   mxpactive = active;
0108 }
0109 
0110 void cMXPManager::processText (const QString &text)
0111 {
0112   if (!havehandler)
0113     return;
0114 
0115   //give the text to the library
0116   mxpProcessText (h, text.toLocal8Bit().data());
0117 
0118   //process each result
0119   while (mxpHasResults (h)) {
0120     mxpResult *res = mxpNextResult (h);
0121     if (res->type >= 2)  //got some MXP stuff...
0122       mxpinuse = true;
0123     processResult (res);
0124   };
0125 }
0126 
0127 void cMXPManager::switchToOpenMode ()
0128 {
0129   if (!havehandler)
0130     return;
0131   mxpSwitchToOpen (h);
0132 }
0133 
0134 void cMXPManager::setDefaultFont (QFont font, QColor fg, QColor bg)
0135 {
0136   deffont = font;
0137   deffg = fg;
0138   defbg = bg;
0139   //send font info to the lib, if we have a handler
0140   if (havehandler)
0141     sendDefaultFont ();
0142 }
0143 
0144 void cMXPManager::processResult (mxpResult *res)
0145 {
0146   switch (res->type) {
0147     case 0: { /* NOTHING */ }
0148     break;
0149     case 1: {   //text or newline or SBR
0150       char *s = (char *) res->data;
0151       if (s && (strcmp (s, "\r\n") == 0))  //newlines are always sent separately
0152         emit gotNewLine ();
0153       else
0154       if (s && ((s[0] == 0x1f) && (s[1] == '\0')))
0155         //<SBR> tag - ignored - converted into a space
0156         emit gotNewText (QString (" "));
0157       else
0158         emit gotNewText (s ? QString::fromLocal8Bit (s) : QString (""));
0159     }
0160     break;
0161     case 3: {
0162     // NOTHING HERE YET
0163     }
0164     break;
0165     case 4: {   //variable
0166       varStruct *vs = (varStruct *) res->data;
0167       char *n = vs->name;
0168       char *v = vs->value;
0169       cVariableList *vl = dynamic_cast<cVariableList *>(object ("variables"));
0170       cProfileSettings *sett = settings();
0171       if (sett && n)  //we need a profile and a variable name
0172       {
0173         QString prefix = sett->getString ("mxp-variable-prefix");
0174         if (vs->erase)
0175           //erase that variable
0176           vl->unset (prefix + QString(n));
0177         else
0178           //set that variable
0179           vl->set (prefix+QString(n), v ? QString::fromLocal8Bit(v) : QString());
0180       }
0181     }
0182     break;
0183     case 5: {  //formatting
0184       formatStruct *fs = (formatStruct *) res->data;
0185       unsigned char mask = fs->usemask;
0186 
0187       //colors
0188       if (mask & USE_FG)
0189         emit gotFgColor (toColor (fs->fg));
0190       if (mask & USE_BG)
0191         emit gotBgColor (toColor (fs->bg));
0192 
0193       //font and font size: IGNORED
0194 
0195       //attributes
0196       int oldattrib = curattrib;
0197       if (mask & USE_BOLD)
0198         curattrib = (fs->attributes & Bold) ? (curattrib | ATTRIB_BOLD) :
0199             (curattrib & ~ATTRIB_BOLD);
0200       if (mask & USE_ITALICS)
0201         curattrib = (fs->attributes & Italic) ? (curattrib | ATTRIB_ITALIC) :
0202             (curattrib & ~ATTRIB_ITALIC);
0203       if (mask & USE_UNDERLINE)
0204         curattrib = (fs->attributes & Underline) ? (curattrib | ATTRIB_UNDERLINE) :
0205             (curattrib & ~ATTRIB_UNDERLINE);
0206       if (mask & USE_STRIKEOUT)
0207         curattrib = (fs->attributes & Strikeout) ? (curattrib | ATTRIB_STRIKEOUT) :
0208             (curattrib & ~ATTRIB_STRIKEOUT);
0209       if (curattrib != oldattrib) //attributes have changed somehow
0210         emit gotAttrib (curattrib);
0211     }
0212     break;
0213     case 6: {  //A-link
0214       linkStruct *ls = (linkStruct *) res->data;
0215       QString name = ls->name ? QString::fromLocal8Bit (ls->name) : QString();
0216       QString url = ls->url ? QString::fromLocal8Bit (ls->url) : QString();
0217       QString text = ls->text ? QString::fromLocal8Bit (ls->text) : QString();
0218       QString hint = ls->hint ? QString::fromLocal8Bit (ls->hint) : QString();
0219       emit gotALink (name, url, text, hint);
0220     }
0221     break;
0222     case 7: {  //SEND-link
0223       sendStruct *ss = (sendStruct *) res->data;
0224       QString name = ss->name ? QString::fromLocal8Bit (ss->name) : QString();
0225       QString command = ss->command ? QString::fromLocal8Bit (ss->command) : QString();
0226       QString text = ss->text ? QString::fromLocal8Bit (ss->text) : QString();
0227       QString hint = ss->hint ? QString::fromLocal8Bit (ss->hint) : QString();
0228       emit gotSENDLink (name, command, text, hint, ss->toprompt, ss->ismenu);
0229     }
0230     break;
0231     case 8: {  //expire link
0232       char *name = (char *) res->data;
0233       if (name)
0234         emit gotExpire (QString (name));
0235       else
0236         emit gotExpire (QString());
0237     }
0238     break;
0239     case 9: {  //send this
0240       char *s = (char *) res->data;
0241       cTelnet *telnet = dynamic_cast<cTelnet *>(object ("telnet"));
0242       telnet->sendData (s);
0243     }
0244     break;
0245     case 11: {  //sound/music
0246       soundStruct *ss = (soundStruct *) res->data;
0247       QString fName = ss->fname ? QString (ss->fname) : QString();
0248       QString url = ss->url ? QString (ss->url) : QString();
0249       QString type = ss->type ? QString (ss->type) : QString();
0250       int priority = ss->isSOUND ? ss->priority : (ss->continuemusic ? 1 : 0);
0251 
0252       cTelnet *telnet = dynamic_cast<cTelnet *>(object ("telnet"));
0253       telnet->processSoundRequest (ss->isSOUND, fName, ss->vol, ss->repeats,
0254           priority, type, url);
0255     }
0256     break;
0257     case 22: {  //gauge
0258 /*
0259 // TODO We need to re-enable the MXP gauges !
0260       gaugeStruct *gs = (gaugeStruct *) res->data;
0261       QString var = gs->variable ? QString (gs->variable) : QString();
0262       QString maxvar = gs->maxvariable ? QString (gs->maxvariable) : QString();
0263       QString caption = gs->caption ? QString::fromLocal8Bit (gs->caption) : QString();
0264       QColor color = toColor (gs->color);
0265 
0266       cGaugeList *gl = dynamic_cast<cGaugeList *>(object ("gaugelist"));
0267       if (gl && (!var.isEmpty()))
0268         gl->requestGauge (var, maxvar, caption, color, false);
0269 */
0270     }
0271     break;
0272     case 23: {  //status bar
0273 /*
0274 // TODO We need to re-enable the MXP status variables !
0275       statStruct *ss = (statStruct *) res->data;
0276       QString var = ss->variable ? QString (ss->variable) : QString();
0277       QString maxvar = ss->maxvariable ? QString (ss->maxvariable) : QString();
0278       QString caption = ss->caption ? QString::fromLocal8Bit (ss->caption) : QString();
0279 
0280       cStatusVarList *svl = dynamic_cast<cStatusVarList *>(object ("statusvarlist"));
0281       if (svl && (!var.isEmpty()))
0282         svl->requestStatusVar (var, maxvar, caption, false, false);
0283 */
0284     }
0285     break;
0286     case -1: {  //error
0287       char *s = (char *) res->data;
0288       cMXPConsole::self()->addError (sess(), QString::fromLocal8Bit (s));
0289     }
0290     break;
0291     case -2: {  //warning
0292       char *s = (char *) res->data;
0293       cMXPConsole::self()->addWarning (sess(), QString::fromLocal8Bit (s));
0294     }
0295     break;
0296     default: {
0297       QString reqName;
0298       switch (res->type) {
0299         case 2: reqName = i18n ("line tag"); break;
0300         case 8: reqName = i18n ("expire link"); break;
0301         case 10: reqName = i18n ("horizontal line"); break;
0302         case 12: reqName = i18n ("create window"); break;
0303         case 13: reqName = i18n ("create internal window"); break;
0304         case 14: reqName = i18n ("close window"); break;
0305         case 15: reqName = i18n ("set active window"); break;
0306         case 16: reqName = i18n ("move cursor"); break;
0307         case 17: reqName = i18n ("erase text"); break;
0308         case 18: reqName = i18n ("relocate"); break;
0309         case 19: reqName = i18n ("send username/password"); break;
0310         case 20: reqName = i18n ("image"); break;
0311         case 21: reqName = i18n ("image map"); break;
0312         default: reqName = i18n ("unknown"); break;
0313       };
0314       cMXPConsole::self()->addWarning (sess(), i18n ("Ignoring unsupported MXP request (%1)", reqName));
0315     }
0316     break;
0317   };
0318 }
0319 
0320 QColor cMXPManager::toColor (RGB mxpColor)
0321 {
0322   return QColor (mxpColor.r, mxpColor.g, mxpColor.b);
0323 }
0324 
0325 void cMXPManager::sendDefaultFont ()
0326 {
0327   const char *name = deffont.family ().toLatin1().data();
0328   int size = deffont.pointSize ();
0329   bool bold = deffont.bold ();
0330   bool italics = deffont.italic ();
0331   bool underline = deffont.underline ();
0332   bool strikeout = deffont.strikeOut ();
0333   RGB fg, bg;
0334   fg.r = deffg.red ();
0335   fg.g = deffg.green ();
0336   fg.b = deffg.blue ();
0337   bg.r = defbg.red ();
0338   bg.g = defbg.green ();
0339   bg.b = defbg.blue ();
0340 
0341   //remember current attributes
0342   curattrib = ATTRIB_BOLD * (bold?1:0) + ATTRIB_ITALIC * (italics?1:0) +
0343       ATTRIB_UNDERLINE * (underline?1:0) + ATTRIB_STRIKEOUT * (strikeout?1:0);
0344 
0345   mxpSetDefaultText (h, name, size, bold, italics, underline, strikeout, fg, bg);
0346   mxpSetNonProportFont (h, name);
0347   //header params... most of these aren't used anyway ;)
0348   mxpSetHeaderParams (h, 1, name, size * 3, true, false, true, false, fg, bg);
0349   mxpSetHeaderParams (h, 2, name, size * 2, true, false, false, false, fg, bg);
0350   mxpSetHeaderParams (h, 3, name, size * 3 / 2, true, false, false, false, fg, bg);
0351   mxpSetHeaderParams (h, 4, name, size * 4 / 3, true, false, false, false, fg, bg);
0352   mxpSetHeaderParams (h, 5, name, size + 2, true, false, false, false, fg, bg);
0353   mxpSetHeaderParams (h, 6, name, size, true, false, false, false, fg, bg);
0354 }
0355 
0356 void cMXPManager::initLibrary ()
0357 {
0358   h = mxpCreateHandler ();
0359 
0360   mxpSetClient (h, PACKAGE, VERSION);
0361   sendDefaultFont ();
0362 
0363   //set supported features...
0364   mxpSupportsLink (h, true);
0365   mxpSupportsGauge (h, true);
0366   mxpSupportsStatus (h, true);
0367   mxpSupportsSound (h, true);
0368   mxpSupportsFrame (h, false);
0369   mxpSupportsImage (h, false);
0370   mxpSupportsRelocate (h, false);
0371 
0372   //mxpSetScreenProps is not issued, because we don't need it yet
0373 
0374   havehandler = true;
0375 }
0376 
0377 #endif
0378 
0379 //slot - must always exist
0380 void cMXPManager::reset ()
0381 {
0382 #ifdef HAVE_MXP
0383 
0384   if (havehandler)
0385     mxpDestroyHandler (h);
0386   havehandler = false;
0387   mxpactive = false;
0388   mxpinuse = false;
0389   deffont.setFamily ("fixed");  //some default font, will be changed when settings are loaded
0390   deffg = Qt::lightGray;
0391   defbg = Qt::black;
0392   curattrib = 0;
0393 
0394 #endif  //HAVE_MXP
0395 }
0396 
0397 #include "moc_cmxpmanager.cpp"