Subversion Repositories Games.Chess Giants

Rev

Rev 1 | Details | Compare with Previous | 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
 
161 pmbaty 129
void Interlocutor_Chat (interlocutor_t *interlocutor, const wchar_t *sender, bool is_localsender, const wchar_t *message)
1 pmbaty 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
   int sender_length;
143
   int text_length;
144
   int smiley_index;
145
   smiley_t *smiley;
146
   wchar_t *smiley_text;
147
   wchar_t *after_smiley;
148
 
149
   // if dialog is just starting, we need to insert a RTF header
150
   if (interlocutor->dialogtext == NULL)
151
   {
152
      interlocutor->dialogtext = (wchar_t *) SAFE_malloc (WCHAR_SIZEOF (rtf_header), sizeof (wchar_t), false); // allocate space for it
153
      wcscpy_s (interlocutor->dialogtext, WCHAR_SIZEOF (rtf_header), rtf_header); // copy RTF header
154
      interlocutor->dialogtext_size = WCHAR_SIZEOF (rtf_header); // save RTF header length
155
   }
156
 
157
   // concatenate all the arguments in one string, but have a space before and after it
161 pmbaty 158
   swprintf_s (text_buffer, WCHAR_SIZEOF (text_buffer), L" %s ", message);
1 pmbaty 159
 
160
   // as long as there are smilies in this text, replace them with their equivalent data
161
   for (smiley_index = 0; smiley_index < smiley_count; smiley_index++)
162
   {
163
      smiley = &smilies[smiley_index]; // quick access to smiley
164
 
165
      while ((smiley_text = wcsistr (text_buffer, smiley->name)) != NULL)
166
      {
167
         after_smiley = smiley_text + wcslen (smiley->name);
168
         memmove (smiley_text + smiley->rtf_len, after_smiley, (wcslen (after_smiley) + 1) * sizeof (wchar_t));
169
         memcpy (smiley_text, smiley->rtf_data, smiley->rtf_len * sizeof (wchar_t));
170
      }
171
   }
172
 
173
   // get sender and text lengths
174
   sender_length = wcslen (sender);
175
   text_length = wcslen (text_buffer);
176
 
177
   // resize the chat text buffer
178
   interlocutor->dialogtext = (wchar_t *) SAFE_realloc (interlocutor->dialogtext,
179
                                                        interlocutor->dialogtext_size,
180
                                                        interlocutor->dialogtext_size + template_length + 1 + sender_length + text_length,
181
                                                        sizeof (wchar_t), false);
182
 
183
   // append the message to the chat text and save the new text length (overwrite the closing brace)
184
   swprintf_s (&interlocutor->dialogtext[wcslen (interlocutor->dialogtext) - 2],
185
               template_length + 1 + sender_length + text_length + 2 + 1, // +1 for null terminator
186
               rtf_template, (is_localsender ? 2 : 1), sender, text_buffer);
187
   interlocutor->dialogtext_size += template_length + 1 + sender_length + text_length; // save new string length
188
 
189
   // and tell our chat window there's a new message to display
190
   interlocutor->update_dialog = true;
191
 
192
   return; // finished
193
}
194
 
195
 
196
void Interlocutor_Notify (interlocutor_t *interlocutor, const wchar_t *fmt, ...)
197
{
198
   // helper function to quickly add an entry to an interlocutor's RTF chat window
199
 
200
   // {\rtf1\ansi{\fonttbl\f0\fswiss Helvetica;}\f0\pard
201
   // This is some {\b bold} text.\par
202
   // }
203
   // NOTE: color table indices are 1-based
204
 
205
   static const wchar_t rtf_template[] = L"{\\cf4\\fs16\\i • %s}\\par\n"
206
                                         L"}\n";
207
   static const int template_length = WCHAR_SIZEOF (rtf_template) - 2 - 2; // don't take in account closing brace, it's counted in the header
208
   va_list argptr;
209
   int text_length;
210
 
211
   // if dialog is just starting, we need to insert a RTF header
212
   if (interlocutor->dialogtext == NULL)
213
   {
214
      interlocutor->dialogtext = (wchar_t *) SAFE_malloc (WCHAR_SIZEOF (rtf_header), sizeof (wchar_t), false); // allocate space for it
215
      wcscpy_s (interlocutor->dialogtext, WCHAR_SIZEOF (rtf_header), rtf_header); // copy RTF header
216
      interlocutor->dialogtext_size = WCHAR_SIZEOF (rtf_header); // save RTF header length
217
   }
218
 
219
   // concatenate all the arguments in one string
220
   va_start (argptr, fmt);
221
   vswprintf_s (text_buffer, WCHAR_SIZEOF (text_buffer), fmt, argptr);
222
   va_end (argptr);
223
 
224
   // get text length
225
   text_length = wcslen (text_buffer);
226
 
227
   // resize the chat text buffer
228
   interlocutor->dialogtext = (wchar_t *) SAFE_realloc (interlocutor->dialogtext,
229
                                                        interlocutor->dialogtext_size,
230
                                                        interlocutor->dialogtext_size + template_length + text_length,
231
                                                        sizeof (wchar_t), false);
232
 
233
   // append the message to the chat text and save the new text length (overwrite the closing brace)
234
   swprintf_s (&interlocutor->dialogtext[wcslen (interlocutor->dialogtext) - 2],
235
               template_length + text_length + 2 + 1, // +1 for null terminator
236
               rtf_template, text_buffer);
237
   interlocutor->dialogtext_size += template_length + text_length; // save new string length
238
 
239
   // and tell our chat window there's a new message to display
240
   interlocutor->update_dialog = true;
241
 
242
   return; // finished
243
}