/*---------------------------------------------------------------------- ChangePRule A specific PRule will be created or modified by the user for a given element. (pre-event) ----------------------------------------------------------------------*/ ThotBool ChangePRule (NotifyPresentation *event) { ElementType elType, parentType; Element el, span, body, parent; PRule presRule; Document doc; SSchema HTMLschema; AttributeType attrType; Attribute attr; #define STYLELEN 1000 char buffer[15], *name; int presType; int w, h, unit, value; ThotBool ret; el = event->element; doc = event->document; presType = event->pRuleType; presRule = event->pRule; elType = TtaGetElementType (el); parentType.ElSSchema = NULL; parentType.ElTypeNum = 0; ret = FALSE; HTMLschema = TtaGetSSchema ("HTML", doc); if (event->event != TtePRuleDelete) { /* if a style property is being changed, we have its new value in the PRule to set the corresponding style attribute, but if its a change in the geometry, we have the old value to see the difference */ if (presType == PRHeight || presType == PRWidth || presType == PRVertPos || presType == PRHorizPos) /* Store the new value into the presentation rule before it is potentially copied by MovePRule */ TtaSetPRuleValue (el, presRule, event->value, doc); if (elType.ElSSchema != HTMLschema) /* it's not an HTML element */ { name = TtaGetSSchemaName (elType.ElSSchema); if (!strcmp (name, "TextFile")) { /* should generate the CSS rule */ SetStyleString (doc, el, presRule); ret = TRUE; /* don't let Thot perform normal operation */ } else if ((!strcmp (name, "MathML") || !strcmp (name, "SVG")) && TtaGetConstruct (el) == ConstructBasicType) /* it's a basic type. Move the PRule to the parent element */ { el = TtaGetParent (el); MovePRule (presRule, event->element, el, doc, FALSE); ret = TRUE; /* don't let Thot perform normal operation */ } } else /* it's an HTML element */ /* if it's a rule on the root or HTML element, move it to BODY element: the HTML DTD does not allow a style attribute on the HTML element */ { if (elType.ElTypeNum == HTML_EL_HTML || elType.ElTypeNum == HTML_EL_Document) { elType.ElTypeNum = HTML_EL_BODY; body = TtaSearchTypedElement (elType, SearchInTree, el); if (body) { MovePRule (presRule, el, body, doc, TRUE); ret = TRUE; /* don't let Thot perform normal operation */ /* the style attribute must be created on the BODY element */ el = body; } } else { /* style is not allowed in Head section */ if (elType.ElTypeNum == HTML_EL_HEAD) parent = el; else { parentType.ElSSchema = elType.ElSSchema; parentType.ElTypeNum = HTML_EL_HEAD; parent = TtaGetTypedAncestor (el, parentType); } if (parent != NULL) { TtaSetStatus (doc, 1, TtaGetMessage (AMAYA, AM_INVALID_TARGET), NULL); return (TRUE); /* don't let Thot perform normal operation */ } else { /* style is not allowed in MAP */ if (elType.ElTypeNum == HTML_EL_MAP) parent = el; else { parentType.ElTypeNum = HTML_EL_MAP; parent = TtaGetTypedAncestor (el, parentType); } if (parent != NULL) { TtaSetStatus (doc, 1, TtaGetMessage (AMAYA, AM_INVALID_TARGET), NULL); return (TRUE); } } if ((presType == PRWidth || presType == PRHeight) && elType.ElSSchema == HTMLschema && elType.ElTypeNum == HTML_EL_Pseudo_paragraph) { /* check if the rule has to be moved to a cell */ parent = TtaGetParent (el); parentType = TtaGetElementType (parent); if (parentType.ElSSchema == HTMLschema && (parentType.ElTypeNum == HTML_EL_Data_cell || parentType.ElTypeNum == HTML_EL_Heading_cell)) { el = parent; elType.ElTypeNum = parentType.ElTypeNum; } } if ((presType == PRWidth || presType == PRHeight) && elType.ElSSchema == HTMLschema && (elType.ElTypeNum == HTML_EL_PICTURE_UNIT || elType.ElTypeNum == HTML_EL_Table_ || elType.ElTypeNum == HTML_EL_Data_cell || elType.ElTypeNum == HTML_EL_Heading_cell || elType.ElTypeNum == HTML_EL_Object || elType.ElTypeNum == HTML_EL_Applet)) { /* store information in Width or Height attribute */ if (elType.ElTypeNum == HTML_EL_PICTURE_UNIT) { el = TtaGetParent (el); TtaGiveBoxSize (el, doc, 1, UnPixel, &w, &h); } else { w = -1; h = -1; } attrType.AttrSSchema = HTMLschema; unit = TtaGetPRuleUnit (presRule); if (presType == PRWidth) { /* the new value is the old one plus the delta */ //TtaGiveBoxSize (el, doc, 1, (TypeUnit)unit, &value, &i); value = event->value; sprintf (buffer, "%d", value); attrType.AttrTypeNum = HTML_ATTR_Width__; attr = TtaGetAttribute (el, attrType); if (attr == NULL) { attr = TtaNewAttribute (attrType); TtaAttachAttribute (el, attr, doc); TtaSetAttributeText (attr, buffer, el, doc); TtaRegisterAttributeCreate (attr, el, doc); } else { TtaRegisterAttributeReplace (attr, el, doc); TtaSetAttributeText (attr, buffer, el, doc); } CreateAttrWidthPercentPxl (buffer, el, doc, w); } else { /* the new value is the old one plus the delta */ //TtaGiveBoxSize (el, doc, 1, (TypeUnit)unit, &i, &value); value = event->value; sprintf (buffer, "%d", value); attrType.AttrTypeNum = HTML_ATTR_Height_; attr = TtaGetAttribute (el, attrType); if (attr == NULL) { attr = TtaNewAttribute (attrType); TtaAttachAttribute (el, attr, doc); TtaSetAttributeText (attr, buffer, el, doc); TtaRegisterAttributeCreate (attr, el, doc); } else { TtaRegisterAttributeReplace (attr, el, doc); TtaSetAttributeText (attr, buffer, el, doc); } CreateAttrHeightPercentPxl (buffer, el, doc, h); } TtaSetDocumentModified (doc); return TRUE; /* don't let Thot perform normal operation */ } else if (IsCharacterLevelElement (el) && (presType == PRIndent || presType == PRLineSpacing || presType == PRAdjust || presType == PRHyphenate)) /* if the rule is a Format rule applied to a character-level element, move it to the first enclosing non character-level element */ { do el = TtaGetParent (el); while (el && IsCharacterLevelElement (el)); /* if the PRule is on a Pseudo-Paragraph, move it to the enclosing element */ elType = TtaGetElementType (el); if (elType.ElSSchema == HTMLschema && elType.ElTypeNum == HTML_EL_Pseudo_paragraph) el = GetParentDiv (el, HTMLschema, doc); MovePRule (presRule, event->element, el, doc, TRUE); ret = TRUE; /* don't let Thot perform normal operation */ } else if (elType.ElTypeNum == HTML_EL_Pseudo_paragraph) /* if the PRule is on a Pseudo-Paragraph, move it to the enclosing element */ { el = GetParentDiv (el, HTMLschema, doc); MovePRule (presRule, event->element, el, doc, TRUE); ret = TRUE; /* don't let Thot perform normal operation */ } else if (MakeASpan (el, &span, doc, presRule)) /* if it is a new PRule on a text string, create a SPAN element that encloses this text string and move the PRule to that SPAN element */ { el = span; ret = TRUE; /* don't let Thot perform normal operation */ } } } } /* set the Style_ attribute ? */ if (DocumentTypes[doc] == docHTML || DocumentTypes[doc] == docMath || DocumentTypes[doc] == docSVG) SetStyleAttribute (doc, el); TtaSetDocumentModified (doc); return (ret); }
/*----------------------------------------------------------------------- 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)); }