Subversion Repositories Games.Chess Giants

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
// interlocutor.cpp
2
 
3
#include "common.h"
4
 
5
 
6
// global variables used in this module only
7
static const wchar_t rtf_header[] = L"{\\rtf1\\ansi"
8
                                       L"{\\fonttbl\\f0\\f{Comic Sans MS};}"
9
                                       L"{\\colortbl;\\red0\\green0\\blue0;\\red192\\green192\\blue192;\\red0\\green0\\blue100;\\red160\\green160\\blue160;}"
10
                                       L"\\f0\\fs18\\cf3\\pard\n"
11
                                    L"}\n";
12
static wchar_t text_buffer[1024 * 1024];
13
 
14
 
15
void Interlocutors_Init (void)
16
{
17
   // this function resets the interlocutors array, preparing it for a new use
18
 
19
   interlocutors = NULL; // reset the array pointer
20
   interlocutor_count = 0; // and set the element count to zero
21
 
22
   return; // that's all there is
23
}
24
 
25
 
26
void Interlocutors_Shutdown (void)
27
{
28
   // this function empties the interlocutors array, closing windows and freeing allocated resources
29
 
30
   int interlocutor_index;
31
 
32
   // for each player card we know...
33
   for (interlocutor_index = 0; interlocutor_index < interlocutor_count; interlocutor_index++)
34
   {
35
      if (IsWindow (interlocutors[interlocutor_index].hWnd))
36
         DestroyWindow (interlocutors[interlocutor_index].hWnd); // destroy any eventual opened chat window
37
      SAFE_free ((void **) &interlocutors[interlocutor_index].dialogtext); // free the interlocutor's dialog text buffer
38
      interlocutors[interlocutor_index].dialogtext_size = 0; // and reset this buffer's size
39
   }
40
   SAFE_free ((void **) &interlocutors); // free the chat interlocutors array
41
   interlocutor_count = 0; // and reset the interlocutors count
42
 
43
   return; // finished
44
}
45
 
46
 
47
interlocutor_t *Interlocutor_FindOrCreate (const wchar_t *nickname)
48
{
49
   // this function returns a pointer to the interlocutor whose nickname is specified,
50
   // creating a new slot for him in the interlocutors array if he can't be found.
51
 
52
   interlocutor_t *interlocutor;
53
   int interlocutor_index;
54
 
55
   // see if we already know this interlocutor, loop through all of them...
56
   for (interlocutor_index = 0; interlocutor_index < interlocutor_count; interlocutor_index++)
57
      if (_wcsicmp (nickname, interlocutors[interlocutor_index].nickname) == 0)
58
         break; // break as soon as we find it
59
 
60
   // have we found it ?
61
   if (interlocutor_index < interlocutor_count)
62
   {
63
      // get a quick access to interlocutor
64
      interlocutor = &interlocutors[interlocutor_index];
65
 
66
      // is this interlocutor NO LONGER active ?
67
      if (!interlocutor->is_active)
68
      {
69
         interlocutor->hWnd = NULL; // reset some values for this interlocutor
70
         interlocutor->current_displaypicture = 0;
71
         interlocutor->is_active = true; // remember it's becoming active again
72
 
73
         Window_Chat (interlocutor_index); // his chat window has been closen, so fire it up again
74
      }
75
      else
76
      {
77
         // does the chat window exist AND is it currently NOT the foreground window ?
78
         if (IsWindow (interlocutor->hWnd) && (GetForegroundWindow () != interlocutor->hWnd))
79
         {
80
            interlocutor->update_dialog = true; // update this interlocutor's window
81
            ShowWindow (interlocutor->hWnd, SW_RESTORE); // restore it from the taskbar
82
            SetForegroundWindow (interlocutor->hWnd); // bring the window to front if necessary
83
         }
84
      }
85
   }
86
 
87
   // else we haven't found it
88
   else
89
   {
90
      // so resize our interlocutors array and add this interlocutor to it
91
      interlocutors = (interlocutor_t *) SAFE_realloc (interlocutors, interlocutor_count, interlocutor_count + 1, sizeof (interlocutor_t), false);
92
      interlocutor_count++; // we know now one interlocutor more
93
 
94
      // get a quick access to interlocutor. Only do it after the realloc, as the array may have moved.
95
      interlocutor = &interlocutors[interlocutor_index];
96
 
97
      // reset some values for this new interlocutor
98
      wcscpy_s (interlocutor->nickname, WCHAR_SIZEOF (interlocutor->nickname), nickname); // save nickname
99
      interlocutor->hWnd = NULL;
100
      interlocutor->dialogtext = NULL; // no dialog text yet
101
      interlocutor->dialogtext_size = 0;
102
      interlocutor->current_displaypicture = 0;
103
      interlocutor->is_active = true;
104
 
105
      // and fire up the new chat window
106
      Window_Chat (interlocutor_index);
107
   }
108
 
109
   return (interlocutor); // return pointer to interlocutor
110
}
111
 
