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