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