112
 
113
interlocutor_t *Interlocutor_FindByWindowHandle (HWND window_handle)
114
{
115
   // this function returns a pointer to the interlocutor whose chat window handle
116
   // matches the one specified. If no such chat window exists, NULL is returned.
117
 
118
   int interlocutor_index;
119
 
120
   // cycle through all interlocutors and find the one we want...
121
   for (interlocutor_index = 0; interlocutor_index < interlocutor_count; interlocutor_index++)
122
      if (interlocutors[interlocutor_index].hWnd == window_handle)
123
         return (&interlocutors[interlocutor_index]); // found it, return its pointer
124
 
125
   return (NULL); // we couldn't find that interlocutor, return FALSE
126
}
127
 
128
 
129
void Interlocutor_Chat (interlocutor_t *interlocutor, const wchar_t *sender, bool is_localsender, const wchar_t *fmt, ...)
130
{
131
   // helper function to quickly add an entry to an interlocutor's RTF chat window
132
 
133
   // {\rtf1\ansi{\fonttbl\f0\fswiss Helvetica;}\f0\pard
134
   // This is some {\b bold} text.\par
135
   // }
136
   // NOTE: color table indices are 1-based
137
 
138
   static const wchar_t rtf_template[] = L"{\\cf%d\\b %s}\\par\n"
139
                                         L"   %s\\par\n"
140
                                         L"}\n";
141
   static const int template_length = WCHAR_SIZEOF (rtf_template) - 6 - 2; // don't take in account closing brace, it's counted in the header
142
   va_list argptr;
143
   int sender_length;
144
   int text_length;
145
   int smiley_index;
146
   smiley_t *smiley;
147
   wchar_t *smiley_text;
148
   wchar_t *after_smiley;
149
 
150
   // if dialog is just starting, we need to insert a RTF header
151
   if (interlocutor->dialogtext == NULL)
152
   {
153
      interlocutor->dialogtext = (wchar_t *) SAFE_malloc (WCHAR_SIZEOF (rtf_header), sizeof (wchar_t), false); // allocate space for it
154
      wcscpy_s (interlocutor->dialogtext, WCHAR_SIZEOF (rtf_header), rtf_header); // copy RTF header
155
      interlocutor->dialogtext_size = WCHAR_SIZEOF (rtf_header); // save RTF header length
156
   }
157
 
158
   // concatenate all the arguments in one string, but have a space before and after it
159
   wcscpy_s (text_buffer, WCHAR_SIZEOF (text_buffer), L" ");
160
   va_start (argptr, fmt);
161
   vswprintf_s (&text_buffer[1], WCHAR_SIZEOF (text_buffer), fmt, argptr);
162
   va_end (argptr);
163
   wcscat_s (text_buffer, WCHAR_SIZEOF (text_buffer), L" ");
164
 
165
   // as long as there are smilies in this text, replace them with their equivalent data
166
   for (smiley_index = 0; smiley_index < smiley_count; smiley_index++)
167
   {
168
      smiley = &smilies[smiley_index]; // quick access to smiley
169
 
170
      while ((smiley_text = wcsistr (text_buffer, smiley->name)) != NULL)
171
      {
172
         after_smiley = smiley_text + wcslen (smiley->name);
173
         memmove (smiley_text + smiley->rtf_len, after_smiley, (wcslen (after_smiley) + 1) * sizeof (wchar_t));
174
         memcpy (smiley_text, smiley->rtf_data, smiley->rtf_len * sizeof (wchar_t));
175
      }
176
   }
177
 
178
   // get sender and text lengths
179
   sender_length = wcslen (sender);
180
   text_length = wcslen (text_buffer);
181
 
182
   // resize the chat text buffer
183
   interlocutor->dialogtext = (wchar_t *) SAFE_realloc (interlocutor->dialogtext,
184
                                                        interlocutor->dialogtext_size,
185
                                                        interlocutor->dialogtext_size + template_length + 1 + sender_length + text_length,
186
                                                        sizeof (wchar_t), false);
187
 
188
   // append the message to the chat text and save the new text length (overwrite the closing brace)
189
   swprintf_s (&interlocutor->dialogtext[wcslen (interlocutor->dialogtext) - 2],
190
               template_length + 1 + sender_length + text_length + 2 + 1, // +1 for null terminator
191
               rtf_template, (is_localsender ? 2 : 1), sender, text_buffer);
192
   interlocutor->dialogtext_size += template_length + 1 + sender_length + text_length; // save new string length
193
 
194
   // and tell our chat window there's a new message to display
195
   interlocutor->update_dialog = true;
196
 
197
   return; // finished
198
}
199
 
