ManaPlus
browserbox.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2004-2009 The Mana World Development Team
4  * Copyright (C) 2009-2010 The Mana Developers
5  * Copyright (C) 2011-2018 The ManaPlus Developers
6  * Copyright (C) 2009 Aethyra Development Team
7  *
8  * This file is part of The ManaPlus Client.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program. If not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 #include "gui/widgets/browserbox.h"
25 
27 
28 #include "gui/gui.h"
29 #include "gui/mouseoverlink.h"
30 #include "gui/skin.h"
31 
32 #include "gui/fonts/font.h"
33 
34 #include "gui/widgets/browserbox.inc"
36 
37 #include "render/graphics.h"
38 
39 #include "resources/imageset.h"
40 
41 #include "resources/image/image.h"
42 
45 
46 #include "utils/browserboxtools.h"
47 #include "utils/checkutils.h"
48 #include "utils/foreach.h"
49 #include "utils/stringutils.h"
50 #include "utils/timer.h"
52 
53 #include <algorithm>
54 
55 #include "debug.h"
56 
57 ImageSet *BrowserBox::mEmotes = nullptr;
59 
60 BrowserBox::BrowserBox(const Widget2 *const widget,
61  const Opaque opaque,
62  const std::string &skin) :
63  Widget(widget),
64  MouseListener(),
66  mTextRows(),
67  mTextRowLinksCount(),
68  mLineParts(),
69  mLinks(),
70  mLinkHandler(nullptr),
71  mSkin(nullptr),
72  mHighlightMode(0),
73  mSelectedLink(-1),
74  mMaxRows(0),
75  mHeight(0),
76  mWidth(0),
77  mYStart(0),
78  mUpdateTime(-1),
79  mPadding(0),
80  mNewLinePadding(15U),
81  mItemPadding(0),
82  mDataWidth(0),
83  mHighlightColor(getThemeColor(ThemeColorId::HIGHLIGHT, 255U)),
84  mHyperLinkColor(getThemeColor(ThemeColorId::HYPERLINK, 255U)),
85  mOpaque(opaque),
86  mUseLinksAndUserColors(true),
87  mUseEmotes(true),
88  mAlwaysUpdate(true),
89  mProcessVars(false),
90  mEnableImages(false),
91  mEnableKeys(false),
92  mEnableTabs(false)
93 {
94  mAllowLogic = false;
95 
96  setFocusable(true);
97  addMouseListener(this);
98  addWidgetListener(this);
99 
101 
102  if (theme != nullptr)
103  {
104  mSkin = theme->load(skin,
105  "browserbox.xml",
106  true,
108  }
109  if (mInstances == 0)
110  {
112  "graphics/sprites/chatemotes.png", 17, 18);
113  }
114  mInstances ++;
115 
116  if (mSkin != nullptr)
117  {
120  mSkin->getOption("newLinePadding", 15));
121  mItemPadding = mSkin->getOption("itemPadding");
122  if (mSkin->getOption("highlightBackground") != 0)
124  if (mSkin->getOption("highlightUnderline") != 0)
126  }
127 
128  readColor(BLACK);
129  readColor(RED);
130  readColor(GREEN);
131  readColor(BLUE);
132  readColor(ORANGE);
133  readColor(YELLOW);
134  readColor(PINK);
135  readColor(PURPLE);
136  readColor(GRAY);
137  readColor(BROWN);
138 
141 }
142 
144 {
145  if (gui != nullptr)
146  gui->removeDragged(this);
147 
148  if (theme != nullptr)
149  {
150  theme->unload(mSkin);
151  mSkin = nullptr;
152  }
153 
154  mInstances --;
155  if (mInstances == 0)
156  {
157  if (mEmotes != nullptr)
158  {
159  mEmotes->decRef();
160  mEmotes = nullptr;
161  }
162  }
163 }
164 
166 {
167  mLinkHandler = linkHandler;
168 }
169 
170 void BrowserBox::addRow(const std::string &row, const bool atTop)
171 {
172  std::string tmp = row;
173  std::string newRow;
174  const Font *const font = getFont();
175  int linksCount = 0;
176 
177  if (getWidth() < 0)
178  return;
179 
180  if (mProcessVars)
181  {
183  }
184 
185  // Use links and user defined colors
187  {
188  BrowserLink bLink;
189 
190  // Check for links in format "@@link|[email protected]@"
191  const uint32_t sz = CAST_U32(mTextRows.size());
192 
193  if (mEnableKeys)
194  {
196  }
197 
198  size_t idx1 = tmp.find("@@");
199  while (idx1 != std::string::npos)
200  {
201  const size_t idx2 = tmp.find('|', idx1);
202  const size_t idx3 = tmp.find("@@", idx2);
203 
204  if (idx2 == std::string::npos || idx3 == std::string::npos)
205  break;
206  bLink.link = tmp.substr(idx1 + 2, idx2 - (idx1 + 2));
207  bLink.caption = tmp.substr(idx2 + 1, idx3 - (idx2 + 1));
208  bLink.y1 = CAST_S32(sz) * font->getHeight();
209  bLink.y2 = bLink.y1 + font->getHeight();
210  if (bLink.caption.empty())
211  {
213  bLink.link);
214  if (translator != nullptr)
215  bLink.caption = translator->getStr(bLink.caption);
216  }
217 
218  newRow.append(tmp.substr(0, idx1));
219 
220  std::string tmp2 = newRow;
221  idx1 = tmp2.find("##");
222  while (idx1 != std::string::npos)
223  {
224  tmp2.erase(idx1, 3);
225  idx1 = tmp2.find("##");
226  }
227  bLink.x1 = font->getWidth(tmp2) - 1;
228  bLink.x2 = bLink.x1 + font->getWidth(bLink.caption) + 1;
229 
230  if (atTop)
231  mLinks.insert(mLinks.begin(), bLink);
232  else
233  mLinks.push_back(bLink);
234  linksCount ++;
235 
236  newRow.append("##<").append(bLink.caption);
237 
238  tmp.erase(0, idx3 + 2);
239  if (!tmp.empty())
240  newRow.append("##>");
241 
242  idx1 = tmp.find("@@");
243  }
244 
245  newRow.append(tmp);
246  }
247  // Don't use links and user defined colors
248  else
249  {
250  newRow = row;
251  }
252 
253  if (mEnableTabs)
254  {
256  }
257 
258  if (atTop)
259  {
260  mTextRows.push_front(newRow);
261  mTextRowLinksCount.push_front(linksCount);
262  }
263  else
264  {
265  mTextRows.push_back(newRow);
266  mTextRowLinksCount.push_back(linksCount);
267  }
268 
269  // discard older rows when a row limit has been set
270  if (mMaxRows > 0 && !mTextRows.empty())
271  {
272  while (mTextRows.size() > CAST_SIZE(mMaxRows))
273  {
274  mTextRows.pop_front();
275  int cnt = mTextRowLinksCount.front();
276  mTextRowLinksCount.pop_front();
277 
278  while ((cnt != 0) && !mLinks.empty())
279  {
280  mLinks.erase(mLinks.begin());
281  cnt --;
282  }
283  }
284  }
285 
286  const int fontHeight = font->getHeight();
287  unsigned int y = 0;
288  unsigned int nextChar;
289  const char *const hyphen = "~";
290  const unsigned int hyphenWidth = CAST_U32(
291  font->getWidth(hyphen));
292  unsigned int x = 0;
293 
295  {
296  std::string tempRow = *i;
297  for (uint32_t j = 0, sz = CAST_U32(tempRow.size());
298  j < sz;
299  j++)
300  {
301  const std::string character = tempRow.substr(j, 1);
302  x += CAST_U32(font->getWidth(character));
303  nextChar = j + 1;
304 
305  // Wraping between words (at blank spaces)
306  if (nextChar < sz && tempRow.at(nextChar) == ' ')
307  {
308  int nextSpacePos = CAST_U32(
309  tempRow.find(' ', (nextChar + 1)));
310  if (nextSpacePos <= 0)
311  nextSpacePos = CAST_U32(sz) - 1U;
312 
313  const unsigned int nextWordWidth =
314  CAST_U32(font->getWidth(
315  tempRow.substr(nextChar,
316  (CAST_U32(nextSpacePos) - nextChar))));
317 
318  if ((x + nextWordWidth + 10)
319  > CAST_U32(getWidth()))
320  {
321  x = mNewLinePadding; // Ident in new line
322  y += 1;
323  j ++;
324  }
325  }
326  // Wrapping looong lines (brutal force)
327  else if ((x + 2 * hyphenWidth)
328  > CAST_U32(getWidth()))
329  {
330  x = mNewLinePadding; // Ident in new line
331  y += 1;
332  }
333  }
334  }
335 
336  setHeight(fontHeight * (CAST_S32(
337  CAST_U32(mTextRows.size()) + y)));
338  mUpdateTime = 0;
339  updateHeight();
340 }
341 
342 void BrowserBox::addRow(const std::string &cmd, const char *const text)
343 {
344  addRow(strprintf("@@%s|%[email protected]@", encodeLinkText(cmd).c_str(),
345  encodeLinkText(text).c_str()),
346  false);
347 }
348 
349 void BrowserBox::addImage(const std::string &path)
350 {
351  if (!mEnableImages)
352  return;
353 
354  mTextRows.push_back("~~~" + path);
355  mTextRowLinksCount.push_back(0);
356 }
357 
359 {
360  mTextRows.clear();
361  mTextRowLinksCount.clear();
362  mLinks.clear();
363  setWidth(0);
364  setHeight(0);
365  mSelectedLink = -1;
366  mUpdateTime = 0;
367  mDataWidth = 0;
368  updateHeight();
369 }
370 
372 {
373  if (mLinkHandler == nullptr)
374  return;
375 
376  const LinkIterator i = std::find_if(mLinks.begin(), mLinks.end(),
377  MouseOverLink(event.getX(), event.getY()));
378 
379  if (i != mLinks.end())
380  {
381  mLinkHandler->handleLink(i->link, &event);
382  event.consume();
383  }
384 }
385 
387 {
388  const LinkIterator i = std::find_if(mLinks.begin(), mLinks.end(),
389  MouseOverLink(event.getX(), event.getY()));
390 
391  mSelectedLink = (i != mLinks.end())
392  ? CAST_S32(i - mLinks.begin()) : -1;
393 }
394 
396 {
397  mSelectedLink = -1;
398 }
399 
400 void BrowserBox::draw(Graphics *const graphics)
401 {
402  BLOCK_START("BrowserBox::draw")
403  const ClipRect &cr = graphics->getTopClip();
404  mYStart = cr.y - cr.yOffset;
405  const int yEnd = mYStart + cr.height;
406  if (mYStart < 0)
407  mYStart = 0;
408 
409  if (mDimension.width != mWidth)
410  {
412  mHeight = calcHeight();
415  if (mDimension.width != mWidth)
416  reportAlways("browserbox resize in draw");
417  }
418 
419  if (mOpaque == Opaque_true)
420  {
421  graphics->setColor(mBackgroundColor);
422  graphics->fillRectangle(Rect(0, 0,
424  }
425 
426  if (mSelectedLink >= 0 &&
427  mSelectedLink < CAST_S32(mLinks.size()))
428  {
430  {
432  graphics->setColor(mHighlightColor);
433  graphics->fillRectangle(Rect(
434  link.x1,
435  link.y1,
436  link.x2 - link.x1,
437  link.y2 - link.y1));
438  }
439 
441  {
443  graphics->setColor(mHyperLinkColor);
444  graphics->drawLine(
445  link.x1,
446  link.y2,
447  link.x2,
448  link.y2);
449  }
450  }
451 
452  Font *const font = getFont();
453 
455  {
456  const LinePart &part = *i;
457  if (part.mY + 50 < mYStart)
458  continue;
459  if (part.mY > yEnd)
460  break;
461  if (part.mType == 0U)
462  {
463  if (part.mBold)
464  {
465  boldFont->drawString(graphics,
466  part.mColor,
467  part.mColor2,
468  part.mText,
469  part.mX, part.mY);
470  }
471  else
472  {
473  font->drawString(graphics,
474  part.mColor,
475  part.mColor2,
476  part.mText,
477  part.mX, part.mY);
478  }
479  }
480  else if (part.mImage != nullptr)
481  {
482  graphics->drawImage(part.mImage, part.mX, part.mY);
483  }
484  }
485 
486  BLOCK_END("BrowserBox::draw")
487 }
488 
489 void BrowserBox::safeDraw(Graphics *const graphics)
490 {
491  BrowserBox::draw(graphics);
492 }
493 
495 {
496  unsigned int y = CAST_U32(mPadding);
497  int wrappedLines = 0;
498  int moreHeight = 0;
499  int maxWidth = mDimension.width - mPadding;
500  int link = 0;
501  bool bold = false;
502  unsigned int wWidth = CAST_U32(maxWidth);
503 
504  if (maxWidth < 0)
505  return 1;
506 
507  const Font *const font = getFont();
508  const int fontHeight = font->getHeight() + 2 * mItemPadding;
509  const int fontWidthMinus = font->getWidth("-");
510  const char *const hyphen = "~";
511  const int hyphenWidth = font->getWidth(hyphen);
512 
513  Color selColor[2] = {mForegroundColor, mForegroundColor2};
514  const Color textColor[2] = {mForegroundColor, mForegroundColor2};
515  mLineParts.clear();
516 
518  {
519  unsigned int x = CAST_U32(mPadding);
520  const std::string row = *(i);
521  bool wrapped = false;
522  int objects = 0;
523 
524  // Check for separator lines
525  if (row.find("---", 0) == 0)
526  {
527  const int dashWidth = fontWidthMinus;
528  for (x = CAST_U32(mPadding); x < wWidth; x ++)
529  {
530  mLineParts.push_back(LinePart(CAST_S32(x),
531  CAST_S32(y) + mItemPadding,
532  selColor[0], selColor[1], "-", false));
533  x += CAST_U32(CAST_S32(
534  dashWidth) - 2);
535  }
536 
537  y += CAST_U32(fontHeight);
538  continue;
539  }
540  else if (mEnableImages && row.find("~~~", 0) == 0)
541  {
542  std::string str = row.substr(3);
543  const size_t sz = str.size();
544  if (sz > 2 && str.substr(sz - 1) == "~")
545  str = str.substr(0, sz - 1);
546  Image *const img = Loader::getImage(str);
547  if (img != nullptr)
548  {
549  img->incRef();
550  mLineParts.push_back(LinePart(CAST_S32(x),
551  CAST_S32(y) + mItemPadding,
552  selColor[0], selColor[1], img));
553  y += CAST_U32(img->getHeight() + 2);
554  moreHeight += img->getHeight();
555  if (img->getWidth() > maxWidth)
556  maxWidth = img->getWidth() + 2;
557  }
558  continue;
559  }
560 
561  Color prevColor[2];
562  prevColor[0] = selColor[0];
563  prevColor[1] = selColor[1];
564  bold = false;
565 
566  const int xPadding = CAST_S32(mNewLinePadding) + mPadding;
567 
568  for (size_t start = 0, end = std::string::npos;
569  start != std::string::npos;
570  start = end, end = std::string::npos)
571  {
572  bool processed(false);
573 
574  // Wrapped line continuation shall be indented
575  if (wrapped)
576  {
577  y += CAST_U32(fontHeight);
578  x = CAST_U32(xPadding);
579  wrapped = false;
580  }
581 
582  size_t idx1 = end;
583  size_t idx2 = end;
584 
585  // "Tokenize" the string at control sequences
587  idx1 = row.find("##", start + 1);
588  if (start == 0 || mUseLinksAndUserColors)
589  {
590  // Check for color change in format "##x", x = [L,P,0..9]
591  if (row.find("##", start) == start && row.size() > start + 2)
592  {
593  const signed char c = row.at(start + 2);
594 
595  bool valid(false);
596  const Color col[2] =
597  {
598  getThemeCharColor(c, valid),
600  c | 0x80), valid)
601  };
602 
603  if (c == '>')
604  {
605  selColor[0] = prevColor[0];
606  selColor[1] = prevColor[1];
607  }
608  else if (c == '<')
609  {
610  prevColor[0] = selColor[0];
611  prevColor[1] = selColor[1];
612  selColor[0] = col[0];
613  selColor[1] = col[1];
614  }
615  else if (c == 'B')
616  {
617  bold = true;
618  }
619  else if (c == 'b')
620  {
621  bold = false;
622  }
623  else if (valid)
624  {
625  selColor[0] = col[0];
626  selColor[1] = col[1];
627  }
628  else
629  {
630  switch (c)
631  {
632  case '0':
633  selColor[0] = mColors[0][ColorName::BLACK];
634  selColor[1] = mColors[1][ColorName::BLACK];
635  break;
636  case '1':
637  selColor[0] = mColors[0][ColorName::RED];
638  selColor[1] = mColors[1][ColorName::RED];
639  break;
640  case '2':
641  selColor[0] = mColors[0][ColorName::GREEN];
642  selColor[1] = mColors[1][ColorName::GREEN];
643  break;
644  case '3':
645  selColor[0] = mColors[0][ColorName::BLUE];
646  selColor[1] = mColors[1][ColorName::BLUE];
647  break;
648  case '4':
649  selColor[0] = mColors[0][ColorName::ORANGE];
650  selColor[1] = mColors[1][ColorName::ORANGE];
651  break;
652  case '5':
653  selColor[0] = mColors[0][ColorName::YELLOW];
654  selColor[1] = mColors[1][ColorName::YELLOW];
655  break;
656  case '6':
657  selColor[0] = mColors[0][ColorName::PINK];
658  selColor[1] = mColors[1][ColorName::PINK];
659  break;
660  case '7':
661  selColor[0] = mColors[0][ColorName::PURPLE];
662  selColor[1] = mColors[1][ColorName::PURPLE];
663  break;
664  case '8':
665  selColor[0] = mColors[0][ColorName::GRAY];
666  selColor[1] = mColors[1][ColorName::GRAY];
667  break;
668  case '9':
669  selColor[0] = mColors[0][ColorName::BROWN];
670  selColor[1] = mColors[1][ColorName::BROWN];
671  break;
672  default:
673  selColor[0] = textColor[0];
674  selColor[1] = textColor[1];
675  break;
676  }
677  }
678 
679  if (c == '<' && link < CAST_S32(mLinks.size()))
680  {
681  int size;
682  if (bold)
683  {
684  size = boldFont->getWidth(
685  mLinks[CAST_SIZE(link)].caption) + 1;
686  }
687  else
688  {
689  size = font->getWidth(
690  mLinks[CAST_SIZE(link)].caption) + 1;
691  }
692 
693  BrowserLink &linkRef = mLinks[CAST_SIZE(
694  link)];
695  linkRef.x1 = CAST_S32(x);
696  linkRef.y1 = CAST_S32(y);
697  linkRef.x2 = linkRef.x1 + size;
698  linkRef.y2 = CAST_S32(y) + fontHeight - 1;
699  link++;
700  }
701 
702  processed = true;
703  start += 3;
704  if (start == row.size())
705  break;
706  }
707  }
708  if (mUseEmotes)
709  idx2 = row.find("%%", start + 1);
710  if (idx1 < idx2)
711  end = idx1;
712  else
713  end = idx2;
714  if (mUseEmotes)
715  {
716  // check for emote icons
717  if (row.size() > start + 2 && row.substr(start, 2) == "%%")
718  {
719  if (objects < 5)
720  {
721  const int cid = row.at(start + 2) - '0';
722  if (cid >= 0)
723  {
724  if (mEmotes != nullptr)
725  {
726  const size_t sz = mEmotes->size();
727  if (CAST_SIZE(cid) < sz)
728  {
729  Image *const img = mEmotes->get(
730  CAST_SIZE(cid));
731  if (img != nullptr)
732  {
733  mLineParts.push_back(LinePart(
734  CAST_S32(x),
735  CAST_S32(y) + mItemPadding,
736  selColor[0], selColor[1], img));
737  x += 18;
738  }
739  }
740  }
741  }
742  objects ++;
743  processed = true;
744  }
745 
746  start += 3;
747  if (start == row.size())
748  {
749  if (x > mDataWidth)
750  mDataWidth = x;
751  break;
752  }
753  }
754  }
755  const size_t len = (end == std::string::npos) ? end : end - start;
756 
757  if (start >= row.length())
758  break;
759 
760  std::string part = row.substr(start, len);
761  int width = 0;
762  if (bold)
763  width = boldFont->getWidth(part);
764  else
765  width = font->getWidth(part);
766 
767  // Auto wrap mode
768  if (wWidth > 0 &&
769  width > 0 &&
770  (x + CAST_U32(width) + 10) > wWidth)
771  {
772  bool forced = false;
773 
774  /* FIXME: This code layout makes it easy to crash remote
775  clients by talking garbage. Forged long utf-8 characters
776  will cause either a buffer underflow in substr or an
777  infinite loop in the main loop. */
778  do
779  {
780  if (!forced)
781  end = row.rfind(' ', end);
782 
783  // Check if we have to (stupidly) force-wrap
784  if (end == std::string::npos || end <= start)
785  {
786  forced = true;
787  end = row.size();
788  x += CAST_U32(hyphenWidth);
789  continue;
790  }
791 
792  // Skip to the start of the current character
793  while ((row[end] & 192) == 128)
794  end--;
795  end--; // And then to the last byte of the previous one
796 
797  part = row.substr(start, end - start + 1);
798  if (bold)
799  width = boldFont->getWidth(part);
800  else
801  width = font->getWidth(part);
802  }
803  while (end > start &&
804  width > 0 &&
805  (x + CAST_U32(width) + 10) > wWidth);
806 
807  if (forced)
808  {
809  x -= CAST_U32(hyphenWidth);
810  mLineParts.push_back(LinePart(
811  CAST_S32(wWidth) - hyphenWidth,
812  CAST_S32(y) + mItemPadding,
813  selColor[0], selColor[1], hyphen, bold));
814  end++; // Skip to the next character
815  }
816  else
817  {
818  end += 2; // Skip to after the space
819  }
820 
821  wrapped = true;
822  wrappedLines++;
823  }
824 
825  mLineParts.push_back(LinePart(CAST_S32(x),
826  CAST_S32(y) + mItemPadding,
827  selColor[0], selColor[1], part.c_str(), bold));
828 
829  if (bold)
830  width = boldFont->getWidth(part);
831  else
832  width = font->getWidth(part);
833 
834  if (width == 0 && !processed)
835  break;
836 
837  x += CAST_U32(width);
838  if (x > mDataWidth)
839  mDataWidth = x;
840  }
841  y += CAST_U32(fontHeight);
842  }
843  if (CAST_S32(wWidth) != maxWidth)
844  setWidth(maxWidth);
845 
846  return (CAST_S32(mTextRows.size()) + wrappedLines)
847  * fontHeight + moreHeight + 2 * mPadding;
848 }
849 
851 {
853  || mTextRows.size() < 3 || (mUpdateTime == 0))
854  {
856  mHeight = calcHeight();
859  }
860 }
861 
862 void BrowserBox::updateSize(const bool always)
863 {
864  if (always)
865  mUpdateTime = 0;
866  updateHeight();
867 }
868 
869 std::string BrowserBox::getTextAtPos(const int x, const int y) const
870 {
871  int textX = 0;
872  int textY = 0;
873 
874  getAbsolutePosition(textX, textY);
875  if (x < textX || y < textY)
876  return std::string();
877 
878  textY = y - textY;
879  std::string str;
880  int lastY = 0;
881 
883  {
884  const LinePart &part = *i;
885  if (part.mY + 50 < mYStart)
886  continue;
887  if (part.mY > textY)
888  break;
889 
890  if (part.mY > lastY)
891  {
892  str = part.mText;
893  lastY = part.mY;
894  }
895  else
896  {
897  str.append(part.mText);
898  }
899  }
900 
901  return str;
902 }
903 
905  const Color &color2)
906 {
907  mForegroundColor = color1;
908  mForegroundColor2 = color2;
909 }
910 
912 {
913  if (mSelectedLink <= 0)
914  mSelectedLink = CAST_S32(mLinks.size()) - 1;
915  else
916  mSelectedLink --;
917 }
918 
920 {
921  mSelectedLink ++;
922  if (mSelectedLink >= static_cast<signed int>(mLinks.size()))
923  mSelectedLink = 0;
924 }
925 
927 {
928  if ((mLinkHandler == nullptr) ||
929  mSelectedLink < 0 ||
930  mSelectedLink >= static_cast<signed int>(mLinks.size()))
931  {
932  return;
933  }
934 
936  nullptr);
937 }
938 
940 {
941  updateHeight();
942 }
#define CAST_U32
Definition: cast.h:30
Font * getFont() const
Definition: widget.cpp:330
void moveSelectionUp()
Definition: browserbox.cpp:911
#define FOR_EACH(type, iter, array)
Definition: foreach.h:24
std::string encodeLinkText(std::string data)
int width
Definition: rect.h:218
bool mEnableTabs
Definition: browserbox.h:205
bool mBold
Definition: linepart.h:99
int getWidth() const
Definition: widget.h:220
Font * boldFont
Definition: gui.cpp:111
Image * get(const size_type i) const
Definition: imageset.cpp:66
void setWidth(const int width)
Definition: widget.cpp:132
void unload(Skin *const skin)
Definition: theme.cpp:249
ClipRect & getTopClip() const
Definition: graphics.h:280
Gui * gui
Definition: gui.cpp:110
Definition: font.h:88
Color mHyperLinkColor
Definition: browserbox.h:195
LinePartList mLineParts
Definition: browserbox.h:174
unsigned int mMaxRows
Definition: browserbox.h:184
virtual void decRef()
Definition: resource.cpp:49
LinkHandler * mLinkHandler
Definition: browserbox.h:180
void replaceVars(std::string &data)
Definition: rect.h:72
unsigned int mHighlightMode
Definition: browserbox.h:182
int calcHeight()
Definition: browserbox.cpp:494
#define BLOCK_START(name)
Definition: perfomance.h:78
ImageSet * getImageSet(const std::string &imagePath, const int w, const int h)
static std::string getThemePath()
Definition: theme.h:66
void moveSelectionDown()
Definition: browserbox.cpp:919
bool mProcessVars
Definition: browserbox.h:202
Skin * load(const std::string &filename, const std::string &filename2, const bool full, const std::string &defaultPath)
Definition: theme.cpp:178
#define BLOCK_END(name)
Definition: perfomance.h:79
int yOffset
Definition: cliprect.h:126
std::list< int > mTextRowLinksCount
Definition: browserbox.h:169
Color mForegroundColor
Definition: widget.h:1085
std::string getTextAtPos(const int x, const int y) const
Definition: browserbox.cpp:869
void selectSelection()
Definition: browserbox.cpp:926
int getOption(const std::string &name) const
Definition: skin.h:105
time_t mUpdateTime
Definition: browserbox.h:188
Links mLinks
Definition: browserbox.h:178
void widgetResized(const Event &event)
Definition: browserbox.cpp:939
void mouseMoved(MouseEvent &event)
Definition: browserbox.cpp:386
bool mEnableImages
Definition: browserbox.h:203
BrowserBox(const Widget2 *const widget, const Opaque opaque, const std::string &skin)
Definition: browserbox.cpp:60
Color mColors[2][ColorName::COLORS_MAX]
Definition: browserbox.h:196
int getPadding() const
Definition: skin.h:99
const Color & getThemeCharColor(const signed char c, bool &valid) const A_INLINE
Definition: widget2.h:51
Color mBackgroundColor
Definition: widget.h:1090
virtual void setColor(const Color &color)
Definition: graphics.h:319
#define CAST_S32
Definition: cast.h:29
std::string strprintf(const char *const format,...)
Definition: stringutils.cpp:99
TextRows mTextRows
Definition: browserbox.h:168
size_type size() const
Definition: imageset.h:72
Image * mImage
Definition: linepart.h:98
Image * getImage(const std::string &idPath)
Definition: imageloader.cpp:85
unsigned char mType
Definition: linepart.h:97
static ImageSet * mEmotes
Definition: browserbox.h:207
Opaque mOpaque
Definition: browserbox.h:198
TextRows::const_iterator TextRowCIter
Definition: browserbox.h:167
int y
Definition: rect.h:213
static int mInstances
Definition: browserbox.h:208
static Color readColor(const std::string &description)
Definition: theme.cpp:696
void drawString(Graphics *const graphics, Color col, const Color &col2, const std::string &text, const int x, const int y)
Definition: font.cpp:253
virtual void handleLink(const std::string &link, MouseEvent *event)=0
#define nullptr
Definition: localconsts.h:44
bool mAllowLogic
Definition: widget.h:1159
#define CAST_S8
Definition: cast.h:25
void addMouseListener(MouseListener *const mouseListener)
Definition: widget.cpp:291
bool mAlwaysUpdate
Definition: browserbox.h:201
int mX
Definition: linepart.h:92
int height
Definition: rect.h:223
bool mEnableKeys
Definition: browserbox.h:204
volatile time_t cur_time
Definition: timer.cpp:57
virtual void getAbsolutePosition(int &x, int &y) const
Definition: widget.cpp:311
void draw(Graphics *const graphics)
Definition: browserbox.cpp:400
void addImage(const std::string &path)
Definition: browserbox.cpp:349
void safeDraw(Graphics *const graphics)
Definition: browserbox.cpp:489
void setHeight(const int height)
Definition: widget.cpp:139
void addWidgetListener(WidgetListener *const widgetListener)
Definition: widget.cpp:301
Color mHighlightColor
Definition: browserbox.h:194
std::string replaceLinkCommands(const std::string &link)
virtual void incRef()
Definition: resource.cpp:37
virtual void fillRectangle(const Rect &rectangle)=0
Theme * theme
Definition: theme.cpp:61
#define A_UNUSED
Definition: localconsts.h:159
void setFocusable(const bool focusable)
Definition: widget.cpp:191
void addRow(const std::string &row, const bool atTop)
Definition: browserbox.cpp:170
Color mForegroundColor2
Definition: widget2.h:112
virtual void drawImage(const Image *const image, int dstX, int dstY)=0
Color mColor
Definition: linepart.h:94
void removeDragged(const Widget *const widget)
Definition: gui.cpp:1161
Definition: widget.h:97
void setLinkHandler(LinkHandler *linkHandler)
Definition: browserbox.cpp:165
virtual void drawLine(int x1, int y1, int x2, int y2)=0
const bool Opaque_true
Definition: opaque.h:29
int getWidth(const std::string &text) const
Definition: font.cpp:333
Definition: event.h:77
int mPadding
Definition: browserbox.h:189
void mouseExited(MouseEvent &event)
Definition: browserbox.cpp:395
Definition: image.h:61
bool mUseEmotes
Definition: browserbox.h:200
unsigned int mNewLinePadding
Definition: browserbox.h:190
Definition: color.h:74
int getWidth() const A_INLINE
Definition: image.h:116
#define CAST_SIZE
Definition: cast.h:33
Links::iterator LinkIterator
Definition: browserbox.h:177
const Color & getThemeColor(const ThemeColorIdT type, const unsigned int alpha) const A_INLINE
Definition: widget2.h:44
int getX() const
Definition: mouseevent.h:126
void setForegroundColorAll(const Color &color1, const Color &color2)
Definition: browserbox.cpp:904
bool mUseLinksAndUserColors
Definition: browserbox.h:199
void replaceTabs(std::string &data)
int getHeight() const
Definition: font.cpp:361
Skin * mSkin
Definition: browserbox.h:181
Color mColor2
Definition: linepart.h:95
int mItemPadding
Definition: browserbox.h:191
void replaceKeys(std::string &data)
int mSelectedLink
Definition: browserbox.h:183
const std::string getStr(const std::string &str)
Definition: podict.cpp:44
Rect mDimension
Definition: widget.h:1100
PoDict * translator
Definition: podict.cpp:27
#define reportAlways(...)
Definition: checkutils.h:252
unsigned int mDataWidth
Definition: browserbox.h:192
void updateSize(const bool always)
Definition: browserbox.cpp:862
int mY
Definition: linepart.h:93
void updateHeight()
Definition: browserbox.cpp:850
void clearRows()
Definition: browserbox.cpp:358
std::string mText
Definition: linepart.h:96
int getHeight() const A_INLINE
Definition: image.h:122
void mousePressed(MouseEvent &event)
Definition: browserbox.cpp:371
LinePartList::const_iterator LinePartCIter
Definition: browserbox.h:173