/*----------------------------------------------------------------------- LINK_AddLinkToSource Adds to a source document, an annotation link pointing to the annotation. Returns TRUE if the annotation could be attached and FALSE if the annotation became orphan. -----------------------------------------------------------------------*/ ThotBool LINK_AddLinkToSource (Document source_doc, AnnotMeta *annot) { ElementType elType, firstElType; Element el, first, anchor, child_el; AttributeType attrType; Attribute attr; SSchema XLinkSchema; char *docSchemaName, *CharNum; int c1, cN, Char, line, length; int length_el, line_el, count_child; ThotBool check_mode; /*annot_user = GetAnnotUser ();*/ if (DocumentTypes[source_doc] != docText) { if (annot->xptr) { XPointerContextPtr ctx; nodeInfo *node; ctx = XPointer_parse (source_doc, annot->xptr); node = XPointer_nodeStart (ctx); first = XPointer_el (node); c1 = XPointer_startC (node); cN = XPointer_endC (node); XPointer_free (ctx); } else { first = TtaSearchElementByLabel(annot->labf, TtaGetRootElement (source_doc)); c1 = annot->c1; cN = annot->cl; } } else { first = SearchTextattribute (source_doc, annot->xptr); line = TtaGetElementLineNumber (first); CharNum = strstr (annot->xptr, "="); CharNum = &CharNum[1]; Char = atoi (CharNum); c1 = CharNum_IN_Line (source_doc, Char); if(c1 == -1) c1 = 0; cN = c1 - 1; length = TtaGetElementVolume (first); el = TtaGetMainRoot (source_doc); elType = TtaGetElementType (el); elType.ElTypeNum = TextFile_EL_Line_; el = TtaSearchTypedElement (elType, SearchForward, el); for (line_el=1; line_el < line; line_el++) TtaNextSibling (&el); child_el = TtaGetFirstChild(el); length_el = TtaGetElementVolume(child_el); count_child = 1; while(child_el != first) { if(count_child % 3 != 2) { c1 -= length_el; cN = c1 - 1; } count_child++; TtaNextSibling(&child_el); length_el = TtaGetElementVolume(child_el); } } if (first) /* we found it */ annot->is_orphan = FALSE; else { /* it's an orphan annotation */ first = TtaGetRootElement (source_doc); annot->is_orphan = TRUE; } #ifdef ANNOT_ON_ANNOT /* don't add the Xlink element for replies */ if (annot->inReplyTo) return (!(annot->is_orphan)); #endif /* ANNOT_ON_ANNOT */ /* Verify that the annotates property really does point to this document and discard if not (or if there is no annotates property). */ if (!Annot_isSameURL (annot->source_url, DocumentURLs[source_doc])) return TRUE; /* treat this as not orphanned */ /* create the anotation element */ XLinkSchema = GetXLinkSSchema (source_doc); elType.ElSSchema = XLinkSchema; elType.ElTypeNum = XLink_EL_XLink; anchor = TtaNewTree (source_doc, elType, ""); /* ** insert the anchor in the document tree */ firstElType = TtaGetElementType (first); docSchemaName = TtaGetSSchemaName (firstElType.ElSSchema); check_mode = TtaGetStructureChecking (source_doc); TtaSetStructureChecking (FALSE, source_doc); /* @@ JK: this doesn't seem useful anymore */ /* is the user trying to annotate an annotation? */ el = TtaGetTypedAncestor (first, elType); if (el) { /* yes, so we will add the anchor one element before in the struct tree */ TtaInsertSibling (anchor, el, TRUE, source_doc); } else if (!strcmp (docSchemaName, "MathML")) { /* An annotation on a MathMl structure. We backtrace the tree until we find the Math root element and then add the annotation as its first child. */ el = first; while (el) { elType = TtaGetElementType (el); if (elType.ElTypeNum == MathML_EL_MathML) break; el = TtaGetParent (el); } TtaInsertFirstChild (&anchor, el, source_doc); } else if (!strcmp (docSchemaName, "SVG")) { /* An annotation on an SVG structure. We backtrace the tree until we find the SVG root element and then add the annotation as its first child. */ el = first; while (el) { elType = TtaGetElementType (el); if (elType.ElTypeNum == SVG_EL_SVG) break; el = TtaGetParent (el); } TtaInsertFirstChild (&anchor, el, source_doc); } else if (!strcmp (docSchemaName, "HTML") || !strcmp (docSchemaName, "HTML5")) { /* it's an HTML document */ el = first; elType = TtaGetElementType (el); if (elType.ElTypeNum == HTML_EL_HTML || elType.ElTypeNum == HTML_EL_HEAD || elType.ElTypeNum == HTML_EL_TITLE || elType.ElTypeNum == HTML_EL_BASE || elType.ElTypeNum == HTML_EL_META || elType.ElTypeNum == HTML_EL_SCRIPT_ || elType.ElTypeNum == HTML_EL_STYLE_ || elType.ElTypeNum == HTML_EL_BODY) { /* we can't put the annotation icon here, so let's find the first child of body and add it to it */ el = TtaGetRootElement (source_doc); elType.ElTypeNum = HTML_EL_BODY; el = TtaSearchTypedElement (elType, SearchForward, el); if (el) /* add it to the beginning */ TtaInsertFirstChild (&anchor, el, source_doc); else /* we add it where it was declared, although we may not see it at all */ TtaInsertSibling (anchor, first, TRUE, source_doc); } else if (elType.ElTypeNum == HTML_EL_Unnumbered_List || elType.ElTypeNum == HTML_EL_Numbered_List || elType.ElTypeNum == HTML_EL_List_Item || elType.ElTypeNum == HTML_EL_Definition) { /* for lists, we attach the A-element to the first pseudo paragraph. The .S forbids doing so elsewhere */ elType.ElTypeNum = HTML_EL_Pseudo_paragraph; el = TtaSearchTypedElement (elType, SearchForward, el); if (el) /* add it to the beginning */ TtaInsertFirstChild (&anchor, el, source_doc); else /* we add it where it was declared, although we may not see it at all */ TtaInsertSibling (anchor, first, TRUE, source_doc); } else if (elType.ElTypeNum == HTML_EL_PICTURE_UNIT) { /* add it before the image */ TtaInsertSibling (anchor, first, TRUE, source_doc); } else if (elType.ElTypeNum == HTML_EL_Table_ || elType.ElTypeNum == HTML_EL_thead || elType.ElTypeNum == HTML_EL_tbody || elType.ElTypeNum == HTML_EL_tfoot ) { /* add the A-element before the table */ el = first; elType = TtaGetElementType (el); while (elType.ElTypeNum != HTML_EL_Table_) { el = TtaGetParent (el); elType = TtaGetElementType (el); } /* add it before the image */ TtaInsertSibling (anchor, el, TRUE, source_doc); } else if (elType.ElTypeNum == HTML_EL_Table_row) { /* add the A-element to the first cell */ el = first; while ((el = TtaGetFirstChild (el))) { elType = TtaGetElementType (el); /* the elements where we can add the A-element */ if (elType.ElTypeNum == HTML_EL_Table_cell || elType.ElTypeNum == HTML_EL_Data_cell || elType.ElTypeNum == HTML_EL_Heading_cell) break; } TtaInsertFirstChild (&anchor, el, source_doc); } else { if (c1 == 0) { /* add it as the first child of the element */ TtaInsertFirstChild (&anchor, el, source_doc); } else if (c1 == 1) { /* add it to the beginning of the element */ TtaInsertSibling (anchor, first, TRUE, source_doc); } else if (c1 > 1) { /* split the text */ int len; len = TtaGetTextLength (first); if (cN > len && c1 == cN) /* add it to the end (a caret) */ TtaInsertSibling (anchor, first, FALSE, source_doc); else { /* add it in the middle */ TtaSplitText (first, c1, source_doc); TtaNextSibling (&first); TtaInsertSibling (anchor, first, TRUE, source_doc); } } } } else if (DocumentTypes[source_doc] == docXml) { /* An annotation on a generic XML structure. We don't do anything special. */ el = first; if (c1 == 0) { /* add it as the first child of the element */ TtaInsertFirstChild (&anchor, el, source_doc); } else if (c1 == 1) { /* add it to the beginning of the element */ TtaInsertSibling (anchor, first, TRUE, source_doc); } else if (c1 > 1) { /* split the text */ int len; len = TtaGetTextLength (first); if (cN > len && c1 == cN) /* add it to the end (a caret) */ TtaInsertSibling (anchor, first, FALSE, source_doc); else { /* add it in the middle */ TtaSplitText (first, c1, source_doc); TtaNextSibling (&first); TtaInsertSibling (anchor, first, TRUE, source_doc); } } } else if (!strcmp (docSchemaName, "TextFile")) { el = first; elType = TtaGetElementType (el); elType.ElTypeNum = TextFile_EL_Line_; el = TtaSearchTypedElement (elType, SearchForward, el); if (c1 == 0) { /* add it as the first child of the element */ TtaInsertFirstChild (&anchor, el, source_doc); } else if (c1 == 1) { /* add it to the beginning of the element */ TtaInsertSibling (anchor, first, TRUE, source_doc); } else if (c1 > 1) { int len; len = TtaGetElementVolume(first); if (c1 > len) /* add it to the end (a caret)*/ TtaInsertSibling (anchor, first, FALSE, source_doc); else { /* add it in the middle */ TtaSplitText (first, c1, source_doc); TtaNextSibling (&first); TtaSplitText (first, 2,source_doc); TtaInsertSibling (anchor, first, TRUE, source_doc); TtaSelectString(source_doc,first,1,0); } } } TtaSetStructureChecking (check_mode, source_doc); /* add the Xlink attribute */ SetXLinkTypeSimple (anchor, source_doc, FALSE); /* ** add the other attributes */ attrType.AttrSSchema = XLinkSchema; #ifdef ANNOT_ON_ANNOT /* @@ JK: Systematically hiding the thread annotations */ if (annot->inReplyTo) { attrType.AttrTypeNum = XLink_ATTR_AnnotIsHidden; attr = TtaNewAttribute (attrType); TtaAttachAttribute (anchor, attr, source_doc); } #endif /* ANNOT_ON_ANNOT */ /* add the annotation icon */ if (!annot->is_orphan) attrType.AttrTypeNum = XLink_ATTR_AnnotIcon1; else attrType.AttrTypeNum = XLink_ATTR_AnnotOrphIcon; attr = TtaNewAttribute (attrType); TtaAttachAttribute (anchor, attr, source_doc); /* add an HREF attribute pointing to the annotation */ attrType.AttrTypeNum = XLink_ATTR_href_; attr = TtaNewAttribute (attrType); TtaAttachAttribute (anchor, attr, source_doc); TtaSetAttributeText (attr, annot->body_url, anchor, source_doc); /* add a ID attribute so that the annotation doc can point back to the source of the annotation link */ attrType.AttrTypeNum = XLink_ATTR_id; attr = TtaNewAttribute (attrType); TtaAttachAttribute (anchor, attr, source_doc); /* set the ID value (anchor endpoint) */ TtaSetAttributeText (attr, annot->name, anchor, source_doc); /* add the annotation icon */ LINK_AddAnnotIcon (source_doc, anchor, annot); return (!(annot->is_orphan)); }
/*---------------------------------------------------------------------- GetStyleContents returns a buffer that contains the whole text of the style element el. It returns NULL if the element is empty. The buffer should be freed by the caller. ----------------------------------------------------------------------*/ char *GetStyleContents (Element el) { ElementType elType; Element text; Attribute attr; AttributeType attrType; CSSmedia media = CSS_ALL; Language lang; char *buffer, *name; int length, i, j; ThotBool loadcss; buffer = NULL; /* check if we have to load CSS */ TtaGetEnvBoolean ("LOAD_CSS", &loadcss); if (loadcss && el) { /* check the media type of the element */ elType = TtaGetElementType (el); attrType.AttrSSchema = elType.ElSSchema; name = TtaGetSSchemaName (attrType.AttrSSchema); if (!strcmp (name, "HTML")) attrType.AttrTypeNum = HTML_ATTR_media; #ifdef _SVG else if (!strcmp (name, "HTML")) attrType.AttrTypeNum = SVG_ATTR_media; #endif /* _SVG */ else attrType.AttrTypeNum = 0; if (attrType.AttrTypeNum) { attr = TtaGetAttribute (el, attrType); if (attr) { length = TtaGetTextAttributeLength (attr); name = (char *)TtaGetMemory (length + 1); TtaGiveTextAttributeValue (attr, name, &length); media = CheckMediaCSS (name); TtaFreeMemory (name); } } /* get enough space to store UTF-8 characters */ length = TtaGetElementVolume (el) * 6 + 1; if ((media == CSS_ALL || media == CSS_SCREEN) && length > 1) { /* get the length of the included text */ buffer = (char *)TtaGetMemory (length); /* fill the buffer */ elType.ElTypeNum = 1 /* 1 = TEXT_UNIT element */; text = TtaSearchTypedElementInTree (elType, SearchForward, el, el); i = 0; while (text != NULL) { j = length - i; TtaGiveTextContent (text, (unsigned char *)&buffer[i], &j, &lang); i += TtaGetTextLength (text); text = TtaSearchTypedElementInTree (elType, SearchForward, el, text); } buffer[i] = EOS; } } return (buffer); }