Changeset 332 for trunk/src


Ignore:
Timestamp:
Nov 20, 2009, 2:53:36 AM (16 years ago)
Author:
Dmitry A. Kuminov
Message:

gui/kernel: mime: Implemented mime->clipboard interface for "text/plain" (only putting to the system clipboard so far).

Location:
trunk/src/gui/kernel
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/gui/kernel/qmime.h

    r326 r332  
    134134
    135135    static ULONG registerMimeType(const QString &mime);
     136
     137    static ULONG allocateMemory(size_t size);
     138    static void freeMemory(ULONG addr);
    136139
    137140private:
  • trunk/src/gui/kernel/qmime_pm.cpp

    r324 r332  
    136136/*!
    137137    Registers the MIME type \a mime, and returns an ID number
    138     identifying the format on OS/2.
    139 */
     138    identifying the format on OS/2. Intended to be used by QPMMime
     139    implementations for registering custom clipboard formats they use.
     140*/
     141// static
    140142ULONG QPMMime::registerMimeType(const QString &mime)
    141143{
    142     QString atom = QLatin1String("mime:") + mime;
    143 
    144     ULONG cf = WinAddAtom(WinQuerySystemAtomTable(), atom.toLocal8Bit());
     144    ULONG cf = WinAddAtom(WinQuerySystemAtomTable(), mime.toLocal8Bit());
    145145    if (!cf) {
    146146#ifndef QT_NO_DEBUG
     
    155155
    156156/*!
     157    Allocates a block of shared memory of the given size and returns the address
     158    of this block. This memory block may be then filled with data and returned
     159    by convertFromMimeData() as the value of the CFI_POINTER type.
     160*/
     161// static
     162ULONG QPMMime::allocateMemory(size_t size)
     163{
     164    if (size == 0)
     165        return 0;
     166
     167    ULONG data = 0;
     168
     169    // allocate giveable memory for the array + dword for its size
     170    APIRET arc = DosAllocSharedMem((PVOID *)&data, NULL, size + 4,
     171                                   PAG_WRITE  | PAG_COMMIT | OBJ_GIVEABLE);
     172    if (arc != NO_ERROR) {
     173#ifndef QT_NO_DEBUG
     174        qWarning("QPMMime::allocateMemory: DosAllocSharedMem failed with %lu", arc);
     175#endif
     176        return 0;
     177    }
     178    // get the size rounded to the page boundary (4K)
     179    ULONG sz = ~0, flags = 0;
     180    arc = DosQueryMem((PVOID)(data + size - 1), &sz, &flags);
     181    if (arc != NO_ERROR) {
     182#ifndef QT_NO_DEBUG
     183        qWarning("QPMMime::allocateMemory: DosQueryMem failed with %lu", arc);
     184#endif
     185        DosFreeMem((PVOID)data);
     186        return 0;
     187    }
     188    sz += (size - 1);
     189    // store the exact size to the last dword of the last page
     190    *(((ULONG *)(data + sz)) - 1) = size;
     191
     192    return data;
     193}
     194
     195/*!
     196    Frees memory allocated by allocateMemory(). Normally, not used because the
     197    CFI_POINTER memory blocks are owned by the system after
     198    convertFromMimeData() returns.
     199*/
     200// static
     201void QPMMime::freeMemory(ULONG addr)
     202{
     203    DosFreeMem((PVOID)addr);
     204}
     205
     206/*!
    157207    \fn QList<ULONG> QPMMime::formatsForMimeData(const QMimeData *mimeData) const
    158208
     
    180230    \table
    181231    \row \o \c CFI_POINTER        \o \a data is a pointer to a block of memory
    182                                       allocated with QPMMime::allocMem()
     232                                      allocated with QPMMime::allocateMemory()
    183233    \row \o \c CFI_HANDLE         \o \a data is a handle to the appropriate
    184234                                      PM resource
     
    285335////////////////////////////////////////////////////////////////////////////////
    286336
     337class QPMMimeText : public QPMMime
     338{
     339public:
     340    QPMMimeText();
     341
     342    QList<ULONG> formatsForMimeData(const QMimeData *mimeData) const;
     343    bool convertFromMimeData(const QMimeData *mimeData, ULONG format,
     344                             ULONG &flags, ULONG *data) const;
     345
     346    QStringList mimesForFormats(const QList<ULONG> &formats) const;
     347    QVariant convertFromFormat(ULONG format, ULONG flags, ULONG data,
     348                               const QString &mimeType,
     349                               QVariant::Type preferredType) const;
     350
     351    const ULONG CF_TextUnicode;
     352};
     353
     354QPMMimeText::QPMMimeText()
     355    // "text/unicode" is what Mozilla uses to for unicode, so Qt apps will
     356    // be able to interchange unicode text with Mozilla apps
     357    : CF_TextUnicode (registerMimeType(QLatin1String("text/unicode")))
     358{
     359}
     360
     361QList<ULONG> QPMMimeText::formatsForMimeData(const QMimeData *mimeData) const
     362{
     363    QList<ULONG> cfs;
     364    if (mimeData->hasText())
     365        cfs << CF_TEXT << CF_TextUnicode;
     366    return cfs;
     367}
     368
     369// text/plain is defined as using CRLF, but so many programs don't,
     370// and programmers just look for '\n' in strings.
     371// OS/2 really needs CRLF, so we ensure it here.
     372bool QPMMimeText::convertFromMimeData(const QMimeData *mimeData, ULONG format,
     373                                      ULONG &flags, ULONG *data) const
     374{
     375    if (!mimeData->hasText())
     376        return false;
     377
     378    flags = CFI_POINTER;
     379
     380    if (data == NULL)
     381        return true; // delayed rendering, nothing to do
     382
     383    QByteArray r;
     384
     385    if (format == CF_TEXT) {
     386        QByteArray str = mimeData->text().toLocal8Bit();
     387        // Anticipate required space for CRLFs at 1/40
     388        int maxsize = str.size()+str.size()/40+3;
     389        r.fill('\0', maxsize);
     390        char* o = r.data();
     391        const char* d = str.data();
     392        const int s = str.size();
     393        bool cr = false;
     394        int j = 0;
     395        for (int i = 0; i < s; i++) {
     396            char c = d[i];
     397            if (c == '\r')
     398                cr = true;
     399            else {
     400                if (c == '\n') {
     401                    if (!cr)
     402                        o[j++] = '\r';
     403                }
     404                cr = false;
     405            }
     406            o[j++] = c;
     407            if (j+3 >= maxsize) {
     408                maxsize += maxsize/4;
     409                r.resize(maxsize);
     410                o = r.data();
     411            }
     412        }
     413        o[j] = 0;
     414    } else if (format == CF_TextUnicode) {
     415        QString str = mimeData->text();
     416        const QChar *u = str.unicode();
     417        QString res;
     418        const int s = str.length();
     419        int maxsize = s + s/40 + 3;
     420        res.resize(maxsize);
     421        int ri = 0;
     422        bool cr = false;
     423        for (int i = 0; i < s; ++i) {
     424            if (*u == QLatin1Char('\r'))
     425                cr = true;
     426            else {
     427                if (*u == QLatin1Char('\n') && !cr)
     428                    res[ri++] = QLatin1Char('\r');
     429                cr = false;
     430            }
     431            res[ri++] = *u;
     432            if (ri+3 >= maxsize) {
     433                maxsize += maxsize/4;
     434                res.resize(maxsize);
     435            }
     436            ++u;
     437        }
     438        res.truncate(ri);
     439        const int byteLength = res.length()*2;
     440        r.fill('\0', byteLength + 2);
     441        memcpy(r.data(), res.unicode(), byteLength);
     442        r[byteLength] = 0;
     443        r[byteLength+1] = 0;
     444    } else{
     445        return false;
     446    }
     447
     448    *data = QPMMime::allocateMemory(r.size());
     449    if (!*data)
     450        return false;
     451
     452    memcpy((void *)*data, r.data(), r.size());
     453    return true;
     454}
     455
     456QStringList QPMMimeText::mimesForFormats(const QList<ULONG> &formats) const
     457{
     458    QStringList mimes;
     459    foreach(ULONG cf, formats) {
     460        if (cf == CF_TEXT || cf == CF_TextUnicode){
     461            mimes << QLatin1String("text/plain");
     462            break;
     463        }
     464    }
     465    return mimes;
     466}
     467
     468QVariant QPMMimeText::convertFromFormat(ULONG format, ULONG flags, ULONG data,
     469                                        const QString &mimeType,
     470                                        QVariant::Type preferredType) const
     471{
     472    return QVariant();
     473}
     474
    287475////////////////////////////////////////////////////////////////////////////////
    288476
     
    303491    if (!initialized) {
    304492        initialized = true;
    305         // @todo new QPMMimeXXX;
     493        new QPMMimeText;
    306494    }
    307495}
Note: See TracChangeset for help on using the changeset viewer.