00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifdef WIN32
00010 #pragma warning(disable : 4786 )
00011 #endif
00012
00013 #include "CSHTMLElement.h"
00014 #include "CSFont.h"
00015 #include "CSDesktop.h"
00016 #include "CSWindow.h"
00017 #include "CSLAF.h"
00018 #include "CSScrollbar.h"
00019 #include "CSHelper.h"
00020
00021 const char *HTMLElement::CLASS = "HTMLElement";
00022
00023 HTMLElement::HTMLElement(CSHTMLNode node)
00024 {
00025 mNode = node;
00026 mParent = 0;
00027 mPositionsStored = false;
00028 CSHTMLNode child = mNode.firstChild();
00029 while (!child.isEmpty())
00030 {
00031 HTMLElement * nextChild = new HTMLElement(child);
00032 nextChild->setParent(this);
00033 mElements.push_back(nextChild);
00034 child = mNode.nextChild();
00035 }
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 }
00046
00047 HTMLElement::~HTMLElement()
00048 {
00049 clearPosition();
00050 clearCompiled();
00051 HTMLElements::iterator iter = mElements.begin();
00052 while (iter != mElements.end())
00053 {
00054 HTMLElement *element = *iter;
00055 mElements.erase(iter);
00056 delete element;
00057 iter = mElements.begin();
00058 }
00059 }
00060
00061 void HTMLElement::clearPosition()
00062 {
00063 HTMLElements::iterator eiter;
00064 for (eiter = mElements.begin(); eiter != mElements.end(); eiter++)
00065 {
00066 HTMLElement *element = *eiter;
00067 element->clearPosition();
00068 }
00069
00070 Positions::iterator iter = mPositions.begin();
00071 while (iter != mPositions.end())
00072 {
00073 SDL_Rect *rect = *iter;
00074 mPositions.erase(iter);
00075 delete (rect);
00076 iter = mPositions.begin();
00077 }
00078 mPositionsStored = false;
00079 }
00080
00081 void HTMLElement::clearCompiled()
00082 {
00083 }
00084
00085 HTMLElement *HTMLElement::getAncestorType(int type)
00086 {
00087 HTMLElement *parent = getParent();
00088 while (parent)
00089 {
00090 if (parent->getTagType() == type)
00091 {
00092 return parent;
00093 }
00094 parent = parent->getParent();
00095 }
00096 return 0;
00097 }
00098
00099 int HTMLElement::getTagType()
00100 {
00101 return getTagType(mNode);
00102 }
00103
00104
00105
00106
00107 HTMLTagMap *HTMLElement::mHTMLTagMap = 0;
00108
00109 int HTMLElement::getTagType(CSHTMLNode &node)
00110 {
00111 if (mHTMLTagMap == 0)
00112 {
00113 mHTMLTagMap = new HTMLTagMap();
00114 mHTMLTagMap->insert(HTMLTagMap::value_type("HTML", HTML_HTML));
00115 mHTMLTagMap->insert(HTMLTagMap::value_type("HEAD", HTML_HEAD));
00116 mHTMLTagMap->insert(HTMLTagMap::value_type("TITLE", HTML_TITLE));
00117 mHTMLTagMap->insert(HTMLTagMap::value_type("BODY", HTML_BODY));
00118 mHTMLTagMap->insert(HTMLTagMap::value_type("H1", HTML_H1));
00119 mHTMLTagMap->insert(HTMLTagMap::value_type("H2", HTML_H2));
00120 mHTMLTagMap->insert(HTMLTagMap::value_type("H3", HTML_H3));
00121 mHTMLTagMap->insert(HTMLTagMap::value_type("H4", HTML_H4));
00122 mHTMLTagMap->insert(HTMLTagMap::value_type("H5", HTML_H5));
00123 mHTMLTagMap->insert(HTMLTagMap::value_type("P", HTML_P));
00124 mHTMLTagMap->insert(HTMLTagMap::value_type("BR", HTML_BR));
00125 mHTMLTagMap->insert(HTMLTagMap::value_type("HL", HTML_HL));
00126 mHTMLTagMap->insert(HTMLTagMap::value_type("PRE", HTML_PRE));
00127 mHTMLTagMap->insert(HTMLTagMap::value_type("IMG", HTML_IMG));
00128 mHTMLTagMap->insert(HTMLTagMap::value_type("A", HTML_A));
00129 mHTMLTagMap->insert(HTMLTagMap::value_type("B", HTML_B));
00130 mHTMLTagMap->insert(HTMLTagMap::value_type("I", HTML_I));
00131 mHTMLTagMap->insert(HTMLTagMap::value_type("DD", HTML_DD));
00132 mHTMLTagMap->insert(HTMLTagMap::value_type("DL", HTML_DL));
00133 mHTMLTagMap->insert(HTMLTagMap::value_type("DT", HTML_DT));
00134 mHTMLTagMap->insert(HTMLTagMap::value_type("UL", HTML_UL));
00135 mHTMLTagMap->insert(HTMLTagMap::value_type("OL", HTML_OL));
00136
00137 mHTMLTagMap->insert(HTMLTagMap::value_type("TABLE", HTML_TABLE));
00138 mHTMLTagMap->insert(HTMLTagMap::value_type("TR", HTML_TR));
00139 mHTMLTagMap->insert(HTMLTagMap::value_type("TH", HTML_TH));
00140 mHTMLTagMap->insert(HTMLTagMap::value_type("TT", HTML_TT));
00141 }
00142 std::string tag = node.getTag();
00143 if (tag.size() != 0)
00144 {
00145 HTMLTagMap::iterator iter = mHTMLTagMap->find(tag);
00146 if (iter != mHTMLTagMap->end())
00147 {
00148 return iter->second;
00149 }
00150 }
00151 return 0;
00152 }
00153
00154
00155
00156
00157 StringVector *HTMLElement::tokenifyText(const std::string &text)
00158 {
00159 StringVector *tokens = new StringVector();
00160 char *copy = strdup(text.c_str());
00161 char *tmp = copy;
00162
00163 char *pointerToWord = strtok( copy, " \n\t");
00164 while (pointerToWord != 0)
00165 {
00166 tokens->push_back(strdup(pointerToWord));
00167 pointerToWord = strtok( 0, " \n\t");
00168 }
00169 free(tmp);
00170 return tokens;
00171 }
00172
00173
00174
00175 std::string HTMLElement::getChildrenAsText()
00176 {
00177 std::string text="";
00178 HTMLElements::iterator iter;
00179 for (iter = mElements.begin(); iter != mElements.end(); iter++)
00180 {
00181 HTMLElement *element = *iter;
00182 if (element->mNode.isText())
00183 {
00184 text = text + element->mNode.getValue();
00185 }
00186 text = text + element->getChildrenAsText();
00187 }
00188 return text;
00189 }
00190
00191
00192
00193
00194
00195 HTMLElement *HTMLElement::getChildType(int type, std::string attributeName, std::string attributeValue)
00196 {
00197 HTMLElements::iterator iter;
00198 for (iter = mElements.begin(); iter != mElements.end(); iter++)
00199 {
00200 HTMLElement *element = *iter;
00201 if (element->getTagType() == type)
00202 {
00203 if ((attributeName.size() == 0) || (attributeValue.size == 0))
00204 {
00205 return element;
00206 }
00207 std::string elementAttributeValue = element->getAttributValue(attributeName);
00208 if (elementAttributeValue.compare(attributeValue) == 0)
00209 {
00210 return element;
00211 }
00212 }
00213 HTMLElement *childResult = element->getChildType(type, attributeName, attributeValue);
00214 if (childResult)
00215 {
00216 return childResult;
00217 }
00218 }
00219 return 0;
00220 }
00221
00222
00223 std::string HTMLElement::formatURL(const std::string &rawURL)
00224 {
00225 return rawURL;
00226 }
00227
00228
00229 std::string HTMLElement::getAttributValue(std::string attributeName)
00230 {
00231 return mNode.attributValue(attributeName);
00232 }
00233
00234
00235
00236 int HTMLElement::getColorFromString(std::string acolor)
00237 {
00238 if (acolor.size()<= 0)
00239 {
00240 return -1;
00241 }
00242 int posStart = strstr(acolor.c_str(), "#") - acolor.c_str()+1;
00243 std::string v = acolor.substr(posStart, acolor.size()-posStart);
00244 int value = CSHelper::convert(v.c_str(), 16);
00245 return value;
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257 HTMLCursor HTMLElement::buildDisplay(HTMLCursor cursor, CSGrafikElement *destination, int parentViewportWidth, std::string &title)
00258 {
00259 bool goDeeper = true;
00260 std::string text = "";
00261 std::string tag = mNode.getTag();
00262 HTMLCursor returnCursor = cursor;
00263
00264
00265
00266
00267 switch (getTagType(mNode))
00268 {
00269 case HTML_PRE:
00270 {
00271 CSLAF *laf = CSLAF::getCurrentLAF();
00272 cursor.mInPre = true;
00273
00274
00275 cursor.mXPos = 0;
00276 cursor.mXPos += cursor.mAddX;
00277 cursor.mYPos += cursor.nextAdd;
00278 cursor.nextAdd = cursor.mFont->getHeight();
00279 cursor.mFont = laf->getFont("MonoSpaced");
00280 break;
00281 }
00282 case HTML_HTML:
00283 {
00284 break;
00285 }
00286 case HTML_BODY:
00287 {
00288
00289 std::string bgColor = mNode.attributValue("BGCOLOR");
00290 std::string textColor = mNode.attributValue("TEXT");
00291 std::string linkColor = mNode.attributValue("LINK");
00292
00293 int t = getColorFromString(textColor);
00294 if (t != -1) cursor.mPenColor = t;
00295
00296 t = getColorFromString(bgColor);
00297 if (t != -1) cursor.mBackgroundColor = t;
00298
00299 t = getColorFromString(linkColor);
00300 if (t != -1) cursor.mLinkColor = t;
00301
00302
00303 cursor.mInBody = true;
00304 break;
00305 }
00306 case HTML_TITLE:
00307 {
00308
00309 title = getChildrenAsText();
00310 goDeeper = false;
00311 break;
00312 }
00313 case HTML_LI:
00314 {
00315
00316
00317
00318
00319
00320
00321 if (cursor.mListCounter != -1)
00322 {
00323
00324 char helper[10];
00325 cursor.mListCounter++;
00326 sprintf(helper, "%i. ", cursor.mListCounter);
00327 text = std::string(helper);
00328 }
00329 else
00330 {
00331
00332 text = std::string("* ");
00333 }
00334 }
00335 case HTML_DT:
00336 {
00337 cursor.mXPos = 0;
00338 cursor.mYPos += cursor.nextAdd;
00339 cursor.nextAdd = cursor.mFont->getHeight();
00340 cursor.mXPos += cursor.mAddX;
00341 break;
00342 }
00343 case HTML_OL:
00344 {
00345
00346 cursor.mListCounter = 0;
00347 }
00348 case HTML_UL:
00349 case HTML_DD:
00350 {
00351
00352 cursor.mAddX += 3*cursor.mFont->getWidth(" ");
00353 break;
00354 }
00355
00356
00357 case HTML_BR:
00358
00359 case HTML_H1:
00360 {
00361 cursor.mXPos = 0;
00362 cursor.mXPos += cursor.mAddX;
00363 cursor.mYPos += cursor.nextAdd;
00364 cursor.nextAdd = cursor.mFont->getHeight();
00365 break;
00366 }
00367
00368
00369
00370 case HTML_P:
00371 {
00372 cursor.mXPos = 0;
00373 cursor.mXPos += cursor.mAddX;
00374 cursor.mYPos += cursor.nextAdd;
00375 cursor.nextAdd = cursor.mFont->getHeight();
00376 cursor.mYPos += cursor.nextAdd;
00377 break;
00378 }
00379 case HTML_A:
00380 {
00381
00382
00383
00384
00385 if (mNode.attributValue("HREF").size() != 0 )
00386 {
00387 cursor.mStyle = cursor.mStyle | FONT_STYLE_UNDERLINE;
00388 cursor.mPenColor = cursor.mLinkColor;
00389 }
00390
00391
00392 mX = cursor.mXPos;
00393 mY = cursor.mYPos;
00394 break;
00395 }
00396 case HTML_B:
00397 {
00398 cursor.mStyle = cursor.mStyle | FONT_STYLE_BOLD;
00399 break;
00400 }
00401 case HTML_I:
00402 {
00403
00404 cursor.mStyle = cursor.mStyle | FONT_STYLE_ITALIC;
00405 break;
00406 }
00407 case HTML_IMG:
00408 {
00409
00410 cursor.mXPos = 0;
00411 cursor.mXPos += cursor.mAddX;
00412 std::string rawURL = mNode.attributValue("SRC");
00413 std::string formattedURL = formatURL(rawURL);
00414
00415
00416
00417
00418
00419 int x = cursor.mXPos;
00420 int y = cursor.mYPos;
00421
00422 CSIcon *icon = CSPictureIcon::buildIcon(CSPictureDirectLoader::INSTANCE.load(formattedURL));
00423 if (icon == 0)
00424 {
00425 text = std::string()+"[Image not found: "+formattedURL+"]";
00426 icon = CSTextIcon::buildIcon(text);
00427 }
00428 if (icon != 0)
00429 {
00430 cursor.mXPos += icon->getWidth();
00431 cursor.nextAdd = icon->getHeight();
00432 if (cursor.mXPos > cursor.mXPosMax)
00433 {
00434 cursor.mXPosMax = cursor.mXPos;
00435 }
00436
00437 if (destination)
00438 {
00439 destination->addElement(icon, x, y);
00440 }
00441 else
00442 {
00443 delete icon;
00444 }
00445 }
00446 }
00447 }
00448
00449
00450 if (mNode.isText())
00451 {
00452 text = mNode.getValue();
00453 }
00454
00455
00456
00457
00458
00459 if (cursor.mInBody == true)
00460 {
00461 if (text.size() != 0)
00462 {
00463
00464
00465
00466 if (cursor.mInPre)
00467 {
00468 std::string textOut = "";
00469 for (const char *pointerToText = text.c_str(); (*pointerToText);pointerToText++)
00470 {
00471 if (*pointerToText != '\n')
00472 {
00473 char letter[2];
00474 letter[0] = *pointerToText;
00475 letter[1] = 0;
00476 textOut += letter;
00477 }
00478 else
00479 {
00480
00481 if (destination)
00482 {
00483 int x = cursor.mXPos;
00484 int y = cursor.mYPos;
00485
00486 CSLabel *label = new CSLabel();
00487 label->setFont(cursor.mFont);
00488 label->setStyle(cursor.mStyle);
00489 label->setTextColor(cursor.mPenColor);
00490 label->setText(textOut);
00491 destination->addElement(label, x, y);
00492 }
00493
00494 if (!mPositionsStored)
00495 {
00496 addPostion(cursor.mXPos, cursor.mYPos, cursor.mFont->getWidth(textOut), cursor.mFont->getHeight());
00497 }
00498 cursor.mXPos += cursor.mFont->getWidth(textOut);
00499 textOut = "";
00500 if (cursor.mXPos > cursor.mXPosMax)
00501 {
00502 cursor.mXPosMax = cursor.mXPos;
00503 }
00504
00505 cursor.mXPos = 0;
00506 cursor.mXPos += cursor.mAddX;
00507 cursor.mYPos += cursor.nextAdd;
00508 cursor.nextAdd = cursor.mFont->getHeight();
00509 }
00510 }
00511
00512
00513
00514 if (textOut.size() > 0)
00515 {
00516 if (destination)
00517 {
00518 int x = cursor.mXPos;
00519 int y = cursor.mYPos;
00520 CSLabel *label = new CSLabel();
00521 label->setFont(cursor.mFont);
00522 label->setStyle(cursor.mStyle);
00523 label->setTextColor(cursor.mPenColor);
00524 label->setText(textOut);
00525 destination->addElement(label, x, y);
00526 }
00527 if (!mPositionsStored)
00528 {
00529 addPostion(cursor.mXPos, cursor.mYPos, cursor.mFont->getWidth(textOut), cursor.mFont->getHeight());
00530 }
00531 cursor.mXPos += cursor.mFont->getWidth(textOut);
00532 textOut = "";
00533 if (cursor.mXPos > cursor.mXPosMax)
00534 {
00535 cursor.mXPosMax = cursor.mXPos;
00536 }
00537 }
00538 }
00539 else
00540 {
00541
00542
00543
00544 StringVector::iterator iter;
00545 StringVector *tokens = tokenifyText(text);
00546 int width = 0;
00547
00548 std::string line="";
00549
00550
00551 for (iter = tokens->begin(); iter != tokens->end();)
00552 {
00553 char *word = *iter;
00554
00555 width = cursor.mFont->getWidth(line+" "+word);
00556
00557 if (cursor.mXPos + width < parentViewportWidth)
00558 {
00559 if (line.size()>0)
00560 {
00561 line = line +" "+ word;
00562 }
00563 else
00564 {
00565 line = line + word;
00566 }
00567 }
00568 else
00569 {
00570
00571
00572 if (destination)
00573 {
00574 int x = cursor.mXPos;
00575 int y = cursor.mYPos;
00576 CSLabel *label = new CSLabel();
00577 label->setFont(cursor.mFont);
00578 label->setStyle(cursor.mStyle);
00579 label->setTextColor(cursor.mPenColor);
00580 label->setText(line);
00581 destination->addElement(label, x, y);
00582 }
00583 if (!mPositionsStored)
00584 {
00585 addPostion(cursor.mXPos, cursor.mYPos, cursor.mFont->getWidth(line), cursor.mFont->getHeight());
00586 }
00587 cursor.mXPos += cursor.mFont->getWidth(line);
00588 if (cursor.mXPos > cursor.mXPosMax)
00589 {
00590 cursor.mXPosMax = cursor.mXPos;
00591 }
00592 cursor.mXPos = 0;
00593 cursor.mXPos += cursor.mAddX;
00594 cursor.mYPos += cursor.nextAdd;
00595 cursor.nextAdd = cursor.mFont->getHeight();
00596 line = word;
00597 }
00598 iter++;
00599 }
00600
00601
00602
00603 if (destination)
00604 {
00605 int x = cursor.mXPos;
00606 int y = cursor.mYPos;
00607 CSLabel *label = new CSLabel();
00608 label->setFont(cursor.mFont);
00609 label->setStyle(cursor.mStyle);
00610 label->setTextColor(cursor.mPenColor);
00611 label->setText(line);
00612 destination->addElement(label, x, y);
00613 }
00614 if (!mPositionsStored)
00615 {
00616 addPostion(cursor.mXPos, cursor.mYPos, cursor.mFont->getWidth(line), cursor.mFont->getHeight());
00617 }
00618 if (line.size()>0)
00619 {
00620 line = line + " ";
00621 }
00622 cursor.mXPos += cursor.mFont->getWidth(line);
00623 if (cursor.mXPos > cursor.mXPosMax)
00624 {
00625 cursor.mXPosMax = cursor.mXPos;
00626 }
00627
00628 for (iter = tokens->begin(); iter != tokens->end();iter++)
00629 {
00630 char *word = *iter;
00631 free(word);
00632 }
00633 tokens->clear();
00634 delete (tokens);
00635 tokens = 0;
00636 }
00637 }
00638 }
00639
00640
00641
00642 if (goDeeper == true)
00643 {
00644 HTMLElements::iterator iter;
00645 for (iter = mElements.begin(); iter != mElements.end(); iter++)
00646 {
00647 HTMLElement *element = *iter;
00648 cursor = element->buildDisplay(cursor, destination, parentViewportWidth, title);
00649 }
00650 }
00651
00652
00653
00654 returnCursor.mYPos = cursor.mYPos;
00655 returnCursor.mXPos = cursor.mXPos;
00656 returnCursor.nextAdd = cursor.nextAdd;
00657 returnCursor.mXPosMax = cursor.mXPosMax;
00658
00659
00660
00661 returnCursor.mListCounter = cursor.mListCounter;
00662 mPositionsStored = true;
00663
00664 return returnCursor;
00665 }
00666
00667
00668 void HTMLElement::addPostion(int x, int y, int w, int h)
00669 {
00670 SDL_Rect *rect = new SDL_Rect();
00671 rect->x = x;
00672 rect->y = y;
00673 rect->w = w;
00674 rect->h = h;
00675 mPositions.push_back(rect);
00676 }
00677
00678
00679
00680
00681
00682 HTMLElement *HTMLElement::checkPostion(int x, int y)
00683 {
00684 Positions::iterator iter = mPositions.begin();
00685 while (iter != mPositions.end())
00686 {
00687 SDL_Rect *rect = *iter;
00688 if (((x > rect->x) && (x < rect->x + rect->w)) && ((y > rect->y) && (y < rect->y + rect->h)))
00689 {
00690 return this;
00691 }
00692 iter++;
00693 }
00694 HTMLElements::iterator eiter;
00695 for (eiter = mElements.begin(); eiter != mElements.end(); eiter++)
00696 {
00697 HTMLElement *checked = (*eiter)->checkPostion(x, y);
00698 if (checked != 0)
00699 {
00700 return checked;
00701 }
00702 }
00703 return 0;
00704 }
00705
00706
00707
00708 int HTMLElement::getFirstYPostion()
00709 {
00710 return mY;
00711 }