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