00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "compat.h"
00022
00023 #include "Text.h"
00024 #include "Visible.h"
00025 #include "Presentable.h"
00026 #include "Ingredients.h"
00027 #include "Root.h"
00028 #include "BaseClasses.h"
00029 #include "ParseNode.h"
00030 #include "ASN1Codes.h"
00031 #include "Engine.h"
00032 #include "Logging.h"
00033 #include "freemheg.h"
00034
00035 MHText::MHText()
00036 {
00037 m_nCharSet = -1;
00038 m_HorizJ = m_VertJ = Start;
00039 m_LineOrientation = Horizontal;
00040 m_StartCorner = UpperLeft;
00041 m_fTextWrap = false;
00042 m_pDisplay = NULL;
00043 m_fNeedsRedraw = false;
00044 }
00045
00046 MHText::MHText(const MHText &ref): MHVisible(ref)
00047 {
00048 m_OrigFont.Copy(ref.m_OrigFont);
00049 m_OriginalFontAttrs.Copy(ref.m_OriginalFontAttrs);
00050 m_OriginalTextColour.Copy(ref.m_OriginalTextColour);
00051 m_OriginalBgColour.Copy(ref.m_OriginalBgColour);
00052 m_nCharSet = ref.m_nCharSet;
00053 m_HorizJ = ref.m_HorizJ;
00054 m_VertJ = ref.m_VertJ;
00055 m_LineOrientation = ref.m_LineOrientation;
00056 m_StartCorner = ref.m_StartCorner;
00057 m_fTextWrap = ref.m_fTextWrap;
00058 m_pDisplay = NULL;
00059 m_fNeedsRedraw = ref.m_fNeedsRedraw;
00060 }
00061
00062 MHText::~MHText()
00063 {
00064 delete(m_pDisplay);
00065 }
00066
00067
00068 void MHText::Initialise(MHParseNode *p, MHEngine *engine)
00069 {
00070 MHVisible::Initialise(p, engine);
00071
00072 MHParseNode *pFontBody = p->GetNamedArg(C_ORIGINAL_FONT);
00073
00074 if (pFontBody)
00075 {
00076 m_OrigFont.Initialise(pFontBody->GetArgN(0), engine);
00077 }
00078
00079 MHParseNode *pFontAttrs = p->GetNamedArg(C_FONT_ATTRIBUTES);
00080
00081 if (pFontAttrs)
00082 {
00083 pFontAttrs->GetArgN(0)->GetStringValue(m_OriginalFontAttrs);
00084 }
00085
00086
00087 MHParseNode *pTextColour = p->GetNamedArg(C_TEXT_COLOUR);
00088
00089 if (pTextColour)
00090 {
00091 m_OriginalTextColour.Initialise(pTextColour->GetArgN(0), engine);
00092 }
00093
00094 MHParseNode *pBGColour = p->GetNamedArg(C_BACKGROUND_COLOUR);
00095
00096 if (pBGColour)
00097 {
00098 m_OriginalBgColour.Initialise(pBGColour->GetArgN(0), engine);
00099 }
00100
00101
00102 MHParseNode *pChset = p->GetNamedArg(C_CHARACTER_SET);
00103
00104 if (pChset)
00105 {
00106 m_nCharSet = pChset->GetArgN(0)->GetIntValue();
00107 }
00108
00109
00110 MHParseNode *pHJust = p->GetNamedArg(C_HORIZONTAL_JUSTIFICATION);
00111
00112 if (pHJust)
00113 {
00114 m_HorizJ = (enum Justification)pHJust->GetArgN(0)->GetEnumValue();
00115 }
00116
00117 MHParseNode *pVJust = p->GetNamedArg(C_VERTICAL_JUSTIFICATION);
00118
00119 if (pVJust)
00120 {
00121 m_VertJ = (enum Justification)pVJust->GetArgN(0)->GetEnumValue();
00122 }
00123
00124
00125 MHParseNode *pLineO = p->GetNamedArg(C_LINE_ORIENTATION);
00126
00127 if (pLineO)
00128 {
00129 m_LineOrientation = (enum LineOrientation)pLineO->GetArgN(0)->GetEnumValue();
00130 }
00131
00132
00133 MHParseNode *pStartC = p->GetNamedArg(C_START_CORNER);
00134
00135 if (pStartC)
00136 {
00137 m_StartCorner = (enum StartCorner)pStartC->GetArgN(0)->GetEnumValue();
00138 }
00139
00140
00141 MHParseNode *pTextWrap = p->GetNamedArg(C_TEXT_WRAPPING);
00142
00143 if (pTextWrap)
00144 {
00145 m_fTextWrap = pTextWrap->GetArgN(0)->GetBoolValue();
00146 }
00147
00148 m_pDisplay = engine->GetContext()->CreateText();
00149 m_fNeedsRedraw = true;
00150 }
00151
00152 static const char *rchJustification[] =
00153 {
00154 "start",
00155 "end",
00156 "centre",
00157 "justified"
00158 };
00159
00160
00161 int MHText::GetJustification(const char *str)
00162 {
00163 for (int i = 0; i < (int)(sizeof(rchJustification) / sizeof(rchJustification[0])); i++)
00164 {
00165 if (strcasecmp(str, rchJustification[i]) == 0)
00166 {
00167 return (i + 1);
00168 }
00169 }
00170
00171 return 0;
00172 }
00173
00174 static const char *rchlineOrientation[] =
00175 {
00176 "vertical",
00177 "horizontal"
00178 };
00179
00180 int MHText::GetLineOrientation(const char *str)
00181 {
00182 for (int i = 0; i < (int)(sizeof(rchlineOrientation) / sizeof(rchlineOrientation[0])); i++)
00183 {
00184 if (strcasecmp(str, rchlineOrientation[i]) == 0)
00185 {
00186 return (i + 1);
00187 }
00188 }
00189
00190 return 0;
00191 }
00192
00193 static const char *rchStartCorner[] =
00194 {
00195 "upper-left",
00196 "upper-right",
00197 "lower-left",
00198 "lower-right"
00199 };
00200
00201 int MHText::GetStartCorner(const char *str)
00202 {
00203 for (int i = 0; i < (int)(sizeof(rchStartCorner) / sizeof(rchStartCorner[0])); i++)
00204 {
00205 if (strcasecmp(str, rchStartCorner[i]) == 0)
00206 {
00207 return (i + 1);
00208 }
00209 }
00210
00211 return 0;
00212 }
00213
00214 void MHText::PrintMe(FILE *fd, int nTabs) const
00215 {
00216 PrintTabs(fd, nTabs);
00217 fprintf(fd, "{:Text ");
00218 MHVisible::PrintMe(fd, nTabs + 1);
00219
00220 if (m_OrigFont.IsSet())
00221 {
00222 PrintTabs(fd, nTabs + 1);
00223 fprintf(fd, ":OrigFont ");
00224 m_OrigFont.PrintMe(fd, nTabs + 1);
00225 fprintf(fd, "\n");
00226 }
00227
00228 if (m_OriginalFontAttrs.Size() > 0)
00229 {
00230 PrintTabs(fd, nTabs + 1);
00231 fprintf(fd, ":FontAttributes ");
00232 m_OriginalFontAttrs.PrintMe(fd, nTabs + 1);
00233 fprintf(fd, "\n");
00234 }
00235
00236 if (m_OriginalTextColour.IsSet())
00237 {
00238 PrintTabs(fd, nTabs + 1);
00239 fprintf(fd, ":TextColour ");
00240 m_OriginalTextColour.PrintMe(fd, nTabs + 1);
00241 fprintf(fd, "\n");
00242 }
00243
00244 if (m_OriginalBgColour.IsSet())
00245 {
00246 PrintTabs(fd, nTabs + 1);
00247 fprintf(fd, ":BackgroundColour ");
00248 m_OriginalBgColour.PrintMe(fd, nTabs + 1);
00249 fprintf(fd, "\n");
00250 }
00251
00252 if (m_nCharSet >= 0)
00253 {
00254 PrintTabs(fd, nTabs + 1);
00255 fprintf(fd, ":CharacterSet %d\n", m_nCharSet);
00256 }
00257
00258 if (m_HorizJ != Start)
00259 {
00260 PrintTabs(fd, nTabs + 1);
00261 fprintf(fd, ":HJustification %s\n", rchJustification[m_HorizJ-1]);
00262 }
00263
00264 if (m_VertJ != Start)
00265 {
00266 PrintTabs(fd, nTabs + 1);
00267 fprintf(fd, ":VJustification %s\n", rchJustification[m_VertJ-1]);
00268 }
00269
00270 if (m_LineOrientation != Horizontal)
00271 {
00272 PrintTabs(fd, nTabs + 1);
00273 fprintf(fd, ":LineOrientation %s\n", rchlineOrientation[m_LineOrientation-1]);
00274 }
00275
00276 if (m_StartCorner != UpperLeft)
00277 {
00278 PrintTabs(fd, nTabs + 1);
00279 fprintf(fd, ":StartCorner %s\n", rchStartCorner[m_StartCorner-1]);
00280 }
00281
00282 if (m_fTextWrap)
00283 {
00284 PrintTabs(fd, nTabs + 1);
00285 fprintf(fd, ":TextWrapping true\n");
00286 }
00287
00288 PrintTabs(fd, nTabs);
00289 fprintf(fd, "}\n");
00290 }
00291
00292 void MHText::Preparation(MHEngine *engine)
00293 {
00294 if (m_fAvailable)
00295 {
00296 return;
00297 }
00298
00299
00300
00301
00302 if (m_OriginalTextColour.IsSet())
00303 {
00304 m_textColour.Copy(m_OriginalTextColour);
00305 }
00306 else
00307 {
00308 engine->GetDefaultTextColour(m_textColour);
00309 }
00310
00311 if (m_OriginalBgColour.IsSet())
00312 {
00313 m_bgColour.Copy(m_OriginalBgColour);
00314 }
00315 else
00316 {
00317 engine->GetDefaultBGColour(m_bgColour);
00318 }
00319
00320 if (m_OriginalFontAttrs.Size() > 0)
00321 {
00322 m_fontAttrs.Copy(m_OriginalFontAttrs);
00323 }
00324 else
00325 {
00326 engine->GetDefaultFontAttrs(m_fontAttrs);
00327 }
00328
00329 MHVisible::Preparation(engine);
00330
00331 m_pDisplay->SetSize(m_nBoxWidth, m_nBoxHeight);
00332 m_fNeedsRedraw = true;
00333 }
00334
00335
00336 void MHText::ContentPreparation(MHEngine *engine)
00337 {
00338 MHVisible::ContentPreparation(engine);
00339
00340 if (m_ContentType == IN_NoContent)
00341 {
00342 MHERROR("Text object must have content");
00343 }
00344
00345 if (m_ContentType == IN_IncludedContent)
00346 {
00347 CreateContent(m_IncludedContent.Bytes(), m_IncludedContent.Size(), engine);
00348 }
00349 }
00350
00351
00352 void MHText::ContentArrived(const unsigned char *data, int length, MHEngine *engine)
00353 {
00354 CreateContent(data, length, engine);
00355
00356 engine->EventTriggered(this, EventContentAvailable);
00357 m_fNeedsRedraw = true;
00358 }
00359
00360
00361 void MHText::CreateContent(const unsigned char *p, int s, MHEngine *engine)
00362 {
00363 m_Content.Copy(MHOctetString((const char *)p, s));
00364 engine->Redraw(GetVisibleArea());
00365 m_fNeedsRedraw = true;
00366
00367 }
00368
00369 void MHText::SetTextColour(const MHColour &colour, MHEngine *engine)
00370 {
00371 m_textColour.Copy(colour);
00372 m_fNeedsRedraw = true;
00373 engine->Redraw(GetVisibleArea());
00374 }
00375
00376 void MHText::SetBackgroundColour(const MHColour &colour, MHEngine *engine)
00377 {
00378 m_bgColour.Copy(colour);
00379
00380
00381 engine->Redraw(GetVisibleArea());
00382 }
00383
00384 void MHText::SetFontAttributes(const MHOctetString &fontAttrs, MHEngine *engine)
00385 {
00386 m_fontAttrs.Copy(fontAttrs);
00387 m_fNeedsRedraw = true;
00388 engine->Redraw(GetVisibleArea());
00389 }
00390
00391
00392 static void InterpretAttributes(const MHOctetString &attrs, int &style, int &size, int &lineSpace, int &letterSpace)
00393 {
00394
00395 style = 0;
00396 size = 0x18;
00397 lineSpace = 0x18;
00398 letterSpace = 0;
00399
00400 if (attrs.Size() == 5)
00401 {
00402 style = attrs.GetAt(0);
00403 size = attrs.GetAt(1);
00404 lineSpace = attrs.GetAt(2);
00405
00406 letterSpace = attrs.GetAt(3) * 256 + attrs.GetAt(4);
00407
00408 if (letterSpace > 32767)
00409 {
00410 letterSpace -= 65536;
00411 }
00412 }
00413 else
00414 {
00415 const unsigned char *str = attrs.Bytes();
00416 char *p = (char *)str;
00417 char *q = strchr(p, '.');
00418
00419 if (q != NULL)
00420 {
00421 if (q - p == 6 && strncmp(p, "italic", 6) == 0)
00422 {
00423 style = 1;
00424 }
00425 else if (q - p == 4 && strncmp(p, "bold", 4) == 0)
00426 {
00427 style = 2;
00428 }
00429 else if (q - p == 11 && strncmp(p, "bold-italic", 11) == 0)
00430 {
00431 style = 3;
00432 }
00433
00434
00435 p = q + 1;
00436 q = strchr(p, '.');
00437 }
00438
00439 if (q != NULL)
00440 {
00441 size = atoi(p);
00442
00443 if (size == 0)
00444 {
00445 size = 0x18;
00446 }
00447
00448 p = q + 1;
00449 q = strchr(p, '.');
00450 }
00451
00452 if (q != NULL)
00453 {
00454 lineSpace = atoi(p);
00455
00456 if (lineSpace == 0)
00457 {
00458 size = 0x18;
00459 }
00460
00461 p = q + 1;
00462 q = strchr(p, '.');
00463 }
00464
00465 if (q != NULL)
00466 {
00467 letterSpace = atoi(p);
00468 }
00469 }
00470 }
00471
00472
00473 class MHTextItem
00474 {
00475 public:
00476 MHTextItem();
00477 MHOctetString m_Text;
00478 QString m_Unicode;
00479 int m_nUnicode;
00480 int m_Width;
00481 MHRgba m_Colour;
00482 int m_nTabCount;
00483
00484
00485 MHTextItem *NewItem();
00486 };
00487
00488 MHTextItem::MHTextItem()
00489 {
00490 m_nUnicode = 0;
00491 m_Width = 0;
00492 m_Colour = MHRgba(0, 0, 0, 255);
00493 m_nTabCount = 0;
00494 }
00495
00496 MHTextItem *MHTextItem::NewItem()
00497 {
00498 MHTextItem *pItem = new MHTextItem;
00499 pItem->m_Colour = m_Colour;
00500 return pItem;
00501 }
00502
00503
00504 class MHTextLine
00505 {
00506 public:
00507 MHTextLine(): m_nLineWidth(0), m_nLineHeight(0), m_nDescent(0) {}
00508 ~MHTextLine();
00509 MHSequence <MHTextItem *> m_Items;
00510 int m_nLineWidth;
00511 int m_nLineHeight;
00512 int m_nDescent;
00513 };
00514
00515 MHTextLine::~MHTextLine()
00516 {
00517 for (int i = 0; i < m_Items.Size(); i++)
00518 {
00519 delete(m_Items.GetAt(i));
00520 }
00521 }
00522
00523
00524 #define TABSTOP 45
00525
00526
00527
00528
00529
00530
00531 void MHText::Redraw()
00532 {
00533 if (! m_fRunning || !m_pDisplay)
00534 {
00535 return;
00536 }
00537
00538 if (m_nBoxWidth == 0 || m_nBoxHeight == 0)
00539 {
00540 return;
00541 }
00542
00543 m_pDisplay->SetSize(m_nBoxWidth, m_nBoxHeight);
00544 m_pDisplay->Clear();
00545
00546 MHRgba textColour = GetColour(m_textColour);
00547
00548 MHSequence <MHTextLine *> theText;
00549
00550 MHTextItem *pCurrItem = new MHTextItem;
00551 MHTextLine *pCurrLine = new MHTextLine;
00552 pCurrLine->m_Items.Append(pCurrItem);
00553 theText.Append(pCurrLine);
00554 MHStack <MHRgba> m_ColourStack;
00555 m_ColourStack.Push(textColour);
00556 pCurrItem->m_Colour = textColour;
00557
00558 int i = 0;
00559
00560 while (i < m_Content.Size())
00561 {
00562 unsigned char ch = m_Content.GetAt(i++);
00563
00564 if (ch == '\t')
00565 {
00566 if (pCurrItem->m_Text.Size() != 0)
00567 {
00568 pCurrItem = pCurrItem->NewItem();
00569 pCurrLine->m_Items.Append(pCurrItem);
00570 }
00571
00572 pCurrItem->m_nTabCount++;
00573 }
00574
00575 else if (ch == '\r')
00576 {
00577
00578
00579 pCurrLine = new MHTextLine;
00580 theText.Append(pCurrLine);
00581 pCurrItem = pCurrItem->NewItem();
00582 pCurrLine->m_Items.Append(pCurrItem);
00583 }
00584
00585 else if (ch == 0x1b)
00586 {
00587 if (i == m_Content.Size())
00588 {
00589 break;
00590 }
00591
00592 unsigned char code = m_Content.GetAt(i);
00593
00594
00595
00596 if (code >= 0x40 && code <= 0x5e)
00597 {
00598
00599 if (++i == m_Content.Size())
00600 {
00601 break;
00602 }
00603
00604 unsigned char paramCount = m_Content.GetAt(i);
00605 i++;
00606
00607 if (code == 0x43 && paramCount == 4 && i + paramCount <= m_Content.Size())
00608 {
00609
00610 if (pCurrItem->m_Text.Size() != 0)
00611 {
00612 pCurrItem = pCurrItem->NewItem();
00613 pCurrLine->m_Items.Append(pCurrItem);
00614 }
00615
00616 pCurrItem->m_Colour = MHRgba(m_Content.GetAt(i), m_Content.GetAt(i + 1),
00617 m_Content.GetAt(i + 2), 255 - m_Content.GetAt(i + 3));
00618
00619 m_ColourStack.Push(pCurrItem->m_Colour);
00620 }
00621 else
00622 {
00623 MHLOG(MHLogWarning, QString("Unknown text escape code 0x%1").arg(code, 2, 16));
00624 }
00625
00626 i += paramCount;
00627 }
00628 else if (code >= 0x60 && code <= 0x7e)
00629 {
00630 i++;
00631
00632 if (code == 0x63)
00633 {
00634 if (m_ColourStack.Size() > 1)
00635 {
00636 m_ColourStack.Pop();
00637
00638
00639 if (pCurrItem->m_Text.Size() != 0)
00640 {
00641 pCurrItem = pCurrItem->NewItem();
00642 pCurrLine->m_Items.Append(pCurrItem);
00643 }
00644
00645
00646 pCurrItem->m_Colour = m_ColourStack.Top();
00647 }
00648 }
00649 }
00650 }
00651
00652 else if (ch <= 0x1f)
00653 {
00654
00655
00656 }
00657
00658 else
00659 {
00660 int nStart = i - 1;
00661
00662 while (i < m_Content.Size() && m_Content.GetAt(i) >= 0x20)
00663 {
00664 i++;
00665 }
00666
00667 pCurrItem->m_Text.Append(MHOctetString(m_Content, nStart, i - nStart));
00668 }
00669 }
00670
00671
00672 int style, size, lineSpace, letterSpace;
00673 InterpretAttributes(m_fontAttrs, style, size, lineSpace, letterSpace);
00674
00675 m_pDisplay->SetFont(size, (style & 2) != 0, (style & 1) != 0);
00676
00677
00678 for (i = 0; i < theText.Size(); i++)
00679 {
00680 MHTextLine *pLine = theText.GetAt(i);
00681 pLine->m_nLineWidth = 0;
00682
00683 for (int j = 0; j < pLine->m_Items.Size(); j++)
00684 {
00685 MHTextItem *pItem = pLine->m_Items.GetAt(j);
00686
00687
00688 for (int k = 0; k < pItem->m_nTabCount; k++)
00689 {
00690 pLine->m_nLineWidth += TABSTOP - pLine->m_nLineWidth % TABSTOP;
00691 }
00692
00693 if (pItem->m_Unicode.isEmpty())
00694 {
00695 int s = pItem->m_Text.Size();
00696 pItem->m_Unicode = QString::fromUtf8((const char *)pItem->m_Text.Bytes(), s);
00697 pItem->m_nUnicode = pItem->m_Unicode.length();
00698 }
00699
00700
00701 int nFullText = pItem->m_nUnicode;
00702
00703 QRect rect = m_pDisplay->GetBounds(pItem->m_Unicode, pItem->m_nUnicode, m_nBoxWidth - pLine->m_nLineWidth);
00704
00705 if (nFullText != pItem->m_nUnicode && m_fTextWrap)
00706 {
00707 int nTruncated = pItem->m_nUnicode;
00708
00709 while (pItem->m_nUnicode > 0 && pItem->m_Unicode[pItem->m_nUnicode] != ' ')
00710 {
00711 pItem->m_nUnicode--;
00712 }
00713
00714
00715 if (pItem->m_nUnicode == 0)
00716 {
00717 pItem->m_nUnicode = nTruncated;
00718 }
00719
00720
00721 if (pItem->m_nUnicode == 0)
00722 {
00723 pItem->m_nUnicode = 1;
00724 }
00725
00726
00727 int nNewWidth = nFullText - pItem->m_nUnicode;
00728 int nNewStart = pItem->m_nUnicode;
00729
00730
00731 while (nNewWidth != 0 && pItem->m_Unicode[nNewStart] == ' ')
00732 {
00733 nNewStart++;
00734 nNewWidth--;
00735 }
00736
00737 if (nNewWidth != 0)
00738 {
00739
00740 MHTextLine *pNewLine = new MHTextLine;
00741 theText.InsertAt(pNewLine, i + 1);
00742
00743 MHTextItem *pNewItem = pItem->NewItem();
00744 pNewLine->m_Items.Append(pNewItem);
00745 pNewItem->m_Unicode = pItem->m_Unicode.mid(nNewStart, nNewWidth);
00746 pNewItem->m_nUnicode = nNewWidth;
00747
00748
00749 while (pLine->m_Items.Size() > j + 1)
00750 {
00751 pNewLine->m_Items.Append(pLine->m_Items.GetAt(j + 1));
00752 pLine->m_Items.RemoveAt(j + 1);
00753 }
00754 }
00755
00756
00757
00758 while (pItem->m_nUnicode > 1 && pItem->m_Unicode[pItem->m_nUnicode-1] == ' ')
00759 {
00760 pItem->m_nUnicode--;
00761 }
00762
00763 rect = m_pDisplay->GetBounds(pItem->m_Unicode, pItem->m_nUnicode);
00764 }
00765
00766 pItem->m_Width = rect.width();
00767 pLine->m_nLineWidth += rect.width();
00768
00769 if (rect.height() > pLine->m_nLineHeight)
00770 {
00771 pLine->m_nLineHeight = rect.height();
00772 }
00773
00774 if (rect.bottom() > pLine->m_nDescent)
00775 {
00776 pLine->m_nDescent = rect.bottom();
00777 }
00778 }
00779 }
00780
00781
00782 int yOffset = 0;
00783
00784 int nNumLines = theText.Size();
00785
00786 do
00787 {
00788 if (m_VertJ == End)
00789 {
00790 yOffset = m_nBoxHeight - nNumLines * lineSpace;
00791 }
00792 else if (m_VertJ == Centre)
00793 {
00794 yOffset = (m_nBoxHeight - nNumLines * lineSpace) / 2;
00795 }
00796
00797 if (yOffset < 0)
00798 {
00799 nNumLines--;
00800 }
00801 }
00802 while (yOffset < 0);
00803
00804 for (i = 0; i < nNumLines; i++)
00805 {
00806 MHTextLine *pLine = theText.GetAt(i);
00807 int xOffset = 0;
00808
00809 if (m_HorizJ == End)
00810 {
00811 xOffset = m_nBoxWidth - pLine->m_nLineWidth;
00812 }
00813 else if (m_HorizJ == Centre)
00814 {
00815 xOffset = (m_nBoxWidth - pLine->m_nLineWidth) / 2;
00816 }
00817
00818 for (int j = 0; j < pLine->m_Items.Size(); j++)
00819 {
00820 MHTextItem *pItem = pLine->m_Items.GetAt(j);
00821
00822
00823 for (int k = 0; k < pItem->m_nTabCount; k++)
00824 {
00825 xOffset += TABSTOP - xOffset % TABSTOP;
00826 }
00827
00828 if (! pItem->m_Unicode.isEmpty())
00829 {
00830 m_pDisplay->AddText(xOffset, yOffset + (pLine->m_nLineHeight + lineSpace) / 2 - pLine->m_nDescent,
00831 pItem->m_Unicode.left(pItem->m_nUnicode), pItem->m_Colour);
00832 }
00833
00834 xOffset += pItem->m_Width;
00835 }
00836
00837 yOffset += lineSpace;
00838
00839 if (yOffset + lineSpace > m_nBoxHeight)
00840 {
00841 break;
00842 }
00843 }
00844
00845
00846 for (int k = 0; k < theText.Size(); k++)
00847 {
00848 delete(theText.GetAt(k));
00849 }
00850 }
00851
00852 void MHText::Display(MHEngine *engine)
00853 {
00854 if (! m_fRunning || ! m_pDisplay || m_nBoxWidth == 0 || m_nBoxHeight == 0)
00855 {
00856 return;
00857 }
00858
00859
00860 if (m_fNeedsRedraw)
00861 {
00862 Redraw();
00863 m_fNeedsRedraw = false;
00864 }
00865
00866
00867 engine->GetContext()->DrawRect(m_nPosX, m_nPosY, m_nBoxWidth, m_nBoxHeight, GetColour(m_bgColour));
00868 m_pDisplay->Draw(m_nPosX, m_nPosY);
00869 }
00870
00871
00872 QRegion MHText::GetOpaqueArea()
00873 {
00874 if (! m_fRunning || (GetColour(m_bgColour)).alpha() != 255)
00875 {
00876 return QRegion();
00877 }
00878 else
00879 {
00880 return QRegion(QRect(m_nPosX, m_nPosY, m_nBoxWidth, m_nBoxHeight));
00881 }
00882 }
00883
00884
00885 MHHyperText::MHHyperText(): MHInteractible(this)
00886 {
00887
00888 }
00889
00890 MHHyperText::~MHHyperText()
00891 {
00892
00893 }
00894
00895 void MHHyperText::Initialise(MHParseNode *p, MHEngine *engine)
00896 {
00897 MHText::Initialise(p, engine);
00898 MHInteractible::Initialise(p, engine);
00899
00900 }
00901
00902 void MHHyperText::PrintMe(FILE *fd, int nTabs) const
00903 {
00904 PrintTabs(fd, nTabs);
00905 fprintf(fd, "{:HyperText ");
00906 MHText::PrintMe(fd, nTabs + 1);
00907 MHInteractible::PrintMe(fd, nTabs + 1);
00908 fprintf(fd, "****TODO\n");
00909 PrintTabs(fd, nTabs);
00910 fprintf(fd, "}\n");
00911 }
00912
00913
00914 void MHSetFontAttributes::Initialise(MHParseNode *p, MHEngine *engine)
00915 {
00916 MHElemAction::Initialise(p, engine);
00917 m_FontAttrs.Initialise(p->GetArgN(1), engine);
00918 }
00919
00920 void MHSetFontAttributes::Perform(MHEngine *engine)
00921 {
00922
00923 MHOctetString newAttrs;
00924 m_FontAttrs.GetValue(newAttrs, engine);
00925 Target(engine)->SetFontAttributes(newAttrs, engine);
00926 }