XEmacs 21.2.32 "Kastor & Polydeukes".
[chise/xemacs-chise.git.1] / src / select-msw.c
1 /* mswindows selection processing for XEmacs
2    Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
3
4 This file is part of XEmacs.
5
6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with XEmacs; 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 /* Synched up with: Not synched with FSF. */
22
23 /* Authorship:
24
25    Written by Kevin Gallo for FSF Emacs.
26    Rewritten for mswindows by Jonathan Harris, December 1997 for 21.0.
27  */
28
29
30 #include <config.h>
31 #include "lisp.h"
32 #include "frame.h"
33 #include "select.h"
34
35 #include "console-msw.h"
36
37
38 /* Do protocol to assert ourself as a selection owner. Under mswindows
39 this is easy, we just set the clipboard.  */
40 static Lisp_Object
41 mswindows_own_selection (Lisp_Object selection_name,
42                          Lisp_Object selection_value)
43 {
44   Lisp_Object converted_value = get_local_selection (selection_name, QSTRING);
45
46   if (!NILP (converted_value) &&
47       CONSP (converted_value) &&
48       EQ (XCAR (converted_value), QSTRING) &&
49       /* pure mswindows behaviour only says we can own the selection 
50          if it is the clipboard */
51       EQ (selection_name, QCLIPBOARD))
52     {
53       int rawsize, size, i;
54       unsigned char *src, *dst, *next;
55       HGLOBAL h = NULL;
56       struct frame *f = NULL;
57       struct gcpro gcpro1, gcpro2;
58       Lisp_Object string = XCDR (converted_value);
59
60       GCPRO2 (converted_value, string);
61
62       CHECK_STRING (string);
63
64       /* Calculate size with LFs converted to CRLFs because
65        * CF_TEXT format uses CRLF delimited ASCIIZ */
66       src = XSTRING_DATA (string);
67       size = rawsize = XSTRING_LENGTH (string) + 1;
68       for (i=0; i<rawsize; i++)
69         if (src[i] == '\n')
70           size++;
71
72       f = selected_frame ();
73       if (!OpenClipboard (FRAME_MSWINDOWS_HANDLE (f)))
74         {
75           UNGCPRO;
76           return Qnil;
77         }
78
79       /* This call to EmptyClipboard may post an event back to us if
80          we already own the clipboard (to tell us we lost it) and this
81          event may execute random lisp code.  Hence we must protect
82          the string and get its address again after the call. */
83       if (!EmptyClipboard () ||
84           (h = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, size)) == NULL ||
85           (dst = (unsigned char *) GlobalLock (h)) == NULL)
86         {
87           if (h != NULL) GlobalFree (h);
88           CloseClipboard ();
89           UNGCPRO;
90           return Qnil;
91         }
92       src = XSTRING_DATA (string);
93
94       /* Convert LFs to CRLFs */
95       do
96         {
97           /* copy next line or remaining bytes including '\0' */
98           next = (char*) memccpy (dst, src, '\n', rawsize);
99           if (next)
100             {
101               /* copied one line ending with '\n' */
102               int copied = next - dst;
103               rawsize -= copied;
104               src += copied;
105               /* insert '\r' before '\n' */
106               next[-1] = '\r';
107               next[0] = '\n';
108               dst = next+1;
109             }       
110         }
111       while (next);
112     
113       GlobalUnlock (h);
114   
115       i = (SetClipboardData (CF_TEXT, h) != NULL);
116   
117       CloseClipboard ();
118
119       UNGCPRO;
120       /* #### we are supposed to return a time! */
121       /* return i ? Qt : Qnil; */
122       return Qnil;
123     }
124
125   return Qnil;
126 }
127
128 static Lisp_Object
129 mswindows_get_foreign_selection (Lisp_Object selection_symbol,
130                                  Lisp_Object target_type)
131 {
132   if (EQ (selection_symbol, QCLIPBOARD))
133     {
134       HANDLE h;
135       unsigned char *src, *dst, *next;
136       Lisp_Object ret = Qnil;
137
138       if (!OpenClipboard (NULL))
139         return Qnil;
140
141       if ((h = GetClipboardData (CF_TEXT)) != NULL &&
142           (src = (unsigned char *) GlobalLock (h)) != NULL)
143         {
144           int i;
145           int size, rawsize;
146           size = rawsize = strlen (src);
147
148           for (i=0; i<rawsize; i++)
149             if (src[i] == '\r' && src[i+1] == '\n')
150               size--;
151
152           /* Convert CRLFs to LFs */
153           ret = make_uninit_string (size);
154           dst = XSTRING_DATA (ret);
155           do
156             {
157               /* copy next line or remaining bytes excluding '\0' */
158               next = (unsigned char *) memccpy (dst, src, '\r', rawsize);
159               if (next)
160                 {
161                   /* copied one line ending with '\r' */
162                   int copied = next - dst;
163                   rawsize -= copied;
164                   src += copied;
165                   if (*src == '\n')
166                     dst += copied - 1;          /* overwrite '\r' */
167                   else
168                     dst += copied;
169                 }           
170             }
171           while (next);
172
173           GlobalUnlock (h);
174         }
175
176       CloseClipboard ();
177
178       return ret;
179     }
180   else
181     return Qnil;
182 }
183
184 static void
185 mswindows_disown_selection (Lisp_Object selection, Lisp_Object timeval)
186 {
187   if (EQ (selection, QCLIPBOARD))
188     {
189       BOOL success = OpenClipboard (NULL);
190       if (success)
191         {
192           success = EmptyClipboard ();
193           /* Close it regardless of whether empty worked. */
194           if (!CloseClipboard ())
195             success = FALSE;
196         }
197
198       /* #### return success ? Qt : Qnil; */
199     }
200 }
201
202 static Lisp_Object
203 mswindows_selection_exists_p (Lisp_Object selection)
204 {
205   if (EQ (selection, QCLIPBOARD))
206     return IsClipboardFormatAvailable (CF_TEXT) ? Qt : Qnil;
207   else
208     return Qnil;
209 }
210
211 \f
212 /************************************************************************/
213 /*                            initialization                            */
214 /************************************************************************/
215
216 void
217 console_type_create_select_mswindows (void)
218 {
219   CONSOLE_HAS_METHOD (mswindows, own_selection);
220   CONSOLE_HAS_METHOD (mswindows, disown_selection);
221   CONSOLE_HAS_METHOD (mswindows, selection_exists_p);
222   CONSOLE_HAS_METHOD (mswindows, get_foreign_selection);
223 }
224
225 void
226 syms_of_select_mswindows (void)
227 {
228 }
229
230 void
231 vars_of_select_mswindows (void)
232 {
233 }