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