*** empty log message ***
[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 26#include "dispextern.h" /* frame.h seems to want this */
3e4731a3 27#include "keyboard.h"
ee78dc32
GV
28#include "frame.h" /* Need this to get the X window of selected_frame */
29#include "blockinput.h"
bbb059f3
AI
30#include "buffer.h"
31#include "charset.h"
32#include "coding.h"
ee78dc32 33
9aa94bd5
KH
34Lisp_Object QCLIPBOARD;
35
bbb059f3
AI
36/* Coding system for communicating with other Windows programs via the
37 clipboard. */
72aca5fa 38static Lisp_Object Vselection_coding_system;
bbb059f3 39
06466d9a 40/* Coding system for the next communicating with other Windows programs. */
93cbf229
GV
41static Lisp_Object Vnext_selection_coding_system;
42
06466d9a
JR
43/* The last text we put into the clipboard. This is used to prevent
44 passing back our own text from the clipboard, instead of using the
45 kill ring. The former is undesirable because the clipboard data
46 could be MULEtilated by inappropriately chosen
47 (next-)selection-coding-system. For this reason, we must store the
48 text *after* it was encoded/Unix-to-DOS-converted. */
49static unsigned char *last_clipboard_text = NULL;
50static size_t clipboard_storage_size = 0;
51
ee78dc32 52#if 0
fbd6baed 53DEFUN ("w32-open-clipboard", Fw32_open_clipboard, Sw32_open_clipboard, 0, 1, 0,
ee78dc32
GV
54 "This opens the clipboard with the given frame pointer.")
55 (frame)
56 Lisp_Object frame;
57{
58 BOOL ok = FALSE;
59
60 if (!NILP (frame))
61 CHECK_LIVE_FRAME (frame, 0);
62
63 BLOCK_INPUT;
64
fbd6baed 65 ok = OpenClipboard ((!NILP (frame) && FRAME_W32_P (XFRAME (frame))) ? FRAME_W32_WINDOW (XFRAME (frame)) : NULL);
ee78dc32
GV
66
67 UNBLOCK_INPUT;
68
69 return (ok ? frame : Qnil);
70}
71
fbd6baed 72DEFUN ("w32-empty-clipboard", Fw32_empty_clipboard, Sw32_empty_clipboard, 0, 0, 0,
ee78dc32
GV
73 "This empties the clipboard and assigns ownership to the window which opened the clipboard.")
74 ()
75{
76 BOOL ok = FALSE;
77
78 BLOCK_INPUT;
79
80 ok = EmptyClipboard ();
81
82 UNBLOCK_INPUT;
83
84 return (ok ? Qt : Qnil);
85}
86
fbd6baed 87DEFUN ("w32-close-clipboard", Fw32_close_clipboard, Sw32_close_clipboard, 0, 0, 0,
ee78dc32
GV
88 "This closes the clipboard.")
89 ()
90{
91 BOOL ok = FALSE;
92
93 BLOCK_INPUT;
94
95 ok = CloseClipboard ();
96
97 UNBLOCK_INPUT;
98
99 return (ok ? Qt : Qnil);
100}
101
102#endif
103
fbd6baed 104DEFUN ("w32-set-clipboard-data", Fw32_set_clipboard_data, Sw32_set_clipboard_data, 1, 2, 0,
ee78dc32
GV
105 "This sets the clipboard data to the given text.")
106 (string, frame)
107 Lisp_Object string, frame;
108{
109 BOOL ok = TRUE;
110 HANDLE htext;
69cddef0 111 int nbytes;
0ece9ef6 112 int truelen, nlines = 0;
69cddef0
GV
113 unsigned char *src;
114 unsigned char *dst;
0ece9ef6 115
ee78dc32
GV
116 CHECK_STRING (string, 0);
117
118 if (!NILP (frame))
119 CHECK_LIVE_FRAME (frame, 0);
120
121 BLOCK_INPUT;
69cddef0 122
bbb059f3 123 nbytes = STRING_BYTES (XSTRING (string)) + 1;
69cddef0 124 src = XSTRING (string)->data;
0ece9ef6
AI
125 dst = src;
126
127 /* We need to know how many lines there are, since we need CRLF line
128 termination for compatibility with other Windows Programs.
129 avoid using strchr because it recomputes the length every time */
130 while ((dst = memchr (dst, '\n', nbytes - (dst - src))) != NULL)
131 {
132 nlines++;
133 dst++;
134 }
69cddef0 135
bbb059f3
AI
136 {
137 /* Since we are now handling multilingual text, we must consider
138 encoding text for the clipboard. */
69ebbf81 139 int charset_info = find_charset_in_text (src, XSTRING (string)->size,
11f292ed 140 nbytes, NULL, Qnil);
bbb059f3 141
69ebbf81 142 if (charset_info == 0)
bbb059f3
AI
143 {
144 /* No multibyte character in OBJ. We need not encode it. */
69cddef0 145
c0ca703b 146 /* Need to know final size after CR chars are inserted (the
bbb059f3 147 standard CF_TEXT clipboard format uses CRLF line endings,
c0ca703b 148 while Emacs uses just LF internally). */
69cddef0 149
0ece9ef6 150 truelen = nbytes + nlines;
69cddef0 151
bbb059f3
AI
152 if ((htext = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, truelen)) == NULL)
153 goto error;
154
155 if ((dst = (unsigned char *) GlobalLock (htext)) == NULL)
156 goto error;
ee78dc32 157
bbb059f3
AI
158 /* convert to CRLF line endings expected by clipboard */
159 while (1)
160 {
161 unsigned char *next;
162 /* copy next line or remaining bytes including '\0' */
163 next = _memccpy (dst, src, '\n', nbytes);
164 if (next)
165 {
166 /* copied one line ending with '\n' */
167 int copied = next - dst;
168 nbytes -= copied;
169 src += copied;
170 /* insert '\r' before '\n' */
171 next[-1] = '\r';
172 next[0] = '\n';
173 dst = next + 1;
174 }
175 else
176 /* copied remaining partial line -> now finished */
177 break;
178 }
ee78dc32 179
bbb059f3 180 GlobalUnlock (htext);
0108f679
AI
181
182 Vlast_coding_system_used = Qraw_text;
bbb059f3
AI
183 }
184 else
185 {
06466d9a
JR
186 /* We must encode contents of OBJ to the selection coding
187 system. */
bbb059f3
AI
188 int bufsize;
189 struct coding_system coding;
190 HANDLE htext2;
191
93cbf229
GV
192 if (NILP (Vnext_selection_coding_system))
193 Vnext_selection_coding_system = Vselection_coding_system;
bbb059f3 194 setup_coding_system
93cbf229 195 (Fcheck_coding_system (Vnext_selection_coding_system), &coding);
69ebbf81
KH
196 coding.src_multibyte = 1;
197 coding.dst_multibyte = 0;
93cbf229 198 Vnext_selection_coding_system = Qnil;
bbb059f3 199 coding.mode |= CODING_MODE_LAST_BLOCK;
43df7d0b 200 bufsize = encoding_buffer_size (&coding, nbytes);
bbb059f3
AI
201 if ((htext = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, bufsize)) == NULL)
202 goto error;
203 if ((dst = (unsigned char *) GlobalLock (htext)) == NULL)
204 goto error;
205 encode_coding (&coding, src, dst, nbytes, bufsize);
0108f679 206 Vlast_coding_system_used = coding.symbol;
06466d9a
JR
207
208 /* Stash away the data we are about to put into the clipboard, so we
209 could later check inside Fw32_get_clipboard_data whether
210 the clipboard still holds our data. */
211 if (clipboard_storage_size < coding.produced)
212 {
213 clipboard_storage_size = coding.produced + 100;
214 last_clipboard_text = (char *) xrealloc (last_clipboard_text,
215 clipboard_storage_size);
216 }
217 if (last_clipboard_text)
218 memcpy (last_clipboard_text, dst, coding.produced);
219
bbb059f3 220 GlobalUnlock (htext);
06466d9a 221
bbb059f3 222 /* Shrink data block to actual size. */
06466d9a
JR
223 htext2 = GlobalReAlloc (htext, coding.produced,
224 GMEM_MOVEABLE | GMEM_DDESHARE);
bbb059f3
AI
225 if (htext2 != NULL) htext = htext2;
226 }
227 }
ee78dc32 228
fbd6baed 229 if (!OpenClipboard ((!NILP (frame) && FRAME_W32_P (XFRAME (frame))) ? FRAME_W32_WINDOW (XFRAME (frame)) : NULL))
ee78dc32 230 goto error;
06466d9a 231
ee78dc32
GV
232 ok = EmptyClipboard () && SetClipboardData (CF_TEXT, htext);
233
234 CloseClipboard ();
235
236 if (ok) goto done;
237
238 error:
239
240 ok = FALSE;
241 if (htext) GlobalFree (htext);
06466d9a
JR
242 if (last_clipboard_text)
243 *last_clipboard_text = '\0';
244
ee78dc32
GV
245 done:
246 UNBLOCK_INPUT;
247
248 return (ok ? string : Qnil);
249}
250
fbd6baed 251DEFUN ("w32-get-clipboard-data", Fw32_get_clipboard_data, Sw32_get_clipboard_data, 0, 1, 0,
ee78dc32
GV
252 "This gets the clipboard data in text format.")
253 (frame)
254 Lisp_Object frame;
255{
256 HANDLE htext;
257 Lisp_Object ret = Qnil;
258
259 if (!NILP (frame))
260 CHECK_LIVE_FRAME (frame, 0);
261
262 BLOCK_INPUT;
263
fbd6baed 264 if (!OpenClipboard ((!NILP (frame) && FRAME_W32_P (XFRAME (frame))) ? FRAME_W32_WINDOW (XFRAME (frame)) : NULL))
ee78dc32
GV
265 goto done;
266
267 if ((htext = GetClipboardData (CF_TEXT)) == NULL)
268 goto closeclip;
269
ee78dc32 270 {
69cddef0
GV
271 unsigned char *src;
272 unsigned char *dst;
ee78dc32 273 int nbytes;
69cddef0 274 int truelen;
c0ca703b 275 int require_decoding = 0;
ee78dc32 276
69cddef0 277 if ((src = (unsigned char *) GlobalLock (htext)) == NULL)
ee78dc32
GV
278 goto closeclip;
279
69cddef0
GV
280 nbytes = strlen (src);
281
06466d9a
JR
282 /* If the text in clipboard is identical to what we put there
283 last time w32_set_clipboard_data was called, pretend there's no
284 data in the clipboard. This is so we don't pass our own text
285 from the clipboard (which might be troublesome if the killed
286 text includes null characters). */
287 if (last_clipboard_text
288 && clipboard_storage_size >= nbytes
289 && memcmp(last_clipboard_text, src, nbytes) == 0)
290 goto closeclip;
291
93cbf229
GV
292 if (
293#if 1
294 1
295#else
296 ! NILP (buffer_defaults.enable_multibyte_characters)
297#endif
298 )
299 {
c0ca703b 300 /* If the clipboard data contains any non-ascii code, we
93cbf229
GV
301 need to decode it. */
302 int i;
303
304 for (i = 0; i < nbytes; i++)
305 {
306 if (src[i] >= 0x80)
307 {
c0ca703b 308 require_decoding = 1;
93cbf229
GV
309 break;
310 }
311 }
312 }
313
c0ca703b 314 if (require_decoding)
69cddef0 315 {
bbb059f3
AI
316 int bufsize;
317 unsigned char *buf;
318 struct coding_system coding;
319
93cbf229
GV
320 if (NILP (Vnext_selection_coding_system))
321 Vnext_selection_coding_system = Vselection_coding_system;
bbb059f3 322 setup_coding_system
93cbf229 323 (Fcheck_coding_system (Vnext_selection_coding_system), &coding);
69ebbf81
KH
324 coding.src_multibyte = 0;
325 coding.dst_multibyte = 1;
93cbf229 326 Vnext_selection_coding_system = Qnil;
bbb059f3
AI
327 coding.mode |= CODING_MODE_LAST_BLOCK;
328 bufsize = decoding_buffer_size (&coding, nbytes);
329 buf = (unsigned char *) xmalloc (bufsize);
330 decode_coding (&coding, src, buf, nbytes, bufsize);
0108f679 331 Vlast_coding_system_used = coding.symbol;
06466d9a
JR
332 ret = make_string_from_bytes ((char *) buf,
333 coding.produced_char, coding.produced);
bbb059f3 334 xfree (buf);
69cddef0 335 }
bbb059f3
AI
336 else
337 {
c0ca703b
GV
338 /* Need to know final size after CR chars are removed because we
339 can't change the string size manually, and doing an extra
340 copy is silly. Note that we only remove CR when it appears
341 as part of CRLF. */
bbb059f3
AI
342
343 truelen = nbytes;
344 dst = src;
345 /* avoid using strchr because it recomputes the length everytime */
346 while ((dst = memchr (dst, '\r', nbytes - (dst - src))) != NULL)
347 {
c0ca703b
GV
348 if (dst[1] == '\n') /* safe because of trailing '\0' */
349 truelen--;
bbb059f3
AI
350 dst++;
351 }
69cddef0 352
bbb059f3 353 ret = make_uninit_string (truelen);
69cddef0 354
c0ca703b
GV
355 /* Convert CRLF line endings (the standard CF_TEXT clipboard
356 format) to LF endings as used internally by Emacs. */
69cddef0 357
bbb059f3
AI
358 dst = XSTRING (ret)->data;
359 while (1)
69cddef0 360 {
bbb059f3
AI
361 unsigned char *next;
362 /* copy next line or remaining bytes excluding '\0' */
363 next = _memccpy (dst, src, '\r', nbytes);
364 if (next)
365 {
366 /* copied one line ending with '\r' */
367 int copied = next - dst;
368 nbytes -= copied;
c0ca703b 369 dst += copied;
bbb059f3 370 src += copied;
c0ca703b
GV
371 if (*src == '\n')
372 dst--; /* overwrite '\r' with '\n' */
373 }
bbb059f3
AI
374 else
375 /* copied remaining partial line -> now finished */
376 break;
377 }
0108f679
AI
378
379 Vlast_coding_system_used = Qraw_text;
69cddef0
GV
380 }
381
ee78dc32
GV
382 GlobalUnlock (htext);
383 }
384
385 closeclip:
386 CloseClipboard ();
387
388 done:
389 UNBLOCK_INPUT;
390
391 return (ret);
392}
393
9aa94bd5
KH
394/* Support checking for a clipboard selection. */
395
396DEFUN ("x-selection-exists-p", Fx_selection_exists_p, Sx_selection_exists_p,
397 0, 1, 0,
398 "Whether there is an owner for the given X Selection.\n\
399The arg should be the name of the selection in question, typically one of\n\
400the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\
401\(Those are literal upper-case symbol names, since that's what X expects.)\n\
402For convenience, the symbol nil is the same as `PRIMARY',\n\
403and t is the same as `SECONDARY'.")
404 (selection)
405 Lisp_Object selection;
406{
407 CHECK_SYMBOL (selection, 0);
408
409 /* Return nil for PRIMARY and SECONDARY selections; for CLIPBOARD, check
410 if the clipboard currently has valid text format contents. */
411
412 if (EQ (selection, QCLIPBOARD))
413 {
414 Lisp_Object val = Qnil;
415
416 if (OpenClipboard (NULL))
417 {
418 int format = 0;
419 while (format = EnumClipboardFormats (format))
420 if (format == CF_TEXT)
421 {
422 val = Qt;
423 break;
424 }
425 CloseClipboard ();
426 }
427 return val;
428 }
429 return Qnil;
430}
431
ee78dc32 432void
fbd6baed 433syms_of_w32select ()
ee78dc32
GV
434{
435#if 0
fbd6baed
GV
436 defsubr (&Sw32_open_clipboard);
437 defsubr (&Sw32_empty_clipboard);
438 defsubr (&Sw32_close_clipboard);
ee78dc32 439#endif
fbd6baed
GV
440 defsubr (&Sw32_set_clipboard_data);
441 defsubr (&Sw32_get_clipboard_data);
9aa94bd5
KH
442 defsubr (&Sx_selection_exists_p);
443
72aca5fa 444 DEFVAR_LISP ("selection-coding-system", &Vselection_coding_system,
bbb059f3
AI
445 "Coding system for communicating with other X clients.\n\
446When sending or receiving text via cut_buffer, selection, and clipboard,\n\
447the text is encoded or decoded by this coding system.\n\
448A default value is `compound-text'");
72aca5fa 449 Vselection_coding_system=intern ("iso-latin-1-dos");
bbb059f3 450
93cbf229
GV
451 DEFVAR_LISP ("next-selection-coding-system", &Vnext_selection_coding_system,
452 "Coding system for the next communication with other X clients.\n\
453Usually, `selection-coding-system' is used for communicating with\n\
454other X clients. But, if this variable is set, it is used for the\n\
455next communication only. After the communication, this variable is\n\
456set to nil.");
457 Vnext_selection_coding_system = Qnil;
458
9aa94bd5 459 QCLIPBOARD = intern ("CLIPBOARD"); staticpro (&QCLIPBOARD);
ee78dc32 460}