char * AP_Dialog_MarkRevisions::getComment1() { _initRevision(); if(!m_pRev || m_bForceNew) return NULL; bool bFree = false; const UT_UCS4Char * pC = m_pRev->getDescription(); if(!pC) return NULL; // now we run this string through fribidi if(XAP_App::getApp()->theOSHasBidiSupport() == XAP_App::BIDI_SUPPORT_NONE) { UT_UCS4Char *pStr2 = 0; UT_uint32 iLen = UT_UCS4_strlen(pC); pStr2 = (UT_UCS4Char *)UT_calloc( iLen + 1, sizeof(UT_UCS4Char)); UT_return_val_if_fail(pStr2,NULL); bFree = true; UT_BidiCharType iDomDir = UT_bidiGetCharType(pC[0]); UT_bidiReorderString(pC, iLen, iDomDir, pStr2); pC = pStr2; } char * pComment = (char *)UT_calloc(UT_UCS4_strlen(pC) + 1, sizeof(char)); UT_return_val_if_fail(pComment,NULL); UT_UCS4_strcpy_to_char(pComment,pC); if(bFree) { FREEP(pC); } return pComment; }
bool GR_Graphics::itemize(UT_TextIterator & text, GR_Itemization & I) { UT_return_val_if_fail(text.getStatus() == UTIter_OK, false); I.clear(); UT_uint32 iCurOffset = 0, iLastOffset = 0; UT_uint32 iPosStart = text.getPosition(); // the main loop that will span the whole text of the iterator while(text.getStatus() == UTIter_OK) { UT_BidiCharType iPrevType, iLastStrongType = UT_BIDI_UNSET, iType; UT_UCS4Char c = text.getChar(); UT_return_val_if_fail(text.getStatus() == UTIter_OK, false); iType = UT_bidiGetCharType(c); #if 0 // this branch of code breaks at all direction bounaries // it is disabled because doing that causes bug 8099 iCurOffset = iLastOffset = text.getPosition(); ++text; // this loop will cover a single homogenous item while(text.getStatus() == UTIter_OK) { iPrevType = iType; c = text.getChar(); UT_return_val_if_fail(text.getStatus() == UTIter_OK, false); // remember the offset iLastOffset = text.getPosition(); iType = UT_bidiGetCharType(c); if(iType != iPrevType) { break; } ++text; } #else //we have to break the text into chunks that each will go into a //separate run in a manner that will ensure that the text will //be correctly processed later. The most obvious way is to //break every time we encounter a change of directional //properties. Unfortunately that means breaking at each white //space, which adds a huge amount of processing due to //allocating and deleting runs when loading a //document. The following code tries to catch out the obvious //cases when the span can remain intact. Tomas, Jan 28, 2003 // remember where we are ... iCurOffset = iLastOffset = text.getPosition(); ++text; UT_BidiCharType iNextType; // this loop will cover a single homogenous item while(text.getStatus() == UTIter_OK) { iPrevType = iType; if(UT_BIDI_IS_STRONG(iType)) iLastStrongType = iType; c = text.getChar(); UT_return_val_if_fail(text.getStatus() == UTIter_OK, false); // remember the offset iLastOffset = text.getPosition(); ++text; iType = UT_bidiGetCharType(c); if(iType != iPrevType) { // potential direction boundary see if we can ignore // it bool bIgnore = false; #if 0 // this assumption is not true; for instance in the // sequence ") " the parenthesis and the space can // resolve to different directions // // I am leaving it here so that I do not add it one // day again (Tomas, Apr 10, 2003) if(UT_BIDI_IS_NEUTRAL(iPrevType) && UT_BIDI_IS_NEUTRAL(iType)) { // two neutral characters in a row will have the same // direction xxx_UT_DEBUGMSG(("GR_Graphics::itemize: ntrl->ntrl (c=0x%04x)\n",c)); bIgnore = true; } else #endif if(UT_BIDI_IS_STRONG(iPrevType) && UT_BIDI_IS_NEUTRAL(iType)) { // we can ignore a neutral character following a // strong one if it is followed by a strong // character of identical type to the previous one xxx_UT_DEBUGMSG(("GR_Graphics::itemize: strong->ntrl (c=0x%04x)\n",c)); // take a peek at what follows UT_uint32 iOldPos = text.getPosition(); while(text.getStatus() == UTIter_OK) { UT_UCS4Char c2 = text.getChar(); UT_return_val_if_fail(text.getStatus() == UTIter_OK, false); ++text; iNextType = UT_bidiGetCharType(c2); xxx_UT_DEBUGMSG(("GR_Graphics::itemize: iNextType 0x%04x\n", iNextType)); if(iNextType == iPrevType) { bIgnore = true; break; } // if the next character is strong, we cannot // ignore the boundary if(UT_BIDI_IS_STRONG(iNextType)) break; } // restore position text.setPosition(iOldPos); } else if(UT_BIDI_IS_NEUTRAL(iPrevType) && UT_BIDI_IS_STRONG(iType)) { // a neutral character followed by a strong one -- we // can ignore it, if the neutral character was // preceeded by a strong character of the same // type if(iType == iLastStrongType) { bIgnore = true; } xxx_UT_DEBUGMSG(("GR_Graphics::itemize: ntrl->strong (c=0x%04x)\n",c)); } else { // in all other cases we will split xxx_UT_DEBUGMSG(("GR_Graphics::itemize: other (c=0x%04x)\n",pSpan[i])); } xxx_UT_DEBUGMSG(("GR_Graphics::itemize: bIgnore %d\n",static_cast<UT_uint32>(bIgnore))); if(!bIgnore) break; } } #endif I.addItem(iCurOffset - iPosStart, new GR_XPItem(GRScriptType_Undefined)); } // add an extra record of type Void to allow for calculation of // length of the last item // iLastOffset is the offset of the last valid character; the Void // offset is one beyond that I.addItem(iLastOffset - iPosStart + 1, new GR_XPItem(GRScriptType_Void)); return true; }
/*! Insert a span of text into the document \param b Buffer containing UCS text to insert Uses appropriate function for clipboard or file */ bool IE_Imp_Text::_insertSpan(UT_GrowBuf &b) { UT_uint32 iLength = b.getLength(); const UT_UCS4Char * pData = (const UT_UCS4Char *)b.getPointer(0); // handle block direction if needed ... if(pData && m_bBlockDirectionPending) { const UT_UCS4Char * p = pData; // we look for the first strong character for(UT_uint32 i = 0; i < iLength; i++, p++) { UT_BidiCharType type = UT_bidiGetCharType(*p); if(UT_BIDI_IS_STRONG(type)) { m_bBlockDirectionPending = false; // set 'dom-dir' property of the block ... const gchar * propsArray[3]; propsArray[0] = "props"; propsArray[1] = NULL; propsArray[2] = NULL; UT_String props("dom-dir:"); if(UT_BIDI_IS_RTL(type)) props += "rtl;text-align:right"; else props += "ltr;text-align:left"; propsArray[1] = props.c_str(); // we need to modify the existing formatting ... if(m_pBlock == NULL) { PL_StruxDocHandle sdh = NULL; if(getDoc()->getStruxOfTypeFromPosition(getDocPos(), PTX_Block,&sdh)) { m_pBlock = static_cast<pf_Frag_Strux *>(const_cast<void *>(sdh)); } } appendStruxFmt(m_pBlock, static_cast<const gchar **>(&propsArray[0])); // if this is the first data in the block and the first // character is LRM or RLM followed by a strong character, // then we will remove it if(m_bFirstBlockData && i==0 && iLength > 1 && (*p == UCS_LRM || *p == UCS_RLM)) { UT_BidiCharType next_type = UT_bidiGetCharType(*(p+1)); if(UT_BIDI_IS_STRONG(next_type)) { pData++; iLength--; } } break; } } } bool bRes = appendSpan (pData, iLength); b.truncate(0); m_bFirstBlockData = false; return bRes; }
bool Text_Listener::populate(PL_StruxFmtHandle /*sfh*/, const PX_ChangeRecord * pcr) { switch (pcr->getType()) { case PX_ChangeRecord::PXT_InsertSpan: { const PX_ChangeRecord_Span * pcrs = static_cast<const PX_ChangeRecord_Span *>(pcr); PT_AttrPropIndex api = pcr->getIndexAP(); _handleDirMarker(api); PT_BufIndex bi = pcrs->getBufIndex(); const UT_UCS4Char * pData = m_pDocument->getPointer(bi); // first see if there is a pending marker (for block direction) // and handle it if(pData && m_eDirMarkerPending != DO_UNSET) { UT_UCS4Char cRLM = UCS_RLM; UT_UCS4Char cLRM = UCS_LRM; UT_BidiCharType type = UT_bidiGetCharType(*pData); if(m_eDirMarkerPending == DO_RTL && type == UT_BIDI_RTL) { //the override corresponds to the marker, no marker needed m_eDirMarkerPending = DO_UNSET; } else if(m_eDirMarkerPending == DO_RTL && type == UT_BIDI_LTR) { //need to issue marker _outputData(&cRLM, 1); m_eDirMarkerPending = DO_UNSET; } else if(m_eDirMarkerPending == DO_LTR && type == UT_BIDI_LTR) { //the override corresponds to the marker, no marker needed m_eDirMarkerPending = DO_UNSET; } else if(m_eDirMarkerPending == DO_LTR && type == UT_BIDI_RTL) { //need to issue marker _outputData(&cLRM, 1); m_eDirMarkerPending = DO_UNSET; } } _outputData(pData,pcrs->getLength()); return true; } case PX_ChangeRecord::PXT_InsertObject: { // TODO decide how to indicate objects in text output. const PX_ChangeRecord_Object * pcro = static_cast<const PX_ChangeRecord_Object *>(pcr); //PT_AttrPropIndex api = pcr->getIndexAP(); fd_Field* field; switch (pcro->getObjectType()) { case PTO_Image: return true; case PTO_Field: // Lossy, but pretty much unavoidable field = pcro->getField(); UT_return_val_if_fail(field, false); m_pie->populateFields (); if(field->getValue() != NULL) m_pie->write(field->getValue()); return true; case PTO_Bookmark: return true; case PTO_Hyperlink: return true; case PTO_Embed: return true; case PTO_Math: return true; case PTO_Annotation: return true; case PTO_RDFAnchor: return true; default: UT_ASSERT_HARMLESS(UT_TODO); return true; } } case PX_ChangeRecord::PXT_InsertFmtMark: return true; default: UT_ASSERT_HARMLESS(0); return false; } }