(top-level let): add defsubst.
[bpt/emacs.git] / src / w32select.c
CommitLineData
e9e23e23 1/* Selection processing for Emacs on the Microsoft W32 API.
ee78dc32
GV
2 Copyright (C) 1993, 1994 Free Software Foundation.
3
3b7ad313
EN
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
ee78dc32
GV
20
21/* Written by Kevin Gallo */
22
23#include <config.h>
24#include "lisp.h"
fbd6baed 25#include "w32term.h" /* for all of the w32 includes */
ee78dc32
GV
26#include "dispextern.h" /* frame.h seems to want this */
27#include "frame.h" /* Need this to get the X window of selected_frame */
28#include "blockinput.h"
bbb059f3
AI
29#include "buffer.h"
30#include "charset.h"
31#include "coding.h"
ee78dc32 32
9aa94bd5
KH
33Lisp_Object QCLIPBOARD;
34
bbb059f3
AI
35/* Coding system for communicating with other Windows programs via the
36 clipboard. */
37static Lisp_Object Vclipboard_coding_system;
38
ee78dc32 39#if 0
fbd6baed 40DEFUN ("w32-open-clipboard", Fw32_open_clipboard, Sw32_open_clipboard, 0, 1, 0,
ee78dc32
GV
41 "This opens the clipboard with the given frame pointer.")
42 (frame)
43 Lisp_Object frame;
44{
45 BOOL ok = FALSE;
46
47 if (!NILP (frame))
48 CHECK_LIVE_FRAME (frame, 0);
49
50 BLOCK_INPUT;
51
fbd6baed 52 ok = OpenClipboard ((!NILP (frame) && FRAME_W32_P (XFRAME (frame))) ? FRAME_W32_WINDOW (XFRAME (frame)) : NULL);
ee78dc32
GV
53
54 UNBLOCK_INPUT;
55
56 return (ok ? frame : Qnil);
57}
58
fbd6baed 59DEFUN ("w32-empty-clipboard", Fw32_empty_clipboard, Sw32_empty_clipboard, 0, 0, 0,
ee78dc32
GV
60 "This empties the clipboard and assigns ownership to the window which opened the clipboard.")
61 ()
62{
63 BOOL ok = FALSE;
64
65 BLOCK_INPUT;
66
67 ok = EmptyClipboard ();
68
69 UNBLOCK_INPUT;
70
71 return (ok ? Qt : Qnil);
72}
73
fbd6baed 74DEFUN ("w32-close-clipboard", Fw32_close_clipboard, Sw32_close_clipboard, 0, 0, 0,
ee78dc32
GV
75 "This closes the clipboard.")
76 ()
77{
78 BOOL ok = FALSE;
79
80 BLOCK_INPUT;
81
82 ok = CloseClipboard ();
83
84 UNBLOCK_INPUT;
85
86 return (ok ? Qt : Qnil);
87}
88
89#endif
90
fbd6baed 91DEFUN ("w32-set-clipboard-data", Fw32_set_clipboard_data, Sw32_set_clipboard_data, 1, 2, 0,
ee78dc32
GV
92 "This sets the clipboard data to the given text.")
93 (string, frame)
94 Lisp_Object string, frame;
95{
96 BOOL ok = TRUE;
97 HANDLE htext;
69cddef0
GV
98 int nbytes;
99 int truelen;
100 unsigned char *src;
101 unsigned char *dst;
ee78dc32
GV
102
103 CHECK_STRING (string, 0);
104
105 if (!NILP (frame))
106 CHECK_LIVE_FRAME (frame, 0);
107
108 BLOCK_INPUT;
69cddef0 109
bbb059f3 110 nbytes = STRING_BYTES (XSTRING (string)) + 1;
69cddef0
GV
111 src = XSTRING (string)->data;
112
bbb059f3
AI
113 {
114 /* Since we are now handling multilingual text, we must consider
115 encoding text for the clipboard. */
116 int charsets[MAX_CHARSET + 1];
117 int num;
118
119 bzero (charsets, (MAX_CHARSET + 1) * sizeof (int));
120 num = ((nbytes <= 2 /* Check the possibility of short cut. */
121 || NILP (buffer_defaults.enable_multibyte_characters))
122 ? 0
123 : find_charset_in_str (src, nbytes, charsets, Qnil, 1));
124
125 if (!num || (num == 1 && charsets[CHARSET_ASCII]))
126 {
127 /* No multibyte character in OBJ. We need not encode it. */
69cddef0 128
bbb059f3
AI
129 /* need to know final size after '\r' chars are inserted (the
130 standard CF_TEXT clipboard format uses CRLF line endings,
131 while Emacs uses just LF internally) */
69cddef0 132
bbb059f3
AI
133 truelen = nbytes;
134 dst = src;
135 /* avoid using strchr because it recomputes the length everytime */
136 while ((dst = memchr (dst, '\n', nbytes - (dst - src))) != NULL)
137 {
138 truelen++;
139 dst++;
140 }
69cddef0 141
bbb059f3
AI
142 if ((htext = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, truelen)) == NULL)
143 goto error;
144
145 if ((dst = (unsigned char *) GlobalLock (htext)) == NULL)
146 goto error;
ee78dc32 147
bbb059f3
AI
148 /* convert to CRLF line endings expected by clipboard */
149 while (1)
150 {
151 unsigned char *next;
152 /* copy next line or remaining bytes including '\0' */
153 next = _memccpy (dst, src, '\n', nbytes);
154 if (next)
155 {
156 /* copied one line ending with '\n' */
157 int copied = next - dst;
158 nbytes -= copied;
159 src += copied;
160 /* insert '\r' before '\n' */
161 next[-1] = '\r';
162 next[0] = '\n';
163 dst = next + 1;
164 }
165 else
166 /* copied remaining partial line -> now finished */
167 break;
168 }
ee78dc32 169
bbb059f3 170 GlobalUnlock (htext);
0108f679
AI
171
172 Vlast_coding_system_used = Qraw_text;
bbb059f3
AI
173 }
174 else
175 {
176 /* We must encode contents of OBJ to compound text format.
177 The format is compatible with what the target `STRING'
178 expects if OBJ contains only ASCII and Latin-1
179 characters. */
180 int bufsize;
181 struct coding_system coding;
182 HANDLE htext2;
183
184 setup_coding_system
185 (Fcheck_coding_system (Vclipboard_coding_system), &coding);
186 coding.mode |= CODING_MODE_LAST_BLOCK;
187 bufsize = encoding_buffer_size (&coding, nbytes);
188 if ((htext = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, bufsize)) == NULL)
189 goto error;
190 if ((dst = (unsigned char *) GlobalLock (htext)) == NULL)
191 goto error;
192 encode_coding (&coding, src, dst, nbytes, bufsize);
0108f679 193 Vlast_coding_system_used = coding.symbol;
bbb059f3
AI
194 GlobalUnlock (htext);
195 /* Shrink data block to actual size. */
196 htext2 = GlobalReAlloc (htext, coding.produced, GMEM_MOVEABLE | GMEM_DDESHARE);
197 if (htext2 != NULL) htext = htext2;
198 }
199 }
ee78dc32 200
fbd6baed 201 if (!OpenClipboard ((!NILP (frame) && FRAME_W32_P (XFRAME (frame))) ? FRAME_W32_WINDOW (XFRAME (frame)) : NULL))
ee78dc32
GV
202 goto error;
203
204 ok = EmptyClipboard () && SetClipboardData (CF_TEXT, htext);
205
206 CloseClipboard ();
207
208 if (ok) goto done;
209
210 error:
211
212 ok = FALSE;
213 if (htext) GlobalFree (htext);
214
215 done:
216 UNBLOCK_INPUT;
217
218 return (ok ? string : Qnil);
219}
220
fbd6baed 221DEFUN ("w32-get-clipboard-data", Fw32_get_clipboard_data, Sw32_get_clipboard_data, 0, 1, 0,
ee78dc32
GV
222 "This gets the clipboard data in text format.")
223 (frame)
224 Lisp_Object frame;
225{
226 HANDLE htext;
227 Lisp_Object ret = Qnil;
228
229 if (!NILP (frame))
230 CHECK_LIVE_FRAME (frame, 0);
231
232 BLOCK_INPUT;
233
fbd6baed 234 if (!OpenClipboard ((!NILP (frame) && FRAME_W32_P (XFRAME (frame))) ? FRAME_W32_WINDOW (XFRAME (frame)) : NULL))
ee78dc32
GV
235 goto done;
236
237 if ((htext = GetClipboardData (CF_TEXT)) == NULL)
238 goto closeclip;
239
ee78dc32 240 {
69cddef0
GV
241 unsigned char *src;
242 unsigned char *dst;
ee78dc32 243 int nbytes;
69cddef0 244 int truelen;
ee78dc32 245
69cddef0 246 if ((src = (unsigned char *) GlobalLock (htext)) == NULL)
ee78dc32
GV
247 goto closeclip;
248
69cddef0
GV
249 nbytes = strlen (src);
250
bbb059f3 251 if (! NILP (buffer_defaults.enable_multibyte_characters))
69cddef0 252 {
bbb059f3
AI
253 int bufsize;
254 unsigned char *buf;
255 struct coding_system coding;
256
257 setup_coding_system
258 (Fcheck_coding_system(Vclipboard_coding_system), &coding);
259 coding.mode |= CODING_MODE_LAST_BLOCK;
260 bufsize = decoding_buffer_size (&coding, nbytes);
261 buf = (unsigned char *) xmalloc (bufsize);
262 decode_coding (&coding, src, buf, nbytes, bufsize);
0108f679 263 Vlast_coding_system_used = coding.symbol;
bbb059f3
AI
264 truelen = (coding.fake_multibyte
265 ? multibyte_chars_in_text (buf, coding.produced)
266 : coding.produced_char);
267 ret = make_string_from_bytes ((char *) buf, truelen, coding.produced);
268 xfree (buf);
69cddef0 269 }
bbb059f3
AI
270 else
271 {
272 /* need to know final size after '\r' chars are removed because
273 we can't change the string size manually, and doing an extra
274 copy is silly */
275
276 truelen = nbytes;
277 dst = src;
278 /* avoid using strchr because it recomputes the length everytime */
279 while ((dst = memchr (dst, '\r', nbytes - (dst - src))) != NULL)
280 {
281 truelen--;
282 dst++;
283 }
69cddef0 284
bbb059f3 285 ret = make_uninit_string (truelen);
69cddef0 286
bbb059f3
AI
287 /* convert CRLF line endings (the standard CF_TEXT clipboard
288 format) to LF endings as used internally by Emacs */
69cddef0 289
bbb059f3
AI
290 dst = XSTRING (ret)->data;
291 while (1)
69cddef0 292 {
bbb059f3
AI
293 unsigned char *next;
294 /* copy next line or remaining bytes excluding '\0' */
295 next = _memccpy (dst, src, '\r', nbytes);
296 if (next)
297 {
298 /* copied one line ending with '\r' */
299 int copied = next - dst;
300 nbytes -= copied;
301 dst += copied - 1; /* overwrite '\r' */
302 src += copied;
303 }
304 else
305 /* copied remaining partial line -> now finished */
306 break;
307 }
0108f679
AI
308
309 Vlast_coding_system_used = Qraw_text;
69cddef0
GV
310 }
311
ee78dc32
GV
312 GlobalUnlock (htext);
313 }
314
315 closeclip:
316 CloseClipboard ();
317
318 done:
319 UNBLOCK_INPUT;
320
321 return (ret);
322}
323
9aa94bd5
KH
324/* Support checking for a clipboard selection. */
325
326DEFUN ("x-selection-exists-p", Fx_selection_exists_p, Sx_selection_exists_p,
327 0, 1, 0,
328 "Whether there is an owner for the given X Selection.\n\
329The arg should be the name of the selection in question, typically one of\n\
330the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\
331\(Those are literal upper-case symbol names, since that's what X expects.)\n\
332For convenience, the symbol nil is the same as `PRIMARY',\n\
333and t is the same as `SECONDARY'.")
334 (selection)
335 Lisp_Object selection;
336{
337 CHECK_SYMBOL (selection, 0);
338
339 /* Return nil for PRIMARY and SECONDARY selections; for CLIPBOARD, check
340 if the clipboard currently has valid text format contents. */
341
342 if (EQ (selection, QCLIPBOARD))
343 {
344 Lisp_Object val = Qnil;
345
346 if (OpenClipboard (NULL))
347 {
348 int format = 0;
349 while (format = EnumClipboardFormats (format))
350 if (format == CF_TEXT)
351 {
352 val = Qt;
353 break;
354 }
355 CloseClipboard ();
356 }
357 return val;
358 }
359 return Qnil;
360}
361
ee78dc32 362void
fbd6baed 363syms_of_w32select ()
ee78dc32
GV
364{
365#if 0
fbd6baed
GV
366 defsubr (&Sw32_open_clipboard);
367 defsubr (&Sw32_empty_clipboard);
368 defsubr (&Sw32_close_clipboard);
ee78dc32 369#endif
fbd6baed
GV
370 defsubr (&Sw32_set_clipboard_data);
371 defsubr (&Sw32_get_clipboard_data);
9aa94bd5
KH
372 defsubr (&Sx_selection_exists_p);
373
bbb059f3
AI
374 DEFVAR_LISP ("clipboard-coding-system", &Vclipboard_coding_system,
375 "Coding system for communicating with other X clients.\n\
376When sending or receiving text via cut_buffer, selection, and clipboard,\n\
377the text is encoded or decoded by this coding system.\n\
378A default value is `compound-text'");
379 Vclipboard_coding_system=intern ("iso-latin-1-dos");
380 staticpro(&Vclipboard_coding_system);
381
9aa94bd5 382 QCLIPBOARD = intern ("CLIPBOARD"); staticpro (&QCLIPBOARD);
ee78dc32 383}