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, 5 months ago) by gbeauche
Branch: MAIN
CVS Tags: HEAD
Changes since 1.3: +1 -1 lines
Log Message:
Happy New Year!

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * clip_beos.cpp - Clipboard handling, BeOS implementation
3     *
4 gbeauche 1.4 * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig
5 cebix 1.1 *
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     }