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