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