OpenTTD
network_chat_gui.cpp
Go to the documentation of this file.
1 /* $Id: network_chat_gui.cpp 27893 2017-08-13 18:38:42Z frosch $ */
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 #ifdef ENABLE_NETWORK
15 
16 #include "../stdafx.h"
17 #include "../strings_func.h"
18 #include "../blitter/factory.hpp"
19 #include "../console_func.h"
20 #include "../video/video_driver.hpp"
21 #include "../querystring_gui.h"
22 #include "../town.h"
23 #include "../window_func.h"
24 #include "../toolbar_gui.h"
25 #include "../core/geometry_func.hpp"
26 #include "network.h"
27 #include "network_client.h"
28 #include "network_base.h"
29 
30 #include "../widgets/network_chat_widget.h"
31 
32 #include "table/strings.h"
33 
34 #include "../safeguards.h"
35 
39 
41 static const uint NETWORK_CHAT_LINE_SPACING = 3;
42 
44 struct ChatMessage {
47  uint32 remove_time;
48 };
49 
50 /* used for chat window */
51 static ChatMessage *_chatmsg_list = NULL;
52 static bool _chatmessage_dirty = false;
53 static bool _chatmessage_visible = false;
55 static uint MAX_CHAT_MESSAGES = 0;
56 
62 static uint8 *_chatmessage_backup = NULL;
63 
68 static inline uint GetChatMessageCount()
69 {
70  uint i = 0;
71  for (; i < MAX_CHAT_MESSAGES; i++) {
72  if (_chatmsg_list[i].message[0] == '\0') break;
73  }
74 
75  return i;
76 }
77 
84 void CDECL NetworkAddChatMessage(TextColour colour, uint duration, const char *message, ...)
85 {
86  char buf[DRAW_STRING_BUFFER];
87  va_list va;
88 
89  va_start(va, message);
90  vseprintf(buf, lastof(buf), message, va);
91  va_end(va);
92 
94 
95  uint msg_count = GetChatMessageCount();
96  if (MAX_CHAT_MESSAGES == msg_count) {
97  memmove(&_chatmsg_list[0], &_chatmsg_list[1], sizeof(_chatmsg_list[0]) * (msg_count - 1));
98  msg_count = MAX_CHAT_MESSAGES - 1;
99  }
100 
101  ChatMessage *cmsg = &_chatmsg_list[msg_count++];
102  strecpy(cmsg->message, buf, lastof(cmsg->message));
103  cmsg->colour = (colour & TC_IS_PALETTE_COLOUR) ? colour : TC_WHITE;
104  cmsg->remove_time = _realtime_tick + duration * 1000;
105 
106  _chatmessage_dirty = true;
107 }
108 
111 {
112  _chatmsg_box.y = 3 * FONT_HEIGHT_NORMAL;
113  _chatmsg_box.height = MAX_CHAT_MESSAGES * (FONT_HEIGHT_NORMAL + NETWORK_CHAT_LINE_SPACING) + 4;
114  _chatmessage_backup = ReallocT(_chatmessage_backup, _chatmsg_box.width * _chatmsg_box.height * BlitterFactory::GetCurrentBlitter()->GetBytesPerPixel());
115 }
116 
119 {
120  MAX_CHAT_MESSAGES = _settings_client.gui.network_chat_box_height;
121 
122  _chatmsg_list = ReallocT(_chatmsg_list, _settings_client.gui.network_chat_box_height);
123  _chatmsg_box.x = 10;
124  _chatmsg_box.width = _settings_client.gui.network_chat_box_width_pct * _screen.width / 100;
126  _chatmessage_visible = false;
127 
128  for (uint i = 0; i < MAX_CHAT_MESSAGES; i++) {
129  _chatmsg_list[i].message[0] = '\0';
130  }
131 }
132 
135 {
136  /* Sometimes we also need to hide the cursor
137  * This is because both textmessage and the cursor take a shot of the
138  * screen before drawing.
139  * Now the textmessage takes his shot and paints his data before the cursor
140  * does, so in the shot of the cursor is the screen-data of the textmessage
141  * included when the cursor hangs somewhere over the textmessage. To
142  * avoid wrong repaints, we undraw the cursor in that case, and everything
143  * looks nicely ;)
144  * (and now hope this story above makes sense to you ;))
145  */
146  if (_cursor.visible &&
147  _cursor.draw_pos.x + _cursor.draw_size.x >= _chatmsg_box.x &&
148  _cursor.draw_pos.x <= _chatmsg_box.x + _chatmsg_box.width &&
149  _cursor.draw_pos.y + _cursor.draw_size.y >= _screen.height - _chatmsg_box.y - _chatmsg_box.height &&
150  _cursor.draw_pos.y <= _screen.height - _chatmsg_box.y) {
151  UndrawMouseCursor();
152  }
153 
154  if (_chatmessage_visible) {
156  int x = _chatmsg_box.x;
157  int y = _screen.height - _chatmsg_box.y - _chatmsg_box.height;
158  int width = _chatmsg_box.width;
159  int height = _chatmsg_box.height;
160  if (y < 0) {
161  height = max(height + y, min(_chatmsg_box.height, _screen.height));
162  y = 0;
163  }
164  if (x + width >= _screen.width) {
165  width = _screen.width - x;
166  }
167  if (width <= 0 || height <= 0) return;
168 
169  _chatmessage_visible = false;
170  /* Put our 'shot' back to the screen */
171  blitter->CopyFromBuffer(blitter->MoveTo(_screen.dst_ptr, x, y), _chatmessage_backup, width, height);
172  /* And make sure it is updated next time */
173  VideoDriver::GetInstance()->MakeDirty(x, y, width, height);
174 
175  _chatmessage_dirty = true;
176  }
177 }
178 
181 {
182  for (uint i = 0; i < MAX_CHAT_MESSAGES; i++) {
183  ChatMessage *cmsg = &_chatmsg_list[i];
184  if (cmsg->message[0] == '\0') continue;
185 
186  /* Message has expired, remove from the list */
187  if (cmsg->remove_time < _realtime_tick) {
188  /* Move the remaining messages over the current message */
189  if (i != MAX_CHAT_MESSAGES - 1) memmove(cmsg, cmsg + 1, sizeof(*cmsg) * (MAX_CHAT_MESSAGES - i - 1));
190 
191  /* Mark the last item as empty */
192  _chatmsg_list[MAX_CHAT_MESSAGES - 1].message[0] = '\0';
193  _chatmessage_dirty = true;
194 
195  /* Go one item back, because we moved the array 1 to the left */
196  i--;
197  }
198  }
199 }
200 
203 {
205  if (!_chatmessage_dirty) return;
206 
207  /* First undraw if needed */
209 
210  if (_iconsole_mode == ICONSOLE_FULL) return;
211 
212  /* Check if we have anything to draw at all */
213  uint count = GetChatMessageCount();
214  if (count == 0) return;
215 
216  int x = _chatmsg_box.x;
217  int y = _screen.height - _chatmsg_box.y - _chatmsg_box.height;
218  int width = _chatmsg_box.width;
219  int height = _chatmsg_box.height;
220  if (y < 0) {
221  height = max(height + y, min(_chatmsg_box.height, _screen.height));
222  y = 0;
223  }
224  if (x + width >= _screen.width) {
225  width = _screen.width - x;
226  }
227  if (width <= 0 || height <= 0) return;
228 
229  assert(blitter->BufferSize(width, height) <= (int)(_chatmsg_box.width * _chatmsg_box.height * blitter->GetBytesPerPixel()));
230 
231  /* Make a copy of the screen as it is before painting (for undraw) */
232  blitter->CopyToBuffer(blitter->MoveTo(_screen.dst_ptr, x, y), _chatmessage_backup, width, height);
233 
234  _cur_dpi = &_screen; // switch to _screen painting
235 
236  int string_height = 0;
237  for (uint i = 0; i < count; i++) {
238  SetDParamStr(0, _chatmsg_list[i].message);
239  string_height += GetStringLineCount(STR_JUST_RAW_STRING, width - 1) * FONT_HEIGHT_NORMAL + NETWORK_CHAT_LINE_SPACING;
240  }
241 
242  string_height = min(string_height, MAX_CHAT_MESSAGES * (FONT_HEIGHT_NORMAL + NETWORK_CHAT_LINE_SPACING));
243 
244  int top = _screen.height - _chatmsg_box.y - string_height - 2;
245  int bottom = _screen.height - _chatmsg_box.y - 2;
246  /* Paint a half-transparent box behind the chat messages */
247  GfxFillRect(_chatmsg_box.x, top - 2, _chatmsg_box.x + _chatmsg_box.width - 1, bottom,
248  PALETTE_TO_TRANSPARENT, FILLRECT_RECOLOUR // black, but with some alpha for background
249  );
250 
251  /* Paint the chat messages starting with the lowest at the bottom */
252  int ypos = bottom - 2;
253 
254  for (int i = count - 1; i >= 0; i--) {
255  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;
256  if (ypos < top) break;
257  }
258 
259  /* Make sure the data is updated next flush */
260  VideoDriver::GetInstance()->MakeDirty(x, y, width, height);
261 
262  _chatmessage_visible = true;
263  _chatmessage_dirty = false;
264 }
265 
272 static void SendChat(const char *buf, DestType type, int dest)
273 {
274  if (StrEmpty(buf)) return;
275  if (!_network_server) {
276  MyClient::SendChat((NetworkAction)(NETWORK_ACTION_CHAT + type), type, dest, buf, 0);
277  } else {
278  NetworkServerSendChat((NetworkAction)(NETWORK_ACTION_CHAT + type), type, dest, buf, CLIENT_ID_SERVER);
279  }
280 }
281 
283 struct NetworkChatWindow : public Window {
286  int dest;
288 
295  NetworkChatWindow(WindowDesc *desc, DestType type, int dest) : Window(desc), message_editbox(NETWORK_CHAT_LENGTH)
296  {
297  this->dtype = type;
298  this->dest = dest;
299  this->querystrings[WID_NC_TEXTBOX] = &this->message_editbox;
300  this->message_editbox.cancel_button = WID_NC_CLOSE;
301  this->message_editbox.ok_button = WID_NC_SENDBUTTON;
302 
303  static const StringID chat_captions[] = {
304  STR_NETWORK_CHAT_ALL_CAPTION,
305  STR_NETWORK_CHAT_COMPANY_CAPTION,
306  STR_NETWORK_CHAT_CLIENT_CAPTION
307  };
308  assert((uint)this->dtype < lengthof(chat_captions));
309  this->dest_string = chat_captions[this->dtype];
310 
311  this->InitNested(type);
312 
313  this->SetFocusedWidget(WID_NC_TEXTBOX);
314  InvalidateWindowData(WC_NEWS_WINDOW, 0, this->height);
315  _chat_tab_completion_active = false;
316 
318  }
319 
321  {
323  }
324 
325  virtual void FindWindowPlacementAndResize(int def_width, int def_height)
326  {
328  }
329 
336  const char *ChatTabCompletionNextItem(uint *item)
337  {
338  static char chat_tab_temp_buffer[64];
339 
340  /* First, try clients */
341  if (*item < MAX_CLIENT_SLOTS) {
342  /* Skip inactive clients */
343  NetworkClientInfo *ci;
344  FOR_ALL_CLIENT_INFOS_FROM(ci, *item) {
345  *item = ci->index;
346  return ci->client_name;
347  }
348  *item = MAX_CLIENT_SLOTS;
349  }
350 
351  /* Then, try townnames
352  * Not that the following assumes all town indices are adjacent, ie no
353  * towns have been deleted. */
354  if (*item < (uint)MAX_CLIENT_SLOTS + Town::GetPoolSize()) {
355  const Town *t;
356 
357  FOR_ALL_TOWNS_FROM(t, *item - MAX_CLIENT_SLOTS) {
358  /* Get the town-name via the string-system */
359  SetDParam(0, t->index);
360  GetString(chat_tab_temp_buffer, STR_TOWN_NAME, lastof(chat_tab_temp_buffer));
361  return &chat_tab_temp_buffer[0];
362  }
363  }
364 
365  return NULL;
366  }
367 
373  static char *ChatTabCompletionFindText(char *buf)
374  {
375  char *p = strrchr(buf, ' ');
376  if (p == NULL) return buf;
377 
378  *p = '\0';
379  return p + 1;
380  }
381 
386  {
387  static char _chat_tab_completion_buf[NETWORK_CHAT_LENGTH];
388  assert(this->message_editbox.text.max_bytes == lengthof(_chat_tab_completion_buf));
389 
390  Textbuf *tb = &this->message_editbox.text;
391  size_t len, tb_len;
392  uint item;
393  char *tb_buf, *pre_buf;
394  const char *cur_name;
395  bool second_scan = false;
396 
397  item = 0;
398 
399  /* Copy the buffer so we can modify it without damaging the real data */
400  pre_buf = (_chat_tab_completion_active) ? stredup(_chat_tab_completion_buf) : stredup(tb->buf);
401 
402  tb_buf = ChatTabCompletionFindText(pre_buf);
403  tb_len = strlen(tb_buf);
404 
405  while ((cur_name = ChatTabCompletionNextItem(&item)) != NULL) {
406  item++;
407 
408  if (_chat_tab_completion_active) {
409  /* We are pressing TAB again on the same name, is there another name
410  * that starts with this? */
411  if (!second_scan) {
412  size_t offset;
413  size_t length;
414 
415  /* If we are completing at the begin of the line, skip the ': ' we added */
416  if (tb_buf == pre_buf) {
417  offset = 0;
418  length = (tb->bytes - 1) - 2;
419  } else {
420  /* Else, find the place we are completing at */
421  offset = strlen(pre_buf) + 1;
422  length = (tb->bytes - 1) - offset;
423  }
424 
425  /* Compare if we have a match */
426  if (strlen(cur_name) == length && strncmp(cur_name, tb->buf + offset, length) == 0) second_scan = true;
427 
428  continue;
429  }
430 
431  /* Now any match we make on _chat_tab_completion_buf after this, is perfect */
432  }
433 
434  len = strlen(cur_name);
435  if (tb_len < len && strncasecmp(cur_name, tb_buf, tb_len) == 0) {
436  /* Save the data it was before completion */
437  if (!second_scan) seprintf(_chat_tab_completion_buf, lastof(_chat_tab_completion_buf), "%s", tb->buf);
438  _chat_tab_completion_active = true;
439 
440  /* Change to the found name. Add ': ' if we are at the start of the line (pretty) */
441  if (pre_buf == tb_buf) {
442  this->message_editbox.text.Print("%s: ", cur_name);
443  } else {
444  this->message_editbox.text.Print("%s %s", pre_buf, cur_name);
445  }
446 
447  this->SetDirty();
448  free(pre_buf);
449  return;
450  }
451  }
452 
453  if (second_scan) {
454  /* We walked all possibilities, and the user presses tab again.. revert to original text */
455  this->message_editbox.text.Assign(_chat_tab_completion_buf);
456  _chat_tab_completion_active = false;
457 
458  this->SetDirty();
459  }
460  free(pre_buf);
461  }
462 
463  virtual Point OnInitialPosition(int16 sm_width, int16 sm_height, int window_number)
464  {
465  Point pt = { 0, _screen.height - sm_height - FindWindowById(WC_STATUS_BAR, 0)->height };
466  return pt;
467  }
468 
469  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
470  {
471  if (widget != WID_NC_DESTINATION) return;
472 
473  if (this->dtype == DESTTYPE_CLIENT) {
474  SetDParamStr(0, NetworkClientInfo::GetByClientID((ClientID)this->dest)->client_name);
475  }
476  Dimension d = GetStringBoundingBox(this->dest_string);
479  *size = maxdim(*size, d);
480  }
481 
482  virtual void DrawWidget(const Rect &r, int widget) const
483  {
484  if (widget != WID_NC_DESTINATION) return;
485 
486  if (this->dtype == DESTTYPE_CLIENT) {
487  SetDParamStr(0, NetworkClientInfo::GetByClientID((ClientID)this->dest)->client_name);
488  }
489  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, this->dest_string, TC_BLACK, SA_RIGHT);
490  }
491 
492  virtual void OnClick(Point pt, int widget, int click_count)
493  {
494  switch (widget) {
495  case WID_NC_SENDBUTTON: /* Send */
496  SendChat(this->message_editbox.text.buf, this->dtype, this->dest);
497  FALLTHROUGH;
498 
499  case WID_NC_CLOSE: /* Cancel */
500  delete this;
501  break;
502  }
503  }
504 
505  virtual EventState OnKeyPress(WChar key, uint16 keycode)
506  {
507  EventState state = ES_NOT_HANDLED;
508  if (keycode == WKC_TAB) {
509  ChatTabCompletion();
510  state = ES_HANDLED;
511  }
512  return state;
513  }
514 
515  virtual void OnEditboxChanged(int wid)
516  {
517  _chat_tab_completion_active = false;
518  }
519 
525  virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
526  {
527  if (data == this->dest) delete this;
528  }
529 };
530 
534  NWidget(WWT_CLOSEBOX, COLOUR_GREY, WID_NC_CLOSE),
535  NWidget(WWT_PANEL, COLOUR_GREY, WID_NC_BACKGROUND),
537  NWidget(WWT_TEXT, COLOUR_GREY, WID_NC_DESTINATION), SetMinimalSize(62, 12), SetPadding(1, 0, 1, 0), SetDataTip(STR_NULL, STR_NULL),
538  NWidget(WWT_EDITBOX, COLOUR_GREY, WID_NC_TEXTBOX), SetMinimalSize(100, 12), SetPadding(1, 0, 1, 0), SetResize(1, 0),
539  SetDataTip(STR_NETWORK_CHAT_OSKTITLE, STR_NULL),
540  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_NC_SENDBUTTON), SetMinimalSize(62, 12), SetPadding(1, 0, 1, 0), SetDataTip(STR_NETWORK_CHAT_SEND, STR_NULL),
541  EndContainer(),
542  EndContainer(),
543  EndContainer(),
544 };
545 
548  WDP_MANUAL, NULL, 0, 0,
550  0,
551  _nested_chat_window_widgets, lengthof(_nested_chat_window_widgets)
552 );
553 
554 
561 {
563  new NetworkChatWindow(&_chat_window_desc, type, dest);
564 }
565 
566 #endif /* ENABLE_NETWORK */
EventState
State of handling an event.
Definition: window_type.h:701
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:1566
Container for all information known about a client.
Definition: network_base.h:27
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:48
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:398
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:1105
The passed event is not handled.
Definition: window_type.h:703
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
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:50
a textbox for typing
Definition: widget_type.h:71
virtual Point OnInitialPosition(int16 sm_width, int16 sm_height, int window_number)
Compute the initial position of the window.
Client part of the network protocol.
virtual void OnEditboxChanged(int wid)
The text in an editbox has been edited.
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:418
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:87
Send message/notice to only a certain client (Private)
Definition: network_type.h:85
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
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
Servers always have this ID.
Definition: network_type.h:45
NetworkChatWindow(WindowDesc *desc, DestType type, int dest)
Create a chat input window.
In-game console is closed.
Definition: console_type.h:19
Force the alignment, i.e. don&#39;t swap for RTL languages.
Definition: gfx_func.h:110
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:271
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:279
void NetworkChatMessageLoop()
Check if a message is expired.
void NetworkDrawChatMessage()
Draw the chat message-box.
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:29
Chatbox; Window numbers:
Definition: window_type.h:493
virtual void DrawWidget(const Rect &r, int widget) const
Draw the contents of a nested widget.
int ok_button
Widget button of parent window to simulate when pressing OK in OSK.
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:511
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:180
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:76
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:105
#define FOR_ALL_CLIENT_INFOS_FROM(var, start)
Iterate over all the clients from a given index.
Definition: network_base.h:49
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:3429
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:126
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
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.
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:42
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
virtual void OnInvalidateData(int data=0, bool gui_scope=true)
Some data on this window has become invalid.
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:1150
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:399
void NetworkUndrawChatMessage()
Hide the chatbox.
Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition: gfx.cpp:699
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 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:61
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.
ClientID
&#39;Unique&#39; identifier to be given to clients
Definition: network_type.h:43
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:57
Coordinates of a point in 2D.
virtual EventState OnKeyPress(WChar key, uint16 keycode)
A key has been pressed.
static const uint MAX_CLIENT_SLOTS
The number of slots; must be at least 1 more than MAX_CLIENTS.
Definition: network_type.h:27
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:114
virtual void FindWindowPlacementAndResize(int def_width, int def_height)
Resize window towards the default size.
Definition: window.cpp:1498
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
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
static const NWidgetPart _nested_chat_window_widgets[]
The widgets of the chat window.
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:702
char message[DRAW_STRING_BUFFER]
The action message.
Right align the text (must be a single bit).
Definition: gfx_func.h:100
Left align the text.
Definition: gfx_func.h:98
static WindowDesc _chat_window_desc(WDP_MANUAL, NULL, 0, 0, WC_SEND_NETWORK_MSG, WC_NONE, 0, _nested_chat_window_widgets, lengthof(_nested_chat_window_widgets))
The description of the chat window.
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:126
static bool _chatmessage_visible
Is a chat message visible.
virtual void FindWindowPlacementAndResize(int def_width, int def_height)
Resize window towards the default size.
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:35
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:82
NetworkAction
Actions that can be used for NetworkTextMessage.
Definition: network_type.h:89
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:3220
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:315
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