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