The Battle for Wesnoth  1.15.2+dev
textbox.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2018 by David White <dave@whitevine.net>
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #define GETTEXT_DOMAIN "wesnoth-lib"
16 
17 #include "widgets/textbox.hpp"
18 
19 #include "cursor.hpp"
20 #include "desktop/clipboard.hpp"
21 #include "font/sdl_ttf.hpp"
22 #include "log.hpp"
23 #include "sdl/rect.hpp"
25 #include "video.hpp"
26 
27 static lg::log_domain log_display("display");
28 #define WRN_DP LOG_STREAM(warn, log_display)
29 #define DBG_G LOG_STREAM(debug, lg::general())
30 
31 namespace gui {
32 
33 textbox::textbox(CVideo &video, int width, const std::string& text, bool editable, std::size_t max_size, int font_size, double alpha, double alpha_focus, const bool auto_join)
34  : scrollarea(video, auto_join), max_size_(max_size), font_size_(font_size), text_(unicode_cast<std::u32string>(text)),
35  cursor_(text_.size()), selstart_(-1), selend_(-1),
36  grabmouse_(false), text_pos_(0), editable_(editable),
37  show_cursor_(true), show_cursor_at_(0), text_image_(nullptr),
38  wrap_(false), line_height_(0), yscroll_(0), alpha_(alpha),
39  alpha_focus_(alpha_focus),
40  edit_target_(nullptr)
41  ,listening_(false)
42 {
43  // static const SDL_Rect area = video.screen_area();
44  // const int height = font::draw_text(nullptr,area,font_size,font::NORMAL_COLOR,"ABCD",0,0).h;
47  update_text_cache(true);
48 }
49 
51 {
52  // Restore the cursor on destruction if we (probably) set it to IBEAM
53  if(cursor::get() == cursor::IBEAM) {
55  }
56 }
57 
58 void textbox::update_location(const SDL_Rect& rect)
59 {
61  update_text_cache(true);
62  set_dirty(true);
63 }
64 
65 void textbox::set_inner_location(const SDL_Rect& rect)
66 {
67  bg_register(rect);
68  if (!text_image_) return;
69  text_pos_ = 0;
70  update_text_cache(false);
71 }
72 
73 const std::string textbox::text() const
74 {
75  const std::string &ret = unicode_cast<std::string>(text_);
76  return ret;
77 }
78 
79 // set_text does not respect max_size_
80 void textbox::set_text(const std::string& text, const color_t& color)
81 {
82  text_ = unicode_cast<std::u32string>(text);
83  cursor_ = text_.size();
84  text_pos_ = 0;
85  selstart_ = -1;
86  selend_ = -1;
87  set_dirty(true);
88  update_text_cache(true, color);
90 }
91 
92 void textbox::append_text(const std::string& text, bool auto_scroll, const color_t& color)
93 {
94  if(text_image_.get() == nullptr) {
95  set_text(text, color);
96  return;
97  }
98 
99  //disallow adding multi-line text to a single-line text box
100  if(wrap_ == false && std::find_if(text.begin(),text.end(),utils::isnewline) != text.end()) {
101  return;
102  }
103  const bool is_at_bottom = get_position() == get_max_position();
104  const std::u32string& wtext = unicode_cast<std::u32string>(text);
105 
106  surface new_text = add_text_line(wtext, color);
107  surface new_surface(std::max<std::size_t>(text_image_->w,new_text->w),text_image_->h+new_text->h);
108 
109  adjust_surface_alpha(new_text, SDL_ALPHA_TRANSPARENT);
110  adjust_surface_alpha(text_image_, SDL_ALPHA_TRANSPARENT);
111  SDL_SetSurfaceBlendMode(text_image_, SDL_BLENDMODE_NONE);
112  sdl_blit(text_image_,nullptr,new_surface,nullptr);
113  SDL_SetSurfaceBlendMode(text_image_, SDL_BLENDMODE_BLEND);
114 
115  SDL_Rect target {
116  0
117  , text_image_->h
118  , new_text->w
119  , new_text->h
120  };
121  SDL_SetSurfaceBlendMode(new_text, SDL_BLENDMODE_NONE);
122  sdl_blit(new_text,nullptr,new_surface,&target);
123  text_image_ = new_surface;
124 
125  text_.insert(text_.end(), wtext.begin(), wtext.end());
126 
127  set_dirty(true);
128  update_text_cache(false);
129  if(auto_scroll && is_at_bottom) scroll_to_bottom();
131 }
132 
134 {
135  text_.clear();
136  cursor_ = 0;
137  cursor_pos_ = 0;
138  text_pos_ = 0;
139  selstart_ = -1;
140  selend_ = -1;
141  set_dirty(true);
142  update_text_cache(true);
144 }
145 
146 void textbox::set_selection(const int selstart, const int selend)
147 {
148  if (!editable_) {
149  return;
150  }
151  if (selstart < 0 || selend < 0 || std::size_t(selstart) > text_.size() ||
152  std::size_t(selend) > text_.size()) {
153  WRN_DP << "out-of-boundary selection" << std::endl;
154  return;
155  }
156  selstart_= selstart;
157  selend_ = selend;
158  set_dirty(true);
159 }
160 
161 void textbox::set_cursor_pos(const int cursor_pos)
162 {
163  if (!editable_) {
164  return;
165  }
166  if (cursor_pos < 0 || std::size_t(cursor_pos) > text_.size()) {
167  WRN_DP << "out-of-boundary selection" << std::endl;
168  return;
169  }
170 
171  cursor_ = cursor_pos;
172  update_text_cache(false);
173  set_dirty(true);
174 }
175 
176 void textbox::draw_cursor(int pos) const
177 {
178  if(show_cursor_ && editable_ && enabled()) {
179  SDL_Rect rect {
180  location().x + pos
181  , location().y
182  , 1
183  , location().h
184  };
185 
186  sdl::fill_rectangle(rect, {255, 255, 255, 255});
187  }
188 }
189 
191 {
192  const SDL_Rect& loc = inner_location();
193 
194  surface& surf = video().getSurface();
195 
196  color_t c(0, 0, 0);
197 
198  double& alpha = focus(nullptr) ? alpha_focus_ : alpha_;
199  c.a = 255 * alpha;
200 
201  sdl::fill_rectangle(loc, c);
202 
203  SDL_Rect src;
204 
205  if(text_image_ == nullptr) {
206  update_text_cache(true);
207  }
208 
209  if(text_image_ != nullptr) {
210  src.y = yscroll_;
211  src.w = std::min<std::size_t>(loc.w,text_image_->w);
212  src.h = std::min<std::size_t>(loc.h,text_image_->h);
213  src.x = text_pos_;
214  SDL_Rect dest = video().screen_area();
215  dest.x = loc.x;
216  dest.y = loc.y;
217 
218  // Fills the selected area
219  if(enabled() && is_selection()) {
220  const int start = std::min<int>(selstart_,selend_);
221  const int end = std::max<int>(selstart_,selend_);
222  int startx = char_x_[start];
223  int starty = char_y_[start];
224  const int endx = char_x_[end];
225  const int endy = char_y_[end];
226 
227  while(starty <= endy) {
228  const std::size_t right = starty == endy ? endx : text_image_->w;
229  if(right <= std::size_t(startx)) {
230  break;
231  }
232 
233  SDL_Rect rect = sdl::create_rect(loc.x + startx
234  , loc.y + starty - src.y
235  , right - startx
236  , line_height_);
237 
238  const clip_rect_setter clipper(surf, &loc);
239 
240  color_t c2(0, 0, 160, 140);
241  sdl::fill_rectangle(rect, c2);
242 
243  starty += int(line_height_);
244  startx = 0;
245  }
246  }
247 
248  if(enabled()) {
249  sdl_blit(text_image_, &src, surf, &dest);
250  } else {
251  // HACK: using 30% opacity allows white text to look as though it is grayed out,
252  // while not changing any applicable non-grayscale AA. Actual colored text will
253  // not look as good, but this is not currently a concern since GUI1 textboxes
254  // are not used much nowadays, and they will eventually all go away.
256  sdl_blit(text_image_, &src, surf, &dest);
257  }
258  }
259 
260  draw_cursor(cursor_pos_ == 0 ? 0 : cursor_pos_ - 1);
261 }
262 
263 void textbox::set_editable(bool value)
264 {
265  editable_ = value;
266 }
267 
268 bool textbox::editable() const
269 {
270  return editable_;
271 }
272 
274 {
275  return font_size_;
276 }
277 
279 {
280  font_size_ = fs;
281 }
282 
284 {
286 }
287 
288 void textbox::set_wrap(bool val)
289 {
290  if(wrap_ != val) {
291  wrap_ = val;
292  update_text_cache(true);
293  set_dirty(true);
294  }
295 }
296 
297 void textbox::scroll(unsigned int pos)
298 {
299  yscroll_ = pos;
300  set_dirty(true);
301 }
302 
303 surface textbox::add_text_line(const std::u32string& text, const color_t& color)
304 {
306 
307  if(char_y_.empty()) {
308  char_y_.push_back(0);
309  } else {
310  char_y_.push_back(char_y_.back() + line_height_);
311  }
312 
313  char_x_.push_back(0);
314 
315  // Re-calculate the position of each glyph. We approximate this by asking the
316  // width of each substring, but this is a flawed assumption which won't work with
317  // some more complex scripts (that is, RTL languages). This part of the work should
318  // actually be done by the font-rendering system.
319  std::string visible_string;
320  std::u32string wrapped_text;
321 
322  std::u32string::const_iterator backup_itor = text.end();
323 
324  std::u32string::const_iterator itor = text.begin();
325  while(itor != text.end()) {
326  //If this is a space, save copies of the current state so we can roll back
327  if(char(*itor) == ' ') {
328  backup_itor = itor;
329  }
330  visible_string.append(unicode_cast<std::string>(*itor));
331 
332  if(char(*itor) == '\n') {
333  backup_itor = text.end();
334  visible_string = "";
335  }
336 
337  int w = font::line_width(visible_string, font_size_);
338 
339  if(wrap_ && w >= inner_location().w) {
340  if(backup_itor != text.end()) {
341  int backup = itor - backup_itor;
342  itor = backup_itor + 1;
343  if(backup > 0) {
344  char_x_.erase(char_x_.end()-backup, char_x_.end());
345  char_y_.erase(char_y_.end()-backup, char_y_.end());
346  wrapped_text.erase(wrapped_text.end()-backup, wrapped_text.end());
347  }
348  } else {
349  if (visible_string == std::string("").append(unicode_cast<std::string>(*itor))) {
350  break; //breaks infinite loop where when running with a fake display, we word wrap a single character infinitely.
351  }
352  }
353  backup_itor = text.end();
354  wrapped_text.push_back(char32_t('\n'));
355  char_x_.push_back(0);
356  char_y_.push_back(char_y_.back() + line_height_);
357  visible_string = "";
358  } else {
359  wrapped_text.push_back(*itor);
360  char_x_.push_back(w);
361  char_y_.push_back(char_y_.back() + (char(*itor) == '\n' ? line_height_ : 0));
362  ++itor;
363  }
364  }
365 
366  const std::string s = unicode_cast<std::string>(wrapped_text);
367  const surface res(font::get_rendered_text(s, font_size_, color));
368 
369  return res;
370 }
371 
372 
373 void textbox::update_text_cache(bool changed, const color_t& color)
374 {
375  if(changed) {
376  char_x_.clear();
377  char_y_.clear();
378 
379  text_image_ = add_text_line(text_, color);
380  }
381 
382  int cursor_x = char_x_[cursor_];
383 
384  if(cursor_x - text_pos_ > location().w) {
385  text_pos_ = cursor_x - location().w;
386  } else if(cursor_x - text_pos_ < 0) {
387  text_pos_ = cursor_x;
388  }
389  cursor_pos_ = cursor_x - text_pos_;
390 
391  if (text_image_) {
394  }
395 }
396 
398 {
399  return (selstart_ != -1) && (selend_ != -1) && (selstart_ != selend_);
400 }
401 
403 {
404  if(!is_selection())
405  return;
406 
407  std::u32string::iterator itor = text_.begin() + std::min(selstart_, selend_);
408  text_.erase(itor, itor + std::abs(selend_ - selstart_));
409  cursor_ = std::min(selstart_, selend_);
410  selstart_ = selend_ = -1;
411 }
412 
413 namespace {
414  const unsigned int copypaste_modifier =
415 #ifdef __APPLE__
416  KMOD_LGUI | KMOD_RGUI
417 #else
418  KMOD_CTRL
419 #endif
420  ;
421 }
422 
423 bool textbox::requires_event_focus(const SDL_Event* event) const
424 {
425  if(!focus_ || hidden() || !enabled()) {
426  return false;
427  }
428  if(event == nullptr) {
429  //when event is not specified, signal that focus may be desired later
430  return true;
431  }
432 
433  if(event->type == SDL_KEYDOWN) {
434  SDL_Keycode key = event->key.keysym.sym;
435  switch(key) {
436  case SDLK_UP:
437  case SDLK_DOWN:
438  case SDLK_PAGEUP:
439  case SDLK_PAGEDOWN:
440  //in the future we may need to check for input history or multi-line support
441  //for now, just return false since these events are not handled.
442  return false;
443  default:
444  return true;
445  }
446  }
447  //mouse events are processed regardless of focus
448  return false;
449 }
450 
451 void textbox::handle_event(const SDL_Event& event)
452 {
454  handle_event(event, false);
455 }
456 
457 bool textbox::handle_text_input(const SDL_Event& event)
458 {
459  bool changed = false;
460  std::string str = event.text.text;
461  std::u32string s = unicode_cast<std::u32string>(str);
462 
463  DBG_G << "Char: " << str << "\n";
464 
465  if (editable_) {
466  changed = true;
467  if (is_selection())
468  erase_selection();
469 
470  if (text_.size() + 1 <= max_size_) {
471 
472  text_.insert(text_.begin() + cursor_, s.begin(), s.end());
473  cursor_ += s.size();
474  }
475  } else {
476  pass_event_to_target(event);
477  }
478  return changed;
479 }
480 
481 bool textbox::handle_key_down(const SDL_Event &event)
482 {
483  bool changed = false;
484 
485  const SDL_Keysym& key = reinterpret_cast<const SDL_KeyboardEvent&>(event).keysym;
486  const SDL_Keymod modifiers = SDL_GetModState();
487 
488  const int c = key.sym;
489  const int old_cursor = cursor_;
490 
491  listening_ = true;
492 
493  if(editable_) {
494  if(c == SDLK_LEFT && cursor_ > 0)
495  --cursor_;
496 
497  if(c == SDLK_RIGHT && cursor_ < static_cast<int>(text_.size()))
498  ++cursor_;
499 
500  // ctrl-a, ctrl-e and ctrl-u are readline style shortcuts, even on Macs
501  if(c == SDLK_END || (c == SDLK_e && (modifiers & KMOD_CTRL)))
502  cursor_ = text_.size();
503 
504  if(c == SDLK_HOME || (c == SDLK_a && (modifiers & KMOD_CTRL)))
505  cursor_ = 0;
506 
507  if((old_cursor != cursor_) && (modifiers & KMOD_SHIFT)) {
508  if(selstart_ == -1)
509  selstart_ = old_cursor;
510  selend_ = cursor_;
511  }
512  } else if(c == SDLK_LEFT || c == SDLK_RIGHT || c == SDLK_END || c == SDLK_HOME) {
513  pass_event_to_target(event);
514  }
515 
516  if(editable_) {
517  if(c == SDLK_BACKSPACE) {
518  changed = true;
519  if(is_selection()) {
520  erase_selection();
521  } else if(cursor_ > 0) {
522  --cursor_;
523  text_.erase(text_.begin()+cursor_);
524  }
525  }
526 
527  if(c == SDLK_u && (modifiers & KMOD_CTRL)) { // clear line
528  changed = true;
529  cursor_ = 0;
530  text_.resize(0);
531  }
532 
533  if(c == SDLK_DELETE && !text_.empty()) {
534  changed = true;
535  if(is_selection()) {
536  erase_selection();
537  } else {
538  if(cursor_ < static_cast<int>(text_.size())) {
539  text_.erase(text_.begin()+cursor_);
540  }
541  }
542  }
543  } else if(c == SDLK_BACKSPACE || c == SDLK_DELETE || (c == SDLK_u && (modifiers & KMOD_CTRL))) {
544  pass_event_to_target(event);
545  }
546 
547 
548  //movement characters may have a "Unicode" field on some platforms, so ignore it.
549  if(!(c == SDLK_UP || c == SDLK_DOWN || c == SDLK_LEFT || c == SDLK_RIGHT ||
550  c == SDLK_DELETE || c == SDLK_BACKSPACE || c == SDLK_END || c == SDLK_HOME ||
551  c == SDLK_PAGEUP || c == SDLK_PAGEDOWN)) {
552  if((event.key.keysym.mod & copypaste_modifier)
553  //on windows SDL fires for AltGr lctrl+ralt (needed to access @ etc on certain keyboards)
554 #ifdef _WIN32
555  && !(event.key.keysym.mod & KMOD_ALT)
556 #endif
557  ) {
558  switch(c) {
559  case SDLK_v: // paste
560  {
561  if(!editable()) {
562  pass_event_to_target(event);
563  break;
564  }
565 
566  changed = true;
567  if(is_selection())
568  erase_selection();
569 
570  std::string str = desktop::clipboard::copy_from_clipboard(false);
571 
572  //cut off anything after the first newline
573  str.erase(std::find_if(str.begin(),str.end(),utils::isnewline),str.end());
574 
575  std::u32string s = unicode_cast<std::u32string>(str);
576 
577  if(text_.size() < max_size_) {
578  if(s.size() + text_.size() > max_size_) {
579  s.resize(max_size_ - text_.size());
580  }
581  text_.insert(text_.begin()+cursor_, s.begin(), s.end());
582  cursor_ += s.size();
583  }
584 
585  }
586 
587  break;
588 
589  case SDLK_c: // copy
590  {
591  if(is_selection())
592  {
593  const std::size_t beg = std::min<std::size_t>(std::size_t(selstart_),std::size_t(selend_));
594  const std::size_t end = std::max<std::size_t>(std::size_t(selstart_),std::size_t(selend_));
595 
596  std::u32string ws(text_.begin() + beg, text_.begin() + end);
597  std::string s = unicode_cast<std::string>(ws);
599  }
600  }
601  break;
602 
603  case SDLK_x: // cut
604  {
605  if(is_selection())
606  {
607  const size_t beg = std::min<size_t>(size_t(selstart_),size_t(selend_));
608  const size_t end = std::max<size_t>(size_t(selstart_),size_t(selend_));
609 
610  std::u32string ws(text_.begin() + beg, text_.begin() + end);
611  std::string s = unicode_cast<std::string>(ws);
613  erase_selection();
614  }
615  break;
616  }
617  case SDLK_a: // selectall
618  {
619  set_selection(0, text_.size());
620  break;
621  }
622  }//end switch
623  }
624  else {
625  pass_event_to_target(event);
626  }
627  }
628 
629  return changed;
630 }
631 
632 void textbox::handle_event(const SDL_Event& event, bool was_forwarded)
633 {
634  if(!enabled())
635  return;
636 
638  if(hidden())
639  return;
640 
641  bool changed = false;
642 
643  const int old_selstart = selstart_;
644  const int old_selend = selend_;
645 
646  //Sanity check: verify that selection start and end are within text
647  //boundaries
648  if(is_selection() && !(std::size_t(selstart_) <= text_.size() && std::size_t(selend_) <= text_.size())) {
649  WRN_DP << "out-of-boundary selection" << std::endl;
650  selstart_ = selend_ = -1;
651  }
652 
653  int mousex, mousey;
654  const uint8_t mousebuttons = SDL_GetMouseState(&mousex,&mousey);
655  if(!(mousebuttons & SDL_BUTTON(1))) {
656  grabmouse_ = false;
657  }
658 
659  const SDL_Rect& loc = inner_location();
660 
661  const bool mouse_inside = sdl::point_in_rect(mousex, mousey, loc);
662 
663  // Someone else may set the mouse cursor for us to something unusual (e.g.
664  // the WAIT cursor) so we ought to mess with that only if it's set to
665  // NORMAL or IBEAM.
666 
667  if(mouse_inside && cursor::get() == cursor::NORMAL) {
669  } else if(!mouse_inside && cursor::get() == cursor::IBEAM) {
671  }
672 
673  bool clicked_inside = !mouse_locked() && (event.type == SDL_MOUSEBUTTONDOWN
674  && (mousebuttons & SDL_BUTTON(1))
675  && mouse_inside);
676  if(clicked_inside) {
677  set_focus(true);
678  }
679  if ((grabmouse_ && (!mouse_locked() && event.type == SDL_MOUSEMOTION)) || clicked_inside) {
680  const int x = mousex - loc.x + text_pos_;
681  const int y = mousey - loc.y;
682  int pos = 0;
683  int distance = x;
684 
685  for(unsigned int i = 1; i < char_x_.size(); ++i) {
686  if(static_cast<int>(yscroll_) + y < char_y_[i]) {
687  break;
688  }
689 
690  // Check individually each distance (if, one day, we support
691  // RTL languages, char_x_[c] may not be monotonous.)
692  if(std::abs(x - char_x_[i]) < distance && yscroll_ + y < char_y_[i] + line_height_) {
693  pos = i;
694  distance = std::abs(x - char_x_[i]);
695  }
696  }
697 
698  cursor_ = pos;
699 
700  if(grabmouse_)
701  selend_ = cursor_;
702 
703  update_text_cache(false);
704 
705  if(!grabmouse_ && (mousebuttons & SDL_BUTTON(1))) {
706  grabmouse_ = true;
708  } else if (! (mousebuttons & SDL_BUTTON(1))) {
709  grabmouse_ = false;
710  }
711 
712  set_dirty();
713  }
714 
715  //if we don't have the focus, then see if we gain the focus,
716  //otherwise return
717  if(!was_forwarded && focus(&event) == false) {
718  if (!mouse_locked() && event.type == SDL_MOUSEMOTION && sdl::point_in_rect(mousex, mousey, loc))
719  events::focus_handler(this);
720 
721  return;
722  }
723 
724  const int old_cursor = cursor_;
725 
726  if (event.type == SDL_TEXTINPUT && listening_) {
727  changed = handle_text_input(event);
728  } else
729  if (event.type == SDL_KEYDOWN) {
730  changed = handle_key_down(event);
731  }
732  else {
733  if(event.type != SDL_KEYDOWN || (!was_forwarded && focus(&event) != true)) {
734  draw();
735  return;
736  }
737  }
738 
739 
740  if(is_selection() && (selend_ != cursor_))
741  selstart_ = selend_ = -1;
742 
743  //since there has been cursor activity, make the cursor appear for
744  //at least the next 500ms.
745  show_cursor_ = true;
746  show_cursor_at_ = SDL_GetTicks();
747 
748  if(changed || old_cursor != cursor_ || old_selstart != selstart_ || old_selend != selend_) {
749  text_image_ = nullptr;
751  }
752 
753  set_dirty(true);
754 }
755 
756 void textbox::pass_event_to_target(const SDL_Event& event)
757 {
759  edit_target_->handle_event(event, true);
760  }
761 }
762 
764 {
765  edit_target_ = target;
766 }
767 
768 } //end namespace gui
bool is_selection()
Definition: textbox.cpp:397
double alpha_focus_
Definition: textbox.hpp:91
SDL_Surface * get() const
Definition: surface.hpp:99
std::vector< int > char_x_
Definition: textbox.hpp:74
bool enabled() const
Definition: widget.cpp:202
void set_shown_size(unsigned h)
Definition: scrollarea.cpp:109
virtual void update_location(const SDL_Rect &rect)
Definition: textbox.cpp:58
void set(CURSOR_TYPE type)
Use the default parameter to reset cursors.
Definition: cursor.cpp:175
void set_edit_target(textbox *target)
Definition: textbox.cpp:763
int cursor_pos_
Definition: textbox.hpp:73
textbox(CVideo &video, int width, const std::string &text="", bool editable=true, std::size_t max_size=256, int font_size=font::SIZE_PLUS, double alpha=0.4, double alpha_focus=0.2, const bool auto_join=true)
Definition: textbox.cpp:33
std::string copy_from_clipboard(const bool)
Copies text from the clipboard.
Definition: clipboard.cpp:40
const std::string text() const
Definition: textbox.cpp:73
bool hidden() const
Definition: widget.cpp:188
#define DBG_G
Definition: textbox.cpp:29
void pass_event_to_target(const SDL_Event &event)
Definition: textbox.cpp:756
int font_size() const
Definition: textbox.cpp:273
Definition: video.hpp:31
void draw_cursor(int pos) const
Definition: textbox.cpp:176
ucs4_convert_impl::enableif< TD, typename TS::value_type >::type unicode_cast(const TS &source)
bool grabmouse_
Definition: textbox.hpp:70
General purpose widgets.
int selstart_
Definition: textbox.hpp:68
virtual void update_location(const SDL_Rect &rect)
Definition: scrollarea.cpp:46
void set_focus(bool focus)
Definition: widget.cpp:139
virtual void draw_contents()
Definition: textbox.cpp:190
STL namespace.
#define h
virtual ~textbox()
Definition: textbox.cpp:50
void set_scroll_rate(unsigned r)
Definition: scrollarea.cpp:123
surface text_image_
Definition: textbox.hpp:84
std::vector< int > char_y_
Definition: textbox.hpp:74
-file util.hpp
textbox * edit_target_
Definition: textbox.hpp:93
surface & getSurface()
Returns a reference to the framebuffer.
Definition: video.cpp:459
std::size_t max_size_
Definition: textbox.hpp:60
std::u32string text_
Definition: textbox.hpp:64
void set_measurements(int w, int h)
Definition: widget.cpp:119
bool requires_event_focus(const SDL_Event *event=nullptr) const
Definition: textbox.cpp:423
void set_cursor_pos(const int cursor_pos)
Definition: textbox.cpp:161
void set_full_size(unsigned h)
Definition: scrollarea.cpp:116
void set_dirty(bool dirty=true)
Definition: widget.cpp:207
void append_text(const std::string &text, bool auto_scroll=false, const color_t &color=font::NORMAL_COLOR)
Definition: textbox.cpp:92
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:86
void focus_handler(const sdl_handler *ptr)
Definition: events.cpp:396
void adjust_surface_alpha(surface &surf, fixed_t amount)
Definition: utils.cpp:1086
virtual void handle_event(const SDL_Event &)
Definition: widget.cpp:330
void set_wrap(bool val)
Definition: textbox.cpp:288
void set_position(unsigned pos)
Definition: scrollarea.cpp:94
#define WRN_DP
Definition: textbox.cpp:28
bool focus(const SDL_Event *event)
Definition: widget.cpp:147
int show_cursor_at_
Definition: textbox.hpp:83
bool handle_text_input(const SDL_Event &event)
Definition: textbox.cpp:457
const SDL_Rect & location() const
Definition: widget.cpp:134
bool editable() const
Definition: textbox.cpp:268
void set_editable(bool value)
Definition: textbox.cpp:263
void erase_selection()
Definition: textbox.cpp:402
void scroll_to_bottom()
Definition: textbox.cpp:283
bool handle_key_down(const SDL_Event &event)
Definition: textbox.cpp:481
void update_text_cache(bool reset=false, const color_t &color=font::NORMAL_COLOR)
Definition: textbox.cpp:373
void bg_register(const SDL_Rect &rect)
Definition: widget.cpp:99
uint8_t a
Alpha value.
Definition: color.hpp:186
void set_font_size(int fs)
Definition: textbox.cpp:278
bool listening_
Definition: textbox.hpp:99
static lg::log_domain log_display("display")
int get_max_height(int size)
Definition: sdl_ttf.cpp:407
bool point_in_rect(int x, int y, const SDL_Rect &rect)
Tests whether a point is inside a rectangle.
Definition: rect.cpp:22
lu_byte right
Definition: lparser.cpp:1027
int text_pos_
Definition: textbox.hpp:72
#define ftofxp(x)
IN: float or int - OUT: fixed_t.
Definition: math.hpp:297
bool show_cursor_
Definition: textbox.hpp:78
void handle_event(const SDL_Event &event, bool was_forwarded)
Definition: textbox.cpp:632
std::size_t i
Definition: function.cpp:933
void set_selection(const int selstart, const int selend)
Definition: textbox.cpp:146
surface add_text_line(const std::u32string &text, const color_t &color=font::NORMAL_COLOR)
Definition: textbox.cpp:303
static map_location::DIRECTION s
virtual void handle_event(const SDL_Event &event)
Definition: scrollarea.cpp:150
SDL_Rect inner_location() const
Definition: scrollarea.cpp:137
bool focus_
Definition: widget.hpp:96
void clear()
Definition: textbox.cpp:133
unsigned get_max_position() const
Definition: scrollarea.cpp:89
CURSOR_TYPE get()
Definition: cursor.cpp:215
surface get_rendered_text(const std::string &str, int size, const color_t &color, int style)
Definition: sdl_ttf.cpp:333
virtual void draw()
Definition: widget.cpp:269
int w
virtual void scroll(unsigned int pos)
Definition: textbox.cpp:297
bool mouse_locked() const
Definition: widget.cpp:62
bool isnewline(const char c)
std::size_t yscroll_
Definition: textbox.hpp:88
std::size_t line_height_
Definition: textbox.hpp:88
CVideo & video() const
Definition: widget.hpp:83
void set_text(const std::string &text, const color_t &color=font::NORMAL_COLOR)
Definition: textbox.cpp:80
SDL_Rect create_rect(const int x, const int y, const int w, const int h)
Creates an SDL_Rect with the given dimensions.
Definition: rect.hpp:39
void copy_to_clipboard(const std::string &text, const bool)
Copies text to the clipboard.
Definition: clipboard.cpp:35
Contains the SDL_Rect helper code.
bool editable_
Definition: textbox.hpp:76
void fill_rectangle(const SDL_Rect &rect, const color_t &color)
Draws a filled rectangle.
Definition: rect.cpp:65
Standard logging facilities (interface).
EXIT_STATUS start(const std::string &filename, bool take_screenshot, const std::string &screenshot_filename)
Main interface for launching the editor from the title screen.
Definition: editor_main.cpp:28
bool wrap_
Definition: textbox.hpp:86
void sdl_blit(const surface &src, SDL_Rect *src_rect, surface &dst, SDL_Rect *dst_rect)
Definition: utils.hpp:33
mock_char c
SDL_Rect screen_area(bool as_pixels=true) const
Returns the current window renderer area, either in pixels or screen coordinates. ...
Definition: video.cpp:286
const int font_size
Definition: button.cpp:40
int line_width(const std::string &line, int font_size, int style)
Determine the width of a line of text given a certain font size.
Definition: sdl_ttf.cpp:416
std::string::const_iterator iterator
Definition: tokenizer.hpp:24
unsigned get_position() const
Definition: scrollarea.cpp:84
virtual void set_inner_location(const SDL_Rect &)
Definition: textbox.cpp:65
virtual void handle_text_changed(const std::u32string &)
Definition: textbox.hpp:58
int font_size_
Definition: textbox.hpp:62
double alpha_
Definition: textbox.hpp:90