Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

swmodule.cpp

00001 /******************************************************************************
00002  *  swmodule.cpp -code for base class 'module'.  Module is the basis for all
00003  *                types of modules (e.g. texts, commentaries, maps, lexicons,
00004  *                etc.)
00005  */
00006 
00007 #include <string.h>
00008 #include <swmodule.h>
00009 #include <utilfuns.h>
00010 #include <regex.h>      // GNU
00011 #include <swfilter.h>
00012 #include <versekey.h>   // KLUDGE for Search
00013 #ifndef _MSC_VER
00014 #include <iostream.h>
00015 #endif
00016 
00017 SWDisplay SWModule::rawdisp;
00018 void SWModule::nullPercent(char percent, void *percentUserData) {}
00019 
00020 /******************************************************************************
00021  * SWModule Constructor - Initializes data for instance of SWModule
00022  *
00023  * ENT: imodname - Internal name for module
00024  *      imoddesc - Name to display to user for module
00025  *      idisp    - Display object to use for displaying
00026  *      imodtype - Type of Module (All modules will be displayed with
00027  *                      others of same type under their modtype heading
00028  *      unicode  - if this module is unicode
00029  */
00030 
00031 SWModule::SWModule(const char *imodname, const char *imoddesc, SWDisplay *idisp, char *imodtype, SWTextEncoding encoding, SWTextDirection direction, SWTextMarkup markup, const char* imodlang)
00032 {
00033         key       = CreateKey();
00034         entrybuf  = new char [1];
00035         *entrybuf = 0;
00036         config    = &ownConfig;
00037         entrybufallocsize = 0;
00038         modname   = 0;
00039         error     = 0;
00040         moddesc   = 0;
00041         modtype   = 0;
00042         modlang   = 0;
00043         this->encoding = encoding;
00044         this->direction = direction;
00045         this->markup  = markup;
00046         entrySize= -1;
00047         disp     = (idisp) ? idisp : &rawdisp;
00048         stdstr(&modname, imodname);
00049         stdstr(&moddesc, imoddesc);
00050         stdstr(&modtype, imodtype);
00051         stdstr(&modlang, imodlang);
00052         stripFilters = new FilterList();
00053         rawFilters = new FilterList();
00054         renderFilters = new FilterList();
00055         optionFilters = new FilterList();
00056         encodingFilters = new FilterList();
00057         skipConsecutiveLinks = true;
00058         procEntAttr = true;
00059 }
00060 
00061 
00062 /******************************************************************************
00063  * SWModule Destructor - Cleans up instance of SWModule
00064  */
00065 
00066 SWModule::~SWModule()
00067 {
00068         if (entrybuf)
00069                 delete [] entrybuf;
00070         if (modname)
00071                 delete [] modname;
00072         if (moddesc)
00073                 delete [] moddesc;
00074         if (modtype)
00075                 delete [] modtype;
00076         if (modlang)
00077                 delete [] modlang;
00078 
00079         if (key) {
00080                 if (!key->Persist())
00081                         delete key;
00082         }
00083 
00084         stripFilters->clear();
00085      rawFilters->clear();
00086      renderFilters->clear();
00087      optionFilters->clear();
00088      encodingFilters->clear();
00089         entryAttributes.clear();
00090 
00091      delete stripFilters;
00092      delete rawFilters;
00093      delete renderFilters;
00094      delete optionFilters;
00095      delete encodingFilters;
00096 }
00097 
00098 
00099 /******************************************************************************
00100  * SWModule::CreateKey - Allocates a key of specific type for module
00101  *
00102  * RET: pointer to allocated key
00103  */
00104 
00105 SWKey *SWModule::CreateKey()
00106 {
00107         return new SWKey();
00108 }
00109 
00110 
00111 /******************************************************************************
00112  * SWModule::Error - Gets and clears error status
00113  *
00114  * RET: error status
00115  */
00116 
00117 char SWModule::Error()
00118 {
00119         char retval = error;
00120 
00121         error = 0;
00122         return retval;
00123 }
00124 
00125 
00126 /******************************************************************************
00127  * SWModule::Name - Sets/gets module name
00128  *
00129  * ENT: imodname - value which to set modname
00130  *              [0] - only get
00131  *
00132  * RET: pointer to modname
00133  */
00134 
00135 char *SWModule::Name(const char *imodname)
00136 {
00137         return stdstr(&modname, imodname);
00138 }
00139 
00140 
00141 /******************************************************************************
00142  * SWModule::Description - Sets/gets module description
00143  *
00144  * ENT: imoddesc - value which to set moddesc
00145  *              [0] - only get
00146  *
00147  * RET: pointer to moddesc
00148  */
00149 
00150 char *SWModule::Description(const char *imoddesc)
00151 {
00152         return stdstr(&moddesc, imoddesc);
00153 }
00154 
00155 
00156 /******************************************************************************
00157  * SWModule::Type - Sets/gets module type
00158  *
00159  * ENT: imodtype - value which to set modtype
00160  *              [0] - only get
00161  *
00162  * RET: pointer to modtype
00163  */
00164 
00165 char *SWModule::Type(const char *imodtype)
00166 {
00167         return stdstr(&modtype, imodtype);
00168 }
00169 
00170 /******************************************************************************
00171  * SWModule::Direction - Sets/gets module direction
00172  *
00173  * ENT: newdir - value which to set direction
00174  *              [-1] - only get
00175  *
00176  * RET: char direction
00177  */
00178 char SWModule::Direction(signed char newdir) {
00179         if (newdir != -1)
00180                 direction = newdir;
00181         return direction;
00182 }
00183 
00184 /******************************************************************************
00185  * SWModule::Encoding - Sets/gets module encoding
00186  *
00187  * ENT: newdir - value which to set direction
00188  *              [-1] - only get
00189  *
00190  * RET: char encoding
00191  */
00192 char SWModule::Encoding(signed char newenc) {
00193         if (newenc != -1)
00194                 encoding = newenc;
00195         return encoding;
00196 }
00197 
00198 /******************************************************************************
00199  * SWModule::Markup - Sets/gets module markup
00200  *
00201  * ENT: newdir - value which to set direction
00202  *              [-1] - only get
00203  *
00204  * RET: char markup
00205  */
00206 char SWModule::Markup(signed char newmark) {
00207         if (newmark != -1)
00208                 markup = newmark;
00209         return markup;
00210 }
00211 
00212 
00213 /******************************************************************************
00214  * SWModule::Lang - Sets/gets module language
00215  *
00216  * ENT: imodlang - value which to set modlang
00217  *              [0] - only get
00218  *
00219  * RET: pointer to modname
00220  */
00221 
00222 char *SWModule::Lang(const char *imodlang)
00223 {
00224         return stdstr(&modlang, imodlang);
00225 }
00226 
00227 
00228 /******************************************************************************
00229  * SWModule::Disp - Sets/gets display driver
00230  *
00231  * ENT: idisp - value which to set disp
00232  *              [0] - only get
00233  *
00234  * RET: pointer to disp
00235  */
00236 
00237 SWDisplay *SWModule::Disp(SWDisplay *idisp)
00238 {
00239         if (idisp)
00240                 disp = idisp;
00241 
00242         return disp;
00243 }
00244 
00245 
00246 /******************************************************************************
00247  * SWModule::Display - Calls this modules display object and passes itself
00248  *
00249  * RET: error status
00250  */
00251 
00252 char SWModule::Display()
00253 {
00254         disp->Display(*this);
00255         return 0;
00256 }
00257 
00258 
00259 /******************************************************************************
00260  * SWModule::SetKey - Sets a key to this module for position to a particular
00261  *                      record or set of records
00262  *
00263  * ENT: ikey - key with which to set this module
00264  *
00265  * RET: error status
00266  */
00267 
00268 char SWModule::SetKey(const SWKey &ikey) {
00269         return SetKey(&ikey);
00270 }
00271 
00272 char SWModule::SetKey(const SWKey *ikey)
00273 {
00274         SWKey *oldKey = 0;
00275 
00276         if (key) {
00277                 if (!key->Persist())    // if we have our own copy
00278                         oldKey = key;
00279         }
00280 
00281         if (!ikey->Persist()) {         // if we are to keep our own copy
00282                  key = CreateKey();
00283                 *key = *ikey;
00284         }
00285         else     key = (SWKey *)ikey;           // if we are to just point to an external key
00286 
00287         if (oldKey)
00288                 delete oldKey;
00289 
00290         return 0;
00291 }
00292 
00293 
00294 /******************************************************************************
00295  * SWModule::KeyText - Sets/gets module KeyText
00296  *
00297  * ENT: ikeytext - value which to set keytext
00298  *              [0] - only get
00299  *
00300  * RET: pointer to keytext
00301  */
00302 
00303 const char *SWModule::KeyText(const char *ikeytext)
00304 {
00305         if (ikeytext)
00306                 SetKey(ikeytext);
00307 
00308         return *key;
00309 }
00310 
00311 
00312 /******************************************************************************
00313  * SWModule::operator =(SW_POSITION)    - Positions this modules to an entry
00314  *
00315  * ENT: p       - position (e.g. TOP, BOTTOM)
00316  *
00317  * RET: *this
00318  */
00319 
00320 SWModule &SWModule::operator =(SW_POSITION p)
00321 {
00322         *key = p;
00323         char saveError = key->Error();
00324 
00325         switch (p) {
00326         case POS_TOP:
00327                 (*this)++;
00328                 (*this)--;
00329                 break;
00330 
00331         case POS_BOTTOM:
00332                 (*this)--;
00333                 (*this)++;
00334                 break;
00335         }
00336 
00337         error = saveError;
00338         return *this;
00339 }
00340 
00341 
00342 /******************************************************************************
00343  * SWModule::operator +=        - Increments module key a number of entries
00344  *
00345  * ENT: increment       - Number of entries to jump forward
00346  *
00347  * RET: *this
00348  */
00349 
00350 SWModule &SWModule::operator +=(int increment)
00351 {
00352         (*key) += increment;
00353         error = key->Error();
00354 
00355         return *this;
00356 }
00357 
00358 
00359 /******************************************************************************
00360  * SWModule::operator -=        - Decrements module key a number of entries
00361  *
00362  * ENT: decrement       - Number of entries to jump backward
00363  *
00364  * RET: *this
00365  */
00366 
00367 SWModule &SWModule::operator -=(int increment)
00368 {
00369         (*key) -= increment;
00370         error = key->Error();
00371 
00372         return *this;
00373 }
00374 
00375 
00376 /******************************************************************************
00377  * SWModule::Search     - Searches a module for a string
00378  *
00379  * ENT: istr            - string for which to search
00380  *      searchType      - type of search to perform
00381  *                              >=0 - regex
00382  *                              -1  - phrase
00383  *                              -2  - multiword
00384  *      flags           - options flags for search
00385  *      justCheckIfSupported    - if set, don't search, only tell if this
00386  *                                                      function supports requested search.
00387  *
00388  * RET: listkey set to verses that contain istr
00389  */
00390 
00391 ListKey &SWModule::Search(const char *istr, int searchType, int flags, SWKey *scope, bool *justCheckIfSupported, void (*percent)(char, void *), void *percentUserData)
00392 {
00393         SWKey *savekey = 0;
00394         SWKey *searchkey = 0;
00395         regex_t preg;
00396         SWKey textkey;
00397         char **words = 0;
00398         char *wordBuf = 0;
00399         int wordCount = 0;
00400         const char *sres;
00401         terminateSearch = false;
00402         char perc = 1;
00403         bool savePEA = isProcessEntryAttributes();
00404 
00405         processEntryAttributes(false);
00406         listkey.ClearList();
00407 
00408         if (!key->Persist()) {
00409                 savekey = CreateKey();
00410                 *savekey = *key;
00411         }
00412         else    savekey = key;
00413 
00414         searchkey = (scope)?scope->clone():(key->Persist())?key->clone():0;
00415         if (searchkey) {
00416                 searchkey->Persist(1);
00417                 SetKey(*searchkey);
00418         }
00419 
00420         (*percent)(perc, percentUserData);
00421         // MAJOR KLUDGE: VerseKey::Index still return index within testament.
00422         //      VerseKey::NewIndex should be moved to Index and Index should be some
00423         //      VerseKey specific name
00424         VerseKey *vkcheck = 0;
00425 #ifndef _WIN32_WCE
00426         try {
00427 #endif
00428                 vkcheck = SWDYNAMIC_CAST(VerseKey, key);
00429 #ifndef _WIN32_WCE
00430         }
00431         catch (...) {}
00432 #endif
00433         // end MAJOR KLUDGE
00434 
00435         *this = BOTTOM;
00436         // fix below when we find out the bug
00437         long highIndex = (vkcheck)?32300/*vkcheck->NewIndex()*/:key->Index();
00438         if (!highIndex)
00439                 highIndex = 1;          // avoid division by zero errors.
00440         *this = TOP;
00441         if (searchType >= 0) {
00442                 flags |=searchType|REG_NOSUB|REG_EXTENDED;
00443                 regcomp(&preg, istr, flags);
00444         }
00445 
00446         (*percent)(++perc, percentUserData);
00447         if (searchType == -2) {
00448                 wordBuf = (char *)calloc(sizeof(char), strlen(istr) + 1);
00449                 strcpy(wordBuf, istr);
00450                 words = (char **)calloc(sizeof(char *), 10);
00451                 int allocWords = 10;
00452                 words[wordCount] = strtok(wordBuf, " ");
00453                 while (words[wordCount]) {
00454                         wordCount++;
00455                         if (wordCount == allocWords) {
00456                                 allocWords+=10;
00457                                 words = (char **)realloc(words, sizeof(char *)*allocWords);
00458                         }
00459                         words[wordCount] = strtok(NULL, " ");
00460                 }
00461         }
00462 
00463         perc = 5;
00464         (*percent)(perc, percentUserData);
00465 
00466         while (!Error() && !terminateSearch) {
00467 
00468         
00469                 long mindex = 0;
00470                 if (vkcheck)
00471                         mindex = vkcheck->NewIndex();
00472                 else mindex = key->Index();
00473                 float per = (float)mindex / highIndex;
00474                 per *= 93;
00475                 per += 5;
00476                 char newperc = (char)per;
00477 //              char newperc = (char)(5+(93*(((float)((vkcheck)?vkcheck->NewIndex():key->Index()))/highIndex)));
00478                 if (newperc > perc) {
00479                         perc = newperc;
00480                         (*percent)(perc, percentUserData);
00481                 }
00482                 else if (newperc < perc) {
00483 #ifndef _MSC_VER
00484                         cerr << "Serious error: new percentage complete is less than previous value\n";
00485                         cerr << "using vk? " << ((vkcheck)?"yes":"no") << "\n";
00486                         cerr << "index: " << ((vkcheck)?vkcheck->NewIndex():key->Index()) << "\n";
00487                         cerr << "highIndex: " << highIndex << "\n";
00488                         cerr << "newperc ==" << (int)newperc << "%" << "is smaller than\n";
00489                         cerr << "perc == "  << (int )perc << "% \n";
00490 #endif
00491                 }
00492                 if (searchType >= 0) {
00493                         if (!regexec(&preg,  StripText(), 0, 0, 0)) {
00494                                 textkey = KeyText();
00495                                 listkey << textkey;
00496                         }
00497                 }
00498                 else {
00499                         if (searchType == -1) {
00500                                 sres = ((flags & REG_ICASE) == REG_ICASE) ? stristr(StripText(), istr) : strstr(StripText(), istr);
00501                                 if (sres) {
00502                                                 textkey = KeyText();
00503                                                 listkey << textkey;
00504                                 }
00505                         }
00506                         if (searchType == -2) {
00507                                 int i;
00508                                 const char *stripBuf = StripText();
00509                                 for (i = 0; i < wordCount; i++) {
00510                                         sres = ((flags & REG_ICASE) == REG_ICASE) ? stristr(stripBuf, words[i]) : strstr(stripBuf, words[i]);
00511                                         if (!sres)
00512                                                 break;
00513                                 }
00514                                 if (i == wordCount) {
00515                                         textkey = KeyText();
00516                                         listkey << textkey;
00517                                 }
00518 
00519                         }
00520                 }
00521                 (*this)++;
00522         }
00523         if (searchType >= 0)
00524                 regfree(&preg);
00525 
00526         if (searchType == -2) {
00527                 free(words);
00528                 free(wordBuf);
00529         }
00530 
00531         SetKey(*savekey);
00532 
00533         if (!savekey->Persist())
00534                 delete savekey;
00535 
00536         if (searchkey)
00537                 delete searchkey;
00538 
00539         listkey = TOP;
00540         processEntryAttributes(savePEA);
00541         (*percent)(100, percentUserData);
00542 
00543         return listkey;
00544 }
00545 
00546 
00547 /******************************************************************************
00548  * SWModule::StripText()        - calls all stripfilters on current text
00549  *
00550  * ENT: buf     - buf to massage instead of this modules current text
00551  *      len     - max len of buf
00552  *
00553  * RET: this module's text at specified key location massaged by Strip filters
00554  */
00555 
00556 const char *SWModule::StripText(char *buf, int len)
00557 {
00558         return RenderText(buf, len, false);
00559 }
00560 
00561 
00562 /******************************************************************************
00563  * SWModule::RenderText         - calls all renderfilters on current text
00564  *
00565  * ENT: buf     - buffer to Render instead of current module position
00566  *
00567  * RET: listkey set to verses that contain istr
00568  */
00569 
00570  const char *SWModule::RenderText(char *buf, int len, bool render) {
00571         entryAttributes.clear();
00572         char *tmpbuf = (buf) ? buf : getRawEntry();
00573         SWKey *key = 0;
00574         static char *null = "";
00575 
00576         if (tmpbuf) {
00577                 unsigned long size = (len < 0) ? ((getEntrySize()<0) ? strlen(tmpbuf) : getEntrySize()) * FILTERPAD : len;
00578                 if (size > 0) {
00579                         key = (SWKey *)*this;
00580 
00581                         optionFilter(tmpbuf, size, key);
00582         
00583                         if (render) {
00584                                 renderFilter(tmpbuf, size, key);
00585                                 encodingFilter(tmpbuf, size, key);
00586                         }
00587                         else    stripFilter(tmpbuf, size, key);
00588                 }
00589         }
00590         else {
00591                 tmpbuf = null;
00592         }
00593 
00594         return tmpbuf;
00595 }
00596 
00597 
00598 /******************************************************************************
00599  * SWModule::RenderText         - calls all renderfilters on current text
00600  *
00601  * ENT: tmpKey  - key to use to grab text
00602  *
00603  * RET: this module's text at specified key location massaged by RenderFilers
00604  */
00605 
00606  const char *SWModule::RenderText(SWKey *tmpKey)
00607 {
00608         SWKey *savekey;
00609         const char *retVal;
00610 
00611         if (!key->Persist()) {
00612                 savekey = CreateKey();
00613                 *savekey = *key;
00614         }
00615         else    savekey = key;
00616 
00617         SetKey(*tmpKey);
00618 
00619         retVal = RenderText();
00620 
00621         SetKey(*savekey);
00622 
00623         if (!savekey->Persist())
00624                 delete savekey;
00625 
00626         return retVal;
00627 }
00628 
00629 
00630 /******************************************************************************
00631  * SWModule::StripText  - calls all StripTextFilters on current text
00632  *
00633  * ENT: tmpKey  - key to use to grab text
00634  *
00635  * RET: this module's text at specified key location massaged by Strip filters
00636  */
00637 
00638 const char *SWModule::StripText(SWKey *tmpKey)
00639 {
00640         SWKey *savekey;
00641         const char *retVal;
00642 
00643         if (!key->Persist()) {
00644                 savekey = CreateKey();
00645                 *savekey = *key;
00646         }
00647         else    savekey = key;
00648 
00649         SetKey(*tmpKey);
00650 
00651         retVal = StripText();
00652 
00653         SetKey(*savekey);
00654 
00655         if (!savekey->Persist())
00656                 delete savekey;
00657 
00658         return retVal;
00659 }
00660 
00661 
00662 SWModule::operator const char*() {
00663         return RenderText();
00664 }
00665 
00666 
00667 const char *SWModule::getConfigEntry(const char *key) const {
00668         ConfigEntMap::iterator it = config->find(key);
00669         return (it != config->end()) ? it->second.c_str() : 0;
00670 }
00671 
00672 
00673 void SWModule::setConfig(ConfigEntMap *config) {
00674         this->config = config;
00675 }

Generated on Thu Jun 20 22:13:00 2002 for The Sword Project by doxygen1.2.15