- // interlocutor.cpp 
-   
- #include "common.h" 
-   
-   
- // global variables used in this module only 
- static const wchar_t rtf_header[] = L"{\\rtf1\\ansi" 
-                                        L"{\\fonttbl\\f0\\f{Comic Sans MS};}" 
-                                        L"{\\colortbl;\\red0\\green0\\blue0;\\red192\\green192\\blue192;\\red0\\green0\\blue100;\\red160\\green160\\blue160;}" 
-                                        L"\\f0\\fs18\\cf3\\pard\n" 
-                                     L"}\n"; 
- static wchar_t text_buffer[1024 * 1024]; 
-   
-   
- void Interlocutors_Init (void) 
- { 
-    // this function resets the interlocutors array, preparing it for a new use 
-   
-    interlocutors = NULL; // reset the array pointer 
-    interlocutor_count = 0; // and set the element count to zero 
-   
-    return; // that's all there is 
- } 
-   
-   
- void Interlocutors_Shutdown (void) 
- { 
-    // this function empties the interlocutors array, closing windows and freeing allocated resources 
-   
-    int interlocutor_index; 
-   
-    // for each player card we know... 
-    for (interlocutor_index = 0; interlocutor_index < interlocutor_count; interlocutor_index++) 
-    { 
-       if (IsWindow (interlocutors[interlocutor_index].hWnd)) 
-          DestroyWindow (interlocutors[interlocutor_index].hWnd); // destroy any eventual opened chat window 
-       SAFE_free ((void **) &interlocutors[interlocutor_index].dialogtext); // free the interlocutor's dialog text buffer 
-       interlocutors[interlocutor_index].dialogtext_size = 0; // and reset this buffer's size 
-    } 
-    SAFE_free ((void **) &interlocutors); // free the chat interlocutors array 
-    interlocutor_count = 0; // and reset the interlocutors count 
-   
-    return; // finished 
- } 
-   
-   
- interlocutor_t *Interlocutor_FindOrCreate (const wchar_t *nickname) 
- { 
-    // this function returns a pointer to the interlocutor whose nickname is specified, 
-    // creating a new slot for him in the interlocutors array if he can't be found. 
-   
-    interlocutor_t *interlocutor; 
-    int interlocutor_index; 
-   
-    // see if we already know this interlocutor, loop through all of them... 
-    for (interlocutor_index = 0; interlocutor_index < interlocutor_count; interlocutor_index++) 
-       if (_wcsicmp (nickname, interlocutors[interlocutor_index].nickname) == 0) 
-          break; // break as soon as we find it 
-   
-    // have we found it ? 
-    if (interlocutor_index < interlocutor_count) 
-    { 
-       // get a quick access to interlocutor 
-       interlocutor = &interlocutors[interlocutor_index]; 
-   
-       // is this interlocutor NO LONGER active ? 
-       if (!interlocutor->is_active) 
-       { 
-          interlocutor->hWnd = NULL; // reset some values for this interlocutor 
-          interlocutor->current_displaypicture = 0; 
-          interlocutor->is_active = true; // remember it's becoming active again 
-   
-          Window_Chat (interlocutor_index); // his chat window has been closen, so fire it up again 
-       } 
-       else 
-       { 
-          // does the chat window exist AND is it currently NOT the foreground window ? 
-          if (IsWindow (interlocutor->hWnd) && (GetForegroundWindow () != interlocutor->hWnd)) 
-          { 
-             interlocutor->update_dialog = true; // update this interlocutor's window 
-             ShowWindow (interlocutor->hWnd, SW_RESTORE); // restore it from the taskbar 
-             SetForegroundWindow (interlocutor->hWnd); // bring the window to front if necessary 
-          } 
-       } 
-    } 
-   
-    // else we haven't found it 
-    else 
-    { 
-       // so resize our interlocutors array and add this interlocutor to it 
-       interlocutors = (interlocutor_t *) SAFE_realloc (interlocutors, interlocutor_count, interlocutor_count + 1, sizeof (interlocutor_t), false); 
-       interlocutor_count++; // we know now one interlocutor more 
-   
-       // get a quick access to interlocutor. Only do it after the realloc, as the array may have moved. 
-       interlocutor = &interlocutors[interlocutor_index]; 
-   
-       // reset some values for this new interlocutor 
-       wcscpy_s (interlocutor->nickname, WCHAR_SIZEOF (interlocutor->nickname), nickname); // save nickname 
-       interlocutor->hWnd = NULL; 
-       interlocutor->dialogtext = NULL; // no dialog text yet 
-       interlocutor->dialogtext_size = 0; 
-       interlocutor->current_displaypicture = 0; 
-       interlocutor->is_active = true; 
-   
-       // and fire up the new chat window 
-       Window_Chat (interlocutor_index); 
-    } 
-   
-    return (interlocutor); // return pointer to interlocutor 
- } 
-   
-   
- interlocutor_t *Interlocutor_FindByWindowHandle (HWND window_handle) 
- { 
-    // this function returns a pointer to the interlocutor whose chat window handle 
-    // matches the one specified. If no such chat window exists, NULL is returned. 
-   
-    int interlocutor_index; 
-   
-    // cycle through all interlocutors and find the one we want... 
-    for (interlocutor_index = 0; interlocutor_index < interlocutor_count; interlocutor_index++) 
-       if (interlocutors[interlocutor_index].hWnd == window_handle) 
-          return (&interlocutors[interlocutor_index]); // found it, return its pointer 
-   
-    return (NULL); // we couldn't find that interlocutor, return FALSE 
- } 
-   
-   
- void Interlocutor_Chat (interlocutor_t *interlocutor, const wchar_t *sender, bool is_localsender, const wchar_t *message) 
- { 
-    // helper function to quickly add an entry to an interlocutor's RTF chat window 
-   
-    // {\rtf1\ansi{\fonttbl\f0\fswiss Helvetica;}\f0\pard 
-    // This is some {\b bold} text.\par 
-    // } 
-    // NOTE: color table indices are 1-based 
-   
-    static const wchar_t rtf_template[] = L"{\\cf%d\\b %s}\\par\n" 
-                                          L"   %s\\par\n" 
-                                          L"}\n"; 
-    static const int template_length = WCHAR_SIZEOF (rtf_template) - 6 - 2; // don't take in account closing brace, it's counted in the header 
-    int sender_length; 
-    int text_length; 
-    int smiley_index; 
-    smiley_t *smiley; 
-    wchar_t *smiley_text; 
-    wchar_t *after_smiley; 
-   
-    // if dialog is just starting, we need to insert a RTF header 
-    if (interlocutor->dialogtext == NULL) 
-    { 
-       interlocutor->dialogtext = (wchar_t *) SAFE_malloc (WCHAR_SIZEOF (rtf_header), sizeof (wchar_t), false); // allocate space for it 
-       wcscpy_s (interlocutor->dialogtext, WCHAR_SIZEOF (rtf_header), rtf_header); // copy RTF header 
-       interlocutor->dialogtext_size = WCHAR_SIZEOF (rtf_header); // save RTF header length 
-    } 
-   
-    // concatenate all the arguments in one string, but have a space before and after it 
-    swprintf_s (text_buffer, WCHAR_SIZEOF (text_buffer), L" %s ", message); 
-   
-    // as long as there are smilies in this text, replace them with their equivalent data 
-    for (smiley_index = 0; smiley_index < smiley_count; smiley_index++) 
-    { 
-       smiley = &smilies[smiley_index]; // quick access to smiley 
-   
-       while ((smiley_text = wcsistr (text_buffer, smiley->name)) != NULL) 
-       { 
-          after_smiley = smiley_text + wcslen (smiley->name); 
-          memmove (smiley_text + smiley->rtf_len, after_smiley, (wcslen (after_smiley) + 1) * sizeof (wchar_t)); 
-          memcpy (smiley_text, smiley->rtf_data, smiley->rtf_len * sizeof (wchar_t)); 
-       } 
-    } 
-   
-    // get sender and text lengths 
-    sender_length = wcslen (sender); 
-    text_length = wcslen (text_buffer); 
-   
-    // resize the chat text buffer 
-    interlocutor->dialogtext = (wchar_t *) SAFE_realloc (interlocutor->dialogtext, 
-                                                         interlocutor->dialogtext_size, 
-                                                         interlocutor->dialogtext_size + template_length + 1 + sender_length + text_length, 
-                                                         sizeof (wchar_t), false); 
-   
-    // append the message to the chat text and save the new text length (overwrite the closing brace) 
-    swprintf_s (&interlocutor->dialogtext[wcslen (interlocutor->dialogtext) - 2], 
-                template_length + 1 + sender_length + text_length + 2 + 1, // +1 for null terminator 
-                rtf_template, (is_localsender ? 2 : 1), sender, text_buffer); 
-    interlocutor->dialogtext_size += template_length + 1 + sender_length + text_length; // save new string length 
-   
-    // and tell our chat window there's a new message to display 
-    interlocutor->update_dialog = true; 
-   
-    return; // finished 
- } 
-   
-   
- void Interlocutor_Notify (interlocutor_t *interlocutor, const wchar_t *fmt, ...) 
- { 
-    // helper function to quickly add an entry to an interlocutor's RTF chat window 
-   
-    // {\rtf1\ansi{\fonttbl\f0\fswiss Helvetica;}\f0\pard 
-    // This is some {\b bold} text.\par 
-    // } 
-    // NOTE: color table indices are 1-based 
-   
-    static const wchar_t rtf_template[] = L"{\\cf4\\fs16\\i  %s}\\par\n" 
-                                          L"}\n"; 
-    static const int template_length = WCHAR_SIZEOF (rtf_template) - 2 - 2; // don't take in account closing brace, it's counted in the header 
-    va_list argptr; 
-    int text_length; 
-   
-    // if dialog is just starting, we need to insert a RTF header 
-    if (interlocutor->dialogtext == NULL) 
-    { 
-       interlocutor->dialogtext = (wchar_t *) SAFE_malloc (WCHAR_SIZEOF (rtf_header), sizeof (wchar_t), false); // allocate space for it 
-       wcscpy_s (interlocutor->dialogtext, WCHAR_SIZEOF (rtf_header), rtf_header); // copy RTF header 
-       interlocutor->dialogtext_size = WCHAR_SIZEOF (rtf_header); // save RTF header length 
-    } 
-   
-    // concatenate all the arguments in one string 
-    va_start (argptr, fmt); 
-    vswprintf_s (text_buffer, WCHAR_SIZEOF (text_buffer), fmt, argptr); 
-    va_end (argptr); 
-   
-    // get text length 
-    text_length = wcslen (text_buffer); 
-   
-    // resize the chat text buffer 
-    interlocutor->dialogtext = (wchar_t *) SAFE_realloc (interlocutor->dialogtext, 
-                                                         interlocutor->dialogtext_size, 
-                                                         interlocutor->dialogtext_size + template_length + text_length, 
-                                                         sizeof (wchar_t), false); 
-   
-    // append the message to the chat text and save the new text length (overwrite the closing brace) 
-    swprintf_s (&interlocutor->dialogtext[wcslen (interlocutor->dialogtext) - 2], 
-                template_length + text_length + 2 + 1, // +1 for null terminator 
-                rtf_template, text_buffer); 
-    interlocutor->dialogtext_size += template_length + text_length; // save new string length 
-   
-    // and tell our chat window there's a new message to display 
-    interlocutor->update_dialog = true; 
-   
-    return; // finished 
- } 
-