(rmail-summary-output): Properly advance
[bpt/emacs.git] / src / w32select.c
CommitLineData
e9e23e23 1/* Selection processing for Emacs on the Microsoft W32 API.
ee78dc32
GV
2 Copyright (C) 1993, 1994 Free Software Foundation.
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"
ee78dc32 33
9aa94bd5
KH
34Lisp_Object QCLIPBOARD;
35
bbb059f3
AI
36/* Coding system for communicating with other Windows programs via the
37 clipboard. */
72aca5fa 38static Lisp_Object Vselection_coding_system;
bbb059f3 39
06466d9a 40/* Coding system for the next communicating with other Windows programs. */
93cbf229
GV
41static Lisp_Object Vnext_selection_coding_system;
42
06466d9a
JR
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
ee78dc32 52#if 0
fbd6baed 53DEFUN ("w32-open-clipboard", Fw32_open_clipboard, Sw32_open_clipboard, 0, 1, 0,
33f09670 54 doc: /* This opens the clipboard with the given frame pointer. */)
ee78dc32
GV
55 (frame)
56 Lisp_Object frame;
57{
58 BOOL ok = FALSE;
59
60 if (!NILP (frame))
b7826503 61 CHECK_LIVE_FRAME (frame);
ee78dc32
GV
62
63 BLOCK_INPUT;
64
fbd6baed 65 ok = OpenClipboard ((!NILP (frame) && FRAME_W32_P (XFRAME (frame))) ? FRAME_W32_WINDOW (XFRAME (frame)) : NULL);
ee78dc32
GV
66
67 UNBLOCK_INPUT;
68
69 return (ok ? frame : Qnil);
70}
71
33f09670
JR
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. */)
ee78dc32
GV
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
33f09670
JR
89DEFUN ("w32-close-clipboard", Fw32_close_clipboard,
90 Sw32_close_clipboard, 0, 0, 0,
91 doc: /* Close the clipboard. */)
ee78dc32
GV
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
33f09670
JR
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. */)
ee78dc32
GV
110 (string, frame)
111 Lisp_Object string, frame;
112{
113 BOOL ok = TRUE;
114 HANDLE htext;
69cddef0 115 int nbytes;
0ece9ef6 116 int truelen, nlines = 0;
69cddef0
GV
117 unsigned char *src;
118 unsigned char *dst;
0ece9ef6 119
b7826503 120 CHECK_STRING (string);
ee78dc32
GV
121
122 if (!NILP (frame))
b7826503 123 CHECK_LIVE_FRAME (frame);
ee78dc32
GV
124
125 BLOCK_INPUT;
69cddef0 126
bbb059f3 127 nbytes = STRING_BYTES (XSTRING (string)) + 1;
69cddef0 128 src = XSTRING (string)->data;
0ece9ef6
AI
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 }
69cddef0 139
bbb059f3
AI
140 {
141 /* Since we are now handling multilingual text, we must consider
142 encoding text for the clipboard. */
69ebbf81 143 int charset_info = find_charset_in_text (src, XSTRING (string)->size,
11f292ed 144 nbytes, NULL, Qnil);
bbb059f3 145
69ebbf81 146 if (charset_info == 0)
bbb059f3
AI
147 {
148 /* No multibyte character in OBJ. We need not encode it. */
69cddef0 149
c0ca703b 150 /* Need to know final size after CR chars are inserted (the
bbb059f3 151 standard CF_TEXT clipboard format uses CRLF line endings,
c0ca703b 152 while Emacs uses just LF internally). */
69cddef0 153
0ece9ef6 154 truelen = nbytes + nlines;
69cddef0 155
bbb059f3
AI
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;
ee78dc32 161
bbb059f3
AI
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 }
ee78dc32 183
bbb059f3 184 GlobalUnlock (htext);
0108f679
AI
185
186 Vlast_coding_system_used = Qraw_text;
bbb059f3
AI
187 }
188 else
189 {
06466d9a
JR
190 /* We must encode contents of OBJ to the selection coding
191 system. */
bbb059f3
AI
192 int bufsize;
193 struct coding_system coding;
194 HANDLE htext2;
195
93cbf229
GV
196 if (NILP (Vnext_selection_coding_system))
197 Vnext_selection_coding_system = Vselection_coding_system;
bbb059f3 198 setup_coding_system
93cbf229 199 (Fcheck_coding_system (Vnext_selection_coding_system), &coding);
69ebbf81
KH
200 coding.src_multibyte = 1;
201 coding.dst_multibyte = 0;
93cbf229 202 Vnext_selection_coding_system = Qnil;
bbb059f3 203 coding.mode |= CODING_MODE_LAST_BLOCK;
43df7d0b 204 bufsize = encoding_buffer_size (&coding, nbytes);
bbb059f3
AI
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);
0108f679 210 Vlast_coding_system_used = coding.symbol;
06466d9a
JR
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
bbb059f3 224 GlobalUnlock (htext);
06466d9a 225
bbb059f3 226 /* Shrink data block to actual size. */
06466d9a
JR
227 htext2 = GlobalReAlloc (htext, coding.produced,
228 GMEM_MOVEABLE | GMEM_DDESHARE);
bbb059f3
AI
229 if (htext2 != NULL) htext = htext2;
230 }
231 }
ee78dc32 232
fbd6baed 233 if (!OpenClipboard ((!NILP (frame) && FRAME_W32_P (XFRAME (frame))) ? FRAME_W32_WINDOW (XFRAME (frame)) : NULL))
ee78dc32 234 goto error;
06466d9a 235
ee78dc32
GV
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);
06466d9a
JR
246 if (last_clipboard_text)
247 *last_clipboard_text = '\0';
248
ee78dc32
GV
249 done:
250 UNBLOCK_INPUT;
251
252 return (ok ? string : Qnil);
253}
254
33f09670
JR
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. */)
ee78dc32
GV
258 (frame)
259 Lisp_Object frame;
260{
261 HANDLE htext;
262 Lisp_Object ret = Qnil;
263
264 if (!NILP (frame))
b7826503 265 CHECK_LIVE_FRAME (frame);
ee78dc32
GV
266
267 BLOCK_INPUT;
268
fbd6baed 269 if (!OpenClipboard ((!NILP (frame) && FRAME_W32_P (XFRAME (frame))) ? FRAME_W32_WINDOW (XFRAME (frame)) : NULL))
ee78dc32
GV
270 goto done;
271
272 if ((htext = GetClipboardData (CF_TEXT)) == NULL)
273 goto closeclip;
274
ee78dc32 275 {
69cddef0
GV
276 unsigned char *src;
277 unsigned char *dst;
ee78dc32 278 int nbytes;
69cddef0 279 int truelen;
c0ca703b 280 int require_decoding = 0;
ee78dc32 281
69cddef0 282 if ((src = (unsigned char *) GlobalLock (htext)) == NULL)
ee78dc32
GV
283 goto closeclip;
284
69cddef0
GV
285 nbytes = strlen (src);
286
06466d9a
JR
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
93cbf229
GV
297 if (
298#if 1
299 1
300#else
301 ! NILP (buffer_defaults.enable_multibyte_characters)
302#endif
303 )
304 {
c0ca703b 305 /* If the clipboard data contains any non-ascii code, we
93cbf229
GV
306 need to decode it. */
307 int i;
308
309 for (i = 0; i < nbytes; i++)
310 {
311 if (src[i] >= 0x80)
312 {
c0ca703b 313 require_decoding = 1;
93cbf229
GV
314 break;
315 }
316 }
317 }
318
c0ca703b 319 if (require_decoding)
69cddef0 320 {
bbb059f3
AI
321 int bufsize;
322 unsigned char *buf;
323 struct coding_system coding;
324
93cbf229
GV
325 if (NILP (Vnext_selection_coding_system))
326 Vnext_selection_coding_system = Vselection_coding_system;
bbb059f3 327 setup_coding_system
93cbf229 328 (Fcheck_coding_system (Vnext_selection_coding_system), &coding);
69ebbf81
KH
329 coding.src_multibyte = 0;
330 coding.dst_multibyte = 1;
93cbf229 331 Vnext_selection_coding_system = Qnil;
bbb059f3
AI
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);
0108f679 336 Vlast_coding_system_used = coding.symbol;
06466d9a
JR
337 ret = make_string_from_bytes ((char *) buf,
338 coding.produced_char, coding.produced);
bbb059f3 339 xfree (buf);
69cddef0 340 }
bbb059f3
AI
341 else
342 {
c0ca703b
GV
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. */
bbb059f3
AI
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 {
c0ca703b
GV
353 if (dst[1] == '\n') /* safe because of trailing '\0' */
354 truelen--;
bbb059f3
AI
355 dst++;
356 }
69cddef0 357
bbb059f3 358 ret = make_uninit_string (truelen);
69cddef0 359
c0ca703b
GV
360 /* Convert CRLF line endings (the standard CF_TEXT clipboard
361 format) to LF endings as used internally by Emacs. */
69cddef0 362
bbb059f3
AI
363 dst = XSTRING (ret)->data;
364 while (1)
69cddef0 365 {
bbb059f3
AI
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;
c0ca703b 374 dst += copied;
bbb059f3 375 src += copied;
c0ca703b
GV
376 if (*src == '\n')
377 dst--; /* overwrite '\r' with '\n' */
378 }
bbb059f3
AI
379 else
380 /* copied remaining partial line -> now finished */
381 break;
382 }
0108f679
AI
383
384 Vlast_coding_system_used = Qraw_text;
69cddef0
GV
385 }
386
ee78dc32
GV
387 GlobalUnlock (htext);
388 }
389
390 closeclip:
391 CloseClipboard ();
392
393 done:
394 UNBLOCK_INPUT;
395
396 return (ret);
397}
398
9aa94bd5
KH
399/* Support checking for a clipboard selection. */
400
401DEFUN ("x-selection-exists-p", Fx_selection_exists_p, Sx_selection_exists_p,
33f09670
JR
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'. */)
9aa94bd5
KH
409 (selection)
410 Lisp_Object selection;
411{
b7826503 412 CHECK_SYMBOL (selection);
9aa94bd5
KH
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
ee78dc32 437void
fbd6baed 438syms_of_w32select ()
ee78dc32
GV
439{
440#if 0
fbd6baed
GV
441 defsubr (&Sw32_open_clipboard);
442 defsubr (&Sw32_empty_clipboard);
443 defsubr (&Sw32_close_clipboard);
ee78dc32 444#endif
fbd6baed
GV
445 defsubr (&Sw32_set_clipboard_data);
446 defsubr (&Sw32_get_clipboard_data);
9aa94bd5
KH
447 defsubr (&Sx_selection_exists_p);
448
72aca5fa 449 DEFVAR_LISP ("selection-coding-system", &Vselection_coding_system,
33f09670
JR
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. */);
72aca5fa 453 Vselection_coding_system=intern ("iso-latin-1-dos");
bbb059f3 454
93cbf229 455 DEFVAR_LISP ("next-selection-coding-system", &Vnext_selection_coding_system,
33f09670
JR
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. */);
93cbf229
GV
461 Vnext_selection_coding_system = Qnil;
462
9aa94bd5 463 QCLIPBOARD = intern ("CLIPBOARD"); staticpro (&QCLIPBOARD);
ee78dc32 464}