Add arch taglines
[bpt/emacs.git] / src / w32select.c
1 /* Selection processing for Emacs on the Microsoft W32 API.
2 Copyright (C) 1993, 1994 Free Software Foundation.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, 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
35 Lisp_Object QCLIPBOARD;
36
37 /* Coding system for communicating with other Windows programs via the
38 clipboard. */
39 static Lisp_Object Vselection_coding_system;
40
41 /* Coding system for the next communicating with other Windows programs. */
42 static Lisp_Object Vnext_selection_coding_system;
43
44 /* Sequence number, used where possible to detect when we are pasting
45 our own text. */
46 static DWORD last_clipboard_sequence_number;
47 extern 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. */
55 static unsigned char *last_clipboard_text = NULL;
56 static size_t clipboard_storage_size = 0;
57
58 #if 0
59 DEFUN ("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
78 DEFUN ("w32-empty-clipboard", Fw32_empty_clipboard,
79 Sw32_empty_clipboard, 0, 0, 0,
80 doc: /* Empty the clipboard.
81 Assigns 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
95 DEFUN ("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
113 DEFUN ("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 Vnext_selection_coding_system = Qnil;
216 coding.mode |= CODING_MODE_LAST_BLOCK;
217 bufsize = encoding_buffer_size (&coding, nbytes);
218 if ((htext = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, bufsize)) == NULL)
219 goto error;
220 if ((dst = (unsigned char *) GlobalLock (htext)) == NULL)
221 goto error;
222 encode_coding (&coding, src, dst, nbytes, bufsize);
223 Vlast_coding_system_used = coding.symbol;
224
225 /* If clipboard sequence numbers are not supported, keep a copy for
226 later comparison. */
227 if (!clipboard_sequence_fn)
228 {
229 /* Stash away the data we are about to put into the
230 clipboard, so we could later check inside
231 Fw32_get_clipboard_data whether the clipboard still
232 holds our data. */
233 if (clipboard_storage_size < coding.produced)
234 {
235 clipboard_storage_size = coding.produced + 100;
236 last_clipboard_text = (char *) xrealloc (last_clipboard_text,
237 clipboard_storage_size);
238 }
239 if (last_clipboard_text)
240 memcpy (last_clipboard_text, dst, coding.produced);
241 }
242
243 GlobalUnlock (htext);
244
245 /* Shrink data block to actual size. */
246 htext2 = GlobalReAlloc (htext, coding.produced,
247 GMEM_MOVEABLE | GMEM_DDESHARE);
248 if (htext2 != NULL) htext = htext2;
249 }
250 }
251
252 if (!OpenClipboard ((!NILP (frame) && FRAME_W32_P (XFRAME (frame))) ? FRAME_W32_WINDOW (XFRAME (frame)) : NULL))
253 goto error;
254
255 ok = EmptyClipboard () && SetClipboardData (CF_TEXT, htext);
256
257 if (clipboard_sequence_fn)
258 last_clipboard_sequence_number = clipboard_sequence_fn ();
259
260 CloseClipboard ();
261
262 if (ok) goto done;
263
264 error:
265
266 ok = FALSE;
267 if (htext) GlobalFree (htext);
268 if (last_clipboard_text)
269 *last_clipboard_text = '\0';
270
271 last_clipboard_sequence_number = 0;
272
273 done:
274 UNBLOCK_INPUT;
275
276 return (ok ? string : Qnil);
277 }
278
279 DEFUN ("w32-get-clipboard-data", Fw32_get_clipboard_data,
280 Sw32_get_clipboard_data, 0, 1, 0,
281 doc: /* This gets the clipboard data in text format. */)
282 (frame)
283 Lisp_Object frame;
284 {
285 HANDLE htext;
286 Lisp_Object ret = Qnil;
287
288 if (!NILP (frame))
289 CHECK_LIVE_FRAME (frame);
290
291 BLOCK_INPUT;
292
293 if (!OpenClipboard ((!NILP (frame) && FRAME_W32_P (XFRAME (frame))) ? FRAME_W32_WINDOW (XFRAME (frame)) : NULL))
294 goto done;
295
296 if ((htext = GetClipboardData (CF_TEXT)) == NULL)
297 goto closeclip;
298
299 {
300 unsigned char *src;
301 unsigned char *dst;
302 int nbytes;
303 int truelen;
304 int require_decoding = 0;
305
306 if ((src = (unsigned char *) GlobalLock (htext)) == NULL)
307 goto closeclip;
308
309 nbytes = strlen (src);
310
311 /* If the text in clipboard is identical to what we put there
312 last time w32_set_clipboard_data was called, pretend there's no
313 data in the clipboard. This is so we don't pass our own text
314 from the clipboard (which might be troublesome if the killed
315 text includes null characters). */
316 if ((clipboard_sequence_fn
317 && clipboard_sequence_fn () == last_clipboard_sequence_number)
318 || (last_clipboard_text
319 && clipboard_storage_size >= nbytes
320 && memcmp(last_clipboard_text, src, nbytes) == 0))
321 goto closeclip;
322
323 {
324 /* If the clipboard data contains any non-ascii code, we
325 need to decode it. */
326 int i;
327
328 for (i = 0; i < nbytes; i++)
329 {
330 if (src[i] >= 0x80)
331 {
332 require_decoding = 1;
333 break;
334 }
335 }
336 }
337
338 if (require_decoding)
339 {
340 int bufsize;
341 unsigned char *buf;
342 struct coding_system coding;
343
344 if (NILP (Vnext_selection_coding_system))
345 Vnext_selection_coding_system = Vselection_coding_system;
346 setup_coding_system
347 (Fcheck_coding_system (Vnext_selection_coding_system), &coding);
348 coding.src_multibyte = 0;
349 coding.dst_multibyte = 1;
350 Vnext_selection_coding_system = Qnil;
351 coding.mode |= CODING_MODE_LAST_BLOCK;
352 /* We explicitely disable composition handling because
353 selection data should not contain any composition
354 sequence. */
355 coding.composing = COMPOSITION_DISABLED;
356 bufsize = decoding_buffer_size (&coding, nbytes);
357 buf = (unsigned char *) xmalloc (bufsize);
358 decode_coding (&coding, src, buf, nbytes, bufsize);
359 Vlast_coding_system_used = coding.symbol;
360 ret = make_string_from_bytes ((char *) buf,
361 coding.produced_char, coding.produced);
362 xfree (buf);
363 if (SYMBOLP (coding.post_read_conversion)
364 && !NILP (Ffboundp (coding.post_read_conversion)))
365 ret = run_pre_post_conversion_on_str (ret, &coding, 0);
366 }
367 else
368 {
369 /* Need to know final size after CR chars are removed because we
370 can't change the string size manually, and doing an extra
371 copy is silly. Note that we only remove CR when it appears
372 as part of CRLF. */
373
374 truelen = nbytes;
375 dst = src;
376 /* avoid using strchr because it recomputes the length everytime */
377 while ((dst = memchr (dst, '\r', nbytes - (dst - src))) != NULL)
378 {
379 if (dst[1] == '\n') /* safe because of trailing '\0' */
380 truelen--;
381 dst++;
382 }
383
384 ret = make_uninit_string (truelen);
385
386 /* Convert CRLF line endings (the standard CF_TEXT clipboard
387 format) to LF endings as used internally by Emacs. */
388
389 dst = SDATA (ret);
390 while (1)
391 {
392 unsigned char *next;
393 /* copy next line or remaining bytes excluding '\0' */
394 next = _memccpy (dst, src, '\r', nbytes);
395 if (next)
396 {
397 /* copied one line ending with '\r' */
398 int copied = next - dst;
399 nbytes -= copied;
400 dst += copied;
401 src += copied;
402 if (*src == '\n')
403 dst--; /* overwrite '\r' with '\n' */
404 }
405 else
406 /* copied remaining partial line -> now finished */
407 break;
408 }
409
410 Vlast_coding_system_used = Qraw_text;
411 }
412
413 GlobalUnlock (htext);
414 }
415
416 closeclip:
417 CloseClipboard ();
418
419 done:
420 UNBLOCK_INPUT;
421
422 return (ret);
423 }
424
425 /* Support checking for a clipboard selection. */
426
427 DEFUN ("x-selection-exists-p", Fx_selection_exists_p, Sx_selection_exists_p,
428 0, 1, 0,
429 doc: /* Whether there is an owner for the given X Selection.
430 The arg should be the name of the selection in question, typically one of
431 the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.
432 \(Those are literal upper-case symbol names, since that's what X expects.)
433 For convenience, the symbol nil is the same as `PRIMARY',
434 and t is the same as `SECONDARY'. */)
435 (selection)
436 Lisp_Object selection;
437 {
438 CHECK_SYMBOL (selection);
439
440 /* Return nil for PRIMARY and SECONDARY selections; for CLIPBOARD, check
441 if the clipboard currently has valid text format contents. */
442
443 if (EQ (selection, QCLIPBOARD))
444 {
445 Lisp_Object val = Qnil;
446
447 if (OpenClipboard (NULL))
448 {
449 int format = 0;
450 while (format = EnumClipboardFormats (format))
451 if (format == CF_TEXT)
452 {
453 val = Qt;
454 break;
455 }
456 CloseClipboard ();
457 }
458 return val;
459 }
460 return Qnil;
461 }
462
463 void
464 syms_of_w32select ()
465 {
466 #if 0
467 defsubr (&Sw32_open_clipboard);
468 defsubr (&Sw32_empty_clipboard);
469 defsubr (&Sw32_close_clipboard);
470 #endif
471 defsubr (&Sw32_set_clipboard_data);
472 defsubr (&Sw32_get_clipboard_data);
473 defsubr (&Sx_selection_exists_p);
474
475 DEFVAR_LISP ("selection-coding-system", &Vselection_coding_system,
476 doc: /* Coding system for communicating with other programs.
477 When sending or receiving text via cut_buffer, selection, and clipboard,
478 the text is encoded or decoded by this coding system.
479 The default value is `iso-latin-1-dos'. */);
480 Vselection_coding_system = intern ("iso-latin-1-dos");
481
482 DEFVAR_LISP ("next-selection-coding-system", &Vnext_selection_coding_system,
483 doc: /* Coding system for the next communication with other programs.
484 Usually, `selection-coding-system' is used for communicating with
485 other programs. But, if this variable is set, it is used for the
486 next communication only. After the communication, this variable is
487 set to nil. */);
488 Vnext_selection_coding_system = Qnil;
489
490 QCLIPBOARD = intern ("CLIPBOARD"); staticpro (&QCLIPBOARD);
491 }
492
493 /* arch-tag: c96e9724-5eb1-4dad-be07-289f092fd2af
494 (do not change this comment) */