changes from Alessandro Scotti from 20051129
[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 $
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);
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 \r
61 VOID\r
62 CopyGameToClipboard()\r
63 {\r
64   /* A rather cheesy hack here. Write the game to a file, then read from the\r
65    * file into the clipboard.\r
66    */\r
67   char *buf = NULL;\r
68   FILE *f;\r
69   unsigned long size;\r
70   size_t len;\r
71   struct stat st;\r
72 \r
73   if (!copyTemp) {\r
74     copyTemp = tempnam(NULL, "wbcp");\r
75   }\r
76   if (!copyTemp) {\r
77       DisplayError("Cannot create temporary file name.",0);\r
78       return;\r
79   }\r
80   f = fopen(copyTemp, "w");\r
81   if (!f) {\r
82     DisplayError("Cannot open temporary file.", 0);\r
83     return;\r
84   }\r
85   if (!SaveGame(f,0,"")) {                      /* call into backend */\r
86     DisplayError("Cannot write to temporary file.", 0);\r
87     goto copy_game_to_clipboard_cleanup;\r
88   }\r
89   f = fopen(copyTemp, "rb");\r
90   if (!f) {\r
91     DisplayError("Cannot reopen temporary file.", 0);\r
92     goto copy_game_to_clipboard_cleanup;\r
93   }\r
94   if (fstat(fileno(f), &st) < 0) {\r
95     DisplayError("Cannot determine size of file.", 0);\r
96     goto copy_game_to_clipboard_cleanup;\r
97   }\r
98   size = st.st_size;\r
99   if (size == -1) {\r
100     DisplayError("Cannot determine size of file.", 0);\r
101     goto copy_game_to_clipboard_cleanup;\r
102   }\r
103   rewind(f);\r
104   buf = (char*)malloc(size+1);\r
105   if (!buf) {\r
106     DisplayError("Cannot allocate clipboard buffer.", 0);\r
107     goto copy_game_to_clipboard_cleanup;\r
108   }\r
109   len = fread(buf, sizeof(char), size, f);\r
110   if (len == -1) {\r
111     DisplayError("Cannot read from temporary file.", 0);\r
112     goto copy_game_to_clipboard_cleanup;\r
113   }\r
114   if ((unsigned long)size != (unsigned long)len) { /* sigh */ \r
115       DisplayError("Error reading from temporary file.", 0);\r
116       goto copy_game_to_clipboard_cleanup;\r
117   }\r
118   buf[size] = 0;\r
119   if (!CopyTextToClipboard(buf)) {\r
120       DisplayError("Cannot copy text to clipboard", 0);\r
121   }\r
122 \r
123 copy_game_to_clipboard_cleanup:\r
124   if (buf) free(buf);\r
125   if (f) fclose(f);\r
126 }\r
127 \r
128 \r
129 int \r
130 CopyTextToClipboard(char *text)\r
131 {\r
132   /* some (most?) of the error checking may be overkill, \r
133    * but hey, this is Windows \r
134    */\r
135   HGLOBAL hGlobalMem;\r
136   LPVOID lpGlobalMem;\r
137   BOOL locked;\r
138   UINT lockCount;\r
139   DWORD err;\r
140 \r
141   hGlobalMem = GlobalAlloc(GHND, (DWORD)lstrlen(text)+1);\r
142   if (hGlobalMem == NULL) {\r
143     DisplayError("Unable to allocate memory for clipboard.", 0);\r
144     return FALSE;\r
145   }\r
146   lpGlobalMem = GlobalLock(hGlobalMem);\r
147   if (lpGlobalMem == NULL) {\r
148     DisplayError("Unable to lock clipboard memory.", 0);\r
149     GlobalFree(hGlobalMem);\r
150     return FALSE;\r
151   }\r
152   lstrcpy(lpGlobalMem, text);\r
153   if (appData.debugMode) {\r
154     lockCount = GlobalFlags(hGlobalMem) & GMEM_LOCKCOUNT;\r
155     fprintf(debugFP, "CopyTextToClipboard(): lock count %d\n", lockCount);\r
156   }\r
157   SetLastError(NO_ERROR);\r
158   locked = GlobalUnlock(hGlobalMem);\r
159   err = GetLastError();\r
160   if (appData.debugMode) {\r
161     lockCount = GlobalFlags(hGlobalMem) & GMEM_LOCKCOUNT;\r
162     fprintf(debugFP, "CopyTextToClipboard(): lock count %d\n", lockCount);\r
163   }\r
164   if (!locked) {\r
165     locked = !((err == NO_ERROR) || (err == ERROR_NOT_LOCKED));\r
166     if (appData.debugMode) {\r
167       fprintf(debugFP, \r
168               "CopyTextToClipboard(): err %d locked %d\n", err, locked);\r
169     }\r
170   }\r
171   if (locked) {\r
172     DisplayError("Cannot unlock clipboard memory.", 0);\r
173     GlobalFree(hGlobalMem);\r
174     return FALSE;\r
175   }\r
176   if (!OpenClipboard(hwndMain)) {\r
177     DisplayError("Cannot open clipboard.", 0);\r
178     GlobalFree(hGlobalMem);\r
179     return FALSE;\r
180   }\r
181   if (!EmptyClipboard()) {\r
182     DisplayError("Cannot empty clipboard.", 0);\r
183     return FALSE;\r
184   }\r
185   if (hGlobalMem != SetClipboardData(CF_TEXT, hGlobalMem)) {\r
186     DisplayError("Cannot copy text to clipboard.", 0);\r
187     CloseClipboard();\r
188     GlobalFree(hGlobalMem);\r
189     return FALSE;\r
190   }\r
191   if (!CloseClipboard())\r
192     DisplayError("Cannot close clipboard.", 0);\r
193   \r
194   return TRUE;\r
195 }\r
196 \r
197 /* [AS] Reworked paste functions so they can work with strings too */
198
199 VOID PasteFENFromString( char * fen )
200 {
201   if (appData.debugMode) {
202     fprintf(debugFP, "PasteFenFromString(): fen '%s'\n", fen);
203   }
204   EditPositionPasteFEN(fen); /* call into backend */
205   free(fen);
206 }
207 \r
208 \r
209 VOID\r
210 PasteFENFromClipboard()\r
211 {\r
212   char *fen = NULL;\r
213   if (!PasteTextFromClipboard(&fen)) {\r
214       DisplayError("Unable to paste FEN from clipboard.", 0);\r
215       return;\r
216   }\r
217   PasteFENFromString( fen );
218 }\r
219 \r
220 VOID PasteGameFromString( char * buf )
221 {\r
222   FILE *f;\r
223   size_t len;\r
224   if (!pasteTemp) {\r
225     pasteTemp = tempnam(NULL, "wbpt");\r
226   }\r
227   f = fopen(pasteTemp, "w");\r
228   if (!f) {\r
229     DisplayError("Unable to create temporary file.", 0);\r
230     free(buf); /* [AS] */
231     return;\r
232   }\r
233   len = fwrite(buf, sizeof(char), strlen(buf), f);\r
234   fclose(f);\r
235   if (len != strlen(buf)) {\r
236     DisplayError("Error writing to temporary file.", 0);\r
237     free(buf); /* [AS] */
238     return;\r
239   }\r
240   LoadGameFromFile(pasteTemp, 0, "Clipboard", TRUE);\r
241   free( buf ); /* [AS] */
242 }
243
244
245 VOID
246 PasteGameFromClipboard()
247 {
248   /* Write the clipboard to a temp file, then let LoadGameFromFile()
249    * do all the work.  */
250   char *buf;
251   if (!PasteTextFromClipboard(&buf)) {
252     return;
253   }
254   PasteGameFromString( buf );
255 }\r
256 \r
257 /* [AS] Try to detect whether the clipboard contains FEN or PGN data */
258 VOID PasteGameOrFENFromClipboard()
259 {
260   char *buf;
261   char *tmp;
262
263   if (!PasteTextFromClipboard(&buf)) {
264     return;
265   }
266
267   tmp = buf;
268   while( *tmp == ' ' || *tmp == '\t' || *tmp == '\r' || *tmp == '\n' ) {
269       tmp++;
270   }
271
272   if( *tmp == '[' ) {
273       PasteGameFromString( buf );
274   }
275   else {
276       PasteFENFromString( buf );
277   }
278 }
279 \r
280 int \r
281 PasteTextFromClipboard(char **text)\r
282 {\r
283   /* some (most?) of the error checking may be overkill, \r
284    * but hey, this is Windows \r
285    */\r
286   HANDLE hClipMem;\r
287   LPVOID lpClipMem;\r
288   BOOL locked = FALSE;\r
289   DWORD err;\r
290   UINT lockCount;\r
291 \r
292   if (!OpenClipboard(hwndMain)) {\r
293     DisplayError("Unable to open clipboard.", 0);\r
294     return FALSE;\r
295   }\r
296   hClipMem = GetClipboardData(CF_TEXT);\r
297   if (hClipMem == NULL) {\r
298     CloseClipboard();\r
299     DisplayError("No text in clipboard.", 0);\r
300     return FALSE;\r
301   }\r
302   lpClipMem = GlobalLock(hClipMem);\r
303   if (lpClipMem == NULL) {\r
304     CloseClipboard();\r
305     DisplayError("Unable to lock clipboard memory.", 0);\r
306     return FALSE;\r
307   }\r
308   *text = (char *) malloc(GlobalSize(hClipMem)+1);\r
309   if (!*text) {\r
310     DisplayError("Unable to allocate memory for text string.", 0);\r
311     CloseClipboard();\r
312     return FALSE;\r
313   }\r
314   lstrcpy(*text, lpClipMem);\r
315   if (appData.debugMode) {\r
316     lockCount = GlobalFlags(hClipMem) & GMEM_LOCKCOUNT;\r
317     fprintf(debugFP, "PasteTextFromClipboard(): lock count %d\n", lockCount);\r
318   }\r
319   SetLastError(NO_ERROR);\r
320 #if 1\r
321   /*suggested by Wilkin Ng*/\r
322   lockCount = GlobalFlags(hClipMem) & GMEM_LOCKCOUNT;\r
323   if (lockCount) {\r
324     locked = GlobalUnlock(hClipMem);\r
325   }\r
326 #else\r
327   locked = GlobalUnlock(hClipMem);\r
328 #endif\r
329   err = GetLastError();\r
330   if (appData.debugMode) {\r
331     lockCount = GlobalFlags(hClipMem) & GMEM_LOCKCOUNT;\r
332     fprintf(debugFP, "PasteTextFromClipboard(): lock count %d\n", lockCount);\r
333   }\r
334   if (!locked) {\r
335     locked = !((err == NO_ERROR) || (err == ERROR_NOT_LOCKED));\r
336     if (appData.debugMode) {\r
337       fprintf(debugFP, \r
338               "PasteTextFromClipboard(): err %d locked %d\n", err, locked);\r
339     }\r
340   }\r
341   if (locked) \r
342     DisplayError("Unable to unlock clipboard memory.", 0);\r
343   \r
344   if (!CloseClipboard())\r
345     DisplayError("Unable to close clipboard.", 0);\r
346   \r
347   return TRUE;\r
348 }\r
349 \r
350 VOID\r
351 DeleteClipboardTempFiles()\r
352 {\r
353   if (copyTemp) remove(copyTemp);\r
354   if (pasteTemp) remove(pasteTemp);\r
355 }\r