Fix multi-leg promotions
[xboard.git] / winboard / wedittags.c
1 /*\r
2  * wedittags.c -- EditTags window for WinBoard\r
3  *\r
4  * Copyright 1995, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Free\r
5  * Software Foundation, Inc.\r
6  *\r
7  * Enhancements Copyright 2005 Alessandro Scotti\r
8  *\r
9  * ------------------------------------------------------------------------\r
10  *\r
11  * GNU XBoard is free software: you can redistribute it and/or modify\r
12  * it under the terms of the GNU General Public License as published by\r
13  * the Free Software Foundation, either version 3 of the License, or (at\r
14  * your option) any later version.\r
15  *\r
16  * GNU XBoard is distributed in the hope that it will be useful, but\r
17  * WITHOUT ANY WARRANTY; without even the implied warranty of\r
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
19  * General Public License for more details.\r
20  *\r
21  * You should have received a copy of the GNU General Public License\r
22  * along with this program. If not, see http://www.gnu.org/licenses/.  *\r
23  *\r
24  *------------------------------------------------------------------------\r
25  ** See the file ChangeLog for a revision history.  */\r
26 \r
27 #include "config.h"\r
28 \r
29 #include <windows.h>   /* required for all Windows applications */\r
30 #include <richedit.h>\r
31 #include <stdio.h>\r
32 #include <stdlib.h>\r
33 #include <malloc.h>\r
34 #include <fcntl.h>\r
35 #include <math.h>\r
36 #include <commdlg.h>\r
37 #include <dlgs.h>\r
38 \r
39 #include "common.h"\r
40 #include "frontend.h"\r
41 #include "backend.h"\r
42 #include "winboard.h"\r
43 \r
44 #define _(s) T_(s)\r
45 \r
46 /* Module globals */\r
47 static char *editTagsText, **resPtr;\r
48 static HWND memo;\r
49 BOOL editTagsUp = FALSE;\r
50 BOOL canEditTags = FALSE;\r
51 \r
52 /* Imports from winboard.c */\r
53 extern HINSTANCE hInst;\r
54 extern HWND hwndMain;\r
55 extern BoardSize boardSize;\r
56 \r
57 LRESULT CALLBACK\r
58 EditTagsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
59 {\r
60   static HANDLE hwndText;\r
61   static int sizeX, sizeY;\r
62   int len, newSizeX, newSizeY;\r
63   char *str;\r
64   RECT rect;\r
65   MINMAXINFO *mmi;\r
66   int err;\r
67   \r
68   switch (message) {\r
69   case WM_INITDIALOG: /* message: initialize dialog box */\r
70     /* Initialize the dialog items */\r
71     Translate(hDlg, DLG_EditTags);\r
72    hwndText = memo = GetDlgItem(hDlg, OPT_TagsText);\r
73     SendMessage(hwndText, WM_SETFONT, \r
74       (WPARAM)font[boardSize][EDITTAGS_FONT]->hf, MAKELPARAM(FALSE, 0));\r
75     SetDlgItemText(hDlg, OPT_TagsText, editTagsText);\r
76     EnableWindow(GetDlgItem(hDlg, OPT_TagsCancel), canEditTags);\r
77     EnableWindow(GetDlgItem(hDlg, OPT_EditTags), !canEditTags || bookUp);\r
78     SendMessage(hwndText, EM_SETREADONLY, !canEditTags, 0);\r
79     if (bookUp) {\r
80       SetDlgItemText(hDlg, OPT_EditTags, _("&Play Move"));\r
81       SetWindowText(hDlg, _("Edit Book"));\r
82       SetFocus(hwndText);\r
83     } else\r
84     if (canEditTags) {\r
85       SetWindowText(hDlg, _("Edit Tags"));\r
86       SetFocus(hwndText);\r
87     } else {\r
88       SetWindowText(hDlg, _("Tags"));\r
89       SetFocus(GetDlgItem(hDlg, IDOK));\r
90     }\r
91     if (!editTagsDialog) {\r
92       editTagsDialog = hDlg;\r
93       GetClientRect(hDlg, &rect);\r
94       sizeX = rect.right;\r
95       sizeY = rect.bottom;\r
96       SendDlgItemMessage( hDlg, OPT_TagsText, EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS );\r
97       if (wpTags.x != CW_USEDEFAULT && wpTags.y != CW_USEDEFAULT &&\r
98           wpTags.width != CW_USEDEFAULT && wpTags.height != CW_USEDEFAULT) {\r
99         WINDOWPLACEMENT wp;\r
100         EnsureOnScreen(&wpTags.x, &wpTags.y, 0, 0);\r
101         wp.length = sizeof(WINDOWPLACEMENT);\r
102         wp.flags = 0;\r
103         wp.showCmd = SW_SHOW;\r
104         wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;\r
105         wp.rcNormalPosition.left = wpTags.x;\r
106         wp.rcNormalPosition.right = wpTags.x + wpTags.width;\r
107         wp.rcNormalPosition.top = wpTags.y;\r
108         wp.rcNormalPosition.bottom = wpTags.y + wpTags.height;\r
109         SetWindowPlacement(hDlg, &wp);\r
110 \r
111         GetClientRect(hDlg, &rect);\r
112         newSizeX = rect.right;\r
113         newSizeY = rect.bottom;\r
114         ResizeEditPlusButtons(hDlg, hwndText, sizeX, sizeY,\r
115                               newSizeX, newSizeY);\r
116         sizeX = newSizeX;\r
117         sizeY = newSizeY;\r
118       }\r
119     }\r
120     return FALSE;\r
121     \r
122   case WM_COMMAND:\r
123     switch (LOWORD(wParam)) {\r
124     case IDOK:\r
125     case OPT_TagsSave:\r
126       if (canEditTags) {\r
127         char *p, *q;\r
128         /* Read changed options from the dialog box */\r
129         len = GetWindowTextLength(hwndText);\r
130         str = (char *) malloc(len + 1);\r
131         GetWindowText(hwndText, str, len + 1);\r
132         p = q = str;\r
133         while (*q) {\r
134           if (*q == '\r')\r
135             q++;\r
136           else\r
137             *p++ = *q++;\r
138         }\r
139         *p = NULLCHAR; err = 0;\r
140         if(resPtr) *resPtr = strdup(str); else\r
141         if(bookUp) SaveToBook(str), DisplayBook(currentMove); else\r
142         err = ReplaceTags(str, &gameInfo);\r
143         if (err) DisplayError(_("Error replacing tags."), err);\r
144 \r
145         free(str);\r
146       }\r
147       if(LOWORD(wParam) == IDOK) TagsPopDown();\r
148       return TRUE;\r
149       \r
150     case IDCANCEL:\r
151     case OPT_TagsCancel:\r
152       TagsPopDown();\r
153       return TRUE;\r
154       \r
155     case OPT_EditTags:\r
156       if(bookUp) addToBookFlag = !addToBookFlag; else\r
157       EditTagsEvent();\r
158       return TRUE;\r
159 \r
160     default:\r
161       break;\r
162     }\r
163     break;\r
164 \r
165   case WM_NOTIFY: // [HGM] vari: cloned from whistory.c\r
166         if( wParam == OPT_TagsText ) {\r
167             MSGFILTER * lpMF = (MSGFILTER *) lParam;\r
168 \r
169             if( lpMF->msg == WM_RBUTTONDOWN ) {\r
170                 POINTL pt;\r
171                 LRESULT index;\r
172 \r
173                 pt.x = LOWORD( lpMF->lParam );\r
174                 pt.y = HIWORD( lpMF->lParam );\r
175 \r
176                 index = SendDlgItemMessage( hDlg, OPT_TagsText, EM_CHARFROMPOS, 0, (LPARAM) &pt );\r
177 \r
178                 hwndText = GetDlgItem(hDlg, OPT_TagsText); // cloned from above\r
179                 len = GetWindowTextLength(hwndText);\r
180                 str = (char *) malloc(len + 1);\r
181                 GetWindowText(hwndText, str, len + 1);\r
182                 if(bookUp) PlayBookMove(str, index);\r
183                 free(str);\r
184 \r
185                 /* Zap the message for good: apparently, returning non-zero is not enough */\r
186                 lpMF->msg = WM_USER;\r
187 \r
188                 return TRUE;\r
189             }\r
190         }\r
191         break;\r
192 \r
193   case WM_SIZE:\r
194     newSizeX = LOWORD(lParam);\r
195     newSizeY = HIWORD(lParam);\r
196     ResizeEditPlusButtons(hDlg, hwndText, sizeX, sizeY, newSizeX, newSizeY);\r
197     sizeX = newSizeX;\r
198     sizeY = newSizeY;\r
199     break;\r
200 \r
201   case WM_GETMINMAXINFO:\r
202     /* Prevent resizing window too small */\r
203     mmi = (MINMAXINFO *) lParam;\r
204     mmi->ptMinTrackSize.x = 100;\r
205     mmi->ptMinTrackSize.y = 100;\r
206     break;\r
207   }\r
208   return FALSE;\r
209 }\r
210 \r
211 VOID AddBookMove(char *text)\r
212 {\r
213     SendMessage( memo, EM_SETSEL, 999999, 999999 ); // [HGM] multivar: choose insertion point\r
214     SendMessage( memo, EM_REPLACESEL, (WPARAM) FALSE, (LPARAM) text );\r
215 }\r
216 \r
217 VOID TagsPopDown(void)\r
218 {\r
219   if (editTagsDialog) ShowWindow(editTagsDialog, SW_HIDE);\r
220   CheckMenuItem(GetMenu(hwndMain), IDM_Tags, MF_UNCHECKED);\r
221   editTagsUp = bookUp = addToBookFlag = FALSE;\r
222 }\r
223 \r
224 \r
225 VOID EitherTagsPopUp(char *tags, char *msg, BOOLEAN edit)\r
226 {\r
227   FARPROC lpProc;\r
228   char *p, *q;\r
229   \r
230   if (msg == NULL) msg = "";\r
231   p = (char *) malloc(2 * (strlen(tags) + strlen(msg)) + 2);\r
232   q = p;\r
233   while (*tags) {\r
234     if (*tags == '\n') *q++ = '\r';\r
235     *q++ = *tags++;\r
236   }\r
237   if (*msg != NULLCHAR) {\r
238     *q++ = '\r';\r
239     *q++ = '\n';\r
240     while (*msg) {\r
241       if (*msg == '\n') *q++ = '\r';\r
242       *q++ = *msg++;\r
243     }\r
244   }\r
245   *q = NULLCHAR;\r
246   if (editTagsText != NULL) free(editTagsText);\r
247   editTagsText = p;\r
248   canEditTags = edit;\r
249   \r
250   CheckMenuItem(GetMenu(hwndMain), IDM_Tags, MF_CHECKED);\r
251   if (editTagsDialog) {\r
252     SendMessage(editTagsDialog, WM_INITDIALOG, 0, 0);\r
253     ShowWindow(editTagsDialog, SW_SHOW);\r
254     if(bookUp) SetFocus(hwndMain);\r
255   } else {\r
256     lpProc = MakeProcInstance((FARPROC)EditTagsDialog, hInst);\r
257     CreateDialog(hInst, MAKEINTRESOURCE(DLG_EditTags),\r
258       hwndMain, (DLGPROC)lpProc);\r
259     FreeProcInstance(lpProc);\r
260   }\r
261   editTagsUp = TRUE;\r
262 }\r
263 \r
264 VOID TagsPopUp(char *tags, char *msg)\r
265 {\r
266   HWND hwnd = GetActiveWindow();\r
267   EitherTagsPopUp(tags, msg, FALSE);\r
268   SetActiveWindow(hwnd);\r
269 }\r
270 \r
271 VOID EditTagsPopUp(char *tags, char **dest)\r
272 {\r
273   resPtr = dest;\r
274   EitherTagsPopUp(tags, "", TRUE);\r
275 }\r
276 \r
277 VOID EditTagsProc()\r
278 {\r
279   if (editTagsUp && !bookUp) {\r
280     TagsPopDown();\r
281   } else {\r
282     EditTagsEvent();\r
283   }\r
284 }\r