filters

msod.cc

00001 /*
00002     Copyright (C) 2000, S.R.Haque <shaheedhaque@hotmail.com>.
00003     This file is part of the KDE project
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License as published by the Free Software Foundation; either
00008     version 2 of the License, or (at your option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014 
00015     You should have received a copy of the GNU Library General Public License
00016     along with this library; see the file COPYING.LIB.  If not, write to
00017     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019 
00020 DESCRIPTION
00021 */
00022 
00023 #include <kdebug.h>
00024 #include <qdatastream.h>
00025 #include <qfile.h>
00026 #include <qptrlist.h>
00027 #include <qpointarray.h>
00028 #include <qrect.h>
00029 #include <qsize.h>
00030 #include <msod.h>
00031 #include <zlib.h>
00032 
00033 const int Msod::s_area = 30505;
00034 
00035 Msod::Msod(
00036     unsigned dpi) :
00037         KWmf(dpi)
00038 {
00039     m_dpi = dpi;
00040     m_images.setAutoDelete(true);
00041     m_opt = new Options(*this);
00042     m_shape.data = 0L;
00043     m_shape.length = 0;
00044 }
00045 
00046 Msod::~Msod()
00047 {
00048     delete [] m_shape.data;
00049     delete m_opt;
00050 }
00051 
00052 void Msod::drawShape(
00053     unsigned shapeType,
00054     Q_UINT32 bytes,
00055     QDataStream &operands)
00056 {
00057     static const char *funcTab[] =
00058     {
00059         "UNKNOWN",                  // Unknown
00060         "RECTANGLE",                // Rectangle
00061         "ROUNDRECTANGLE",           // Roundrectangle
00062         "ELLIPSE",                  // Ellipse
00063         "DIAMOND",                  // Diamond
00064         "ISOCELESTRIANGLE",         // Isocelestriangle
00065         "RIGHTTRIANGLE",            // Righttriangle
00066         "PARALLELOGRAM",            // Parallelogram
00067         "TRAPEZOID",                // Trapezoid
00068         "HEXAGON",                  // Hexagon
00069         "OCTAGON",                  // Octagon
00070         "PLUS",                     // Plus
00071         "STAR",                     // Star
00072         "ARROW",                    // Arrow
00073         "THICKARROW",               // Thickarrow
00074         "HOMEPLATE",                // Homeplate
00075         "CUBE",                     // Cube
00076         "BALLOON",                  // Balloon
00077         "SEAL",                     // Seal
00078         "ARC",                      // Arc
00079         "LINE",                     // Line
00080         "PLAQUE",                   // Plaque
00081         "CAN",                      // Can
00082         "DONUT",                    // Donut
00083         "TEXTSIMPLE",               // Textsimple
00084         "TEXTOCTAGON",              // Textoctagon
00085         "TEXTHEXAGON",              // Texthexagon
00086         "TEXTCURVE",                // Textcurve
00087         "TEXTWAVE",                 // Textwave
00088         "TEXTRING",                 // Textring
00089         "TEXTONCURVE",              // Textoncurve
00090         "TEXTONRING",               // Textonring
00091         "STRAIGHTCONNECTOR1",       // Straightconnector1
00092         "BENTCONNECTOR2",           // Bentconnector2
00093         "BENTCONNECTOR3",           // Bentconnector3
00094         "BENTCONNECTOR4",           // Bentconnector4
00095         "BENTCONNECTOR5",           // Bentconnector5
00096         "CURVEDCONNECTOR2",         // Curvedconnector2
00097         "CURVEDCONNECTOR3",         // Curvedconnector3
00098         "CURVEDCONNECTOR4",         // Curvedconnector4
00099         "CURVEDCONNECTOR5",         // Curvedconnector5
00100         "CALLOUT1",                 // Callout1
00101         "CALLOUT2",                 // Callout2
00102         "CALLOUT3",                 // Callout3
00103         "ACCENTCALLOUT1",           // Accentcallout1
00104         "ACCENTCALLOUT2",           // Accentcallout2
00105         "ACCENTCALLOUT3",           // Accentcallout3
00106         "BORDERCALLOUT1",           // bordercallout1
00107         "BORDERCALLOUT2",           // Bordercallout2
00108         "BORDERCALLOUT3",           // Bordercallout3
00109         "ACCENTBORDERCALLOUT1",     // Accentbordercallout1
00110         "ACCENTBORDERCALLOUT2",     // Accentbordercallout2
00111         "ACCENTBORDERCALLOUT3",     // Accentbordercallout3
00112         "RIBBON",                   // Ribbon
00113         "RIBBON2",                  // Ribbon2
00114         "CHEVRON",                  // Chevron
00115         "PENTAGON",                 // Pentagon
00116         "NOSMOKING",                // Nosmoking
00117         "SEAL8",                    // Seal8
00118         "SEAL16",                   // Seal16
00119         "SEAL32",                   // Seal32
00120         "WEDGERECTCALLOUT",         // Wedgerectcallout
00121         "WEDGERRECTCALLOUT",        // Wedgerrectcallout
00122         "WEDGEELLIPSECALLOUT",      // Wedgeellipsecallout
00123         "WAVE",                     // Wave
00124         "FOLDEDCORNER",             // Foldedcorner
00125         "LEFTARROW",                // Leftarrow
00126         "DOWNARROW",                // Downarrow
00127         "UPARROW",                  // Uparrow
00128         "LEFTRIGHTARROW",           // Leftrightarrow
00129         "UPDOWNARROW",              // Updownarrow
00130         "IRREGULARSEAL1",           // Irregularseal1
00131         "IRREGULARSEAL2",           // Irregularseal2
00132         "LIGHTNINGBOLT",            // Lightningbolt
00133         "HEART",                    // Heart
00134         "PICTUREFRAME",             // PictureFrame
00135         "QUADARROW",                // Quadarrow
00136         "LEFTARROWCALLOUT",         // Leftarrowcallout
00137         "RIGHTARROWCALLOUT",        // Rightarrowcallout
00138         "UPARROWCALLOUT",           // Uparrowcallout
00139         "DOWNARROWCALLOUT",         // Downarrowcallout
00140         "LEFTRIGHTARROWCALLOUT",    // Leftrightarrowcallout
00141         "UPDOWNARROWCALLOUT",       // Updownarrowcallout
00142         "QUADARROWCALLOUT",         // Quadarrowcallout
00143         "BEVEL",                    // Bevel
00144         "LEFTBRACKET",              // Leftbracket
00145         "RIGHTBRACKET",             // Rightbracket
00146         "LEFTBRACE",                // Leftbrace
00147         "RIGHTBRACE",               // Rightbrace
00148         "LEFTUPARROW",              // Leftuparrow
00149         "BENTUPARROW",              // Bentuparrow
00150         "BENTARROW",                // Bentarrow
00151         "SEAL24",                   // Seal24
00152         "STRIPEDRIGHTARROW",        // Stripedrightarrow
00153         "NOTCHEDRIGHTARROW",        // Notchedrightarrow
00154         "BLOCKARC",                 // Blockarc
00155         "SMILEYFACE",               // Smileyface
00156         "VERTICALSCROLL",           // Verticalscroll
00157         "HORIZONTALSCROLL",         // Horizontalscroll
00158         "CIRCULARARROW",            // Circulararrow
00159         "NOTCHEDCIRCULARARROW",     // Notchedcirculararrow
00160         "UTURNARROW",               // Uturnarrow
00161         "CURVEDRIGHTARROW",         // Curvedrightarrow
00162         "CURVEDLEFTARROW",          // Curvedleftarrow
00163         "CURVEDUPARROW",            // Curveduparrow
00164         "CURVEDDOWNARROW",          // Curveddownarrow
00165         "CLOUDCALLOUT",             // Cloudcallout
00166         "ELLIPSERIBBON",            // Ellipseribbon
00167         "ELLIPSERIBBON2",           // Ellipseribbon2
00168         "FLOWCHARTPROCESS",         // Flowchartprocess
00169         "FLOWCHARTDECISION",        // Flowchartdecision
00170         "FLOWCHARTINPUTOUTPUT",     // Flowchartinputoutput
00171         "FLOWCHARTPREDEFINEDPROCESS",   // Flowchartpredefinedprocess
00172         "FLOWCHARTINTERNALSTORAGE",   // Flowchartinternalstorage
00173         "FLOWCHARTDOCUMENT",        // Flowchartdocument
00174         "FLOWCHARTMULTIDOCUMENT",   // Flowchartmultidocument
00175         "FLOWCHARTTERMINATOR",      // Flowchartterminator
00176         "FLOWCHARTPREPARATION",     // Flowchartpreparation
00177         "FLOWCHARTMANUALINPUT",     // Flowchartmanualinput
00178         "FLOWCHARTMANUALOPERATION",   // Flowchartmanualoperation
00179         "FLOWCHARTCONNECTOR",       // Flowchartconnector
00180         "FLOWCHARTPUNCHEDCARD",     // Flowchartpunchedcard
00181         "FLOWCHARTPUNCHEDTAPE",     // Flowchartpunchedtape
00182         "FLOWCHARTSUMMINGJUNCTION",   // Flowchartsummingjunction
00183         "FLOWCHARTOR",              // Flowchartor
00184         "FLOWCHARTCOLLATE",         // Flowchartcollate
00185         "FLOWCHARTSORT",            // Flowchartsort
00186         "FLOWCHARTEXTRACT",         // Flowchartextract
00187         "FLOWCHARTMERGE",           // Flowchartmerge
00188         "FLOWCHARTOFFLINESTORAGE",   // Flowchartofflinestorage
00189         "FLOWCHARTONLINESTORAGE",   // Flowchartonlinestorage
00190         "FLOWCHARTMAGNETICTAPE",    // Flowchartmagnetictape
00191         "FLOWCHARTMAGNETICDISK",    // Flowchartmagneticdisk
00192         "FLOWCHARTMAGNETICDRUM",    // Flowchartmagneticdrum
00193         "FLOWCHARTDISPLAY",         // Flowchartdisplay
00194         "FLOWCHARTDELAY",           // Flowchartdelay
00195         "TEXTPLAINTEXT",            // Textplaintext
00196         "TEXTSTOP",                 // Textstop
00197         "TEXTTRIANGLE",             // Texttriangle
00198         "TEXTTRIANGLEINVERTED",     // Texttriangleinverted
00199         "TEXTCHEVRON",              // Textchevron
00200         "TEXTCHEVRONINVERTED",      // Textchevroninverted
00201         "TEXTRINGINSIDE",           // Textringinside
00202         "TEXTRINGOUTSIDE",          // Textringoutside
00203         "TEXTARCHUPCURVE",          // Textarchupcurve
00204         "TEXTARCHDOWNCURVE",        // Textarchdowncurve
00205         "TEXTCIRCLECURVE",          // Textcirclecurve
00206         "TEXTBUTTONCURVE",          // Textbuttoncurve
00207         "TEXTARCHUPPOUR",           // Textarchuppour
00208         "TEXTARCHDOWNPOUR",         // Textarchdownpour
00209         "TEXTCIRCLEPOUR",           // Textcirclepour
00210         "TEXTBUTTONPOUR",           // Textbuttonpour
00211         "TEXTCURVEUP",              // Textcurveup
00212         "TEXTCURVEDOWN",            // Textcurvedown
00213         "TEXTCASCADEUP",            // Textcascadeup
00214         "TEXTCASCADEDOWN",          // Textcascadedown
00215         "TEXTWAVE1",                // Textwave1
00216         "TEXTWAVE2",                // Textwave2
00217         "TEXTWAVE3",                // Textwave3
00218         "TEXTWAVE4",                // Textwave4
00219         "TEXTINFLATE",              // Textinflate
00220         "TEXTDEFLATE",              // Textdeflate
00221         "TEXTINFLATEBOTTOM",        // Textinflatebottom
00222         "TEXTDEFLATEBOTTOM",        // Textdeflatebottom
00223         "TEXTINFLATETOP",           // Textinflatetop
00224         "TEXTDEFLATETOP",           // Textdeflatetop
00225         "TEXTDEFLATEINFLATE",       // Textdeflateinflate
00226         "TEXTDEFLATEINFLATEDEFLATE",   // Textdeflateinflatedeflate
00227         "TEXTFADERIGHT",            // Textfaderight
00228         "TEXTFADELEFT",             // Textfadeleft
00229         "TEXTFADEUP",               // Textfadeup
00230         "TEXTFADEDOWN",             // Textfadedown
00231         "TEXTSLANTUP",              // Textslantup
00232         "TEXTSLANTDOWN",            // Textslantdown
00233         "TEXTCANUP",                // Textcanup
00234         "TEXTCANDOWN",              // Textcandown
00235         "FLOWCHARTALTERNATEPROCESS",   // Flowchartalternateprocess
00236         "FLOWCHARTOFFPAGECONNECTOR",   // Flowchartoffpageconnector
00237         "CALLOUT90",                // Callout90
00238         "ACCENTCALLOUT90",          // Accentcallout90
00239         "BORDERCALLOUT90",          // Bordercallout90
00240         "ACCENTBORDERCALLOUT90",    // Accentbordercallout90
00241         "LEFTRIGHTUPARROW",         // Leftrightuparrow
00242         "SUN",                      // Sun
00243         "MOON",                     // Moon
00244         "BRACKETPAIR",              // Bracketpair
00245         "BRACEPAIR",                // Bracepair
00246         "SEAL4",                    // Seal4
00247         "DOUBLEWAVE",               // Doublewave
00248         "ACTIONBUTTONBLANK",        // Actionbuttonblank
00249         "ACTIONBUTTONHOME",         // Actionbuttonhome
00250         "ACTIONBUTTONHELP",         // Actionbuttonhelp
00251         "ACTIONBUTTONINFORMATION",  // Actionbuttoninformation
00252         "ACTIONBUTTONFORWARDNEXT",  // Actionbuttonforwardnext
00253         "ACTIONBUTTONBACKPREVIOUS", // Actionbuttonbackprevious
00254         "ACTIONBUTTONEND",          // Actionbuttonend
00255         "ACTIONBUTTONBEGINNING",    // Actionbuttonbeginning
00256         "ACTIONBUTTONRETURN",       // Actionbuttonreturn
00257         "ACTIONBUTTONDOCUMENT",     // Actionbuttondocument
00258         "ACTIONBUTTONSOUND",        // Actionbuttonsound
00259         "ACTIONBUTTONMOVIE",        // Actionbuttonmovie
00260         "HOSTCONTROL",              // Hostcontrol
00261         "TEXTBOX",                  // Textbox
00262     };
00263     struct
00264     {
00265         Q_UINT32 spid;                  // The shape id
00266         union
00267         {
00268             Q_UINT32 info;
00269             struct
00270             {
00271                 Q_UINT32 fGroup : 1;    // This shape is a group shape
00272                 Q_UINT32 fChild : 1;    // Not a top-level shape
00273                 Q_UINT32 fPatriarch : 1; // This is the topmost group shape.
00274                                         // Exactly one of these per drawing.
00275                 Q_UINT32 fDeleted : 1;  // The shape has been deleted
00276                 Q_UINT32 fOleShape : 1; // The shape is an OLE object
00277                 Q_UINT32 fHaveMaster : 1; // Shape has a hspMaster property
00278                 Q_UINT32 fFlipH : 1;    // Shape is flipped horizontally
00279                 Q_UINT32 fFlipV : 1;    // Shape is flipped vertically
00280                 Q_UINT32 fConnector : 1; // Connector type of shape
00281                 Q_UINT32 fHaveAnchor : 1; // Shape has an anchor of some kind
00282                 Q_UINT32 fBackground : 1; // Background shape
00283                 Q_UINT32 fHaveSpt : 1;  // Shape has a shape type property
00284                 Q_UINT32 reserved : 20; // Not yet used
00285             } fields;
00286         } grfPersistent;
00287     } data;
00288 
00289     // Scan lookup table for operation.
00290 
00291     operands >> data.spid;
00292     operands >> data.grfPersistent.info;
00293     bytes -= 8;
00294     kdDebug(s_area) << "shape-id: " << data.spid << " type: " << funcTab[shapeType] << " (" << shapeType << ")" <<
00295         (data.grfPersistent.fields.fGroup ? " group" : "") <<
00296         (data.grfPersistent.fields.fChild ? " child" : "") <<
00297         (data.grfPersistent.fields.fPatriarch ? " patriarch" : "") <<
00298         (data.grfPersistent.fields.fDeleted ? " deleted" : "") <<
00299         (data.grfPersistent.fields.fOleShape ? " oleshape" : "") <<
00300         (data.grfPersistent.fields.fHaveMaster ? " master" : "") <<
00301         (data.grfPersistent.fields.fFlipH ? " flipv" : "") <<
00302         (data.grfPersistent.fields.fConnector ? " connector" : "") <<
00303         (data.grfPersistent.fields.fHaveAnchor ? " anchor" : "") <<
00304         (data.grfPersistent.fields.fBackground ? " background" : "") <<
00305         (data.grfPersistent.fields.fHaveSpt ? " spt" : "") <<
00306         " operands: " << bytes << endl;
00307     if (data.grfPersistent.fields.fDeleted)
00308         return;
00309     if ((!m_isRequiredDrawing) && (m_requestedShapeId != data.spid))
00310         return;
00311 
00312     // An active shape! Let's draw it...
00313 
00314     switch (shapeType)
00315     {
00316     case 0:
00317         if (m_opt->m_pVertices)
00318         {
00319             gotPolyline(m_dc, *m_opt->m_pVertices);
00320         }
00321         break;
00322     case 1:
00323         if (bytes > 7)
00324         {
00325             QPoint topLeft;
00326             QSize size;
00327 
00328             topLeft = normalisePoint(operands);
00329             size = normaliseSize(operands);
00330 
00331             QRect rect(topLeft, size);
00332             QPointArray points(4);
00333 
00334             points.setPoint(0, topLeft);
00335             points.setPoint(1, rect.topRight());
00336             points.setPoint(2, rect.bottomRight());
00337             points.setPoint(3, rect.bottomLeft());
00338             gotRectangle(m_dc, points);
00339         }
00340     case 20:
00341         if (bytes > 7)
00342         {
00343             QPoint lineFrom;
00344             QPoint lineTo;
00345 
00346             lineTo = normalisePoint(operands);
00347 
00348             QPointArray points(2);
00349 
00350             points.setPoint(0, lineFrom);
00351             points.setPoint(1, lineTo);
00352             gotPolyline(m_dc, points);
00353         }
00354         break;
00355     default:
00356         break;
00357     }
00358 }
00359 
00360 void Msod::invokeHandler(
00361     Header &op,
00362     Q_UINT32 bytes,
00363     QDataStream &operands)
00364 {
00365     typedef void (Msod::*method)(Header &op, Q_UINT32 bytes, QDataStream &operands);
00366 
00367     typedef struct
00368     {
00369         const char *name;
00370         Q_UINT16 opcode;
00371         method handler;
00372     } opcodeEntry;
00373 
00374     static const opcodeEntry funcTab[] =
00375     {
00376         { "ALIGNRULE",          0xF013, &Msod::opAlignrule },
00377         { "ANCHOR",             0xF00E, &Msod::opAnchor },
00378         { "ARCRULE",            0xF014, &Msod::opArcrule },
00379         { "BSE",                0xF007, &Msod::opBse },
00380         { "BSTORECONTAINER",    0xF001, &Msod::opBstorecontainer },
00381         { "CALLOUTRULE",        0xF017, &Msod::opCalloutrule },
00382         { "CHILDANCHOR",        0xF00F, &Msod::opChildanchor },
00383         { "CLIENTANCHOR",       0xF010, &Msod::opClientanchor },
00384         { "CLIENTDATA",         0xF011, &Msod::opClientdata },
00385         { "CLIENTRULE",         0xF015, &Msod::opClientrule },
00386         { "CLIENTTEXTBOX",      0xF00D, &Msod::opClienttextbox },
00387         { "CLSID",              0xF016, &Msod::opClsid },
00388         { "COLORMRU",           0xF11A, &Msod::opColormru },
00389         { "CONNECTORRULE",      0xF012, &Msod::opConnectorrule },
00390         { "DELETEDPSPL",        0xF11D, &Msod::opDeletedpspl },
00391         { "DG",                 0xF008, &Msod::opDg },
00392         { "DGCONTAINER",        0xF002, &Msod::opDgcontainer },
00393         { "DGG",                0xF006, &Msod::opDgg },
00394         { "DGGCONTAINER",       0xF000, &Msod::opDggcontainer },
00395         { "OLEOBJECT",          0xF11F, &Msod::opOleobject },
00396         { "OPT",                0xF00B, &Msod::opOpt },
00397         { "REGROUPITEMS",       0xF118, &Msod::opRegroupitems },
00398         { "SELECTION",          0xF119, &Msod::opSelection },
00399         { "SOLVERCONTAINER",    0xF005, &Msod::opSolvercontainer },
00400         { "SP",                 0xF00A, &Msod::opSp },
00401         { "SPCONTAINER",        0xF004, &Msod::opSpcontainer },
00402         { "SPGR",               0xF009, &Msod::opSpgr },
00403         { "SPGRCONTAINER",      0xF003, &Msod::opSpgrcontainer },
00404         { "SPLITMENUCOLORS",    0xF11E, &Msod::opSplitmenucolors },
00405         { "TEXTBOX",            0xF00C, &Msod::opTextbox },
00406         { NULL,                 0,      0 },
00407         { "BLIP",               0,      &Msod::opBlip }
00408     };
00409     unsigned i;
00410     method result;
00411 
00412     // Scan lookup table for operation.
00413 
00414     for (i = 0; funcTab[i].name; i++)
00415     {
00416         if (funcTab[i].opcode == op.opcode.fields.fbt)
00417         {
00418             break;
00419         }
00420     }
00421 
00422     // Invoke handler.
00423 
00424     result = funcTab[i].handler;
00425     if (!result && (op.opcode.fields.fbt >= 0xF018) && (0xF117 >= op.opcode.fields.fbt))
00426         result = funcTab[++i].handler;
00427     if (!result)
00428     {
00429         if (funcTab[i].name)
00430             kdWarning(s_area) << "invokeHandler: unsupported opcode: " <<
00431                 funcTab[i].name <<
00432                 " operands: " << bytes << endl;
00433         else
00434             kdWarning(s_area) << "invokeHandler: unsupported opcode: 0x" <<
00435                 QString::number(op.opcode.fields.fbt, 16) <<
00436                 " operands: " << bytes << endl;
00437 
00438         // Skip data we cannot use.
00439 
00440         skip(bytes, operands);
00441     }
00442     else
00443     {
00444         kdDebug(s_area) << "invokeHandler: opcode: " << funcTab[i].name <<
00445             " operands: " << bytes << endl;
00446 
00447         // We don't invoke the handler directly on the incoming operands, but
00448         // via a temporary datastream. This adds overhead, but eliminates the
00449         // need for the individual handlers to read *exactly* the right amount
00450         // of data (thus speeding development, and possibly adding some
00451         // future-proofing).
00452 
00453         if (bytes)
00454         {
00455             QByteArray *record = new QByteArray(bytes);
00456             QDataStream *body;
00457 
00458             operands.readRawBytes(record->data(), bytes);
00459             body = new QDataStream(*record, IO_ReadOnly);
00460             body->setByteOrder(QDataStream::LittleEndian);
00461             (this->*result)(op, bytes, *body);
00462             delete body;
00463             delete record;
00464         }
00465         else
00466         {
00467             QDataStream *body = new QDataStream();
00468 
00469             (this->*result)(op, bytes, *body);
00470             delete body;
00471         }
00472     }
00473 }
00474 
00475 QPoint Msod::normalisePoint(
00476     QDataStream &operands)
00477 {
00478     Q_UINT16 x;
00479     Q_UINT16 y;
00480 
00481     operands >> x >> y;
00482     return QPoint(x / m_dpi, y / m_dpi);
00483 }
00484 
00485 QSize Msod::normaliseSize(
00486     QDataStream &operands)
00487 {
00488     Q_UINT16 width;
00489     Q_UINT16 height;
00490 
00491     operands >> width >> height;
00492     return QSize(width / m_dpi, height / m_dpi);
00493 }
00494 
00495 bool Msod::parse(
00496     unsigned shapeId,
00497     const QString &file,
00498     const char *delayStream)
00499 {
00500     QFile in(file);
00501     if (!in.open(IO_ReadOnly))
00502     {
00503         kdError(s_area) << "Unable to open input file!" << endl;
00504         in.close();
00505         return false;
00506     }
00507     QDataStream stream(&in);
00508     bool result = parse(shapeId, stream, in.size(), delayStream);
00509     in.close();
00510     return result;
00511 }
00512 
00513 bool Msod::parse(
00514     unsigned shapeId,
00515     QDataStream &stream,
00516     unsigned size,
00517     const char *delayStream)
00518 {
00519     stream.setByteOrder(QDataStream::LittleEndian); // Great, I love Qt !
00520     m_requestedShapeId = shapeId;
00521     m_isRequiredDrawing = false;
00522     m_delayStream = delayStream;
00523 
00524     // Read bits.
00525 
00526     walk(size, stream);
00527     return true;
00528 }
00529 
00530 void Msod::opAlignrule(
00531     Header &,
00532     Q_UINT32,
00533     QDataStream &)
00534 {
00535 }
00536 
00537 void Msod::opAnchor(
00538     Header &,
00539     Q_UINT32,
00540     QDataStream &)
00541 {
00542 }
00543 
00544 void Msod::opArcrule(
00545     Header &,
00546     Q_UINT32,
00547     QDataStream &)
00548 {
00549 }
00550 
00551 void Msod::opBlip(Header &, Q_UINT32 bytes, QDataStream &operands)
00552 {
00553     typedef enum
00554     {
00555         msobiWMF = 0x216,       // Metafile header then compressed WMF.
00556         msobiEMF = 0x3D4,       // Metafile header then compressed EMF.
00557         msobiPICT = 0x542,      // Metafile header then compressed PICT.
00558         msobiPNG = 0x6E0,       // One byte tag then PNG data.
00559         msobiJPEG = 0x46A,      // One byte tag then JFIF data.
00560         msobiDIB = 0x7A8,       // One byte tag then DIB data.
00561         msobiClient = 0x800     // Clients should set this bit.
00562     } MSOBI;
00563     typedef enum
00564     {
00565         msocompressionDeflate,
00566         msocompressionNone = 254,
00567         msocompressionTest
00568     } MSOBLIPCOMPRESSION;
00569 
00570     bool hasPrimaryId;
00571     Q_UINT32 length = 0;
00572     struct
00573     {
00574         Q_UINT32 cb;
00575         struct
00576         {
00577             Q_UINT32 x;
00578             Q_UINT32 y;
00579             Q_UINT32 w;
00580             Q_UINT32 h;
00581         } bounds;
00582         struct
00583         {
00584             Q_UINT32 w;
00585             Q_UINT32 h;
00586         } ptSize;
00587         Q_UINT32 cbSave;
00588         Q_UINT8 compression;
00589         Q_UINT8 filter;
00590     } data;
00591 
00592     // Skip any explicit primary header (m_rgbUidprimary).
00593 
00594     switch (m_blipType)
00595     {
00596     case msoblipEMF:
00597         hasPrimaryId = (m_blipType ^ msobiEMF) != 0;
00598         break;
00599     case msoblipWMF:
00600         hasPrimaryId = (m_blipType ^ msobiWMF) != 0;
00601         break;
00602     case msoblipPICT:
00603         hasPrimaryId = (m_blipType ^ msobiPICT) != 0;
00604         break;
00605     case msoblipJPEG:
00606         hasPrimaryId = (m_blipType ^ msobiJPEG) != 0;
00607         break;
00608     case msoblipPNG:
00609         hasPrimaryId = (m_blipType ^ msobiPNG) != 0;
00610         break;
00611     case msoblipDIB:
00612         hasPrimaryId = (m_blipType ^ msobiDIB) != 0;
00613         break;
00614     default:
00615         hasPrimaryId = (m_blipType ^ msobiClient) != 0;
00616         break;
00617     }
00618     if (hasPrimaryId)
00619     {
00620         length += 16;
00621         skip(16, operands);
00622     }
00623 
00624     // Process the rest of the header.
00625 
00626     data.compression = msocompressionNone;
00627     switch (m_blipType)
00628     {
00629     case msoblipEMF:
00630     case msoblipWMF:
00631     case msoblipPICT:
00632         length += 34;
00633         operands >> data.cb;
00634         operands >> data.bounds.x >> data.bounds.y >> data.bounds.w >> data.bounds.h;
00635         operands >> data.ptSize.w >> data.ptSize.h;
00636         operands >> data.cbSave;
00637         operands >> data.compression >> data.filter;
00638         break;
00639     case msoblipJPEG:
00640     case msoblipPNG:
00641     case msoblipDIB:
00642         // Skip the "tag".
00643         length += 1;
00644         skip(1, operands);
00645         break;
00646     default:
00647         break;
00648     }
00649 
00650     // Work out the file type.
00651 
00652     Image *image = new Image();
00653     switch (m_blipType)
00654     {
00655     case msoblipEMF:
00656         image->extension = "emf";
00657         break;
00658     case msoblipWMF:
00659         image->extension = "wmf";
00660         break;
00661     case msoblipPICT:
00662         image->extension = "pic";
00663         break;
00664     case msoblipJPEG:
00665         image->extension = "jpg";
00666         break;
00667     case msoblipPNG:
00668         image->extension = "png";
00669         break;
00670     case msoblipDIB:
00671         image->extension = "dib";
00672         break;
00673     default:
00674         image->extension = "img";
00675         break;
00676     }
00677     image->length = bytes - length;
00678     image->data = new char[image->length];
00679     operands.readRawBytes((char *)image->data, image->length);
00680     if (data.compression == msocompressionDeflate)
00681     {
00682         const char *tmp;
00683         uLongf destLen = data.cb;
00684         int result;
00685 
00686         tmp = new char[data.cb];
00687         result = uncompress((Q_UINT8 *)tmp, &destLen, (Q_UINT8 *)image->data, image->length);
00688         if (result != Z_OK)
00689         {
00690             kdError(s_area) << "opBlip: uncompress failed: " << result << endl;
00691         }
00692         if (destLen != data.cb)
00693         {
00694             kdError(s_area) << "opBlip: uncompressed " << destLen << " instead of " << data.cb << endl;
00695         }
00696         delete [] image->data;
00697         image->data = tmp;
00698         image->length = destLen;
00699     }
00700     m_images.resize(m_images.size() + 1);
00701     m_images.insert(m_images.size() - 1, image);
00702 }
00703 
00704 // FBSE - File Blip Store Entry
00705 
00706 void Msod::opBse(Header &op, Q_UINT32, QDataStream &operands)
00707 {
00708     struct
00709     {
00710         Q_UINT8 btWin32;     // Required type on Win32.
00711         Q_UINT8 btMacOS;     // Required type on Mac.
00712         Q_UINT8 rgbUid[16];  // Identifier of blip.
00713         Q_UINT16 tag;        // currently unused.
00714         Q_UINT32 size;       // Blip size in stream.
00715         Q_UINT32 cRef;       // Reference count on the blip.
00716         Q_UINT32 foDelay;    // File offset in the delay stream.
00717         Q_UINT8 usage;       // How this blip is used (MSOBLIPUSAGE).
00718         Q_UINT8 cbName;      // length of the blip name.
00719         Q_UINT8 unused2;     // for the future.
00720         Q_UINT8 unused3;     // for the future.
00721     } data;
00722     unsigned i;
00723 
00724     // Work out the type of the BLIP.
00725 
00726     m_blipType = static_cast<MSOBLIPTYPE>(op.opcode.fields.inst);
00727     operands >> data.btWin32;
00728     operands >> data.btMacOS;
00729     for (i = 0; i < 16; i++)
00730         operands >> data.rgbUid[i];
00731     operands >> data.tag >> data.size;
00732     operands >> data.cRef >> data.foDelay;
00733     operands >> data.usage >> data.cbName;
00734     operands >> data.unused2 >> data.unused2;
00735 
00736     // If the Blip is not in this drawing file, process it "manually".
00737 
00738     if (m_delayStream)
00739     {
00740         // The m_pib refers to images by number, which includes images
00741         // that are no longer here. Thus, we fake these out so that any
00742         // references to non-deleted images are still valid (!!!).
00743 
00744         if (data.size && data.cRef)
00745         {
00746             QByteArray bytes;
00747             bytes.setRawData(m_delayStream + data.foDelay, data.size);
00748             QDataStream stream(bytes, IO_ReadOnly);
00749             stream.setByteOrder(QDataStream::LittleEndian);
00750             walk(data.size, stream);
00751             bytes.resetRawData(m_delayStream + data.foDelay, data.size);
00752         }
00753         else
00754         {
00755             m_images.resize(m_images.size() + 1);
00756             m_images.insert(m_images.size() - 1, 0L);
00757         }
00758     }
00759 }
00760 
00761 void Msod::opBstorecontainer(Header &, Q_UINT32 bytes, QDataStream &operands)
00762 {
00763     walk(bytes, operands);
00764 }
00765 
00766 void Msod::opCalloutrule(
00767     Header &,
00768     Q_UINT32,
00769     QDataStream &)
00770 {
00771 }
00772 
00773 void Msod::opChildanchor(
00774     Header &,
00775     Q_UINT32,
00776     QDataStream &)
00777 {
00778 }
00779 
00780 void Msod::opClientanchor(Header &, Q_UINT32, QDataStream &operands)
00781 {
00782     struct
00783     {
00784         Q_UINT32 unknown;
00785     } data;
00786 
00787     operands >> data.unknown;
00788     kdDebug(s_area) << "client anchor: " << data.unknown << endl;
00789 }
00790 
00791 void Msod::opClientdata(Header &, Q_UINT32, QDataStream &operands)
00792 {
00793     struct
00794     {
00795         Q_UINT32 unknown;
00796     } data;
00797 
00798     operands >> data.unknown;
00799     kdDebug(s_area) << "client data: " << data.unknown << endl;
00800 }
00801 
00802 void Msod::opClientrule(
00803     Header &,
00804     Q_UINT32,
00805     QDataStream &)
00806 {
00807 }
00808 
00809 void Msod::opClienttextbox(
00810     Header &,
00811     Q_UINT32,
00812     QDataStream &operands)
00813 {
00814     struct
00815     {
00816         Q_UINT32 unknown;
00817     } data;
00818 
00819     operands >> data.unknown;
00820     kdDebug(s_area) << "client textbox: 0x" << QString::number(data.unknown,16) << endl;
00821 }
00822 
00823 void Msod::opClsid(
00824     Header &,
00825     Q_UINT32,
00826     QDataStream &)
00827 {
00828 }
00829 
00830 void Msod::opColormru(
00831     Header &,
00832     Q_UINT32,
00833     QDataStream &)
00834 {
00835 }
00836 
00837 void Msod::opConnectorrule(
00838     Header &,
00839     Q_UINT32,
00840     QDataStream &)
00841 {
00842 }
00843 
00844 void Msod::opDeletedpspl(
00845     Header &,
00846     Q_UINT32,
00847     QDataStream &)
00848 {
00849 }
00850 
00851 // FDG - File DG
00852 
00853 void Msod::opDg(Header &, Q_UINT32, QDataStream &operands)
00854 {
00855     struct
00856     {
00857         Q_UINT32 csp;        // The number of shapes in this drawing.
00858         Q_UINT32 spidCur;    // The last shape ID given to an SP in this DG.
00859     } data;
00860 
00861     operands >> data.csp >> data.spidCur;
00862     kdDebug(s_area) << "drawing id: " << data.spidCur << endl;
00863     m_isRequiredDrawing = (m_requestedShapeId == data.spidCur);
00864     if (m_isRequiredDrawing)
00865     {
00866         kdDebug(s_area) << "found requested drawing" << endl;
00867     }
00868 }
00869 
00870 void Msod::opDgcontainer(Header &, Q_UINT32 bytes, QDataStream &operands)
00871 {
00872     walk(bytes, operands);
00873 }
00874 
00875 // FDGG - File DGG
00876 
00877 void Msod::opDgg(Header &, Q_UINT32, QDataStream &operands)
00878 {
00879     struct
00880     {
00881         Q_UINT32 spidMax;    // The current maximum shape ID.
00882         Q_UINT32 cidcl;      // The number of ID clusters (FIDCLs).
00883         Q_UINT32 cspSaved;   // The total number of shapes saved.
00884                         // (including deleted shapes, if undo
00885                         // information was saved).
00886         Q_UINT32 cdgSaved;   // The total number of drawings saved.
00887     } data;
00888 
00889     // File ID Cluster - used to save IDCLs
00890 
00891     struct
00892     {
00893         Q_UINT32 dgid;       // DG owning the SPIDs in this cluster
00894         Q_UINT32 cspidCur;   // number of SPIDs used so far
00895     } data1;
00896     unsigned i;
00897 
00898     operands >> data.spidMax >> data.cidcl >> data.cspSaved >> data.cdgSaved;
00899     kdDebug(s_area) << data.cspSaved << " shapes in " <<
00900         data.cidcl - 1 << " clusters in " <<
00901         data.cdgSaved << " drawings" << endl;
00902     for (i = 0; i < data.cidcl - 1; i++)
00903     {
00904         operands >> data1.dgid >> data1.cspidCur;
00905     }
00906 }
00907 
00908 void Msod::opDggcontainer(Header &, Q_UINT32 bytes, QDataStream &operands)
00909 {
00910     walk(bytes, operands);
00911 }
00912 
00913 void Msod::opOleobject(
00914     Header &,
00915     Q_UINT32,
00916     QDataStream &)
00917 {
00918 }
00919 
00920 void Msod::opOpt(Header &, Q_UINT32 bytes, QDataStream &operands)
00921 {
00922     m_opt->walk(bytes, operands);
00923 }
00924 
00925 void Msod::opRegroupitems(
00926     Header &,
00927     Q_UINT32,
00928     QDataStream &)
00929 {
00930 }
00931 
00932 void Msod::opSelection(
00933     Header &,
00934     Q_UINT32,
00935     QDataStream &)
00936 {
00937 }
00938 
00939 void Msod::opSolvercontainer(Header &, Q_UINT32 bytes, QDataStream &operands)
00940 {
00941     walk(bytes, operands);
00942 }
00943 
00944 void Msod::opSp(Header &op, Q_UINT32 bytes, QDataStream &operands)
00945 {
00946     // We want to defer the act of drawing a shape until we have seen any options
00947     // that may affect it. Thus, we merely store the data away, and let opSpContainer
00948     // do all the ahrd work.
00949 
00950     m_shape.type = op.opcode.fields.inst;
00951     m_shape.length = bytes;
00952     m_shape.data = new char [bytes];
00953     operands.readRawBytes(m_shape.data, bytes);
00954 }
00955 
00956 void Msod::opSpcontainer(Header &, Q_UINT32 bytes, QDataStream &operands)
00957 {
00958     walk(bytes, operands);
00959 
00960     // Having gathered all the information for this shape, we can now draw it.
00961 
00962     QByteArray  a;
00963 
00964     a.setRawData(m_shape.data, m_shape.length);
00965     QDataStream s(a, IO_ReadOnly);
00966     s.setByteOrder(QDataStream::LittleEndian); // Great, I love Qt !
00967     drawShape(m_shape.type, m_shape.length, s);
00968     a.resetRawData(m_shape.data, m_shape.length);
00969     delete [] m_shape.data;
00970     m_shape.data = 0L;
00971 }
00972 
00973 void Msod::opSpgr(Header &, Q_UINT32, QDataStream &operands)
00974 {
00975     struct
00976     {
00977         Q_UINT32 x;
00978         Q_UINT32 y;
00979         Q_UINT32 w;
00980         Q_UINT32 h;
00981     } data;
00982 
00983     operands >> data.x >> data.y >> data.w >> data.h;
00984 }
00985 
00986 void Msod::opSpgrcontainer(Header &, Q_UINT32 bytes, QDataStream &operands)
00987 {
00988     walk(bytes, operands);
00989 }
00990 
00991 void Msod::opSplitmenucolors(Header &, Q_UINT32, QDataStream &operands)
00992 {
00993     struct
00994     {
00995         Q_UINT32 fill;
00996         Q_UINT32 line;
00997         Q_UINT32 shadow;
00998         Q_UINT32 threeDee;
00999     } data;
01000 
01001     operands >> data.fill >> data.line >> data.shadow >> data.threeDee;
01002 }
01003 
01004 void Msod::opTextbox(
01005     Header &,
01006     Q_UINT32,
01007     QDataStream &)
01008 {
01009 }
01010 
01011 void Msod::skip(Q_UINT32 bytes, QDataStream &operands)
01012 {
01013     if ((int)bytes < 0)
01014     {
01015         kdError(s_area) << "skip: " << (int)bytes << endl;
01016         return;
01017     }
01018     if (bytes)
01019     {
01020         Q_UINT32 i;
01021         Q_UINT8 discard;
01022 
01023         kdDebug(s_area) << "skip: " << bytes << endl;
01024         for (i = 0; i < bytes; i++)
01025         {
01026             operands >> discard;
01027         }
01028     }
01029 }
01030 
01031 void Msod::walk(Q_UINT32 bytes, QDataStream &operands)
01032 {
01033     Header op;
01034     Q_UINT32 length = 0;
01035 
01036     // Stop parsing when there are no more records. Note that we stop as soon
01037     // as we cannot get a complete header.
01038     while (length + 8 <= bytes)
01039     {
01040         operands >> op.opcode.info >> op.cbLength;
01041 
01042         // If we get some duff data, protect ourselves.
01043         if (length + op.cbLength + 8 > bytes)
01044         {
01045             op.cbLength = bytes - length - 8;
01046         }
01047         length += op.cbLength + 8;
01048         if (op.opcode.fields.fbt == 0x200)
01049         {
01050             // This appears to be an EOF marker.
01051             break;
01052         }
01053 
01054         // Package the arguments...
01055 
01056         invokeHandler(op, op.cbLength, operands);
01057     }
01058 
01059     // Eat unexpected data that the caller may expect us to consume.
01060     skip(bytes - length, operands);
01061 }
01062 
01063 Msod::Options::Options(
01064     Msod &parent) :
01065         m_parent(parent)
01066 {
01067     m_pVertices = 0L;
01068     initialise();
01069 }
01070 
01071 Msod::Options::~Options()
01072 {
01073     delete m_pVertices;
01074 }
01075 
01076 double Msod::Options::from1616ToDouble(Q_UINT32 value)
01077 {
01078     return (value >> 16) + 65535.0 / (double)(value & 0xffff);
01079 }
01080 
01081 void Msod::Options::initialise()
01082 {
01083     m_rotation = 0.0;
01084 
01085     m_lTxid = 0;
01086 
01087     m_pib = 0;
01088     m_pibName = QString::null;
01089     m_pibFlags = 0;
01090     m_pictureId = 0;
01091     m_fNoHitTestPicture = false;
01092     m_pictureGray = false;
01093     m_pictureBiLevel = false;
01094     m_pictureActive = false;
01095 
01096     m_geoLeft = 0;
01097     m_geoTop = 0;
01098     m_geoRight = 21600;
01099     m_geoBottom = 21600;
01100     m_shapePath = 1;
01101     delete m_pVertices;
01102     m_pVertices = 0L;
01103     m_fShadowOK = true;
01104     m_f3DOK = true;
01105     m_fLineOK = true;
01106     m_fGTextOK = false;
01107     m_fFillShadeShapeOK = false;
01108     m_fFillOK = true;
01109 
01110     m_fFilled = true;
01111     m_fHitTestFill = true;
01112     m_fillShape = true;
01113     m_fillUseRect = false;
01114     m_fNoFillHitTest = false;
01115 
01116     m_lineColor = 0;
01117     m_lineBackColor = 0xffffff;
01118     m_lineType = 0;
01119     m_lineWidth = 9525;
01120 
01121     m_fArrowheadsOK = false;
01122     m_fLine = true;
01123     m_fHitTestLine = true;
01124     m_lineFillShape = true;
01125     m_fNoLineDrawDash = false;
01126 
01127     m_bWMode = 1;
01128 
01129     m_fOleIcon = false;
01130     m_fPreferRelativeResize = false;
01131     m_fLockShapeType = false;
01132     m_fDeleteAttachedObject = false;
01133     m_fBackground = false;
01134 }
01135 
01136 void Msod::Options::walk(Q_UINT32 bytes, QDataStream &operands)
01137 {
01138     Header op;
01139     Q_UINT16 length = 0;
01140     Q_UINT16 complexLength = 0;
01141 
01142     // Reset all options to default values.
01143 
01144     initialise();
01145 
01146     // First process all simple options, and add all complex options to a list.
01147 
01148     QPtrList<Header> complexOpts;
01149     complexOpts.setAutoDelete(true);
01150     bool unsupported;
01151     while (length + complexLength < (int)bytes)
01152     {
01153         operands >> op.opcode.info >> op.value;
01154         length += 6;
01155 
01156         // Defer processing of complex options.
01157 
01158         if (op.opcode.fields.fComplex)
01159         {
01160             complexLength += op.value;
01161             complexOpts.append(new Header(op));
01162             continue;
01163         }
01164 
01165         // Now squirrel away the option value.
01166 
01167         unsupported = false;
01168         switch (op.opcode.fields.pid)
01169         {
01170         case 4:
01171             m_rotation = from1616ToDouble(op.value);
01172             break;
01173         case 128:
01174             m_lTxid = op.value;
01175     kdDebug(s_area) << "textbox: 0x" << QString::number(op.value,16) << endl;
01176             break;
01177         case 260:
01178             if (op.opcode.fields.fBid)
01179             {
01180                 m_pib = op.value;
01181                 if (m_parent.m_isRequiredDrawing)
01182                 {
01183                     Image *image = m_parent.m_images[m_pib - 1];
01184 
01185                     // If it is an embedded WMF we don't bother with the
01186                     // part; we just extract it as more vector graphics.
01187 
01188                     if (image->extension == "wmf")
01189                     {
01190                         QByteArray  a;
01191                         a.setRawData(image->data, image->length);
01192                         QDataStream s(a, IO_ReadOnly);
01193                         m_parent.KWmf::parse(s, image->length);
01194                         a.resetRawData(image->data, image->length);
01195                     }
01196                     else
01197                     {
01198                         m_parent.gotPicture(
01199                             m_pib,
01200                             image->extension,
01201                             image->length,
01202                             image->data);
01203                     }
01204                 }
01205             }
01206             else
01207             {
01208                 kdError(s_area) << "Cannot handle IMsoBlip" << endl;
01209             }
01210             break;
01211         case 262:
01212             m_pibFlags = op.value;
01213             break;
01214         case 267:
01215             m_pictureId = op.value;
01216             break;
01217         case 319:
01218             m_fNoHitTestPicture = (op.value & 0x0008) != 0;
01219             m_pictureGray = (op.value & 0x0004) != 0;
01220             m_pictureBiLevel = (op.value & 0x0002) != 0;
01221             m_pictureActive = (op.value & 0x0001) != 0;
01222             break;
01223         case 320:
01224             m_geoLeft = op.value;
01225             break;
01226         case 321:
01227             m_geoTop = op.value;
01228             break;
01229         case 322:
01230             m_geoRight = op.value;
01231             break;
01232         case 323:
01233             m_geoBottom = op.value;
01234             break;
01235         case 324:
01236             m_shapePath = op.value;
01237             break;
01238         case 383:
01239             m_fShadowOK = (op.value & 0x0020) != 0;
01240             m_f3DOK = (op.value & 0x0010) != 0;
01241             m_fLineOK = (op.value & 0x0008) != 0;
01242             m_fGTextOK = (op.value & 0x0004) != 0;
01243             m_fFillShadeShapeOK = (op.value & 0x0002) != 0;
01244             m_fFillOK = (op.value & 0x0001) != 0;
01245             break;
01246         case 447:
01247             m_fFilled = (op.value & 0x0010) != 0;
01248             m_fHitTestFill = (op.value & 0x0008) != 0;
01249             m_fillShape = (op.value & 0x0004) != 0;
01250             m_fillUseRect = (op.value & 0x0002) != 0;
01251             m_fNoFillHitTest = (op.value & 0x0001) != 0;
01252             break;
01253         case 448:
01254             m_lineColor = op.value;
01255             break;
01256         case 450:
01257             m_lineBackColor = op.value;
01258             break;
01259         case 452:
01260             m_lineType = op.value;
01261             break;
01262         case 459:
01263             m_lineWidth = op.value;
01264             break;
01265         case 511:
01266             m_fArrowheadsOK = (op.value & 0x0010) != 0;
01267             m_fLine = (op.value & 0x0008) != 0;
01268             m_fHitTestLine = (op.value & 0x0004) != 0;
01269             m_lineFillShape = (op.value & 0x0002) != 0;
01270             m_fNoLineDrawDash = (op.value & 0x0001) != 0;
01271             break;
01272         case 772:
01273             m_bWMode = op.value;
01274             break;
01275         case 831:
01276             m_fOleIcon = (op.value & 0x0010) != 0;
01277             m_fPreferRelativeResize = (op.value & 0x0008) != 0;
01278             m_fLockShapeType = (op.value & 0x0004) != 0;
01279             m_fDeleteAttachedObject = (op.value & 0x0002) != 0;
01280             m_fBackground = (op.value & 0x0001) != 0;
01281             break;
01282         default:
01283             unsupported = true;
01284             kdWarning(s_area) << "unsupported simple option: " <<
01285                 op.opcode.fields.pid << endl;
01286             break;
01287         }
01288         if (!unsupported)
01289             kdDebug(s_area) << "simple option: " <<
01290                 op.opcode.fields.pid << endl;
01291     }
01292 
01293     // Now empty the list of complex options.
01294 
01295     while (complexOpts.count())
01296     {
01297         Q_INT16 t16;
01298         unsigned i;
01299 
01300         op = *complexOpts.getFirst();
01301         complexOpts.removeFirst();
01302         unsupported = false;
01303         switch (op.opcode.fields.pid)
01304         {
01305         case 261:
01306             while (true)
01307             {
01308                 operands >> t16;
01309                 if (!t16)
01310                     break;
01311                 m_pibName += QChar(t16);
01312             };
01313             break;
01314         case 325:
01315             m_pVertices = new QPointArray(op.value / 4);
01316             for (i = 0; i < m_pVertices->count(); i++)
01317             {
01318                 m_pVertices->setPoint(i, m_parent.normalisePoint(operands));
01319             };
01320             break;
01321         case 326:
01322             operands >> t16;
01323             i = t16;
01324             operands >> t16;
01325             operands >> t16;
01326             m_parent.skip(i * t16, operands);
01327             break;
01328         default:
01329             unsupported = true;
01330             kdWarning(s_area) << "unsupported complex option: " <<
01331                 op.opcode.fields.pid << " operands: " << op.value << endl;
01332             m_parent.skip(op.value, operands);
01333             break;
01334         }
01335         if (!unsupported)
01336             kdDebug(s_area) << "complex option: " <<
01337                 op.opcode.fields.pid << " operands: " << op.value  << endl;
01338         complexLength -= op.value;
01339     }
01340 }
KDE Home | KDE Accessibility Home | Description of Access Keys