MarkupTextBlock.cpp
Go to the documentation of this file.00001 //*** MarkupTextBlock.cpp *** 00002 00003 #include "MarkupTextBlock.h" 00004 #include "StandardLibrary.h" 00005 #include "Bitmap.h" 00006 #include "Font.h" 00007 #include "MarkupTextManager.h" 00008 00009 00010 //*** Constructor *** 00011 00012 MarkupTextBlock::MarkupTextBlock(): 00013 pmlString_(0), 00014 tokenBuffer_(0), 00015 currentTokenIsMarkupCode_(false), 00016 currentTokenPosition_(0), 00017 tokenStreamSize_(0) 00018 { 00019 } 00020 00021 00022 //*** Destructor *** 00023 00024 MarkupTextBlock::~MarkupTextBlock() 00025 { 00026 if (pmlString_) 00027 { 00028 Free(pmlString_); 00029 pmlString_=0; 00030 } 00031 00032 if (tokenBuffer_) 00033 { 00034 Free(tokenBuffer_); 00035 tokenBuffer_=0; 00036 } 00037 } 00038 00039 00040 //*** Copy Constructor *** 00041 00042 MarkupTextBlock::MarkupTextBlock(const MarkupTextBlock& textblock): 00043 pmlString_(0), 00044 tokenBuffer_(0), 00045 currentTokenIsMarkupCode_(false), 00046 currentTokenPosition_(0), 00047 tokenStreamSize_(0) 00048 { 00049 if (textblock.pmlString_) 00050 { 00051 SetString(textblock.pmlString_); 00052 } 00053 } 00054 00055 00056 //*** Assignment operator*** 00057 00058 const MarkupTextBlock& MarkupTextBlock::operator=(const MarkupTextBlock& textblock) 00059 { 00060 SetString(textblock.pmlString_); 00061 return *this; 00062 } 00063 00064 00065 //*** SetString *** 00066 00067 void MarkupTextBlock::SetString(const char* pmlString) 00068 { 00069 if (pmlString_) 00070 { 00071 Free(pmlString_); 00072 pmlString_=0; 00073 } 00074 00075 if (tokenBuffer_) 00076 { 00077 Free(tokenBuffer_); 00078 tokenBuffer_=0; 00079 } 00080 00081 if (pmlString) 00082 { 00083 pmlString_=StrDup(pmlString); 00084 tokenBuffer_=static_cast<char*>(Malloc(StrLen(pmlString_)+2)); 00085 tokenBuffer_[0]=0; 00086 } 00087 00088 ResetTokenStream(); 00089 } 00090 00091 00092 //*** AddString *** 00093 00094 void MarkupTextBlock::AddString(const char* pmlString) 00095 { 00096 if (!pmlString_) 00097 { 00098 if (tokenBuffer_) 00099 { 00100 Free(tokenBuffer_); 00101 tokenBuffer_=0; 00102 } 00103 00104 if (pmlString) 00105 { 00106 pmlString_=StrDup(pmlString); 00107 tokenBuffer_=static_cast<char*>(Malloc(StrLen(pmlString_)+2)); 00108 tokenBuffer_[0]=0; 00109 } 00110 ResetTokenStream(); 00111 return; 00112 } 00113 00114 if (pmlString) 00115 { 00116 if (tokenBuffer_) 00117 { 00118 Free(tokenBuffer_); 00119 tokenBuffer_=0; 00120 } 00121 00122 char* str=static_cast<char*>(Malloc(StrLen(pmlString)+StrLen(pmlString_)+1)); 00123 StrCpy(str,pmlString_); 00124 StrCat(str,pmlString); 00125 Free(pmlString_); 00126 pmlString_=str; 00127 tokenBuffer_=static_cast<char*>(Malloc(StrLen(pmlString_)+2)); 00128 tokenBuffer_[0]=0; 00129 } 00130 00131 ResetTokenStream(); 00132 } 00133 00134 00135 //*** GetString *** 00136 00137 const char* MarkupTextBlock::GetString() const 00138 { 00139 return pmlString_; 00140 } 00141 00142 00143 //*** ResetTokenStream *** 00144 00145 void MarkupTextBlock::ResetTokenStream() 00146 { 00147 currentTokenPosition_=0; 00148 currentTokenIsMarkupCode_=false; 00149 tokenStreamSize_=0; 00150 if (pmlString_) 00151 { 00152 tokenStreamSize_=StrLen(pmlString_); 00153 } 00154 } 00155 00156 00157 //*** GetNextToken *** 00158 00159 const char* MarkupTextBlock::GetNextToken() 00160 { 00161 currentTokenIsMarkupCode_=false; 00162 00163 // If we're past the end of the string, we're done 00164 if (currentTokenPosition_>=tokenStreamSize_) 00165 { 00166 return 0; 00167 } 00168 00169 // If there's whitespace, just skip forward 00170 while (pmlString_[currentTokenPosition_]<=32) 00171 { 00172 currentTokenPosition_++; 00173 if (currentTokenPosition_>=tokenStreamSize_) 00174 { 00175 return 0; 00176 } 00177 } 00178 00179 // If this is the start of a markup code, look for its end marker 00180 if (pmlString_[currentTokenPosition_]=='[') 00181 { 00182 int codeStart=currentTokenPosition_; 00183 while (currentTokenPosition_<tokenStreamSize_) 00184 { 00185 currentTokenPosition_++; 00186 char c=pmlString_[currentTokenPosition_]; 00187 if (c==']') 00188 { 00189 currentTokenPosition_++; 00190 currentTokenIsMarkupCode_=true; 00191 // Copy code to buffer 00192 StrNCpy(tokenBuffer_,&pmlString_[codeStart],currentTokenPosition_-codeStart); 00193 tokenBuffer_[currentTokenPosition_-codeStart]=0; 00194 return tokenBuffer_; 00195 } 00196 } 00197 00198 // No closing bracket, so treat this as a normal word 00199 currentTokenPosition_=codeStart; 00200 } 00201 00202 // If not a markup code, just get the next word 00203 int wordStart=currentTokenPosition_; 00204 while (currentTokenPosition_<tokenStreamSize_) 00205 { 00206 currentTokenPosition_++; 00207 char c=pmlString_[currentTokenPosition_]; 00208 if (c<=32 || c=='[' || c==']') 00209 { 00210 break; 00211 } 00212 } 00213 00214 // Copy word to buffer 00215 StrNCpy(tokenBuffer_,&pmlString_[wordStart],Min(currentTokenPosition_-wordStart,tokenStreamSize_)); 00216 tokenBuffer_[currentTokenPosition_-wordStart]=' '; // End each token with a space 00217 tokenBuffer_[currentTokenPosition_-wordStart+1]=0; 00218 return tokenBuffer_; 00219 } 00220 00221 00222 //*** Render *** 00223 00224 void MarkupTextBlock::Render(Bitmap& target, int x1, int y1, int x2, int y2, StringId hoverOption, StringId hoverLink) 00225 { 00226 if (!pmlString_) 00227 { 00228 return; 00229 } 00230 00231 links_.Clear(); 00232 options_.Clear(); 00233 00234 int extraVSpace=0; 00235 00236 Font* font=siMarkupTextManager->GetFont(MarkupTextManager::FontStyle_Normal); 00237 unsigned short color=siMarkupTextManager->GetFontColor(MarkupTextManager::FontStyle_Normal); 00238 unsigned short bgcolor=siMarkupTextManager->GetFontBgColor(MarkupTextManager::FontStyle_Normal); 00239 unsigned char opacity=siMarkupTextManager->GetFontBgOpacity(MarkupTextManager::FontStyle_Normal); 00240 bool isBold=false; 00241 bool isItalic=false; 00242 bool isLink=false; 00243 bool isOption=false; 00244 bool isDisabledOption=false; 00245 bool isHeadline=false; 00246 bool isStyle=false; 00247 00248 int xp=x1; 00249 int yp=y1; 00250 char idbuffer[256]; 00251 StringId idString; 00252 StringId styleId; 00253 char varbuffer[1024]; 00254 StringId varString; 00255 00256 ResetTokenStream(); 00257 const char* token=GetNextToken(); 00258 while (token) 00259 { 00260 // Write the next word 00261 if (!currentTokenIsMarkupCode_) 00262 { 00263 Font* fontStore=font; 00264 unsigned short colorStore=color; 00265 unsigned short bgcolorStore=bgcolor; 00266 unsigned char opacityStore=opacity; 00267 00268 if (isOption && idString==hoverOption) 00269 { 00270 font=siMarkupTextManager->GetFont(MarkupTextManager::FontStyle_OptionHover); 00271 color=siMarkupTextManager->GetFontColor(MarkupTextManager::FontStyle_OptionHover); 00272 bgcolor=siMarkupTextManager->GetFontBgColor(MarkupTextManager::FontStyle_OptionHover); 00273 opacity=siMarkupTextManager->GetFontBgOpacity(MarkupTextManager::FontStyle_OptionHover); 00274 } 00275 else if (isLink && idString==hoverLink) 00276 { 00277 font=siMarkupTextManager->GetFont(MarkupTextManager::FontStyle_LinkHover); 00278 color=siMarkupTextManager->GetFontColor(MarkupTextManager::FontStyle_LinkHover); 00279 bgcolor=siMarkupTextManager->GetFontBgColor(MarkupTextManager::FontStyle_LinkHover); 00280 opacity=siMarkupTextManager->GetFontBgOpacity(MarkupTextManager::FontStyle_LinkHover); 00281 } 00282 00283 Font::Bounds bounds=font->GetBounds(token,0); 00284 if (xp+bounds.width>x2) 00285 { 00286 xp=x1; 00287 yp+=bounds.height+extraVSpace; 00288 } 00289 00290 int yskip=font->GetGlyphHeight()-font->GetSize(); 00291 00292 if (isOption) 00293 { 00294 InteractiveRegion region; 00295 region.x1=xp; 00296 region.y1=yp+yskip; 00297 region.x2=xp+bounds.width; 00298 region.y2=yp+bounds.height; 00299 region.id=idString; 00300 options_.Add(region); 00301 } 00302 else if (isLink) 00303 { 00304 InteractiveRegion region; 00305 region.x1=xp; 00306 region.y1=yp+yskip; 00307 region.x2=xp+bounds.width; 00308 region.y2=yp+bounds.height; 00309 region.id=idString; 00310 links_.Add(region); 00311 } 00312 00313 if (opacity>0) 00314 { 00315 target.Fill(xp,yp+yskip,xp+bounds.width-1,yp+bounds.height-1,bgcolor,opacity); 00316 } 00317 00318 font->Blit(target,xp,yp,token,0,color); 00319 xp+=bounds.width; 00320 00321 font=fontStore; 00322 color=colorStore; 00323 bgcolor=bgcolorStore; 00324 opacity=opacityStore; 00325 } 00326 00327 // Apply markup codes 00328 if (currentTokenIsMarkupCode_) 00329 { 00330 // [br] line breaks 00331 if (StrICmp(token,"[br]")==0) 00332 { 00333 xp=x1; 00334 if (font) 00335 { 00336 Font::Bounds bounds=font->GetBounds(" ",0); 00337 yp+=bounds.height+extraVSpace; 00338 } 00339 else 00340 { 00341 yp+=10+extraVSpace; 00342 } 00343 } 00344 00345 // [var=...] horizontal spacing 00346 if (StrNICmp(token,"[var=",5)==0) 00347 { 00348 int l=Min(StrLen(token)-6,1023); 00349 StrNCpy(varbuffer,&token[5],l); 00350 varbuffer[l]=0; 00351 varString=varbuffer; 00352 siMarkupTextManager->GetVariableValue(varString,varbuffer,1024); 00353 currentTokenIsMarkupCode_=false; 00354 token=varbuffer; 00355 continue; 00356 } 00357 00358 // [hspace=...] horizontal spacing 00359 if (StrNICmp(token,"[hspace=",8)==0) 00360 { 00361 xp+=StringToInt(&token[8]); 00362 } 00363 00364 // [vspace=...] vertical spacing 00365 if (StrNICmp(token,"[vspace=",8)==0) 00366 { 00367 yp+=StringToInt(&token[8]); 00368 } 00369 00370 // [halign=...] horizontal alignment 00371 if (StrNICmp(token,"[halign=",8)==0) 00372 { 00373 xp=StringToInt(&token[8]); 00374 } 00375 00376 // [valign=...] vertical alignment 00377 if (StrNICmp(token,"[valign=",8)==0) 00378 { 00379 yp=StringToInt(&token[8]); 00380 } 00381 00382 bool fontChanged=false; 00383 00384 // [style=] special font style 00385 if (StrNICmp(token,"[style=",7)==0) 00386 { 00387 isStyle=true; 00388 int l=Min(StrLen(token)-8,255); 00389 StrNCpy(idbuffer,&token[7],l); 00390 idbuffer[l]=0; 00391 styleId=idbuffer; 00392 fontChanged=true; 00393 } 00394 00395 // [/style] end of special font style 00396 if (StrICmp(token,"[/b]")==0) 00397 { 00398 isStyle=false; 00399 fontChanged=true; 00400 } 00401 00402 // [b] bold font 00403 if (StrICmp(token,"[b]")==0) 00404 { 00405 isBold=true; 00406 fontChanged=true; 00407 } 00408 00409 // [/b] non-bold font 00410 if (StrICmp(token,"[/b]")==0) 00411 { 00412 isBold=false; 00413 fontChanged=true; 00414 } 00415 00416 // [i] italic font 00417 if (StrICmp(token,"[i]")==0) 00418 { 00419 isItalic=true; 00420 fontChanged=true; 00421 } 00422 00423 // [/i] non-italic font 00424 if (StrICmp(token,"[/i]")==0) 00425 { 00426 isItalic=false; 00427 fontChanged=true; 00428 } 00429 00430 // [h] headline 00431 if (StrICmp(token,"[h]")==0) 00432 { 00433 isHeadline=true; 00434 fontChanged=true; 00435 } 00436 00437 // [/h] non-headline 00438 if (StrICmp(token,"[/h]")==0) 00439 { 00440 isHeadline=false; 00441 fontChanged=true; 00442 00443 // Automatic line breaks after headlines 00444 xp=x1; 00445 if (font) 00446 { 00447 Font::Bounds bounds=font->GetBounds(" ",0); 00448 yp+=bounds.height+extraVSpace; 00449 } 00450 else 00451 { 00452 yp+=10; 00453 } 00454 } 00455 00456 // [link=..] hyperlink 00457 if (StrNICmp(token,"[link=",6)==0) 00458 { 00459 isLink=true; 00460 fontChanged=true; 00461 int l=Min(StrLen(token)-7,255); 00462 StrNCpy(idbuffer,&token[6],l); 00463 idbuffer[l]=0; 00464 idString=idbuffer; 00465 } 00466 00467 // [/link] hyperlink end 00468 if (StrICmp(token,"[/link]")==0) 00469 { 00470 isLink=false; 00471 fontChanged=true; 00472 } 00473 00474 // [option=..] option 00475 if (StrNICmp(token,"[option=",8)==0) 00476 { 00477 isOption=true; 00478 fontChanged=true; 00479 int l=Min(StrLen(token)-9,255); 00480 StrNCpy(idbuffer,&token[8],l); 00481 idbuffer[l]=0; 00482 idString=idbuffer; 00483 } 00484 00485 // [/option] option end 00486 if (StrICmp(token,"[/option]")==0) 00487 { 00488 isOption=false; 00489 fontChanged=true; 00490 } 00491 00492 // [optiondisabled] disabled option 00493 if (StrICmp(token,"[optiondisabled]")==0) 00494 { 00495 isDisabledOption=true; 00496 fontChanged=true; 00497 } 00498 00499 // [/optiondisabled] disabled option end 00500 if (StrICmp(token,"[/optiondisabled]")==0) 00501 { 00502 isDisabledOption=false; 00503 fontChanged=true; 00504 } 00505 00506 // If any of the previous markup coded caused a font change/// 00507 if (fontChanged) 00508 { 00509 if (isOption) 00510 { 00511 font=siMarkupTextManager->GetFont(MarkupTextManager::FontStyle_Option); 00512 color=siMarkupTextManager->GetFontColor(MarkupTextManager::FontStyle_Option); 00513 bgcolor=siMarkupTextManager->GetFontBgColor(MarkupTextManager::FontStyle_Option); 00514 opacity=siMarkupTextManager->GetFontBgOpacity(MarkupTextManager::FontStyle_Option); 00515 } 00516 else if (isDisabledOption) 00517 { 00518 font=siMarkupTextManager->GetFont(MarkupTextManager::FontStyle_OptionDisabled); 00519 color=siMarkupTextManager->GetFontColor(MarkupTextManager::FontStyle_OptionDisabled); 00520 bgcolor=siMarkupTextManager->GetFontBgColor(MarkupTextManager::FontStyle_OptionDisabled); 00521 opacity=siMarkupTextManager->GetFontBgOpacity(MarkupTextManager::FontStyle_OptionDisabled); 00522 } 00523 else if (isLink) 00524 { 00525 font=siMarkupTextManager->GetFont(MarkupTextManager::FontStyle_Link); 00526 color=siMarkupTextManager->GetFontColor(MarkupTextManager::FontStyle_Link); 00527 bgcolor=siMarkupTextManager->GetFontBgColor(MarkupTextManager::FontStyle_Link); 00528 opacity=siMarkupTextManager->GetFontBgOpacity(MarkupTextManager::FontStyle_Link); 00529 } 00530 else if (isHeadline) 00531 { 00532 font=siMarkupTextManager->GetFont(MarkupTextManager::FontStyle_Headline); 00533 color=siMarkupTextManager->GetFontColor(MarkupTextManager::FontStyle_Headline); 00534 bgcolor=siMarkupTextManager->GetFontBgColor(MarkupTextManager::FontStyle_Headline); 00535 opacity=siMarkupTextManager->GetFontBgOpacity(MarkupTextManager::FontStyle_Headline); 00536 } 00537 else 00538 { 00539 if (isBold && isItalic) 00540 { 00541 font=siMarkupTextManager->GetFont(MarkupTextManager::FontStyle_BoldItalic); 00542 color=siMarkupTextManager->GetFontColor(MarkupTextManager::FontStyle_BoldItalic); 00543 bgcolor=siMarkupTextManager->GetFontBgColor(MarkupTextManager::FontStyle_BoldItalic); 00544 opacity=siMarkupTextManager->GetFontBgOpacity(MarkupTextManager::FontStyle_BoldItalic); 00545 } 00546 else if (isItalic) 00547 { 00548 font=siMarkupTextManager->GetFont(MarkupTextManager::FontStyle_Italic); 00549 color=siMarkupTextManager->GetFontColor(MarkupTextManager::FontStyle_Italic); 00550 bgcolor=siMarkupTextManager->GetFontBgColor(MarkupTextManager::FontStyle_Italic); 00551 opacity=siMarkupTextManager->GetFontBgOpacity(MarkupTextManager::FontStyle_Italic); 00552 } 00553 else if (isBold) 00554 { 00555 font=siMarkupTextManager->GetFont(MarkupTextManager::FontStyle_Bold); 00556 color=siMarkupTextManager->GetFontColor(MarkupTextManager::FontStyle_Bold); 00557 bgcolor=siMarkupTextManager->GetFontBgColor(MarkupTextManager::FontStyle_Bold); 00558 opacity=siMarkupTextManager->GetFontBgOpacity(MarkupTextManager::FontStyle_Bold); 00559 } 00560 else if (isStyle) 00561 { 00562 font=siMarkupTextManager->GetFont(styleId); 00563 color=siMarkupTextManager->GetFontColor(styleId); 00564 bgcolor=siMarkupTextManager->GetFontBgColor(styleId); 00565 opacity=siMarkupTextManager->GetFontBgOpacity(styleId); 00566 } 00567 else 00568 { 00569 font=siMarkupTextManager->GetFont(MarkupTextManager::FontStyle_Normal); 00570 color=siMarkupTextManager->GetFontColor(MarkupTextManager::FontStyle_Normal); 00571 bgcolor=siMarkupTextManager->GetFontBgColor(MarkupTextManager::FontStyle_Normal); 00572 opacity=siMarkupTextManager->GetFontBgOpacity(MarkupTextManager::FontStyle_Normal); 00573 } 00574 } 00575 } 00576 } 00577 // Process next token 00578 token=GetNextToken(); 00579 } 00580 00581 } 00582 00583 00584 //*** IsOverOption *** 00585 00586 StringId MarkupTextBlock::IsOverOption(int cursorX, int cursorY) const 00587 { 00588 for (int i=0; i<options_.GetItemCount(); i++) 00589 { 00590 InteractiveRegion region=options_.Get(i); 00591 if (cursorX>=region.x1 && cursorX<=region.x2 && cursorY>=region.y1 && cursorY<=region.y2) 00592 { 00593 return region.id; 00594 } 00595 } 00596 00597 return 0; 00598 } 00599 00600 00601 //*** IsOverLink *** 00602 00603 StringId MarkupTextBlock::IsOverLink(int cursorX, int cursorY) const 00604 { 00605 for (int i=0; i<links_.GetItemCount(); i++) 00606 { 00607 InteractiveRegion region=links_.Get(i); 00608 if (cursorX>=region.x1 && cursorX<=region.x2 && cursorY>=region.y1 && cursorY<=region.y2) 00609 { 00610 return region.id; 00611 } 00612 } 00613 00614 return 0; 00615 } 00616 00617
Reproduction/republishing of any material on this site without permission is strictly prohibited.
