FS2_Open
Open source remastering of the Freespace 2 engine
chatbox.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) Volition, Inc. 1999. All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 
12 
13 #include "cfile/cfile.h"
14 #include "cmdline/cmdline.h"
15 #include "gamesnd/gamesnd.h"
16 #include "globalincs/alphacolors.h"
17 #include "io/key.h"
18 #include "missionui/chatbox.h"
19 #include "network/multi.h"
20 #include "network/multi_pmsg.h"
21 #include "network/multimsgs.h"
22 #include "network/multiui.h"
23 #include "parse/parselo.h"
24 #include "playerman/player.h"
25 #include "ui/ui.h"
26 
27 
28 
30 // Chat window UI
32 
33 // a little extra spacing for the team vs. team icons
34 #define CHATBOX_TEAM_ICON_SPACE 18
35 
36 // SMALL CHATBOX ----------------------------------------------------------------------------------
37 
38 // background bitmap
40  "Chatbox", // GR_640
41  "2_Chatbox" // GR_1024
42 };
43 
44 // background mask
46  "Chatbox-m", // GR_640
47  "2_Chatbox-m" // GR_1024
48 };
49 
50 // chatbox coords
52  { // GR_640
53  192, 0
54  },
55  { // GR_1024
56  308, 0 // ?
57  }
58 };
59 
60 // display area coods
62  { // GR_640
64  },
65  { // GR_1024
67  }
68 };
69 
70 // input box coords
72  { // GR_640
73  204, 100, 371, 22
74  },
75  { // GR_1024
76  328, 163, 591, 34
77  }
78 };
79 
80 // max # of lines
82  7, // GR_640
83  12 // GR_1024
84 };
85 
86 // BIG CHATBOX ----------------------------------------------------------------------------------
87 
88 // background bitmap
90  "ChatboxBig", // GR_640
91  "2_ChatboxBig" // GR_1024
92 };
93 
94 // mask
96  "Chatbox-m", // GR_640
97  "2_Chatbox-m" // GR_1024
98 };
99 
100 // chatbox coords
102  { // GR_640
103  192, 0
104  },
105  { // GR_1024
106  307, 0
107  }
108 };
109 
110 // display area coords
112  { // GR_640
114  },
115  { // GR_1024
117  }
118 };
119 
120 // input box coords
122  { // GR_640
123  204, 352, 371, 22
124  },
125  { // GR_1024
126  328, 565, 591, 34
127  }
128 };
129 
130 // max # of lines
132  32, // GR_640
133  51 // GR_1024
134 };
135 
136 // PAUSED CHATBOX ----------------------------------------------------------------------------------
137 
138 // mask
140  "MPPause", // GR_640
141  "2_MPPause" // GR_1024
142 };
143 
144 // mask
146  "MPPause-m", // GR_640
147  "2_MPPause-m" // GR_1024
148 };
149 
150 // chatbox coords
152  { // GR_640
153  // 192, 0
154  0, 0
155  },
156  { // GR_1024
157  // 307, 0
158  0, 0
159  }
160 };
161 
162 // display area coords
164  { // GR_640
165  103 + CHATBOX_TEAM_ICON_SPACE, 149, 380 - CHATBOX_TEAM_ICON_SPACE, 143
166  },
167  { // GR_1024
168  165 + CHATBOX_TEAM_ICON_SPACE, 244, 654 - CHATBOX_TEAM_ICON_SPACE, 263
169  }
170 };
171 
172 // input box coords
174  { // GR_640
175  106, 328, 379, 17
176  },
177  { // GR_1024
178  165, 525, 607, 27
179  }
180 };
181 
182 // max # of lines
184  17, // GR_640
185  26 // GR_1024
186 };
187 
188 // defines for location and other info of chat box MULTI_PAUSED
189 /*
190 #define CHATBOX_MP_FNAME NOX("MPPause")
191 #define CHATBOX_MP_MASK NOX("MPPause-m")
192 #define CHATBOX_MP_X1 112
193 #define CHATBOX_MP_Y1 198
194 #define CHATBOX_MP_X2 477
195 #define CHATBOX_MP_Y2 308
196 #define CHATBOX_MP_ICON_X (CHATBOX_MP_X1)
197 #define CHATBOX_MP_W (CHATBOX_MP_X2 - CHATBOX_MP_X1 + 1)
198 #define CHATBOX_MP_H (CHATBOX_MP_Y2 - CHATBOX_MP_Y1 + 1)
199 #define CHATBOX_MP_BEGIN_X (CHATBOX_MP_X1 + 3 + CHATBOX_TEAM_ICON_SPACE)
200 #define CHATBOX_MP_BEGIN_Y CHATBOX_MP_Y1
201 #define CHATBOX_MP_DISP_W 365
202 #define CHATBOX_MP_MAX_LINES 11
203 #define CHATBOX_MP_INPUTBOX_X (CHATBOX_MP_X1 + 3)
204 #define CHATBOX_MP_INPUTBOX_W (CHATBOX_MP_W)
205 #define CHATBOX_MP_TEXTENTER_Y 329
206 */
207 
208 // CHATBOX ----------------------------------------------------------------------------------
209 
210 // the settings being used for this instance
211 char Chatbox_mask[50];
226 
227 // how many pixels to indent succesive lines of text from a given player
228 #define CHAT_LINE_INDENT 20
229 
230 // what chars other than letters and number's we'll toss
231 #define CHATBOX_INVALID_CHARS NOX("~`") // this is primarily so that we don't interfere with the voice recording keys
232 
233 // common defines and data
234 #define CHATBOX_STRING_LEN (CALLSIGN_LEN + CHATBOX_MAX_LEN + 32)
238 
239 // button controls
240 #define CHATBOX_NUM_BUTTONS 3
241 #define CHATBOX_SCROLL_UP 0
242 #define CHATBOX_SCROLL_DOWN 1
243 #define CHATBOX_TOGGLE_SIZE 2 // used for both big and small
244 
245 // coordinate indicies
246 #define CHATBOX_X_COORD 0
247 #define CHATBOX_Y_COORD 1
248 #define CHATBOX_W_COORD 2
249 #define CHATBOX_H_COORD 3
250 
251 // chatbox buttons
253  { // GR_640
254  ui_button_info("CHB_00", 613, 3, -1, -1, 0),
255  ui_button_info("CHB_01", 613, 41, -1, -1, 1),
256  ui_button_info("CHB_02a", 607, 74, -1, -1, 2),
257  ui_button_info("CHB_02b", 607, 74, -1, -1, 2),
258  },
259  { // GR_1024
260  ui_button_info("2_CHB_00", 981, 5, -1, -1, 0),
261  ui_button_info("2_CHB_01", 981, 67, -1, -1, 1),
262  ui_button_info("2_CHB_02a", 971, 119, -1, -1, 2),
263  ui_button_info("2_CHB_02b", 971, 119, -1, -1, 2),
264  }
265 };
266 
268 
269 int Chatbox_bitmap = -1;
274 
276 // Chat window text
278 #define MAX_BRIEF_CHAT_LINES 60 // how many lines we can store in the scrollback buffer
279 #define BRIEF_DISPLAY_SPACING 2 // pixel spacing between chat lines
280 
281 // the first byte of the text string will be the net player id of the
284 
290 
291 // chatbox line recall data
292 #define CHATBOX_MAX_RECALL_LINES 10
297 
299 // forward declarations
301 void chatbox_chat_init();
303 void chatbox_set_mode(int mode_flags);
304 void chatbox_toggle_size();
306 void chat_autosplit_line(char *msg,char *remainder);
308 void chatbox_recall_add(char *string);
309 void chatbox_recall_up();
310 void chatbox_recall_down();
311 
312 // set the chatbox mode without checking for any previous modes which may need to be handled specially
313 void chatbox_set_mode(int mode_flags)
314 {
315  int size;
316 
317  // set the stored mode
318  Chatbox_mode_flags = mode_flags;
319 
320  // small pregame chatbox
322  size = 0;
323  }
324  // big pregame chatbox
326  size = 1;
327  }
328  // multiplayer paused
329  else {
330  size = 2;
331  }
332 
333  // set up the display/init variables based upon what mode we chode
334  switch(size){
335  case 0:
349  break;
350 
351  case 1:
365  break;
366 
367  case 2:
380  break;
381  }
382 }
383 
385 {
386  if (msg[0] != '/') {
387  return MULTI_MSG_ALL;
388  }
389 
390  if (!strnicmp (msg, "/f:", 3)) {
391  return MULTI_MSG_FRIENDLY;
392  }
393 
394  if (!strnicmp (msg, "/h:", 3)) {
395  return MULTI_MSG_HOSTILE;
396  }
397 
398  return MULTI_MSG_EXPR;
399 }
400 
402 {
403  if ((msg[0] != '/') && (strchr(msg, ':') != NULL) ) {
404  return -1;
405  }
406 
407  // find the first space
408  return strcspn(msg, ":") + 1 ;
409 
410 }
411 
412 // automatically split up any input text, send it, and leave the remainder
414 {
415  char *remainder,msg[150];
416  char temp[150];
417  int msg_pixel_width;
418  int target, target_length = -1;
419 
420  // if the chat line is getting too long, fire off the message, putting the last
421  // word on the next input line.
422  memset(msg,0,150);
423  Chat_inputbox.get_text(msg);
424  remainder = "";
425 
426  // check if this message is supposed to have a recipient
427  target = chatbox_get_msg_target_type(msg);
428  target_length = chatbox_get_msg_target_length(msg);
429 
430  // determine if the width of the string in pixels is > than the inputbox width -- if so,
431  // then send the message
432  gr_get_string_size(&msg_pixel_width, NULL, msg);
433  // if ( msg_pixel_width >= (Chatbox_inputbox_w - Player->short_callsign_width) ) {
434  if ( msg_pixel_width >= (Chatbox_inputbox_w - 25)) {
435  remainder = strrchr(msg, ' ');
436  if ( remainder ) {
437  *remainder = '\0';
438  remainder++;
439  } else {
440  remainder = "";
441  }
442  // if I'm the server, then broadcast the packet
443  chatbox_recall_add(msg);
444 
445  if (target != MULTI_MSG_EXPR) {
446  send_game_chat_packet(Net_player, msg, target);
447  }
448  else {
449  // copy the name of the player the message is being sent to
450  strncpy(temp, msg+1, target_length-2);
451  temp[target_length-2] = '\0';
452  send_game_chat_packet(Net_player, msg, target, NULL, temp);
453  }
455 
456  if (target != MULTI_MSG_ALL) {
457  // we need to add the target the message is going to before we add the rest of the string
458  strncpy(temp, msg, target_length);
459  temp[target_length] = ' ';
460  temp[target_length+1] = '\0';
461  strcat_s(temp, remainder);
462  Chat_inputbox.set_text(temp);
463  }
464  else {
465  // display any remainder of text on the next line
466  Chat_inputbox.set_text(remainder);
467  }
468  } else if((Chat_inputbox.pressed() && (msg[0] != '\0')) || (strlen(msg) >= CHATBOX_MAX_LEN)) {
469  // tack on the null terminator in the boundary case
470  int x = strlen(msg);
471  if(x >= CHATBOX_MAX_LEN){
472  msg[CHATBOX_MAX_LEN-1] = '\0';
473  }
474 
475  // if I'm the server, then broadcast the packet
476  chatbox_recall_add(msg);
477  if (target != MULTI_MSG_EXPR) {
478  send_game_chat_packet(Net_player, msg, target);
479  }
480  else {
481  // copy the name of the player the message is being sent to
482  strncpy(temp, msg+1, target_length-2);
483  temp[target_length-2] = '\0';
484  send_game_chat_packet(Net_player, msg, target, NULL, temp);
485  }
486 
488 
489  // display any remainder of text on the next line
490  Chat_inputbox.set_text(remainder);
491  }
492 }
493 
494 // initialize all chatbox details with the given mode flags
495 int chatbox_create(int mode_flags)
496 {
497  int idx;
498 
499  // don't do anything if the chatbox is already initialized
500  if (Chatbox_created){
501  return -1;
502  }
503 
504  // probably shouldn't be using the chatbox in single player mode
506 
507  // setup all data to correspond to our mode flags
508  chatbox_set_mode(mode_flags);
509 
510  // initialize all low-level details related to chatting
512 
513  // attempt to load in the chatbox background bitmap
518 
523  } else {
525  }
526 
527  if((Chatbox_bitmap == -1) || (Chatbox_small_bitmap == -1) || (Chatbox_big_bitmap == -1) || (Chatbox_mp_bitmap == -1)){
528  return -1;
529  }
530  }
531 
532  // attempt to create the ui window for the chatbox and assign the mask
533  Chat_window.create( 0, 0, gr_screen.max_w_unscaled, gr_screen.max_h_unscaled, 0 );
534  Chat_window.set_mask_bmap(Chatbox_mask);
535 
536  // create the chat text enter input area
538  Chat_inputbox.set_focus();
540 
541  // if we're supposed to supply and check for out own buttons
542  if((Chatbox_mode_flags & CHATBOX_FLAG_BUTTONS) && (Chatbox_mode_flags & CHATBOX_FLAG_DRAW_BOX)){
543  for(idx=0; idx<CHATBOX_NUM_BUTTONS; idx++){
544  // create the button
545  Chatbox_buttons[gr_screen.res][idx].button.create(&Chat_window, "", Chatbox_buttons[gr_screen.res][idx].x, Chatbox_buttons[gr_screen.res][idx].y, 60, 30, (idx == CHATBOX_TOGGLE_SIZE) ? 0 : 1);
546 
547  // set the highlight action
549 
550  // set the bitmap
551  Chatbox_buttons[gr_screen.res][idx].button.set_bmaps(Chatbox_buttons[gr_screen.res][idx].filename);
552 
553  // set the hotspot
554  Chatbox_buttons[gr_screen.res][idx].button.link_hotspot(Chatbox_buttons[gr_screen.res][idx].hotspot);
555  }
556 
557  // now create the toggle size button with the appropriate button
560  } else {
562  }
563  }
564 
565  // an invisible button that will set focus to input box when clicked on
566  Chat_enter_text.create( &Chat_window, "", 0, 0, 60, 30, 0);
567  Chat_enter_text.hide(); // button doesn't show up
568  Chat_enter_text.link_hotspot(50);
569 
570  Chatbox_created = 1;
571  return 0;
572 }
573 
574 // process this frame for the chatbox
575 int chatbox_process(int key_in)
576 {
577  int key_out;
578 
579  key_out = key_in;
580 
581  // if the chatbox hasn't explicitly been created, we can't do any processing
582  if(!Chatbox_created){
583  return key_out;
584  }
585 
586  // process the incoming key appropriately
587  if (key_in == -1) {
588  key_out = Chat_window.process();
589  } else {
590  key_out = Chat_window.process(key_in);
591  }
592 
593  // look for special keypresses
594  switch(key_out){
595  // line recall up one
596  case KEY_UP:
598  key_out = 0;
599  break;
600 
601  // line recall down one
602  case KEY_DOWN:
604  key_out = 0;
605  break;
606  }
607 
608  // if we're supposed to be checking our own scroll buttons
610  if ( Chatbox_buttons[gr_screen.res][CHATBOX_SCROLL_UP].button.pressed() ) {
612  }
613 
614  if ( Chatbox_buttons[gr_screen.res][CHATBOX_SCROLL_DOWN].button.pressed() ) {
616  }
617 
618  if ( Chatbox_buttons[gr_screen.res][CHATBOX_TOGGLE_SIZE].button.pressed() ){
620  }
621  }
622 
623  // check to see if the enter text button has been pressed
624  if ( Chat_enter_text.pressed() ) {
625  Chat_inputbox.set_focus();
626  }
627 
628  // check to see if the current input text needs to be split up and sent automaticall
630 
631  return key_out;
632 }
633 
635 {
636  if (!Chatbox_created)
637  return;
638 
639  // destory the UI window
640  Chat_window.destroy();
641 
642  // unload any bitmaps
643  if (Chatbox_small_bitmap != -1) {
646  }
647 
648  if (Chatbox_big_bitmap != -1) {
650  Chatbox_big_bitmap = -1;
651  }
652 
653  if (Chatbox_mp_bitmap != -1) {
655  Chatbox_mp_bitmap = -1;
656  }
657 
658  // clear all the text lines in the
659  chatbox_clear();
660  Chatbox_created = 0;
661 }
662 
663 // shutdown all chatbox functionality
665 {
666  // only do this if we have valid data
667  if(Chatbox_created){
668  // clear all chat data
673 
674  // clear all line recall data
677  Chatbox_recall_last = -1;
679  }
680 }
681 
682 // render the chatbox for this frame
684 {
685  if (!Chatbox_created){
686  return;
687  }
688 
689  // clear the multiplayer chat window
690  // gr_set_clip(Chatbox_x1, Chatbox_y1, Chatbox_w, Chatbox_h, GR_RESIZE_MENU);
691  // gr_clear();
692  // gr_reset_clip();
693 
694  // draw the background bitmap if we're supposed to
698  }
699 
700  // render the chat lines
702 
703  // render any UI window stuff
704  Chat_window.draw();
705 }
706 
707 // try and scroll the chatbox up. return 0 or 1 on fail or success
709 {
712 
713  // check to make sure we won't be going "up" above the "beginning" of the text array
716  return 1;
717  }
718 
719  }
720  return 0;
721 }
722 
723 // try and scroll the chatbox down, return 0 or 1 on fail or success
725 {
726  int idx;
727  int next;
728 
730  // yuck. There's got to be a better way to do this.
732  for(idx = 1;idx <= Chatbox_max_lines; idx++){
733  next = Brief_chat_next_index[next];
734  }
735 
736  // check to make sure we won't be going "down" below the "bottom" of the text array
739  return 1;
740  }
741  }
742  return 0;
743 }
744 
745 // quick explanation as to how the scrolling works :
746 // Brief_chat_next_index is an array A of size n, where A[i] = i+1 and A[n] = 0
747 // Brief_chat_prev_index is an array A of size n, where A[i] = i-1 and A[0] = n
748 // in other words, if you increment an integer i = A[i], you get the next index (or the prev)
749 // with wrapping. In this way, as chat lines are entered, they are continuously wrapped
750 // around the Brief_chat_lines array so we can keep it at a fixed size. These arrays are used
751 // for both entering new chat strings as well as moving the Brief_start_display_index
752 // integer, which is self-explanatory
753 
755 {
756  int idx;
757 
758  chatbox_clear();
759 
760  // setup the wraparound arrays
761  for(idx=0;idx<MAX_BRIEF_CHAT_LINES;idx++){
762  Brief_chat_next_index[idx] = idx+1;
763  }
764  Brief_chat_next_index[MAX_BRIEF_CHAT_LINES-1]=0;
765 
766  for(idx=MAX_BRIEF_CHAT_LINES-1; idx > 0 ; idx--){
767  Brief_chat_prev_index[idx] = idx - 1;
768  }
769  Brief_chat_prev_index[0] = MAX_BRIEF_CHAT_LINES-1;
770 
771  // initialize the line recall data
774  Chatbox_recall_last = -1;
776 }
777 
778 // int Test_color = 0;
779 void chatbox_add_line(const char *msg, int pid, int add_id)
780 {
781  int backup;
782  int n_lines,idx;
783  int n_chars[3];
784  const char *p_str[3]; // for the initial line (unindented)
785  char msg_extra[CHATBOX_STRING_LEN];
786 
787  if(!Chatbox_created){
788  return;
789  }
790 
791  // maybe stick on who sent the message
792  if(add_id){
793  if(MULTI_STANDALONE(Net_players[pid])){
794  sprintf(msg_extra, NOX("%s %s"), NOX("<SERVER>"), msg );
795  } else {
796  sprintf(msg_extra, NOX("%s: %s"), Net_players[pid].m_player->short_callsign, msg );
797  }
798  } else {
799  strcpy_s(msg_extra,msg);
800  }
801  Assert(strlen(msg_extra) < (CHATBOX_STRING_LEN - 2));
802 
803  // split the text up into as many lines as necessary
804  n_lines = split_str(msg_extra, Chatbox_disp_w, n_chars, p_str, 3);
805  Assert(n_lines != -1);
806 
807  // setup the first line -- be sure to clear out the line
809 
810  // add the player id #
811  Brief_chat_lines[Brief_current_add_line][0] = (char)(pid % 16);
812  // Brief_chat_lines[Brief_current_add_line][0] = (char)Test_color;
813  // Test_color = (Test_color == MAX_PLAYERS - 1) ? 0 : Test_color++;
814 
815  // set the indent to 0
817 
818  // copy in the chars
819  strncpy(&Brief_chat_lines[Brief_current_add_line][1],p_str[0],CHATBOX_STRING_LEN - 1);
820  if(n_chars[0] >= CHATBOX_STRING_LEN){
822  } else {
823  Brief_chat_lines[Brief_current_add_line][n_chars[0] + 1] = '\0';
824  }
825 
826  // increment the total line count if we haven't reached the max already
829  }
830 
831  // get the index of the next string to add text to
832  Brief_current_add_line = Brief_chat_next_index[Brief_current_add_line];
833 
834  // if we have more than 1 line, re-split everything so that the rest are indented
835  if(n_lines > 1){
836  // split up the string after the first break-marker
837  n_lines = split_str(msg_extra + n_chars[0],Chatbox_disp_w - CHAT_LINE_INDENT,n_chars,p_str,3);
838  Assert(n_lines != -1);
839 
840  // setup these remaining lines
841  for(idx=0;idx<n_lines;idx++){
842  // add the player id#
843  Brief_chat_lines[Brief_current_add_line][0] = (char)(pid % 16);
844 
845  // add the proper indent
847 
848  // copy in the line text itself
849  strncpy(&Brief_chat_lines[Brief_current_add_line][1],p_str[idx],CHATBOX_STRING_LEN-1);
850  if(n_chars[idx] >= CHATBOX_STRING_LEN){
852  } else {
853  Brief_chat_lines[Brief_current_add_line][n_chars[idx] + 1] = '\0';
854  }
855 
856  // increment the total line count if we haven't reached the max already
859  }
860 
861  // get the index of the next line to add text to
862  Brief_current_add_line = Brief_chat_next_index[Brief_current_add_line];
863  }
864  }
865 
866  // COMMAND LINE OPTION
867  if(Cmdline_multi_stream_chat_to_file && Multi_chat_stream!=NULL && msg[0] != '\0'){ // stream to the file if we're supposed to
870  }
871 
872  // if this line of text is from the player himself, automatically go to the bottom of
873  // the chat list
874  if(pid == MY_NET_PLAYER_NUM){
877  for(backup = 1;backup <= Chatbox_max_lines;backup++){
879  }
880  }
881  }
882  // if we have enough lines of text to require scrolling, scroll down by one.
883  else {
885  }
886 }
887 
889 {
890  int started_at,player_num,count,ly,line_height;
891 
892  started_at = Brief_start_display_index;
893  count = 0;
894  ly = Chatbox_begin_y;
895  line_height = gr_get_font_height() + 1;
896  while((count < Chatbox_max_lines) && (count < Num_brief_chat_lines)){
897  // determine what player this chat line came from, and set the appropriate text color
898  player_num = Brief_chat_lines[started_at][0];
899 
900  // print the line out
901  gr_set_color_fast(Color_netplayer[player_num]);
902 
903  // draw the first line (no indent)
905 
906  // if we're in a team vs. team game, blit the player color icon
908  switch(Net_players[player_num].p_info.team){
909  case 0 :
910  // if he's a team captain
911  if(Net_players[player_num].flags & NETINFO_FLAG_TEAM_CAPTAIN){
915  }
916  }
917  // just you're average peon
918  else {
919  if(Multi_common_icons[MICON_TEAM0] != -1){
922  }
923  }
924  break;
925  case 1 :
926  // if he's a team captain
927  if(Net_players[player_num].flags & NETINFO_FLAG_TEAM_CAPTAIN){
931  }
932  }
933  // just your average peon
934  else {
935  if(Multi_common_icons[MICON_TEAM1] != -1){
938  }
939  }
940  break;
941  }
942  }
943 
944  // increment the count and line position
945  count++;
946  ly += line_height;
947 
948  // increment the started at index
949  started_at = Brief_chat_next_index[started_at];
950  }
951 }
952 
954 {
955  // if we're in "small" mode
958 
959  // play a sound
961  }
962  // if we're in "big" mode
965 
966  // play a sound
968  }
969 }
970 
972 {
973  int count_diff;
974 
975  // if the chatbox is now big, move the starting display index _up_ as far as possible
977  // if we've wrapped around or we have more chatlines then we can display, move back as far as we can
980  while(count_diff > 0){
982  count_diff--;
983  }
984  }
985  // otherwise start displaying from position 0
986  else {
988  }
989  }
990  // if the chatbox is now small, move the starting display index down as far as we need
992  count_diff = chatbox_num_displayed_lines();
993  // if we were displaying more lines than we can now
994  if(count_diff > Chatbox_max_lines){
995  count_diff -= Chatbox_max_lines;
996  while(count_diff > 0){
998  count_diff--;
999  }
1000  }
1001  }
1002 }
1003 
1005 {
1007  int count;
1008 
1009  // count the lines up
1010  count = 0;
1011  while(idx != Brief_current_add_line){
1012  idx = Brief_chat_next_index[idx];
1013  count++;
1014  }
1015 
1016  return count;
1017 }
1018 
1019 // force the chatbox to go into small mode (if its in large mode) - will not wotk if in multi paused chatbox mode
1021 {
1022  int new_mode_flags;
1023 
1024  // don't do anything unless we're currently in "big" mode
1026  return;
1027  }
1028 
1029  new_mode_flags = Chatbox_mode_flags;
1030 
1031  // switch to the appropriate mode
1032  new_mode_flags &= ~(CHATBOX_FLAG_SMALL | CHATBOX_FLAG_BIG);
1033  new_mode_flags |= CHATBOX_FLAG_SMALL;
1035 
1036  // flip the up/down arrow
1038 
1039  // call this to set everything up correctly
1040  chatbox_set_mode(new_mode_flags);
1041 
1042  // change the location of the input box
1044  Chat_inputbox.set_focus();
1045 
1046  // adjust what line we start displaying from based upon the new size of the window
1048 }
1049 
1050 // force the chatbox to go into big mode (if its in small mode) - will not work if in multi paused chatbox mode
1052 {
1053  int new_mode_flags;
1054 
1055  // don't do anything unless we're currently in "small" mode
1057  return;
1058  }
1059 
1060  new_mode_flags = Chatbox_mode_flags;
1061 
1062  // switch to the appropriate mode
1063  new_mode_flags &= ~(CHATBOX_FLAG_SMALL | CHATBOX_FLAG_BIG);
1064  new_mode_flags |= CHATBOX_FLAG_BIG;
1066 
1067  // flip the up/down arrow
1069 
1070  // call this to set everything up correctly
1071  chatbox_set_mode(new_mode_flags);
1072 
1073  // change the location of the input box
1075  Chat_inputbox.set_focus();
1076 
1077  // adjust what line we start displaying from based upon the new size of the window
1079 }
1080 
1081 // "lose" the focus on the chatbox inputbox
1083 {
1084  if(!Chatbox_created){
1085  return;
1086  }
1087 
1088  // clear the focus on the inputbox
1089  Chat_inputbox.clear_focus();
1090 }
1091 
1092 // return if the inputbox for the chatbox currently has focus
1094 {
1095  return Chat_inputbox.has_focus();
1096 }
1097 
1098 // grab the focus for the chatbox inputbox
1100 {
1101  Chat_inputbox.set_focus();
1102 }
1103 
1104 // return if the inputbox was pressed - "clicked on"
1106 {
1107  return Chat_inputbox.pressed();
1108 }
1109 
1110 // add the string to the line recall list
1111 void chatbox_recall_add(char *string)
1112 {
1113  int idx;
1114 
1115  // aleays reset the recall index when adding
1117  Chatbox_recall_last = -1;
1118 
1119  // if this string matches the last string we entered, don't add it again
1120  if(!strcmp(string,Chatbox_recall_lines[0])){
1121  return;
1122  }
1123 
1124  // move all items up (this works fine for small #'s of recall lines
1125  for(idx=CHATBOX_MAX_RECALL_LINES-1;idx > 0;idx--){
1127  }
1128 
1129  // copy the new item into spot 0
1130  strcpy_s(Chatbox_recall_lines[0],string);
1131 
1132  // increment the recall count if necessary
1135  }
1136 }
1137 
1138 // user has pressed the "up" key
1140 {
1141  // if we've got no recall lines, do nothing
1142  if(Chatbox_recall_count <= 0){
1143  return;
1144  }
1145 
1146  // if we can increment up
1148  // if this is the last line we recalled, pre-increment
1152  }
1153  // otherwise, post increment
1154  else {
1157  }
1158  }
1159  // if we can't increment up
1160  else {
1163  }
1164 }
1165 
1166 // user has pressed the "down" key
1168 {
1169  // if we've got no recall lines, do nothing
1170  if(Chatbox_recall_count <= 0){
1171  return;
1172  }
1173 
1174  // if we can decrement down
1175  if(Chatbox_recall_index > 0){
1176  // if this is the last line we recalled, pre-decrement
1180  }
1181  // otherwise post,decrement
1182  else {
1185  }
1186  }
1187  // if we can't decrement down
1188  else {
1189  Chat_inputbox.set_text("");
1190  Chatbox_recall_last = -1;
1191  }
1192 }
1193 
1194 // reset all timestamps associated with the chatbox
1196 {
1197  int idx;
1198 
1199  // if there is no chatbox created, do nothing
1200  if(!Chatbox_created){
1201  return;
1202  }
1203 
1204  // otherwise clear all timestamps on all the buttons
1205  for(idx=0; idx<CHATBOX_NUM_BUTTONS+1; idx++){
1206  Chatbox_buttons[gr_screen.res][idx].button.reset_timestamps();
1207  }
1208 }
void set_text(const char *in)
Definition: inputbox.cpp:490
void set_highlight_action(void(*_user_function)(void))
Definition: button.cpp:375
int Chatbox_bitmap
Definition: chatbox.cpp:269
#define MY_NET_PLAYER_NUM
Definition: multi.h:127
#define UI_INPUTBOX_FLAG_EAT_USED
Definition: ui.h:40
int chatbox_create(int mode_flags)
Definition: chatbox.cpp:495
int Chatbox_mode_flags
Definition: chatbox.cpp:267
int Chatbox_begin_y
Definition: chatbox.cpp:218
void chatbox_chat_init()
Definition: chatbox.cpp:754
#define KEY_DOWN
Definition: key.h:180
int Game_mode
Definition: systemvars.cpp:24
#define CHATBOX_SCROLL_DOWN
Definition: chatbox.cpp:242
int x
Definition: ui.h:658
#define MULTI_MSG_FRIENDLY
Definition: multi_pmsg.h:28
#define CHATBOX_MAX_RECALL_LINES
Definition: chatbox.cpp:292
#define CHATBOX_SCROLL_UP
Definition: chatbox.cpp:241
#define GR_RESIZE_MENU
Definition: 2d.h:684
net_player * Net_player
Definition: multi.cpp:94
INT64 INT64 INT64 remainder
Definition: wglext.h:660
#define CHATBOX_TEAM_ICON_SPACE
Definition: chatbox.cpp:34
int y
Definition: ui.h:658
CFILE * Multi_chat_stream
Definition: multi.cpp:111
int Chatbox_recall_last
Definition: chatbox.cpp:295
#define CHATBOX_Y_COORD
Definition: chatbox.cpp:247
int Chatbox_inputbox_w
Definition: chatbox.cpp:222
#define MULTI_STANDALONE(np)
Definition: multi.h:139
#define MICON_TEAM1
Definition: multiui.h:58
#define CHATBOX_NUM_BUTTONS
Definition: chatbox.cpp:240
#define CHAT_LINE_INDENT
Definition: chatbox.cpp:228
Assert(pm!=NULL)
int Chatbox_small_coords[GR_NUM_RESOLUTIONS][2]
Definition: chatbox.cpp:51
#define GR_NUM_RESOLUTIONS
Definition: 2d.h:651
__inline void gr_string(int x, int y, const char *string, int resize_mode=GR_RESIZE_FULL)
Definition: 2d.h:769
int Chatbox_p_input_coords[GR_NUM_RESOLUTIONS][4]
Definition: chatbox.cpp:173
int Chatbox_textenter_y
Definition: chatbox.cpp:223
int res
Definition: 2d.h:370
int max_h_unscaled
Definition: 2d.h:361
#define CHATBOX_MAX_LEN
Definition: chatbox.h:18
void clear_focus()
Definition: gadget.cpp:328
int Chatbox_recall_count
Definition: chatbox.cpp:293
void chatbox_toggle_size_adjust_lines()
Definition: chatbox.cpp:971
#define MAX_BRIEF_CHAT_LINES
Definition: chatbox.cpp:278
void set_focus()
Definition: gadget.cpp:321
int Chatbox_created
Definition: chatbox.cpp:273
int chatbox_scroll_down()
Definition: chatbox.cpp:724
int Chatbox_begin_x
Definition: chatbox.cpp:217
int chatbox_pressed()
Definition: chatbox.cpp:1105
#define CHATBOX_FLAG_BIG
Definition: chatbox.h:22
int Chat_scroll_up_coord[2]
Definition: chatbox.cpp:224
virtual void hide(int n)
Definition: gadget.cpp:207
void gr_set_color_fast(color *dst)
Definition: 2d.cpp:1197
int chatbox_num_displayed_lines()
Definition: chatbox.cpp:1004
Definition: ui.h:195
#define CHATBOX_W_COORD
Definition: chatbox.cpp:248
void gr_set_bitmap(int bitmap_num, int alphablend_mode, int bitblt_mode, float alpha)
Definition: 2d.cpp:2105
GLsizeiptr size
Definition: Glext.h:5496
int max_w_unscaled
Definition: 2d.h:361
#define CHATBOX_FLAG_BUTTONS
Definition: chatbox.h:25
int chatbox_get_msg_target_length(char *msg)
Definition: chatbox.cpp:401
int bm_release(int handle, int clear_render_targets)
Frees both a bitmap's data and it's associated slot.
Definition: bmpman.cpp:2603
int Num_brief_chat_lines
Definition: chatbox.cpp:287
char Brief_chat_lines[MAX_BRIEF_CHAT_LINES][CHATBOX_STRING_LEN]
Definition: chatbox.cpp:282
int Brief_chat_prev_index[MAX_BRIEF_CHAT_LINES]
Definition: chatbox.cpp:286
void chatbox_recall_add(char *string)
Definition: chatbox.cpp:1111
int chatbox_get_msg_target_type(char *msg)
Definition: chatbox.cpp:384
int cfwrite_char(char b, CFILE *file)
Definition: cfile.cpp:1361
void destroy()
Definition: window.cpp:189
int Chatbox_mp_bitmap
Definition: chatbox.cpp:272
void chatbox_force_big()
Definition: chatbox.cpp:1051
int Chatbox_h
Definition: chatbox.cpp:216
void set_mask_bmap(char *fname)
Definition: window.cpp:75
int set_bmaps(char *ani_filename, int nframes=3, int start_frame=1)
Definition: gadget.cpp:71
void chatbox_reset_timestamps()
Definition: chatbox.cpp:1195
void chatbox_render()
Definition: chatbox.cpp:683
int type_flags
Definition: multi.h:493
void chatbox_recall_up()
Definition: chatbox.cpp:1139
#define CHATBOX_FLAG_SMALL
Definition: chatbox.h:21
UI_WINDOW Chat_window
Definition: chatbox.cpp:235
#define GM_MULTIPLAYER
Definition: systemvars.h:18
int pressed()
Definition: inputbox.cpp:479
void send_game_chat_packet(net_player *from, const char *msg, int msg_mode, net_player *to, const char *expr, int server_msg)
Definition: multimsgs.cpp:615
int Chat_scroll_down_coord[2]
Definition: chatbox.cpp:225
#define strnicmp(s1, s2, n)
Definition: config.h:272
netgame_info Netgame
Definition: multi.cpp:97
int hotspot
Definition: ui.h:659
int pressed()
Definition: button.cpp:325
int cfwrite_string(const char *buf, CFILE *file)
Definition: cfile.cpp:1366
void chatbox_force_small()
Definition: chatbox.cpp:1020
void chatbox_set_mode(int mode_flags)
Definition: chatbox.cpp:313
sprintf(buf,"(%f,%f,%f)", v3->xyz.x, v3->xyz.y, v3->xyz.z)
#define NG_TYPE_TEAM
Definition: multi.h:650
int Brief_chat_next_index[MAX_BRIEF_CHAT_LINES]
Definition: chatbox.cpp:285
UI_INPUTBOX Chat_inputbox
Definition: chatbox.cpp:236
#define CHATBOX_STRING_LEN
Definition: chatbox.cpp:234
int Chatbox_small_display_coords[GR_NUM_RESOLUTIONS][4]
Definition: chatbox.cpp:61
int Brief_start_display_index
Definition: chatbox.cpp:289
char * Chatbox_p_bitmap_mask_fname[GR_NUM_RESOLUTIONS]
Definition: chatbox.cpp:145
#define NETINFO_FLAG_TEAM_CAPTAIN
Definition: multi.h:612
int Brief_chat_indents[MAX_BRIEF_CHAT_LINES]
Definition: chatbox.cpp:283
int split_str(const char *src, int max_pixel_w, int *n_chars, const char **p_str, int max_lines, char ignore_char)
Definition: parselo.cpp:3412
void chatbox_clear()
Definition: chatbox.cpp:664
UI_BUTTON button
Definition: ui.h:660
void chatbox_toggle_size()
Definition: chatbox.cpp:953
color * Color_netplayer[NETPLAYER_COLORS]
int idx
Definition: multiui.cpp:761
int chatbox_has_focus()
Definition: chatbox.cpp:1093
GLint GLint GLint GLint GLint x
Definition: Glext.h:5182
void chatbox_lose_focus()
Definition: chatbox.cpp:1082
#define MULTI_MSG_ALL
Definition: multi_pmsg.h:27
int Chatbox_small_max_lines[GR_NUM_RESOLUTIONS]
Definition: chatbox.cpp:81
#define CHATBOX_H_COORD
Definition: chatbox.cpp:249
#define MULTI_MSG_HOSTILE
Definition: multi_pmsg.h:29
#define NOX(s)
Definition: pstypes.h:473
void reset_timestamps()
Definition: button.cpp:408
int Chatbox_y1
Definition: chatbox.cpp:213
GLbitfield flags
Definition: Glext.h:6722
int Chatbox_big_max_lines[GR_NUM_RESOLUTIONS]
Definition: chatbox.cpp:131
ui_button_info Chatbox_buttons[GR_NUM_RESOLUTIONS][CHATBOX_NUM_BUTTONS+1]
Definition: chatbox.cpp:252
int bm_load(const char *real_filename)
Loads a bitmap so we can draw with it later.
Definition: bmpman.cpp:1119
void update_dimensions(int _x, int _y, int _w, int _h)
Definition: gadget.cpp:187
void chatbox_close()
Definition: chatbox.cpp:634
#define MULTI_MSG_EXPR
Definition: multi_pmsg.h:31
void link_hotspot(int num)
Definition: gadget.cpp:50
int Chatbox_big_coords[GR_NUM_RESOLUTIONS][2]
Definition: chatbox.cpp:101
int Chatbox_p_coords[GR_NUM_RESOLUTIONS][2]
Definition: chatbox.cpp:151
#define CHATBOX_FLAG_DRAW_BOX
Definition: chatbox.h:24
#define strcat_s(...)
Definition: safe_strings.h:68
void create(UI_WINDOW *wnd, char *_text, int _x, int _y, int _w, int _h, int do_repeat=0, int ignore_focus=0)
Definition: button.cpp:26
void create(int _x, int _y, int _w, int _h, int _flags, int _f_id=-1)
Definition: window.cpp:140
int Chatbox_icon_x
Definition: chatbox.cpp:214
GLenum target
Definition: Glext.h:6872
Definition: ui.h:584
void chatbox_set_focus()
Definition: chatbox.cpp:1099
int Chatbox_max_lines
Definition: chatbox.cpp:220
screen gr_screen
Definition: 2d.cpp:46
void gr_get_string_size(int *w, int *h, const char *text, int len=9999)
Definition: font.cpp:196
char Chatbox_recall_lines[CHATBOX_MAX_RECALL_LINES][CHATBOX_MAX_LEN+2]
Definition: chatbox.cpp:296
#define CHATBOX_X_COORD
Definition: chatbox.cpp:246
int Chatbox_p_max_lines[GR_NUM_RESOLUTIONS]
Definition: chatbox.cpp:183
void chatbox_autosplit_line()
Definition: chatbox.cpp:413
void set_invalid_chars(char *ichars)
Definition: inputbox.cpp:163
char * Chatbox_small_bitmap_mask_fname[GR_NUM_RESOLUTIONS]
Definition: chatbox.cpp:45
int Brief_current_add_line
Definition: chatbox.cpp:288
int gr_get_font_height()
Definition: font.cpp:187
char * Chatbox_p_bitmap_fname[GR_NUM_RESOLUTIONS]
Definition: chatbox.cpp:139
void common_play_highlight_sound()
Definition: gamesnd.cpp:1151
int Chatbox_big_display_coords[GR_NUM_RESOLUTIONS][4]
Definition: chatbox.cpp:111
int Chatbox_inputbox_x
Definition: chatbox.cpp:221
#define MICON_TEAM0_SELECT
Definition: multiui.h:57
void create(UI_WINDOW *wnd, int _x, int _y, int _w, int _textlen, char *_text, int _flags=0, int pixel_lim=-1, color *clr=NULL)
Definition: inputbox.cpp:101
int has_focus()
Definition: gadget.cpp:334
#define UI_INPUTBOX_FLAG_INVIS
Definition: ui.h:35
int chatbox_process(int key_in)
Definition: chatbox.cpp:575
mouse click
Definition: gamesnd.h:287
void chat_autosplit_line(char *msg, char *remainder)
char * filename
Definition: ui.h:657
#define MICON_TEAM1_SELECT
Definition: multiui.h:59
void get_text(char *out)
Definition: inputbox.cpp:484
GLint GLsizei count
Definition: Gl.h:1491
void gr_bitmap(int _x, int _y, int resize_mode)
Definition: 2d.cpp:1303
#define KEY_UP
Definition: key.h:179
int Chatbox_x1
Definition: chatbox.cpp:212
int temp
Definition: lua.cpp:4996
int Chatbox_w
Definition: chatbox.cpp:215
int Chatbox_disp_w
Definition: chatbox.cpp:219
int Chatbox_big_input_coords[GR_NUM_RESOLUTIONS][4]
Definition: chatbox.cpp:121
char * Chatbox_big_bitmap_mask_fname[GR_NUM_RESOLUTIONS]
Definition: chatbox.cpp:95
int chatbox_scroll_up()
Definition: chatbox.cpp:708
void chatbox_recall_down()
Definition: chatbox.cpp:1167
char * Chatbox_small_bitmap_fname[GR_NUM_RESOLUTIONS]
Definition: chatbox.cpp:39
void gamesnd_play_iface(int n)
Definition: gamesnd.cpp:260
void draw()
Definition: window.cpp:220
struct ui_button_info ui_button_info
int Chatbox_small_input_coords[GR_NUM_RESOLUTIONS][4]
Definition: chatbox.cpp:71
int Chatbox_recall_index
Definition: chatbox.cpp:294
int process(int key_in=-1, int process_mouse=1)
Definition: window.cpp:401
int Multi_common_icons[MULTI_NUM_COMMON_ICONS]
Definition: multiui.cpp:304
void chatbox_add_line(const char *msg, int pid, int add_id)
Definition: chatbox.cpp:779
#define MICON_TEAM0
Definition: multiui.h:56
net_player Net_players[MAX_PLAYERS]
Definition: multi.cpp:93
char Chatbox_mask[50]
Definition: chatbox.cpp:211
int Cmdline_multi_stream_chat_to_file
Definition: cmdline.cpp:276
#define UI_INPUTBOX_FLAG_KEYTHRU
Definition: ui.h:36
#define CHATBOX_INVALID_CHARS
Definition: chatbox.cpp:231
int Chatbox_big_bitmap
Definition: chatbox.cpp:270
UI_BUTTON Chat_enter_text
Definition: chatbox.cpp:237
#define UI_INPUTBOX_FLAG_ESC_CLR
Definition: ui.h:37
int Chatbox_small_bitmap
Definition: chatbox.cpp:271
#define strcpy_s(...)
Definition: safe_strings.h:67
#define CHATBOX_TOGGLE_SIZE
Definition: chatbox.cpp:243
void chatbox_render_chat_lines()
Definition: chatbox.cpp:888
int Chatbox_p_display_coords[GR_NUM_RESOLUTIONS][4]
Definition: chatbox.cpp:163
char * Chatbox_big_bitmap_fname[GR_NUM_RESOLUTIONS]
Definition: chatbox.cpp:89