Index: src/text/fmt/xp/fp_Run.h =================================================================== --- src/text/fmt/xp/fp_Run.h (revision 31276) +++ src/text/fmt/xp/fp_Run.h (working copy) @@ -744,7 +744,8 @@ virtual FP_HYPERLINK_TYPE getHyperlinkType(void) const { return HYPERLINK_NORMAL;} bool isStartOfHyperlink() const {return m_bIsStart;}; const gchar * getTarget() const {return static_cast(m_pTarget);}; - + const gchar * getTitle() const {return static_cast(m_pTitle);}; + virtual bool canBreakAfter(void) const; virtual bool canBreakBefore(void) const; @@ -780,11 +781,13 @@ virtual bool _letPointPass(void) const; virtual bool _canContainPoint(void) const; virtual bool _deleteFollowingIfAtInsPoint() const; - void _setTarget( const gchar * pTarget ); + void _setTarget( const gchar * pTarget ); + void _setTitle( const gchar * pTitle ); void _setTargetFromAPAttribute( const gchar* pAttrName ); - + void _setTitleFromAPAttribute( const gchar* pAttrName ); bool m_bIsStart; gchar * m_pTarget; + gchar * m_pTitle; }; Index: src/text/fmt/xp/fv_View.h =================================================================== --- src/text/fmt/xp/fv_View.h (revision 31276) +++ src/text/fmt/xp/fv_View.h (working copy) @@ -290,7 +290,7 @@ UT_Error cmdInsertField(const char* szName, const gchar ** extra_attrs = NULL, const gchar ** extra_props = NULL); UT_Error cmdInsertBookmark(const char* szName); UT_Error cmdDeleteBookmark(const char* szName); - UT_Error cmdInsertHyperlink(const char* szName); + UT_Error cmdInsertHyperlink(const char* szName, const char* szTitle = NULL); UT_Error cmdInsertXMLID(const std::string& name); UT_Error cmdDeleteXMLID(const std::string& name); Index: src/text/fmt/xp/fp_Run.cpp =================================================================== --- src/text/fmt/xp/fp_Run.cpp (revision 31276) +++ src/text/fmt/xp/fp_Run.cpp (working copy) @@ -3052,6 +3052,7 @@ : fp_Run(pBL, iOffsetFirst, 1, FPRUN_HYPERLINK) , m_bIsStart(false) , m_pTarget(NULL) + , m_pTitle(NULL) { _setLength(1); _setDirty(false); @@ -3061,13 +3062,15 @@ UT_ASSERT((pBL)); _setDirection(UT_BIDI_WS); - _setTargetFromAPAttribute( "xlink:href" ); + _setTargetFromAPAttribute( "xlink:href"); + _setTitleFromAPAttribute( "xlink:title"); } fp_HyperlinkRun::~fp_HyperlinkRun() { DELETEPV(m_pTarget); + DELETEPV(m_pTitle); } void fp_HyperlinkRun::_lookupProperties(const PP_AttrProp * /*pSpanAP*/, @@ -3147,7 +3150,7 @@ // is to a potentially volatile location if(bFound) { - _setTarget( pTarget ); + _setTarget( pTarget ); m_bIsStart = true; //if this is a start of the hyperlink, we set m_pHyperlink to this, //so that when a run gets inserted after this one, its m_pHyperlink is @@ -3162,6 +3165,20 @@ } } +void fp_HyperlinkRun::_setTitleFromAPAttribute( const gchar* pAttrName ) +{ + const PP_AttrProp * pAP = NULL; + getSpanAP(pAP); + + const gchar *pTitle; + if (pAP->getAttribute(pAttrName, pTitle)) + { + _setTitle(pTitle); + } else + { + m_pTitle = NULL; + } +} void fp_HyperlinkRun::_setTarget( const gchar * pTarget ) { @@ -3171,7 +3188,15 @@ strncpy(m_pTarget, pTarget, iTargetLen + 1); } +void fp_HyperlinkRun::_setTitle( const gchar * pTitle ) +{ + DELETEPV(m_pTitle); + UT_uint32 iTitleLen = strlen(pTitle); + m_pTitle = new gchar [iTitleLen + 1]; + strncpy(m_pTitle, pTitle, iTitleLen + 1); +} + ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// fp_EndOfParagraphRun::fp_EndOfParagraphRun(fl_BlockLayout* pBL, Index: src/text/fmt/xp/fv_View_cmd.cpp =================================================================== --- src/text/fmt/xp/fv_View_cmd.cpp (revision 31276) +++ src/text/fmt/xp/fv_View_cmd.cpp (working copy) @@ -5000,7 +5000,7 @@ return pAL; } -UT_Error FV_View::cmdInsertHyperlink(const char * szName) +UT_Error FV_View::cmdInsertHyperlink(const char * szName, const char * szTitle) { bool bRet; @@ -5111,8 +5111,7 @@ { return false; } - gchar * pAttr[4]; - + UT_uint32 target_len = strlen(szName); gchar * target = new gchar[ target_len+ 2]; @@ -5125,12 +5124,36 @@ target[0] = '#'; strncpy(target + 1, static_cast(szName), target_len + 1); } + + gchar * title; + int attrCount = 0; + + if (szTitle != NULL) + { + UT_uint32 title_len = strlen(szTitle); + title = new gchar[ title_len + 1]; + strncpy(title, static_cast(szTitle), title_len); + attrCount = 6; + } else + { + attrCount = 4; + title = NULL; + } + + gchar * pAttr[attrCount]; + int attr = 0; gchar target_l[] = "xlink:href"; - pAttr [0] = &target_l[0]; - pAttr [1] = &target[0]; - pAttr [2] = 0; - pAttr [3] = 0; + gchar title_l[] = "xlink:title"; + pAttr [attr++] = &target_l[0]; + pAttr [attr++] = &target[0]; + if ((szTitle != NULL) && (strlen(szTitle) > 0)) + { + pAttr [attr++] = &title_l[0]; + pAttr [attr++] = &title[0]; + } + pAttr[attr++] = 0; + pAttr[attr++] = 0; UT_DEBUGMSG(("fv_View::cmdInsertHyperlink: target \"%s\"\n", target)); @@ -5159,6 +5182,11 @@ } delete [] target; + + if (szTitle != NULL) + { + delete [] title; + } // Signal piceTable is stable again _restorePieceTableState(); Index: src/wp/ap/gtk/ap_UnixDialog_InsertHyperlink.h =================================================================== --- src/wp/ap/gtk/ap_UnixDialog_InsertHyperlink.h (revision 31276) +++ src/wp/ap/gtk/ap_UnixDialog_InsertHyperlink.h (working copy) @@ -65,6 +65,7 @@ //GtkWidget * m_comboHyperlink; GtkWidget * m_clist; GtkWidget * m_swindow; + GtkWidget * m_titleEntry; gint m_iRow; }; Index: src/wp/ap/gtk/ap_UnixDialog_InsertHyperlink.cpp =================================================================== --- src/wp/ap/gtk/ap_UnixDialog_InsertHyperlink.cpp (revision 31291) +++ src/wp/ap/gtk/ap_UnixDialog_InsertHyperlink.cpp (working copy) @@ -56,6 +56,7 @@ // m_comboEntry(0), m_clist(0), m_swindow(0), + m_titleEntry(0), m_iRow(-1) { @@ -113,10 +114,12 @@ UT_ASSERT(m_windowMain); // get the bookmark name, if any (return cancel if no name given) const gchar * res = gtk_entry_get_text(GTK_ENTRY(m_entry)); + const gchar * title = gtk_entry_get_text(GTK_ENTRY(m_titleEntry)); if(res && *res) { setAnswer(AP_Dialog_InsertHyperlink::a_OK); setHyperlink(static_cast(res)); + setHyperlinkTitle(static_cast(title)); } else { @@ -134,17 +137,18 @@ const XAP_StringSet * pSS = m_pApp->getStringSet(); GtkWidget *label1; + GtkWidget *label2; UT_UTF8String s; pSS->getValueUTF8(AP_STRING_ID_DLG_InsertHyperlink_Msg,s); label1 = gtk_label_new (s.utf8_str()); gtk_widget_show (label1); gtk_box_pack_start (GTK_BOX (vbox2), label1, TRUE, FALSE, 3); - + m_entry = gtk_entry_new(); gtk_box_pack_start (GTK_BOX (vbox2), m_entry, FALSE, FALSE, 0); gtk_widget_show(m_entry); - + const gchar * hyperlink = getHyperlink(); if (hyperlink && *hyperlink) @@ -196,6 +200,23 @@ } gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(m_swindow),m_clist); + + + pSS->getValueUTF8(AP_STRING_ID_DLG_InsertHyperlink_TitleLabel, s); + label2 = gtk_label_new(s.utf8_str()); + gtk_widget_show(label2); + gtk_box_pack_start(GTK_BOX(vbox2), label2, TRUE, TRUE, 3); + + m_titleEntry = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(vbox2), m_titleEntry, FALSE, FALSE, 0); + gtk_widget_show(m_titleEntry); + + const gchar * hyperlinkTitle = getHyperlinkTitle(); + + if (hyperlinkTitle && *hyperlinkTitle) + { + gtk_entry_set_text(GTK_ENTRY(m_titleEntry), hyperlinkTitle); + } } GtkWidget* AP_UnixDialog_InsertHyperlink::_constructWindow(void) Index: src/wp/ap/xp/ap_Dialog_InsertHyperlink.h =================================================================== --- src/wp/ap/xp/ap_Dialog_InsertHyperlink.h (revision 31276) +++ src/wp/ap/xp/ap_Dialog_InsertHyperlink.h (working copy) @@ -44,7 +44,9 @@ UT_uint32 getExistingBookmarksCount() const; const std::string & getNthExistingBookmark(UT_uint32 n) const; const gchar * getHyperlink() const; + const gchar * getHyperlinkTitle() const; void setHyperlink(const gchar * link); + void setHyperlinkTitle(const gchar * title); void setDoc(FV_View * pView); private: @@ -53,6 +55,7 @@ AP_Dialog_InsertHyperlink::tAnswer m_answer; gchar * m_pHyperlink; + gchar * m_pHyperlinkTitle; }; #endif /* AP_DIALOG_TOGGLECASE_H */ Index: src/wp/ap/xp/ap_Dialog_InsertHyperlink.cpp =================================================================== --- src/wp/ap/xp/ap_Dialog_InsertHyperlink.cpp (revision 31276) +++ src/wp/ap/xp/ap_Dialog_InsertHyperlink.cpp (working copy) @@ -24,7 +24,10 @@ AP_Dialog_InsertHyperlink::AP_Dialog_InsertHyperlink(XAP_DialogFactory * pDlgFactory, XAP_Dialog_Id id) - : XAP_Dialog_NonPersistent(pDlgFactory,id, "interface/dialoghyperlink"), m_answer(a_CANCEL), m_pHyperlink(0) + : XAP_Dialog_NonPersistent(pDlgFactory,id, "interface/dialoghyperlink"), + m_answer(a_CANCEL), + m_pHyperlink(0), + m_pHyperlinkTitle(0) { } @@ -60,6 +63,11 @@ return (const gchar *)m_pHyperlink; } +const gchar * AP_Dialog_InsertHyperlink::getHyperlinkTitle() const +{ + return (const gchar*)m_pHyperlinkTitle; +} + void AP_Dialog_InsertHyperlink::setHyperlink(const gchar * link) { DELETEPV(m_pHyperlink); @@ -68,6 +76,14 @@ strncpy(m_pHyperlink, link, len + 1); } +void AP_Dialog_InsertHyperlink::setHyperlinkTitle(const gchar * title) +{ + DELETEPV(m_pHyperlinkTitle); + UT_uint32 len = strlen(title); + m_pHyperlinkTitle = new gchar [len+1]; + strncpy(m_pHyperlinkTitle, title, len + 1); +} + void AP_Dialog_InsertHyperlink::setDoc(FV_View * pView) { m_pView = pView; Index: src/wp/ap/xp/ap_EditMethods.cpp =================================================================== --- src/wp/ap/xp/ap_EditMethods.cpp (revision 31276) +++ src/wp/ap/xp/ap_EditMethods.cpp (working copy) @@ -6165,6 +6165,7 @@ = static_cast(pDialogFactory->requestDialog(AP_DIALOG_ID_INSERTHYPERLINK)); UT_return_val_if_fail(pDialog, false); UT_UTF8String sTarget; + UT_UTF8String sTitle; bool bEdit = false; PT_DocPosition pos1 = 0; PT_DocPosition pos2 = 0; @@ -6180,6 +6181,7 @@ } bEdit = true; sTarget = pHRun->getTarget(); + sTitle = pHRun->getTitle(); fl_BlockLayout * pBL = pHRun->getBlock(); fp_Run * pRun = NULL; if(pHRun->isStartOfHyperlink()) @@ -6212,6 +6214,7 @@ // Set the target // pDialog->setHyperlink(sTarget.utf8_str()); + pDialog->setHyperlinkTitle(sTitle.utf8_str()); } pDialog->runModal(pFrame); @@ -6234,13 +6237,15 @@ // Select our range // pView->cmdSelect(pos1,pos2); - pView->cmdInsertHyperlink(pDialog->getHyperlink()); + pView->cmdInsertHyperlink(pDialog->getHyperlink(), + pDialog->getHyperlinkTitle()); pView->cmdUnselectSelection(); pView->setPoint(posOrig); } else { - pView->cmdInsertHyperlink(pDialog->getHyperlink()); + pView->cmdInsertHyperlink(pDialog->getHyperlink(), + pDialog->getHyperlinkTitle()); } } else Index: src/wp/ap/xp/ap_String_Id.h =================================================================== --- src/wp/ap/xp/ap_String_Id.h (revision 31276) +++ src/wp/ap/xp/ap_String_Id.h (working copy) @@ -841,6 +841,7 @@ dcl(DLG_InsertHyperlink_Title, "Insert Hyperlink") dcl(DLG_InsertHyperlink_Msg, "Select a target bookmark from the list.") +dcl(DLG_InsertHyperlink_TitleLabel, "Type a title for the hyperlink") /* Mark revisions dialog */ dcl(DLG_MarkRevisions_Title, "Mark Revisions")