OpenTTD
network_chat_gui.cpp
Go to the documentation of this file.
1 /* $Id$ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8  */
9 
12 #include <stdarg.h> /* va_list */
13 
14 #include "../stdafx.h"
15 #include "../strings_func.h"
16 #include "../blitter/factory.hpp"
17 #include "../console_func.h"
18 #include "../video/video_driver.hpp"
19 #include "../querystring_gui.h"
20 #include "../town.h"
21 #include "../window_func.h"
22 #include "../toolbar_gui.h"
23 #include "../core/geometry_func.hpp"
24 #include "network.h"
25 #include "network_client.h"
26 #include "network_base.h"
27 
28 #include "../widgets/network_chat_widget.h"
29 
30 #include "table/strings.h"
31 
32 #include "../safeguards.h"
33 
37 
39 static const uint NETWORK_CHAT_LINE_SPACING = 3;
40 
42 struct ChatMessage {
45  uint32 remove_time;
46 };
47 
48 /* used for chat window */
49 static ChatMessage *_chatmsg_list = nullptr;
50 static bool _chatmessage_dirty = false;
51 static bool _chatmessage_visible = false;
53 static uint MAX_CHAT_MESSAGES = 0;
54 
60 static uint8 *_chatmessage_backup = nullptr;
61 
66 static inline uint GetChatMessageCount()
67 {
68  uint i = 0;
69  for (; i < MAX_CHAT_MESSAGES; i++) {
70  if (_chatmsg_list[i].message[0] == '\0') break;
71  }
72 
73  return i;
74 }
75 
82 void CDECL NetworkAddChatMessage(TextColour colour, uint duration, const char *message, ...)
83 {
84  char buf[DRAW_STRING_BUFFER];
85  va_list va;
86 
87  va_start(va, message);
88  vseprintf(buf, lastof(buf), message, va);
89  va_end(va);
90 
92 
93  uint msg_count = GetChatMessageCount();
94  if (MAX_CHAT_MESSAGES == msg_count) {
95  memmove(&_chatmsg_list[0], &_chatmsg_list[1], sizeof(_chatmsg_list[0]) * (msg_count - 1));
96  msg_count = MAX_CHAT_MESSAGES - 1;
97  }
98 
99  ChatMessage *cmsg = &_chatmsg_list[msg_count++];
100  strecpy(cmsg->message, buf, lastof(cmsg->message));
101  cmsg->colour = (colour & TC_IS_PALETTE_COLOUR) ? colour : TC_WHITE;
102  cmsg->remove_time = _realtime_tick + duration * 1000;
103 
104  _chatmessage_dirty = true;
105 }
106 
109 {
110  _chatmsg_box.y = 3 * FONT_HEIGHT_NORMAL;
111  _chatmsg_box.height = MAX_CHAT_MESSAGES * (FONT_HEIGHT_NORMAL + NETWORK_CHAT_LINE_SPACING) + 4;
112  _chatmessage_backup = ReallocT(_chatmessage_backup, _chatmsg_box.width * _chatmsg_box.height * BlitterFactory::GetCurrentBlitter()->GetBytesPerPixel());
113 }
114 
117 {
118  MAX_CHAT_MESSAGES = _settings_client.gui.network_chat_box_height;
119 
120  _chatmsg_list = ReallocT(_chatmsg_list, _settings_client.gui.network_chat_box_height);
121  _chatmsg_box.x = 10;
122  _chatmsg_box.width = _settings_client.gui.network_chat_box_width_pct * _screen.width / 100;
124  _chatmessage_visible = false;
125 
126  for (uint i = 0; i < MAX_CHAT_MESSAGES; i++) {
127  _chatmsg_list[i].message[0] = '\0';
128  }
129 }
130 
133 {
134  /* Sometimes we also need to hide the cursor
135  * This is because both textmessage and the cursor take a shot of the
136  * screen before drawing.
137  * Now the textmessage takes his shot and paints his data before the cursor
138  * does, so in the shot of the cursor is the screen-data of the textmessage
139  * included when the cursor hangs somewhere over the textmessage. To
140  * avoid wrong repaints, we undraw the cursor in that case, and everything
141  * looks nicely ;)
142  * (and now hope this story above makes sense to you ;))
143  */
144  if (_cursor.visible &&
145  _cursor.draw_pos.x + _cursor.draw_size.x >= _chatmsg_box.x &&
146  _cursor.draw_pos.x <= _chatmsg_box.x + _chatmsg_box.width &&
147  _cursor.draw_pos.y + _cursor.draw_size.y >= _screen.height - _chatmsg_box.y - _chatmsg_box.height &&
148  _cursor.draw_pos.y <= _screen.height - _chatmsg_box.y) {
149  UndrawMouseCursor();
150  }
151 
152  if (_chatmessage_visible) {
154  int x = _chatmsg_box.x;
155  int y = _screen.height - _chatmsg_box.y - _chatmsg_box.height;
156  int width = _chatmsg_box.width;
157  int height = _chatmsg_box.height;
158  if (y < 0) {
159  height = max(height + y, min(_chatmsg_box.height, _screen.height));
160  y = 0;
161  }
162  if (x + width >= _screen.width) {
163  width = _screen.width - x;
164  }
165  if (width <= 0 || height <= 0) return;
166 
167  _chatmessage_visible = false;
168  /* Put our 'shot' back to the screen */
169  blitter->CopyFromBuffer(blitter->MoveTo(_screen.dst_ptr, x, y), _chatmessage_backup, width, height);
170  /* And make sure it is updated next time */
171  VideoDriver::GetInstance()->MakeDirty(x, y, width, height);
172 
173  _chatmessage_dirty = true;
174  }
175 }
176 
179 {
180  for (uint i = 0; i < MAX_CHAT_MESSAGES; i++) {
181  ChatMessage *cmsg = &_chatmsg_list[i];
182  if (cmsg->message[0] == '\0') continue;
183 
184  /* Message has expired, remove from the list */
185  if (cmsg->remove_time < _realtime_tick) {
186  /* Move the remaining messages over the current message */
187  if (i != MAX_CHAT_MESSAGES - 1) memmove(cmsg, cmsg + 1, sizeof(*cmsg) * (MAX_CHAT_MESSAGES - i - 1));
188 
189  /* Mark the last item as empty */
190  _chatmsg_list[MAX_CHAT_MESSAGES - 1].message[0] = '\0';
191  _chatmessage_dirty = true;
192 
193  /* Go one item back, because we moved the array 1 to the left */
194  i--;
195  }
196  }
197 }
198 
201 {
203  if (!_chatmessage_dirty) return;
204 
205  /* First undraw if needed */
207 
208  if (_iconsole_mode == ICONSOLE_FULL) return;
209 
210  /* Check if we have anything to draw at all */
211  uint count = GetChatMessageCount();
212  if (count == 0) return;
213 
214  int x = _chatmsg_box.x;
215  int y = _screen.height - _chatmsg_box.y - _chatmsg_box.height;
216  int width = _chatmsg_box.width;
217  int height = _chatmsg_box.height;
218  if (y < 0) {
219  height = max(height + y, min(_chatmsg_box.height, _screen.height));
220  y = 0;
221  }
222  if (x + width >= _screen.width) {
223  width = _screen.width - x;
224  }
225  if (width <= 0 || height <= 0) return;
226 
227  assert(blitter->BufferSize(width, height) <= (int)(_chatmsg_box.width * _chatmsg_box.height * blitter->GetBytesPerPixel()));
228 
229  /* Make a copy of the screen as it is before painting (for undraw) */
230  blitter->CopyToBuffer(blitter->MoveTo(_screen.dst_ptr, x, y), _chatmessage_backup, width, height);
231 
232  _cur_dpi = &_screen; // switch to _screen painting
233 
234  int string_height = 0;
235  for (uint i = 0; i < count; i++) {
236  SetDParamStr(0, _chatmsg_list[i].message);
237  string_height += GetStringLineCount(STR_JUST_RAW_STRING, width - 1) * FONT_HEIGHT_NORMAL + NETWORK_CHAT_LINE_SPACING;
238  }
239 
240  string_height = min(string_height, MAX_CHAT_MESSAGES * (FONT_HEIGHT_NORMAL + NETWORK_CHAT_LINE_SPACING));
241 
242  int top = _screen.height - _chatmsg_box.y - string_height - 2;
243  int bottom = _screen.height - _chatmsg_box.y - 2;
244  /* Paint a half-transparent box behind the chat messages */
245  GfxFillRect(_chatmsg_box.x, top - 2, _chatmsg_box.x + _chatmsg_box.width - 1, bottom,
246  PALETTE_TO_TRANSPARENT, FILLRECT_RECOLOUR // black, but with some alpha for background
247  );
248 
249  /* Paint the chat messages starting with the lowest at the bottom */
250  int ypos = bottom - 2;
251 
252  for (int i = count - 1; i >= 0; i--) {
253  ypos = DrawStringMultiLine(_chatmsg_box.x + 3, _chatmsg_box.x + _chatmsg_box.width - 1, top, ypos, _chatmsg_list[i].message, _chatmsg_list[i].colour, SA_LEFT | SA_BOTTOM | SA_FORCE) - NETWORK_CHAT_LINE_SPACING;
254  if (ypos < top) break;
255  }
256 
257  /* Make sure the data is updated next flush */
258  VideoDriver::GetInstance()->MakeDirty(x, y, width, height);
259 
260  _chatmessage_visible = true;
261  _chatmessage_dirty = false;
262 }
263 
270 static void SendChat(const char *buf, DestType type, int dest)
271 {
272  if (StrEmpty(buf)) return;
273  if (!_network_server) {
274  MyClient::SendChat((NetworkAction)(NETWORK_ACTION_CHAT + type), type, dest, buf, 0);
275  } else {
276  NetworkServerSendChat((NetworkAction)(NETWORK_ACTION_CHAT + type), type, dest, buf, CLIENT_ID_SERVER);
277  }
278 }
279 
281 struct NetworkChatWindow : public Window {
284  int dest;
286 
293  NetworkChatWindow(WindowDesc *desc, DestType type, int dest) : Window(desc), message_editbox(NETWORK_CHAT_LENGTH)
294  {
295  this->dtype = type;
296  this->dest = dest;
297  this->querystrings[WID_NC_TEXTBOX] = &this->message_editbox;
298  this->message_editbox.cancel_button = WID_NC_CLOSE;
299  this->message_editbox.ok_button = WID_NC_SENDBUTTON;
300 
301  static const StringID chat_captions[] = {
302  STR_NETWORK_CHAT_ALL_CAPTION,
303  STR_NETWORK_CHAT_COMPANY_CAPTION,
304  STR_NETWORK_CHAT_CLIENT_CAPTION
305  };
306  assert((uint)this->dtype < lengthof(chat_captions));
307  this->dest_string = chat_captions[this->dtype];
308 
309  this->InitNested(type);
310 
311  this->SetFocusedWidget(WID_NC_TEXTBOX);
312  InvalidateWindowData(WC_NEWS_WINDOW, 0, this->height);
313  _chat_tab_completion_active = false;
314 
316  }
317 
319  {
321  }
322 
323  void FindWindowPlacementAndResize(int def_width, int def_height) override
324  {
326  }
327 
334  const char *ChatTabCompletionNextItem(uint *item)
335  {
336  static char chat_tab_temp_buffer[64];
337 
338  /* First, try clients */
339  if (*item < MAX_CLIENT_SLOTS) {
340  /* Skip inactive clients */
341  NetworkClientInfo *ci;
342  FOR_ALL_CLIENT_INFOS_FROM(ci, *item) {
343  *item = ci->index;
344  return ci->client_name;
345  }
346  *item = MAX_CLIENT_SLOTS;
347  }
348 
349  /* Then, try townnames
350  * Not that the following assumes all town indices are adjacent, ie no
351  * towns have been deleted. */
352  if (*item < (uint)MAX_CLIENT_SLOTS + Town::GetPoolSize()) {
353  const Town *t;
354 
355  FOR_ALL_TOWNS_FROM(t, *item - MAX_CLIENT_SLOTS) {
356  /* Get the town-name via the string-system */
357  SetDParam(0, t->index);
358  GetString(chat_tab_temp_buffer, STR_TOWN_NAME, lastof(chat_tab_temp_buffer));
359  return &chat_tab_temp_buffer[0];
360  }
361  }
362 
363  return nullptr;
364  }
365 
371  static char *ChatTabCompletionFindText(char *buf)
372  {
373  char *p = strrchr(buf, ' ');
374  if (p == nullptr) return buf;
375 
376  *p = '\0';
377  return p + 1;
378  }
379 
384  {
385  static char _chat_tab_completion_buf[NETWORK_CHAT_LENGTH];
386  assert(this->message_editbox.text.max_bytes == lengthof(_chat_tab_completion_buf));
387 
388  Textbuf *tb = &this->message_editbox.text;
389  size_t len, tb_len;
390  uint item;
391  char *tb_buf, *pre_buf;
392  const char *cur_name;
393  bool second_scan = false;
394 
395  item = 0;
396 
397  /* Copy the buffer so we can modify it without damaging the real data */
398  pre_buf = (_chat_tab_completion_active) ? stredup(_chat_tab_completion_buf) : stredup(tb->buf);
399 
400  tb_buf = ChatTabCompletionFindText(pre_buf);
401  tb_len = strlen(tb_buf);
402 
403  while ((cur_name = ChatTabCompletionNextItem(&item)) != nullptr) {
404  item++;
405 
406  if (_chat_tab_completion_active) {
407  /* We are pressing TAB again on the same name, is there another name
408  * that starts with this? */
409  if (!second_scan) {
410  size_t offset;
411  size_t length;
412 
413  /* If we are completing at the begin of the line, skip the ': ' we added */
414  if (tb_buf == pre_buf) {
415  offset = 0;
416  length = (tb->bytes - 1) - 2;
417  } else {
418  /* Else, find the place we are completing at */
419  offset = strlen(pre_buf) + 1;
420  length = (tb->bytes - 1) - offset;
421  }
422 
423  /* Compare if we have a match */
424  if (strlen(cur_name) == length && strncmp(cur_name, tb->buf + offset, length) == 0) second_scan = true;
425 
426  continue;
427  }
428 
429  /* Now any match we make on _chat_tab_completion_buf after this, is perfect */
430  }
431 
432  len = strlen(cur_name);
433  if (tb_len < len && strncasecmp(cur_name, tb_buf, tb_len) == 0) {
434  /* Save the data it was before completion */
435  if (!second_scan) seprintf(_chat_tab_completion_buf, lastof(_chat_tab_completion_buf), "%s", tb->buf);
436  _chat_tab_completion_active = true;
437 
438  /* Change to the found name. Add ': ' if we are at the start of the line (pretty) */
439  if (pre_buf == tb_buf) {
440  this->message_editbox.text.Print("%s: ", cur_name);
441  } else {
442  this->message_editbox.text.Print("%s %s", pre_buf, cur_name);
443  }
444 
445  this->SetDirty();
446  free(pre_buf);
447  return;
448  }
449  }
450 
451  if (second_scan) {
452  /* We walked all possibilities, and the user presses tab again.. revert to original text */
453  this->message_editbox.text.Assign(_chat_tab_completion_buf);
454  _chat_tab_completion_active = false;
455 
456  this->SetDirty();
457  }
458  free(pre_buf);
459  }
460 
461  Point OnInitialPosition(int16 sm_width, int16 sm_height, int window_number) override
462  {
463  Point pt = { 0, _screen.height - sm_height - FindWindowById(WC_STATUS_BAR, 0)->height };
464  return pt;
465  }
466 
467  void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
468  {
469  if (widget != WID_NC_DESTINATION) return;
470 
471  if (this->dtype == DESTTYPE_CLIENT) {
472  SetDParamStr(0, NetworkClientInfo::GetByClientID((ClientID)this->dest)->client_name);
473  }
474  Dimension d = GetStringBoundingBox(this->dest_string);
477  *size = maxdim(*size, d);
478  }
479 
480  void DrawWidget(const Rect &r, int widget) const override
481  {
482  if (widget != WID_NC_DESTINATION) return;
483 
484  if (this->dtype == DESTTYPE_CLIENT) {
485  SetDParamStr(0, NetworkClientInfo::GetByClientID((ClientID)this->dest)->client_name);
486  }
487  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, this->dest_string, TC_BLACK, SA_RIGHT);
488  }
489 
490  void OnClick(Point pt, int widget, int click_count) override
491  {
492  switch (widget) {
493  case WID_NC_SENDBUTTON: /* Send */
494  SendChat(this->message_editbox.text.buf, this->dtype, this->dest);
495  FALLTHROUGH;
496 
497  case WID_NC_CLOSE: /* Cancel */
498  delete this;
499  break;
500  }
501  }
502 
503  EventState OnKeyPress(WChar key, uint16 keycode) override
504  {
505  EventState state = ES_NOT_HANDLED;
506  if (keycode == WKC_TAB) {
507  ChatTabCompletion();
508  state = ES_HANDLED;
509  }
510  return state;
511  }
512 
513  void OnEditboxChanged(int wid) override
514  {
515  _chat_tab_completion_active = false;
516  }
517 
523  void OnInvalidateData(int data = 0, bool gui_scope = true) override
524  {
525  if (data == this->dest) delete this;
526  }
527 };
528 
532  NWidget(WWT_CLOSEBOX, COLOUR_GREY, WID_NC_CLOSE),
533  NWidget(WWT_PANEL, COLOUR_GREY, WID_NC_BACKGROUND),
535  NWidget(WWT_TEXT, COLOUR_GREY, WID_NC_DESTINATION), SetMinimalSize(62, 12), SetPadding(1, 0, 1, 0), SetDataTip(STR_NULL, STR_NULL),
536  NWidget(WWT_EDITBOX, COLOUR_GREY, WID_NC_TEXTBOX), SetMinimalSize(100, 12), SetPadding(1, 0, 1, 0), SetResize(1, 0),
537  SetDataTip(STR_NETWORK_CHAT_OSKTITLE, STR_NULL),
538  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_NC_SENDBUTTON), SetMinimalSize(62, 12), SetPadding(1, 0, 1, 0), SetDataTip(STR_NETWORK_CHAT_SEND, STR_NULL),
539  EndContainer(),
540  EndContainer(),
541  EndContainer(),
542 };
543 
546  WDP_MANUAL, nullptr, 0, 0,
548  0,
549  _nested_chat_window_widgets, lengthof(_nested_chat_window_widgets)
550 );
551 
552 
559 {
561  new NetworkChatWindow(&_chat_window_desc, type, dest);
562 }
EventState
State of handling an event.
Definition: window_type.h:713
virtual void MakeDirty(int left, int top, int width, int height)=0
Mark a particular area dirty.
Container for a message.
Window to enter the chat message in.
static const PaletteID PALETTE_TO_TRANSPARENT
This sets the sprite to transparent.
Definition: sprites.h:1586
Container for all information known about a client.
Definition: network_base.h:25
static NWidgetPart SetResize(int16 dx, int16 dy)
Widget part function for setting the resize step.
Definition: widget_type.h:930
uint32 _realtime_tick
The real time in the game.
Definition: debug.cpp:50
void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode)
Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen...
Definition: gfx.cpp:112
High level window description.
Definition: window_gui.h:168
TextColour colour
The colour of the message.
uint16 network_chat_box_width_pct
width of the chat box in percent
int CDECL seprintf(char *str, const char *last, const char *format,...)
Safer implementation of snprintf; same as snprintf except:
Definition: string.cpp:409
Close button.
Offset at top to draw the frame rectangular area.
Definition: window_gui.h:64
void NetworkReInitChatBoxSize()
Initialize all font-dependent chat box sizes.
Horizontal container.
Definition: widget_type.h:75
Window * FindWindowById(WindowClass cls, WindowNumber number)
Find a window by its class and window number.
Definition: window.cpp:1114
The passed event is not handled.
Definition: window_type.h:715
int CDECL vseprintf(char *str, const char *last, const char *format, va_list ap)
Safer implementation of vsnprintf; same as vsnprintf except:
Definition: string.cpp:62
void OnEditboxChanged(int wid) override
The text in an editbox has been edited.
a textbox for typing
Definition: widget_type.h:71
Client part of the network protocol.
Tindex index
Index of this pool item.
Definition: pool_type.hpp:147
void CDECL Print(const char *format,...) WARN_FORMAT(2
Print a formatted string into the textbuffer.
Definition: textbuf.cpp:417
Close box (at top-left of a window)
Definition: widget_type.h:69
static const int DRAW_STRING_BUFFER
Size of the buffer used for drawing strings.
Definition: gfx_func.h:85
Send message/notice to only a certain client (Private)
Definition: network_type.h:83
void ChatTabCompletion()
See if we can auto-complete the current text of the user.
#define lastof(x)
Get the last element of an fixed size array.
Definition: depend.cpp:50
Helper/buffer for input fields.
Definition: textbuf_type.h:32
Base core network types and some helper functions to access them.
How all blitters should look like.
Definition: base.hpp:30
uint16 bytes
the current size of the string in bytes (including terminating &#39;\0&#39;)
Definition: textbuf_type.h:37
ClientID
&#39;Unique&#39; identifier to be given to clients
Definition: network_type.h:41
static T max(const T a, const T b)
Returns the maximum of two values.
Definition: math_func.hpp:26
bool visible
cursor is visible
Definition: gfx_type.h:141
virtual int GetBytesPerPixel()=0
Get how many bytes are needed to store a pixel.
Pure simple text.
Definition: widget_type.h:58
NetworkChatWindow(WindowDesc *desc, DestType type, int dest)
Create a chat input window.
In-game console is closed.
Definition: console_type.h:19
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
Force the alignment, i.e. don&#39;t swap for RTL languages.
Definition: gfx_func.h:108
Partial widget specification to allow NWidgets to be written nested.
Definition: widget_type.h:910
Data structure for an opened window.
Definition: window_gui.h:278
Point draw_size
position and size bounding-box for drawing
Definition: gfx_type.h:135
static NWidgetPart SetPadding(uint8 top, uint8 right, uint8 bottom, uint8 left)
Widget part function for setting additional space around a widget.
Definition: widget_type.h:1046
void SetDParamStr(uint n, const char *str)
This function is used to "bind" a C string to a OpenTTD dparam slot.
Definition: strings.cpp:281
void NetworkChatMessageLoop()
Check if a message is expired.
void NetworkDrawChatMessage()
Draw the chat message-box.
void DrawWidget(const Rect &r, int widget) const override
Draw the contents of a nested widget.
uint8 network_chat_box_height
height of the chat box in lines
static size_t GetPoolSize()
Returns first unused index.
Definition: pool_type.hpp:267
char client_name[NETWORK_CLIENT_NAME_LENGTH]
Name of the client.
Definition: network_base.h:27
Chatbox; Window numbers:
Definition: window_type.h:493
int ok_button
Widget button of parent window to simulate when pressing OK in OSK.
void OnClick(Point pt, int widget, int click_count) override
A click with the left mouse button has been made on the window.
static uint GetChatMessageCount()
Count the chat messages.
size_t Utf8TrimString(char *s, size_t maxlen)
Properly terminate an UTF8 string to some maximum length.
Definition: string.cpp:522
static char * ChatTabCompletionFindText(char *buf)
Find what text to complete.
#define FONT_HEIGHT_NORMAL
Height of characters in the normal (FS_NORMAL) font.
Definition: gfx_func.h:178
static NWidgetPart SetDataTip(uint32 data, StringID tip)
Widget part function for setting the data and tooltip.
Definition: widget_type.h:1014
Data stored about a string that can be modified in the GUI.
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:80
Apply a recolour sprite to the screen content.
Definition: gfx_type.h:285
static NWidgetPart SetMinimalSize(int16 x, int16 y)
Widget part function for setting the minimal size.
Definition: widget_type.h:947
static bool _chatmessage_dirty
Does the chat message need repainting?
Bottom align the text.
Definition: gfx_func.h:103
#define FOR_ALL_CLIENT_INFOS_FROM(var, start)
Iterate over all the clients from a given index.
Definition: network_base.h:47
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition: gfx_type.h:247
Normal push-button (no toggle button) with text caption.
Definition: widget_type.h:104
Simple depressed panel.
Definition: widget_type.h:50
int PositionNetworkChatWindow(Window *w)
(Re)position network chat window at the screen.
Definition: window.cpp:3519
int dest
The identifier of the destination.
char * stredup(const char *s, const char *last)
Create a duplicate of the given string.
Definition: string.cpp:138
static T * ReallocT(T *t_ptr, size_t num_elements)
Simplified reallocation function that allocates the specified number of elements of the given type...
Definition: alloc_func.hpp:113
EventState OnKeyPress(WChar key, uint16 keycode) override
A key has been pressed.
static PointDimension _chatmsg_box
The chatbox grows from the bottom so the coordinates are pixels from the left and pixels from the bot...
static const uint NETWORK_CHAT_LENGTH
The maximum length of a chat message, in bytes including &#39;\0&#39;.
Definition: config.h:52
static NWidgetPart NWidget(WidgetType tp, Colours col, int16 idx=-1)
Widget part function for starting a new &#39;real&#39; widget.
Definition: widget_type.h:1114
Offset at bottom to draw the frame rectangular area.
Definition: window_gui.h:65
static bool _chat_tab_completion_active
Whether tab completion is active.
int DrawString(int left, int right, int top, const char *str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition: gfx.cpp:499
const char * ChatTabCompletionNextItem(uint *item)
Find the next item of the list of things that can be auto-completed.
Basic functions/variables used all over the place.
static ChatMessage * _chatmsg_list
The actual chat message list.
Point OnInitialPosition(int16 sm_width, int16 sm_height, int window_number) override
Compute the initial position of the window.
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:42
void FindWindowPlacementAndResize(int def_width, int def_height) override
Resize window towards the default size.
static Blitter * GetCurrentBlitter()
Get the current active blitter (always set by calling SelectBlitter).
Definition: factory.hpp:147
static T min(const T a, const T b)
Returns the minimum of two values.
Definition: math_func.hpp:42
int cancel_button
Widget button of parent window to simulate when pressing CANCEL in OSK.
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:18
void DeleteWindowByClass(WindowClass cls)
Delete all windows of a given class.
Definition: window.cpp:1159
virtual void CopyToBuffer(const void *video, void *dst, int width, int height)=0
Copy from the screen to a buffer.
void Assign(StringID string)
Render a string into the textbuffer.
Definition: textbuf.cpp:398
void NetworkUndrawChatMessage()
Hide the chatbox.
Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition: gfx.cpp:698
uint32 remove_time
The time to remove the message.
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
No window, redirects to WC_MAIN_WINDOW.
Definition: window_type.h:40
void NetworkInitChatMessage()
Initialize all buffers of the chat visualisation.
virtual int BufferSize(int width, int height)=0
Calculate how much memory there is needed for an image of this size in the video-buffer.
char *const buf
buffer in which text is saved
Definition: textbuf_type.h:34
Background of the window.
void NetworkServerSendChat(NetworkAction action, DestType type, int dest, const char *msg, ClientID from_id, int64 data=0, bool from_admin=false)
Send an actual chat message.
StringID dest_string
String representation of the destination.
GUISettings gui
settings related to the GUI
uint16 max_bytes
the maximum size of the buffer in bytes (including terminating &#39;\0&#39;)
Definition: textbuf_type.h:35
static WindowDesc _chat_window_desc(WDP_MANUAL, nullptr, 0, 0, WC_SEND_NETWORK_MSG, WC_NONE, 0, _nested_chat_window_widgets, lengthof(_nested_chat_window_widgets))
The description of the chat window.
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
Update size and resize step of a widget in the window.
static bool StrEmpty(const char *s)
Check if a string buffer is empty.
Definition: string_func.h:59
int GetStringLineCount(StringID str, int maxw)
Calculates number of lines of string.
Definition: gfx.cpp:572
Specification of a rectangle with an absolute top-left coordinate and a (relative) width/height...
uint _toolbar_width
Width of the toolbar, shared by statusbar.
Definition: toolbar_gui.cpp:64
static VideoDriver * GetInstance()
Get the currently active instance of the video driver.
virtual void CopyFromBuffer(void *video, const void *src, int width, int height)=0
Copy from a buffer to the screen.
static uint8 * _chatmessage_backup
Backup in case text is moved.
static NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME, WWT_INSET, or WWT_PANEL).
Definition: widget_type.h:999
QueryString message_editbox
Message editbox.
char * strecpy(char *dst, const char *src, const char *last)
Copies characters from one buffer to another.
Definition: depend.cpp:68
Town data structure.
Definition: town.h:55
void CDECL NetworkAddChatMessage(TextColour colour, uint duration, const char *message,...)
Add a text message to the &#39;chat window&#39; to be shown.
virtual void * MoveTo(void *video, int x, int y)=0
Move the destination pointer the requested amount x and y, keeping in mind any pitch and bpp of the r...
Statusbar (at the bottom of your screen); Window numbers:
Definition: window_type.h:59
bool _network_server
network-server is active
Definition: network.cpp:55
Coordinates of a point in 2D.
static const uint MAX_CLIENT_SLOTS
The number of slots; must be at least 1 more than MAX_CLIENTS.
Definition: network_type.h:25
static void SendChat(const char *buf, DestType type, int dest)
Send an actual chat message.
Colour value is already a real palette colour index, not an index of a StringColour.
Definition: gfx_type.h:270
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: depend.cpp:131
virtual void FindWindowPlacementAndResize(int def_width, int def_height)
Resize window towards the default size.
Definition: window.cpp:1506
Offset at right to draw the frame rectangular area.
Definition: window_gui.h:63
static const uint NETWORK_NAME_LENGTH
The maximum length of the server name and map name, in bytes including &#39;\0&#39;.
Definition: config.h:42
static const NWidgetPart _nested_chat_window_widgets[]
The widgets of the chat window.
Servers always have this ID.
Definition: network_type.h:43
static uint MAX_CHAT_MESSAGES
The limit of chat messages to show.
Specification of a rectangle with absolute coordinates of all edges.
The passed event is handled.
Definition: window_type.h:714
char message[DRAW_STRING_BUFFER]
The action message.
Right align the text (must be a single bit).
Definition: gfx_func.h:98
Left align the text.
Definition: gfx_func.h:96
static const uint NETWORK_CHAT_LINE_SPACING
Spacing between chat lines.
static NetworkClientInfo * GetByClientID(ClientID client_id)
Return the CI given it&#39;s client-identifier.
Definition: network.cpp:124
static bool _chatmessage_visible
Is a chat message visible.
Manually align the window (so no automatic location finding)
Definition: window_gui.h:155
static NetworkRecvStatus SendChat(NetworkAction action, DestType type, int dest, const char *msg, int64 data)
Send a chat-packet over the network.
uint32 WChar
Type for wide characters, i.e.
Definition: string_type.h:37
Dimensions (a width and height) of a rectangle in 2D.
Offset at left to draw the frame rectangular area.
Definition: window_gui.h:62
DestType dtype
The type of destination.
DestType
Destination of our chat messages.
Definition: network_type.h:80
NetworkAction
Actions that can be used for NetworkTextMessage.
Definition: network_type.h:87
void ShowNetworkChatQueryWindow(DestType type, int dest)
Show the chat window.
void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
Mark window data of the window of a given class and specific window number as invalid (in need of re-...
Definition: window.cpp:3300
assert_compile((int) DRAW_STRING_BUFFER >=(int) NETWORK_CHAT_LENGTH+NETWORK_NAME_LENGTH+40)
The draw buffer must be able to contain the chat message, client name and the "[All]" message...
int height
Height of the window (number of pixels down in y direction)
Definition: window_gui.h:322
News window; Window numbers:
Definition: window_type.h:243
int DrawStringMultiLine(int left, int right, int top, int bottom, const char *str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly over multiple lines.
Definition: gfx.cpp:620
static void SetDParam(uint n, uint64 v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings_func.h:201