Annotation of Amaya/amaya/MathMLbuilder.c, revision 1.176
1.1 cvs 1: /*
2: *
1.144 vatton 3: * (c) COPYRIGHT MIT and INRIA, 1996-2002
1.1 cvs 4: * Please first read the full copyright statement in file COPYRIGHT.
5: *
6: */
1.159 quint 7:
1.1 cvs 8: /*
9: * MathMLbuilder
10: *
11: * Author: V. Quint
12: */
13:
14: #define THOT_EXPORT extern
1.4 cvs 15: #include "amaya.h"
1.25 cvs 16: #include "css.h"
1.59 cvs 17: #include "html2thot_f.h"
1.133 cvs 18: #include "HTMLactions_f.h"
1.25 cvs 19: #include "MathML.h"
1.169 quint 20: #include "HTML.h"
1.25 cvs 21: #include "parser.h"
1.59 cvs 22: #include "styleparser_f.h"
23: #include "style.h"
24: #include "undo.h"
1.133 cvs 25: #include "Xml2thot_f.h"
1.109 cvs 26:
1.106 cvs 27: /* Define a pointer to let parser functions access the Math entity table */
28: extern XmlEntity *pMathEntityTable;
1.1 cvs 29:
30: #define MaxMsgLength 200
31:
1.12 cvs 32: #include "HTMLtable_f.h"
1.29 cvs 33: #include "Mathedit_f.h"
34: #include "styleparser_f.h"
35: #include "fetchXMLname_f.h"
1.1 cvs 36:
37: /*----------------------------------------------------------------------
1.170 quint 38: IsLargeOp
39: Return TRUE if character is listed as a largeop in the MathML 2.0
40: Operator dictionary (appendix F.5)
41: ----------------------------------------------------------------------*/
1.171 carcone 42: static ThotBool IsLargeOp (CHAR_T character, char script)
1.170 quint 43: {
44: /****** to be completed *****/
45: #ifdef _I18N_
46: if (character == 8721 || character == 8719) /* large Sigma or Pi */
47: #else
48: if ((script == 'G') &&
49: (character == 229 || character == 213)) /* large Sigma or Pi */
50: #endif
51: /* it's a large character */
52: return TRUE;
53: else
54: return FALSE;
55: }
56:
57: /*----------------------------------------------------------------------
58: IsStretchy
59: Return TRUE if character is listed as a stretchy operator in the MathML 2.0
60: Operator dictionary (appendix F.5)
61: ----------------------------------------------------------------------*/
1.171 carcone 62: static ThotBool IsStretchy (CHAR_T character, char script)
1.170 quint 63: {
64: /****** to be completed *****/
65: if ((
66: #ifndef _I18N_
67: (script == 'L') &&
68: #endif
69: (character == '(' || character == ')' ||
70: character == '[' || character == ']' ||
71: character == '{' || character == '}' ||
72: character == '|')) ||
73: (
74: /* test left and right angle brackets */
75: #ifdef _I18N_
76: (character == 9001 || character == 9002)
77: #else
78: (script == 'G') &&
79: (character == 225 || character == 241)
80: #endif
81: ))
82: return TRUE;
83: else
84: return FALSE;
85: }
86:
87: /*----------------------------------------------------------------------
1.1 cvs 88: MapMathMLAttribute
89: Search in the Attribute Mapping Table the entry for the
90: attribute of name Attr and returns the corresponding Thot attribute type.
91: ----------------------------------------------------------------------*/
1.120 cvs 92: void MapMathMLAttribute (char *attrName, AttributeType *attrType,
93: char *elementName, ThotBool *level, Document doc)
1.1 cvs 94: {
1.68 cvs 95: attrType->AttrSSchema = GetMathMLSSchema (doc);
1.170 quint 96: MapXMLAttribute (MATH_TYPE, attrName, elementName, level, doc,
97: &(attrType->AttrTypeNum));
1.1 cvs 98: }
99:
100: /*----------------------------------------------------------------------
101: MapMathMLAttributeValue
102: Search in the Attribute Value Mapping Table the entry for the attribute
103: ThotAtt and its value AttrVal. Returns the corresponding Thot value.
104: ----------------------------------------------------------------------*/
1.150 vatton 105: void MapMathMLAttributeValue (char *attVal, AttributeType attrType, int *value)
1.1 cvs 106: {
1.150 vatton 107: MapXMLAttributeValue (MATH_TYPE, attVal, attrType, value);
1.1 cvs 108: }
109:
110: /*----------------------------------------------------------------------
1.130 carcone 111: MathMLEntityCreated
112: ----------------------------------------------------------------------*/
113: void MathMLEntityCreated (unsigned char *entityValue, Language lang,
114: char *entityName, Document doc)
115: {
116: }
117:
118: /*----------------------------------------------------------------------
1.1 cvs 119: ElementNeedsPlaceholder
120: returns TRUE if element el needs a sibling placeholder.
121: ----------------------------------------------------------------------*/
1.18 cvs 122: ThotBool ElementNeedsPlaceholder (Element el)
1.1 cvs 123: {
124: ElementType elType;
1.138 cvs 125: Element child, parent, sibling;
1.18 cvs 126: ThotBool ret;
1.139 quint 127:
1.1 cvs 128: ret = FALSE;
129: elType = TtaGetElementType (el);
1.43 cvs 130: if (elType.ElTypeNum == MathML_EL_MS ||
1.39 cvs 131: elType.ElTypeNum == MathML_EL_MFRAC ||
1.54 cvs 132: elType.ElTypeNum == MathML_EL_BevelledMFRAC ||
1.39 cvs 133: elType.ElTypeNum == MathML_EL_MSQRT ||
134: elType.ElTypeNum == MathML_EL_MROOT ||
135: elType.ElTypeNum == MathML_EL_MSTYLE ||
136: elType.ElTypeNum == MathML_EL_MERROR ||
137: elType.ElTypeNum == MathML_EL_MPADDED ||
138: elType.ElTypeNum == MathML_EL_MPHANTOM ||
139: elType.ElTypeNum == MathML_EL_MFENCED ||
1.1 cvs 140: elType.ElTypeNum == MathML_EL_MF ||
141: elType.ElTypeNum == MathML_EL_MSUB ||
142: elType.ElTypeNum == MathML_EL_MSUP ||
1.39 cvs 143: elType.ElTypeNum == MathML_EL_MSUBSUP ||
1.1 cvs 144: elType.ElTypeNum == MathML_EL_MUNDER ||
145: elType.ElTypeNum == MathML_EL_MOVER ||
146: elType.ElTypeNum == MathML_EL_MUNDEROVER ||
1.28 cvs 147: elType.ElTypeNum == MathML_EL_MMULTISCRIPTS ||
1.39 cvs 148: elType.ElTypeNum == MathML_EL_MTABLE ||
149: elType.ElTypeNum == MathML_EL_MACTION)
1.1 cvs 150: ret = TRUE;
1.138 cvs 151: else if (elType.ElTypeNum == MathML_EL_MROW)
152: /* a mrow needs a place holder only if it's not the sole child of
153: an element such as Numerator, Denominator, RootBase, Index, etc. */
154: {
155: ret = TRUE;
156: sibling = el; TtaNextSibling (&sibling);
157: if (!sibling)
158: {
1.139 quint 159: sibling = el; TtaPreviousSibling (&sibling);
1.138 cvs 160: if (!sibling)
161: {
162: parent = TtaGetParent (el);
163: if (parent)
164: {
165: elType = TtaGetElementType (parent);
166: if (elType.ElTypeNum == MathML_EL_Numerator ||
167: elType.ElTypeNum == MathML_EL_Denominator ||
168: elType.ElTypeNum == MathML_EL_RootBase ||
169: elType.ElTypeNum == MathML_EL_Index ||
170: elType.ElTypeNum == MathML_EL_FencedExpression ||
171: elType.ElTypeNum == MathML_EL_Base ||
172: elType.ElTypeNum == MathML_EL_Subscript ||
173: elType.ElTypeNum == MathML_EL_Superscript ||
174: elType.ElTypeNum == MathML_EL_UnderOverBase ||
175: elType.ElTypeNum == MathML_EL_Underscript ||
176: elType.ElTypeNum == MathML_EL_Overscript ||
177: elType.ElTypeNum == MathML_EL_MultiscriptBase ||
178: elType.ElTypeNum == MathML_EL_MSubscript ||
179: elType.ElTypeNum == MathML_EL_MSuperscript)
180: ret = FALSE;
181: }
182: }
183: }
184: }
1.158 quint 185: else if (elType.ElTypeNum == MathML_EL_MO ||
186: elType.ElTypeNum == MathML_EL_OpeningFence ||
187: elType.ElTypeNum == MathML_EL_ClosingFence ||
188: elType.ElTypeNum == MathML_EL_FencedSeparator)
1.138 cvs 189: /* an operator that contains a single Symbol needs a placeholder,
190: except when it is in a Base or UnderOverBase */
191: {
192: child = TtaGetFirstChild (el);
193: if (child != NULL)
1.1 cvs 194: {
1.138 cvs 195: elType = TtaGetElementType (child);
196: if (elType.ElTypeNum == MathML_EL_SYMBOL_UNIT)
197: {
1.1 cvs 198: ret = TRUE;
199: parent = TtaGetParent (el);
200: if (parent != NULL)
201: {
1.138 cvs 202: elType = TtaGetElementType (parent);
203: if (elType.ElTypeNum == MathML_EL_Base ||
204: elType.ElTypeNum == MathML_EL_UnderOverBase)
1.139 quint 205: ret = FALSE;
206: }
207: }
208: }
209: }
210: else if (elType.ElTypeNum == MathML_EL_MSPACE)
211: {
212: /* in principle mspace needs a placeholder sibling */
213: ret = TRUE;
214: /* but if it's the only child of a mstyle element, the placeholders
215: would change the height and width of the mstyle. Consider for
216: instance:
217: <mstyle background="#000099">
218: <mspace depth="2mm" width=".2in"/>
219: </mstyle> */
220: sibling = el; TtaNextSibling (&sibling);
221: if (!sibling)
222: {
223: sibling = el; TtaPreviousSibling (&sibling);
224: if (!sibling)
225: {
226: parent = TtaGetParent (el);
227: if (parent)
228: {
229: elType = TtaGetElementType (parent);
230: if (elType.ElTypeNum == MathML_EL_MSTYLE)
1.138 cvs 231: ret = FALSE;
1.1 cvs 232: }
1.138 cvs 233: }
1.1 cvs 234: }
1.138 cvs 235: }
1.1 cvs 236: return ret;
237: }
1.132 cvs 238:
1.1 cvs 239: /*----------------------------------------------------------------------
240: CreatePlaceholders
241: ----------------------------------------------------------------------*/
242: static void CreatePlaceholders (Element el, Document doc)
243: {
1.132 cvs 244: Element sibling, prev, constr, child;
245: Attribute attr;
246: ElementType elType;
247: AttributeType attrType;
248: ThotBool create, stretchableSubsup;
1.1 cvs 249:
1.55 cvs 250: if (!el)
251: return;
1.2 cvs 252: elType.ElSSchema = GetMathMLSSchema (doc);
1.1 cvs 253: prev = NULL;
254: create = TRUE;
255: sibling = el;
256: while (sibling != NULL)
257: {
258: if (!ElementNeedsPlaceholder (sibling))
259: create = FALSE;
260: else
261: {
262: if (sibling == el)
263: /* first element */
264: {
265: elType = TtaGetElementType (sibling);
266: if (elType.ElTypeNum == MathML_EL_MF)
267: /* the first element is a MF. Don't create a placeholder
268: before */
269: create = FALSE;
270: else if (elType.ElTypeNum == MathML_EL_MROW)
271: /* the first element is a MROW */
272: {
273: child = TtaGetFirstChild (sibling);
274: if (child != NULL)
275: {
276: elType = TtaGetElementType (child);
277: if (elType.ElTypeNum != MathML_EL_MF)
278: /* the first child of the MROW element is not a MF */
279: /* Don't create a placeholder before */
280: create = FALSE;
281: }
282: }
283: }
284: if (create)
285: {
286: elType.ElTypeNum = MathML_EL_Construct;
287: constr = TtaNewElement (doc, elType);
288: TtaInsertSibling (constr, sibling, TRUE, doc);
289: attrType.AttrSSchema = elType.ElSSchema;
1.22 cvs 290: attrType.AttrTypeNum = MathML_ATTR_IntPlaceholder;
1.1 cvs 291: attr = TtaNewAttribute (attrType);
292: TtaAttachAttribute (constr, attr, doc);
1.55 cvs 293: TtaSetAttributeValue (attr, MathML_ATTR_IntPlaceholder_VAL_yes_,
294: constr, doc);
1.1 cvs 295: }
296: create = TRUE;
297: }
298: prev = sibling;
299: TtaNextSibling (&sibling);
300: }
301: if (prev != NULL && create)
302: {
1.132 cvs 303: stretchableSubsup = FALSE;
1.1 cvs 304: elType = TtaGetElementType (prev);
1.95 cvs 305: /* don't insert a placeholder after the last element if it's a MF */
306: if (elType.ElTypeNum == MathML_EL_MF)
1.1 cvs 307: create = FALSE;
308: else if (elType.ElTypeNum == MathML_EL_MROW)
309: /* the last element is a MROW */
310: {
311: child = TtaGetLastChild (prev);
312: if (child != NULL)
313: {
314: elType = TtaGetElementType (child);
315: if (elType.ElTypeNum != MathML_EL_MF)
316: /* the last child of the MROW element is not a MF */
317: /* Don't create a placeholder before */
318: create = FALSE;
319: }
320: }
1.132 cvs 321: else if (elType.ElTypeNum == MathML_EL_MSUBSUP ||
322: elType.ElTypeNum == MathML_EL_MSUB ||
323: elType.ElTypeNum == MathML_EL_MSUP ||
324: elType.ElTypeNum == MathML_EL_MUNDEROVER ||
325: elType.ElTypeNum == MathML_EL_MUNDER ||
326: elType.ElTypeNum == MathML_EL_MUNDEROVER)
327: {
328: attrType.AttrSSchema = elType.ElSSchema;
329: attrType.AttrTypeNum = MathML_ATTR_IntVertStretch;
330: if (TtaGetAttribute (prev, attrType))
331: stretchableSubsup = TRUE;
332: }
333:
1.1 cvs 334: if (create)
335: {
1.132 cvs 336: if (stretchableSubsup)
337: elType.ElTypeNum = MathML_EL_Construct1;
338: else
339: elType.ElTypeNum = MathML_EL_Construct;
1.1 cvs 340: constr = TtaNewElement (doc, elType);
341: TtaInsertSibling (constr, prev, FALSE, doc);
342: attrType.AttrSSchema = elType.ElSSchema;
1.22 cvs 343: attrType.AttrTypeNum = MathML_ATTR_IntPlaceholder;
1.1 cvs 344: attr = TtaNewAttribute (attrType);
345: TtaAttachAttribute (constr, attr, doc);
1.55 cvs 346: TtaSetAttributeValue (attr, MathML_ATTR_IntPlaceholder_VAL_yes_,
347: constr, doc);
1.132 cvs 348: }
1.1 cvs 349: }
350: }
351:
352: /*----------------------------------------------------------------------
1.95 cvs 353: NextNotComment
354: Return the next sibling of element el that is not an XMLcomment element.
355: Return el itself if it's not a comment.
1.1 cvs 356: ----------------------------------------------------------------------*/
1.95 cvs 357: static void NextNotComment (Element* el, Element* prev)
1.1 cvs 358: {
359: ElementType elType;
360:
361: if (*el == NULL)
362: return;
363: elType = TtaGetElementType (*el);
1.95 cvs 364: while (*el != NULL && elType.ElTypeNum == MathML_EL_XMLcomment)
1.1 cvs 365: {
366: *prev = *el;
367: TtaNextSibling (el);
368: if (*el != NULL)
369: elType = TtaGetElementType (*el);
370: }
371: }
372:
373: /*----------------------------------------------------------------------
374: CheckMathSubExpressions
375: Children of element el should be of type type1, type2, and type3.
1.56 cvs 376: If they are not, wrap them in elements of these types.
1.124 cvs 377: If element el has too many or not enough children, return FALSE.
1.1 cvs 378: ----------------------------------------------------------------------*/
1.56 cvs 379: static ThotBool CheckMathSubExpressions (Element el, int type1, int type2, int type3, Document doc)
1.1 cvs 380: {
381: Element child, new, prev;
382: ElementType elType, childType;
1.124 cvs 383: char msgBuffer[200];
1.56 cvs 384: ThotBool result;
1.1 cvs 385:
1.56 cvs 386: result = TRUE;
1.2 cvs 387: elType.ElSSchema = GetMathMLSSchema (doc);
1.1 cvs 388: child = TtaGetFirstChild (el);
389: prev = NULL;
1.95 cvs 390: NextNotComment (&child, &prev);
1.56 cvs 391: if (type1 == 0)
1.1 cvs 392: {
1.56 cvs 393: if (child)
394: /* no child expected and there is one, error */
1.124 cvs 395: {
396: sprintf (msgBuffer, "No subexpression allowed in %s",
397: TtaGetElementTypeName (TtaGetElementType (el)));
398: XmlParseError (errorParsing, msgBuffer, 0);
399: result = FALSE;
400: }
1.56 cvs 401: }
402: else
403: if (!child)
404: /* a first child is expected and it's missing */
1.124 cvs 405: {
406: sprintf (msgBuffer, "Missing subexpression in %s",
407: TtaGetElementTypeName (TtaGetElementType (el)));
408: XmlParseError (errorParsing, msgBuffer, 0);
409: result = FALSE;
410: }
1.56 cvs 411: else
412: {
1.1 cvs 413: elType.ElTypeNum = type1;
414: childType = TtaGetElementType (child);
415: if (TtaSameTypes (childType, elType) == 0)
416: {
417: TtaRemoveTree (child, doc);
418: new = TtaNewElement (doc, elType);
419: if (prev == NULL)
420: TtaInsertFirstChild (&new, el, doc);
421: else
422: TtaInsertSibling (new, prev, FALSE, doc);
423: TtaInsertFirstChild (&child, new, doc);
424: CreatePlaceholders (child, doc);
425: child = new;
426: }
1.56 cvs 427: prev = child;
428: TtaNextSibling (&child);
1.95 cvs 429: NextNotComment (&child, &prev);
1.56 cvs 430: if (type2 == 0)
431: {
432: if (child)
433: /* this second child is not expected, error */
1.124 cvs 434: {
435: sprintf (msgBuffer, "Only 1 subexpression allowed in %s",
436: TtaGetElementTypeName (TtaGetElementType (el)));
437: XmlParseError (errorParsing, msgBuffer, 0);
438: result = FALSE;
439: }
1.56 cvs 440: }
441: else
1.1 cvs 442: {
1.56 cvs 443: if (!child)
444: /* a second child is expected and it's missing */
1.124 cvs 445: {
446: sprintf (msgBuffer, "2 subexpressions required in %s",
447: TtaGetElementTypeName (TtaGetElementType (el)));
448: XmlParseError (errorParsing, msgBuffer, 0);
449: result = FALSE;
450: }
1.56 cvs 451: else
1.1 cvs 452: {
453: elType.ElTypeNum = type2;
454: childType = TtaGetElementType (child);
455: if (TtaSameTypes (childType, elType) == 0)
456: {
457: TtaRemoveTree (child, doc);
458: new = TtaNewElement (doc, elType);
459: TtaInsertSibling (new, prev, FALSE, doc);
460: TtaInsertFirstChild (&child, new, doc);
461: CreatePlaceholders (child, doc);
462: child = new;
463: }
1.56 cvs 464: prev = child;
465: TtaNextSibling (&child);
1.95 cvs 466: NextNotComment (&child, &prev);
1.56 cvs 467: if (type3 == 0)
1.1 cvs 468: {
1.56 cvs 469: if (child)
470: /* this third child is not expected, error */
1.124 cvs 471: {
472: sprintf (msgBuffer, "Only 2 subexpressions allowed in %s",
473: TtaGetElementTypeName (TtaGetElementType (el)));
474: XmlParseError (errorParsing, msgBuffer, 0);
475: result = FALSE;
476: }
1.56 cvs 477: }
478: else
479: {
480: if (!child)
481: /* a third child is expected and it's missing */
1.124 cvs 482: {
483: sprintf (msgBuffer, "3 subexpressions required in %s",
484: TtaGetElementTypeName (TtaGetElementType (el)));
485: XmlParseError (errorParsing, msgBuffer, 0);
486: result = FALSE;
487: }
1.56 cvs 488: else
1.1 cvs 489: {
490: elType.ElTypeNum = type3;
491: childType = TtaGetElementType (child);
492: if (TtaSameTypes (childType, elType) == 0)
493: {
494: TtaRemoveTree (child, doc);
495: new = TtaNewElement (doc, elType);
496: TtaInsertSibling (new, prev, FALSE, doc);
497: TtaInsertFirstChild (&child, new, doc);
498: CreatePlaceholders (child, doc);
1.56 cvs 499: child = new;
1.1 cvs 500: }
501: }
1.56 cvs 502: prev = child;
503: TtaNextSibling (&child);
1.95 cvs 504: NextNotComment (&child, &prev);
1.56 cvs 505: if (child)
506: /* this fourth child is unexpected */
1.124 cvs 507: {
508: sprintf (msgBuffer,"Only 3 subexpressions allowed in %s",
509: TtaGetElementTypeName (TtaGetElementType (el)));
510: XmlParseError (errorParsing, msgBuffer, 0);
511: result = FALSE;
512: }
1.1 cvs 513: }
514: }
515: }
1.56 cvs 516: }
517: return result;
1.1 cvs 518: }
519:
520: /*----------------------------------------------------------------------
1.22 cvs 521: SetSingleIntHorizStretchAttr
1.1 cvs 522:
1.22 cvs 523: Put a IntHorizStretch attribute on element el if it contains only
1.1 cvs 524: a MO element that is a stretchable symbol.
525: -----------------------------------------------------------------------*/
1.22 cvs 526: void SetSingleIntHorizStretchAttr (Element el, Document doc, Element* selEl)
1.1 cvs 527: {
528: Element child, sibling, textEl, symbolEl;
1.152 quint 529: ElementType elType, childType, siblingType;
1.1 cvs 530: Attribute attr;
531: AttributeType attrType;
1.55 cvs 532: Language lang;
1.128 vatton 533: CHAR_T text[2];
1.143 vatton 534: char script;
1.49 cvs 535: unsigned char c;
1.128 vatton 536: int len;
1.152 quint 537: ThotBool doit;
1.1 cvs 538:
539: if (el == NULL)
540: return;
541: child = TtaGetFirstChild (el);
1.154 vatton 542: textEl = NULL;
1.55 cvs 543: if (child)
1.1 cvs 544: {
545: elType = TtaGetElementType (child);
1.162 quint 546: /* skip empty Constructs (placeholders) and comments */
547: while (child &&
548: (elType.ElTypeNum == MathML_EL_Construct ||
549: elType.ElTypeNum == MathML_EL_XMLcomment) &&
550: !strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML"))
1.152 quint 551: {
552: TtaNextSibling (&child);
553: if (child)
554: elType = TtaGetElementType (child);
555: }
1.162 quint 556: while (child && elType.ElTypeNum == MathML_EL_MROW &&
557: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML") == 0)
558: /* the first significant child is a mrow. Check whether it has a
559: single child */
1.98 cvs 560: {
561: child = TtaGetFirstChild (child);
562: if (child)
563: {
1.152 quint 564: elType = TtaGetElementType (child);
1.162 quint 565: /* skip empty Constructs (placeholders) and comments */
566: while (child &&
567: (elType.ElTypeNum == MathML_EL_Construct ||
568: elType.ElTypeNum == MathML_EL_XMLcomment) &&
569: !strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML"))
1.152 quint 570: {
1.162 quint 571: TtaNextSibling (&child);
572: if (child)
573: elType = TtaGetElementType (child);
1.152 quint 574: }
1.98 cvs 575: sibling = child;
576: TtaNextSibling (&sibling);
1.152 quint 577: if (sibling)
578: /* there are other children */
579: {
580: siblingType = TtaGetElementType (sibling);
1.162 quint 581: while (sibling &&
582: (siblingType.ElTypeNum == MathML_EL_Construct ||
583: siblingType.ElTypeNum == MathML_EL_XMLcomment) &&
584: !strcmp (TtaGetSSchemaName (siblingType.ElSSchema), "MathML"))
585: /* its an empty construct (placeholder) or a comment, skip it*/
586: {
587: TtaNextSibling (&sibling);
588: if (sibling)
589: siblingType = TtaGetElementType (sibling);
590: }
1.152 quint 591: if (sibling)
1.162 quint 592: /* there are significant siblings */
1.152 quint 593: child = NULL;
594: }
1.98 cvs 595: }
596: }
1.152 quint 597: if (child && (elType.ElTypeNum == MathML_EL_MO ||
598: elType.ElTypeNum == MathML_EL_MOVER ||
599: elType.ElTypeNum == MathML_EL_MUNDER))
600: /* the first child is a MO, a MUNDER or a MOVER */
1.1 cvs 601: {
602: sibling = child;
603: TtaNextSibling (&sibling);
1.152 quint 604: if (sibling)
1.162 quint 605: siblingType = TtaGetElementType (sibling);
606: /* skip empty Constructs (placeholders) and comments */
607: while (sibling &&
608: (siblingType.ElTypeNum == MathML_EL_Construct ||
609: siblingType.ElTypeNum == MathML_EL_XMLcomment) &&
610: !strcmp (TtaGetSSchemaName (siblingType.ElSSchema), "MathML"))
1.152 quint 611: {
1.162 quint 612: TtaNextSibling (&sibling);
613: if (sibling)
614: siblingType = TtaGetElementType (sibling);
1.152 quint 615: }
1.1 cvs 616: if (sibling == NULL)
1.162 quint 617: /* there is no other significant child */
1.1 cvs 618: {
1.152 quint 619: c = EOS;
620: doit = FALSE;
621: attrType.AttrSSchema = elType.ElSSchema;
622: attrType.AttrTypeNum = MathML_ATTR_IntHorizStretch;
623:
624: if (elType.ElTypeNum == MathML_EL_MOVER ||
625: elType.ElTypeNum == MathML_EL_MUNDER)
626: /* check if the UnderOverBase has a IntHorizStretch attribute */
627: {
628: childType.ElTypeNum = MathML_EL_UnderOverBase;
1.172 cheyroul 629: childType.ElSSchema = elType.ElSSchema;
1.152 quint 630: textEl = TtaSearchTypedElement (childType, SearchInTree, child);
631: if (textEl)
632: {
633: if (TtaGetAttribute (textEl, attrType))
634: doit = TRUE;
635: }
636: }
637: else if (elType.ElTypeNum == MathML_EL_MO)
638: {
639: textEl = TtaGetFirstChild (child);
640: childType = TtaGetElementType (textEl);
641: if (childType.ElTypeNum == MathML_EL_TEXT_UNIT)
642: /* the MO child contains a TEXT element */
643: {
644: len = TtaGetElementVolume (textEl);
645: if (len == 1)
1.123 cvs 646: /* the TEXT element contains a single character */
647: {
1.152 quint 648: /* get that character */
649: len = 2;
650: TtaGiveBufferContent (textEl, text, len, &lang);
651: script = TtaGetScript (lang);
652: if (
1.146 quint 653: #ifndef _I18N_
1.152 quint 654: (script == 'L') &&
1.146 quint 655: #endif
1.152 quint 656: (text[0] == '-' || text[0] == '_' ||
657: text[0] == 175))
1.146 quint 658: /* a horizontal line in the middle of the box */
659: c = 'h';
1.152 quint 660: else
661: #ifdef _I18N_
662: if (text[0] == 0x2190)
663: c = 'L'; /* arrow left */
664: else if (text[0] == 0x2192)
665: c = 'R'; /* arrow right */
1.153 quint 666: else if (text[0] == 45) /* - (minus) */
667: /* a horizontal line in the middle of the box */
668: c = 'h';
669: else if (text[0] == 0x2212) /* - (minus) */
1.152 quint 670: /* a horizontal line in the middle of the box */
671: c = 'h';
672: else if (text[0] == 0x0332) /* UnderBar */
673: /* a horizontal line */
674: c = 'h';
675: else if (text[0] == 65079)
676: c = 'o'; /* Over brace */
677: else if (text[0] == 65080)
678: c = 'u'; /* Under brace */
1.146 quint 679: #else
680: if (script == 'G')
681: /* a single Symbol character */
682: {
683: if (text[0] == 172)
684: c = 'L'; /* arrow left */
685: else if (text[0] == 174)
686: c = 'R'; /* arrow right */
687: else if (text[0] == 45) /* - (minus) */
688: /* a horizontal line in the middle of the box */
689: c = 'h';
690: else if (text[0] == 132)
691: c = 'o'; /* Over brace */
692: else if (text[0] == 133)
693: c = 'u'; /* Under brace */
694: }
695: #endif
1.152 quint 696: if (c != EOS)
697: doit = TRUE;
1.123 cvs 698: }
1.152 quint 699: }
700: }
701: if (doit)
702: {
703: /* attach a IntHorizStretch attribute to the element
704: (UnderOverBase, Underscript, or Overscript) */
705: attr = TtaNewAttribute (attrType);
706: TtaAttachAttribute (el, attr, doc);
707: TtaSetAttributeValue (attr, MathML_ATTR_IntHorizStretch_VAL_yes_, el, doc);
708: attr = TtaNewAttribute (attrType);
709: TtaAttachAttribute (child, attr, doc);
710: TtaSetAttributeValue (attr, MathML_ATTR_IntHorizStretch_VAL_yes_, child, doc);
711: }
712: if (c != EOS)
713: {
714: /* replace the TEXT element by a Thot SYMBOL element */
715: childType.ElTypeNum = MathML_EL_SYMBOL_UNIT;
716: symbolEl = TtaNewElement (doc, childType);
717: TtaInsertSibling (symbolEl, textEl, FALSE, doc);
718: if (selEl != NULL)
719: if (*selEl == textEl)
720: *selEl = symbolEl;
721: TtaDeleteTree (textEl, doc);
722: if (c != EOS)
723: TtaSetGraphicsShape (symbolEl, c, doc);
724: }
1.1 cvs 725: }
726: }
727: }
728: }
1.162 quint 729:
1.1 cvs 730: /*----------------------------------------------------------------------
1.22 cvs 731: SetIntHorizStretchAttr
1.1 cvs 732:
1.152 quint 733: Put a IntHorizStretch attribute on all children of element el that
1.1 cvs 734: contain only a MO element that is a stretchable symbol.
735: -----------------------------------------------------------------------*/
1.22 cvs 736: static void SetIntHorizStretchAttr (Element el, Document doc)
1.1 cvs 737: {
738: Element child;
739:
740: if (el == NULL)
741: return;
742: child = TtaGetFirstChild (el);
743: while (child != NULL)
744: {
1.22 cvs 745: SetSingleIntHorizStretchAttr (child, doc, NULL);
1.1 cvs 746: TtaNextSibling (&child);
747: }
748: }
749:
750: /*----------------------------------------------------------------------
1.22 cvs 751: SetIntVertStretchAttr
1.1 cvs 752:
1.22 cvs 753: Put a IntVertStretch attribute on element el if its base element
1.1 cvs 754: (Base for a MSUBSUP, MSUP or MSUB; UnderOverBase for a MUNDEROVER,
755: a MUNDER of a MOVER) contains only a MO element that is a vertically
1.162 quint 756: stretchable symbol (integral, vertical arrow, etc).
1.1 cvs 757: -----------------------------------------------------------------------*/
1.22 cvs 758: void SetIntVertStretchAttr (Element el, Document doc, int base, Element* selEl)
1.1 cvs 759: {
1.132 cvs 760: Element child, sibling, textEl, symbolEl, parent, operator, next;
1.1 cvs 761: ElementType elType;
762: Attribute attr;
763: AttributeType attrType;
1.131 cvs 764: SSchema MathMLSSchema;
1.128 vatton 765: Language lang;
1.143 vatton 766: char script;
1.131 cvs 767: #define buflen 50
768: CHAR_T text[buflen];
1.49 cvs 769: unsigned char c;
1.131 cvs 770: int len, i;
1.162 quint 771: ThotBool inbase, stretchable;
1.1 cvs 772:
773: if (el == NULL)
1.131 cvs 774: return;
1.1 cvs 775: operator = NULL;
1.131 cvs 776: inbase = FALSE;
777: MathMLSSchema = TtaGetElementType(el).ElSSchema;
1.154 vatton 778: symbolEl = parent = NULL;
1.1 cvs 779: if (base == 0)
1.131 cvs 780: /* it's a MO */
781: {
782: parent = TtaGetParent (el);
783: if (parent != NULL)
1.1 cvs 784: {
1.131 cvs 785: /* don't process the mo if it is within a base. It will be processed
786: when the enclosing construct is processed (see below) */
787: elType = TtaGetElementType (parent);
788: if (elType.ElSSchema != MathMLSSchema ||
789: (elType.ElTypeNum != MathML_EL_Base &&
790: elType.ElTypeNum != MathML_EL_UnderOverBase &&
791: elType.ElTypeNum != MathML_EL_MSUBSUP &&
792: elType.ElTypeNum != MathML_EL_MSUB &&
793: elType.ElTypeNum != MathML_EL_MSUP &&
794: elType.ElTypeNum != MathML_EL_MUNDEROVER &&
795: elType.ElTypeNum != MathML_EL_MUNDER &&
1.162 quint 796: elType.ElTypeNum != MathML_EL_MUNDEROVER &&
797: elType.ElTypeNum != MathML_EL_MTD))
1.131 cvs 798: operator = el;
1.1 cvs 799: }
1.131 cvs 800: }
1.1 cvs 801: else
1.131 cvs 802: /* it's not a MO */
803: {
804: /* search the Base or UnderOverBase child */
805: child = TtaGetFirstChild (el);
806: if (child != NULL)
1.1 cvs 807: {
1.131 cvs 808: elType = TtaGetElementType (child);
1.162 quint 809: /* skip empty Constructs (placeholders) and comments */
810: while (child &&
811: (elType.ElTypeNum == MathML_EL_Construct ||
812: elType.ElTypeNum == MathML_EL_XMLcomment) &&
813: elType.ElSSchema == MathMLSSchema)
814: {
815: TtaNextSibling (&child);
816: if (child)
817: elType = TtaGetElementType (child);
818: }
819:
1.131 cvs 820: if (elType.ElTypeNum == base && elType.ElSSchema == MathMLSSchema)
821: /* the first child is a Base or UnderOverBase */
822: {
823: child = TtaGetFirstChild (child);
824: if (child != NULL)
825: {
826: elType = TtaGetElementType (child);
1.162 quint 827: /* skip empty Constructs (placeholders) and comments */
828: while (child &&
829: (elType.ElTypeNum == MathML_EL_Construct ||
830: elType.ElTypeNum == MathML_EL_XMLcomment) &&
831: elType.ElSSchema == MathMLSSchema)
832: {
833: TtaNextSibling (&child);
834: if (child)
835: elType = TtaGetElementType (child);
836: }
837:
1.131 cvs 838: if (elType.ElTypeNum == MathML_EL_MO &&
839: elType.ElSSchema == MathMLSSchema)
1.162 quint 840: /* its first significant child is a MO */
1.131 cvs 841: {
842: sibling = child;
843: TtaNextSibling (&sibling);
1.162 quint 844: /* skip empty Constructs (placeholders) and comments */
845: while (sibling &&
846: (elType.ElTypeNum == MathML_EL_Construct ||
847: elType.ElTypeNum == MathML_EL_XMLcomment) &&
848: elType.ElSSchema == MathMLSSchema)
849: {
850: TtaNextSibling (&sibling);
851: if (sibling)
852: elType = TtaGetElementType (sibling);
853: }
854:
1.131 cvs 855: if (sibling == NULL)
1.162 quint 856: /* there is no other significant child */
1.131 cvs 857: {
858: operator = child;
859: if (base == MathML_EL_Base ||
860: base == MathML_EL_UnderOverBase)
861: {
862: parent = el;
863: inbase = TRUE;
864: }
865: }
866: }
867: }
868: }
1.1 cvs 869: }
1.131 cvs 870: }
871: if (operator)
872: {
873: textEl = TtaGetFirstChild (operator);
874: if (textEl != NULL)
1.84 cvs 875: {
1.131 cvs 876: elType = TtaGetElementType (textEl);
877: if (elType.ElTypeNum == MathML_EL_TEXT_UNIT)
878: {
1.146 quint 879: len = TtaGetElementVolume (textEl);
1.131 cvs 880: if (len >= 1)
881: {
882: if (len >= buflen)
883: len = buflen-1;
1.146 quint 884: TtaGiveBufferContent (textEl, text, len+1, &lang);
1.143 vatton 885: script = TtaGetScript (lang);
1.146 quint 886: #ifdef _I18N_
1.162 quint 887: stretchable = TRUE;
1.146 quint 888: for (i = 0; i < len; i++)
1.162 quint 889: if ((text[i] < 0x222B || text[i] > 0x2233) &&
890: text[i] != 0x2191 && text[i] != 0x2193 &&
891: text[i] != 0x2195 &&
892: text[i] != 0x21D1 && text[i] != 0x21D3 &&
893: text[i] != 0x21D5)
1.146 quint 894: /* accept only symbols like simple integral, double or
1.162 quint 895: triple integral, contour integral, etc. or vertical
896: arrows (add more arrows *****) */
897: stretchable = FALSE;
1.146 quint 898: #else
1.162 quint 899: stretchable = FALSE;
1.143 vatton 900: if (script == 'G')
1.131 cvs 901: /* Adobe Symbol character set */
1.55 cvs 902: {
1.162 quint 903: stretchable = TRUE;
1.131 cvs 904: /* check all characters in this TEXT element */
905: for (i = 0; i < len; i++)
1.162 quint 906: if (text[i] != 242 && /* integral */
907: text[i] != 173 && text[i] != 175 && /* arrows */
908: text[i] != 221 && text[i] != 223) /* double arrows */
1.131 cvs 909: /**** accept also other symbols like double or triple
910: integral, contour integral, etc. ****/
1.162 quint 911: stretchable = FALSE;
1.146 quint 912: }
913: #endif
1.162 quint 914: if (stretchable)
915: /* the operator contains only stretchable symbols */
1.146 quint 916: {
917: /* attach a IntVertStretch attribute */
918: attrType.AttrSSchema = MathMLSSchema;
919: attrType.AttrTypeNum = MathML_ATTR_IntVertStretch;
920: attr = TtaNewAttribute (attrType);
921: TtaAttachAttribute (el, attr, doc);
922: TtaSetAttributeValue (attr,
1.131 cvs 923: MathML_ATTR_IntVertStretch_VAL_yes_,
924: el, doc);
1.146 quint 925: TtaRegisterAttributeCreate (attr, el, doc);
926:
1.162 quint 927: /* replace the stretchable characters by a Thot SYMBOL
1.146 quint 928: element. If there are several such characters in
1.162 quint 929: the mo (multiple integral for instance), replace
930: them too. */
1.146 quint 931: do
932: {
933: /* replace the TEXT element by a Thot SYMBOL */
1.162 quint 934: elType.ElSSchema = MathMLSSchema;
1.146 quint 935: elType.ElTypeNum = MathML_EL_SYMBOL_UNIT;
936: for (i = 0; i < len; i++)
1.162 quint 937: {
938: if (selEl != NULL)
939: if (*selEl == textEl)
940: *selEl = symbolEl;
1.176 ! cvs 941: c = (unsigned char) text[i];
1.146 quint 942: #ifdef _I18N_
1.162 quint 943: if (text[i] == 0x222B)
944: c = 'i';
945: else if (text[i] == 0x222C)
946: c = 'd';
947: else if (text[i] == 0x222D)
948: c = 't';
949: else if (text[i] == 0x222E)
950: c = 'c';
951: else if (text[i] == 0x2191)
952: c = '^';
953: else if (text[i] == 0x2193)
954: c = 'V';
1.173 vatton 955: #else /*_I18N_ */
1.162 quint 956: if (text[i] == 242)
957: c = 'i';
958: else if (text[i] == 173)
959: c = '<';
960: else if (text[i] == 175)
961: c = '>';
1.173 vatton 962: #endif /*_I18N_ */
1.162 quint 963: symbolEl = TtaNewElement (doc, elType);
964: TtaInsertSibling (symbolEl, textEl, TRUE,doc);
965: TtaSetGraphicsShape (symbolEl, c, doc);
966: TtaRegisterElementCreate (symbolEl, doc);
967: }
1.146 quint 968: TtaRegisterElementDelete (textEl, doc);
969: TtaDeleteTree (textEl, doc);
970: /* is there an other text element after the
1.162 quint 971: stretchable symbol? */
1.146 quint 972: textEl = symbolEl; TtaNextSibling (&textEl);
973: if (textEl)
974: {
975: elType = TtaGetElementType (textEl);
976: if (elType.ElTypeNum != MathML_EL_TEXT_UNIT)
977: textEl = NULL;
978: else
979: /* there is another text element.
1.162 quint 980: Is it a single stretchable symbol? */
1.146 quint 981: {
982: len = TtaGetElementVolume (textEl);
983: if (len < 1)
984: /* not a single character */
985: textEl = NULL;
986: else
987: {
988: if (len >= buflen)
989: len = buflen-1;
990: TtaGiveBufferContent (textEl, text,
991: len+1, &lang);
992: script = TtaGetScript (lang);
993: #ifdef _I18N_
1.164 quint 994: if (text[0] != 0x222B &&
995: text[0] != 0x222C &&
996: text[0] != 0x222D &&
997: text[0] != 0x222E &&
998: text[0] != 0x2191 &&
999: text[0] != 0x2193)
1.173 vatton 1000: #else /*_I18N_ */
1.162 quint 1001: if (script != 'G' ||
1.164 quint 1002: (text[0] != 242 && text[0] != 173 &&
1003: text[0] != 175))
1.173 vatton 1004: #endif /*_I18N_ */
1.162 quint 1005: /* not a stretchable symbol */
1.146 quint 1006: textEl = NULL;
1007: }
1008: }
1009: }
1010: }
1011: while (textEl);
1012:
1013: if (inbase)
1014: /* it's within a Base or UnderOverBase element */
1015: {
1016: sibling = parent;
1017: TtaNextSibling (&sibling);
1018: if (sibling)
1019: /* the msubsup of munderover element has a next
1020: sibling */
1021: {
1022: elType = TtaGetElementType (sibling);
1023: if (elType.ElTypeNum == MathML_EL_Construct &&
1024: elType.ElSSchema == MathMLSSchema)
1025: /* the next sibling is a Construct */
1026: {
1027: next = sibling;
1028: TtaNextSibling (&next);
1029: if (!next)
1030: /* there is no other sibling after the
1031: Construct. Change it into Construct1*/
1032: {
1033: TtaRegisterElementDelete (sibling, doc);
1034: TtaRemoveTree (sibling, doc);
1035: ChangeElementType (sibling,
1.132 cvs 1036: MathML_EL_Construct1);
1.146 quint 1037: TtaInsertSibling (sibling, parent,
1038: FALSE, doc);
1039: TtaRegisterElementCreate (sibling, doc);
1040: /* force the msubsup element to be
1041: reformatted and to take into account
1042: its new next sibling */
1043: TtaRemoveTree (parent, doc);
1044: TtaInsertSibling (parent, sibling, TRUE,
1045: doc);
1046: }
1047: }
1048: }
1049: }
1.55 cvs 1050: }
1.131 cvs 1051: }
1052: }
1.84 cvs 1053: }
1.131 cvs 1054: }
1.1 cvs 1055: }
1056:
1057: /*----------------------------------------------------------------------
1.169 quint 1058: SetIntMovelimitsAttr
1059: Put a IntMovelimits attribute on element el (which is a munder, mover
1060: or munderover) if the current value of IntDisplaystyle is false and
1061: if el contains a MO element that allows limits to be moved.
1062: -----------------------------------------------------------------------*/
1063: void SetIntMovelimitsAttr (Element el, Document doc)
1064: {
1065: Element ancestor, child, base, operator, textEl;
1066: int value, len;
1067: ElementType elType;
1068: AttributeType attrType;
1069: Attribute attr;
1070: Language lang;
1071: CHAR_T text[10];
1072: char buffer[20];
1073: ThotBool movable;
1074: #ifndef _I18N_
1075: char script;
1076: #endif
1077:
1078: if (el == NULL || doc == 0)
1079: return;
1080: movable = FALSE;
1081:
1082: /* first look for an IntDisplaystyle attribute on an ancestor */
1083: elType = TtaGetElementType (el);
1084: attrType.AttrSSchema = elType.ElSSchema;
1085: attrType.AttrTypeNum = MathML_ATTR_IntDisplaystyle;
1086: ancestor = el;
1087: do
1088: {
1089: attr = TtaGetAttribute (ancestor, attrType);
1090: if (!attr)
1091: ancestor = TtaGetParent(ancestor);
1092: }
1093: while (!attr && ancestor);
1094: if (attr)
1095: /* there is an ancestor with an attribute IntDisplaystyle */
1096: {
1097: value = TtaGetAttributeValue (attr);
1098: if (value == MathML_ATTR_IntDisplaystyle_VAL_false)
1099: /* an ancestor has an attribute IntDisplaystyle = false */
1100: {
1101: /* Check the operator within the base */
1102: child = TtaGetFirstChild (el);
1103: base = NULL;
1104: do
1105: {
1106: elType = TtaGetElementType (child);
1107: if (elType.ElTypeNum == MathML_EL_UnderOverBase)
1108: base = child;
1109: else
1110: TtaNextSibling (&child);
1111: }
1112: while (child && !base);
1113: if (base)
1114: {
1115: child = TtaGetFirstChild (base);
1116: operator = NULL;
1117: do
1118: {
1119: elType = TtaGetElementType (child);
1120: if (elType.ElTypeNum == MathML_EL_MO)
1121: operator = child;
1122: else
1123: TtaNextSibling (&child);
1124: }
1125: while (child && !operator);
1126: if (operator)
1127: {
1128: attrType.AttrTypeNum = MathML_ATTR_movablelimits;
1129: attr = TtaGetAttribute (operator, attrType);
1130: if (attr)
1131: /* the operator has an attribute movablelimits */
1132: {
1133: value = TtaGetAttributeValue (attr);
1134: if (value == MathML_ATTR_movablelimits_VAL_true)
1135: movable = TRUE;
1136: }
1137: else
1138: /* no attribute movablelimits. Look at the content of the
1139: operator element */
1140: {
1141: textEl = TtaGetFirstChild (operator);
1142: if (textEl)
1143: {
1144: elType = TtaGetElementType (textEl);
1145: if (elType.ElTypeNum == MathML_EL_TEXT_UNIT)
1146: {
1147: len = TtaGetElementVolume (textEl);
1148: if (len == 3)
1149: {
1150: TtaGiveTextContent (textEl, buffer, &len, &lang);
1151: #ifndef _I18N_
1152: script = TtaGetScript (lang);
1153: if (script == 'L')
1154: #endif
1155: {
1156: if (!strcmp (buffer, "lim") ||
1157: !strcmp (buffer, "max") ||
1158: !strcmp (buffer, "min"))
1159: movable = TRUE;
1160: }
1161: }
1162: else if (len == 1)
1163: {
1164: TtaGiveBufferContent (textEl, text, len+1, &lang);
1165: #ifdef _I18N_
1166: if (text[0] == 0x22C1 /* Vee */ ||
1167: text[0] == 0x2296 /* CircleMinus */ ||
1168: text[0] == 0x2295 /* CirclePlus */ ||
1169: text[0] == 0x2211 /* Sum */ ||
1170: text[0] == 0x22C3 /* Union */ ||
1171: text[0] == 0x228E /* UnionPlus */ ||
1172: text[0] == 0x22C0 /* Wedge */ ||
1173: text[0] == 0x2297 /* CircleTimes */ ||
1174: text[0] == 0x2210 /* Coproduct */ ||
1175: text[0] == 0x220F /* Product */ ||
1176: text[0] == 0x22C2 /* Intersection */ ||
1177: text[0] == 0x2299 /* CircleDot */ )
1178: movable = TRUE;
1179: #else
1180: script = TtaGetScript (lang);
1181: if (script == 'G')
1182: /* Adobe Symbol character set */
1183: if (text[0] == 197 || text[0] == 229 ||
1184: text[0] == 200 || text[0] == 196 ||
1185: text[0] == 213 || text[0] == 199)
1186: movable = TRUE;
1187: #endif
1188: }
1189: }
1190: }
1191: }
1192: }
1193: }
1194: }
1195: }
1196:
1197: attrType.AttrTypeNum = MathML_ATTR_IntMovelimits;
1198: attr = TtaGetAttribute (el, attrType);
1199: if (movable)
1200: {
1201: if (!attr)
1202: {
1203: attr = TtaNewAttribute (attrType);
1204: TtaAttachAttribute (el, attr, doc);
1205: }
1206: TtaSetAttributeValue (attr, MathML_ATTR_IntMovelimits_VAL_yes_, el, doc);
1207: }
1208: else if (attr)
1209: TtaRemoveAttribute (el, attr, doc);
1210: }
1211:
1212: /*----------------------------------------------------------------------
1.22 cvs 1213: SetIntPlaceholderAttr
1.1 cvs 1214:
1.22 cvs 1215: Put a IntPlaceholder attribute on all Construct elements in the
1.1 cvs 1216: subtree of root el.
1217: -----------------------------------------------------------------------*/
1.22 cvs 1218: static void SetIntPlaceholderAttr (Element el, Document doc)
1.1 cvs 1219: {
1220: Element child;
1221: ElementType elType;
1222: Attribute attr;
1223: AttributeType attrType;
1224:
1225: if (el == NULL)
1226: return;
1227: elType = TtaGetElementType (el);
1228: if (elType.ElTypeNum == MathML_EL_Construct &&
1.2 cvs 1229: elType.ElSSchema == GetMathMLSSchema (doc))
1.1 cvs 1230: {
1231: attrType.AttrSSchema = elType.ElSSchema;
1.22 cvs 1232: attrType.AttrTypeNum = MathML_ATTR_IntPlaceholder;
1.1 cvs 1233: attr = TtaNewAttribute (attrType);
1234: TtaAttachAttribute (el, attr, doc);
1.22 cvs 1235: TtaSetAttributeValue (attr, MathML_ATTR_IntPlaceholder_VAL_yes_, el, doc);
1.1 cvs 1236: }
1237: else
1238: {
1239: child = TtaGetFirstChild (el);
1240: while (child != NULL)
1241: {
1.22 cvs 1242: SetIntPlaceholderAttr (child, doc);
1.1 cvs 1243: TtaNextSibling (&child);
1244: }
1245: }
1246: }
1247:
1248: /*----------------------------------------------------------------------
1249: BuildMultiscript
1250:
1251: The content of a MMULTISCRIPT element has been created following
1252: the original MathML structure. Create all Thot elements defined
1253: in the MathML S schema.
1254: -----------------------------------------------------------------------*/
1255: static void BuildMultiscript (Element elMMULTISCRIPT, Document doc)
1256: {
1257: Element elem, base, next, group, pair, script, prevPair, prevScript;
1258: ElementType elType, elTypeGroup, elTypePair, elTypeScript;
1.2 cvs 1259: SSchema MathMLSSchema;
1.1 cvs 1260: base = NULL;
1261: group = NULL;
1262: prevPair = NULL;
1263: prevScript = NULL;
1264:
1.2 cvs 1265: MathMLSSchema = GetMathMLSSchema (doc);
1.1 cvs 1266: elTypeGroup.ElSSchema = MathMLSSchema;
1267: elTypePair.ElSSchema = MathMLSSchema;
1268: elTypeScript.ElSSchema = MathMLSSchema;
1269:
1270: /* process all children of the MMULTISCRIPT element */
1271: elem = TtaGetFirstChild (elMMULTISCRIPT);
1272: while (elem != NULL)
1273: {
1274: /* remember the element to be processed after the current one */
1275: next = elem;
1276: TtaNextSibling (&next);
1277:
1278: /* remove the current element from the tree */
1279: TtaRemoveTree (elem, doc);
1280:
1281: if (base == NULL)
1282: /* the current element is the first child of the MMULTISCRIPT
1283: element */
1284: {
1285: /* Create a MultiscriptBase element as the first child of
1286: MMULTISCRIPT and move the current element as the first child
1287: of the MultiscriptBase element */
1288: elTypeGroup.ElTypeNum = MathML_EL_MultiscriptBase;
1289: base = TtaNewElement (doc, elTypeGroup);
1290: TtaInsertFirstChild (&base, elMMULTISCRIPT, doc);
1291: TtaInsertFirstChild (&elem, base, doc);
1292: }
1293: else
1294: /* the current element is a subscript or a superscript */
1295: {
1296: if (group == NULL)
1297: /* there is no PostscriptPairs element. Create one */
1298: {
1299: elTypeGroup.ElTypeNum = MathML_EL_PostscriptPairs;
1300: group = TtaNewElement (doc, elTypeGroup);
1301: TtaInsertSibling (group, base, FALSE, doc);
1302: elTypePair.ElTypeNum = MathML_EL_PostscriptPair;
1303: /* create a first and a last PostscriptPair as placeholders */
1.47 cvs 1304: pair = TtaNewTree (doc, elTypePair, "");
1.1 cvs 1305: TtaInsertFirstChild (&pair, group, doc);
1.22 cvs 1306: SetIntPlaceholderAttr (pair, doc);
1.1 cvs 1307: prevPair = pair;
1.47 cvs 1308: pair = TtaNewTree (doc, elTypePair, "");
1.1 cvs 1309: TtaInsertSibling (pair, prevPair, FALSE, doc);
1.22 cvs 1310: SetIntPlaceholderAttr (pair, doc);
1.1 cvs 1311: prevScript = NULL;
1312: }
1313: if (prevScript == NULL)
1314: /* the current element is the first subscript or superscript
1315: in a pair */
1316: {
1317: /* create a PostscriptPair or PrescriptPair element */
1318: pair = TtaNewElement (doc, elTypePair);
1319: if (prevPair == NULL)
1320: TtaInsertFirstChild (&pair, group, doc);
1321: else
1322: TtaInsertSibling (pair, prevPair, FALSE, doc);
1323: prevPair = pair;
1324: /* create a MSubscript element */
1325: elTypeScript.ElTypeNum = MathML_EL_MSubscript;
1326: script = TtaNewElement (doc, elTypeScript);
1327: TtaInsertFirstChild (&script, pair, doc);
1328: prevScript = script;
1329: }
1330: else
1331: /* the current element is a superscript in a pair */
1332: {
1333: /* create a MSuperscript element */
1334: elTypeScript.ElTypeNum = MathML_EL_MSuperscript;
1335: script = TtaNewElement (doc, elTypeScript);
1336: /* insert it as a sibling of the previous MSubscript element */
1337: TtaInsertSibling (script, prevScript, FALSE, doc);
1338: prevScript = NULL;
1339: }
1340: /* insert the current element as a child of the new MSuperscript or
1341: MSubscript element */
1342: TtaInsertFirstChild (&elem, script, doc);
1.22 cvs 1343: SetIntPlaceholderAttr (elem, doc);
1.1 cvs 1344: }
1345:
1346: CreatePlaceholders (elem, doc);
1347:
1348: /* get next child of the MMULTISCRIPT element */
1349: elem = next;
1350: if (elem != NULL)
1351: {
1352: elType = TtaGetElementType (elem);
1353: if (elType.ElSSchema == MathMLSSchema &&
1354: elType.ElTypeNum == MathML_EL_PrescriptPairs)
1355: /* the next element is a PrescriptPairs */
1356: {
1357: /* if there there is no PostscriptPairs element, create one as a
1358: placeholder */
1359: if (elTypeGroup.ElTypeNum != MathML_EL_PostscriptPairs)
1360: {
1361: elTypeGroup.ElTypeNum = MathML_EL_PostscriptPairs;
1.47 cvs 1362: group = TtaNewTree (doc, elTypeGroup, "");
1.1 cvs 1363: TtaInsertSibling (group, elem, TRUE, doc);
1.22 cvs 1364: SetIntPlaceholderAttr (group, doc);
1.1 cvs 1365: }
1366: /* the following elements will be interpreted as sub- superscripts
1367: in PrescriptPair elements, wich will be children of this
1368: PrescriptPairs element */
1369: elTypeGroup.ElTypeNum = MathML_EL_PrescriptPairs;
1370: elTypePair.ElTypeNum = MathML_EL_PrescriptPair;
1371: group = elem;
1372: /* create a first and a last PostscriptPair as placeholders */
1.47 cvs 1373: pair = TtaNewTree (doc, elTypePair, "");
1.1 cvs 1374: TtaInsertFirstChild (&pair, group, doc);
1.22 cvs 1375: SetIntPlaceholderAttr (pair, doc);
1.1 cvs 1376: prevPair = pair;
1.47 cvs 1377: pair = TtaNewTree (doc, elTypePair, "");
1.1 cvs 1378: TtaInsertSibling (pair, prevPair, FALSE, doc);
1.22 cvs 1379: SetIntPlaceholderAttr (pair, doc);
1.1 cvs 1380: prevScript = NULL;
1381: TtaNextSibling (&elem);
1382: }
1383: }
1384: }
1385: /* all children of element MMULTISCRIPTS have been processed */
1386: /* if the last group processed is not a PrescriptPairs element,
1387: create one as a placeholder */
1388: if (elTypeGroup.ElTypeNum != MathML_EL_PrescriptPairs && base != NULL)
1389: {
1390: elTypeGroup.ElTypeNum = MathML_EL_PrescriptPairs;
1.47 cvs 1391: elem = TtaNewTree (doc, elTypeGroup, "");
1.1 cvs 1392: if (group == NULL)
1393: group = base;
1394: TtaInsertSibling (elem, group, TRUE, doc);
1.22 cvs 1395: SetIntPlaceholderAttr (elem, doc);
1.1 cvs 1396: }
1397: }
1398:
1.39 cvs 1399: /*----------------------------------------------------------------------
1400: CreateWrapper
1401:
1402: Create an element of type wrapperType as a child of element el and
1403: move all chidren of element el within the new element.
1404: -----------------------------------------------------------------------*/
1405: static void CreateWrapper (Element el, int wrapperType, Document doc)
1406: {
1407: Element wrapper, child, prevChild, nextChild;
1408: ElementType elType;
1409:
1410: child = TtaGetFirstChild (el);
1411: elType.ElSSchema = GetMathMLSSchema (doc);
1412: elType.ElTypeNum = wrapperType;
1413: wrapper = TtaNewElement (doc, elType);
1414: TtaInsertFirstChild (&wrapper, el, doc);
1415: prevChild = NULL;
1416: while (child)
1417: {
1418: nextChild = child;
1419: TtaNextSibling (&nextChild);
1420: TtaRemoveTree (child, doc);
1421: if (prevChild == NULL)
1422: TtaInsertFirstChild (&child, wrapper, doc);
1423: else
1424: TtaInsertSibling (child, prevChild, FALSE, doc);
1425: prevChild = child;
1426: child = nextChild;
1427: }
1428: }
1.5 cvs 1429:
1430: /*----------------------------------------------------------------------
1431: CheckMTable
1432:
1433: The content of a MTABLE element has been created following
1434: the original MathML structure. Create all Thot elements defined
1435: in the MathML S schema.
1.64 cvs 1436: If placeholder, associate an attribute IntPlaceholder with all
1.103 cvs 1437: cells generated in the MathML table.
1.5 cvs 1438: -----------------------------------------------------------------------*/
1.64 cvs 1439: void CheckMTable (Element elMTABLE, Document doc, ThotBool placeholder)
1.5 cvs 1440: {
1441: ElementType elType;
1442: Element MTableHead, MTableBody, row, nextRow, el, prevRow, cell,
1.103 cvs 1443: nextCell, newMTD, firstColHead, label;
1.5 cvs 1444: SSchema MathMLSSchema;
1445:
1446: MathMLSSchema = GetMathMLSSchema (doc);
1447: row = TtaGetFirstChild (elMTABLE);
1448:
1449: /* create a MTable_head as the first child of element MTABLE */
1450: elType.ElSSchema = MathMLSSchema;
1451: elType.ElTypeNum = MathML_EL_MTable_head;
1452: MTableHead = TtaNewElement (doc, elType);
1453: TtaInsertFirstChild (&MTableHead, elMTABLE, doc);
1454: elType.ElTypeNum = MathML_EL_MColumn_head;
1.47 cvs 1455: firstColHead = TtaNewTree (doc, elType, "");
1.5 cvs 1456: TtaInsertFirstChild (&firstColHead, MTableHead, doc);
1457:
1458: /* create a MTable_body */
1459: elType.ElTypeNum = MathML_EL_MTable_body;
1460: MTableBody = TtaNewElement (doc, elType);
1461: TtaInsertSibling (MTableBody, MTableHead, FALSE, doc);
1462:
1463: /* move all children of element MTABLE into the new MTable_body element
1.103 cvs 1464: and wrap each non-MTR element in a MTR, except comments */
1.5 cvs 1465: prevRow = NULL;
1466: while (row)
1467: {
1468: nextRow = row;
1469: TtaNextSibling (&nextRow);
1470: elType = TtaGetElementType (row);
1471: TtaRemoveTree (row, doc);
1472: if (TtaSameSSchemas (elType.ElSSchema, MathMLSSchema) &&
1473: (elType.ElTypeNum == MathML_EL_XMLcomment ||
1.101 cvs 1474: elType.ElTypeNum == MathML_EL_MTR ||
1475: elType.ElTypeNum == MathML_EL_MLABELEDTR))
1.5 cvs 1476: {
1477: if (prevRow == NULL)
1478: TtaInsertFirstChild (&row, MTableBody, doc);
1479: else
1480: TtaInsertSibling (row, prevRow, FALSE, doc);
1481: prevRow = row;
1.101 cvs 1482: if (elType.ElTypeNum == MathML_EL_MTR ||
1483: elType.ElTypeNum == MathML_EL_MLABELEDTR)
1.103 cvs 1484: {
1.5 cvs 1485: cell = TtaGetFirstChild (row);
1.103 cvs 1486: if (elType.ElTypeNum == MathML_EL_MLABELEDTR)
1487: /* skip the first significant child of the mlabeledtr element */
1488: {
1489: /* skip comments first */
1490: do
1491: {
1492: elType = TtaGetElementType (cell);
1493: if (TtaSameSSchemas (elType.ElSSchema, MathMLSSchema) &&
1494: elType.ElTypeNum == MathML_EL_XMLcomment)
1495: TtaNextSibling (&cell);
1496: }
1497: while (cell && elType.ElTypeNum == MathML_EL_XMLcomment);
1498: /* skip the first element after the comments: it's a label */
1499: if (cell)
1500: {
1.105 cvs 1501: /* if it's a MTD change its type into LabelCell */
1502: if (elType.ElTypeNum == MathML_EL_MTD &&
1503: elType.ElSSchema == MathMLSSchema)
1504: ChangeElementType (cell, MathML_EL_LabelCell);
1.103 cvs 1505: /* wrap this element in a RowLabel element */
1.105 cvs 1506: /* This will allow the P schema to specify the horizontal
1507: position of the label */
1.103 cvs 1508: elType.ElSSchema = MathMLSSchema;
1509: elType.ElTypeNum = MathML_EL_RowLabel;
1510: label = TtaNewElement (doc, elType);
1511: TtaInsertSibling (label, cell, TRUE, doc);
1512: TtaRemoveTree (cell, doc);
1513: TtaInsertFirstChild (&cell, label, doc);
1514: cell = label;
1515: TtaNextSibling (&cell);
1516: }
1517: }
1518: }
1.5 cvs 1519: else
1520: cell = NULL;
1521: }
1522: else
1.103 cvs 1523: /* this child is not a MTR, MLABELEDTR, or a comment.
1524: In MathML 2.0, this in an error, but we try to recover by
1525: creating a MTR element */
1.5 cvs 1526: {
1527: elType.ElSSchema = MathMLSSchema;
1528: elType.ElTypeNum = MathML_EL_MTR;
1529: el = TtaNewElement (doc, elType);
1530: if (prevRow == NULL)
1531: TtaInsertFirstChild (&el, MTableBody, doc);
1532: else
1533: TtaInsertSibling (el, prevRow, FALSE, doc);
1534: TtaInsertFirstChild (&row, el, doc);
1535: cell = row;
1536: prevRow = el;
1537: }
1538: while (cell)
1539: /* check all children of the current MTR element */
1540: {
1541: nextCell = cell;
1542: TtaNextSibling (&nextCell);
1543: elType = TtaGetElementType (cell);
1544: if (!TtaSameSSchemas (elType.ElSSchema, MathMLSSchema) ||
1545: (elType.ElTypeNum != MathML_EL_XMLcomment &&
1546: elType.ElTypeNum != MathML_EL_MTD))
1547: /* this is not a MTD nor a comment, create a wrapping MTD */
1548: {
1549: elType.ElSSchema = MathMLSSchema;
1550: elType.ElTypeNum = MathML_EL_MTD;
1551: newMTD = TtaNewElement (doc, elType);
1552: TtaInsertSibling (newMTD, cell, TRUE, doc);
1553: TtaRemoveTree (cell, doc);
1554: TtaInsertFirstChild (&cell, newMTD, doc);
1555: cell = newMTD;
1556: }
1557: if (elType.ElTypeNum == MathML_EL_MTD)
1558: /* This is a MTD element. Wrap its contents with a CellWrapper */
1.162 quint 1559: {
1560: CreateWrapper (cell, MathML_EL_CellWrapper, doc);
1561: SetIntHorizStretchAttr (cell, doc);
1562: SetIntVertStretchAttr (cell, doc, MathML_EL_CellWrapper, NULL);
1563: }
1.5 cvs 1564: cell = nextCell;
1565: }
1566: row = nextRow;
1567: }
1.107 cvs 1568: CheckAllRows (elMTABLE, doc, placeholder, FALSE);
1.5 cvs 1569: }
1.12 cvs 1570:
1.46 cvs 1571: /*----------------------------------------------------------------------
1.1 cvs 1572: SetFontstyleAttr
1573: The content of a MI element has been created or modified.
1574: Create or change attribute IntFontstyle for that element accordingly.
1575: -----------------------------------------------------------------------*/
1576: void SetFontstyleAttr (Element el, Document doc)
1577: {
1578: ElementType elType;
1.157 quint 1579: AttributeType attrType, attrType1;
1.1 cvs 1580: Attribute attr, IntAttr;
1.157 quint 1581: Element ancestor, textEl;
1.1 cvs 1582: int len;
1.163 quint 1583: Language lang;
1584: #ifndef _I18N_
1585: char script;
1.166 quint 1586: char *value;
1.163 quint 1587: #endif
1.166 quint 1588: CHAR_T text[2];
1.54 cvs 1589: ThotBool italic;
1.1 cvs 1590:
1591: if (el != NULL)
1.142 quint 1592: {
1.157 quint 1593: /* search the (deprecated) fontstyle attribute or the mathvariant
1594: attribute on the element and its ancestors */
1.142 quint 1595: elType = TtaGetElementType (el);
1596: attrType.AttrSSchema = elType.ElSSchema;
1597: attrType.AttrTypeNum = MathML_ATTR_fontstyle;
1.157 quint 1598: attrType1.AttrSSchema = elType.ElSSchema;
1599: attrType1.AttrTypeNum = MathML_ATTR_mathvariant;
1600: ancestor = el;
1601: attr = NULL;
1602: do
1603: {
1604: attr = TtaGetAttribute (ancestor, attrType);
1605: if (!attr)
1606: attr = TtaGetAttribute (ancestor, attrType1);
1607: if (!attr)
1608: {
1609: ancestor = TtaGetParent (ancestor);
1610: if (ancestor)
1611: {
1612: elType = TtaGetElementType (ancestor);
1613: if (elType.ElSSchema != attrType.AttrSSchema)
1614: /* this ancestor is not in the MathML namespace */
1615: ancestor = NULL;
1616: }
1617: }
1618: }
1619: while (ancestor && !attr);
1620:
1.142 quint 1621: attrType.AttrTypeNum = MathML_ATTR_IntFontstyle;
1622: IntAttr = TtaGetAttribute (el, attrType);
1623: if (attr != NULL)
1.157 quint 1624: /* there is a fontstyle or mathvariant attribute. Remove the
1625: IntFontstyle internal attribute that is not needed */
1.1 cvs 1626: {
1.142 quint 1627: if (IntAttr != NULL)
1628: TtaRemoveAttribute (el, IntAttr, doc);
1.1 cvs 1629: }
1.142 quint 1630: else
1.157 quint 1631: /* there is no fontstyle or mathvariant attribute. Create an internal
1632: IntFontstyle attribute with a value that depends on the content of
1633: the MI element */
1.1 cvs 1634: {
1.142 quint 1635: /* get content length */
1636: len = TtaGetElementVolume (el);
1637: if (len > 1)
1638: /* put an attribute IntFontstyle = IntNormal */
1639: {
1640: if (IntAttr == NULL)
1641: {
1642: IntAttr = TtaNewAttribute (attrType);
1643: TtaAttachAttribute (el, IntAttr, doc);
1644: }
1645: TtaSetAttributeValue (IntAttr,
1646: MathML_ATTR_IntFontstyle_VAL_IntNormal,
1647: el, doc);
1648: }
1649: else
1650: /* MI contains a single character. Remove attribute IntFontstyle
1651: if it exists, except if it's ImaginaryI, ExponentialE or
1652: DifferentialD */
1653: {
1654: italic = TRUE;
1655: textEl = TtaGetFirstChild (el);
1656: if (textEl != NULL)
1657: {
1658: elType = TtaGetElementType (textEl);
1659: if (elType.ElTypeNum == MathML_EL_MGLYPH)
1660: /* the content of the MI element is a MGLYPH element */
1661: /* check the length if it's alt attribute */
1662: {
1663: /* by default, use normal style */
1664: italic = FALSE;
1665: attrType.AttrTypeNum = MathML_ATTR_alt;
1666: attr = TtaGetAttribute (textEl, attrType);
1667: if (attr)
1668: /* the MGLYPH element has an alt attribute */
1669: {
1670: len = TtaGetTextAttributeLength (attr);
1671: if (len == 1)
1672: italic = TRUE;
1673: }
1674: }
1.163 quint 1675: else if (elType.ElTypeNum == MathML_EL_TEXT_UNIT)
1.142 quint 1676: {
1.166 quint 1677: len = TtaGetElementVolume (textEl);
1.163 quint 1678: if (len == 1)
1.166 quint 1679: /* the TEXT element contains a single character */
1.163 quint 1680: {
1.166 quint 1681: /* get that character */
1682: len = 2;
1683: TtaGiveBufferContent (textEl, text, len, &lang);
1.163 quint 1684: #ifndef _I18N_
1685: script = TtaGetScript (lang);
1686: #endif
1687: if (
1688: #ifndef _I18N_
1689: script == 'L' &&
1690: #endif
1691: text[0] >= '0' && text[0] <= '9')
1.166 quint 1692: /* that's a single digit */
1.163 quint 1693: italic = FALSE;
1.166 quint 1694: else
1695: #ifdef _I18N_
1696: /* is this the Unicode character for DifferentialD,
1697: ExponentialE or ImaginaryI? */
1698: if (text[0] == 0x2146 || text[0] == 0x2147 ||
1699: text[0] == 0x2148)
1700: italic = FALSE;
1701: #else
1.142 quint 1702: {
1.166 quint 1703: /* is there an attribute EntityName on that
1704: character? */
1705: attrType.AttrTypeNum = MathML_ATTR_EntityName;
1706: attr = TtaGetAttribute (textEl, attrType);
1707: if (attr)
1708: {
1709: len = TtaGetTextAttributeLength (attr);
1710: if (len > 0)
1711: {
1712: value = TtaGetMemory (len+1);
1713: TtaGiveTextAttributeValue (attr, value, &len);
1714: if (strcmp (&value[1], "ImaginaryI;") == 0 ||
1715: strcmp (&value[1], "ExponentialE;") == 0 ||
1716: strcmp (&value[1], "DifferentialD;") == 0)
1717: italic = FALSE;
1718: TtaFreeMemory (value);
1719: }
1720: }
1.142 quint 1721: }
1.166 quint 1722: #endif
1.142 quint 1723: }
1724: }
1725: if (italic)
1726: {
1727: if (IntAttr != NULL)
1728: TtaRemoveAttribute (el, IntAttr, doc);
1729: }
1730: else
1731: {
1732: /* put an attribute IntFontstyle = IntNormal */
1733: if (IntAttr == NULL)
1734: {
1735: attrType.AttrTypeNum = MathML_ATTR_IntFontstyle;
1736: IntAttr = TtaNewAttribute (attrType);
1737: TtaAttachAttribute (el, IntAttr, doc);
1738: }
1739: TtaSetAttributeValue (IntAttr,
1740: MathML_ATTR_IntFontstyle_VAL_IntNormal,
1741: el, doc);
1742: }
1743: }
1744: }
1.1 cvs 1745: }
1.142 quint 1746: }
1.1 cvs 1747: }
1748:
1749: /*----------------------------------------------------------------------
1.22 cvs 1750: SetIntAddSpaceAttr
1.1 cvs 1751: The content of a MO element has been created or modified.
1.22 cvs 1752: Create or change attribute IntAddSpace for that element accordingly.
1.1 cvs 1753: -----------------------------------------------------------------------*/
1.22 cvs 1754: void SetIntAddSpaceAttr (Element el, Document doc)
1.1 cvs 1755: {
1756: Element textEl, previous;
1757: ElementType elType;
1758: AttributeType attrType;
1.60 cvs 1759: Attribute attr, formAttr;
1.155 quint 1760: SSchema MathMLSSchema;
1.60 cvs 1761: int len, val, form;
1.146 quint 1762: CHAR_T text[2];
1.1 cvs 1763: Language lang;
1.143 vatton 1764: char script;
1.155 quint 1765: ThotBool comment;
1.1 cvs 1766:
1.155 quint 1767: MathMLSSchema = TtaGetElementType(el).ElSSchema;
1.60 cvs 1768: /* get the content of the mo element */
1.1 cvs 1769: textEl = TtaGetFirstChild (el);
1.155 quint 1770:
1771: /* skip comments if any */
1772: if (textEl)
1773: do
1774: {
1775: elType = TtaGetElementType (textEl);
1776: if (TtaSameSSchemas (elType.ElSSchema, MathMLSSchema) &&
1777: elType.ElTypeNum == MathML_EL_XMLcomment)
1778: /* it's a comment, skip it */
1779: TtaNextSibling (&textEl);
1780: }
1781: while (textEl && elType.ElTypeNum == MathML_EL_XMLcomment);
1782:
1783: if (textEl && elType.ElTypeNum == MathML_EL_TEXT_UNIT)
1784: /* the mo element is not empty */
1785: {
1786: /* does the mo element have an IntAddSpace attribute? */
1787: attrType.AttrSSchema = MathMLSSchema;
1788: attrType.AttrTypeNum = MathML_ATTR_IntAddSpace;
1789: attr = TtaGetAttribute (el, attrType);
1790: if (attr == NULL)
1.60 cvs 1791: /* no IntAddSpace Attr, create one */
1.1 cvs 1792: {
1.155 quint 1793: attr = TtaNewAttribute (attrType);
1794: TtaAttachAttribute (el, attr, doc);
1795: }
1796: /* space on both sides by default */
1797: val = MathML_ATTR_IntAddSpace_VAL_both;
1798: /* does the mo element have a form attribute? */
1799: attrType.AttrTypeNum = MathML_ATTR_form;
1800: formAttr = TtaGetAttribute (el, attrType);
1801: if (formAttr)
1802: /* there is a form attribute */
1803: {
1804: form = TtaGetAttributeValue (formAttr);
1805: switch (form)
1806: {
1807: case MathML_ATTR_form_VAL_prefix:
1808: val = MathML_ATTR_IntAddSpace_VAL_nospace;
1809: break;
1810: case MathML_ATTR_form_VAL_infix:
1811: val = MathML_ATTR_IntAddSpace_VAL_both;
1812: break;
1813: case MathML_ATTR_form_VAL_postfix:
1814: val = MathML_ATTR_IntAddSpace_VAL_spaceafter;
1815: break;
1816: default:
1817: val = MathML_ATTR_IntAddSpace_VAL_both;
1818: break;
1819: }
1.1 cvs 1820: }
1.155 quint 1821: else
1822: /* no form attribute. Analyze the content */
1823: {
1824: len = TtaGetElementVolume (textEl);
1825: if (len == 1)
1826: {
1827: TtaGiveBufferContent (textEl, text, len+1, &lang);
1828: script = TtaGetScript (lang);
1829: /* the mo element contains a single character */
1.146 quint 1830: #ifndef _I18N_
1.155 quint 1831: if (script == 'L')
1832: /* ISO-Latin 1 character */
1833: {
1.146 quint 1834: #endif
1.155 quint 1835: if (text[0] == '-'
1.153 quint 1836: #ifdef _I18N_
1.155 quint 1837: || text[0] == 0x2212 /* minus */
1.153 quint 1838: #endif
1.155 quint 1839: )
1840: /* prefix or infix operator? */
1841: {
1842: /* skip preceding comments if any */
1843: previous = el;
1844: do
1845: {
1846: comment = FALSE;
1847: TtaPreviousSibling (&previous);
1848: if (previous)
1849: {
1850: elType = TtaGetElementType (previous);
1851: comment = (TtaSameSSchemas (elType.ElSSchema, MathMLSSchema) &&
1852: elType.ElTypeNum == MathML_EL_XMLcomment);
1853: }
1854: }
1855: while (previous && comment);
1856:
1857: if (previous == NULL)
1858: /* no previous sibling => prefix operator */
1859: val = MathML_ATTR_IntAddSpace_VAL_nospace;
1860: else
1861: {
1862: elType = TtaGetElementType (previous);
1.158 quint 1863: if (elType.ElTypeNum == MathML_EL_MO ||
1864: elType.ElTypeNum == MathML_EL_OpeningFence ||
1865: elType.ElTypeNum == MathML_EL_ClosingFence ||
1866: elType.ElTypeNum == MathML_EL_FencedSeparator)
1.155 quint 1867: /* after an operator => prefix operator */
1868: val = MathML_ATTR_IntAddSpace_VAL_nospace;
1869: else
1870: /* infix operator */
1871: val = MathML_ATTR_IntAddSpace_VAL_both;
1872: }
1873: }
1874: else if (text[0] == '&' ||
1875: text[0] == '*' ||
1876: text[0] == '+' ||
1877: text[0] == '/' ||
1878: text[0] == '<' ||
1879: text[0] == '=' ||
1880: text[0] == '>' ||
1881: text[0] == '^' ||
1882: (int)text[0] == 177 || /* plus or minus */
1883: (int)text[0] == 215 || /* times */
1884: (int)text[0] == 247) /* divide */
1885: /* infix operator */
1886: val = MathML_ATTR_IntAddSpace_VAL_both;
1887: else if (text[0] == ',' ||
1888: text[0] == '!' ||
1889: text[0] == '&' ||
1890: text[0] == ':' ||
1891: text[0] == ';')
1892: /* separator */
1893: val = MathML_ATTR_IntAddSpace_VAL_spaceafter;
1894: else if (text[0] == '(' ||
1895: text[0] == ')' ||
1896: text[0] == '[' ||
1897: text[0] == ']' ||
1898: text[0] == '{' ||
1899: text[0] == '}' ||
1900: text[0] == '.' ||
1901: text[0] == '@' ||
1.165 quint 1902: #ifndef _I18N_
1903: text[0] == 'd' || /* probably DifferentialD */
1904: #endif
1.155 quint 1905: (int)text[0] == 129 || /* thin space */
1906: (int)text[0] == 130 || /* en space */
1907: (int)text[0] == 160) /* em space */
1908: val = MathML_ATTR_IntAddSpace_VAL_nospace;
1.146 quint 1909: #ifndef _I18N_
1.155 quint 1910: }
1911: else if (script == 'G')
1912: {
1913: /* Symbol character set */
1914: if ((int)text[0] == 163 || /* less or equal */
1915: (int)text[0] == 177 || /* plus or minus */
1916: (int)text[0] == 179 || /* greater or equal */
1917: (int)text[0] == 180 || /* times */
1918: (int)text[0] == 184 || /* divide */
1919: (int)text[0] == 185 || /* not equal */
1920: (int)text[0] == 186 || /* identical */
1921: (int)text[0] == 187 || /* equivalent */
1922: (int)text[0] == 196 || /* circle times */
1923: (int)text[0] == 197 || /* circle plus */
1924: ((int)text[0] >= 199 && (int)text[0] <= 209) || /* */
1925: (int)text[0] == 217 || /* and */
1926: (int)text[0] == 218) /* or */
1.146 quint 1927: #else
1.155 quint 1928: else
1929: if ((int)text[0] == 0x2264 || /* less or equal */
1930: (int)text[0] == 0x00B1 || /* plus or minus */
1931: (int)text[0] == 0x2265 || /* greater or equal */
1932: (int)text[0] == 0x00D7 || /* times */
1933: (int)text[0] == 0x00F7 || /* divide */
1934: (int)text[0] == 0x2260 || /* not equal */
1935: (int)text[0] == 0x2261 || /* identical */
1936: (int)text[0] == 0x2248 || /* equivalent */
1937: (int)text[0] == 0x2297 || /* circle times */
1938: (int)text[0] == 0x2295 || /* circle plus */
1939: (int)text[0] == 0x2229 || /* Intersection */
1940: (int)text[0] == 0x222A || /* Union */
1941: (int)text[0] == 0x2283 || /* Superset of */
1942: (int)text[0] == 0x2287 || /* Superset of or equal to */
1943: (int)text[0] == 0x2284 || /* Not a subset of */
1944: (int)text[0] == 0x2282 || /* Subset of */
1945: (int)text[0] == 0x2286 || /* Subset of or equal to */
1946: (int)text[0] == 0x2208 || /* Element of */
1947: (int)text[0] == 0x2209 || /* Not an element of */
1948: (int)text[0] == 0x2220 || /* Angle */
1949: (int)text[0] == 0x2207 || /* Nabla */
1950: (int)text[0] == 0x2227 || /* and */
1951: (int)text[0] == 0x2228 || /* or */
1952: (int)text[0] == 0x2190 || /* left arrow */
1953: (int)text[0] == 0x2192 || /* right arrow */
1954: (int)text[0] == 0x2194) /* left right arrow */
1.146 quint 1955: #endif
1.155 quint 1956: /* infix operator */
1957: val = MathML_ATTR_IntAddSpace_VAL_both;
1958: else
1959: val = MathML_ATTR_IntAddSpace_VAL_nospace;
1.146 quint 1960: #ifndef _I18N_
1.155 quint 1961: }
1.146 quint 1962: #endif
1.155 quint 1963: }
1964: }
1965: TtaSetAttributeValue (attr, val, el, doc);
1966: }
1.1 cvs 1967: }
1968:
1969: /*----------------------------------------------------------------------
1.58 cvs 1970: ChildOfMRowOrInferred
1971: Return TRUE if element el is a child of a MROW element or an
1972: inferred MROW element
1973: ----------------------------------------------------------------------*/
1974: ThotBool ChildOfMRowOrInferred (Element el)
1975: {
1976: ElementType elType;
1977: Element parent;
1978: ThotBool result;
1979:
1980: result = FALSE;
1981: parent = TtaGetParent (el);
1982: if (parent)
1983: {
1984: elType = TtaGetElementType (parent);
1985: result = (elType.ElTypeNum == MathML_EL_MROW ||
1986: elType.ElTypeNum == MathML_EL_SqrtBase ||
1987: elType.ElTypeNum == MathML_EL_MSTYLE ||
1988: elType.ElTypeNum == MathML_EL_MERROR ||
1.92 cvs 1989: elType.ElTypeNum == MathML_EL_MENCLOSE ||
1.58 cvs 1990: elType.ElTypeNum == MathML_EL_MPADDED ||
1991: elType.ElTypeNum == MathML_EL_MPHANTOM ||
1.158 quint 1992: elType.ElTypeNum == MathML_EL_MFENCED ||
1.58 cvs 1993: elType.ElTypeNum == MathML_EL_CellWrapper ||
1.92 cvs 1994: elType.ElTypeNum == MathML_EL_MathML ||
1.58 cvs 1995: elType.ElTypeNum == MathML_EL_FencedExpression);
1996: }
1997: return result;
1998: }
1999:
2000: /*----------------------------------------------------------------------
1.175 quint 2001: CheckLargeOp
1.84 cvs 2002: If el is a MO element,
1.175 quint 2003: if it's a large operator (∑ for instance), put a presentation
2004: rule to enlarge the character.
1.1 cvs 2005: ----------------------------------------------------------------------*/
1.175 quint 2006: void CheckLargeOp (Element el, Document doc)
1.1 cvs 2007: {
1.158 quint 2008: ElementType elType, contType;
1.170 quint 2009: Element content, ancestor;
1.128 vatton 2010: AttributeType attrType;
1.175 quint 2011: Attribute attrLargeop, attr;
1.128 vatton 2012: Language lang;
1.84 cvs 2013: PresentationValue pval;
2014: PresentationContext ctxt;
1.128 vatton 2015: CHAR_T text[2];
1.143 vatton 2016: char script;
1.175 quint 2017: int len, val;
1.170 quint 2018: ThotBool largeop;
1.1 cvs 2019:
2020: elType = TtaGetElementType (el);
1.175 quint 2021: if (elType.ElTypeNum == MathML_EL_MO)
2022: /* the element is a MO */
1.58 cvs 2023: {
1.84 cvs 2024: content = TtaGetFirstChild (el);
2025: if (content != NULL)
2026: {
1.158 quint 2027: contType = TtaGetElementType (content);
2028: if (contType.ElTypeNum == MathML_EL_TEXT_UNIT)
1.84 cvs 2029: {
1.146 quint 2030: len = TtaGetElementVolume (content);
1.84 cvs 2031: if (len == 1)
2032: /* the MO element contains a single character */
2033: {
1.146 quint 2034: TtaGiveBufferContent (content, text, len+1, &lang);
1.143 vatton 2035: script = TtaGetScript (lang);
1.170 quint 2036: largeop = FALSE;
1.175 quint 2037: /* is there an attribute largeop on this MO element? */
1.170 quint 2038: attrType.AttrSSchema = elType.ElSSchema;
2039: attrType.AttrTypeNum = MathML_ATTR_largeop;
2040: attrLargeop = TtaGetAttribute (el, attrType);
2041: if (attrLargeop)
2042: /* there is an attribute largeop. Just take its value */
2043: largeop = (TtaGetAttributeValue (attrLargeop) == MathML_ATTR_largeop_VAL_true);
2044: else
2045: /* no attribute largeop */
2046: {
2047: /* first look for an IntDisplaystyle attribute on an ancestor */
2048: attrType.AttrSSchema = elType.ElSSchema;
2049: attrType.AttrTypeNum = MathML_ATTR_IntDisplaystyle;
2050: ancestor = el;
2051: do
2052: {
2053: attr = TtaGetAttribute (ancestor, attrType);
2054: if (!attr)
2055: ancestor = TtaGetParent(ancestor);
2056: }
2057: while (!attr && ancestor);
2058: if (attr)
2059: /* there is an ancestor with an attribute IntDisplaystyle */
2060: {
2061: val = TtaGetAttributeValue (attr);
2062: if (val == MathML_ATTR_IntDisplaystyle_VAL_true)
2063: /* an ancestor has an attribute IntDisplaystyle = true */
2064: /* Look at the symbol */
1.171 carcone 2065: largeop = IsLargeOp (text[0], script);
1.170 quint 2066: }
2067: }
2068: ctxt = TtaGetSpecificStyleContext (doc);
2069: if (largeop)
2070: /* it's a large operator. Make it larger */
1.84 cvs 2071: {
2072: ctxt->destroy = FALSE;
2073: /* the specific presentation to be created is not a CSS rule */
1.147 quint 2074: ctxt->cssSpecificity = 0;
1.84 cvs 2075: pval.typed_data.unit = STYLE_UNIT_PERCENT;
2076: pval.typed_data.real = FALSE;
2077: pval.typed_data.value = 180;
2078: }
1.170 quint 2079: else
2080: /* it's not a large operator, remove the Size presentation rule
2081: if it's present */
2082: {
2083: ctxt->destroy = TRUE;
2084: pval.typed_data.value = 0;
2085: }
2086: TtaSetStylePresentation (PRSize, content, NULL, ctxt, pval);
1.175 quint 2087: }
2088: }
2089: }
2090: }
2091: }
2092:
2093: /*----------------------------------------------------------------------
2094: CheckFence
2095: If el is a MO element of a fence,
2096: if it's a child of a MROW (or equivalent) element and if it contains
2097: a single fence character, transform the MO into a MF and the fence
2098: character into a Thot stretchable symbol.
2099: ----------------------------------------------------------------------*/
2100: void CheckFence (Element el, Document doc)
2101: {
2102: ElementType elType, contType;
2103: Element content;
2104: AttributeType attrType;
2105: Attribute attr, attrStretchy;
2106: Language lang;
2107: CHAR_T text[2];
2108: char script;
2109: unsigned char c;
2110: int len, val, oldStructureChecking;
1.170 quint 2111:
1.175 quint 2112: elType = TtaGetElementType (el);
2113: if (elType.ElTypeNum == MathML_EL_MO ||
2114: elType.ElTypeNum == MathML_EL_OpeningFence ||
2115: elType.ElTypeNum == MathML_EL_ClosingFence ||
2116: elType.ElTypeNum == MathML_EL_FencedSeparator)
2117: /* the element is a MO or equivalent */
2118: {
2119: content = TtaGetFirstChild (el);
2120: if (content != NULL)
2121: {
2122: contType = TtaGetElementType (content);
2123: if (contType.ElTypeNum == MathML_EL_TEXT_UNIT)
2124: {
2125: len = TtaGetElementVolume (content);
2126: if (len == 1)
2127: /* the MO or fence element contains a single character */
2128: {
2129: TtaGiveBufferContent (content, text, len+1, &lang);
2130: script = TtaGetScript (lang);
2131: if (ChildOfMRowOrInferred (el))
2132: /* the MO or fence element is a child of a MROW element */
1.170 quint 2133: /* Is it a stretchable symbol? */
1.1 cvs 2134: {
1.175 quint 2135: if (IsStretchy (text[0], script))
1.84 cvs 2136: /* it's a stretchable parenthesis or equivalent */
2137: {
2138: /* remove the content of the MO element */
2139: TtaDeleteTree (content, doc);
2140: /* change the MO element into a MF element */
1.158 quint 2141: if (elType.ElTypeNum == MathML_EL_MO)
2142: ChangeTypeOfElement (el, doc, MathML_EL_MF);
1.84 cvs 2143: /* is there an attribute stretchy on this mo element? */
2144: attrType.AttrSSchema = elType.ElSSchema;
2145: attrType.AttrTypeNum = MathML_ATTR_stretchy;
2146: attrStretchy = TtaGetAttribute (el, attrType);
2147: if (attrStretchy)
2148: val = TtaGetAttributeValue (attrStretchy);
2149: else
2150: val = MathML_ATTR_stretchy_VAL_true;
2151: if (val == MathML_ATTR_stretchy_VAL_true)
2152: {
1.158 quint 2153: /* attach a IntVertStretch attribute to the MF element */
1.84 cvs 2154: attrType.AttrTypeNum = MathML_ATTR_IntVertStretch;
1.158 quint 2155: attr = TtaGetAttribute (el, attrType);
2156: if (!attr)
2157: {
2158: attr = TtaNewAttribute (attrType);
2159: TtaAttachAttribute (el, attr, doc);
2160: }
1.84 cvs 2161: TtaSetAttributeValue (attr,
2162: MathML_ATTR_IntVertStretch_VAL_yes_,
2163: el, doc);
2164: }
2165: /* create a new content for the MF element */
1.87 cvs 2166: elType.ElTypeNum = MathML_EL_SYMBOL_UNIT;
1.146 quint 2167: #ifdef _I18N_
2168: if (text[0] == 9002)
2169: #else
1.143 vatton 2170: if (script == 'G' && text[0] == 241)
1.146 quint 2171: #endif
1.102 cvs 2172: c = '>'; /* RightAngleBracket */
2173: else
1.146 quint 2174: #ifdef _I18N_
2175: if (text[0] == 9001)
2176: #else
2177: if (script == 'G' && text[0] == 225)
2178: #endif
2179: c = '<'; /* LeftAngleBracket */
2180: else
2181: c = (char) text[0];
1.84 cvs 2182: content = TtaNewElement (doc, elType);
1.158 quint 2183: /* do not check the Thot abstract tree against the structure
2184: schema while inserting this child element */
2185: oldStructureChecking = TtaGetStructureChecking (doc);
2186: TtaSetStructureChecking (0, doc);
1.84 cvs 2187: TtaInsertFirstChild (&content, el, doc);
2188: TtaSetGraphicsShape (content, c, doc);
1.158 quint 2189: /* resume structure checking */
2190: TtaSetStructureChecking ((ThotBool)oldStructureChecking, doc);
1.84 cvs 2191: }
1.1 cvs 2192: }
1.84 cvs 2193: }
2194: }
1.58 cvs 2195: }
2196: }
1.1 cvs 2197: }
2198:
2199: /*----------------------------------------------------------------------
2200: CreateFencedSeparators
2201: Create FencedSeparator elements within the fencedExpression
2202: according to attribute separators of the MFENCED element.
2203: ----------------------------------------------------------------------*/
1.110 cvs 2204: void CreateFencedSeparators (Element fencedExpression, Document doc, ThotBool record)
1.1 cvs 2205: {
2206: ElementType elType;
2207: Element child, separator, leaf, next, prev, mfenced;
2208: AttributeType attrType;
2209: Attribute attr;
2210: int length, sep, i;
2211: Language lang;
1.116 cvs 2212: char text[32], sepValue[4];
1.1 cvs 2213:
2214: /* get the separators attribute */
2215: mfenced = TtaGetParent (fencedExpression);
2216: elType = TtaGetElementType (fencedExpression);
2217: attrType.AttrSSchema = elType.ElSSchema;
2218: attrType.AttrTypeNum = MathML_ATTR_separators;
2219: text[0] = ','; /* default value is sparators="," */
2220: text[1] = EOS;
2221: length = 1;
2222: attr = TtaGetAttribute (mfenced, attrType);
2223: if (attr != NULL)
2224: {
2225: length = 31;
2226: TtaGiveTextAttributeValue (attr, text, &length);
2227: }
2228:
2229: /* create FencedSeparator elements in the FencedExpression */
2230: prev = NULL;
2231: sep = 0;
2232: /* skip leading spaces in attribute separators */
2233: while (text[sep] <= SPACE && text[sep] != EOS)
2234: sep++;
2235: /* if attribute separators is empty or contains only spaces, do not
2236: insert any separator element */
2237: if (text[sep] != EOS)
2238: {
2239: child = TtaGetFirstChild (fencedExpression);
2240: while (child != NULL)
2241: {
2242: next = child;
2243: TtaNextSibling (&next);
2244: elType = TtaGetElementType (child);
2245: if (elType.ElTypeNum != MathML_EL_Construct)
2246: {
2247: if (prev != NULL)
2248: {
2249: elType.ElTypeNum = MathML_EL_FencedSeparator;
2250: separator = TtaNewElement (doc, elType);
2251: TtaInsertSibling (separator, prev, FALSE, doc);
2252: elType.ElTypeNum = MathML_EL_TEXT_UNIT;
2253: leaf = TtaNewElement (doc, elType);
2254: TtaInsertFirstChild (&leaf, separator, doc);
2255: sepValue[0] = text[sep];
1.158 quint 2256: sepValue[1] = EOS;
1.143 vatton 2257: lang = TtaGetLanguageIdFromScript('L');
1.1 cvs 2258: TtaSetTextContent (leaf, sepValue, lang, doc);
1.158 quint 2259: SetIntAddSpaceAttr (separator, doc);
2260: SetIntVertStretchAttr (separator, doc, 0, NULL);
1.175 quint 2261: CheckFence (separator, doc);
1.158 quint 2262:
1.1 cvs 2263: /* is there a following non-space character in separators? */
2264: i = sep + 1;
2265: while (text[i] <= SPACE && text[i] != EOS)
2266: i++;
2267: if (text[i] > SPACE && text[i] != EOS)
2268: sep = i;
1.17 cvs 2269: if (record)
2270: TtaRegisterElementCreate (separator, doc);
1.1 cvs 2271: }
2272: prev = child;
2273: }
2274: child = next;
2275: }
2276: }
2277: }
2278:
1.124 cvs 2279: /*----------------------------------------------------------------------
2280: CreateOpeningOrClosingFence
2281: Create the OpeningFence or ClosingFence element (depending on parameter
2282: open) for the MFENCED element el which contain the fencedExpression
2283: element.
2284: ----------------------------------------------------------------------*/
2285: static void CreateOpeningOrClosingFence (Element fencedExpression,
2286: Element el, Document doc,
2287: ThotBool open)
2288: {
2289: ElementType elType;
2290: Element leaf, fence;
2291: AttributeType attrType;
2292: Attribute attr;
2293: int length;
2294: char text[32];
2295:
2296: elType = TtaGetElementType (el);
2297: attrType.AttrSSchema = elType.ElSSchema;
2298: if (open)
2299: {
1.158 quint 2300: text[0] = '('; /* default value of attribute 'open' */
1.124 cvs 2301: attrType.AttrTypeNum = MathML_ATTR_open;
2302: elType.ElTypeNum = MathML_EL_OpeningFence;
2303: }
2304: else
2305: {
1.158 quint 2306: text[0] = ')'; /* default value of attribute 'close' */
1.124 cvs 2307: attrType.AttrTypeNum = MathML_ATTR_close;
2308: elType.ElTypeNum = MathML_EL_ClosingFence;
2309: }
2310: attr = TtaGetAttribute (el, attrType);
2311: if (attr != NULL)
2312: {
2313: length = 31;
2314: TtaGiveTextAttributeValue (attr, text, &length);
2315: if (length != 1)
2316: /* content of attribute open or close should be a single character */
1.158 quint 2317: text[0] = '?';
1.124 cvs 2318: }
1.158 quint 2319: text[1] = EOS;
1.124 cvs 2320: fence = TtaNewElement (doc, elType);
2321: TtaInsertSibling (fence, fencedExpression, open, doc);
1.158 quint 2322: elType.ElTypeNum = MathML_EL_TEXT_UNIT;
1.124 cvs 2323: leaf = TtaNewElement (doc, elType);
2324: TtaInsertFirstChild (&leaf, fence, doc);
1.158 quint 2325: TtaSetTextContent (leaf, text, TtaGetLanguageIdFromScript('L'), doc);
2326: SetIntAddSpaceAttr (fence, doc);
2327: SetIntVertStretchAttr (fence, doc, 0, NULL);
1.175 quint 2328: CheckFence (fence, doc);
1.124 cvs 2329: }
1.1 cvs 2330:
2331: /*----------------------------------------------------------------------
2332: TransformMFENCED
2333: Transform the content of a MFENCED element: create elements
2334: OpeningFence, FencedExpression, ClosingFence and FencedSeparator.
2335: ----------------------------------------------------------------------*/
1.46 cvs 2336: static void TransformMFENCED (Element el, Document doc)
1.1 cvs 2337: {
2338: ElementType elType;
1.124 cvs 2339: Element child, fencedExpression, next, prev, firstChild;
1.1 cvs 2340:
2341: child = TtaGetFirstChild (el);
2342: if (child != NULL)
2343: elType = TtaGetElementType (child);
2344: if (child != NULL && elType.ElTypeNum == MathML_EL_OpeningFence)
2345: /* The first child of this MFENCED element is an OpeningFence.
2346: This MFENCED expression has already been transformed, possibly
2347: by the Transform command */
2348: {
2349: TtaNextSibling (&child);
2350: fencedExpression = child;
2351: if (fencedExpression != NULL)
2352: elType = TtaGetElementType (fencedExpression);
2353: if (elType.ElTypeNum == MathML_EL_FencedExpression)
2354: /* the second child is a FencedExpression. OK.
2355: Remove all existing FencedSeparator elements */
2356: {
2357: child = TtaGetFirstChild (fencedExpression);
2358: prev = NULL;
2359: while (child != NULL)
2360: {
2361: elType = TtaGetElementType (child);
2362: next = child;
2363: TtaNextSibling (&next);
2364: if (elType.ElTypeNum == MathML_EL_FencedSeparator)
2365: /* Remove this separator */
2366: TtaDeleteTree (child, doc);
2367: child = next;
2368: }
2369: /* create FencedSeparator elements in the FencedExpression */
1.17 cvs 2370: CreateFencedSeparators (fencedExpression, doc, FALSE);
1.1 cvs 2371: }
2372: }
2373: else
2374: /* this MFENCED element must be transformed */
2375: {
2376: /* create a FencedExpression element as a child of the MFENCED elem. */
2377: elType = TtaGetElementType (el);
2378: elType.ElTypeNum = MathML_EL_FencedExpression;
2379: fencedExpression = TtaNewElement (doc, elType);
2380: TtaInsertFirstChild (&fencedExpression, el, doc);
2381: if (child == NULL)
2382: /* empty MFENCED element */
2383: {
2384: elType.ElTypeNum = MathML_EL_Construct;
2385: child = TtaNewElement (doc, elType);
2386: TtaInsertFirstChild (&child, fencedExpression, doc);
1.22 cvs 2387: SetIntPlaceholderAttr (child, doc);
1.1 cvs 2388: }
2389: else
2390: {
2391: /* move the content of the MFENCED element within the new
2392: FencedExpression element */
2393: prev = NULL;
2394: firstChild = NULL;
2395: while (child != NULL)
2396: {
2397: next = child;
2398: TtaNextSibling (&next);
2399: TtaRemoveTree (child, doc);
2400: if (prev == NULL)
2401: {
2402: TtaInsertFirstChild (&child, fencedExpression, doc);
2403: firstChild = child;
2404: }
2405: else
2406: TtaInsertSibling (child, prev, FALSE, doc);
2407: prev = child;
2408: child = next;
2409: }
2410:
2411: /* create FencedSeparator elements in the FencedExpression */
1.17 cvs 2412: CreateFencedSeparators (fencedExpression, doc, FALSE);
1.1 cvs 2413:
2414: /* Create placeholders within the FencedExpression element */
2415: CreatePlaceholders (firstChild, doc);
2416: }
2417:
2418: /* create the OpeningFence element according to the open attribute */
1.124 cvs 2419: CreateOpeningOrClosingFence (fencedExpression, el, doc, TRUE);
1.1 cvs 2420:
2421: /* create the ClosingFence element according to close attribute */
1.124 cvs 2422: CreateOpeningOrClosingFence (fencedExpression, el, doc, FALSE);
1.1 cvs 2423: }
2424: }
2425:
2426: /*----------------------------------------------------------------------
1.59 cvs 2427: MathMLScriptShift
2428: The MathML attribute attr (superscriptshift or subscriptshift) is associated
2429: with element el (a msub, msup or msubsup).
2430: If value is not NULL, generate the corresponding Thot VertPos rule for the
2431: Subscript or Superscript child of el.
2432: If value is NULL, remove the Thot VertPos rule.
2433: -----------------------------------------------------------------------*/
1.120 cvs 2434: void MathMLScriptShift (Document doc, Element el, char *value, int attr)
1.59 cvs 2435: {
2436: ElementType elType;
2437: Element script, child;
2438: int scrType;
2439: PresentationValue pval;
2440: PresentationContext ctxt;
2441:
2442: /* get the Superscript or Subscript child of el */
2443: if (attr == MathML_ATTR_superscriptshift)
2444: scrType = MathML_EL_Superscript;
2445: else if (attr == MathML_ATTR_subscriptshift)
2446: scrType = MathML_EL_Subscript;
2447: else
2448: return;
2449: script = NULL;
2450: child = TtaGetFirstChild (el);
2451: while (!script && child)
2452: {
2453: elType = TtaGetElementType (child);
2454: if (elType.ElTypeNum == scrType)
2455: script = child;
2456: else
2457: TtaNextSibling (&child);
2458: }
2459: if (script)
2460: /* Superscript or Subscript element found */
2461: {
2462: ctxt = TtaGetSpecificStyleContext (doc);
2463: if (!value)
2464: /* remove the presentation rule */
2465: {
2466: ctxt->destroy = TRUE;
1.75 cvs 2467: pval.typed_data.value = 0;
1.59 cvs 2468: TtaSetStylePresentation (PRVertPos, script, NULL, ctxt, pval);
2469: }
2470: else
2471: {
2472: ctxt->destroy = FALSE;
2473: /* parse the attribute value (a number followed by a unit) */
1.119 cvs 2474: value = TtaSkipBlanks (value);
1.59 cvs 2475: value = ParseCSSUnit (value, &pval);
2476: if (pval.typed_data.unit != STYLE_UNIT_INVALID)
2477: {
1.78 cvs 2478: /* the specific presentation to be created is not a CSS rule */
1.147 quint 2479: ctxt->cssSpecificity = 0;
1.59 cvs 2480: if (attr == MathML_ATTR_superscriptshift)
2481: pval.typed_data.value = - pval.typed_data.value;
2482: TtaSetStylePresentation (PRVertPos, script, NULL, ctxt, pval);
2483: }
2484: }
2485: TtaFreeMemory (ctxt);
2486: }
2487: }
2488:
2489: /*----------------------------------------------------------------------
2490: SetScriptShift
2491: If element el (which is a msup, msub or msubsup) has an attribute
2492: att (which is subscriptshift or superscriptshift), generate the
2493: corresponding Thot presentation rule.
2494: ----------------------------------------------------------------------*/
1.120 cvs 2495: static void SetScriptShift (Element el, Document doc, int att)
1.59 cvs 2496: {
2497: AttributeType attrType;
2498: ElementType elType;
2499: Attribute attr;
1.120 cvs 2500: char *value;
1.59 cvs 2501: int length;
2502:
2503: elType = TtaGetElementType (el);
2504: attrType.AttrSSchema = elType.ElSSchema;
2505: attrType.AttrTypeNum = att;
2506: attr = TtaGetAttribute (el, attrType);
2507: if (attr)
2508: {
2509: length = TtaGetTextAttributeLength (attr);
2510: if (length > 0)
2511: {
1.116 cvs 2512: value = TtaGetMemory (length+1);
1.59 cvs 2513: value[0] = EOS;
2514: TtaGiveTextAttributeValue (attr, value, &length);
2515: MathMLScriptShift (doc, el, value, att);
2516: TtaFreeMemory (value);
2517: }
2518: }
2519: }
2520:
2521: /*----------------------------------------------------------------------
1.159 quint 2522: DeleteIntRowAlign
2523: Remove attribute IntRowAlign from element row if there is no rowalign_mtr
2524: attribut on this element.
2525: -----------------------------------------------------------------------*/
2526: static void DeleteIntRowAlign (Element row, Document doc)
2527: {
2528: ElementType elType;
2529: AttributeType attrType;
2530: Attribute attr;
2531:
2532: elType = TtaGetElementType (row);
2533: attrType.AttrSSchema = elType.ElSSchema;
2534: attrType.AttrTypeNum = MathML_ATTR_rowalign_mtr;
2535: attr = TtaGetAttribute (row, attrType);
2536: if (!attr)
2537: {
2538: attrType.AttrTypeNum = MathML_ATTR_IntRowAlign;
2539: attr = TtaGetAttribute (row, attrType);
2540: if (attr)
2541: TtaRemoveAttribute (row, attr, doc);
2542: }
2543: }
2544:
2545: /*----------------------------------------------------------------------
2546: SetIntRowAlign
2547: Set attribute IntRowAlign for element row unless this element already has
2548: a rowalign_mtr attribute
2549: -----------------------------------------------------------------------*/
2550: static void SetIntRowAlign (Element row, int val, Document doc)
2551: {
2552: ElementType elType;
2553: AttributeType attrType;
2554: Attribute attr;
2555:
2556: elType = TtaGetElementType (row);
2557: attrType.AttrSSchema = elType.ElSSchema;
2558: attrType.AttrTypeNum = MathML_ATTR_rowalign_mtr;
2559: attr = TtaGetAttribute (row, attrType);
2560: if (!attr)
2561: {
2562: attrType.AttrTypeNum = MathML_ATTR_IntRowAlign;
2563: attr = TtaGetAttribute (row, attrType);
2564: if (!attr)
2565: {
2566: attr = TtaNewAttribute (attrType);
2567: TtaAttachAttribute (row, attr, doc);
2568: }
2569: TtaSetAttributeValue (attr, val, row, doc);
2570: }
2571: }
2572:
2573: /*----------------------------------------------------------------------
2574: HandleRowalignAttribute
2575: An attribute rowalign has been created, updated (if !delete) or deleted
2576: (if delete) for element el in document doc. Update the IntRowAlign
2577: attributes of all enclosed mrow elements accordingly.
2578: ----------------------------------------------------------------------*/
2579: void HandleRowalignAttribute (Attribute attr, Element el, Document doc,
2580: ThotBool delete)
2581: {
2582: char *value;
2583: char *ptr;
2584: int length, val;
2585: ElementType elType;
2586: Element row;
2587:
2588: elType = TtaGetElementType (el);
2589: if (elType.ElTypeNum != MathML_EL_MTABLE ||
2590: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML"))
2591: /* ignore rowalign attribute on mstyle elements */
2592: /* process it only on mtable elements */
2593: return;
2594:
2595: value = NULL;
2596: if (!delete)
2597: {
2598: length = TtaGetTextAttributeLength (attr);
2599: if (length > 0)
2600: {
2601: value = TtaGetMemory (length+1);
2602: value[0] = EOS;
2603: TtaGiveTextAttributeValue (attr, value, &length);
2604: }
2605: }
2606: /* if attribute rowalign is created or updated but has no value, don't
2607: do anything */
2608: if (!delete && !value)
2609: return;
2610:
2611: ptr = value;
2612: val = 0;
2613: elType.ElTypeNum = MathML_EL_TableRow;
2614: row = TtaSearchTypedElement (elType, SearchInTree, el);
2615: while (row)
2616: {
2617: elType = TtaGetElementType (row);
2618: /* skip comments and other non row elements */
2619: if ((elType.ElTypeNum == MathML_EL_MTR ||
2620: elType.ElTypeNum == MathML_EL_MLABELEDTR) &&
2621: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML") == 0)
2622: {
2623: if (delete)
2624: DeleteIntRowAlign (row, doc);
2625: else
2626: {
2627: if (*ptr != EOS)
2628: {
2629: /* get next word in the attribute value */
2630: ptr = TtaSkipBlanks (ptr);
2631: /* process that word */
2632: if (*ptr != EOS && *ptr != ' ')
2633: {
2634: if (!strncasecmp (ptr, "top", 3))
2635: val = MathML_ATTR_IntRowAlign_VAL_IntTop;
2636: else if (!strncasecmp (ptr, "bottom", 6))
2637: val = MathML_ATTR_IntRowAlign_VAL_IntBottom;
2638: else if (!strncasecmp (ptr, "center", 6))
2639: val = MathML_ATTR_IntRowAlign_VAL_IntCenter;
2640: else if (!strncasecmp (ptr, "baseline", 8))
2641: val = MathML_ATTR_IntRowAlign_VAL_IntBaseline;
2642: else if (!strncasecmp (ptr, "axis", 4))
2643: val = MathML_ATTR_IntRowAlign_VAL_IntAxis;
2644: else
2645: val = 0;
2646: /* skip the word that has been processed */
2647: while (*ptr != EOS && *ptr != ' ')
2648: ptr++;
2649: }
2650: }
2651: if (val > 0)
2652: SetIntRowAlign (row, val, doc);
2653: }
2654: }
2655: TtaNextSibling (&row);
2656: }
2657: if (value)
2658: TtaFreeMemory (value);
2659: }
2660:
2661: /*----------------------------------------------------------------------
2662: DeleteIntColAlign
2663: Remove attribute IntColAlign from element cell if there is no columnalign_mtd
2664: attribut on this element.
2665: -----------------------------------------------------------------------*/
2666: static void DeleteIntColAlign (Element cell, Document doc)
2667: {
2668: ElementType elType;
2669: AttributeType attrType;
2670: Attribute attr;
2671:
2672: elType = TtaGetElementType (cell);
2673: attrType.AttrSSchema = elType.ElSSchema;
2674: attrType.AttrTypeNum = MathML_ATTR_columnalign_mtd;
2675: attr = TtaGetAttribute (cell, attrType);
2676: if (!attr)
2677: {
2678: attrType.AttrTypeNum = MathML_ATTR_IntColAlign;
2679: attr = TtaGetAttribute (cell, attrType);
2680: if (attr)
2681: TtaRemoveAttribute (cell, attr, doc);
2682: }
2683: }
2684:
2685: /*----------------------------------------------------------------------
2686: SetIntColAlign
2687: Set attribute IntColAlign for element cell unless this element already has
2688: a columnalign_mtd attribute
2689: -----------------------------------------------------------------------*/
2690: static void SetIntColAlign (Element cell, int val, Document doc)
2691: {
2692: ElementType elType;
2693: AttributeType attrType;
2694: Attribute attr;
2695:
2696: elType = TtaGetElementType (cell);
2697: attrType.AttrSSchema = elType.ElSSchema;
2698: attrType.AttrTypeNum = MathML_ATTR_columnalign_mtd;
2699: attr = TtaGetAttribute (cell, attrType);
2700: if (!attr)
2701: {
2702: attrType.AttrTypeNum = MathML_ATTR_IntColAlign;
2703: attr = TtaGetAttribute (cell, attrType);
2704: if (!attr)
2705: {
2706: attr = TtaNewAttribute (attrType);
2707: TtaAttachAttribute (cell, attr, doc);
2708: }
2709: TtaSetAttributeValue (attr, val, cell, doc);
2710: }
2711: }
2712:
2713: /*----------------------------------------------------------------------
2714: RowWithoutColalignAttr
2715: if skip: if element row has a columnalign attribute, get the next sibling row
2716: element without a columnalign attribute and return its first cell
2717: if not skip: always return the first cell in the row, and the columnalign
2718: attribute of that row if there is one.
2719: -----------------------------------------------------------------------*/
2720: static void RowWithoutColalignAttr (Element *row, Element *cell,
2721: Attribute *attr, ThotBool skip)
2722: {
2723: ElementType elType;
2724: AttributeType attrType;
2725:
2726: elType = TtaGetElementType (*row);
2727: attrType.AttrSSchema = elType.ElSSchema;
2728: attrType.AttrTypeNum = MathML_ATTR_columnalign;
2729: *cell = NULL;
2730: *attr = NULL;
2731: while (*row != NULL && *cell == NULL)
2732: {
2733: elType = TtaGetElementType (*row);
2734: if ((elType.ElTypeNum != MathML_EL_MTR &&
2735: elType.ElTypeNum != MathML_EL_MLABELEDTR) ||
2736: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML"))
2737: /* not a row. Skip it */
2738: TtaNextSibling (row);
2739: else
2740: {
2741: /* skip that row if it has a columnalign attribute */
2742: *attr = TtaGetAttribute (*row, attrType);
2743: if (skip && *attr != NULL)
2744: {
2745: TtaNextSibling (row);
2746: *attr = NULL;
2747: }
2748: else
2749: /* it's a row without a columnalign attribute */
2750: *cell = TtaGetFirstChild (*row);
2751: }
2752: }
2753: }
2754:
2755: /*----------------------------------------------------------------------
2756: HandleColalignAttribute
2757: An attribute columnalign has been created, updated (if !delete) or deleted
2758: (if delete) for element el in document doc. Update the IntColAlign
2759: attributes of all concerned cells accordingly.
2760: If allRows is TRUE, process also rows that have their own columnalign
2761: attribute, according to that attribute, otherwise skip those rows.
2762: ----------------------------------------------------------------------*/
2763: void HandleColalignAttribute (Attribute attr, Element el, Document doc,
2764: ThotBool delete, ThotBool allRows)
2765: {
2766: char *value, *localValue;
2767: char *ptr;
2768: int length, val;
2769: ElementType elType;
2770: Element cell, row;
2771: Attribute localAttr;
2772: ThotBool fullTable;
2773:
2774: elType = TtaGetElementType (el);
2775: if ((elType.ElTypeNum != MathML_EL_MTABLE &&
2776: elType.ElTypeNum != MathML_EL_MTR &&
2777: elType.ElTypeNum != MathML_EL_MLABELEDTR) ||
2778: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML"))
2779: /* ignore columnalign attribute on mstyle elements */
2780: /* process it only on mtable elements */
2781: return;
2782:
2783: fullTable = (elType.ElTypeNum == MathML_EL_MTABLE);
2784: value = NULL;
2785: localValue = NULL;
2786: if (!delete)
2787: {
2788: length = TtaGetTextAttributeLength (attr);
2789: if (length > 0)
2790: {
2791: value = TtaGetMemory (length+1);
2792: value[0] = EOS;
2793: TtaGiveTextAttributeValue (attr, value, &length);
2794: }
2795: }
2796: /* if attribute columnalign is created or updated but has no value, don't
2797: do anything */
2798: if (!delete && !value)
2799: return;
2800:
2801: ptr = value;
2802: val = 0;
2803: /* get the first cell within the element */
2804: elType.ElTypeNum = MathML_EL_MTD;
2805: cell = TtaSearchTypedElement (elType, SearchInTree, el);
2806: if (cell && fullTable)
2807: {
2808: elType.ElTypeNum = MathML_EL_TableRow;
2809: row = TtaGetTypedAncestor (cell, elType);
2810: RowWithoutColalignAttr (&row, &cell, &localAttr, !allRows);
2811: if (localAttr)
2812: {
2813: length = TtaGetTextAttributeLength (localAttr);
2814: if (length > 0)
2815: {
2816: if (localValue)
2817: TtaFreeMemory (localValue);
2818: localValue = TtaGetMemory (length+1);
2819: localValue[0] = EOS;
2820: TtaGiveTextAttributeValue (localAttr, localValue, &length);
2821: ptr = localValue;
2822: }
2823: }
2824: }
2825: while (cell)
2826: {
2827: elType = TtaGetElementType (cell);
2828: /* skip comments and other non cell elements */
2829: if (elType.ElTypeNum == MathML_EL_MTD &&
2830: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML") == 0)
2831: {
2832: if (delete)
2833: DeleteIntColAlign (cell, doc);
2834: else
2835: {
2836: if (*ptr != EOS)
2837: {
2838: /* get next word in the attribute value */
2839: ptr = TtaSkipBlanks (ptr);
2840: /* process that word */
2841: if (*ptr != EOS && *ptr != ' ')
2842: {
2843: if (!strncasecmp (ptr, "left", 4))
2844: val = MathML_ATTR_IntColAlign_VAL_IntLeft;
2845: else if (!strncasecmp (ptr, "center", 6))
2846: val = MathML_ATTR_IntColAlign_VAL_IntCenter;
2847: else if (!strncasecmp (ptr, "right", 5))
2848: val = MathML_ATTR_IntColAlign_VAL_IntRight;
2849: else
2850: val = 0;
2851: /* skip the word that has been processed */
2852: while (*ptr != EOS && *ptr != ' ')
2853: ptr++;
2854: }
2855: }
2856: if (val > 0)
2857: SetIntColAlign (cell, val, doc);
2858: }
2859: }
2860: TtaNextSibling (&cell);
2861: if (!cell && fullTable && row)
2862: /* no more sibling cell. If the columnalign attribute is for the
2863: full table, get the first cell in the next row */
2864: {
2865: TtaNextSibling (&row);
2866: if (row)
2867: {
2868: /* parse value of columnalign attribute again from the beginning */
2869: ptr = value;
2870: RowWithoutColalignAttr (&row, &cell, &localAttr, !allRows);
2871: if (localAttr)
2872: {
2873: length = TtaGetTextAttributeLength (localAttr);
2874: if (length > 0)
2875: {
2876: if (localValue)
2877: TtaFreeMemory (localValue);
2878: localValue = TtaGetMemory (length+1);
2879: localValue[0] = EOS;
2880: TtaGiveTextAttributeValue (localAttr, localValue, &length);
2881: ptr = localValue;
2882: }
2883: }
2884: }
2885: }
2886: }
2887: if (value)
2888: TtaFreeMemory (value);
2889: if (localValue)
2890: TtaFreeMemory (localValue);
2891: }
2892:
2893: /*----------------------------------------------------------------------
1.167 quint 2894: HandleRowspacingAttribute
2895: An attribute rowspacing has been created, updated or deleted (if delete
2896: is TRUE) for element el in document doc. Update the top and bottom padding
2897: of all cells accordingly.
2898: ----------------------------------------------------------------------*/
2899: void HandleRowspacingAttribute (Attribute attr, Element el, Document doc,
2900: ThotBool delete)
2901: {
2902: ElementType elType, rowType, cellType;
2903: int length, val, topVal, topValUnit, bottomVal,
2904: bottomValUnit, rowspan, cellBottomVal, i;
2905: char *value, *ptr, *spanPtr;
2906: PresentationValue pval;
2907: PresentationContext ctxt;
2908: Element row, nextRow, cell;
2909: ThotBool stop, firstRow;
2910: AttributeType rowspanType;
2911: Attribute rowspanAttr;
2912:
2913: elType = TtaGetElementType (el);
2914: if (elType.ElTypeNum != MathML_EL_MTABLE ||
2915: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML"))
2916: /* ignore rowspacing attribute on mstyle elements */
2917: /* process it only on mtable elements */
2918: return;
2919:
2920: value = NULL;
2921: if (!delete && attr)
2922: {
2923: length = TtaGetTextAttributeLength (attr);
2924: if (length > 0)
2925: {
2926: value = TtaGetMemory (length+1);
2927: value[0] = EOS;
2928: TtaGiveTextAttributeValue (attr, value, &length);
2929: }
2930: }
2931:
2932: ctxt = TtaGetSpecificStyleContext (doc);
2933: /* the specific presentation to be created is not a CSS rule */
2934: ctxt->cssSpecificity = 0;
2935: ptr = value;
2936: rowspanType.AttrSSchema = elType.ElSSchema;
2937: rowspanType.AttrTypeNum = MathML_ATTR_rowspan_;
2938:
2939: /* check all rows within the table */
2940: firstRow = TRUE;
2941: bottomVal = 0;
2942: elType.ElTypeNum = MathML_EL_TableRow;
2943: row = TtaSearchTypedElement (elType, SearchInTree, el);
2944: while (row)
2945: {
2946: /* get the next row to check if the current row is the last one */
2947: nextRow = row;
2948: stop = FALSE;
2949: do
2950: {
2951: TtaNextSibling (&nextRow);
2952: if (!nextRow)
2953: stop = TRUE;
2954: else
2955: {
2956: rowType = TtaGetElementType (nextRow);
2957: /* skip comments and other non mrow elements */
2958: if ((rowType.ElTypeNum == MathML_EL_MTR ||
2959: rowType.ElTypeNum == MathML_EL_MLABELEDTR) &&
2960: !strcmp (TtaGetSSchemaName (rowType.ElSSchema), "MathML"))
2961: /* it's the next mrow */
2962: stop = TRUE;
2963: }
2964: }
2965: while (!stop);
2966:
2967: /* prepare the value of the padding to be associated with the cells
2968: of that row */
2969: if (delete)
2970: /* remove the presentation rules */
2971: {
2972: pval.typed_data.value = 0;
2973: val = 0;
2974: }
2975: else
2976: {
2977: if (!value)
2978: {
2979: pval.typed_data.unit = STYLE_UNIT_PT;
2980: pval.typed_data.value = 0;
2981: pval.typed_data.real = FALSE;
2982: val = 0;
2983: }
2984: else
2985: {
2986: /* get the next field in the attribute value (a number followed
2987: by a unit) */
2988: ptr = TtaSkipBlanks (ptr);
2989: if (*ptr != EOS)
2990: {
2991: ptr = ParseCSSUnit (ptr, &pval);
2992: if (pval.typed_data.unit != STYLE_UNIT_INVALID)
2993: {
2994: /* if the value is an integer, make it a real to avoid
2995: errors in dividing small integers, such as "1cm" */
2996: if (!pval.typed_data.real)
2997: {
2998: pval.typed_data.value *= 1000;
2999: pval.typed_data.real = TRUE;
3000: }
3001: val = pval.typed_data.value / 2;
3002: }
1.173 vatton 3003: else
3004: val = pval.typed_data.value;
1.167 quint 3005: }
3006: }
3007: }
3008:
3009: /* initialize the padding to be set at the top and at the bottom
3010: of each cell */
3011: /* the top padding of a row is the same as the bottom padding of the
3012: previous row */
3013: topVal = bottomVal;
3014: topValUnit = bottomValUnit;
3015: if (!nextRow)
3016: /* row is the last in the table. It must not have any padding
3017: at the bottom */
3018: bottomVal = 0;
3019: else
3020: {
3021: bottomVal = val;
3022: bottomValUnit = pval.typed_data.unit;
3023: }
3024:
3025: /* get the first cell of that row (ignoring Label cells) */
3026: elType.ElTypeNum = MathML_EL_MTD;
3027: cell = TtaSearchTypedElement (elType, SearchInTree, row);
3028: /* update attribute MLineBelowtop padding and bottom padding for all
3029: cells in that row */
3030: while (cell)
3031: {
3032: cellType = TtaGetElementType (cell);
3033: /* skip comments and other non mtd elements */
3034: if (cellType.ElTypeNum == MathML_EL_MTD &&
3035: !strcmp (TtaGetSSchemaName (cellType.ElSSchema), "MathML"))
3036: /* that's a mtd element. Process it */
3037: {
3038: /* by default, use the value for the current row */
3039: cellBottomVal = bottomVal;
3040: if (!delete && value)
3041: /* take row spanning into account */
3042: {
3043: /* is there a rowspan attribute on that cell? */
3044: rowspanAttr = TtaGetAttribute (cell, rowspanType);
3045: if (!rowspanAttr)
3046: rowspan = 1;
3047: else
3048: rowspan = TtaGetAttributeValue (rowspanAttr);
3049: if (!delete)
3050: {
3051: /* skip rowspan-1 words in the value of attribute
3052: rowlines */
3053: if (rowspan > 1)
3054: {
3055: spanPtr = ptr;
3056: for (i = 1; i < rowspan && *spanPtr != EOS; i++)
3057: {
3058: spanPtr = TtaSkipBlanks (spanPtr);
3059: spanPtr = ParseCSSUnit (spanPtr, &pval);
3060: }
3061: if (pval.typed_data.unit == STYLE_UNIT_INVALID)
3062: {
3063: val = 0;
3064: cellBottomVal = 0;
3065: bottomValUnit = STYLE_UNIT_PT;
3066: }
3067: else
3068: {
3069: /* if the value is an integer, make it a real to
3070: avoid errors in dividing small integers,
3071: such as "1cm" */
3072: if (!pval.typed_data.real)
3073: {
3074: pval.typed_data.value *= 1000;
3075: pval.typed_data.real = TRUE;
3076: }
3077: val = pval.typed_data.value / 2;
3078: cellBottomVal = val;
3079: bottomValUnit = pval.typed_data.unit;
3080: }
3081: }
3082: }
3083: }
3084:
3085: if ((delete || !value) && !firstRow)
3086: ctxt->destroy = TRUE;
3087: else
3088: {
3089: pval.typed_data.value = topVal;
3090: pval.typed_data.unit = topValUnit;
3091: ctxt->destroy = FALSE;
3092: }
3093: TtaSetStylePresentation (PRPaddingTop, cell, NULL, ctxt, pval);
3094: if ((delete || !value) && nextRow)
3095: ctxt->destroy = TRUE;
3096: else
3097: {
3098: pval.typed_data.value = cellBottomVal;
3099: pval.typed_data.unit = bottomValUnit;
3100: ctxt->destroy = FALSE;
3101: }
3102: TtaSetStylePresentation (PRPaddingBottom, cell, NULL, ctxt,pval);
3103: }
3104: TtaNextSibling (&cell);
3105: }
3106: row = nextRow;
3107: firstRow = FALSE;
3108: }
3109:
3110: TtaFreeMemory (ctxt);
3111: if (value)
3112: TtaFreeMemory (value);
3113: }
3114:
3115: /*----------------------------------------------------------------------
3116: ConvertNamedSpace
3117: if name is the name of a space, return the value of this space
3118: in value, otherwise return an empty string in value.
3119: -----------------------------------------------------------------------*/
3120: static char* ConvertNamedSpace (char *name, char *value)
3121: {
3122: if (strcmp (name, "veryverythinmathspace") == 0)
3123: {
3124: strcpy (value, "0.0555556em");
3125: return (name + strlen("veryverythinmathspace"));
3126: }
3127: else if (strcmp (name, "verythinmathspace") == 0)
3128: {
3129: strcpy (value, "0.111111em");
3130: return (name + strlen("verythinmathspace"));
3131: }
3132: else if (strcmp (name, "thinmathspace") == 0)
3133: {
3134: strcpy (value, "0.166667em");
3135: return (name + strlen("thinmathspace"));
3136: }
3137: else if (strcmp (name, "mediummathspace") == 0)
3138: {
3139: strcpy (value, "0.222222em");
3140: return (name + strlen("mediummathspace"));
3141: }
3142: else if (strcmp (name, "thickmathspace") == 0)
3143: {
3144: strcpy (value, "0.277778em");
3145: return (name + strlen("thickmathspace"));
3146: }
3147: else if (strcmp (name, "verythickmathspace") == 0)
3148: {
3149: strcpy (value, "0.333333em");
3150: return (name + strlen("verythickmathspace"));
3151: }
3152: else if (strcmp (name, "veryverythickmathspace") == 0)
3153: {
3154: strcpy (value, "0.388889em");
3155: return (name + strlen("veryverythickmathspace"));
3156: }
3157: else
3158: {
3159: value[0] = EOS;
3160: return name;
3161: }
3162: }
3163:
3164: /*----------------------------------------------------------------------
3165: HandleColumnspacingAttribute
3166: An attribute columnspacing has been created, updated or deleted (if delete
3167: is TRUE) for element el in document doc. Update the left and right padding
3168: of all cells accordingly.
3169: ----------------------------------------------------------------------*/
3170: void HandleColumnspacingAttribute (Attribute attr, Element el, Document doc,
3171: ThotBool delete)
3172: {
3173: ElementType elType;
3174: int length, val, valUnit, leftVal, leftValUnit,
3175: rightVal, rightValUnit, colspan, i;
3176: char *value, *ptr, valueOfNamedSpace[20];
3177: PresentationValue pval;
3178: PresentationContext ctxt;
3179: Element row, cell, nextCell;
3180: ThotBool stop, firstCell;
1.168 quint 3181: Attribute spanAttr;
1.167 quint 3182: AttributeType colspanType;
3183:
3184: elType = TtaGetElementType (el);
3185: if (elType.ElTypeNum != MathML_EL_MTABLE ||
3186: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML"))
3187: /* ignore columnspacing attribute on mstyle elements */
3188: /* process it only on mtable elements */
3189: return;
3190:
3191: value = NULL;
3192: if (!delete && attr)
3193: {
3194: length = TtaGetTextAttributeLength (attr);
3195: if (length > 0)
3196: {
3197: value = TtaGetMemory (length+1);
3198: value[0] = EOS;
3199: TtaGiveTextAttributeValue (attr, value, &length);
3200: }
3201: }
3202:
3203: ctxt = TtaGetSpecificStyleContext (doc);
3204: /* the specific presentation to be created is not a CSS rule */
3205: ctxt->cssSpecificity = 0;
3206: val = 0;
3207: colspanType.AttrSSchema = elType.ElSSchema;
3208: colspanType.AttrTypeNum = MathML_ATTR_columnspan;
3209:
3210: /* check all cells in all rows within the table */
3211: elType.ElTypeNum = MathML_EL_TableRow;
3212: row = TtaSearchTypedElement (elType, SearchInTree, el);
3213: while (row)
3214: {
3215: elType = TtaGetElementType (row);
3216: if ((elType.ElTypeNum == MathML_EL_MTR ||
3217: elType.ElTypeNum == MathML_EL_MLABELEDTR) &&
3218: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML") == 0)
3219: /* that's a table row. check all its cells */
3220: {
3221: firstCell = TRUE;
3222: rightVal = 0;
3223: val = 0;
3224: valUnit = STYLE_UNIT_PT;
3225: ptr = value;
3226: /* get the first cell of that row (ignoring Label cells) */
3227: elType.ElTypeNum = MathML_EL_MTD;
3228: cell = TtaSearchTypedElement (elType, SearchInTree, row);
3229: while (cell)
3230: {
3231: /* prepare the value of the padding to be associated with the
3232: cells */
3233: if (delete)
3234: /* remove the presentation rules */
3235: {
3236: pval.typed_data.value = 0;
3237: val = 0;
3238: valUnit = STYLE_UNIT_PT;
3239: }
3240: else
3241: {
3242: if (!value)
3243: {
3244: pval.typed_data.unit = STYLE_UNIT_PT;
3245: pval.typed_data.value = 0;
3246: pval.typed_data.real = FALSE;
3247: val = 0;
3248: valUnit = STYLE_UNIT_PT;
3249: }
3250: else
3251: {
3252: /* parse the next field in the attribute value (a number
3253: followed by a unit or a named space) */
3254: ptr = TtaSkipBlanks (ptr);
3255: if (*ptr != EOS)
3256: {
3257: /* is there a columnspan attribute on that cell? */
3258: spanAttr = TtaGetAttribute (cell, colspanType);
3259: if (!spanAttr)
3260: colspan = 1;
3261: else
3262: colspan = TtaGetAttributeValue (spanAttr);
3263: /* skip (colspan - 1) words in the attribute */
3264: for (i = 1; i <= colspan && *ptr != EOS; i++)
3265: {
3266: ptr = TtaSkipBlanks (ptr);
3267: ptr = ConvertNamedSpace (ptr, valueOfNamedSpace);
3268: if (valueOfNamedSpace[0] != EOS)
3269: /* it's a named space */
3270: ptr = ParseCSSUnit (valueOfNamedSpace, &pval);
3271: else
3272: ptr = ParseCSSUnit (ptr, &pval);
3273: if (pval.typed_data.unit == STYLE_UNIT_INVALID)
3274: {
3275: val = 0;
3276: valUnit = STYLE_UNIT_PT;
3277: }
3278: else
3279: {
3280: /* if the value is an integer, make it a real
3281: to avoid errors in dividing small
3282: integers, such as "1cm" */
3283: if (!pval.typed_data.real)
3284: {
3285: pval.typed_data.value *= 1000;
3286: pval.typed_data.real = TRUE;
3287: }
3288: val = pval.typed_data.value / 2;
3289: valUnit = pval.typed_data.unit;
3290: }
3291: }
3292: }
3293: }
3294: }
3295:
3296: /* get the next cell in the current row to check if the current
3297: cell is the last one in the row */
3298: nextCell = cell;
3299: stop = FALSE;
3300: do
3301: {
3302: TtaNextSibling (&nextCell);
3303: if (!nextCell)
3304: stop = TRUE;
3305: else
3306: {
3307: elType = TtaGetElementType (nextCell);
3308: /* skip comments and other non mtd elements */
3309: if (elType.ElTypeNum == MathML_EL_MTD &&
3310: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML") == 0)
3311: /* it's the next cell */
3312: stop = TRUE;
3313: }
3314: }
3315: while (!stop);
3316:
3317: /* initialize the padding to be set at the right and at the left
3318: of each cell */
3319: /* the leftPadding of a cell is the same as the right padding
3320: of the previous cell */
3321: leftVal = rightVal;
1.174 vatton 3322: leftValUnit = rightValUnit = valUnit;
1.167 quint 3323: if (!nextCell)
3324: /* it's the last cell in the row. It must not have any
3325: padding on the right */
3326: {
3327: rightVal = 0;
3328: rightValUnit = STYLE_UNIT_PT;
3329: }
3330: else
3331: {
3332: rightVal = val;
3333: rightValUnit = valUnit;
3334: }
3335:
3336: /* set the left and right padding for this cell */
3337: if ((delete || !value) && !firstCell)
3338: ctxt->destroy = TRUE;
3339: else
3340: {
3341: pval.typed_data.value = leftVal;
3342: pval.typed_data.unit = leftValUnit;
3343: ctxt->destroy = FALSE;
3344: }
3345: TtaSetStylePresentation (PRPaddingLeft, cell, NULL, ctxt, pval);
3346: if ((delete || !value) && nextCell)
3347: ctxt->destroy = TRUE;
3348: else
3349: {
3350: pval.typed_data.value = rightVal;
3351: pval.typed_data.unit = rightValUnit;
3352: ctxt->destroy = FALSE;
3353: }
3354: TtaSetStylePresentation (PRPaddingRight, cell, NULL, ctxt, pval);
3355: cell = nextCell;
3356: firstCell = FALSE;
3357: }
3358: }
3359: TtaNextSibling (&row);
3360: }
3361:
3362: if (value)
3363: TtaFreeMemory (value);
3364: }
3365:
3366: /*----------------------------------------------------------------------
1.159 quint 3367: HandleRowlinesAttribute
3368: An attribute rowlines has been created, updated or deleted (if delete
3369: is TRUE) for element el in document doc. Update attribute MLineBelow
3370: of all cells accordingly.
3371: ----------------------------------------------------------------------*/
3372: void HandleRowlinesAttribute (Attribute attr, Element el, Document doc,
3373: ThotBool delete)
3374: {
3375: char *value;
1.160 quint 3376: char *ptr, *spanPtr;
3377: int length, val, rowspan, i, cellVal;
1.159 quint 3378: ElementType elType, rowType, cellType;
3379: Element row, nextRow, cell;
3380: ThotBool stop;
1.160 quint 3381: AttributeType attrType, rowspanType;
3382: Attribute intAttr, rowspanAttr;
1.159 quint 3383:
3384: elType = TtaGetElementType (el);
3385: if (elType.ElTypeNum != MathML_EL_MTABLE ||
3386: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML"))
3387: /* ignore rowlines attribute on mstyle elements */
3388: /* process it only on mtable elements */
3389: return;
3390:
3391: value = NULL;
3392: if (!delete)
3393: {
3394: length = TtaGetTextAttributeLength (attr);
3395: if (length > 0)
3396: {
3397: value = TtaGetMemory (length+1);
3398: value[0] = EOS;
3399: TtaGiveTextAttributeValue (attr, value, &length);
3400: }
3401: }
3402: /* if attribute rowlines is created or updated but has no value, don't
3403: do anything */
3404: if (!delete && !value)
3405: return;
3406:
3407: ptr = value;
3408: val = 0;
3409: attrType.AttrSSchema = elType.ElSSchema;
1.160 quint 3410: rowspanType.AttrSSchema = elType.ElSSchema;
3411: rowspanType.AttrTypeNum = MathML_ATTR_rowspan_;
1.159 quint 3412:
3413: /* check all rows within the table */
3414: elType.ElTypeNum = MathML_EL_TableRow;
3415: row = TtaSearchTypedElement (elType, SearchInTree, el);
3416: while (row)
3417: {
3418: /* get the next row to check if the current row is the last one */
3419: nextRow = row;
3420: stop = FALSE;
3421: do
3422: {
3423: TtaNextSibling (&nextRow);
3424: if (!nextRow)
3425: stop = TRUE;
3426: else
3427: {
3428: rowType = TtaGetElementType (nextRow);
3429: /* skip comments and other non mrow elements */
3430: if ((rowType.ElTypeNum == MathML_EL_MTR ||
3431: rowType.ElTypeNum == MathML_EL_MLABELEDTR) &&
3432: !strcmp (TtaGetSSchemaName (rowType.ElSSchema), "MathML"))
3433: /* it's the next mrow */
3434: stop = TRUE;
3435: }
3436: }
3437: while (!stop);
3438:
3439: if (!nextRow)
3440: /* row is the last in the table. It must not have a line
3441: at the bottom. Delete it if there is one */
3442: val = 0;
3443: else
3444: {
3445: if (delete)
3446: val = 0;
3447: else
3448: if (*ptr != EOS)
3449: {
3450: /* get next word in the attribute value */
3451: ptr = TtaSkipBlanks (ptr);
3452: /* process that word */
3453: if (*ptr != EOS && *ptr != ' ')
3454: {
3455: if (!strncasecmp (ptr, "none", 4))
3456: val = 0;
3457: else if (!strncasecmp (ptr, "solid", 5))
3458: val = MathML_ATTR_MLineBelow_VAL_solid_;
3459: else if (!strncasecmp (ptr, "dashed", 6))
3460: val = MathML_ATTR_MLineBelow_VAL_dashed_;
3461: else
3462: val = 0;
3463: /* skip the word that has been processed */
3464: while (*ptr != EOS && *ptr != ' ')
3465: ptr++;
3466: }
3467: }
3468: }
3469: /* get the first cell of that row (ignoring Label cells) */
3470: elType.ElTypeNum = MathML_EL_MTD;
3471: cell = TtaSearchTypedElement (elType, SearchInTree, row);
3472: /* update attribute MLineBelow for all cells in that row */
3473: while (cell)
3474: {
3475: cellType = TtaGetElementType (cell);
3476: /* skip comments and other non mtd elements */
3477: if (cellType.ElTypeNum == MathML_EL_MTD &&
3478: !strcmp (TtaGetSSchemaName (cellType.ElSSchema), "MathML"))
3479: /* that's a mtd element. Process it */
3480: {
1.160 quint 3481: /* is there a rowspan attribute on that cell? */
3482: rowspanAttr = TtaGetAttribute (cell, rowspanType);
3483: if (!rowspanAttr)
3484: rowspan = 1;
3485: else
3486: rowspan = TtaGetAttributeValue (rowspanAttr);
1.161 quint 3487: /* by default, use the value for the current row */
3488: cellVal = val;
3489: if (!delete)
1.160 quint 3490: {
1.161 quint 3491: /* skip rowspan-1 words in the value of attribute rowlines */
3492: if (rowspan > 1)
1.160 quint 3493: {
1.161 quint 3494: spanPtr = ptr;
3495: for (i = 1; i < rowspan && *spanPtr != EOS; i++)
1.160 quint 3496: {
1.161 quint 3497: spanPtr = TtaSkipBlanks (spanPtr);
3498: if (*spanPtr != EOS && *spanPtr != ' ')
3499: {
3500: if (!strncasecmp (spanPtr, "none", 4))
3501: cellVal = 0;
3502: else if (!strncasecmp (spanPtr, "solid", 5))
3503: cellVal = MathML_ATTR_MLineBelow_VAL_solid_;
3504: else if (!strncasecmp (spanPtr, "dashed", 6))
3505: cellVal = MathML_ATTR_MLineBelow_VAL_dashed_;
3506: else
3507: cellVal = 0;
3508: }
3509: /* skip the word that has been processed */
3510: while (*spanPtr != EOS && *spanPtr != ' ')
3511: spanPtr++;
1.160 quint 3512: }
3513: }
3514: }
1.161 quint 3515: if (rowspan == 1)
3516: attrType.AttrTypeNum = MathML_ATTR_MLineBelow;
3517: else
3518: attrType.AttrTypeNum = MathML_ATTR_MLineBelowExt;
1.159 quint 3519: intAttr = TtaGetAttribute (cell, attrType);
1.160 quint 3520: if (cellVal == 0)
1.159 quint 3521: {
3522: if (intAttr)
3523: /* remove attribute MLineBelow */
3524: TtaRemoveAttribute (cell, intAttr, doc);
3525: }
3526: else
3527: /* set attribute MLineBelow */
3528: {
3529: if (!intAttr)
3530: {
3531: intAttr = TtaNewAttribute (attrType);
3532: TtaAttachAttribute (cell, intAttr, doc);
3533: }
1.160 quint 3534: TtaSetAttributeValue (intAttr, cellVal, cell, doc);
1.159 quint 3535: }
3536: }
3537: TtaNextSibling (&cell);
3538: }
3539: row = nextRow;
3540: }
3541: if (value)
3542: TtaFreeMemory (value);
3543: }
3544:
3545: /*----------------------------------------------------------------------
3546: HandleColumnlinesAttribute
3547: An attribute columnlines has been created, updated or deleted (if delete
3548: is TRUE) for element el in document doc. Update attribute MLineOnTheRight
3549: of all cells accordingly.
3550: ----------------------------------------------------------------------*/
3551: void HandleColumnlinesAttribute (Attribute attr, Element el, Document doc,
3552: ThotBool delete)
3553: {
3554: char *value;
3555: char *ptr;
1.161 quint 3556: int length, val, colspan, rowspan, i;
1.159 quint 3557: ElementType elType;
3558: Element row, cell, nextCell;
3559: ThotBool stop;
1.161 quint 3560: AttributeType attrType, colspanType, rowspanType;
3561: Attribute intAttr, spanAttr;
1.159 quint 3562:
3563: elType = TtaGetElementType (el);
3564: if (elType.ElTypeNum != MathML_EL_MTABLE ||
3565: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML"))
3566: /* ignore rowlines attribute on mstyle elements */
3567: /* process it only on mtable elements */
3568: return;
3569:
3570: value = NULL;
3571: if (!delete)
3572: {
3573: length = TtaGetTextAttributeLength (attr);
3574: if (length > 0)
3575: {
3576: value = TtaGetMemory (length+1);
3577: value[0] = EOS;
3578: TtaGiveTextAttributeValue (attr, value, &length);
3579: }
3580: }
3581: /* if attribute columnlines is created or updated but has no value, don't
3582: do anything */
3583: if (!delete && !value)
3584: return;
3585:
3586: val = 0;
3587: attrType.AttrSSchema = elType.ElSSchema;
1.160 quint 3588: colspanType.AttrSSchema = elType.ElSSchema;
3589: colspanType.AttrTypeNum = MathML_ATTR_columnspan;
1.161 quint 3590: rowspanType.AttrSSchema = elType.ElSSchema;
3591: rowspanType.AttrTypeNum = MathML_ATTR_rowspan_;
1.159 quint 3592:
3593: /* check all cells in all rows in the table */
3594: elType.ElTypeNum = MathML_EL_TableRow;
3595: row = TtaSearchTypedElement (elType, SearchInTree, el);
3596: while (row)
3597: {
3598: elType = TtaGetElementType (row);
3599: if ((elType.ElTypeNum == MathML_EL_MTR ||
3600: elType.ElTypeNum == MathML_EL_MLABELEDTR) &&
3601: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML") == 0)
3602: /* that's a table row. check all its cells */
3603: {
3604: /* start from the beginning of the columnlines attribute */
3605: ptr = value;
3606: val = 0;
3607: /* get the first cell of that row (ignoring Label cells) */
3608: elType.ElTypeNum = MathML_EL_MTD;
3609: cell = TtaSearchTypedElement (elType, SearchInTree, row);
3610: while (cell)
3611: {
3612: /* get the next cell in the current row to check if the current
3613: cell is the last one in the row */
3614: nextCell = cell;
3615: stop = FALSE;
3616: do
3617: {
3618: TtaNextSibling (&nextCell);
3619: if (!nextCell)
3620: stop = TRUE;
3621: else
3622: {
3623: elType = TtaGetElementType (nextCell);
3624: /* skip comments and other non mtd elements */
3625: if (elType.ElTypeNum == MathML_EL_MTD &&
3626: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML") == 0)
3627: /* it's the next cell */
3628: stop = TRUE;
3629: }
3630: }
3631: while (!stop);
3632:
1.161 quint 3633: /* is there a rowspan attribute on that cell? */
3634: spanAttr = TtaGetAttribute (cell, rowspanType);
3635: if (!spanAttr)
3636: rowspan = 1;
3637: else
3638: rowspan = TtaGetAttributeValue (spanAttr);
3639:
1.159 quint 3640: if (!nextCell)
3641: /* it's the last cell in the row. It must not have a line
3642: on its right edge. Delete it if there is noe. */
3643: val = 0;
3644: else
3645: /* set the attribute MLineOnTheRight for this cell */
3646: {
3647: if (delete)
3648: val = 0;
3649: else
3650: if (*ptr != EOS)
3651: {
1.161 quint 3652: /* is there a columnspan attribute on that cell? */
3653: spanAttr = TtaGetAttribute (cell, colspanType);
3654: if (!spanAttr)
1.160 quint 3655: colspan = 1;
3656: else
1.161 quint 3657: colspan = TtaGetAttributeValue (spanAttr);
1.160 quint 3658: /* skip (colspan - 1) words in the attribute */
3659: for (i = 1; i <= colspan && *ptr != EOS; i++)
1.159 quint 3660: {
1.160 quint 3661: /* get next word in the attribute value */
3662: ptr = TtaSkipBlanks (ptr);
3663: /* process that word */
3664: if (*ptr != EOS && *ptr != ' ')
3665: {
3666: if (!strncasecmp (ptr, "none", 4))
3667: val = 0;
3668: else if (!strncasecmp (ptr, "solid", 5))
3669: val = MathML_ATTR_MLineOnTheRight_VAL_solid_;
3670: else if (!strncasecmp (ptr, "dashed", 6))
3671: val = MathML_ATTR_MLineOnTheRight_VAL_dashed_;
3672: else
3673: val = 0;
3674: /* skip the word that has been processed */
3675: while (*ptr != EOS && *ptr != ' ')
3676: ptr++;
3677: }
1.159 quint 3678: }
3679: }
3680: }
1.161 quint 3681: if (rowspan == 1)
3682: attrType.AttrTypeNum = MathML_ATTR_MLineOnTheRight;
3683: else
3684: attrType.AttrTypeNum = MathML_ATTR_MLineOnTheRightExt;
1.159 quint 3685: intAttr = TtaGetAttribute (cell, attrType);
3686: if (val == 0)
3687: {
3688: if (intAttr)
3689: /* remove attribute MLineOnTheRight */
3690: TtaRemoveAttribute (cell, intAttr, doc);
3691: }
3692: else
3693: /* set attribute MLineOnTheRight */
3694: {
3695: if (!intAttr)
3696: {
3697: intAttr = TtaNewAttribute (attrType);
3698: TtaAttachAttribute (cell, intAttr, doc);
3699: }
3700: TtaSetAttributeValue (intAttr, val, cell, doc);
3701: }
3702: cell = nextCell;
3703: }
3704: }
3705: TtaNextSibling (&row);
3706: }
3707: if (value)
3708: TtaFreeMemory (value);
3709: }
3710:
3711: /*----------------------------------------------------------------------
1.168 quint 3712: HandleFramespacingAttribute
3713: An attribute framespacing has been created, updated or deleted (if delete
3714: is TRUE) for element el in document doc. Update attribute the padding
3715: properties of the concerned table(s).
3716: ----------------------------------------------------------------------*/
3717: void HandleFramespacingAttribute (Attribute attr, Element el, Document doc,
3718: ThotBool delete)
3719: {
3720: ElementType elType;
3721: char *value, *ptr, valueOfNamedSpace[20];
3722: int length, vertPadding, horizPadding, vertPaddingUnit,
3723: horizPaddingUnit;
3724: Attribute attrFrame;
3725: AttributeType attrType;
3726: PresentationValue pval;
3727: PresentationContext ctxt;
3728: ThotBool vertPaddingReal, horizPaddingReal;
3729:
3730: if ((!delete && !attr) || !el)
3731: return;
3732: elType = TtaGetElementType (el);
3733: if (elType.ElTypeNum != MathML_EL_MTABLE ||
3734: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML"))
3735: /* ignore framespacing attribute on mstyle elements */
3736: /* process it only on mtable elements */
3737: return;
3738:
3739: value = NULL;
3740: if (!delete)
3741: {
3742: length = TtaGetTextAttributeLength (attr);
3743: if (length > 0)
3744: {
3745: value = TtaGetMemory (length+1);
3746: value[0] = EOS;
3747: TtaGiveTextAttributeValue (attr, value, &length);
3748: }
3749: }
3750: ctxt = TtaGetSpecificStyleContext (doc);
3751: /* the specific presentation to be created is not a CSS rule */
3752: ctxt->cssSpecificity = 0;
3753: vertPadding = 0;
3754: horizPadding = 0;
3755: vertPaddingUnit = STYLE_UNIT_PT;
3756: horizPaddingUnit = STYLE_UNIT_PT;
3757: vertPaddingReal = FALSE;
3758: horizPaddingReal = FALSE;
3759: /* is there a frame attribute? */
3760: attrType.AttrSSchema = elType.ElSSchema;
3761: attrType.AttrTypeNum = MathML_ATTR_frame;
3762: attrFrame = TtaGetAttribute (el, attrType);
3763: if (!delete && value && attrFrame)
3764: {
3765: ptr = value;
3766: /* parse the first part: horizontal spacing */
3767: ptr = TtaSkipBlanks (ptr);
3768: if (*ptr != EOS)
3769: {
3770: ptr = ConvertNamedSpace (ptr, valueOfNamedSpace);
3771: if (valueOfNamedSpace[0] != EOS)
3772: /* it's a named space */
3773: ptr = ParseCSSUnit (valueOfNamedSpace, &pval);
3774: else
3775: ptr = ParseCSSUnit (ptr, &pval);
3776: if (pval.typed_data.unit != STYLE_UNIT_INVALID)
3777: {
3778: horizPadding = pval.typed_data.value;
3779: horizPaddingUnit = pval.typed_data.unit;
3780: horizPaddingReal = pval.typed_data.real;
3781: /* if there is no second part, the vertical spacing is the same
3782: as the horizontal spacing */
3783: vertPadding = horizPadding;
3784: vertPaddingUnit = horizPaddingUnit;
3785: vertPaddingReal = horizPaddingReal;
3786: /* parse the second part, if any */
3787: ptr = TtaSkipBlanks (ptr);
3788: if (*ptr != EOS)
3789: {
3790: ptr = ConvertNamedSpace (ptr, valueOfNamedSpace);
3791: if (valueOfNamedSpace[0] != EOS)
3792: /* it's a named space */
3793: ptr = ParseCSSUnit (valueOfNamedSpace, &pval);
3794: else
3795: ptr = ParseCSSUnit (ptr, &pval);
3796: if (pval.typed_data.unit != STYLE_UNIT_INVALID)
3797: {
3798: vertPadding = pval.typed_data.value;
3799: vertPaddingUnit = pval.typed_data.unit;
3800: vertPaddingReal = pval.typed_data.real;
3801: }
3802: }
3803: }
3804: }
3805: }
3806: if (delete)
3807: ctxt->destroy = TRUE;
3808: else
3809: {
3810: ctxt->destroy = FALSE;
3811: pval.typed_data.value = horizPadding;
3812: pval.typed_data.unit = horizPaddingUnit;
3813: pval.typed_data.real = horizPaddingReal;
3814: }
3815: TtaSetStylePresentation (PRPaddingLeft, el, NULL, ctxt, pval);
3816: TtaSetStylePresentation (PRPaddingRight, el, NULL, ctxt, pval);
3817: if (!delete)
3818: {
3819: pval.typed_data.value = vertPadding;
3820: pval.typed_data.unit = vertPaddingUnit;
3821: pval.typed_data.real = vertPaddingReal;
3822: }
3823: TtaSetStylePresentation (PRPaddingTop, el, NULL, ctxt, pval);
3824: TtaSetStylePresentation (PRPaddingBottom, el, NULL, ctxt, pval);
3825:
3826: if (value)
3827: TtaFreeMemory (value);
3828: }
3829:
3830: /*----------------------------------------------------------------------
1.175 quint 3831: ApplyDisplaystyle
3832: An IntDisplaystyle attribute has been associated with (or removed from)
3833: element el.
3834: Handle all large operators in the sub tree.
3835: Update attribute IntMovelimits for all munder, mover or munderover
3836: elements in the subtree
3837: ----------------------------------------------------------------------*/
3838: static void ApplyDisplaystyle (Element el, Document doc)
3839: {
3840: ElementType elType;
3841: Element child;
3842:
3843: elType = TtaGetElementType (el);
3844: if (!strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML"))
3845: {
3846: if (elType.ElTypeNum == MathML_EL_MO)
3847: CheckLargeOp (el, doc);
3848: else if (elType.ElTypeNum == MathML_EL_MUNDER ||
3849: elType.ElTypeNum == MathML_EL_MOVER ||
3850: elType.ElTypeNum == MathML_EL_MUNDEROVER)
3851: SetIntMovelimitsAttr (el, doc);
3852: }
3853: child = TtaGetFirstChild (el);
3854: while (child)
3855: {
3856: ApplyDisplaystyle (child, doc);
3857: TtaNextSibling (&child);
3858: }
3859: }
3860:
3861: /*----------------------------------------------------------------------
1.169 quint 3862: SetDisplaystyleMathElement
3863: Associate a IntDisplaystyle attribute with element el (which is a
3864: <math> element), and set its value depending on the surrounding context.
3865: ----------------------------------------------------------------------*/
3866: void SetDisplaystyleMathElement (Element el, Document doc)
3867: {
3868: Element parent, sibling;
3869: ElementType elType, parentType;
3870: Attribute attr;
3871: AttributeType attrType;
3872: int display, val;
3873:
3874: display = MathML_ATTR_IntDisplaystyle_VAL_true;
3875: /* is there an attribute display? */
3876: elType = TtaGetElementType (el);
3877: attrType.AttrSSchema = elType.ElSSchema;
3878: attrType.AttrTypeNum = MathML_ATTR_display;
3879: attr = TtaGetAttribute (el, attrType);
3880: if (attr)
3881: /* there is an attribute display. Take its value */
3882: {
3883: val = TtaGetAttributeValue (attr);
3884: if (val == MathML_ATTR_display_VAL_block)
3885: display = MathML_ATTR_IntDisplaystyle_VAL_true;
3886: else
3887: display = MathML_ATTR_IntDisplaystyle_VAL_false;
3888: }
3889: else
3890: /* no attribute display. Look at the context */
3891: {
3892: parent = TtaGetParent (el);
3893: parentType = TtaGetElementType (parent);
3894: if (elType.ElSSchema == parentType.ElSSchema)
3895: /* it's the only <math> element in a MathML document */
3896: display = MathML_ATTR_IntDisplaystyle_VAL_true;
3897: else
3898: /* it's a MathML expression within another vocabulary */
3899: {
3900: if (!strcmp (TtaGetSSchemaName (parentType.ElSSchema), "SVG"))
3901: /* a <math> element in a SVG element */
3902: display = MathML_ATTR_IntDisplaystyle_VAL_true;
3903: else if (!strcmp (TtaGetSSchemaName (parentType.ElSSchema), "HTML"))
3904: /* a <math> element in a HTML element */
3905: {
3906: display = MathML_ATTR_IntDisplaystyle_VAL_false;
3907: if (parentType.ElTypeNum == HTML_EL_BODY ||
3908: parentType.ElTypeNum == HTML_EL_Division)
3909: display = MathML_ATTR_IntDisplaystyle_VAL_true;
3910: else if (parentType.ElTypeNum == HTML_EL_Pseudo_paragraph ||
3911: parentType.ElTypeNum == HTML_EL_Paragraph)
3912: {
3913: sibling = el;
3914: TtaPreviousSibling (&sibling);
3915: if (!sibling)
3916: {
3917: sibling = el;
3918: TtaNextSibling (&sibling);
3919: if (!sibling)
3920: display = MathML_ATTR_IntDisplaystyle_VAL_true;
3921: }
3922: }
3923: }
3924: }
3925: }
3926: /* create the IntDisplastyle attribute and set its value */
3927: attrType.AttrTypeNum = MathML_ATTR_IntDisplaystyle;
3928: attr = TtaGetAttribute (el, attrType);
3929: if (!attr)
3930: {
3931: attr = TtaNewAttribute (attrType);
3932: TtaAttachAttribute (el, attr, doc);
3933: }
3934: TtaSetAttributeValue (attr, display, el, doc);
1.175 quint 3935: ApplyDisplaystyle (el, doc);
1.169 quint 3936: }
3937:
3938: /*----------------------------------------------------------------------
3939: MathMLElementCreated
3940: The XML parser has just inserted a new element in the abstract tree.
3941: ----------------------------------------------------------------------*/
3942: void MathMLElementCreated (Element el, Document doc)
3943: {
3944: ElementType elType;
3945:
3946: elType = TtaGetElementType (el);
3947: if (elType.ElTypeNum == MathML_EL_MathML)
3948: /* associate a IntDisplaystyle attribute with the element depending
3949: on its context */
3950: SetDisplaystyleMathElement (el, doc);
3951: }
3952:
3953: /*----------------------------------------------------------------------
1.1 cvs 3954: MathMLElementComplete
1.169 quint 3955: Element el has just been completed by the XML parser.
1.1 cvs 3956: Check the Thot structure of the MathML element el.
3957: ----------------------------------------------------------------------*/
1.156 cvs 3958: void MathMLElementComplete (ParserData *context, Element el, int *error)
1.1 cvs 3959: {
1.156 cvs 3960: Document doc;
1.74 cvs 3961: ElementType elType, parentType;
1.1 cvs 3962: Element child, parent, new, prev, next;
1.101 cvs 3963: AttributeType attrType;
3964: Attribute attr;
1.56 cvs 3965: SSchema MathMLSSchema;
3966: ThotBool ok;
1.1 cvs 3967:
1.56 cvs 3968: ok = TRUE;
3969: *error = 0;
1.156 cvs 3970: doc = context->doc;
1.1 cvs 3971: elType = TtaGetElementType (el);
1.2 cvs 3972: MathMLSSchema = GetMathMLSSchema (doc);
1.1 cvs 3973:
1.76 cvs 3974: if (elType.ElSSchema == MathMLSSchema)
1.1 cvs 3975: {
3976: switch (elType.ElTypeNum)
3977: {
1.76 cvs 3978: case MathML_EL_MathML:
3979: /* Create placeholders within the MathML element */
3980: CreatePlaceholders (TtaGetFirstChild (el), doc);
1.132 cvs 3981: break;
1.1 cvs 3982: case MathML_EL_MI:
3983: SetFontstyleAttr (el, doc);
3984: break;
3985: case MathML_EL_MO:
1.22 cvs 3986: SetIntAddSpaceAttr (el, doc);
3987: SetIntVertStretchAttr (el, doc, 0, NULL);
1.58 cvs 3988: /* if the MO element is a child of a MROW (or equivalent) and if it
3989: contains a fence character, transform this MO into MF and
3990: transform the fence character into a Thot SYMBOL */
1.175 quint 3991: CheckFence (el, doc);
3992: /* if the MO element contains an operator that should be
3993: large (∑ for instance), enlarge it */
3994: CheckLargeOp (el, doc);
1.1 cvs 3995: break;
1.60 cvs 3996: case MathML_EL_MSPACE:
3997: break;
1.39 cvs 3998: case MathML_EL_MROW:
1.55 cvs 3999: /* Create placeholders within the MROW */
4000: CreatePlaceholders (TtaGetFirstChild (el), doc);
1.39 cvs 4001: break;
4002: case MathML_EL_MFRAC:
1.54 cvs 4003: case MathML_EL_BevelledMFRAC:
1.39 cvs 4004: /* end of a fraction. Create a Numerator and a Denominator */
1.56 cvs 4005: ok = CheckMathSubExpressions (el, MathML_EL_Numerator,
4006: MathML_EL_Denominator, 0, doc);
1.39 cvs 4007: break;
4008: case MathML_EL_MSQRT:
1.50 cvs 4009: /* end of a Square Root */
4010: /* Create placeholders within the element */
4011: CreatePlaceholders (TtaGetFirstChild (el), doc);
4012: /* Create a SqrtBase that contains all children of the MSQRT */
1.39 cvs 4013: CreateWrapper (el, MathML_EL_SqrtBase, doc);
4014: break;
1.1 cvs 4015: case MathML_EL_MROOT:
4016: /* end of a Root. Create a RootBase and an Index */
1.56 cvs 4017: ok = CheckMathSubExpressions (el, MathML_EL_RootBase,
4018: MathML_EL_Index, 0, doc);
1.1 cvs 4019: break;
1.50 cvs 4020: case MathML_EL_MENCLOSE:
4021: /* Create placeholders within the element */
4022: CreatePlaceholders (TtaGetFirstChild (el), doc);
4023: break;
1.39 cvs 4024: case MathML_EL_MSTYLE:
4025: case MathML_EL_MERROR:
4026: case MathML_EL_MPADDED:
4027: case MathML_EL_MPHANTOM:
4028: /* Create placeholders within the element */
4029: CreatePlaceholders (TtaGetFirstChild (el), doc);
1.1 cvs 4030: break;
4031: case MathML_EL_MFENCED:
4032: TransformMFENCED (el, doc);
4033: break;
4034: case MathML_EL_MSUB:
4035: /* end of a MSUB. Create Base and Subscript */
1.56 cvs 4036: ok = CheckMathSubExpressions (el, MathML_EL_Base,
4037: MathML_EL_Subscript, 0, doc);
1.59 cvs 4038: SetScriptShift (el, doc, MathML_ATTR_subscriptshift);
1.22 cvs 4039: SetIntVertStretchAttr (el, doc, MathML_EL_Base, NULL);
1.1 cvs 4040: break;
4041: case MathML_EL_MSUP:
4042: /* end of a MSUP. Create Base and Superscript */
1.56 cvs 4043: ok = CheckMathSubExpressions (el, MathML_EL_Base,
4044: MathML_EL_Superscript, 0, doc);
1.59 cvs 4045: SetScriptShift (el, doc, MathML_ATTR_superscriptshift);
1.22 cvs 4046: SetIntVertStretchAttr (el, doc, MathML_EL_Base, NULL);
1.1 cvs 4047: break;
1.39 cvs 4048: case MathML_EL_MSUBSUP:
4049: /* end of a MSUBSUP. Create Base, Subscript, and Superscript */
1.56 cvs 4050: ok = CheckMathSubExpressions (el, MathML_EL_Base,
4051: MathML_EL_Subscript,
4052: MathML_EL_Superscript, doc);
1.59 cvs 4053: SetScriptShift (el, doc, MathML_ATTR_subscriptshift);
4054: SetScriptShift (el, doc, MathML_ATTR_superscriptshift);
1.39 cvs 4055: SetIntVertStretchAttr (el, doc, MathML_EL_Base, NULL);
1.1 cvs 4056: break;
4057: case MathML_EL_MUNDER:
4058: /* end of a MUNDER. Create UnderOverBase, and Underscript */
1.56 cvs 4059: ok = CheckMathSubExpressions (el, MathML_EL_UnderOverBase,
4060: MathML_EL_Underscript, 0, doc);
1.22 cvs 4061: SetIntHorizStretchAttr (el, doc);
4062: SetIntVertStretchAttr (el, doc, MathML_EL_UnderOverBase, NULL);
1.169 quint 4063: SetIntMovelimitsAttr (el, doc);
1.1 cvs 4064: break;
4065: case MathML_EL_MOVER:
4066: /* end of a MOVER. Create UnderOverBase, and Overscript */
1.56 cvs 4067: ok = CheckMathSubExpressions (el, MathML_EL_UnderOverBase,
4068: MathML_EL_Overscript, 0, doc);
1.22 cvs 4069: SetIntHorizStretchAttr (el, doc);
4070: SetIntVertStretchAttr (el, doc, MathML_EL_UnderOverBase, NULL);
1.169 quint 4071: SetIntMovelimitsAttr (el, doc);
1.1 cvs 4072: break;
1.39 cvs 4073: case MathML_EL_MUNDEROVER:
4074: /* end of a MUNDEROVER. Create UnderOverBase, Underscript, and
4075: Overscript */
1.56 cvs 4076: ok = CheckMathSubExpressions (el, MathML_EL_UnderOverBase,
4077: MathML_EL_Underscript,
4078: MathML_EL_Overscript, doc);
1.39 cvs 4079: SetIntHorizStretchAttr (el, doc);
4080: SetIntVertStretchAttr (el, doc, MathML_EL_UnderOverBase, NULL);
1.169 quint 4081: SetIntMovelimitsAttr (el, doc);
1.39 cvs 4082: break;
1.1 cvs 4083: case MathML_EL_MMULTISCRIPTS:
4084: /* end of a MMULTISCRIPTS. Create all elements defined in the
4085: MathML S schema */
4086: BuildMultiscript (el, doc);
1.5 cvs 4087: break;
4088: case MathML_EL_MTABLE:
4089: /* end of a MTABLE. Create all elements defined in the MathML S
4090: schema */
1.64 cvs 4091: CheckMTable (el, doc, TRUE);
1.101 cvs 4092: /* if the table has a rowalign attribute, process it */
4093: attrType.AttrSSchema = MathMLSSchema;
4094: attrType.AttrTypeNum = MathML_ATTR_rowalign;
4095: attr = TtaGetAttribute (el, attrType);
4096: if (attr)
4097: HandleRowalignAttribute (attr, el, doc, FALSE);
4098: /* if the table has a columnalign attribute, process it */
4099: attrType.AttrTypeNum = MathML_ATTR_columnalign;
4100: attr = TtaGetAttribute (el, attrType);
4101: if (attr)
1.108 cvs 4102: HandleColalignAttribute (attr, el, doc, FALSE, FALSE);
1.167 quint 4103: /* process the rowspacing attribute, or set the top padding of the
4104: first row and the bottom padding of the last row to 0. */
4105: attrType.AttrSSchema = MathMLSSchema;
4106: attrType.AttrTypeNum = MathML_ATTR_rowspacing;
4107: attr = TtaGetAttribute (el, attrType);
4108: HandleRowspacingAttribute (attr, el, doc, FALSE);
4109: /* process the columnspacing attribute, or set the left padding of
4110: the first column and the right padding of the last column to 0 */
4111: attrType.AttrSSchema = MathMLSSchema;
4112: attrType.AttrTypeNum = MathML_ATTR_columnspacing;
4113: attr = TtaGetAttribute (el, attrType);
4114: HandleColumnspacingAttribute (attr, el, doc, FALSE);
1.159 quint 4115: /* if the table has a rowlines attribute, process it */
4116: attrType.AttrSSchema = MathMLSSchema;
4117: attrType.AttrTypeNum = MathML_ATTR_rowlines;
4118: attr = TtaGetAttribute (el, attrType);
4119: if (attr)
1.167 quint 4120: HandleRowlinesAttribute (attr, el, doc, FALSE);
1.159 quint 4121: /* if the table has a columnlines attribute, process it */
4122: attrType.AttrTypeNum = MathML_ATTR_columnlines;
4123: attr = TtaGetAttribute (el, attrType);
4124: if (attr)
4125: HandleColumnlinesAttribute (attr, el, doc, FALSE);
1.101 cvs 4126: break;
4127: case MathML_EL_MTR:
4128: /* if the row has a columnalign attribute, process it */
4129: attrType.AttrSSchema = MathMLSSchema;
4130: attrType.AttrTypeNum = MathML_ATTR_columnalign;
4131: attr = TtaGetAttribute (el, attrType);
4132: if (attr)
1.108 cvs 4133: HandleColalignAttribute (attr, el, doc, FALSE, TRUE);
1.101 cvs 4134: break;
4135: case MathML_EL_MLABELEDTR:
4136: /* if the row has a columnalign attribute, process it */
4137: attrType.AttrSSchema = MathMLSSchema;
4138: attrType.AttrTypeNum = MathML_ATTR_columnalign;
4139: attr = TtaGetAttribute (el, attrType);
4140: if (attr)
1.108 cvs 4141: HandleColalignAttribute (attr, el, doc, FALSE, TRUE);
1.1 cvs 4142: break;
1.39 cvs 4143: case MathML_EL_MTD:
4144: /* Create placeholders within the table cell */
4145: CreatePlaceholders (TtaGetFirstChild (el), doc);
1.46 cvs 4146: break;
1.39 cvs 4147: case MathML_EL_MACTION:
4148: /* Create placeholders within the MACTION element */
4149: CreatePlaceholders (TtaGetFirstChild (el), doc);
1.1 cvs 4150: break;
4151: default:
4152: break;
4153: }
4154: parent = TtaGetParent (el);
1.118 cvs 4155: if (parent)
4156: {
4157: parentType = TtaGetElementType (parent);
4158: if (parentType.ElSSchema != elType.ElSSchema)
1.175 quint 4159: /* root of a MathML (sub-)tree, Create a MathML element if it is
4160: not present */
1.118 cvs 4161: if (elType.ElTypeNum != MathML_EL_MathML)
4162: {
4163: elType.ElSSchema = MathMLSSchema;
4164: elType.ElTypeNum = MathML_EL_MathML;
4165: new = TtaNewElement (doc, elType);
4166: TtaInsertSibling (new, el, TRUE, doc);
4167: next = el;
4168: TtaNextSibling (&next);
4169: TtaRemoveTree (el, doc);
4170: TtaInsertFirstChild (&el, new, doc);
4171: prev = el;
4172: while (next != NULL)
4173: {
4174: child = next;
4175: TtaNextSibling (&next);
4176: TtaRemoveTree (child, doc);
4177: TtaInsertSibling (child, prev, FALSE, doc);
4178: prev = child;
4179: }
1.169 quint 4180: /* associate a IntDisplaystyle attribute with the element
4181: depending on its context */
4182: SetDisplaystyleMathElement (new, doc);
1.118 cvs 4183: /* Create placeholders within the MathML element */
1.169 quint 4184: CreatePlaceholders (new, doc);
1.118 cvs 4185: }
4186: }
1.1 cvs 4187: }
1.56 cvs 4188: if (!ok)
4189: /* send an error message */
4190: *error = 1;
1.1 cvs 4191: }
4192:
4193: /*----------------------------------------------------------------------
1.126 cvs 4194: UnknownMathMLNameSpace
1.149 cvs 4195: The element doesn't belong to a supported namespace
1.126 cvs 4196: ----------------------------------------------------------------------*/
1.149 cvs 4197: void UnknownMathMLNameSpace (ParserData *context,
4198: Element *unknownEl,
4199: char* content)
1.126 cvs 4200: {
4201: ElementType elType;
1.149 cvs 4202: Element elText;
1.126 cvs 4203:
4204: /* Create a new Invalid_element */
4205: elType.ElSSchema = GetXMLSSchema (MATH_TYPE, context->doc);
4206: elType.ElTypeNum = MathML_EL_Unknown_namespace;
1.149 cvs 4207: *unknownEl = TtaNewElement (context->doc, elType);
4208: if (*unknownEl != NULL)
1.126 cvs 4209: {
1.149 cvs 4210: XmlSetElemLineNumber (*unknownEl);
4211: InsertXmlElement (unknownEl);
1.126 cvs 4212: context->lastElementClosed = TRUE;
4213: elType.ElTypeNum = MathML_EL_TEXT_UNIT;
4214: elText = TtaNewElement (context->doc, elType);
4215: XmlSetElemLineNumber (elText);
1.149 cvs 4216: TtaInsertFirstChild (&elText, *unknownEl, context->doc);
1.126 cvs 4217: TtaSetTextContent (elText, content, context->language, context->doc);
4218: TtaSetAccessRight (elText, ReadOnly, context->doc);
4219: }
4220: }
4221:
4222: /*----------------------------------------------------------------------
1.24 cvs 4223: SetFontfamily
4224: -----------------------------------------------------------------------*/
1.120 cvs 4225: void SetFontfamily (Document doc, Element el, char *value)
1.24 cvs 4226: {
4227: #define buflen 50
1.116 cvs 4228: char css_command[buflen+20];
1.24 cvs 4229:
1.116 cvs 4230: sprintf (css_command, "font-family: %s", value);
1.72 cvs 4231: ParseHTMLSpecificStyle (el, css_command, doc, 0, FALSE);
1.24 cvs 4232: }
4233:
4234: /*----------------------------------------------------------------------
1.83 cvs 4235: MathMLlinethickness
4236: The MathML attribute linthickness is associated with element el. Generate
4237: the corresponding style property for this element.
4238: -----------------------------------------------------------------------*/
1.120 cvs 4239: void MathMLlinethickness (Document doc, Element el, char *value)
1.83 cvs 4240: {
4241: #define buflen 50
1.116 cvs 4242: char css_command[buflen+20];
1.83 cvs 4243:
1.116 cvs 4244: if (strcmp (value, "thin") == 0)
4245: strcpy (value, "1pt");
4246: else if (strcmp (value, "medium") == 0)
4247: strcpy (value, "1pt");
4248: else if (strcmp (value, "thick") == 0)
4249: strcpy (value, "2pt");
4250: sprintf (css_command, "stroke-width: %s", value);
1.83 cvs 4251: ParseHTMLSpecificStyle (el, css_command, doc, 0, FALSE);
4252: }
4253:
4254: /*----------------------------------------------------------------------
1.58 cvs 4255: MathMLAttrToStyleProperty
4256: The MathML attribute attr is associated with element el. Generate
4257: the corresponding style property for this element.
1.24 cvs 4258: -----------------------------------------------------------------------*/
1.138 cvs 4259: void MathMLAttrToStyleProperty (Document doc, Element el, char *value,
4260: int attr)
1.24 cvs 4261: {
1.167 quint 4262: char css_command[buflen+20], namedSpaceVal[20];
1.141 quint 4263: int i;
1.58 cvs 4264:
4265: switch (attr)
4266: {
4267: case MathML_ATTR_fontsize:
1.116 cvs 4268: sprintf (css_command, "font-size: %s", value);
1.58 cvs 4269: break;
1.93 cvs 4270: case MathML_ATTR_mathsize:
1.116 cvs 4271: if (strcmp (value, "small") == 0)
4272: strcpy (value, "80%");
4273: else if (strcmp (value, "normal") == 0)
4274: strcpy (value, "100%");
4275: else if (strcmp (value, "big") == 0)
4276: strcpy (value, "125%");
4277: sprintf (css_command, "font-size: %s", value);
1.93 cvs 4278: break;
1.58 cvs 4279: case MathML_ATTR_lspace:
4280: case MathML_ATTR_rspace:
1.141 quint 4281: if (attr == MathML_ATTR_lspace)
4282: strcpy (css_command, "padding-left: ");
4283: else
4284: strcpy (css_command, "padding-right: ");
1.167 quint 4285: ConvertNamedSpace (value, namedSpaceVal);
4286: if (namedSpaceVal[0] != EOS)
4287: /* it's a named space */
4288: strcat (css_command, namedSpaceVal);
1.141 quint 4289: else
4290: {
4291: strcat (css_command, value);
4292: /* does the value contain an unit at the end? */
4293: i = strlen (value) - 1;
4294: if ((value[i] <= '9' && value[i] >= '0') ||
4295: value[i] == '.')
4296: /* it's just a number. Add the (implicit) unit: em */
4297: strcat (css_command, "em");
4298: }
1.58 cvs 4299: break;
4300: }
1.72 cvs 4301: ParseHTMLSpecificStyle (el, css_command, doc, 0, FALSE);
1.24 cvs 4302: }
4303:
4304: /*----------------------------------------------------------------------
1.60 cvs 4305: MathMLSetScriptLevel
4306: A scriptlevel attribute with value value is associated with element el.
4307: Generate the corresponding style property for this element.
4308: -----------------------------------------------------------------------*/
1.120 cvs 4309: void MathMLSetScriptLevel (Document doc, Element el, char *value)
1.60 cvs 4310: {
4311: PresentationValue pval;
4312: PresentationContext ctxt;
4313: ThotBool relative;
4314: int percentage;
4315:
4316: ctxt = TtaGetSpecificStyleContext (doc);
4317: if (!value)
4318: /* remove the presentation rule */
4319: {
4320: ctxt->destroy = TRUE;
1.75 cvs 4321: pval.typed_data.value = 0;
1.60 cvs 4322: TtaSetStylePresentation (PRSize, el, NULL, ctxt, pval);
4323: }
4324: else
4325: {
4326: ctxt->destroy = FALSE;
4327: /* parse the attribute value (an optional sign and an integer) */
1.119 cvs 4328: value = TtaSkipBlanks (value);
1.60 cvs 4329: relative = (value[0] == '-' || value[0] == '+');
4330: value = ParseCSSUnit (value, &pval);
4331: if (pval.typed_data.unit != STYLE_UNIT_REL &&
4332: pval.typed_data.real)
4333: /* this is an error: it should be an integer without any unit name */
4334: /* error */;
4335: else
4336: {
4337: if (relative)
4338: {
1.63 cvs 4339: percentage = 100;
1.60 cvs 4340: if (pval.typed_data.value == 0)
4341: /* scriptlevel="+0" */
4342: percentage = 100;
4343: else if (pval.typed_data.value == 1)
4344: /* scriptlevel="+1" */
4345: percentage = 71;
4346: else if (pval.typed_data.value == 2)
4347: /* scriptlevel="+2" */
4348: percentage = 50;
4349: else if (pval.typed_data.value >= 3)
4350: /* scriptlevel="+3" or more */
4351: percentage = 35;
4352: else if (pval.typed_data.value == -1)
4353: /* scriptlevel="-1" */
4354: percentage = 141;
4355: else if (pval.typed_data.value == -2)
4356: /* scriptlevel="-2" */
4357: percentage = 200;
4358: else if (pval.typed_data.value <= -3)
4359: /* scriptlevel="-3" or less */
4360: percentage = 282;
4361: pval.typed_data.value = percentage;
4362: pval.typed_data.unit = STYLE_UNIT_PERCENT;
1.78 cvs 4363: /* the specific presentation to be created is not a CSS rule */
1.147 quint 4364: ctxt->cssSpecificity = 0;
1.60 cvs 4365: TtaSetStylePresentation (PRSize, el, NULL, ctxt, pval);
4366: }
4367: else
4368: /* absolute value */
4369: {
4370: /**** ****/;
4371: }
4372: }
4373: }
4374: TtaFreeMemory (ctxt);
4375: }
4376:
4377: /*----------------------------------------------------------------------
4378: MathMLSpacingAttr
4379: The MathML attribute attr (height, width or depth) is associated
4380: with element el (a mspace or mpadding).
4381: If value is not NULL, generate the corresponding Thot presentation rule for
4382: the element.
4383: If value is NULL, remove the corresponding Thot presentation rule.
4384: -----------------------------------------------------------------------*/
1.120 cvs 4385: void MathMLSpacingAttr (Document doc, Element el, char *value, int attr)
1.60 cvs 4386: {
4387: ElementType elType;
4388: PresentationValue pval;
4389: PresentationContext ctxt;
4390: int ruleType;
4391:
4392: /* provisionally, handles only mspace elements */
4393: elType = TtaGetElementType (el);
1.96 cvs 4394: if (elType.ElTypeNum != MathML_EL_MSPACE &&
1.97 cvs 4395: elType.ElTypeNum != MathML_EL_MPADDED &&
4396: elType.ElTypeNum != MathML_EL_MTABLE)
1.60 cvs 4397: return;
4398: switch (attr)
4399: {
4400: case MathML_ATTR_width_:
4401: ruleType = PRWidth;
4402: break;
4403: case MathML_ATTR_height_:
4404: ruleType = PRPaddingTop;
4405: break;
4406: case MathML_ATTR_depth_:
4407: ruleType = PRPaddingBottom;
4408: break;
4409: default:
4410: return;
4411: }
4412: ctxt = TtaGetSpecificStyleContext (doc);
1.116 cvs 4413: if (!value || (strcmp (value, "auto") == 0))
1.60 cvs 4414: /* remove the presentation rule */
4415: {
4416: ctxt->destroy = TRUE;
1.75 cvs 4417: pval.typed_data.value = 0;
1.60 cvs 4418: TtaSetStylePresentation (ruleType, el, NULL, ctxt, pval);
4419: }
4420: else
4421: {
4422: ctxt->destroy = FALSE;
4423: /* parse the attribute value (a number followed by a unit) */
1.119 cvs 4424: value = TtaSkipBlanks (value);
1.60 cvs 4425: value = ParseCSSUnit (value, &pval);
4426: /***** we should accept namedspace for width *****/
4427: if (pval.typed_data.unit != STYLE_UNIT_INVALID)
1.78 cvs 4428: {
4429: /* the specific presentation to be created is not a CSS rule */
1.147 quint 4430: ctxt->cssSpecificity = 0;
1.78 cvs 4431: TtaSetStylePresentation (ruleType, el, NULL, ctxt, pval);
4432: }
1.60 cvs 4433: }
4434: TtaFreeMemory (ctxt);
4435: }
4436:
4437: /*----------------------------------------------------------------------
1.169 quint 4438: MathMLSetDisplaystyleAttr
4439: The attribute displaystyle is associated with element el (which
4440: should be a <mstyle> or a <mtable> element).
1.175 quint 4441: Generate or set the corresponding internal attribute accordingly.
1.169 quint 4442: ----------------------------------------------------------------------*/
4443: void MathMLSetDisplaystyleAttr (Element el, Attribute attr, Document doc,
4444: ThotBool delete)
4445: {
4446: int val, intVal;
4447: ElementType elType;
4448: AttributeType attrType;
4449: Attribute intAttr;
1.153 quint 4450:
1.175 quint 4451: intVal = 0;
1.169 quint 4452: /* get the internal attribute */
4453: elType = TtaGetElementType (el);
4454: attrType.AttrSSchema = elType.ElSSchema;
4455: attrType.AttrTypeNum = MathML_ATTR_IntDisplaystyle;
4456: intAttr = TtaGetAttribute (el, attrType);
4457: if (delete)
4458: /* attribute displaystyle has been deleted */
4459: {
4460: if (elType.ElTypeNum == MathML_EL_MSTYLE)
4461: /* it's a mstyle element. Just remove the internal attribute */
4462: {
4463: if (intAttr)
4464: TtaRemoveAttribute (el, intAttr, doc);
4465: }
4466: else if (elType.ElTypeNum == MathML_EL_MTABLE)
4467: /* it's a matable element, set the default value (false) */
4468: intVal = MathML_ATTR_IntDisplaystyle_VAL_false;
4469: }
4470: else
4471: {
4472: val = TtaGetAttributeValue (attr);
4473: if (val == MathML_ATTR_displaystyle_VAL_true)
4474: intVal = MathML_ATTR_IntDisplaystyle_VAL_true;
4475: else
4476: intVal = MathML_ATTR_IntDisplaystyle_VAL_false;
4477: }
4478: /* create the IntDisplaystyle attribute if needed and set its value */
1.175 quint 4479: if (intVal)
1.169 quint 4480: {
1.175 quint 4481: if (!intAttr)
4482: {
4483: intAttr = TtaNewAttribute (attrType);
4484: TtaAttachAttribute (el, intAttr, doc);
4485: }
4486: TtaSetAttributeValue (intAttr, intVal, el, doc);
1.169 quint 4487: }
1.175 quint 4488: ApplyDisplaystyle (el, doc);
1.153 quint 4489: }
4490:
4491: /*----------------------------------------------------------------------
1.1 cvs 4492: MathMLAttributeComplete
1.58 cvs 4493: The XML parser has completed parsing attribute attr (as well as its value)
4494: that is associated with element el in document doc.
1.1 cvs 4495: ----------------------------------------------------------------------*/
1.120 cvs 4496: void MathMLAttributeComplete (Attribute attr, Element el, Document doc)
1.1 cvs 4497: {
1.134 cvs 4498: AttributeType attrType, depAttrType;
1.23 cvs 4499: int attrKind;
1.50 cvs 4500: ElementType elType;
1.120 cvs 4501: char *value;
1.50 cvs 4502: int val, length;
1.101 cvs 4503: Attribute intAttr;
1.169 quint 4504:
1.58 cvs 4505: /* first get the type of that attribute */
1.23 cvs 4506: TtaGiveAttributeType (attr, &attrType, &attrKind);
1.153 quint 4507:
1.54 cvs 4508: if (attrType.AttrTypeNum == MathML_ATTR_bevelled)
1.58 cvs 4509: /* it's a bevelled attribute */
1.50 cvs 4510: {
4511: val = TtaGetAttributeValue (attr);
1.54 cvs 4512: if (val == MathML_ATTR_bevelled_VAL_true)
4513: /* bevelled = true. Transform MFRAC into BevelledMFRAC */
1.50 cvs 4514: {
4515: elType = TtaGetElementType (el);
4516: if (elType.ElTypeNum == MathML_EL_MFRAC)
1.54 cvs 4517: ChangeTypeOfElement (el, doc, MathML_EL_BevelledMFRAC);
1.50 cvs 4518: }
4519: }
1.101 cvs 4520:
4521: else if (attrType.AttrTypeNum == MathML_ATTR_rowalign_mtr)
4522: {
4523: /* create an equivalent IntRowAlign attribute on the same element */
4524: attrType.AttrTypeNum = MathML_ATTR_IntRowAlign;
4525: intAttr = TtaGetAttribute (el, attrType);
4526: if (!intAttr)
4527: /* no IntRowAlign attribute, create one */
4528: {
4529: intAttr = TtaNewAttribute (attrType);
4530: TtaAttachAttribute (el, intAttr, doc);
4531: }
4532: val = TtaGetAttributeValue (attr);
4533: TtaSetAttributeValue (intAttr, val, el, doc);
4534: }
4535:
4536: else if (attrType.AttrTypeNum == MathML_ATTR_columnalign_mtd)
4537: {
4538: /* create an equivalent IntColAlign attribute on the same element */
4539: attrType.AttrTypeNum = MathML_ATTR_IntColAlign;
4540: intAttr = TtaGetAttribute (el, attrType);
4541: if (!intAttr)
4542: /* no IntColAlign attribute, create one */
4543: {
4544: intAttr = TtaNewAttribute (attrType);
4545: TtaAttachAttribute (el, intAttr, doc);
4546: }
4547: val = TtaGetAttributeValue (attr);
4548: TtaSetAttributeValue (intAttr, val, el, doc);
4549: }
4550:
1.159 quint 4551: /* don't handle attributes columnalign, rowalign, columnlines and rowlines
4552: now: the table or the row is not complete yet. Handle them when the
4553: element is complete.
1.104 cvs 4554: */
1.153 quint 4555:
4556: else if (attrType.AttrTypeNum == MathML_ATTR_display)
1.175 quint 4557: /* it's a display attribute on element <math>, set the corresponding
4558: internal attribute IntDisplaystyle */
4559: SetDisplaystyleMathElement (el, doc);
1.169 quint 4560:
4561: else if (attrType.AttrTypeNum == MathML_ATTR_displaystyle)
4562: /* it's a displaystyle attribute */
4563: MathMLSetDisplaystyleAttr (el, attr, doc, FALSE);
1.138 cvs 4564:
1.168 quint 4565: else if (attrType.AttrTypeNum == MathML_ATTR_framespacing)
4566: /* it's a framespacing attribute */
4567: HandleFramespacingAttribute (attr, el, doc, FALSE);
4568:
1.138 cvs 4569: else if (attrType.AttrTypeNum == MathML_ATTR_Language)
4570: {
4571: if (el == TtaGetRootElement (doc))
4572: /* it's the lang attribute on the root element */
4573: /* set the RealLang attribute */
4574: {
4575: depAttrType.AttrSSchema = attrType.AttrSSchema ;
4576: depAttrType.AttrTypeNum = MathML_ATTR_RealLang;
4577: if (!TtaGetAttribute (el, depAttrType))
4578: /* it's not present. Add it */
4579: {
4580: intAttr = TtaNewAttribute (depAttrType);
4581: TtaAttachAttribute (el, intAttr, doc);
4582: TtaSetAttributeValue (intAttr, MathML_ATTR_RealLang_VAL_Yes_,
4583: el, doc);
4584: }
4585: }
4586: }
1.101 cvs 4587:
1.50 cvs 4588: else if (attrType.AttrTypeNum == MathML_ATTR_color ||
1.93 cvs 4589: attrType.AttrTypeNum == MathML_ATTR_mathcolor ||
4590: attrType.AttrTypeNum == MathML_ATTR_background_ ||
4591: attrType.AttrTypeNum == MathML_ATTR_mathbackground ||
4592: attrType.AttrTypeNum == MathML_ATTR_fontsize ||
4593: attrType.AttrTypeNum == MathML_ATTR_mathsize ||
4594: attrType.AttrTypeNum == MathML_ATTR_fontfamily ||
4595: attrType.AttrTypeNum == MathML_ATTR_linethickness ||
4596: attrType.AttrTypeNum == MathML_ATTR_lspace ||
4597: attrType.AttrTypeNum == MathML_ATTR_rspace ||
4598: attrType.AttrTypeNum == MathML_ATTR_scriptlevel ||
4599: attrType.AttrTypeNum == MathML_ATTR_width_ ||
4600: attrType.AttrTypeNum == MathML_ATTR_height_ ||
1.168 quint 4601: attrType.AttrTypeNum == MathML_ATTR_depth_)
1.93 cvs 4602: {
1.23 cvs 4603: length = TtaGetTextAttributeLength (attr);
4604: if (length >= buflen)
4605: length = buflen - 1;
4606: if (length > 0)
4607: {
1.116 cvs 4608: value = TtaGetMemory (buflen);
1.33 cvs 4609: value[0] = EOS;
4610: TtaGiveTextAttributeValue (attr, value, &length);
4611: switch (attrType.AttrTypeNum)
4612: {
4613: case MathML_ATTR_color:
1.134 cvs 4614: /* deprecated attribute */
4615: /* if the same element has a mathcolor attribute, ignore
4616: the color attribute */
4617: depAttrType.AttrSSchema = attrType.AttrSSchema ;
4618: depAttrType.AttrTypeNum = MathML_ATTR_mathcolor;
4619: if (!TtaGetAttribute (el, depAttrType))
4620: HTMLSetForegroundColor (doc, el, value);
4621: break;
1.93 cvs 4622: case MathML_ATTR_mathcolor:
1.24 cvs 4623: HTMLSetForegroundColor (doc, el, value);
4624: break;
1.33 cvs 4625: case MathML_ATTR_background_:
1.134 cvs 4626: /* deprecated attribute */
4627: /* if the same element has a mathbackground attribute, ignore
4628: the background attribute */
4629: depAttrType.AttrSSchema = attrType.AttrSSchema;
4630: depAttrType.AttrTypeNum = MathML_ATTR_mathbackground;
4631: if (!TtaGetAttribute (el, depAttrType))
4632: HTMLSetBackgroundColor (doc, el, value);
4633: break;
1.93 cvs 4634: case MathML_ATTR_mathbackground:
1.24 cvs 4635: HTMLSetBackgroundColor (doc, el, value);
4636: break;
1.33 cvs 4637: case MathML_ATTR_fontfamily:
1.24 cvs 4638: SetFontfamily (doc, el, value);
1.83 cvs 4639: break;
4640: case MathML_ATTR_linethickness:
4641: MathMLlinethickness (doc, el, value);
1.58 cvs 4642: break;
4643: case MathML_ATTR_fontsize:
1.134 cvs 4644: /* deprecated attribute */
4645: /* if the same element has a mathsize attribute, ignore
4646: the fontsize attribute */
4647: depAttrType.AttrSSchema = attrType.AttrSSchema;
4648: depAttrType.AttrTypeNum = MathML_ATTR_mathsize;
4649: if (!TtaGetAttribute (el, depAttrType))
4650: MathMLAttrToStyleProperty (doc, el, value,
4651: attrType.AttrTypeNum);
4652: break;
1.93 cvs 4653: case MathML_ATTR_mathsize:
1.58 cvs 4654: case MathML_ATTR_lspace:
4655: case MathML_ATTR_rspace:
1.60 cvs 4656: MathMLAttrToStyleProperty (doc, el, value,attrType.AttrTypeNum);
4657: break;
4658: case MathML_ATTR_scriptlevel:
4659: MathMLSetScriptLevel (doc, el, value);
4660: break;
4661: case MathML_ATTR_width_:
4662: case MathML_ATTR_height_:
4663: case MathML_ATTR_depth_:
4664: MathMLSpacingAttr (doc, el, value, attrType.AttrTypeNum);
1.59 cvs 4665: break;
4666: default:
1.24 cvs 4667: break;
1.33 cvs 4668: }
4669: TtaFreeMemory (value);
1.23 cvs 4670: }
4671: }
1.1 cvs 4672: }
4673:
4674: /*----------------------------------------------------------------------
4675: MathMLGetDTDName
4676: ----------------------------------------------------------------------*/
1.120 cvs 4677: void MathMLGetDTDName (char *DTDname, char *elementName)
1.1 cvs 4678: {
4679: /* no other DTD allowed within MathML elements */
1.116 cvs 4680: strcpy (DTDname, "");
1.1 cvs 4681: }
4682:
4683: /* end of module */
Webmaster