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