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