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