200
 
201
void Interlocutor_Notify (interlocutor_t *interlocutor, const wchar_t *fmt, ...)
202
{
203
   // helper function to quickly add an entry to an interlocutor's RTF chat window
204
 
205
   // {\rtf1\ansi{\fonttbl\f0\fswiss Helvetica;}\f0\pard
206
   // This is some {\b bold} text.\par
207
   // }
208
   // NOTE: color table indices are 1-based
209
 
210
   static const wchar_t rtf_template[] = L"{\\cf4\\fs16\\i • %s}\\par\n"
211
                                         L"}\n";
212
   static const int template_length = WCHAR_SIZEOF (rtf_template) - 2 - 2; // don't take in account closing brace, it's counted in the header
213
   va_list argptr;
214
   int text_length;
215
 
216
   // if dialog is just starting, we need to insert a RTF header
217
   if (interlocutor->dialogtext == NULL)
218
   {
219
      interlocutor->dialogtext = (wchar_t *) SAFE_malloc (WCHAR_SIZEOF (rtf_header), sizeof (wchar_t), false); // allocate space for it
220
      wcscpy_s (interlocutor->dialogtext, WCHAR_SIZEOF (rtf_header), rtf_header); // copy RTF header
221
      interlocutor->dialogtext_size = WCHAR_SIZEOF (rtf_header); // save RTF header length
222
   }
223
 
224
   // concatenate all the arguments in one string
225
   va_start (argptr, fmt);
226
   vswprintf_s (text_buffer, WCHAR_SIZEOF (text_buffer), fmt, argptr);
227
   va_end (argptr);
228
 
229
   // get text length
230
   text_length = wcslen (text_buffer);
231
 
232
   // resize the chat text buffer
233
   interlocutor->dialogtext = (wchar_t *) SAFE_realloc (interlocutor->dialogtext,
234
                                                        interlocutor->dialogtext_size,
235
                                                        interlocutor->dialogtext_size + template_length + text_length,
236
                                                        sizeof (wchar_t), false);
237
 
238
   // append the message to the chat text and save the new text length (overwrite the closing brace)
239
   swprintf_s (&interlocutor->dialogtext[wcslen (interlocutor->dialogtext) - 2],
240
               template_length + text_length + 2 + 1, // +1 for null terminator
241
               rtf_template, text_buffer);
242
   interlocutor->dialogtext_size += template_length + text_length; // save new string length
243
 
244
   // and tell our chat window there's a new message to display
245
   interlocutor->update_dialog = true;
246
 
247
   return; // finished
248
}