ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/BeOS/clip_beos.cpp
Revision: 1.4
Committed: 2008-01-01T09:47:38Z (16 years, 10 months ago) by gbeauche
Branch: MAIN
CVS Tags: HEAD
Changes since 1.3: +1 -1 lines
Log Message:
Happy New Year!

File Contents

# Content
1 /*
2 * clip_beos.cpp - Clipboard handling, BeOS implementation
3 *
4 * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig
5 *
6 * This program 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 of the License, or
9 * (at your option) any later version.
10 *
11 * This program 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 this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include <support/UTF8.h>
22
23 #include "clip.h"
24 #include "main.h"
25 #include "cpu_emulation.h"
26 #include "emul_op.h"
27
28 #define DEBUG 0
29 #include "debug.h"
30
31
32 // Global variables
33 static bool we_put_this_data = false; // Flag for PutScrap(): the data was put by GetScrap(), don't bounce it back to the Be side
34 static BTranslatorRoster *roster;
35 static float input_cap = 0;
36 static translator_info input_info;
37 static float output_cap = 0;
38 static translator_id output_trans = 0;
39
40
41 /*
42 * Clipboard manager thread (for calling clipboard functions; this is not safe
43 * under R4 when running on the MacOS stack in kernel space)
44 */
45
46 // Message constants
47 const uint32 MSG_QUIT_CLIP_MANAGER = 'quit';
48 const uint32 MSG_PUT_TEXT = 'ptxt';
49
50 static thread_id cm_thread = -1;
51 static sem_id cm_done_sem = -1;
52
53 // Argument passing
54 static void *cm_scrap;
55 static int32 cm_length;
56
57 static status_t clip_manager(void *arg)
58 {
59 for (;;) {
60
61 // Receive message
62 thread_id sender;
63 uint32 code = receive_data(&sender, NULL, 0);
64 D(bug("Clipboard manager received %08lx\n", code));
65 switch (code) {
66 case MSG_QUIT_CLIP_MANAGER:
67 return 0;
68
69 case MSG_PUT_TEXT:
70 if (be_clipboard->Lock()) {
71 be_clipboard->Clear();
72 BMessage *clipper = be_clipboard->Data();
73
74 // Convert text from Mac charset to UTF-8
75 int32 dest_length = cm_length * 3;
76 int32 state = 0;
77 char *inbuf = new char[cm_length];
78 memcpy(inbuf, cm_scrap, cm_length); // Copy to user space
79 char *outbuf = new char[dest_length];
80 if (convert_to_utf8(B_MAC_ROMAN_CONVERSION, inbuf, &cm_length, outbuf, &dest_length, &state) == B_OK) {
81 for (int i=0; i<dest_length; i++)
82 if (outbuf[i] == 13)
83 outbuf[i] = 10;
84
85 // Add text to Be clipboard
86 clipper->AddData("text/plain", B_MIME_TYPE, outbuf, dest_length);
87 be_clipboard->Commit();
88 } else {
89 D(bug(" text conversion failed\n"));
90 }
91 delete[] outbuf;
92 delete[] inbuf;
93 be_clipboard->Unlock();
94 }
95 break;
96 }
97
98 // Acknowledge
99 release_sem(cm_done_sem);
100 }
101 }
102
103
104 /*
105 * Initialize clipboard
106 */
107
108 void ClipInit(void)
109 {
110 // check if there is a translator that can handle the pict datatype
111 roster = BTranslatorRoster::Default();
112 int32 num_translators, i,j;
113 translator_id *translators;
114 const char *translator_name, *trans_info;
115 int32 translator_version;
116 const translation_format *t_formats;
117 long t_num;
118
119 roster->GetAllTranslators(&translators, &num_translators);
120 for (i=0;i<num_translators;i++) {
121 roster->GetTranslatorInfo(translators[i], &translator_name,
122 &trans_info, &translator_version);
123 D(bug("found translator %s: %s (%.2f)\n", translator_name, trans_info,
124 translator_version/100.));
125 // does this translator support the pict datatype ?
126 roster->GetInputFormats(translators[i], &t_formats,&t_num);
127 //printf(" supports %d input formats \n",t_num);
128 for (j=0;j<t_num;j++) {
129 if (!strcmp (t_formats[j].MIME,"image/pict")) {
130 // matching translator found
131 if (t_formats[j].capability>input_cap) {
132 input_info.type = t_formats[j].type;
133 input_info.group = t_formats[j].group;
134 input_info.quality = t_formats[j].quality;
135 input_info.capability = t_formats[j].capability;
136 strcpy(input_info.MIME,t_formats[j].MIME);
137 strcpy(input_info.name,t_formats[j].name);
138 input_info.translator=translators[i];
139 input_cap = t_formats[j].capability;
140 }
141 D(bug("matching input translator found:type:%c%c%c%c group:%c%c%c%c quality:%f capability:%f MIME:%s name:%s\n",
142 t_formats[j].type>>24,t_formats[j].type>>16,t_formats[j].type>>8,t_formats[j].type,
143 t_formats[j].group>>24,t_formats[j].group>>16,t_formats[j].group>>8,t_formats[j].group,
144 t_formats[j].quality,
145 t_formats[j].capability,t_formats[j].MIME,
146 t_formats[j].name));
147 }
148
149 }
150 roster->GetOutputFormats(translators[i], &t_formats,&t_num);
151 //printf("and %d output formats \n",t_num);
152 for (j=0;j<t_num;j++) {
153 if (!strcmp (t_formats[j].MIME,"image/pict")) {
154 if (t_formats[j].capability>output_cap) {
155 output_trans = translators[i];
156 output_cap = t_formats[j].capability;
157 }
158 D(bug("matching output translator found:type:%c%c%c%c group:%c%c%c%c quality:%f capability:%f MIME:%s name:%s\n",
159 t_formats[j].type>>24,t_formats[j].type>>16,t_formats[j].type>>8,t_formats[j].type,
160 t_formats[j].group>>24,t_formats[j].group>>16,t_formats[j].group>>8,t_formats[j].group,
161 t_formats[j].quality,
162 t_formats[j].capability,t_formats[j].MIME,
163 t_formats[j].name));
164 }
165 }
166 }
167 delete [] translators; // clean up our droppings
168
169 // Start clipboard manager thread
170 cm_done_sem = create_sem(0, "Clipboard Manager Done");
171 cm_thread = spawn_thread(clip_manager, "Clipboard Manager", B_NORMAL_PRIORITY, NULL);
172 resume_thread(cm_thread);
173 }
174
175
176 /*
177 * Deinitialize clipboard
178 */
179
180 void ClipExit(void)
181 {
182 // Stop clipboard manager
183 if (cm_thread > 0) {
184 status_t l;
185 send_data(cm_thread, MSG_QUIT_CLIP_MANAGER, NULL, 0);
186 while (wait_for_thread(cm_thread, &l) == B_INTERRUPTED) ;
187 }
188
189 // Delete semaphores
190 delete_sem(cm_done_sem);
191 }
192
193
194 /*
195 * Mac application wrote to clipboard
196 */
197
198 void PutScrap(uint32 type, void *scrap, int32 length)
199 {
200 D(bug("PutScrap type %08lx, data %p, length %ld\n", type, scrap, length));
201 if (we_put_this_data) {
202 we_put_this_data = false;
203 return;
204 }
205 if (length <= 0)
206 return;
207
208 switch (type) {
209 case 'TEXT':
210 D(bug(" clipping TEXT\n"));
211 cm_scrap = scrap;
212 cm_length = length;
213 while (send_data(cm_thread, MSG_PUT_TEXT, NULL, 0) == B_INTERRUPTED) ;
214 while (acquire_sem(cm_done_sem) == B_INTERRUPTED) ;
215 break;
216
217 case 'PICT':
218 D(bug(" clipping PICT\n"));
219 //!! this has to be converted to use the Clipboard Manager
220 #if 0
221 if (be_clipboard->Lock()) {
222 be_clipboard->Clear();
223 BMessage *clipper = be_clipboard->Data();
224 // Waaaah! This crashes!
225 if (input_cap > 0) { // if there is an converter for PICT datatype convert data to bitmap.
226 BMemoryIO *in_buffer = new BMemoryIO(scrap, length);
227 BMallocIO *out_buffer = new BMallocIO();
228 status_t result=roster->Translate(in_buffer,&input_info,NULL,out_buffer,B_TRANSLATOR_BITMAP);
229 clipper->AddData("image/x-be-bitmap", B_MIME_TYPE, out_buffer->Buffer(), out_buffer->BufferLength());
230 D(bug("conversion result:%08x buffer_size:%d\n",result,out_buffer->BufferLength()));
231 delete in_buffer;
232 delete out_buffer;
233 }
234 clipper->AddData("image/pict", B_MIME_TYPE, scrap, length);
235 be_clipboard->Commit();
236 be_clipboard->Unlock();
237 }
238 #endif
239 break;
240 }
241 }
242
243
244 /*
245 * Mac application reads clipboard
246 */
247
248 void GetScrap(void **handle, uint32 type, int32 offset)
249 {
250 M68kRegisters r;
251 D(bug("GetScrap handle %p, type %08lx, offset %ld\n", handle, type, offset));
252 return; //!! GetScrap is currently broken (should use Clipboard Manager)
253 //!! replace with clipboard notification in BeOS R4.1
254
255 switch (type) {
256 case 'TEXT':
257 D(bug(" clipping TEXT\n"));
258 if (be_clipboard->Lock()) {
259 BMessage *clipper = be_clipboard->Data();
260 char *clip;
261 ssize_t length;
262
263 // Check if we already copied this data
264 if (clipper->HasData("application/x-SheepShaver-cookie", B_MIME_TYPE))
265 return;
266 bigtime_t cookie = system_time();
267 clipper->AddData("application/x-SheepShaver-cookie", B_MIME_TYPE, &cookie, sizeof(bigtime_t));
268
269 // No, is there text in it?
270 if (clipper->FindData("text/plain", B_MIME_TYPE, &clip, &length) == B_OK) {
271 D(bug(" text/plain found\n"));
272
273 // Convert text from UTF-8 to Mac charset
274 int32 src_length = length;
275 int32 dest_length = length;
276 int32 state = 0;
277 char *outbuf = new char[dest_length];
278 if (convert_from_utf8(B_MAC_ROMAN_CONVERSION, clip, &src_length, outbuf, &dest_length, &state) == B_OK) {
279 for (int i=0; i<dest_length; i++)
280 if (outbuf[i] == 10)
281 outbuf[i] = 13;
282
283 // Add text to Mac clipboard
284 static uint16 proc[] = {
285 0x598f, // subq.l #4,sp
286 0xa9fc, // ZeroScrap()
287 0x2f3c, 0, 0, // move.l #length,-(sp)
288 0x2f3c, 'TE', 'XT', // move.l #'TEXT',-(sp)
289 0x2f3c, 0, 0, // move.l #outbuf,-(sp)
290 0xa9fe, // PutScrap()
291 0x588f, // addq.l #4,sp
292 M68K_RTS
293 };
294 *(int32 *)(proc + 3) = dest_length;
295 *(char **)(proc + 9) = outbuf;
296 we_put_this_data = true;
297 Execute68k((uint32)proc, &r);
298 } else {
299 D(bug(" text conversion failed\n"));
300 }
301 delete[] outbuf;
302 }
303 be_clipboard->Commit();
304 be_clipboard->Unlock();
305 }
306 break;
307
308 case 'PICT':
309 D(bug(" clipping PICT\n"));
310 if (be_clipboard->Lock()) {
311 BMessage *clipper = be_clipboard->Data();
312 char *clip;
313 ssize_t length;
314
315 // Check if we already copied this data
316 if (clipper->HasData("application/x-SheepShaver-cookie", B_MIME_TYPE))
317 return;
318 bigtime_t cookie = system_time();
319 clipper->AddData("application/x-SheepShaver-cookie", B_MIME_TYPE, &cookie, sizeof(bigtime_t));
320
321 static uint16 proc2[] = {
322 0x598f, // subq.l #4,sp
323 0xa9fc, // ZeroScrap()
324 0x2f3c, 0, 0, // move.l #length,-(sp)
325 0x2f3c, 'PI', 'CT', // move.l #'PICT',-(sp)
326 0x2f3c, 0, 0, // move.l #buf,-(sp)
327 0xa9fe, // PutScrap()
328 0x588f, // addq.l #4,sp
329 M68K_RTS
330 };
331
332 // No, is there a pict ?
333 if (clipper->FindData("image/pict", B_MIME_TYPE, &clip, &length) == B_OK ) {
334 D(bug(" image/pict found\n"));
335
336 // Add pict to Mac clipboard
337 *(int32 *)(proc2 + 3) = length;
338 *(char **)(proc2 + 9) = clip;
339 we_put_this_data = true;
340 Execute68k((uint32)proc2, &r);
341 #if 0
342 // No, is there a bitmap ?
343 } else if (clipper->FindData("image/x-be-bitmap", B_MIME_TYPE, &clip, &length) == B_OK || output_cap > 0) {
344 D(bug(" image/x-be-bitmap found\nstarting conversion to PICT\n"));
345
346 BMemoryIO *in_buffer = new BMemoryIO(clip, length);
347 BMallocIO *out_buffer = new BMallocIO();
348 status_t result=roster->Translate(output_trans,in_buffer,NULL,out_buffer,'PICT');
349 D(bug("result of conversion:%08x buffer_size:%d\n",result,out_buffer->BufferLength()));
350
351 // Add pict to Mac clipboard
352 *(int32 *)(proc2 + 3) = out_buffer->BufferLength();
353 *(char **)(proc2 + 9) = (char *)out_buffer->Buffer();
354 we_put_this_data = true;
355 Execute68k(proc2, &r);
356
357 delete in_buffer;
358 delete out_buffer;
359 #endif
360 }
361 be_clipboard->Commit();
362 be_clipboard->Unlock();
363 }
364 break;
365 }
366 }