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