1 /* Haiku window system selection support. Hey Emacs, this is -*- C++ -*-
2    Copyright (C) 2021 Free Software Foundation, Inc.
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 3 of the License, or (at
9 your option) 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.  If not, see <https://www.gnu.org/licenses/>.  */
18 
19 #include <config.h>
20 
21 #include <Clipboard.h>
22 
23 #include <cstdlib>
24 #include <cstring>
25 
26 #include "haikuselect.h"
27 
28 
29 static BClipboard *primary = NULL;
30 static BClipboard *secondary = NULL;
31 static BClipboard *system_clipboard = NULL;
32 
33 int selection_state_flag;
34 
35 static char *
BClipboard_find_data(BClipboard * cb,const char * type,ssize_t * len)36 BClipboard_find_data (BClipboard *cb, const char *type, ssize_t *len)
37 {
38   if (!cb->Lock ())
39     return 0;
40 
41   BMessage *dat = cb->Data ();
42   if (!dat)
43     {
44       cb->Unlock ();
45       return 0;
46     }
47 
48   const char *ptr;
49   ssize_t bt;
50   dat->FindData (type, B_MIME_TYPE, (const void **) &ptr, &bt);
51 
52   if (!ptr)
53     {
54       cb->Unlock ();
55       return NULL;
56     }
57 
58   if (len)
59     *len = bt;
60 
61   cb->Unlock ();
62 
63   return strndup (ptr, bt);
64 }
65 
66 static void
BClipboard_get_targets(BClipboard * cb,char ** buf,int buf_size)67 BClipboard_get_targets (BClipboard *cb, char **buf, int buf_size)
68 {
69   BMessage *data;
70   char *name;
71   int32 count_found;
72   type_code type;
73   int32 i;
74   int index;
75 
76   if (!cb->Lock ())
77     {
78       buf[0] = NULL;
79       return;
80     }
81 
82   data = cb->Data ();
83   index = 0;
84 
85   if (!data)
86     {
87       buf[0] = NULL;
88       cb->Unlock ();
89       return;
90     }
91 
92   for (i = 0; (data->GetInfo (B_ANY_TYPE, i, &name,
93 			     &type, &count_found)
94 	       == B_OK); ++i)
95     {
96       if (type == B_MIME_TYPE)
97 	{
98 	  if (index < (buf_size - 1))
99 	    {
100 	      buf[index++] = strdup (name);
101 
102 	      if (!buf[index - 1])
103 		break;
104 	    }
105 	}
106     }
107 
108   buf[index] = NULL;
109 
110   cb->Unlock ();
111 }
112 
113 static void
BClipboard_set_data(BClipboard * cb,const char * type,const char * dat,ssize_t len,bool clear)114 BClipboard_set_data (BClipboard *cb, const char *type, const char *dat,
115 		     ssize_t len, bool clear)
116 {
117   if (!cb->Lock ())
118     return;
119 
120   if (clear)
121     cb->Clear ();
122 
123   BMessage *mdat = cb->Data ();
124   if (!mdat)
125     {
126       cb->Unlock ();
127       return;
128     }
129 
130   if (dat)
131     {
132       if (mdat->ReplaceData (type, B_MIME_TYPE, dat, len)
133 	  == B_NAME_NOT_FOUND)
134 	mdat->AddData (type, B_MIME_TYPE, dat, len);
135     }
136   else
137     mdat->RemoveName (type);
138   cb->Commit ();
139   cb->Unlock ();
140 }
141 
142 char *
BClipboard_find_system_data(const char * type,ssize_t * len)143 BClipboard_find_system_data (const char *type, ssize_t *len)
144 {
145   if (!system_clipboard)
146     return 0;
147 
148   return BClipboard_find_data (system_clipboard, type, len);
149 }
150 
151 char *
BClipboard_find_primary_selection_data(const char * type,ssize_t * len)152 BClipboard_find_primary_selection_data (const char *type, ssize_t *len)
153 {
154   if (!primary)
155     return 0;
156 
157   return BClipboard_find_data (primary, type, len);
158 }
159 
160 char *
BClipboard_find_secondary_selection_data(const char * type,ssize_t * len)161 BClipboard_find_secondary_selection_data (const char *type, ssize_t *len)
162 {
163   if (!secondary)
164     return 0;
165 
166   return BClipboard_find_data (secondary, type, len);
167 }
168 
169 void
BClipboard_set_system_data(const char * type,const char * data,ssize_t len,bool clear)170 BClipboard_set_system_data (const char *type, const char *data,
171 			    ssize_t len, bool clear)
172 {
173   if (!system_clipboard)
174     return;
175 
176   BClipboard_set_data (system_clipboard, type, data, len, clear);
177 }
178 
179 void
BClipboard_set_primary_selection_data(const char * type,const char * data,ssize_t len,bool clear)180 BClipboard_set_primary_selection_data (const char *type, const char *data,
181 				       ssize_t len, bool clear)
182 {
183   if (!primary)
184     return;
185 
186   BClipboard_set_data (primary, type, data, len, clear);
187 }
188 
189 void
BClipboard_set_secondary_selection_data(const char * type,const char * data,ssize_t len,bool clear)190 BClipboard_set_secondary_selection_data (const char *type, const char *data,
191 					 ssize_t len, bool clear)
192 {
193   if (!secondary)
194     return;
195 
196   BClipboard_set_data (secondary, type, data, len, clear);
197 }
198 
199 void
BClipboard_free_data(void * ptr)200 BClipboard_free_data (void *ptr)
201 {
202   std::free (ptr);
203 }
204 
205 void
BClipboard_system_targets(char ** buf,int len)206 BClipboard_system_targets (char **buf, int len)
207 {
208   BClipboard_get_targets (system_clipboard, buf, len);
209 }
210 
211 void
BClipboard_primary_targets(char ** buf,int len)212 BClipboard_primary_targets (char **buf, int len)
213 {
214   BClipboard_get_targets (primary, buf, len);
215 }
216 
217 void
BClipboard_secondary_targets(char ** buf,int len)218 BClipboard_secondary_targets (char **buf, int len)
219 {
220   BClipboard_get_targets (secondary, buf, len);
221 }
222 
223 void
init_haiku_select(void)224 init_haiku_select (void)
225 {
226   system_clipboard = new BClipboard ("system");
227   primary = new BClipboard ("primary");
228   secondary = new BClipboard ("secondary");
229 }
230