79ff2a2471c9731db2cca0efb1687d6612579ddf
[xboard.git] / winboard / wclipbrd.c
1 /*\r
2  * wclipbrd.c -- Clipboard routines for WinBoard\r
3  * $Id$\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);\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 \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 \r
198 \r
199 VOID\r
200 PasteFENFromClipboard()\r
201 {\r
202   char *fen = NULL;\r
203   if (!PasteTextFromClipboard(&fen)) {\r
204       DisplayError("Unable to paste FEN from clipboard.", 0);\r
205       return;\r
206   }\r
207   if (appData.debugMode) {\r
208     fprintf(debugFP, "PasteFenFromClipboard(): fen '%s'\n", fen);\r
209   }\r
210   EditPositionPasteFEN(fen); /* call into backend */\r
211   free(fen);\r
212 }\r
213 \r
214 \r
215 VOID\r
216 PasteGameFromClipboard()\r
217 {\r
218   /* Write the clipboard to a temp file, then let LoadGameFromFile()\r
219    * do all the work.  */\r
220   char *buf;\r
221   FILE *f;\r
222   size_t len;\r
223   if (!PasteTextFromClipboard(&buf)) {\r
224     return;\r
225   }\r
226   if (!pasteTemp) {\r
227     pasteTemp = tempnam(NULL, "wbpt");\r
228   }\r
229   f = fopen(pasteTemp, "w");\r
230   if (!f) {\r
231     DisplayError("Unable to create temporary file.", 0);\r
232     return;\r
233   }\r
234   len = fwrite(buf, sizeof(char), strlen(buf), f);\r
235   fclose(f);\r
236   if (len != strlen(buf)) {\r
237     DisplayError("Error writing to temporary file.", 0);\r
238     return;\r
239   }\r
240   LoadGameFromFile(pasteTemp, 0, "Clipboard", TRUE);\r
241 }\r
242 \r
243 \r
244 int \r
245 PasteTextFromClipboard(char **text)\r
246 {\r
247   /* some (most?) of the error checking may be overkill, \r
248    * but hey, this is Windows \r
249    */\r
250   HANDLE hClipMem;\r
251   LPVOID lpClipMem;\r
252   BOOL locked = FALSE;\r
253   DWORD err;\r
254   UINT lockCount;\r
255 \r
256   if (!OpenClipboard(hwndMain)) {\r
257     DisplayError("Unable to open clipboard.", 0);\r
258     return FALSE;\r
259   }\r
260   hClipMem = GetClipboardData(CF_TEXT);\r
261   if (hClipMem == NULL) {\r
262     CloseClipboard();\r
263     DisplayError("No text in clipboard.", 0);\r
264     return FALSE;\r
265   }\r
266   lpClipMem = GlobalLock(hClipMem);\r
267   if (lpClipMem == NULL) {\r
268     CloseClipboard();\r
269     DisplayError("Unable to lock clipboard memory.", 0);\r
270     return FALSE;\r
271   }\r
272   *text = (char *) malloc(GlobalSize(hClipMem)+1);\r
273   if (!*text) {\r
274     DisplayError("Unable to allocate memory for text string.", 0);\r
275     CloseClipboard();\r
276     return FALSE;\r
277   }\r
278   lstrcpy(*text, lpClipMem);\r
279   if (appData.debugMode) {\r
280     lockCount = GlobalFlags(hClipMem) & GMEM_LOCKCOUNT;\r
281     fprintf(debugFP, "PasteTextFromClipboard(): lock count %d\n", lockCount);\r
282   }\r
283   SetLastError(NO_ERROR);\r
284 #if 1\r
285   /*suggested by Wilkin Ng*/\r
286   lockCount = GlobalFlags(hClipMem) & GMEM_LOCKCOUNT;\r
287   if (lockCount) {\r
288     locked = GlobalUnlock(hClipMem);\r
289   }\r
290 #else\r
291   locked = GlobalUnlock(hClipMem);\r
292 #endif\r
293   err = GetLastError();\r
294   if (appData.debugMode) {\r
295     lockCount = GlobalFlags(hClipMem) & GMEM_LOCKCOUNT;\r
296     fprintf(debugFP, "PasteTextFromClipboard(): lock count %d\n", lockCount);\r
297   }\r
298   if (!locked) {\r
299     locked = !((err == NO_ERROR) || (err == ERROR_NOT_LOCKED));\r
300     if (appData.debugMode) {\r
301       fprintf(debugFP, \r
302               "PasteTextFromClipboard(): err %d locked %d\n", err, locked);\r
303     }\r
304   }\r
305   if (locked) \r
306     DisplayError("Unable to unlock clipboard memory.", 0);\r
307   \r
308   if (!CloseClipboard())\r
309     DisplayError("Unable to close clipboard.", 0);\r
310   \r
311   return TRUE;\r
312 }\r
313 \r
314 VOID\r
315 DeleteClipboardTempFiles()\r
316 {\r
317   if (copyTemp) remove(copyTemp);\r
318   if (pasteTemp) remove(pasteTemp);\r
319 }\r