cleaned up old CVS left overs
[xboard.git] / winboard / wclipbrd.c
1 /*\r
2  * wclipbrd.c -- Clipboard routines for WinBoard\r
3  *\r
4  * Copyright 2000,2009 Free Software Foundation, Inc.\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 <stdio.h>\r
28 #include <stdlib.h>\r
29 #include <malloc.h>\r
30 #include <sys/stat.h>\r
31 \r
32 #include "common.h"\r
33 #include "winboard.h"\r
34 #include "frontend.h"\r
35 #include "backend.h"\r
36 #include "wclipbrd.h"\r
37 \r
38 /* Imports from winboard.c */\r
39 extern HWND hwndMain;\r
40 Boolean ParseFEN(Board b, int *stm, char *FEN);\r
41 \r
42 /* File globals */\r
43 static char *copyTemp;\r
44 static char *pasteTemp;\r
45 \r
46 VOID \r
47 CopyFENToClipboard()\r
48 {\r
49   char *fen = NULL;\r
50 \r
51   fen = PositionToFEN(currentMove, NULL);\r
52   if (!fen) {\r
53     DisplayError("Unable to convert position to FEN.", 0);\r
54     return;\r
55   }\r
56   if (!CopyTextToClipboard(fen))\r
57       DisplayError("Unable to copy FEN to clipboard.", 0);\r
58   free(fen);\r
59 }\r
60 \r
61 /* [AS] */\r
62 HGLOBAL ExportGameListAsText();\r
63 \r
64 VOID CopyGameListToClipboard()\r
65 {\r
66     HGLOBAL hMem = ExportGameListAsText();\r
67     \r
68     if( hMem != NULL ) {\r
69         /* Assign memory block to clipboard */\r
70         BOOL ok = OpenClipboard( hwndMain );\r
71 \r
72         if( ok ) {\r
73             ok = EmptyClipboard();\r
74 \r
75             if( ok ) {\r
76                 if( hMem != SetClipboardData( CF_TEXT, hMem ) ) {\r
77                     ok = FALSE;\r
78                 }\r
79             }\r
80 \r
81             CloseClipboard();\r
82 \r
83             if( ! ok ) {\r
84                 GlobalFree( hMem );\r
85             }\r
86         }\r
87 \r
88         if( ! ok ) {\r
89             DisplayError( "Cannot copy list to clipboard.", 0 );\r
90         }\r
91     }\r
92 }\r
93 \r
94 VOID\r
95 CopyGameToClipboard()\r
96 {\r
97   /* A rather cheesy hack here. Write the game to a file, then read from the\r
98    * file into the clipboard.\r
99    */\r
100   char *buf = NULL;\r
101   FILE *f;\r
102   unsigned long size;\r
103   size_t len;\r
104   struct stat st;\r
105 \r
106   if (!copyTemp) {\r
107     copyTemp = tempnam(NULL, "wbcp");\r
108   }\r
109   if (!copyTemp) {\r
110       DisplayError("Cannot create temporary file name.",0);\r
111       return;\r
112   }\r
113   f = fopen(copyTemp, "w");\r
114   if (!f) {\r
115     DisplayError("Cannot open temporary file.", 0);\r
116     return;\r
117   }\r
118   if (!SaveGame(f,0,"")) {                      /* call into backend */\r
119     DisplayError("Cannot write to temporary file.", 0);\r
120     goto copy_game_to_clipboard_cleanup;\r
121   }\r
122   f = fopen(copyTemp, "rb");\r
123   if (!f) {\r
124     DisplayError("Cannot reopen temporary file.", 0);\r
125     goto copy_game_to_clipboard_cleanup;\r
126   }\r
127   if (fstat(fileno(f), &st) < 0) {\r
128     DisplayError("Cannot determine size of file.", 0);\r
129     goto copy_game_to_clipboard_cleanup;\r
130   }\r
131   size = st.st_size;\r
132   if (size == -1) {\r
133     DisplayError("Cannot determine size of file.", 0);\r
134     goto copy_game_to_clipboard_cleanup;\r
135   }\r
136   rewind(f);\r
137   buf = (char*)malloc(size+1);\r
138   if (!buf) {\r
139     DisplayError("Cannot allocate clipboard buffer.", 0);\r
140     goto copy_game_to_clipboard_cleanup;\r
141   }\r
142   len = fread(buf, sizeof(char), size, f);\r
143   if (len == -1) {\r
144     DisplayError("Cannot read from temporary file.", 0);\r
145     goto copy_game_to_clipboard_cleanup;\r
146   }\r
147   if ((unsigned long)size != (unsigned long)len) { /* sigh */ \r
148       DisplayError("Error reading from temporary file.", 0);\r
149       goto copy_game_to_clipboard_cleanup;\r
150   }\r
151   buf[size] = 0;\r
152   if (!CopyTextToClipboard(buf)) {\r
153       DisplayError("Cannot copy text to clipboard", 0);\r
154   }\r
155 \r
156 copy_game_to_clipboard_cleanup:\r
157   if (buf) free(buf);\r
158   if (f) fclose(f);\r
159 }\r
160 \r
161 \r
162 int \r
163 CopyTextToClipboard(char *text)\r
164 {\r
165   /* some (most?) of the error checking may be overkill, \r
166    * but hey, this is Windows \r
167    */\r
168   HGLOBAL hGlobalMem;\r
169   LPVOID lpGlobalMem;\r
170   BOOL locked;\r
171   UINT lockCount;\r
172   DWORD err;\r
173 \r
174   hGlobalMem = GlobalAlloc(GHND, (DWORD)lstrlen(text)+1);\r
175   if (hGlobalMem == NULL) {\r
176     DisplayError("Unable to allocate memory for clipboard.", 0);\r
177     return FALSE;\r
178   }\r
179   lpGlobalMem = GlobalLock(hGlobalMem);\r
180   if (lpGlobalMem == NULL) {\r
181     DisplayError("Unable to lock clipboard memory.", 0);\r
182     GlobalFree(hGlobalMem);\r
183     return FALSE;\r
184   }\r
185   lstrcpy(lpGlobalMem, text);\r
186   if (appData.debugMode) {\r
187     lockCount = GlobalFlags(hGlobalMem) & GMEM_LOCKCOUNT;\r
188     fprintf(debugFP, "CopyTextToClipboard(): lock count %d\n", lockCount);\r
189   }\r
190   SetLastError(NO_ERROR);\r
191   locked = GlobalUnlock(hGlobalMem);\r
192   err = GetLastError();\r
193   if (appData.debugMode) {\r
194     lockCount = GlobalFlags(hGlobalMem) & GMEM_LOCKCOUNT;\r
195     fprintf(debugFP, "CopyTextToClipboard(): lock count %d\n", lockCount);\r
196   }\r
197   if (!locked) {\r
198     locked = !((err == NO_ERROR) || (err == ERROR_NOT_LOCKED));\r
199     if (appData.debugMode) {\r
200       fprintf(debugFP, \r
201               "CopyTextToClipboard(): err %d locked %d\n", (int)err, locked);\r
202     }\r
203   }\r
204   if (locked) {\r
205     DisplayError("Cannot unlock clipboard memory.", 0);\r
206     GlobalFree(hGlobalMem);\r
207     return FALSE;\r
208   }\r
209   if (!OpenClipboard(hwndMain)) {\r
210     DisplayError("Cannot open clipboard.", 0);\r
211     GlobalFree(hGlobalMem);\r
212     return FALSE;\r
213   }\r
214   if (!EmptyClipboard()) {\r
215     DisplayError("Cannot empty clipboard.", 0);\r
216     return FALSE;\r
217   }\r
218   if (hGlobalMem != SetClipboardData(CF_TEXT, hGlobalMem)) {\r
219     DisplayError("Cannot copy text to clipboard.", 0);\r
220     CloseClipboard();\r
221     GlobalFree(hGlobalMem);\r
222     return FALSE;\r
223   }\r
224   if (!CloseClipboard())\r
225     DisplayError("Cannot close clipboard.", 0);\r
226   \r
227   return TRUE;\r
228 }\r
229 \r
230 /* [AS] Reworked paste functions so they can work with strings too */\r
231 \r
232 VOID PasteFENFromString( char * fen )\r
233 {\r
234   if (appData.debugMode) {\r
235     fprintf(debugFP, "PasteFenFromString(): fen '%s'\n", fen);\r
236   }\r
237   EditPositionPasteFEN(fen); /* call into backend */\r
238   free(fen);\r
239 }\r
240 \r
241 \r
242 VOID\r
243 PasteFENFromClipboard()\r
244 {\r
245   char *fen = NULL;\r
246   if (!PasteTextFromClipboard(&fen)) {\r
247       DisplayError("Unable to paste FEN from clipboard.", 0);\r
248       return;\r
249   }\r
250   PasteFENFromString( fen );\r
251 }\r
252 \r
253 VOID PasteGameFromString( char * buf )\r
254 {\r
255   FILE *f;\r
256   size_t len;\r
257   if (!pasteTemp) {\r
258     pasteTemp = tempnam(NULL, "wbpt");\r
259   }\r
260   f = fopen(pasteTemp, "w");\r
261   if (!f) {\r
262     DisplayError("Unable to create temporary file.", 0);\r
263     free(buf); /* [AS] */\r
264     return;\r
265   }\r
266   len = fwrite(buf, sizeof(char), strlen(buf), f);\r
267   fclose(f);\r
268   if (len != strlen(buf)) {\r
269     DisplayError("Error writing to temporary file.", 0);\r
270     free(buf); /* [AS] */\r
271     return;\r
272   }\r
273   LoadGameFromFile(pasteTemp, 0, "Clipboard", TRUE);\r
274   free( buf ); /* [AS] */\r
275 }\r
276 \r
277 \r
278 VOID\r
279 PasteGameFromClipboard()\r
280 {\r
281   /* Write the clipboard to a temp file, then let LoadGameFromFile()\r
282    * do all the work.  */\r
283   char *buf;\r
284   if (!PasteTextFromClipboard(&buf)) {\r
285     return;\r
286   }\r
287   PasteGameFromString( buf );\r
288 }\r
289 \r
290 /* [AS] Try to detect whether the clipboard contains FEN or PGN data */\r
291 VOID PasteGameOrFENFromClipboard()\r
292 {\r
293   char *buf;\r
294 //  char *tmp;\r
295   Board dummyBoard; int dummy; // [HGM] paste any\r
296 \r
297   if (!PasteTextFromClipboard(&buf)) {\r
298     return;\r
299   }\r
300 \r
301 #if 0\r
302   tmp = buf;\r
303   while( *tmp == ' ' || *tmp == '\t' || *tmp == '\r' || *tmp == '\n' ) {\r
304       tmp++;\r
305   }\r
306 \r
307   if( *tmp == '[' ) {\r
308 #else\r
309   // [HGM] paste any: make still smarter, to allow pasting of games without tags, recognize FEN in stead\r
310   if(!ParseFEN(dummyBoard, &dummy, buf) ) {\r
311 #endif\r
312       PasteGameFromString( buf );\r
313   }\r
314   else {\r
315       PasteFENFromString( buf );\r
316   }\r
317 }\r
318 \r
319 int \r
320 PasteTextFromClipboard(char **text)\r
321 {\r
322   /* some (most?) of the error checking may be overkill, \r
323    * but hey, this is Windows \r
324    */\r
325   HANDLE hClipMem;\r
326   LPVOID lpClipMem;\r
327   BOOL locked = FALSE;\r
328   DWORD err;\r
329   UINT lockCount;\r
330 \r
331   if (!OpenClipboard(hwndMain)) {\r
332     DisplayError("Unable to open clipboard.", 0);\r
333     return FALSE;\r
334   }\r
335   hClipMem = GetClipboardData(CF_TEXT);\r
336   if (hClipMem == NULL) {\r
337     CloseClipboard();\r
338     DisplayError("No text in clipboard.", 0);\r
339     return FALSE;\r
340   }\r
341   lpClipMem = GlobalLock(hClipMem);\r
342   if (lpClipMem == NULL) {\r
343     CloseClipboard();\r
344     DisplayError("Unable to lock clipboard memory.", 0);\r
345     return FALSE;\r
346   }\r
347   *text = (char *) malloc(GlobalSize(hClipMem)+1);\r
348   if (!*text) {\r
349     DisplayError("Unable to allocate memory for text string.", 0);\r
350     CloseClipboard();\r
351     return FALSE;\r
352   }\r
353   lstrcpy(*text, lpClipMem);\r
354   if (appData.debugMode) {\r
355     lockCount = GlobalFlags(hClipMem) & GMEM_LOCKCOUNT;\r
356     fprintf(debugFP, "PasteTextFromClipboard(): lock count %d\n", lockCount);\r
357   }\r
358   SetLastError(NO_ERROR);\r
359 #if 1\r
360   /*suggested by Wilkin Ng*/\r
361   lockCount = GlobalFlags(hClipMem) & GMEM_LOCKCOUNT;\r
362   if (lockCount) {\r
363     locked = GlobalUnlock(hClipMem);\r
364   }\r
365 #else\r
366   locked = GlobalUnlock(hClipMem);\r
367 #endif\r
368   err = GetLastError();\r
369   if (appData.debugMode) {\r
370     lockCount = GlobalFlags(hClipMem) & GMEM_LOCKCOUNT;\r
371     fprintf(debugFP, "PasteTextFromClipboard(): lock count %d\n", lockCount);\r
372   }\r
373   if (!locked) {\r
374     locked = !((err == NO_ERROR) || (err == ERROR_NOT_LOCKED));\r
375     if (appData.debugMode) {\r
376       fprintf(debugFP, \r
377               "PasteTextFromClipboard(): err %d locked %d\n", (int)err, locked);\r
378     }\r
379   }\r
380   if (locked) \r
381     DisplayError("Unable to unlock clipboard memory.", 0);\r
382   \r
383   if (!CloseClipboard())\r
384     DisplayError("Unable to close clipboard.", 0);\r
385   \r
386   return TRUE;\r
387 }\r
388 \r
389 VOID\r
390 DeleteClipboardTempFiles()\r
391 {\r
392   if (copyTemp) remove(copyTemp);\r
393   if (pasteTemp) remove(pasteTemp);\r
394 }\r