fix for keepalive and chat window
[xboard.git] / winboard / wchat.c
1 /*\r
2  * Chat window (PV)\r
3  *\r
4  * Author: H.G.Muller (August 2009)\r
5  *\r
6  * ------------------------------------------------------------------------\r
7  *\r
8  * GNU XBoard is free software: you can redistribute it and/or modify\r
9  * it under the terms of the GNU General Public License as published by\r
10  * the Free Software Foundation, either version 3 of the License, or (at\r
11  * your option) any later version.\r
12  *\r
13  * GNU XBoard is distributed in the hope that it will be useful, but\r
14  * WITHOUT ANY WARRANTY; without even the implied warranty of\r
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
16  * General Public License for more details.\r
17  *\r
18  * You should have received a copy of the GNU General Public License\r
19  * along with this program. If not, see http://www.gnu.org/licenses/.  *\r
20  *\r
21  *------------------------------------------------------------------------\r
22  ** See the file ChangeLog for a revision history.  */\r
23 \r
24 #include "config.h"\r
25 \r
26 #include <windows.h> /* required for all Windows applications */\r
27 #include <richedit.h>\r
28 #include <stdio.h>\r
29 #include <stdlib.h>\r
30 #include <malloc.h>\r
31 #include <commdlg.h>\r
32 #include <dlgs.h>\r
33 \r
34 #include "common.h"\r
35 #include "winboard.h"\r
36 #include "frontend.h"\r
37 #include "backend.h"\r
38 \r
39 #include "wsnap.h"\r
40 \r
41 int chatCount;\r
42 extern char chatPartner[MAX_CHAT][MSG_SIZ];\r
43 HANDLE chatHandle[MAX_CHAT];\r
44 \r
45 void SendToICS P((char *s));\r
46 void ChatPopUp();\r
47 void ChatPopDown();\r
48 \r
49 /* Imports from backend.c */\r
50 char * SavePart(char *str);\r
51 extern int opponentKibitzes;\r
52 \r
53 /* Imports from winboard.c */\r
54 extern HWND ChatDialog;\r
55 \r
56 extern HINSTANCE hInst;\r
57 extern HWND hwndMain;\r
58 \r
59 extern WindowPlacement wpChat[MAX_CHAT];\r
60 \r
61 extern BoardSize boardSize;\r
62 \r
63 /* Module variables */\r
64 #define H_MARGIN            5\r
65 #define V_MARGIN            5\r
66 \r
67 // front end, although we might make GetWindowRect front end instead\r
68 static int GetControlWidth( HWND hDlg, int id )\r
69 {\r
70     RECT rc;\r
71 \r
72     GetWindowRect( GetDlgItem( hDlg, id ), &rc );\r
73 \r
74     return rc.right - rc.left;\r
75 }\r
76 \r
77 // front end?\r
78 static int GetControlHeight( HWND hDlg, int id )\r
79 {\r
80     RECT rc;\r
81 \r
82     GetWindowRect( GetDlgItem( hDlg, id ), &rc );\r
83 \r
84     return rc.bottom - rc.top;\r
85 }\r
86 \r
87 static void SetControlPos( HWND hDlg, int id, int x, int y, int width, int height )\r
88 {\r
89     HWND hControl = GetDlgItem( hDlg, id );\r
90 \r
91     SetWindowPos( hControl, HWND_TOP, x, y, width, height, SWP_NOZORDER );\r
92 }\r
93 \r
94 // Also here some of the size calculations should go to the back end, and their actual application to a front-end routine\r
95 static void ResizeWindowControls( HWND hDlg )\r
96 {\r
97     RECT rc;\r
98     int clientWidth;\r
99     int clientHeight;\r
100     int maxControlWidth;\r
101     int buttonWidth, buttonHeight;\r
102 #if 0\r
103 }\r
104 #else\r
105     /* Initialize variables */\r
106     GetClientRect( hDlg, &rc );\r
107 \r
108     clientWidth = rc.right - rc.left;\r
109     clientHeight = rc.bottom - rc.top;\r
110 \r
111     maxControlWidth = clientWidth - 2*H_MARGIN;\r
112     buttonWidth  = GetControlWidth(hDlg, IDC_Send);\r
113     buttonHeight = GetControlHeight(hDlg, IDC_Send);\r
114 \r
115     /* Resize controls */\r
116     SetControlPos( hDlg, IDC_Clear, maxControlWidth+H_MARGIN-2*buttonWidth-5, V_MARGIN, buttonWidth, buttonHeight );\r
117     SetControlPos( hDlg, IDC_Send, maxControlWidth+H_MARGIN-buttonWidth, V_MARGIN, buttonWidth, buttonHeight );\r
118     SetControlPos( hDlg, IDC_ChatMemo, H_MARGIN, 2*V_MARGIN+buttonHeight, maxControlWidth, clientHeight-3*V_MARGIN-2*buttonHeight );\r
119     SetControlPos( hDlg, OPT_ChatInput, H_MARGIN, clientHeight-V_MARGIN-buttonHeight, maxControlWidth, buttonHeight );\r
120 \r
121 //    InvalidateRect( GetDlgItem(hDlg,IDC_EngineMemo1), NULL, FALSE );\r
122 //    InvalidateRect( GetDlgItem(hDlg,IDC_EngineMemo2), NULL, FALSE );\r
123 }\r
124 #endif\r
125 \r
126 // front end. Actual printing of PV lines into the output field\r
127 static void InsertIntoMemo( HANDLE hDlg, char * text )\r
128 {\r
129     HANDLE hMemo = GetDlgItem(hDlg, IDC_ChatMemo);\r
130 \r
131     SendMessage( hMemo, EM_SETSEL, 1000000, 1000000 );\r
132 \r
133     SendMessage( hMemo, EM_REPLACESEL, (WPARAM) FALSE, (LPARAM) text );\r
134     SendMessage( hMemo, EM_SCROLLCARET, 0, 0);\r
135 }\r
136 \r
137 // This seems pure front end\r
138 LRESULT CALLBACK ChatProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )\r
139 {\r
140     static SnapData sd;\r
141     char buf[MSG_SIZ], mess[MSG_SIZ];\r
142     int partner = -1, i;\r
143 \r
144     for(i=0; i<MAX_CHAT; i++) if(hDlg == chatHandle[i]) { partner = i; break; }\r
145 \r
146     switch (message) {\r
147     case WM_INITDIALOG:\r
148         if(partner<0) {\r
149                 for(i=0; i<MAX_CHAT; i++) if(chatHandle[i] == NULL) { partner = i; break; }\r
150                 chatHandle[partner] = hDlg;\r
151                 sprintf(buf, "Chat Window %s", first.tidy);\r
152                 SetWindowText(hDlg, buf);\r
153         }\r
154         chatPartner[partner][0] = 0;\r
155 \r
156         return FALSE;\r
157 \r
158     case WM_COMMAND:\r
159         switch (LOWORD(wParam)) {\r
160 \r
161         case IDCANCEL:\r
162             chatHandle[partner] = 0;\r
163             chatPartner[partner][0] = 0;\r
164             ChatPopDown();\r
165             EndDialog(hDlg, TRUE);\r
166             break;\r
167 \r
168         case IDC_Clear:\r
169             SendMessage( GetDlgItem(hDlg, IDC_ChatMemo), WM_SETTEXT, 0, (LPARAM) "" );\r
170             break;\r
171 \r
172         case IDC_Change:\r
173             GetDlgItemText(hDlg, IDC_ChatPartner, chatPartner[partner], MSG_SIZ);\r
174             break;\r
175 \r
176         case IDC_Send:\r
177             GetDlgItemText(hDlg, OPT_ChatInput, mess, MSG_SIZ);\r
178             SetDlgItemText(hDlg, OPT_ChatInput, "");\r
179             // from here on it could be back-end\r
180             if(!strcmp("WHISPER", chatPartner[partner]))\r
181                 sprintf(buf, "whisper %s\n", mess); // WHISPER box uses "whisper" to send\r
182             else {\r
183                 if(!atoi(chatPartner[partner])) {\r
184                     sprintf(buf, "> %s\n", mess); // echo only tells to handle, not channel\r
185                 InsertIntoMemo(hDlg, buf);\r
186                 }\r
187                 sprintf(buf, "tell %s %s\n", chatPartner[partner], mess);\r
188             }\r
189             SendToICS(buf);\r
190             break;\r
191 \r
192         default:\r
193           break;\r
194         }\r
195 \r
196         break;\r
197 \r
198     case WM_CLOSE:\r
199         chatHandle[partner] = 0;\r
200         chatPartner[partner][0] = 0;\r
201         ChatPopDown();\r
202         EndDialog(hDlg, TRUE);\r
203         break;\r
204 \r
205     case WM_SIZE:\r
206         ResizeWindowControls( hDlg );\r
207         break;\r
208 \r
209     case WM_ENTERSIZEMOVE:\r
210         return OnEnterSizeMove( &sd, hDlg, wParam, lParam );\r
211 \r
212     case WM_SIZING:\r
213         return OnSizing( &sd, hDlg, wParam, lParam );\r
214 \r
215     case WM_MOVING:\r
216         return OnMoving( &sd, hDlg, wParam, lParam );\r
217 \r
218     case WM_EXITSIZEMOVE:\r
219         return OnExitSizeMove( &sd, hDlg, wParam, lParam );\r
220     }\r
221 \r
222     return FALSE;\r
223 }\r
224 \r
225 // front end\r
226 void ChatPopUp()\r
227 {\r
228   FARPROC lpProc;\r
229   \r
230   if(chatCount >= MAX_CHAT) return;\r
231 \r
232   CheckMenuItem(GetMenu(hwndMain), IDM_NewChat, MF_CHECKED);\r
233   chatCount++;\r
234 \r
235     lpProc = MakeProcInstance( (FARPROC) ChatProc, hInst );\r
236 \r
237     /* Note to self: dialog must have the WS_VISIBLE style set, otherwise it's not shown! */\r
238     CreateDialog( hInst, MAKEINTRESOURCE(DLG_Chat), hwndMain, (DLGPROC)lpProc );\r
239 \r
240     FreeProcInstance(lpProc);\r
241 \r
242 }\r
243 \r
244 // front end\r
245 void ChatPopDown()\r
246 {\r
247   if(--chatCount <= 0)\r
248         CheckMenuItem(GetMenu(hwndMain), IDM_NewChat, MF_UNCHECKED);\r
249 }\r
250 \r
251 \r
252 //------------------------ pure back-end routines -------------------------------\r
253 \r
254 void OutputChatMessage(int partner, char *text)\r
255 {\r
256         if(!chatHandle[partner]) return;\r
257 \r
258         InsertIntoMemo(chatHandle[partner], text);\r
259 }\r