Changeset 441 for trunk/src/gui/kernel
- Timestamp:
- Dec 26, 2009, 2:14:18 AM (16 years ago)
- Location:
- trunk/src/gui/kernel
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/gui/kernel/qmime.h
r439 r441 115 115 */ 116 116 117 typedef unsigned long ULONG; 117 #if !defined(QT_NO_DRAGANDDROP) 118 QT_END_NAMESPACE 119 #include "private/qpmobjectwindow_pm_p.h" 120 QT_BEGIN_NAMESPACE 121 #endif 118 122 119 123 class QPMCoopDragWorker; … … 125 129 #if !defined(QT_NO_DRAGANDDROP) 126 130 131 typedef QList<QByteArray> QByteArrayList; 132 127 133 class DragWorker 128 134 { 129 135 public: 130 DragWorker() : data(0) {}136 DragWorker() : src(0) {} 131 137 virtual ~DragWorker() {} 132 138 … … 177 183 { 178 184 public: 179 virtual const char *format( const char *drf) const = 0;185 virtual const QString &format(const char *drf) const = 0; 180 186 virtual bool provide(const char *drf, const QByteArray &allData, 181 187 ULONG itemIndex, QByteArray &itemData) = 0; … … 246 252 247 253 static bool canRender(DRAGITEM *item, const char *drf ); 248 static bool getSupportedRMFs(DRAGITEM *item, Q PtrList<QStrList> &list);254 static bool getSupportedRMFs(DRAGITEM *item, QList<QByteArrayList> &list); 249 255 250 256 private: … … 297 303 static QByteArray querySourceNameFull(DRAGITEM *item); 298 304 static bool canTargetRenderAsOS2File(DRAGITEM *item, QByteArray *fullName = 0); 299 static bool parseRMFs(HSTR rmfs, QList<Q List<QByteArray>> &list);305 static bool parseRMFs(HSTR rmfs, QList<QByteArrayList> &list); 300 306 static bool parseRMF(HSTR rmf, QByteArray &mechanism, QByteArray &format); 301 307 -
trunk/src/gui/kernel/qmime_pm.cpp
r439 r441 63 63 64 64 #ifdef QDND_DEBUG 65 # include "qdebug.h" 65 66 # define DEBUG(a) qDebug a 66 67 #else … … 72 73 #if !defined(QT_NO_DRAGANDDROP) 73 74 74 // @todo remove 75 //#define DRT_URL "UniformResourceLocator" 76 // 77 //#define DRM_OS2FILE "DRM_OS2FILE" 78 //#define DRM_SHAREDMEM "DRM_SHAREDMEM" 79 // 80 //#define DRF_UNKNOWN "DRF_UNKNOWN" 81 //#define DRF_TEXT "DRF_TEXT" 82 //#define DRF_POINTERDATA "DRF_POINTERDATA" 83 // 84 //#define MIME_TEXT_PLAIN "text/plain" 85 //#define MIME_TEXT_PLAIN_CHARSET_SYSTEM "text/plain;charset=system" 86 //#define MIME_TEXT_URI_LIST "text/uri-list" 75 // Undoc'd DC_PREPAREITEM, see 76 // http://lxr.mozilla.org/seamonkey/source/widget/src/os2/nsDragService.cpp 77 #if !defined (DC_PREPAREITEM) 78 #define DC_PREPAREITEM 0x40 79 #endif 87 80 88 81 /*! \internal … … 241 234 ULONG index; 242 235 Provider *provider; 243 Q CStringdrm;244 Q CStringdrf;236 QByteArray drm; 237 QByteArray drf; 245 238 DRAGTRANSFER *xfer; 246 239 bool rendered; … … 255 248 DrfProvider() : prov(0) {} 256 249 DrfProvider(const char *d, Provider *p) : drf(d), prov(p) {} 257 constQByteArray drf;258 Provider * constprov;250 QByteArray drf; 251 Provider *prov; 259 252 }; 260 253 … … 378 371 // (however, it doesn't help when dropping objects to it -- WPS still 379 372 // chooses DRM_OS2FILE). 380 formats = "( "DRM_SHAREDMEM","DRM_OS2FILE")x(" + formats + "),"381 "< "DRM_SHAREDMEM","DRF_POINTERDATA">";373 formats = "(DRM_SHAREDMEM,DRM_OS2FILE)x(" + formats + ")," 374 "<DRM_SHAREDMEM,DRF_POINTERDATA>"; 382 375 383 376 DEBUG(() << "DefaultDragWorker: formats" << formats … … 400 393 401 394 DEBUG(() << "DefaultDragWorker: Preparing item" << itemIndex << "(id " 402 << item->ulItemID << ") for <" << drm << "," << drf ">");395 << item->ulItemID << ") for <" << drm << "," << drf << ">"); 403 396 404 397 Provider *p = d->providerFor(drf); … … 469 462 << "(id " << xfer->pditem->ulItemID << ")"); 470 463 471 Q CStringdrm, drf;464 QByteArray drm, drf; 472 465 if (!parseRMF(xfer->hstrSelectedRMF, drm, drf)) 473 466 Q_ASSERT(/* parseRMF() = */ FALSE); … … 525 518 526 519 bool renderOk = false; 527 QByteArray allData = 528 source()->encodedData(req->provider->format(req->drf));520 521 QByteArray allData = source()->data(req->provider->format(req->drf)); 529 522 QByteArray itemData; 530 523 … … 534 527 if (renderOk) { 535 528 enum DRM { OS2File, SharedMem } drmType; 536 if (qstrcmp(req->drm, DRM_SHAREDMEM) == 0) drmType = SharedMem;529 if (qstrcmp(req->drm, "DRM_SHAREDMEM") == 0) drmType = SharedMem; 537 530 else drmType = OS2File; 538 531 539 532 if (drmType == OS2File) { 540 Q CStringrenderToName = queryHSTR(req->xfer->hstrRenderToName);533 QByteArray renderToName = queryHSTR(req->xfer->hstrRenderToName); 541 534 Q_ASSERT(!renderToName.isEmpty()); 542 535 renderOk = !renderToName.isEmpty(); … … 544 537 DEBUG(() << "DefaultDragWorker: Will write to" << renderToName); 545 538 QFile file(QFile::decodeName(renderToName)); 546 renderOk = file.open( IO_WriteOnly);539 renderOk = file.open(QIODevice::WriteOnly); 547 540 if (renderOk) { 548 Q_LONG written = 549 file.writeBlock(itemData.data(), itemData.size()); 550 renderOk = written == (Q_LONG) itemData.size() && 551 file.status() == IO_Ok; 541 qint64 written = file.write(itemData, itemData.size()); 542 renderOk = written == itemData.size(); 552 543 file.close(); 553 544 if (renderOk && req->xfer->pditem->hstrType) { … … 626 617 DEBUG(("DefaultDragWorker: Freed DRAGTRANSFER: " 627 618 "req->xfer %p size %lu (0x%08lX) flags 0x%08lX", 628 req->xfer, size, size, flags) ;619 req->xfer, size, size, flags)); 629 620 } 630 621 #endif … … 686 677 // first provider 687 678 d->itemCnt = itemCnt; 688 d->providers. insert(Data::DrfProvider(drf, provider));679 d->providers.append(Data::DrfProvider(drf, provider)); 689 680 return true; 690 681 } … … 693 684 // ensure there are no dups (several providers for the same drf) 694 685 if (!d->providerFor(drf)) 695 d->providers. insert(Data::DrfProvider(drf, provider));686 d->providers.append(Data::DrfProvider(drf, provider)); 696 687 return true; 697 688 } … … 703 694 bool QPMMime::DefaultDragWorker::canRender(const char *drm) 704 695 { 705 return qstrcmp(drm, DRM_SHAREDMEM) == 0 ||706 qstrcmp(drm, DRM_OS2FILE) == 0;696 return qstrcmp(drm, "DRM_SHAREDMEM") == 0 || 697 qstrcmp(drm, "DRM_OS2FILE") == 0; 707 698 } 708 699 … … 715 706 MimeProvider() : prov(NULL) {} 716 707 MimeProvider(const QString &m, Provider *p) : mime(m), prov(p) {} 717 constQString mime;718 Provider * constprov;708 QString mime; 709 Provider *prov; 719 710 }; 720 711 … … 736 727 bool got_DM_RENDERCOMPLETE : 1; 737 728 USHORT flags_DM_RENDERCOMPLETE; 738 int waiting_DM_RENDERCOMPLETE; 729 730 QEventLoop eventLoop; 739 731 }; 740 732 … … 744 736 d->sending_DM_RENDER = d->got_DM_RENDERCOMPLETE = false; 745 737 d->flags_DM_RENDERCOMPLETE = 0; 746 d->waiting_DM_RENDERCOMPLETE = 0;747 738 } 748 739 … … 754 745 void QPMMime::DefaultDropWorker::cleanup(bool isAccepted, bool isActAccepted) 755 746 { 756 if (d-> waiting_DM_RENDERCOMPLETE != 0) {747 if (d->eventLoop.isRunning()) { 757 748 #ifndef QT_NO_DEBUG 758 749 qWarning("The previous drag source didn't post DM_RENDERCOMPLETE!\n" 759 750 "Contact the drag source developer."); 760 751 #endif 761 qApp->eventLoop()->exitLoop();752 d->eventLoop.exit(1); 762 753 } 763 754 … … 766 757 d->sending_DM_RENDER = d->got_DM_RENDERCOMPLETE = false; 767 758 d->flags_DM_RENDERCOMPLETE = 0; 768 d->waiting_DM_RENDERCOMPLETE = 0;769 759 } 770 760 … … 774 764 } 775 765 776 bool QPMMime::DefaultDropWorker::provides(const char *format) const 777 { 778 return d->providerFor(format) != NULL; 779 } 780 781 int QPMMime::DefaultDropWorker::formatCount() const 782 { 783 return d->providers.count(); 784 } 785 786 const char *QPMMime::DefaultDropWorker::format(int fn) const 787 { 788 if (fn >= 0 && (uint) fn < d->providers.count()) 789 return d->providers[ fn ].mime; 790 return NULL; 791 } 792 793 static QCString composeTempFileName() 794 { 795 static char defTmpDir[ 3 ] = { 0 }; 796 const char *tmpDir = getenv("TEMP"); 797 if (!tmpDir) tmpDir = getenv("TMP"); 798 if (!tmpDir || !QFile::exists(QFile::decodeName(tmpDir))) { 799 if (!defTmpDir[ 0 ]) { 800 ULONG bootDrive = 0; 801 DosQuerySysInfo(QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, 802 &bootDrive, sizeof (bootDrive)); 803 defTmpDir[ 0 ] = bootDrive; 804 defTmpDir[ 1 ] = ':'; 805 } 806 tmpDir = defTmpDir; 807 } 766 bool QPMMime::DefaultDropWorker::hasFormat(const QString &mimeType) const 767 { 768 return d->providerFor(mimeType) != NULL; 769 } 770 771 // @todo 772 //int QPMMime::DefaultDropWorker::formatCount() const 773 //{ 774 // return d->providers.count(); 775 //} 776 777 QStringList QPMMime::DefaultDropWorker::formats() const 778 { 779 QStringList mimes; 780 foreach(const Data::MimeProvider &p, d->providers) 781 mimes << p.mime; 782 return mimes; 783 } 784 785 static QByteArray composeTempFileName() 786 { 787 QByteArray tmpDir = 788 QFile::encodeName(QDir::toNativeSeparators(QDir::tempPath())); 808 789 809 790 static bool srandDone = false; … … 817 798 int attempts = Attempts; 818 799 819 Q CString tmpName;800 QString tmpName; 820 801 do { 821 tmpName.sprintf("%s\\%08lX.tmp", tmpDir , num);822 if (!QFile::exists( QFile::decodeName(tmpName)))802 tmpName.sprintf("%s\\%08lX.tmp", tmpDir.constData(), num); 803 if (!QFile::exists(tmpName)) 823 804 break; 824 805 num = rand(); … … 827 808 Q_ASSERT(attempts > 0); 828 809 if (attempts <= 0) 829 tmpName.resize(0); 830 831 return tmpName; 832 } 833 834 QByteArray QPMMime::DefaultDropWorker::encodedData(const char *format) const 835 { 836 DEBUG("DefaultDropWorker::encodedData(" << format << ")"); 837 838 QByteArray data; 810 tmpName.clear(); 811 812 return QFile::encodeName(tmpName); 813 } 814 815 QVariant QPMMime::DefaultDropWorker::retrieveData(const QString &mimeType, 816 QVariant::Type type) const 817 { 818 Q_UNUSED(type); 819 820 DEBUG(() << "DefaultDropWorker::retrieveData(" << mimeType << ")"); 821 822 QVariant ret; 839 823 840 824 Q_ASSERT(info()); 841 825 if (!info()) 842 return data;826 return ret; 843 827 844 828 ULONG itemCount = DrgQueryDragitemCount(info()); 845 829 Q_ASSERT(itemCount); 846 830 if (!itemCount) 847 return data;848 849 Provider *provider = d->providerFor( format);831 return ret; 832 833 Provider *provider = d->providerFor(mimeType); 850 834 if (!provider) 851 return data;852 853 const char *drf = provider->drf( format);835 return ret; 836 837 const char *drf = provider->drf(mimeType); 854 838 Q_ASSERT(drf); 855 839 if (!drf) 856 return data;840 return ret; 857 841 858 842 // Note: Allocating and freeing DRAGTRANSFER structures is a real mess. It's … … 868 852 // always allocate a new struct per every item. It seems to work. 869 853 870 Q CStringrenderToName = composeTempFileName();854 QByteArray renderToName = composeTempFileName(); 871 855 HSTR hstrRenderToName = DrgAddStrHandle(renderToName); 872 856 873 857 HSTR rmfOS2File = 874 DrgAddStrHandle(Q CString().sprintf("<"DRM_OS2FILE",%s>", drf));858 DrgAddStrHandle(QString().sprintf("<DRM_OS2FILE,%s>", drf).toLocal8Bit()); 875 859 HSTR rmfSharedMem = 876 DrgAddStrHandle(Q CString().sprintf("<"DRM_SHAREDMEM",%s>", drf));860 DrgAddStrHandle(QString().sprintf("<DRM_SHAREDMEM,%s>", drf).toLocal8Bit()); 877 861 878 862 MRESULT mrc; … … 880 864 881 865 DRAGTRANSFER *xfer = NULL; 882 Q CStringsrcFileName;866 QByteArray srcFileName; 883 867 884 868 QByteArray allData, itemData; … … 897 881 // determine the mechanism to use (prefer DRM_SHAREDMEM) 898 882 899 if (DrgVerifyRMF(item, DRM_SHAREDMEM, drf) &&900 DrgVerifyRMF(item, DRM_SHAREDMEM, DRF_POINTERDATA))883 if (DrgVerifyRMF(item, "DRM_SHAREDMEM", drf) && 884 DrgVerifyRMF(item, "DRM_SHAREDMEM", "DRF_POINTERDATA")) 901 885 drm = SharedMem; 902 if (DrgVerifyRMF(item, DRM_OS2FILE, drf)) {886 if (DrgVerifyRMF(item, "DRM_OS2FILE", drf)) { 903 887 srcFileName = querySourceNameFull(item); 904 888 // If the source provides the full file name, we prefer DRM_OS2FILE … … 950 934 951 935 mrc = (MRESULT)TRUE; 952 if ((item->fsControl & DC_PREPARE) | 953 936 if ((item->fsControl & DC_PREPARE) || 937 (item->fsControl & DC_PREPAREITEM)) { 954 938 DEBUG(("DefaultDropWorker: Sending DM_RENDERPREPARE to 0x%08lX...", 955 939 info()->hwndSource)); … … 957 941 MPFROMP (xfer), 0); 958 942 DEBUG(("DefaultDropWorker: Finisned sending DM_RENDERPREPARE\n" 959 " mrc %p xfer->fsReply 0x%08hX", mrc, xfer->fsReply) ;943 " mrc %p xfer->fsReply 0x%08hX", mrc, xfer->fsReply)); 960 944 renderOk = (BOOL) mrc; 961 945 } … … 979 963 } else { 980 964 // synchronously wait for DM_RENDERCOMPLETE 981 d->waiting_DM_RENDERCOMPLETE = qApp->loopLevel() + 1;982 965 DEBUG(() << "DefaultDropWorker: Waiting for DM_RENDERCOMPLETE..."); 983 int level = qApp->eventLoop()->enterLoop();966 int result = d->eventLoop.exec(); 984 967 DEBUG(("DefaultDropWorker: Finished waiting for " 985 "DM_RENDERCOMPLETE ( %d)\n"968 "DM_RENDERCOMPLETE (result %d)\n" 986 969 " got_DM_RENDERCOMPLETE %d usFS 0x%hX", 987 level, d->got_DM_RENDERCOMPLETE, d->flags_DM_RENDERCOMPLETE));988 Q_UNUSED( level);970 result, d->got_DM_RENDERCOMPLETE, d->flags_DM_RENDERCOMPLETE)); 971 Q_UNUSED(result); 989 972 // JFTR: at this point, cleanup() might have been called, 990 973 // as a result of either program exit or getting another … … 992 975 // DM_RENDERCOMPLETE from the source. Use data members with 993 976 // care! 994 d->waiting_DM_RENDERCOMPLETE = 0;995 977 renderOk = d->got_DM_RENDERCOMPLETE && 996 978 (d->flags_DM_RENDERCOMPLETE & DMFL_RENDEROK); … … 1000 982 } 1001 983 } else { 1002 DEBUG(() << "DefaultDropWorker: Source supports < " << DRM_OS2FILE1003 << "," <<drf << "> and provides a file" << srcFileName984 DEBUG(() << "DefaultDropWorker: Source supports <DRM_OS2FILE," 985 << drf << "> and provides a file" << srcFileName 1004 986 << "for item" << item << "(no need to render)"); 1005 987 renderOk = true; … … 1010 992 DEBUG(() << "DefaultDragWorker: Will read from" << srcFileName); 1011 993 QFile file(QFile::decodeName(srcFileName)); 1012 renderOk = file.open( IO_ReadOnly);994 renderOk = file.open(QIODevice::ReadOnly); 1013 995 if (renderOk) { 1014 996 itemData = file.readAll(); 1015 renderOk = file. status() == IO_Ok;997 renderOk = file.error() == QFile::NoError; 1016 998 file.close(); 1017 999 } … … 1030 1012 DEBUG(("DefaultDropWorker: Got shared data %p size %lu " 1031 1013 "(0x%08lX) flags 0x%08lX", ptr, size, size, flags)); 1032 Q_ASSERT( flags & (PAG_COMMIT | PAG_READ | PAG_BASE) ==1014 Q_ASSERT((flags & (PAG_COMMIT | PAG_READ | PAG_BASE)) == 1033 1015 (PAG_COMMIT | PAG_READ | PAG_BASE)); 1034 renderOk = flags & (PAG_COMMIT | PAG_READ | PAG_BASE) ==1016 renderOk = (flags & (PAG_COMMIT | PAG_READ | PAG_BASE)) == 1035 1017 (PAG_COMMIT | PAG_READ | PAG_BASE); 1036 1018 #ifndef QT_NO_DEBUG … … 1046 1028 if (renderOk) { 1047 1029 itemData.resize(realSize); 1048 memcpy(itemData.data(), ptr + sizeof 1030 memcpy(itemData.data(), ptr + sizeof(ULONG), realSize); 1049 1031 } 1050 1032 } … … 1058 1040 1059 1041 if (renderOk) 1060 renderOk = provider->provide( format, i, itemData, allData);1042 renderOk = provider->provide(mimeType, i, itemData, allData); 1061 1043 1062 1044 if (needToTalk) { … … 1086 1068 1087 1069 if (renderOk) 1088 data= allData;1089 1090 return data;1070 ret = allData; 1071 1072 return ret; 1091 1073 } 1092 1074 … … 1100 1082 return (MRESULT)FALSE; 1101 1083 1102 DEBUG( "DefaultDropWorker: Got DM_RENDERCOMPLETE");1084 DEBUG(("DefaultDropWorker: Got DM_RENDERCOMPLETE")); 1103 1085 d->got_DM_RENDERCOMPLETE = true; 1104 1086 d->flags_DM_RENDERCOMPLETE = SHORT1FROMMP(mp2); … … 1117 1099 1118 1100 // stop synchronous waiting for DM_RENDERCOMPLETE 1119 if (d-> waiting_DM_RENDERCOMPLETE != 0)1120 qApp->eventLoop()->exitLoop();1101 if (d->eventLoop.isRunning()) 1102 d->eventLoop.exit(); 1121 1103 return (MRESULT)FALSE; 1122 1104 } … … 1128 1110 } 1129 1111 1130 bool QPMMime::DefaultDropWorker::addProvider(const char *format,1112 bool QPMMime::DefaultDropWorker::addProvider(const QString &mimeType, 1131 1113 Provider *provider) 1132 1114 { 1133 Q_ASSERT( format&& provider);1134 if ( format&& provider && !d->exclusive) {1115 Q_ASSERT(!mimeType.isEmpty() && provider); 1116 if (!mimeType.isEmpty() && provider && !d->exclusive) { 1135 1117 // ensure there are no dups (several providers for the same mime) 1136 if (!d->providerFor( format))1137 d->providers. insert(Data::MimeProvider(format, provider));1118 if (!d->providerFor(mimeType)) 1119 d->providers.append(Data::MimeProvider(mimeType, provider)); 1138 1120 return true; 1139 1121 } … … 1141 1123 } 1142 1124 1143 bool QPMMime::DefaultDropWorker::addExclusiveProvider(const char *format,1125 bool QPMMime::DefaultDropWorker::addExclusiveProvider(const QString &mimeType, 1144 1126 Provider *provider) 1145 1127 { 1146 Q_ASSERT( format&& provider);1147 if ( format&& provider && !d->exclusive) {1128 Q_ASSERT(!mimeType.isEmpty() && provider); 1129 if (!mimeType.isEmpty() && provider && !d->exclusive) { 1148 1130 d->exclusive = true; 1149 1131 d->providers.clear(); 1150 d->providers. insert(Data::MimeProvider(format, provider));1132 d->providers.append(Data::MimeProvider(mimeType, provider)); 1151 1133 return true; 1152 1134 } … … 1157 1139 bool QPMMime::DefaultDropWorker::canRender(DRAGITEM *item, const char *drf) 1158 1140 { 1159 return DrgVerifyRMF(item, DRM_OS2FILE, drf) || 1160 (DrgVerifyRMF(item, DRM_SHAREDMEM, drf) && 1161 DrgVerifyRMF(item, DRM_SHAREDMEM, DRF_POINTERDATA)); 1162 } 1163 1141 return DrgVerifyRMF(item, "DRM_OS2FILE", drf) || 1142 (DrgVerifyRMF(item, "DRM_SHAREDMEM", drf) && 1143 DrgVerifyRMF(item, "DRM_SHAREDMEM", "DRF_POINTERDATA")); 1144 } 1145 1146 /*! \internal 1147 1148 Parses the rendering mechanism/format specification of the given \a item 1149 and stores only those mechanism branches in the given \a list that represent 1150 mechanisms supported by this worker. Returns false if fails to parse the 1151 RMF specification. Note that if no supported mechanisms are found, true is 1152 returned but the \a list will simply contain zero items. 1153 1154 \note The method clears the given \a list variable before proceeding. 1155 1156 \sa canRender(), PMMime::parseRMFs() 1157 */ 1164 1158 // static 1165 /*! \internal1166 Parses the rendering mechanism/format specification of the given \a item1167 and stores only those mechanism branches in the given \a list that represent1168 mechanisms supported by this worker. Returns false if fails to parse the1169 RMF specification. Note that if no supported mechanisms are found, true is1170 returned but the \a list will simply contain zero items.1171 \note The method clears the given \a list variable before proceeding and sets1172 auto-deletion to true.1173 \sa canRender(), PMMime::parseRMFs()1174 */1175 1159 bool QPMMime::DefaultDropWorker::getSupportedRMFs(DRAGITEM *item, 1176 Q PtrList<QStrList> &list)1160 QList<QByteArrayList> &list) 1177 1161 { 1178 1162 if (!parseRMFs(item->hstrRMF, list)) 1179 1163 return false; 1180 1164 1181 for (QStrList *mech = list.first(); mech;) { 1182 const char *drm = mech->first(); 1183 if (qstrcmp(drm, DRM_OS2FILE) == 0) { 1184 mech = list.next(); 1165 for (QList<QByteArrayList>::iterator rmf = list.begin(); rmf != list.end();) { 1166 QByteArrayList::iterator mf = rmf->begin(); 1167 Q_ASSERT(mf != rmf->end()); 1168 const char *drm = *mf; 1169 if (qstrcmp(drm, "DRM_OS2FILE") == 0) { 1170 ++rmf; 1185 1171 continue; 1186 1172 } 1187 if (qstrcmp(drm, DRM_SHAREDMEM) == 0) { 1188 const char *drf = mech->next(); 1173 if (qstrcmp(drm, "DRM_SHAREDMEM") == 0) { 1189 1174 // accept DRM_SHAREDMEM only if there is DRF_POINTERDATA 1190 for(; drf; drf = mech->next()) { 1191 if (qstrcmp(drf, DRF_POINTERDATA) == 0) 1175 for(; mf != rmf->end(); ++mf) { 1176 const char *drf = *mf; 1177 if (qstrcmp(drf, "DRF_POINTERDATA") == 0) 1192 1178 break; 1193 1179 } 1194 if ( drf) {1195 mech = list.next();1180 if (mf != rmf->end()) { 1181 ++rmf; 1196 1182 continue; 1197 1183 } 1198 1184 } 1199 1185 // remove the unsupported mechanism branch from the list 1200 bool wasLast = list.getLast() == mech; 1201 list.removeRef(mech); 1202 // after deleting the last item, the current one will be set to the new 1203 // last item which was already analyzed earlier, so set to 0 to stop 1204 mech = wasLast ? 0 : list.current(); 1186 rmf = list.erase(rmf); 1205 1187 } 1206 1188 … … 1518 1500 } 1519 1501 1502 #if !defined(QT_NO_DRAGANDDROP) 1503 1504 /*! 1505 Returns a string represented by \a hstr. 1506 */ 1507 // static 1508 QByteArray QPMMime::queryHSTR(HSTR hstr) 1509 { 1510 QByteArray str; 1511 ULONG len = DrgQueryStrNameLen(hstr); 1512 if (len) { 1513 str.resize(len); 1514 DrgQueryStrName(hstr, str.size() + 1 /* \0 */, str.data()); 1515 } 1516 return str; 1517 } 1518 1519 /*! 1520 Returns a string that is a concatenation of \c hstrContainerName and 1521 \c hstrSourceName fileds of the given \a item structure. 1522 */ 1523 // static 1524 QByteArray QPMMime::querySourceNameFull(DRAGITEM *item) 1525 { 1526 QByteArray fullName; 1527 if (!item) 1528 return fullName; 1529 1530 ULONG pathLen = DrgQueryStrNameLen(item->hstrContainerName); 1531 ULONG nameLen = DrgQueryStrNameLen(item->hstrSourceName); 1532 if (!pathLen || !nameLen) 1533 return fullName; 1534 1535 fullName.resize(pathLen + nameLen); 1536 DrgQueryStrName(item->hstrContainerName, pathLen + 1, fullName.data()); 1537 DrgQueryStrName(item->hstrSourceName, nameLen + 1, fullName.data() + pathLen); 1538 1539 return fullName; 1540 } 1541 1542 /*! \internal 1543 1544 Checks that the given drag \a item supports the DRM_OS2FILE rendering 1545 mechanism and can be rendered by a target w/o involving the source (i.e., 1546 DRM_OS2FILE is the first supported format and a valid file name with full 1547 path is provided). If the function returns TRUE, \a fullName (if not NULL) 1548 will be assigned the item's full source file name (composed from 1549 \c hstrContainerName and \c hstrSourceName fields). 1550 */ 1551 // static 1552 bool QPMMime::canTargetRenderAsOS2File(DRAGITEM *item, QByteArray *fullName /*= 0*/) 1553 { 1554 if ( !item ) 1555 return false; 1556 1557 if (item->fsControl & (DC_PREPARE | DC_PREPAREITEM)) 1558 return false; 1559 1560 { 1561 // DrgVerifyNativeRMF doesn't work on my system (ECS 1.2.1 GA): 1562 // it always returns FALSE regardless of arguments. Use simplified 1563 // hstrRMF parsing to determine whether DRM_OS2FILE is the native 1564 // mechanism or not (i.e. "^\s*[\(<]\s*DRM_OS2FILE\s*,.*"). 1565 1566 QByteArray rmf = queryHSTR(item->hstrRMF); 1567 bool ok = false; 1568 int i = rmf.indexOf("DRM_OS2FILE"); 1569 if (i >= 1) { 1570 for (int j = i - 1; j >= 0; --j) { 1571 char ch = rmf[j]; 1572 if (ch == ' ') 1573 continue; 1574 if (ch == '<' || ch == '(') { 1575 if (ok) 1576 return false; 1577 ok = true; 1578 } else { 1579 return false; 1580 } 1581 } 1582 } 1583 if (ok) { 1584 ok = false; 1585 int drmLen = strlen("DRM_OS2FILE"); 1586 for (int j = i + drmLen; j < (int) rmf.size(); ++j) { 1587 char ch = rmf[j]; 1588 if (ch == ' ') 1589 continue; 1590 if (ch == ',') { 1591 ok = true; 1592 break; 1593 } 1594 return false; 1595 } 1596 } 1597 if (!ok) 1598 return false; 1599 } 1600 1601 QByteArray srcFullName = querySourceNameFull(item); 1602 if (srcFullName.isEmpty()) 1603 return false; 1604 1605 QByteArray srcFullName2(srcFullName.size(), '\0'); 1606 APIRET rc = DosQueryPathInfo(srcFullName, FIL_QUERYFULLNAME, 1607 srcFullName2.data(), srcFullName2.size()); 1608 if (rc != 0) 1609 return false; 1610 1611 QString s1 = QFile::decodeName(srcFullName); 1612 QString s2 = QFile::decodeName(srcFullName2); 1613 1614 if (s1.compare(s2, Qt::CaseInsensitive) != 0) 1615 return false; 1616 1617 if (fullName) 1618 *fullName = srcFullName; 1619 return true; 1620 } 1621 1622 /*! \internal 1623 1624 Parses the given \a rmfs list (full rendering mechanism/format specification) 1625 and builds a \a list of mechanism branches. Each mechanism branch is also a 1626 list, where the first item is the mechahism name and all subsequent items are 1627 formats supported by this mechanism. Returns false if fails to parse \a rmf. 1628 1629 \note The method clears the given \a list variable before proceeding. 1630 */ 1631 // static 1632 bool QPMMime::parseRMFs(HSTR rmfs, QList<QByteArrayList> &list) 1633 { 1634 // The format of the RMF list is "elem {,elem,elem...}" 1635 // where elem is "(mechanism{,mechanism...}) x (format{,format...})" 1636 // or "<mechanism,format>". 1637 // We use a simple FSM to parse it. In terms of FSM, the format is: 1638 // 1639 // STRT ( BCM m CMCH echanism CMCH , NCM m CMCH echanism CMCH ) ECM x 1640 // SCMF ( BCF f CFCH ormat CFCH , NCF f CFCH ormat CFCH ) ECF , STRT 1641 // STRT < BP m PMCH echanism PMCH , SPMF f PFCH ormat PFCH > EP , STRT 1642 1643 QByteArray str = queryHSTR(rmfs); 1644 uint len = str.length(); 1645 1646 enum { 1647 // states 1648 STRT = 0, BCM, CMCH, NCM, ECM, SCMF, BCF, CFCH, NCF, ECF, 1649 BP, PMCH, SPMF, PFCH, EP, 1650 STATES_COUNT, 1651 // pseudo states 1652 Err, Skip, 1653 // inputs 1654 obr = 0, cbr, xx, lt, gt, cm, any, ws, 1655 INPUTS_COUNT, 1656 }; 1657 1658 static const char Chars[] = { '(', ')', 'x', 'X', '<', '>', ',', ' ', 0 }; 1659 static const char Inputs[] = { obr, cbr, xx, xx, lt, gt, cm, ws }; 1660 static const uchar Fsm [STATES_COUNT] [INPUTS_COUNT] = { 1661 /* 0 obr 1 cbr 2 xx 3 lt 4 gt 5 cm 6 any 7 ws */ 1662 /* STRT 0 */ { BCM, Err, Err, BP, Err, Err, Err, Skip }, 1663 /* BCM 1 */ { Err, Err, Err, Err, Err, Err, CMCH, Skip }, 1664 /* CMCH 2 */ { Err, ECM, CMCH, Err, Err, NCM, CMCH, CMCH }, 1665 /* NCM 3 */ { Err, Err, Err, Err, Err, Err, CMCH, Skip }, 1666 /* ECM 4 */ { Err, Err, SCMF, Err, Err, Err, Err, Skip }, 1667 /* SCMF 5 */ { BCF, Err, Err, Err, Err, Err, Err, Skip }, 1668 /* BCF 6 */ { Err, Err, Err, Err, Err, Err, CFCH, Skip }, 1669 /* CFCH 7 */ { Err, ECF, CFCH, Err, Err, NCF, CFCH, CFCH }, 1670 /* NCF 8 */ { Err, Err, Err, Err, Err, Err, CFCH, Skip }, 1671 /* ECF 9 */ { Err, Err, Err, Err, Err, STRT, Err, Skip }, 1672 /* BP 10 */ { Err, Err, Err, Err, Err, Err, PMCH, Skip }, 1673 /* PMCH 11 */ { Err, Err, PMCH, Err, Err, SPMF, PMCH, PMCH }, 1674 /* SPMF 12 */ { Err, Err, Err, Err, Err, Err, PFCH, Skip }, 1675 /* PFCH 13 */ { Err, Err, PFCH, Err, EP, Err, PFCH, PFCH }, 1676 /* EP 14 */ { Err, Err, Err, Err, Err, STRT, Err, Skip } 1677 }; 1678 1679 list.clear(); 1680 1681 QList<QByteArrayList*> refList; 1682 1683 QByteArray buf; 1684 QList<QByteArrayList>::iterator rmf; 1685 1686 uint state = STRT; 1687 uint start = 0, end = 0, space = 0; 1688 1689 for (uint i = 0; i < len && state != Err ; ++i) { 1690 char ch = str[i]; 1691 char *p = strchr(Chars, ch); 1692 uint input = p ? Inputs[p - Chars] : any; 1693 uint newState = Fsm[state][input]; 1694 switch (newState) { 1695 case Skip: 1696 continue; 1697 case CMCH: 1698 case CFCH: 1699 case PMCH: 1700 case PFCH: 1701 if (state != newState) 1702 start = end = i; 1703 ++end; 1704 // accumulate trailing space for truncation 1705 if (input == ws) ++space; 1706 else space = 0; 1707 break; 1708 case NCM: 1709 case ECM: 1710 case SPMF: 1711 buf = QByteArray(str.data() + start, end - start - space); 1712 // find the mechanism branch in the output list 1713 for (rmf = list.begin(); rmf != list.end(); ++rmf) { 1714 if (rmf->first() == buf) 1715 break; 1716 } 1717 if (rmf == list.end()) { 1718 // append to the output list if not found 1719 QByteArrayList newRmf; 1720 newRmf.append(buf); 1721 rmf = list.insert(list.end(), newRmf); 1722 } 1723 // store a refecence in the helper list for making a cross product 1724 refList.append(&*rmf); 1725 start = end = 0; 1726 break; 1727 case NCF: 1728 case ECF: 1729 case EP: 1730 buf = QByteArray(str.data() + start, end - start - space); 1731 // make a cross product with all current mechanisms 1732 foreach(QByteArrayList *rmfRef, refList) 1733 rmfRef->append(buf); 1734 if (newState != NCF) 1735 refList.clear(); 1736 start = end = 0; 1737 break; 1738 default: 1739 break; 1740 } 1741 state = newState; 1742 } 1743 1744 return state == ECF || state == EP; 1745 } 1746 1747 /*! \internal 1748 1749 Splits the given \a rmf (rendering mechanism/format pair) to a \a mechanism 1750 and a \a format string. Returns FALSE if fails to parse \a rmf. 1751 */ 1752 // static 1753 bool QPMMime::parseRMF(HSTR rmf, QByteArray &mechanism, QByteArray &format) 1754 { 1755 QList<QByteArrayList> list; 1756 if (!parseRMFs(rmf, list)) 1757 return false; 1758 1759 if (list.count() != 1 || list.first().count() != 2) 1760 return false; 1761 1762 QByteArrayList first = list.first(); 1763 mechanism = first.at(0); 1764 format = first.at(1); 1765 1766 return true; 1767 } 1768 1769 /*! \internal */ 1770 // static 1771 QPMMime::DefaultDragWorker *QPMMime::defaultCoopDragWorker() 1772 { 1773 static DefaultDragWorker defCoopDragWorker(false /* exclusive */); 1774 return &defCoopDragWorker; 1775 } 1776 1777 // static 1778 /*! \internal */ 1779 QPMMime::DefaultDragWorker *QPMMime::defaultExclDragWorker() 1780 { 1781 static DefaultDragWorker defExclDragWorker(false /* exclusive */); 1782 return &defExclDragWorker; 1783 } 1784 1785 /*! \internal */ 1786 // static 1787 QPMMime::DefaultDropWorker *QPMMime::defaultDropWorker() 1788 { 1789 static DefaultDropWorker defaultDropWorker; 1790 return &defaultDropWorker; 1791 } 1792 1793 #endif // !QT_NO_DRAGANDDROP 1794 1520 1795 //////////////////////////////////////////////////////////////////////////////// 1521 1796
Note:
See TracChangeset
for help on using the changeset viewer.