1 | /****************************************************************************
|
---|
2 | ** $Id: qmime_pm.cpp 20 2005-11-17 18:00:27Z dmik $
|
---|
3 | **
|
---|
4 | ** Implementation of OS/2 PM MIME <-> clipboard converters
|
---|
5 | **
|
---|
6 | ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved.
|
---|
7 | ** Copyright (C) 2004 Norman ASA. Initial OS/2 Port.
|
---|
8 | ** Copyright (C) 2005 netlabs.org. Further OS/2 Development.
|
---|
9 | **
|
---|
10 | ** This file is part of the kernel module of the Qt GUI Toolkit.
|
---|
11 | **
|
---|
12 | ** This file may be distributed under the terms of the Q Public License
|
---|
13 | ** as defined by Trolltech AS of Norway and appearing in the file
|
---|
14 | ** LICENSE.QPL included in the packaging of this file.
|
---|
15 | **
|
---|
16 | ** This file may be distributed and/or modified under the terms of the
|
---|
17 | ** GNU General Public License version 2 as published by the Free Software
|
---|
18 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
---|
19 | ** packaging of this file.
|
---|
20 | **
|
---|
21 | ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
|
---|
22 | ** licenses may use this file in accordance with the Qt Commercial License
|
---|
23 | ** Agreement provided with the Software.
|
---|
24 | **
|
---|
25 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
---|
26 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
---|
27 | **
|
---|
28 | ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
|
---|
29 | ** information about Qt Commercial License Agreements.
|
---|
30 | ** See http://www.trolltech.com/qpl/ for QPL licensing information.
|
---|
31 | ** See http://www.trolltech.com/gpl/ for GPL licensing information.
|
---|
32 | **
|
---|
33 | ** Contact info@trolltech.com if any conditions of this licensing are
|
---|
34 | ** not clear to you.
|
---|
35 | **
|
---|
36 | **********************************************************************/
|
---|
37 |
|
---|
38 | #include "qmime.h"
|
---|
39 |
|
---|
40 | #ifndef QT_NO_MIME
|
---|
41 |
|
---|
42 | #include "qstrlist.h"
|
---|
43 | #include "qimage.h"
|
---|
44 | #include "qdatastream.h"
|
---|
45 | #include "qdragobject.h"
|
---|
46 | #include "qbuffer.h"
|
---|
47 | #include "qapplication_p.h"
|
---|
48 | #include "qtextcodec.h"
|
---|
49 | #include "qregexp.h"
|
---|
50 | #include "qt_os2.h"
|
---|
51 |
|
---|
52 |
|
---|
53 | static QPtrList<QPMMime> mimes;
|
---|
54 |
|
---|
55 | /*!
|
---|
56 | \class QPMMime qmime.h
|
---|
57 | \brief The QPMMime class maps open-standard MIME to OS/2 PM Clipboard formats.
|
---|
58 | \ingroup io
|
---|
59 | \ingroup draganddrop
|
---|
60 | \ingroup misc
|
---|
61 |
|
---|
62 | Qt's drag-and-drop and clipboard facilities use the MIME standard.
|
---|
63 | On X11, this maps trivially to the Xdnd protocol, but on OS/2
|
---|
64 | although some applications use MIME types to describe clipboard
|
---|
65 | formats, others use arbitrary non-standardized naming conventions,
|
---|
66 | or unnamed built-in formats of OS/2.
|
---|
67 |
|
---|
68 | By instantiating subclasses of QPMMime that provide conversions
|
---|
69 | between OS/2 PM Clipboard and MIME formats, you can convert
|
---|
70 | proprietary clipboard formats to MIME formats.
|
---|
71 |
|
---|
72 | Qt has predefined support for the following OS/2 PM Clipboard formats:
|
---|
73 | \list
|
---|
74 | \i CF_TEXT - converted to "text/plain;charset=system" or "text/plain"
|
---|
75 | and supported by QTextDrag.
|
---|
76 | \i CF_BITMAP - converted to "image/fmt", where fmt is
|
---|
77 | a \link QImage::outputFormats() Qt image format\endlink,
|
---|
78 | and supported by QImageDrag.
|
---|
79 | \endlist
|
---|
80 |
|
---|
81 | An example use of this class would be to map the OS/2 Metafile
|
---|
82 | clipboard format (CF_METAFILE) to and from the MIME type "image/x-metafile".
|
---|
83 | This conversion might simply be adding or removing a header, or even
|
---|
84 | just passing on the data. See the
|
---|
85 | \link dnd.html Drag-and-Drop documentation\endlink for more information
|
---|
86 | on choosing and definition MIME types.
|
---|
87 |
|
---|
88 | You can check if a MIME type is convertible using canConvert() and
|
---|
89 | can perform conversions with convertToMime() and convertFromMime().
|
---|
90 | */
|
---|
91 |
|
---|
92 | /*!
|
---|
93 | Constructs a new conversion object, adding it to the globally accessed
|
---|
94 | list of available convertors.
|
---|
95 | */
|
---|
96 | QPMMime::QPMMime()
|
---|
97 | {
|
---|
98 | mimes.append( this );
|
---|
99 | }
|
---|
100 |
|
---|
101 | /*!
|
---|
102 | Destroys a conversion object, removing it from the global
|
---|
103 | list of available convertors.
|
---|
104 | */
|
---|
105 | QPMMime::~QPMMime()
|
---|
106 | {
|
---|
107 | mimes.remove( this );
|
---|
108 | }
|
---|
109 |
|
---|
110 |
|
---|
111 |
|
---|
112 | struct QPMRegisteredMimeType {
|
---|
113 | QPMRegisteredMimeType( ulong c, const char *m ) :
|
---|
114 | cf( c ), mime( m ) {}
|
---|
115 | ulong cf;
|
---|
116 | QCString mime;
|
---|
117 | };
|
---|
118 |
|
---|
119 | static QPtrList<QPMRegisteredMimeType> mimetypes;
|
---|
120 |
|
---|
121 |
|
---|
122 | class QPMMimeAnyMime : public QPMMime {
|
---|
123 | public:
|
---|
124 | const char* convertorName();
|
---|
125 | int countCf();
|
---|
126 | ulong cf( int index );
|
---|
127 | ulong flFor( ulong cf );
|
---|
128 | ulong cfFor( const char* mime );
|
---|
129 | const char* mimeFor( ulong cf );
|
---|
130 | bool canConvert( const char* mime, ulong cf );
|
---|
131 | QByteArray convertToMime( QByteArray data, const char *, ulong );
|
---|
132 | QByteArray convertFromMime( QByteArray data, const char *, ulong );
|
---|
133 | };
|
---|
134 |
|
---|
135 | const char* QPMMimeAnyMime::convertorName()
|
---|
136 | {
|
---|
137 | return "Any-Mime";
|
---|
138 | }
|
---|
139 |
|
---|
140 | int QPMMimeAnyMime::countCf()
|
---|
141 | {
|
---|
142 | return mimetypes.count();
|
---|
143 | }
|
---|
144 |
|
---|
145 | ulong QPMMimeAnyMime::cf( int index )
|
---|
146 | {
|
---|
147 | return mimetypes.at( index )->cf;
|
---|
148 | }
|
---|
149 |
|
---|
150 | ulong QPMMimeAnyMime::flFor( ulong cf )
|
---|
151 | {
|
---|
152 | // all formats in this converter assume CFI_POINTER data storage type
|
---|
153 | return CFI_POINTER;
|
---|
154 | }
|
---|
155 |
|
---|
156 | ulong QPMMimeAnyMime::cfFor( const char* mime )
|
---|
157 | {
|
---|
158 | QPMRegisteredMimeType *mt = mimetypes.current();
|
---|
159 | if ( mt ) // quick check with most-recent
|
---|
160 | if ( qstricmp( mt->mime, mime ) == 0 )
|
---|
161 | return mt->cf;
|
---|
162 | for ( mt = mimetypes.first(); mt; mt = mimetypes.next() )
|
---|
163 | if ( qstricmp( mt->mime, mime ) == 0 )
|
---|
164 | return mt->cf;
|
---|
165 | // try to register the mime type
|
---|
166 | return registerMimeType( mime );
|
---|
167 | }
|
---|
168 |
|
---|
169 | const char* QPMMimeAnyMime::mimeFor( ulong cf )
|
---|
170 | {
|
---|
171 | QPMRegisteredMimeType *mt = mimetypes.current();
|
---|
172 | if ( mt ) // quick check with most-recent
|
---|
173 | if ( mt->cf == cf )
|
---|
174 | return mt->mime;
|
---|
175 | for ( mt = mimetypes.first(); mt; mt = mimetypes.next() )
|
---|
176 | if ( mt->cf == cf )
|
---|
177 | return mt->mime;
|
---|
178 | return 0;
|
---|
179 | }
|
---|
180 |
|
---|
181 | bool QPMMimeAnyMime::canConvert( const char* mime, ulong cf )
|
---|
182 | {
|
---|
183 | QPMRegisteredMimeType *mt = mimetypes.current();
|
---|
184 | do {
|
---|
185 | if ( mt ) // quick check with most-recent
|
---|
186 | if ( mt->cf == cf )
|
---|
187 | break;
|
---|
188 | for ( mt = mimetypes.first(); mt; mt = mimetypes.next() )
|
---|
189 | if ( mt->cf == cf )
|
---|
190 | break;
|
---|
191 | if ( !mt ) {
|
---|
192 | ulong f = registerMimeType( mime );
|
---|
193 | return f && f == cf;
|
---|
194 | }
|
---|
195 | } while ( 0 );
|
---|
196 |
|
---|
197 | return qstricmp( mt->mime, mime ) == 0;
|
---|
198 | }
|
---|
199 |
|
---|
200 | QByteArray QPMMimeAnyMime::convertToMime( QByteArray data, const char *, ulong )
|
---|
201 | {
|
---|
202 | return data;
|
---|
203 | }
|
---|
204 |
|
---|
205 | QByteArray QPMMimeAnyMime::convertFromMime( QByteArray data, const char *, ulong )
|
---|
206 | {
|
---|
207 | return data;
|
---|
208 | }
|
---|
209 |
|
---|
210 |
|
---|
211 |
|
---|
212 | class QPMMimeText : public QPMMime {
|
---|
213 | public:
|
---|
214 | QPMMimeText();
|
---|
215 | const char* convertorName();
|
---|
216 | int countCf();
|
---|
217 | ulong cf( int index );
|
---|
218 | ulong flFor( ulong cf );
|
---|
219 | ulong cfFor( const char* mime );
|
---|
220 | const char* mimeFor( ulong cf );
|
---|
221 | bool canConvert( const char* mime, ulong cf );
|
---|
222 | QByteArray convertToMime( QByteArray data, const char *, ulong cf );
|
---|
223 | QByteArray convertFromMime( QByteArray data, const char *, ulong cf );
|
---|
224 | private:
|
---|
225 | const ulong CF_TextUnicode;
|
---|
226 | };
|
---|
227 |
|
---|
228 | QPMMimeText::QPMMimeText() :
|
---|
229 | // register a clipboard format for unicode text
|
---|
230 | // ("text/unicode" is what Mozilla uses to for unicode, so Qt apps will
|
---|
231 | // be able to interchange unicode text with Mozilla apps)
|
---|
232 | CF_TextUnicode ( WinAddAtom( WinQuerySystemAtomTable(), "text/unicode" ) )
|
---|
233 | {
|
---|
234 | }
|
---|
235 |
|
---|
236 | const char* QPMMimeText::convertorName()
|
---|
237 | {
|
---|
238 | return "Text";
|
---|
239 | }
|
---|
240 |
|
---|
241 | int QPMMimeText::countCf()
|
---|
242 | {
|
---|
243 | return 2;
|
---|
244 | }
|
---|
245 |
|
---|
246 | ulong QPMMimeText::cf( int index )
|
---|
247 | {
|
---|
248 | if ( index == 0 )
|
---|
249 | return CF_TextUnicode;
|
---|
250 | else if ( index == 1 )
|
---|
251 | return CF_TEXT;
|
---|
252 | return 0;
|
---|
253 | }
|
---|
254 |
|
---|
255 | ulong QPMMimeText::flFor( ulong cf )
|
---|
256 | {
|
---|
257 | // both CF_TEXT and CF_TextUnicode use CFI_POINTER
|
---|
258 | return cf == CF_TEXT || cf == CF_TextUnicode ? CFI_POINTER : 0;
|
---|
259 | }
|
---|
260 |
|
---|
261 | ulong QPMMimeText::cfFor( const char* mime )
|
---|
262 | {
|
---|
263 | /// @todo (dmik) do we want to accept "text/plain" w/o "charset="?
|
---|
264 | // if ( qstricmp( mime, "text/plain" ) == 0 )
|
---|
265 | // return CF_TEXT;
|
---|
266 |
|
---|
267 | QCString m( mime );
|
---|
268 | int i = m.find( "charset=" );
|
---|
269 | if ( i >= 0 ) {
|
---|
270 | QCString cs( m.data() + i + 8 );
|
---|
271 | i = cs.find( ";" );
|
---|
272 | if ( i >= 0 )
|
---|
273 | cs = cs.left( i );
|
---|
274 | if ( cs == "system" )
|
---|
275 | return CF_TEXT;
|
---|
276 | if ( cs == "ISO-10646-UCS-2" )
|
---|
277 | return CF_TextUnicode;
|
---|
278 | }
|
---|
279 | return 0;
|
---|
280 | }
|
---|
281 |
|
---|
282 | const char* QPMMimeText::mimeFor( ulong cf )
|
---|
283 | {
|
---|
284 | if ( cf == CF_TEXT )
|
---|
285 | return "text/plain;charset=system";
|
---|
286 | else if ( cf == CF_TextUnicode )
|
---|
287 | return "text/plain;charset=ISO-10646-UCS-2";
|
---|
288 | return 0;
|
---|
289 | }
|
---|
290 |
|
---|
291 | bool QPMMimeText::canConvert( const char* mime, ulong cf )
|
---|
292 | {
|
---|
293 | if ( !cf )
|
---|
294 | return FALSE;
|
---|
295 |
|
---|
296 | return cfFor( mime ) == cf;
|
---|
297 | }
|
---|
298 |
|
---|
299 | /*
|
---|
300 | text/plain is defined as using CRLF, but so many programs don't,
|
---|
301 | and programmers just look for '\n' in strings.
|
---|
302 | OS/2 really needs CRLF, so we ensure it here.
|
---|
303 | */
|
---|
304 |
|
---|
305 | QByteArray QPMMimeText::convertToMime( QByteArray data, const char* , ulong cf )
|
---|
306 | {
|
---|
307 | if ( cf == CF_TEXT ) {
|
---|
308 | const char* d = data.data();
|
---|
309 | const int s = qstrlen( d );
|
---|
310 | QByteArray r( data.size() + 1 );
|
---|
311 | char* o = r.data();
|
---|
312 | int j = 0;
|
---|
313 | for ( int i = 0; i < s; i++ ) {
|
---|
314 | char c = d[i];
|
---|
315 | if ( c != '\r' )
|
---|
316 | o[j++] = c;
|
---|
317 | }
|
---|
318 | o[j] = 0;
|
---|
319 | return r;
|
---|
320 | } else if ( cf == CF_TextUnicode ) {
|
---|
321 | // Mozilla uses un-marked little-endian nul-terminated Unicode
|
---|
322 | // for "text/unicode"
|
---|
323 | int sz = data.size();
|
---|
324 | int len = 0;
|
---|
325 | // Find NUL
|
---|
326 | for ( ; len < sz - 1 && (data[len+0] || data[len+1]); len += 2 )
|
---|
327 | ;
|
---|
328 |
|
---|
329 | QByteArray r( len + 2 );
|
---|
330 | r[0] = uchar( 0xff ); // BOM
|
---|
331 | r[1] = uchar( 0xfe );
|
---|
332 | memcpy( r.data() + 2, data.data(), len );
|
---|
333 | return r;
|
---|
334 | }
|
---|
335 |
|
---|
336 | return QByteArray();
|
---|
337 | }
|
---|
338 |
|
---|
339 | extern QTextCodec* qt_findcharset( const QCString& mimetype );
|
---|
340 |
|
---|
341 | QByteArray QPMMimeText::convertFromMime( QByteArray data, const char *mime, ulong cf )
|
---|
342 | {
|
---|
343 | if ( cf == CF_TEXT ) {
|
---|
344 | // Anticipate required space for CRLFs at 1/40
|
---|
345 | int maxsize = data.size() + data.size() / 40 + 3;
|
---|
346 | QByteArray r( maxsize );
|
---|
347 | char* o = r.data();
|
---|
348 | const char* d = data.data();
|
---|
349 | const int s = data.size();
|
---|
350 | bool cr = FALSE;
|
---|
351 | int j = 0;
|
---|
352 | for ( int i = 0; i < s; i++ ) {
|
---|
353 | char c = d[i];
|
---|
354 | if ( c == '\r' )
|
---|
355 | cr = TRUE;
|
---|
356 | else {
|
---|
357 | if ( c == '\n' ) {
|
---|
358 | if ( !cr )
|
---|
359 | o[j++]='\r';
|
---|
360 | }
|
---|
361 | cr = FALSE;
|
---|
362 | }
|
---|
363 | o[j++] = c;
|
---|
364 | if ( j + 3 >= maxsize ) {
|
---|
365 | maxsize += maxsize / 4;
|
---|
366 | r.resize( maxsize );
|
---|
367 | o = r.data();
|
---|
368 | }
|
---|
369 | }
|
---|
370 | o[j] = 0;
|
---|
371 | return r;
|
---|
372 | } else if ( cf == CF_TextUnicode ) {
|
---|
373 | QTextCodec *codec = qt_findcharset( mime );
|
---|
374 | QString str = codec->toUnicode( data );
|
---|
375 | const QChar *u = str.unicode();
|
---|
376 | QString res;
|
---|
377 | const int s = str.length();
|
---|
378 | int maxsize = s + s / 40 + 3;
|
---|
379 | res.setLength( maxsize );
|
---|
380 | int ri = 0;
|
---|
381 | bool cr = FALSE;
|
---|
382 | for ( int i = 0; i < s; ++ i ) {
|
---|
383 | if ( *u == '\r' )
|
---|
384 | cr = TRUE;
|
---|
385 | else {
|
---|
386 | if ( *u == '\n' && !cr )
|
---|
387 | res[ri++] = QChar('\r');
|
---|
388 | cr = FALSE;
|
---|
389 | }
|
---|
390 | res[ri++] = *u;
|
---|
391 | if ( ri + 3 >= maxsize ) {
|
---|
392 | maxsize += maxsize / 4;
|
---|
393 | res.setLength( maxsize );
|
---|
394 | }
|
---|
395 | ++u;
|
---|
396 | }
|
---|
397 | res.truncate( ri );
|
---|
398 | const int byteLength = res.length() * 2;
|
---|
399 | QByteArray r( byteLength + 2 );
|
---|
400 | memcpy( r.data(), res.unicode(), byteLength );
|
---|
401 | r[byteLength] = 0;
|
---|
402 | r[byteLength+1] = 0;
|
---|
403 | return r;
|
---|
404 | }
|
---|
405 |
|
---|
406 | return QByteArray();
|
---|
407 | }
|
---|
408 |
|
---|
409 |
|
---|
410 | class QPMMimeImage : public QPMMime {
|
---|
411 | public:
|
---|
412 | const char* convertorName();
|
---|
413 | int countCf();
|
---|
414 | ulong cf( int index );
|
---|
415 | ulong flFor( ulong cf );
|
---|
416 | ulong cfFor( const char* mime );
|
---|
417 | const char* mimeFor( ulong cf );
|
---|
418 | bool canConvert( const char* mime, ulong cf );
|
---|
419 | QByteArray convertToMime( QByteArray data, const char *mime, ulong cf );
|
---|
420 | QByteArray convertFromMime( QByteArray data, const char *mime, ulong cf );
|
---|
421 | };
|
---|
422 |
|
---|
423 | const char* QPMMimeImage::convertorName()
|
---|
424 | {
|
---|
425 | return "Image";
|
---|
426 | }
|
---|
427 |
|
---|
428 | int QPMMimeImage::countCf()
|
---|
429 | {
|
---|
430 | return 1;
|
---|
431 | }
|
---|
432 |
|
---|
433 | ulong QPMMimeImage::cf( int index )
|
---|
434 | {
|
---|
435 | return index == 0 ? CF_BITMAP : 0;
|
---|
436 | }
|
---|
437 |
|
---|
438 | ulong QPMMimeImage::flFor( ulong cf )
|
---|
439 | {
|
---|
440 | // CF_BITMAP uses CFI_HANDLE
|
---|
441 | return cf == CF_BITMAP ? CFI_HANDLE : 0;
|
---|
442 | }
|
---|
443 |
|
---|
444 | ulong QPMMimeImage::cfFor( const char *mime )
|
---|
445 | {
|
---|
446 | if ( qstrnicmp( mime, "image/", 6 ) == 0 ) {
|
---|
447 | QStrList ofmts = QImage::outputFormats();
|
---|
448 | for ( const char *fmt = ofmts.first(); fmt; fmt = ofmts.next() )
|
---|
449 | if ( qstricmp( fmt, mime + 6 ) == 0 )
|
---|
450 | return CF_BITMAP;
|
---|
451 | }
|
---|
452 | return 0;
|
---|
453 | }
|
---|
454 |
|
---|
455 | const char* QPMMimeImage::mimeFor( ulong cf )
|
---|
456 | {
|
---|
457 | if ( cf == CF_BITMAP )
|
---|
458 | return "image/bmp";
|
---|
459 | return 0;
|
---|
460 | }
|
---|
461 |
|
---|
462 | bool QPMMimeImage::canConvert( const char* mime, ulong cf )
|
---|
463 | {
|
---|
464 | if ( cf == CF_BITMAP && qstrnicmp( mime, "image/", 6 ) == 0 ) {
|
---|
465 | QStrList ofmts = QImage::outputFormats();
|
---|
466 | for ( const char* fmt = ofmts.first(); fmt; fmt = ofmts.next() )
|
---|
467 | if ( qstricmp( fmt, mime + 6 ) == 0 )
|
---|
468 | return TRUE;
|
---|
469 | }
|
---|
470 | return FALSE;
|
---|
471 | }
|
---|
472 |
|
---|
473 | QByteArray QPMMimeImage::convertToMime( QByteArray data, const char *mime, ulong cf )
|
---|
474 | {
|
---|
475 | if ( qstrnicmp( mime, "image/", 6 ) != 0 || cf != CF_BITMAP ) // Sanity
|
---|
476 | return QByteArray();
|
---|
477 |
|
---|
478 | HBITMAP hbm = (HBITMAP) *(ULONG *) data.data();
|
---|
479 |
|
---|
480 | QPixmap pm;
|
---|
481 | pm.attachHandle( hbm );
|
---|
482 | QImage img = pm.convertToImage();
|
---|
483 | pm.detachHandle(); // prevent hbm from being deleted
|
---|
484 |
|
---|
485 | QCString ofmt = mime + 6;
|
---|
486 | QByteArray ba;
|
---|
487 | QBuffer iod( ba );
|
---|
488 | iod.open( IO_WriteOnly );
|
---|
489 | QImageIO iio( &iod, ofmt.upper() );
|
---|
490 | iio.setImage( img );
|
---|
491 | if ( iio.write() ) {
|
---|
492 | iod.close();
|
---|
493 | return ba;
|
---|
494 | }
|
---|
495 |
|
---|
496 | // Failed
|
---|
497 | return QByteArray();
|
---|
498 | }
|
---|
499 |
|
---|
500 | QByteArray QPMMimeImage::convertFromMime( QByteArray data, const char *mime, ulong cf )
|
---|
501 | {
|
---|
502 | if ( qstrnicmp( mime, "image/", 6 ) != 0 || cf != CF_BITMAP ) // Sanity
|
---|
503 | return QByteArray();
|
---|
504 |
|
---|
505 | QImage img;
|
---|
506 | img.loadFromData( (unsigned char *) data.data(), data.size() );
|
---|
507 | if ( !img.isNull() ) {
|
---|
508 | HBITMAP hbm = QPixmap( img ).detachHandle();
|
---|
509 | if ( hbm ) {
|
---|
510 | QByteArray ba ( sizeof(HBITMAP) );
|
---|
511 | *(HBITMAP *) ba.data() = hbm;
|
---|
512 | return ba;
|
---|
513 | }
|
---|
514 | }
|
---|
515 |
|
---|
516 | // Failed
|
---|
517 | return QByteArray();
|
---|
518 | }
|
---|
519 |
|
---|
520 |
|
---|
521 | static QPMMimeAnyMime *anymime = 0;
|
---|
522 |
|
---|
523 | static
|
---|
524 | void cleanup_mimes()
|
---|
525 | {
|
---|
526 | QPMMime* wm;
|
---|
527 | while ( (wm = mimes.first()) ) {
|
---|
528 | delete wm;
|
---|
529 | }
|
---|
530 | mimetypes.setAutoDelete( TRUE );
|
---|
531 | mimetypes.clear();
|
---|
532 | anymime = 0;
|
---|
533 | }
|
---|
534 |
|
---|
535 | /*!
|
---|
536 | This is an internal function.
|
---|
537 | */
|
---|
538 | void QPMMime::initialize()
|
---|
539 | {
|
---|
540 | if ( mimes.isEmpty() ) {
|
---|
541 | new QPMMimeImage;
|
---|
542 | new QPMMimeText;
|
---|
543 | anymime = new QPMMimeAnyMime;
|
---|
544 |
|
---|
545 | qAddPostRoutine( cleanup_mimes );
|
---|
546 | }
|
---|
547 | }
|
---|
548 |
|
---|
549 | /*!
|
---|
550 | \internal
|
---|
551 | This is an internal function.
|
---|
552 | */
|
---|
553 | ulong QPMMime::registerMimeType( const char *mime )
|
---|
554 | {
|
---|
555 | // first, look if other non-QPMMimeAnyMime convertors support this mime,
|
---|
556 | // to avoid double handling of this mime type by another (probably,
|
---|
557 | // system-integrated and most likely more specialized) convertor and the
|
---|
558 | // dummy "pass-through" QPMMimeAnyMime convertor (which will handle the
|
---|
559 | // given mime type after once we call mimetyes.append (...)).
|
---|
560 | QPtrListIterator<QPMMime> it( mimes );
|
---|
561 | for ( QPMMime* c; (c = *it); ++ it )
|
---|
562 | if ( c != anymime && c->cfFor( mime ) )
|
---|
563 | return 0;
|
---|
564 |
|
---|
565 | ulong f = WinAddAtom( WinQuerySystemAtomTable(), mime );
|
---|
566 | if ( !f ) {
|
---|
567 | #ifndef QT_NO_DEBUG
|
---|
568 | qSystemWarning( "QPMMime: Failed to register clipboard format" );
|
---|
569 | #endif
|
---|
570 | return 0;
|
---|
571 | }
|
---|
572 | QPMRegisteredMimeType *mt = mimetypes.current();
|
---|
573 | if ( !mt || mt->cf != f ) {
|
---|
574 | for ( mt = mimetypes.first(); mt && mt->cf != f; mt = mimetypes.next() )
|
---|
575 | ;
|
---|
576 | if ( !mt ) {
|
---|
577 | mimetypes.append( new QPMRegisteredMimeType ( f, mime ) );
|
---|
578 | // successful memory allocation check
|
---|
579 | if ( !(mt = mimetypes.current()) || mt->cf != f )
|
---|
580 | return 0;
|
---|
581 | }
|
---|
582 | }
|
---|
583 | return f;
|
---|
584 | }
|
---|
585 |
|
---|
586 | /*!
|
---|
587 | Returns the most-recently created QPMMime that can convert
|
---|
588 | between the \a mime and \a cf formats. Returns 0 if no such convertor
|
---|
589 | exists.
|
---|
590 | */
|
---|
591 | QPMMime *
|
---|
592 | QPMMime::convertor( const char *mime, ulong cf )
|
---|
593 | {
|
---|
594 | // return nothing for illegal requests
|
---|
595 | if ( !cf )
|
---|
596 | return 0;
|
---|
597 |
|
---|
598 | QPMMime* wm;
|
---|
599 | for ( wm = mimes.first(); wm; wm = mimes.next() ) {
|
---|
600 | if ( wm->canConvert( mime, cf ) ) {
|
---|
601 | return wm;
|
---|
602 | }
|
---|
603 | }
|
---|
604 | return 0;
|
---|
605 | }
|
---|
606 |
|
---|
607 |
|
---|
608 | /*!
|
---|
609 | Returns a MIME type for \a cf, or 0 if none exists.
|
---|
610 | */
|
---|
611 | const char* QPMMime::cfToMime( ulong cf )
|
---|
612 | {
|
---|
613 | const char* m = 0;
|
---|
614 | QPMMime* wm;
|
---|
615 | for ( wm = mimes.first(); wm && !m; wm = mimes.next() ) {
|
---|
616 | m = wm->mimeFor( cf );
|
---|
617 | }
|
---|
618 | return m;
|
---|
619 | }
|
---|
620 |
|
---|
621 | /*!
|
---|
622 | Returns a list of all currently defined QPMMime objects.
|
---|
623 | */
|
---|
624 | QPtrList<QPMMime> QPMMime::all()
|
---|
625 | {
|
---|
626 | return mimes;
|
---|
627 | }
|
---|
628 |
|
---|
629 | /*!
|
---|
630 | \fn const char* QPMMime::convertorName()
|
---|
631 |
|
---|
632 | Returns a name for the convertor.
|
---|
633 |
|
---|
634 | All subclasses must reimplement this pure virtual function.
|
---|
635 | */
|
---|
636 |
|
---|
637 | /*!
|
---|
638 | \fn int QPMMime::countCf()
|
---|
639 |
|
---|
640 | Returns the number of OS/2 PM Clipboard formats supported by this
|
---|
641 | convertor.
|
---|
642 |
|
---|
643 | All subclasses must reimplement this pure virtual function.
|
---|
644 | */
|
---|
645 |
|
---|
646 | /*!
|
---|
647 | \fn ulong QPMMime::cf(int index)
|
---|
648 |
|
---|
649 | Returns the OS/2 PM Clipboard format supported by this convertor
|
---|
650 | that is ordinarily at position \a index. This means that cf(0)
|
---|
651 | returns the first OS/2 PM Clipboard format supported, and
|
---|
652 | cf(countCf()-1) returns the last. If \a index is out of range the
|
---|
653 | return value is undefined.
|
---|
654 |
|
---|
655 | All subclasses must reimplement this pure virtual function.
|
---|
656 | */
|
---|
657 |
|
---|
658 | /*!
|
---|
659 | \fn ulong QPMMime::flFor(ulong cf)
|
---|
660 |
|
---|
661 | Returns the data storage flag for the OS/2 PM Clipboard type \a cf
|
---|
662 | (either \c CFI_POINTER or \c CFI_HANDLE) used by this convertor,
|
---|
663 | or 0 if invalid \a cf is specified.
|
---|
664 |
|
---|
665 | All subclasses must reimplement this pure virtual function.
|
---|
666 | */
|
---|
667 |
|
---|
668 | /*!
|
---|
669 | \fn bool QPMMime::canConvert( const char* mime, ulong cf )
|
---|
670 |
|
---|
671 | Returns TRUE if the convertor can convert (both ways) between
|
---|
672 | \a mime and \a cf; otherwise returns FALSE.
|
---|
673 |
|
---|
674 | All subclasses must reimplement this pure virtual function.
|
---|
675 | */
|
---|
676 |
|
---|
677 | /*!
|
---|
678 | \fn const char* QPMMime::mimeFor(ulong cf)
|
---|
679 |
|
---|
680 | Returns the MIME type used for OS/2 PM Clipboard format \a cf, or
|
---|
681 | 0 if this convertor does not support \a cf.
|
---|
682 |
|
---|
683 | All subclasses must reimplement this pure virtual function.
|
---|
684 | */
|
---|
685 |
|
---|
686 | /*!
|
---|
687 | \fn ulong QPMMime::cfFor(const char* mime)
|
---|
688 |
|
---|
689 | Returns the OS/2 PM Clipboard type used for MIME type \a mime, or
|
---|
690 | 0 if this convertor does not support \a mime.
|
---|
691 |
|
---|
692 | All subclasses must reimplement this pure virtual function.
|
---|
693 | */
|
---|
694 |
|
---|
695 | /*!
|
---|
696 | \fn QByteArray QPMMime::convertToMime( QByteArray data, const char* mime, ulong cf )
|
---|
697 |
|
---|
698 | Returns \a data converted from OS/2 PM Clipboard format \a cf
|
---|
699 | to MIME type \a mime.
|
---|
700 |
|
---|
701 | Note that OS/2 PM Clipboard formats must all be self-terminating. The
|
---|
702 | input \a data may contain trailing data. If flFor(ulong) for the given \a cf
|
---|
703 | has the \c CFI_HANDLE flag set, then first 4 bytes of \a data represent a
|
---|
704 | valid OS/2 handle of the appropriate type, otherwise \a data contains data
|
---|
705 | itself.
|
---|
706 |
|
---|
707 | All subclasses must reimplement this pure virtual function.
|
---|
708 | */
|
---|
709 |
|
---|
710 | /*!
|
---|
711 | \fn QByteArray QPMMime::convertFromMime( QByteArray data, const char* mime, ulong cf )
|
---|
712 |
|
---|
713 | Returns \a data converted from MIME type \a mime
|
---|
714 | to OS/2 PM Clipboard format \a cf.
|
---|
715 |
|
---|
716 | Note that OS/2 PM Clipboard formats must all be self-terminating. The
|
---|
717 | return value may contain trailing data. If flFor(ulong) for the given \a cf
|
---|
718 | has the \c CFI_HANDLE flag set, then first 4 bytes of the returned array
|
---|
719 | must represent a valid OS/2 handle of the appropriate type, otherwise the array
|
---|
720 | contains data itself.
|
---|
721 |
|
---|
722 | All subclasses must reimplement this pure virtual function.
|
---|
723 | */
|
---|
724 |
|
---|
725 | #endif // QT_NO_MIME
|
---|