/*! * This method sets all the local properties from a vector of pointers * to const gchar * strings of Property - Value pairs. * This method wipes out all the old values and clears all the bools * assciated with them. */ void XAP_Dialog_FontChooser::setAllPropsFromVec(const UT_Vector & vProps) { UT_sint32 remCount = vProps.getItemCount(); if(remCount <= 0) return; // BAD BAD, we have wrong count UT_ASSERT_HARMLESS(remCount % 2 == 0); if(remCount % 2) { remCount--; } m_mapProps.clear(); UT_sint32 i = 0; for(i=0; i< remCount; i+=2) { m_mapProps.insert(std::make_pair((const char*)vProps.getNthItem(i), (const char*)vProps.getNthItem(i+1))); } // // Do the Text decorations // const std::string sDecor = getVal("text-decoration"); m_bUnderline = (NULL != strstr(sDecor.c_str(),"underline")); m_bOverline = (NULL != strstr(sDecor.c_str(),"overline")); m_bStrikeout = (NULL != strstr(sDecor.c_str(),"line-through")); m_bTopline = (NULL != strstr(sDecor.c_str(),"topline")); m_bBottomline = (NULL != strstr(sDecor.c_str(),"bottomline")); const std::string sDisplay = getVal("display"); m_bHidden = !strcmp(sDisplay.c_str(),"none"); const std::string sPosition = getVal("text-position"); m_bSuperScript = strcmp(sPosition.c_str(),"superscript")==0; m_bSubScript = strcmp(sPosition.c_str(),"subscript")==0; }
void XAP_App::enumerateFrames(UT_Vector & v) { for(UT_sint32 i = 0; i < getFrameCount(); ++i) { XAP_Frame * pF = getFrame(i); if(pF) { if (v.findItem((void*)pF) < 0) { v.addItem((void*)pF); } } } }
/*! \fn bool PP_AttrProp::explodeStyle(const PD_Document * pDoc, bool bOverwrite) \brief This function transfers attributes and properties defined in style into the AP. \param bOverwrite indicates what happens if the property/attribute is already present. If false \ (default) the style definition is ignored; if true the style value overrides the present value. */ bool PP_AttrProp::explodeStyle(const PD_Document * pDoc, bool bOverwrite) { UT_return_val_if_fail(pDoc,false); // expand style if present const gchar * pszStyle = NULL; if(getAttribute(PT_STYLE_ATTRIBUTE_NAME, pszStyle)) { PD_Style * pStyle = NULL; if(pszStyle && (strcmp(pszStyle, "None") != 0) && pDoc->getStyle(pszStyle,&pStyle)) { UT_Vector vAttrs; UT_Vector vProps; UT_sint32 i; pStyle->getAllAttributes(&vAttrs, 100); pStyle->getAllProperties(&vProps, 100); for(i = 0; i < vProps.getItemCount(); i += 2) { const gchar * pName = (const gchar *)vProps.getNthItem(i); const gchar * pValue = (const gchar *)vProps.getNthItem(i+1); const gchar * p; bool bSet = bOverwrite || !getProperty(pName, p); if(bSet) setProperty(pName, pValue); } // attributes are more complicated, because there are some style attributes that must // not be transferred to the generic AP for(i = 0; i < vAttrs.getItemCount(); i += 2) { const gchar * pName = (const gchar *)vAttrs.getNthItem(i); if(!pName || !strcmp(pName, "type") || !strcmp(pName, "name") || !strcmp(pName, "basedon") || !strcmp(pName, "followedby") || !strcmp(pName, "props")) { continue; } const gchar * pValue = (const gchar *)vAttrs.getNthItem(i+1); const gchar * p; bool bSet = bOverwrite || !getAttribute(pName, p); if(bSet) setAttribute(pName, pValue); } } } return true; }
/* Get the user interface languages installed Caller should delete the allocated vector */ UT_Vector* AP_Win32App::getInstalledUILanguages(void) { UT_Vector* pVec = new UT_Vector(64,16); UT_Language lang; for (UT_uint32 i=0; i< lang.getCount(); i++) { const char *pLangCode = (const char*)lang.getNthLangCode(i); if (doesStringSetExist(pLangCode)) pVec->addItem(g_strdup((char*)pLangCode)); else { /*The en-US is the default internal string set and wont be found on disk but it should be also listed*/ if (strcmp(pLangCode, "en-US")==0) pVec->addItem(g_strdup((char*)pLangCode)); } } return pVec; }
/* Creates a vector with a list of support languages for spell checking You must to g_free the allocated memory */ UT_Vector* XAP_Dialog_Language::getAvailableDictionaries() { #ifdef ENABLE_SPELL SpellChecker * checker = SpellManager::instance().getInstance(); UT_Vector& vec= checker->getMapping(); DictionaryMapping * mapping; UT_Vector* vecRslt = new UT_Vector(); const UT_uint32 nItems = vec.getItemCount(); for (UT_uint32 iItem = nItems; iItem; --iItem) { mapping = static_cast<DictionaryMapping*>(const_cast<void*>(vec.getNthItem(iItem - 1))); if (checker->doesDictionaryExist(mapping->lang.c_str())) vecRslt->addItem( g_strdup(mapping->lang.c_str())); } return vecRslt; #else return NULL; #endif }
/*! Enumerates currently open document associated with the application, excluding document pointed to by pExclude \param v: UT_Vector into which to store the document pointers \para pExclude: pointer to a document to exclude from enumeration, can be NULL (e.g., if this function is called from inside a document, it might be desirable to exclude that document) */ void XAP_App::enumerateDocuments(UT_Vector & v, const AD_Document * pExclude) { UT_sint32 iIndx; for(UT_sint32 i = 0; i < getFrameCount(); ++i) { XAP_Frame * pF = getFrame(i); if(pF) { AD_Document * pD = pF->getCurrentDoc(); if(pD && pD != pExclude) { iIndx = v.findItem((void*)pD); if(iIndx < 0) { v.addItem((void*)pD); } } } } }
bool AP_Dialog_Paragraph::getDialogData(const gchar **& pProps) { UT_Vector v; struct propPair { gchar * prop; gchar * val; }; propPair * p; // only do this if the control has a proper value if (_wasChanged(id_MENU_ALIGNMENT) && _getMenuItemValue(id_MENU_ALIGNMENT)) { ALLOC_PROP_PAIR(p); p->prop = g_strdup("text-align"); switch (_getMenuItemValue(id_MENU_ALIGNMENT)) { case align_LEFT: p->val = g_strdup("left"); break; case align_CENTERED: p->val = g_strdup("center"); break; case align_RIGHT: p->val = g_strdup("right"); break; case align_JUSTIFIED: p->val = g_strdup("justify"); break; default: UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN); } v.addItem(p); } if (_wasChanged(id_CHECK_DOMDIRECTION)) { ALLOC_PROP_PAIR(p); p->prop = g_strdup("dom-dir"); if (_getCheckItemValue(id_CHECK_DOMDIRECTION) == check_TRUE) p->val = g_strdup("rtl"); else p->val = g_strdup("ltr"); v.addItem(p); } if (_wasChanged(id_SPIN_LEFT_INDENT)) { ALLOC_PROP_PAIR(p); p->prop = g_strdup("margin-left"); p->val = g_strdup(_getSpinItemValue(id_SPIN_LEFT_INDENT)); v.addItem(p); } if (_wasChanged(id_SPIN_RIGHT_INDENT)) { ALLOC_PROP_PAIR(p); p->prop = g_strdup("margin-right"); p->val = g_strdup(_getSpinItemValue(id_SPIN_RIGHT_INDENT)); v.addItem(p); } // TODO : The logic here might not be bulletproof. If the user triggers // TODO : a change in the TYPE of special indent (hanging, first line, // TODO : none), we will always save what's in the box as a property. // TODO : One could make it smarter with a stronger contract with // TODO : the platform interfaces. if (_getMenuItemValue(id_MENU_SPECIAL_INDENT) && (_wasChanged(id_MENU_SPECIAL_INDENT) || _wasChanged(id_SPIN_SPECIAL_INDENT))) { ALLOC_PROP_PAIR(p); p->prop = g_strdup("text-indent"); tIndentState i = (tIndentState) _getMenuItemValue(id_MENU_SPECIAL_INDENT); if (i == indent_NONE) p->val = g_strdup(UT_convertInchesToDimensionString(m_dim, 0)); else if (i == indent_FIRSTLINE) p->val = g_strdup(_getSpinItemValue(id_SPIN_SPECIAL_INDENT)); else if (i == indent_HANGING) { // we have to flip the sign for "hanging" indents to a negative quantity for // storage in the document as a text-indent // get with no dimension UT_Dimension dim = UT_determineDimension(_getSpinItemValue(id_SPIN_SPECIAL_INDENT)); double val = UT_convertDimensionless(_getSpinItemValue(id_SPIN_SPECIAL_INDENT)); // Convert to inches val = UT_convertDimToInches(val, dim); // flip sign val = val * (double) -1; // store the reconstructed p->val = g_strdup(UT_convertInchesToDimensionString(dim, val)); } v.addItem(p); } if (_wasChanged(id_SPIN_BEFORE_SPACING)) { ALLOC_PROP_PAIR(p); p->prop = g_strdup("margin-top"); p->val = g_strdup(_getSpinItemValue(id_SPIN_BEFORE_SPACING)); v.addItem(p); } if (_wasChanged(id_SPIN_AFTER_SPACING)) { ALLOC_PROP_PAIR(p); p->prop = g_strdup("margin-bottom"); p->val = g_strdup(_getSpinItemValue(id_SPIN_AFTER_SPACING)); v.addItem(p); } // TODO : The logic here might not be bulletproof. If the user triggers // TODO : a change in the TYPE of special indent (single, double, etc.) // TODO : we will always save what's in the box as a property. // TODO : One could make it smarter with a stronger contract with // TODO : the platform interfaces. if(_getMenuItemValue(id_MENU_SPECIAL_SPACING) && (_wasChanged(id_MENU_SPECIAL_SPACING) || _wasChanged(id_SPIN_SPECIAL_SPACING))) { ALLOC_PROP_PAIR(p); p->prop = g_strdup("line-height"); // normal spacings (single, 1.5, double) are just simple numbers. // "at least" needs a "+" at the end of the number (no units). // "exactly" simply has units. // "multiple" has no units. gchar * pTmp = NULL; const gchar * pString = _getSpinItemValue(id_SPIN_SPECIAL_SPACING); UT_uint32 nSize = 0; switch(_getMenuItemValue(id_MENU_SPECIAL_SPACING)) { case spacing_SINGLE: p->val = g_strdup("1.0"); break; case spacing_ONEANDHALF: p->val = g_strdup("1.5"); break; case spacing_DOUBLE: p->val = g_strdup("2.0"); break; case spacing_ATLEAST: nSize = strlen(pString); pTmp = (gchar *) UT_calloc(nSize + 2, sizeof(gchar)); UT_return_val_if_fail (pTmp, false); strncpy(pTmp, pString, nSize); // stick a '+' at the end pTmp[nSize] = '+'; p->val = g_strdup(pTmp); FREEP(pTmp); break; case spacing_EXACTLY: // fallthrough case spacing_MULTIPLE: // both these cases either do or don't have units associated with them. // the platform dialog code takes care of that. p->val = g_strdup(pString); break; default: UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN); } v.addItem(p); } // NOTE : "orphans" and "widows" hold a number specifying the number // NOTE : of lines to consider an orphaned or widowed piece of text. // NOTE : If they're both 0 they're off. If either is greater than // NOTE : 0, then some form of control is in effect. If the property // NOTE : is not set, they're indeterminate. if (_wasChanged(id_CHECK_WIDOW_ORPHAN)) { // TODO : fix this! we stomp on both properties (setting them // TODO : to "2"s or "0"s) if the one check box was ever // TODO : changed { ALLOC_PROP_PAIR(p); p->prop = g_strdup("orphans"); if (_getCheckItemValue(id_CHECK_WIDOW_ORPHAN) == check_TRUE) p->val = g_strdup("2"); else p->val = g_strdup("0"); v.addItem(p); } { ALLOC_PROP_PAIR(p); p->prop = g_strdup("widows"); if (_getCheckItemValue(id_CHECK_WIDOW_ORPHAN) == check_TRUE) p->val = g_strdup("2"); else p->val = g_strdup("0"); v.addItem(p); } } if (_wasChanged(id_CHECK_KEEP_LINES)) { ALLOC_PROP_PAIR(p); p->prop = g_strdup("keep-together"); if (_getCheckItemValue(id_CHECK_KEEP_LINES) == check_TRUE) p->val = g_strdup("yes"); else p->val = g_strdup("no"); v.addItem(p); } if (_wasChanged(id_CHECK_KEEP_NEXT)) { ALLOC_PROP_PAIR(p); p->prop = g_strdup("keep-with-next"); if (_getCheckItemValue(id_CHECK_KEEP_NEXT) == check_TRUE) p->val = g_strdup("yes"); else p->val = g_strdup("no"); v.addItem(p); } // TODO : add these to PP_Property (pp_Property.cpp) !!! /* m_pageBreakBefore; m_suppressLineNumbers; m_noHyphenate; */ // export everything in the array UT_uint32 count = v.getItemCount()*2 + 1; const gchar ** newprops = (const gchar **) UT_calloc(count, sizeof(gchar *)); if (!newprops) return false; const gchar ** newitem = newprops; UT_uint32 i = v.getItemCount(); while (i > 0) { p = (propPair *) v.getNthItem(i-1); i--; newitem[0] = p->prop; newitem[1] = p->val; newitem += 2; } // DO purge the vector's CONTENTS, which are just propPair structs UT_VECTOR_FREEALL(propPair *, v); // DO NOT purge the propPair's CONTENTS, because they will be pointed to // by the pointers we just copied into memory typed (gchar **) pProps = newprops; return true; }
bool pt_PieceTable::_realChangeSpanFmt(PTChangeFmt ptc, PT_DocPosition dpos1, PT_DocPosition dpos2, const gchar ** attributes, const gchar ** properties, bool bRevisionDelete) { // apply a span-level formatting change to the given region. UT_return_val_if_fail (m_pts==PTS_Editing,false); _tweakFieldSpan(dpos1,dpos2); // // Deal with case of exactly selecting the endOfFootnote // pf_Frag * pfEndDum = m_fragments.findFirstFragBeforePos(dpos2); if(isEndFootnote(pfEndDum)) { if(dpos2 > dpos1) { dpos2--; } } // // Deal with addStyle // bool bApplyStyle = (PTC_AddStyle == ptc); const gchar ** sProps = NULL; const gchar ** lProps = properties; if(bApplyStyle) { // // OK for styles we expand out all defined properties including BasedOn styles // Then we use these to eliminate any specfic properties in the current strux // Then properties in the current strux will resolve to those defined in the // style (they exist there) to specifc values in strux (if not overridden by // the style) then finally to default value. // const gchar * szStyle = UT_getAttribute(PT_STYLE_ATTRIBUTE_NAME,attributes); PD_Style * pStyle = NULL; UT_return_val_if_fail (szStyle,false); getDocument()->getStyle(szStyle,&pStyle); UT_return_val_if_fail (pStyle,false); UT_Vector vProps; // // Get the vector of properties // pStyle->getAllProperties(&vProps,0); // // Finally make the const gchar * array of properties // UT_uint32 countp = vProps.getItemCount() + 1; sProps = (const gchar **) UT_calloc(countp, sizeof(gchar *)); countp--; UT_uint32 i; for(i=0; i<countp; i++) { sProps[i] = (const gchar *) vProps.getNthItem(i); } sProps[i] = NULL; lProps = sProps; } if (dpos1 == dpos2) // if length of change is zero, then we have a toggle format. { UT_uint32 startUndoPos = m_history.getUndoPos(); bool bRes = _insertFmtMarkFragWithNotify(ptc,dpos1,attributes,lProps); UT_uint32 endUndoPos = m_history.getUndoPos(); // Won't be a persistant change if it's just a toggle PX_ChangeRecord *pcr=0; m_history.getUndo(&pcr,true); if (pcr && (startUndoPos != endUndoPos) ) { UT_DEBUGMSG(("Setting persistance of change to false\n")); pcr->setPersistance(false); m_history.setSavePosition(m_history.getSavePosition()+1); } if(bApplyStyle) { FREEP(sProps); } return bRes; } UT_return_val_if_fail (dpos1 < dpos2,false); bool bHaveAttributes, bHaveProperties; bHaveAttributes = (attributes && *attributes); bHaveProperties = (lProps && *lProps); pf_Frag * pf_First; pf_Frag * pf_End; PT_BlockOffset fragOffset_First; PT_BlockOffset fragOffset_End; bool bFound; bFound = getFragsFromPositions(dpos1,dpos2,&pf_First,&fragOffset_First,&pf_End,&fragOffset_End); UT_return_val_if_fail (bFound, false); #if 0 { pf_Frag * pf1, * pf2; PT_BlockOffset fo1, fo2; bool bFound1 = getFragFromPosition(dpos1,&pf1,&fo1); bool bFound2 = getFragFromPosition(dpos2,&pf2,&fo2); UT_return_val_if_fail (bFound1 && bFound2, false); UT_return_val_if_fail ((pf1==pf_First) && (fragOffset_First==fo1), false); UT_return_val_if_fail ((pf2==pf_End) && (fragOffset_End==fo2), false); } #endif // see if the amount of text to be changed is completely // contained within a single fragment. if so, we have a // simple change. otherwise, we need to set up a multi-step // change -- it may not actually take more than one step, // but it is too complicated to tell at this point, so we // assume it will and don't worry about it. // // we are in a simple change if the beginning and end are // within the same fragment. // NOTE: if we call beginMultiStepGlob() we ***MUST*** call // NOTE: endMultiStepGlob() before we return -- otherwise, // NOTE: the undo/redo won't be properly bracketed. bool bSimple = (pf_First == pf_End); if (!bSimple) beginMultiStepGlob(); pf_Frag_Strux * pfsContainer = NULL; pf_Frag * pfNewEnd; UT_uint32 fragOffsetNewEnd; UT_uint32 length = dpos2 - dpos1; while (length != 0) { // FIXME: Special check to support a FmtMark at the end of the // document. This is necessary because FmtMarks don't have a // length... See bug 452. if (0 == length && (!pf_First || pf_Frag::PFT_FmtMark != pf_First->getType())) break; UT_return_val_if_fail (dpos1+length==dpos2, false); UT_uint32 lengthInFrag = pf_First->getLength() - fragOffset_First; UT_uint32 lengthThisStep = UT_MIN(lengthInFrag, length); switch (pf_First->getType()) { case pf_Frag::PFT_EndOfDoc: default: UT_DEBUGMSG(("fragment type: %d\n",pf_First->getType())); UT_ASSERT_HARMLESS(0); if(bApplyStyle) { FREEP(sProps); } return false; case pf_Frag::PFT_Strux: { // we are only applying span-level changes, so we ignore strux. // but we still need to update our loop indices. pfNewEnd = pf_First->getNext(); fragOffsetNewEnd = 0; pfsContainer = static_cast<pf_Frag_Strux *> (pf_First); bool bFoundStrux = false; if(isEndFootnote(pfsContainer)) { bFoundStrux = _getStruxFromFragSkip(pfsContainer,&pfsContainer); UT_return_val_if_fail (bFoundStrux, false); } } break; case pf_Frag::PFT_Text: { if (!pfsContainer) { bool bFoundStrux; bFoundStrux = _getStruxFromPosition(dpos1,&pfsContainer); UT_return_val_if_fail (bFoundStrux,false); if(isEndFootnote(pfsContainer)) { bFoundStrux = _getStruxFromFragSkip(pfsContainer,&pfsContainer); UT_return_val_if_fail (bFoundStrux,false); } } bool bResult; bResult = _fmtChangeSpanWithNotify(ptc,static_cast<pf_Frag_Text *>(pf_First), fragOffset_First,dpos1,lengthThisStep, attributes,lProps, pfsContainer,&pfNewEnd,&fragOffsetNewEnd,bRevisionDelete); UT_return_val_if_fail (bResult,false); } break; case pf_Frag::PFT_Object: { if (!pfsContainer) { bool bFoundStrux; bFoundStrux = _getStruxFromPosition(dpos1,&pfsContainer); UT_return_val_if_fail (bFoundStrux,false); if(isEndFootnote(pfsContainer)) { bFoundStrux = _getStruxFromFragSkip(pfsContainer,&pfsContainer); UT_return_val_if_fail (bFoundStrux,false); } } bool bResult; bResult = _fmtChangeObjectWithNotify(ptc,static_cast<pf_Frag_Object *>(pf_First), fragOffset_First,dpos1,lengthThisStep, attributes,lProps, pfsContainer,&pfNewEnd,&fragOffsetNewEnd,false); UT_return_val_if_fail (bResult,false); } break; case pf_Frag::PFT_FmtMark: { if (!pfsContainer) { bool bFoundStrux; bFoundStrux = _getStruxFromPosition(dpos1,&pfsContainer); UT_return_val_if_fail (bFoundStrux,false); if(isEndFootnote(pfsContainer)) { bFoundStrux = _getStruxFromFragSkip(pfsContainer,&pfsContainer); UT_return_val_if_fail (bFoundStrux,false); } } bool bResult; bResult = _fmtChangeFmtMarkWithNotify(ptc,static_cast<pf_Frag_FmtMark *>(pf_First), dpos1, attributes,lProps, pfsContainer,&pfNewEnd,&fragOffsetNewEnd); UT_return_val_if_fail (bResult,false); } break; } dpos1 += lengthThisStep; length -= lengthThisStep; // since _fmtChange{Span,FmtMark,...}WithNotify(), can delete pf_First, mess with the // fragment list, and does some aggressive coalescing of // fragments, we cannot just do a pf_First->getNext() here. // to advance to the next fragment, we use the *NewEnd variables // that each of the cases routines gave us. pf_First = pfNewEnd; if (!pf_First) length = 0; fragOffset_First = fragOffsetNewEnd; } if(bApplyStyle) { FREEP(sProps); } if (!bSimple) endMultiStepGlob(); return true; }
UT_Error IE_Imp_StarOffice::_loadFile(GsfInput * input) { try { UT_DEBUGMSG(("SDW: Starting import\n")); mOle = GSF_INFILE (gsf_infile_msole_new(input, NULL)); if (!mOle) return UT_IE_BOGUSDOCUMENT; // firstly, load metadata SDWDocInfo::load(mOle, getDoc()); mDocStream = gsf_infile_child_by_name(mOle, "StarWriterDocument"); if (!mDocStream) return UT_IE_BOGUSDOCUMENT; gsf_off_t size = gsf_input_size(mDocStream); if (!appendStrux(PTX_Section, PP_NOPROPS)) return UT_IE_NOMEMORY; UT_DEBUGMSG(("SDW: Attempting to load DocHdr...\n")); mDocHdr.load(mDocStream); UT_DEBUGMSG(("SDW: ...success\n")); // Ask for and verify the password if (mDocHdr.cryptor) { if (!mDocHdr.cryptor->SetPassword(GetPassword().c_str())) { UT_DEBUGMSG(("SDW: Wrong password\n")); return UT_IE_PROTECTED; } } // do the actual reading char type; bool done = false; UT_uint32 recSize; while (!done) { if (gsf_input_tell(mDocStream) == size) break; readChar(mDocStream, type); gsf_off_t eor; readRecSize(mDocStream, recSize, &eor); switch (type) { case SWG_CONTENTS: { gsf_off_t flagsEnd = 0; UT_uint32 nNodes; // sw/source/core/sw3io/sw3sectn.cxx#L129 if (mDocHdr.nVersion >= SWG_LAYFRAMES) { UT_uint8 flags; readFlagRec(mDocStream, flags, &flagsEnd); } if (mDocHdr.nVersion >= SWG_LONGIDX) streamRead(mDocStream, nNodes); else { if (mDocHdr.nVersion >= SWG_LAYFRAMES) { UT_uint16 sectidDummy; streamRead(mDocStream, sectidDummy); } UT_uint16 nodes16; streamRead(mDocStream, nodes16); nNodes = (UT_uint32)nodes16; } if (flagsEnd) { UT_ASSERT(flagsEnd >= gsf_input_tell(mDocStream)); if (gsf_input_tell(mDocStream) != flagsEnd) { UT_DEBUGMSG(("SDW: have not read all flags\n")); if (gsf_input_seek(mDocStream, flagsEnd, G_SEEK_SET)) return UT_IE_BOGUSDOCUMENT; } } bool done2 = false; UT_uint32 size2; while (!done2) { readChar(mDocStream, type); gsf_off_t eor2; readRecSize(mDocStream, size2, &eor2); switch (type) { case SWG_TEXTNODE: { // sw/source/core/sw3io/sw3nodes.cxx#L788 UT_DEBUGMSG(("SDW: Found Textnode! (start at 0x%08llX end at 0x%08llX)\n", (long long)gsf_input_tell(mDocStream), (long long)eor2)); UT_uint8 flags; gsf_off_t newPos; readFlagRec(mDocStream, flags, &newPos); // XXX check flags if (gsf_input_seek(mDocStream, newPos, G_SEEK_SET)) return UT_IE_BOGUSDOCUMENT; // Read the actual text UT_UCS4Char* str; readByteString(mDocStream, str); UT_UCS4String textNode(str); free(str); UT_DEBUGMSG(("SDW: ...length=%zu contents are: |%s|\n", textNode.length(), textNode.utf8_str())); // now get the attributes UT_String attrs; UT_String pAttrs; UT_Vector charAttributes; while (gsf_input_tell(mDocStream) < eor2) { char attVal; streamRead(mDocStream, attVal); UT_uint32 attSize; gsf_off_t eoa; // end of attribute readRecSize(mDocStream, attSize, &eoa); if (attVal == SWG_ATTRIBUTE) { TextAttr* a = new TextAttr; streamRead(mDocStream, *a, eoa); UT_DEBUGMSG(("SDW: ...found text-sub-node, which=0x%x, ver=0x%x, start=%u, end=%u - data:%s len:%llu data is:", a->which, a->ver, a->start, a->end, a->data?"Yes":"No", (long long unsigned)a->dataLen)); #ifdef DEBUG hexdump(a->data, a->dataLen); putc('\n', stderr); #endif charAttributes.addItem(a); } else if (attVal == SWG_ATTRSET) { // bah, yet another loop UT_DEBUGMSG(("SDW: ...paragraph attributes found\n")); while (gsf_input_tell(mDocStream) < eoa) { // reusing attVal and attSize streamRead(mDocStream, attVal); gsf_off_t eoa2; // end of attribute readRecSize(mDocStream, attSize, &eoa2); if (attVal == SWG_ATTRIBUTE) { TextAttr a; streamRead(mDocStream, a, eoa2); if (!a.attrVal.empty()) { if (a.isPara) UT_String_setProperty(pAttrs, a.attrName, a.attrVal); else UT_String_setProperty(attrs, a.attrName, a.attrVal); } UT_DEBUGMSG(("SDW: ......found paragraph attr, which=0x%x, ver=0x%x, start=%u, end=%u (string now %s) Data:%s Len=%lld Data:", a.which, a.ver, (a.startSet?a.start:0), (a.endSet?a.end:0), attrs.c_str(), (a.data ? "Yes" : "No"), (long long)a.dataLen)); #ifdef DEBUG hexdump(a.data, a.dataLen); putc('\n', stderr); #endif } if (gsf_input_seek(mDocStream, eoa2, G_SEEK_SET)) return UT_IE_BOGUSDOCUMENT; } } else { UT_DEBUGMSG(("SDW: ...unknown attribute '%c' found (start=%" GSF_OFF_T_FORMAT " end=%" GSF_OFF_T_FORMAT ")\n", attVal, gsf_input_tell(mDocStream), eoa)); } if (gsf_input_seek(mDocStream, eoa, G_SEEK_SET)) return UT_IE_BOGUSDOCUMENT; } PP_PropertyVector attributes = { "props", pAttrs.c_str() }; // first, insert the paragraph if (!appendStrux(PTX_Block, attributes)) return UT_IE_NOMEMORY; UT_String pca(attrs); // character attributes for the whole paragraph // now insert the spans of text UT_uint32 len = textNode.length(); UT_uint32 lastInsPos = 0; for (UT_uint32 i = 1; i < len; i++) { bool doInsert = false; // whether there was an attribute change for (UT_sint32 j = 0; j < charAttributes.getItemCount(); j++) { const TextAttr* a = reinterpret_cast<const TextAttr*>(charAttributes[j]); // clear the last attribute, if set if (a->endSet && a->end == (i - 1)) { if (a->isOff) { UT_String propval = UT_String_getPropVal(pca, a->attrName); UT_String_setProperty(attrs, a->attrName, propval); } else UT_String_removeProperty(attrs, a->attrName); } // now set new attribute, if needed if (a->startSet && a->start == (i - 1)) { if (a->isPara) UT_String_setProperty(pAttrs, a->attrName, a->attrVal); else if (a->isOff) UT_String_removeProperty(attrs, a->attrName); else UT_String_setProperty(attrs, a->attrName, a->attrVal); } // insert if this is the last character, or if there was a format change if ((a->endSet && a->end == i) || (a->startSet && a->start == i)) doInsert = true; } if (doInsert || i == (len - 1)) { attributes[1] = attrs.c_str(); UT_DEBUGMSG(("SDW: Going to appendFmt with %s\n", attributes[1].c_str())); if (!appendFmt(attributes)) return UT_IE_NOMEMORY; /* leave cast alone! */ UT_DEBUGMSG(("SDW: About to insert %u-%u\n", lastInsPos, i)); size_t spanLen = i - lastInsPos; if (i == (len - 1)) spanLen++; UT_UCS4String span = textNode.substr(lastInsPos, spanLen); appendSpan(span.ucs4_str(), spanLen); lastInsPos = i; } } UT_VECTOR_PURGEALL(TextAttr*, charAttributes); break; } case SWG_JOBSETUP: { // flags are apparently unused here. no idea why they are there. gsf_off_t newpos; UT_uint8 flags; readFlagRec(mDocStream, flags, &newpos); if (gsf_input_seek(mDocStream, newpos, G_SEEK_SET)) return UT_IE_BOGUSDOCUMENT; UT_uint16 len, system; streamRead(mDocStream, len); streamRead(mDocStream, system); char printerName[64]; streamRead(mDocStream, printerName, 64); char deviceName[32], portName[32], driverName[32]; streamRead(mDocStream, deviceName, 32); streamRead(mDocStream, portName, 32); streamRead(mDocStream, driverName, 32); UT_DEBUGMSG(("SDW: Jobsetup: len %u sys 0x%x printer |%.64s| device |%.32s| port |%.32s| driver |%.32s|\n", len, system, printerName, deviceName, portName, driverName)); if (system == JOBSET_FILE364_SYSTEM || system == JOBSET_FILE605_SYSTEM) { UT_uint16 len2, system2; streamRead(mDocStream, len2); streamRead(mDocStream, system2); UT_uint32 ddl; // driver data length streamRead(mDocStream, ddl); // now the interesting data UT_uint16 orient; // 0=portrait 1=landscape streamRead(mDocStream, orient); UT_uint16 paperBin; streamRead(mDocStream, paperBin); UT_uint16 paperFormat; streamRead(mDocStream, paperFormat); UT_uint32 width, height; streamRead(mDocStream, width); streamRead(mDocStream, height); UT_DEBUGMSG(("SDW: orient %u bin %u format %u width %u height %u\n", orient, paperBin, paperFormat, width, height)); // rest of the data is ignored, seems to be printer specific anyway. // Use A4, Portrait by default PP_PropertyVector attributes = { "pagetype", "a4", // A4/Letter/... "orientation", "portrait", "width", "210", "height", "297", "units", "mm" }; const char* sdwPaperToAbi[] = { "A3", "A4", "A5", "B4", "B5", "Letter", "Legal", "Tabloid/Ledger", "Custom" }; if (paperFormat < sizeof(sdwPaperToAbi)/sizeof(*sdwPaperToAbi)) { attributes[1] = sdwPaperToAbi[paperFormat]; } const char* sdwOrientToAbi[] = { "portrait", "landscape" }; if (orient < sizeof(sdwOrientToAbi)/sizeof(*sdwOrientToAbi)) { attributes[3] = sdwOrientToAbi[orient]; } attributes[5] = UT_std_string_sprintf("%f", static_cast<double>(width)/100); attributes[7] = UT_std_string_sprintf("%f", static_cast<double>(height)/100); getDoc()->setPageSizeFromFile(attributes); } break; } case SWG_EOF: done2 = true; break; default: UT_DEBUGMSG(("SDW: SWG_CONTENT: Skipping %u bytes for record type '%c' (starting at 0x%08llX)\n", size2, type, (long long)gsf_input_tell(mDocStream))); } if (gsf_input_seek(mDocStream, eor2, G_SEEK_SET)) return UT_IE_BOGUSDOCUMENT; } break; } case SWG_STRINGPOOL: { if (mDocHdr.nVersion <= SWG_POOLIDS) { UT_ASSERT_HARMLESS(UT_NOT_IMPLEMENTED); break; } UT_uint8 encoding; streamRead(mDocStream, encoding); UT_iconv_t cd = findConverter(encoding); if (!UT_iconv_isValid(cd)) throw UT_IE_IMPORTERROR; UT_uint16 count; streamRead(mDocStream, count); while (count--) { UT_uint16 id; streamRead(mDocStream, id); char* str; UT_uint16 len; ::readByteString(mDocStream, str, &len); if (id == IDX_NOCONV_FF) { UT_ASSERT_HARMLESS(UT_NOT_IMPLEMENTED); } // FIXME: find a way to not have to copy and free // the result of UT_convert_cd.... --hub UT_DEBUGMSG(("SDW: StringPool: found 0x%04x <-> %.*s\n", id, len, str)); UT_UCS4Char* convertedString = reinterpret_cast<UT_UCS4Char*>(UT_convert_cd(str, len + 1, cd, NULL, NULL)); mStringPool.insert(stringpool_map::value_type(id, convertedString)); FREEP(convertedString); delete [] str; } UT_iconv_close(cd); break; } case SWG_COMMENT: // skip over comments break; case SWG_EOF: done = true; break; default: UT_DEBUGMSG(("SDW: Skipping %u bytes for record type '%c' (starting at 0x%08llX)\n", recSize, type, (long long)gsf_input_tell(mDocStream))); } // Seek to the end of the record, in case it wasn't read completely if (gsf_input_seek(mDocStream, eor, G_SEEK_SET)) return UT_IE_BOGUSDOCUMENT; } UT_DEBUGMSG(("SDW: Done\n")); return UT_OK; } catch(UT_Error e) { UT_DEBUGMSG(("SDW: error %d\n", e)); return e; } catch(...) { UT_DEBUGMSG(("SDW: Unknown error\n")); return UT_IE_BOGUSDOCUMENT; } }