Annotation of Amaya/amaya/MathMLbuilder.c, revision 1.225
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 */
1.225 ! quint 2281: (int)text[0] == 0x2223 || /* Vertical bar */
1.210 gully 2282: (int)text[0] == 0x2227 || /* and */
2283: (int)text[0] == 0x2228 || /* or */
2284: (int)text[0] == 0x2190 || /* left arrow */
2285: (int)text[0] == 0x2192 || /* right arrow */
2286: (int)text[0] == 0x2194) /* left right arrow */
2287: /* infix operator */
2288: val = MathML_ATTR_IntAddSpace_VAL_both_;
2289: else
2290: val = MathML_ATTR_IntAddSpace_VAL_nospace;
2291: }
2292: }
1.155 quint 2293: TtaSetAttributeValue (attr, val, el, doc);
2294: }
1.1 cvs 2295: }
2296:
2297: /*----------------------------------------------------------------------
1.210 gully 2298: ChildOfMRowOrInferred
2299: Return TRUE if element el is a child of a MROW element or an
2300: inferred MROW element
1.58 cvs 2301: ----------------------------------------------------------------------*/
2302: ThotBool ChildOfMRowOrInferred (Element el)
2303: {
1.210 gully 2304: ElementType elType;
2305: Element parent;
2306: ThotBool result;
2307:
2308: result = FALSE;
2309: parent = TtaGetParent (el);
2310: if (parent)
2311: {
1.58 cvs 2312: elType = TtaGetElementType (parent);
2313: result = (elType.ElTypeNum == MathML_EL_MROW ||
1.210 gully 2314: elType.ElTypeNum == MathML_EL_SqrtBase ||
2315: elType.ElTypeNum == MathML_EL_MSTYLE ||
2316: elType.ElTypeNum == MathML_EL_MERROR ||
2317: elType.ElTypeNum == MathML_EL_MENCLOSE ||
2318: elType.ElTypeNum == MathML_EL_MPADDED ||
2319: elType.ElTypeNum == MathML_EL_MPHANTOM ||
2320: elType.ElTypeNum == MathML_EL_MFENCED ||
2321: elType.ElTypeNum == MathML_EL_CellWrapper ||
2322: elType.ElTypeNum == MathML_EL_MathML ||
1.58 cvs 2323: elType.ElTypeNum == MathML_EL_FencedExpression);
1.210 gully 2324: }
2325: return result;
1.58 cvs 2326: }
2327:
2328: /*----------------------------------------------------------------------
1.210 gully 2329: CheckFence
1.212 quint 2330: If el is a MO element or a fence,
1.210 gully 2331: if it's a child of a MROW (or equivalent) element and if it contains
2332: a single fence character, transform the MO into a MF and the fence
2333: character into a Thot stretchable symbol.
1.175 quint 2334: ----------------------------------------------------------------------*/
2335: void CheckFence (Element el, Document doc)
2336: {
1.210 gully 2337: ElementType elType, contType;
2338: Element content;
2339: AttributeType attrType;
2340: Attribute attr, attrStretchy;
2341: Language lang;
2342: CHAR_T text[2];
2343: char script;
2344: unsigned char c;
2345: int len, val;
2346: ThotBool oldStructureChecking;
2347:
2348: elType = TtaGetElementType (el);
2349: if (elType.ElTypeNum == MathML_EL_MO ||
2350: elType.ElTypeNum == MathML_EL_OpeningFence ||
2351: elType.ElTypeNum == MathML_EL_ClosingFence ||
2352: elType.ElTypeNum == MathML_EL_FencedSeparator)
2353: /* the element is a MO or equivalent */
2354: {
2355: content = TtaGetFirstChild (el);
2356: if (content != NULL)
2357: {
2358: contType = TtaGetElementType (content);
2359: if (contType.ElTypeNum == MathML_EL_TEXT_UNIT)
2360: {
2361: len = TtaGetElementVolume (content);
2362: if (len == 1)
2363: /* the MO or fence element contains a single character */
2364: {
2365: TtaGiveBufferContent (content, text, len+1, &lang);
2366: script = TtaGetScript (lang);
2367: if (ChildOfMRowOrInferred (el))
2368: /* the MO or fence element is a child of a MROW element */
2369: /* Is it a stretchable symbol? */
2370: {
2371: if (IsStretchyFence (text[0], script))
2372: /* it's a stretchable parenthesis or equivalent */
2373: {
2374: /* remove the content of the MO element */
2375: TtaDeleteTree (content, doc);
2376: /* change the MO element into a MF element */
2377: if (elType.ElTypeNum == MathML_EL_MO)
2378: TtaChangeTypeOfElement (el, doc, MathML_EL_MF);
2379: /* is there an attribute stretchy on this mo element? */
2380: attrType.AttrSSchema = elType.ElSSchema;
2381: attrType.AttrTypeNum = MathML_ATTR_stretchy;
2382: attrStretchy = TtaGetAttribute (el, attrType);
2383: if (attrStretchy)
2384: val = TtaGetAttributeValue (attrStretchy);
2385: else
2386: val = MathML_ATTR_stretchy_VAL_true;
2387: if (val == MathML_ATTR_stretchy_VAL_true)
2388: {
2389: /* attach a IntVertStretch attribute to the MF element */
2390: attrType.AttrTypeNum = MathML_ATTR_IntVertStretch;
2391: attr = TtaGetAttribute (el, attrType);
1.212 quint 2392: if (attr)
2393: TtaSetAttributeValue (attr,
1.217 vatton 2394: MathML_ATTR_IntVertStretch_VAL_yes_,
2395: el, doc);
1.212 quint 2396: else
1.210 gully 2397: {
2398: attr = TtaNewAttribute (attrType);
1.212 quint 2399: TtaSetAttributeValue (attr,
1.217 vatton 2400: MathML_ATTR_IntVertStretch_VAL_yes_,
2401: el, doc);
1.210 gully 2402: TtaAttachAttribute (el, attr, doc);
2403: }
2404: }
2405: /* create a new content for the MF element */
2406: elType.ElTypeNum = MathML_EL_SYMBOL_UNIT;
1.217 vatton 2407: if (text[0] == 0x2329)
2408: c = '<'; /* LeftAngleBracket */
2409: else if (text[0] == 0x232a)
1.210 gully 2410: c = '>'; /* RightAngleBracket */
1.217 vatton 2411: else if (text[0] == 0x301a)
2412: c = 1; /* LeftDoubleBracket */
2413: else if (text[0] == 0x301b)
2414: c = 2; /* RightDoubleBracket */
2415: else if (text[0] == 0x2308)
2416: c = 3; /* LeftCeiling */
2417: else if (text[0] == 0x2309)
2418: c = 4; /* RightCeiling */
2419: else if (text[0] == 0x230a)
2420: c = 5; /* LeftFloor */
2421: else if (text[0] == 0x230b)
2422: c = 6; /* RightFloor */
1.210 gully 2423: else
2424: c = (char) text[0];
2425: content = TtaNewElement (doc, elType);
2426: /* do not check the Thot abstract tree against the structure
2427: schema while inserting this child element */
2428: oldStructureChecking = TtaGetStructureChecking (doc);
2429: TtaSetStructureChecking (FALSE, doc);
1.212 quint 2430: TtaSetGraphicsShape (content, c, doc);
1.210 gully 2431: TtaInsertFirstChild (&content, el, doc);
2432: /* resume structure checking */
2433: TtaSetStructureChecking (oldStructureChecking, doc);
2434: }
2435: }
2436: }
2437: }
2438: }
2439: }
2440: }
2441:
2442: /*----------------------------------------------------------------------
2443: CreateFencedSeparators
2444: Create FencedSeparator elements within the fencedExpression
2445: according to attribute separators of the MFENCED element.
1.1 cvs 2446: ----------------------------------------------------------------------*/
1.110 cvs 2447: void CreateFencedSeparators (Element fencedExpression, Document doc, ThotBool record)
1.1 cvs 2448: {
1.210 gully 2449: ElementType elType;
2450: Element child, separator, leaf, next, prev, mfenced;
2451: AttributeType attrType;
2452: Attribute attr;
2453: int length, sep, i;
2454: Language lang;
2455: char text[32], sepValue[4];
2456:
2457: /* get the separators attribute */
2458: mfenced = TtaGetParent (fencedExpression);
2459: elType = TtaGetElementType (fencedExpression);
2460: attrType.AttrSSchema = elType.ElSSchema;
2461: attrType.AttrTypeNum = MathML_ATTR_separators;
1.223 vatton 2462: text[0] = ','; /* default value is separators="," */
1.210 gully 2463: text[1] = EOS;
2464: length = 1;
2465: attr = TtaGetAttribute (mfenced, attrType);
2466: if (attr != NULL)
2467: {
1.1 cvs 2468: length = 31;
2469: TtaGiveTextAttributeValue (attr, text, &length);
1.210 gully 2470: }
1.1 cvs 2471:
1.210 gully 2472: /* create FencedSeparator elements in the FencedExpression */
2473: prev = NULL;
2474: sep = 0;
2475: /* skip leading spaces in attribute separators */
2476: while (text[sep] <= SPACE && text[sep] != EOS)
2477: sep++;
2478: /* if attribute separators is empty or contains only spaces, do not
2479: insert any separator element */
2480: if (text[sep] != EOS)
2481: {
2482: child = TtaGetFirstChild (fencedExpression);
2483: while (child != NULL)
2484: {
2485: next = child;
2486: TtaNextSibling (&next);
2487: elType = TtaGetElementType (child);
2488: if (elType.ElTypeNum != MathML_EL_Construct)
2489: {
2490: if (prev != NULL)
2491: {
2492: elType.ElTypeNum = MathML_EL_FencedSeparator;
2493: separator = TtaNewElement (doc, elType);
2494: TtaInsertSibling (separator, prev, FALSE, doc);
2495: elType.ElTypeNum = MathML_EL_TEXT_UNIT;
2496: leaf = TtaNewElement (doc, elType);
2497: TtaInsertFirstChild (&leaf, separator, doc);
2498: sepValue[0] = text[sep];
2499: sepValue[1] = EOS;
2500: lang = TtaGetLanguageIdFromScript('L');
2501: TtaSetTextContent (leaf, (unsigned char *)sepValue, lang, doc);
2502: SetIntAddSpaceAttr (separator, doc);
2503: SetIntVertStretchAttr (separator, doc, 0, NULL);
2504: CheckFence (separator, doc);
2505:
2506: /* is there a following non-space character in separators? */
2507: i = sep + 1;
2508: while (text[i] <= SPACE && text[i] != EOS)
2509: i++;
2510: if (text[i] > SPACE && text[i] != EOS)
2511: sep = i;
2512: if (record)
2513: TtaRegisterElementCreate (separator, doc);
2514: }
2515: prev = child;
2516: }
2517: child = next;
2518: }
2519: }
1.1 cvs 2520: }
2521:
1.124 cvs 2522: /*----------------------------------------------------------------------
1.210 gully 2523: CreateOpeningOrClosingFence
2524: Create the OpeningFence or ClosingFence element (depending on parameter
2525: open) for the MFENCED element el which contain the fencedExpression
2526: element.
1.124 cvs 2527: ----------------------------------------------------------------------*/
2528: static void CreateOpeningOrClosingFence (Element fencedExpression,
1.210 gully 2529: Element el, Document doc,
2530: ThotBool open)
1.124 cvs 2531: {
2532: ElementType elType;
2533: Element leaf, fence;
2534: AttributeType attrType;
2535: Attribute attr;
1.224 vatton 2536: int length, value;
2537: char text[32], *s;
2538: CHAR_T val[2];
1.124 cvs 2539:
2540: elType = TtaGetElementType (el);
2541: attrType.AttrSSchema = elType.ElSSchema;
2542: if (open)
2543: {
1.158 quint 2544: text[0] = '('; /* default value of attribute 'open' */
1.124 cvs 2545: attrType.AttrTypeNum = MathML_ATTR_open;
2546: elType.ElTypeNum = MathML_EL_OpeningFence;
1.223 vatton 2547: length = 1;
1.124 cvs 2548: }
2549: else
2550: {
1.158 quint 2551: text[0] = ')'; /* default value of attribute 'close' */
1.124 cvs 2552: attrType.AttrTypeNum = MathML_ATTR_close;
2553: elType.ElTypeNum = MathML_EL_ClosingFence;
1.223 vatton 2554: length = 1;
1.124 cvs 2555: }
2556: attr = TtaGetAttribute (el, attrType);
2557: if (attr != NULL)
2558: {
2559: length = 31;
2560: TtaGiveTextAttributeValue (attr, text, &length);
1.223 vatton 2561: if (length == 0)
1.210 gully 2562: /* content of attribute open or close should be a single character */
1.223 vatton 2563: text[0] = SPACE;
1.224 vatton 2564: else if (text[0] == START_ENTITY)
2565: {
2566: text[0] = '&';
2567: text[length-1] = EOS;
2568: if (MapXMLEntity (MATH_TYPE, &text[1], &value))
2569: {
2570: // convert the entity
2571: val[0] = (CHAR_T) value;
2572: val[1] = EOS;
2573: s = (char *)TtaConvertWCToByte ((CHAR_T *)val, UTF_8);
2574: strcpy (text, s);
2575: TtaFreeMemory (s);
2576: length = strlen (text);
2577: }
2578: else
2579: text[length-1] = ';';
2580: }
1.124 cvs 2581: }
1.223 vatton 2582: text[length] = EOS;
1.124 cvs 2583: fence = TtaNewElement (doc, elType);
2584: TtaInsertSibling (fence, fencedExpression, open, doc);
1.158 quint 2585: elType.ElTypeNum = MathML_EL_TEXT_UNIT;
1.124 cvs 2586: leaf = TtaNewElement (doc, elType);
2587: TtaInsertFirstChild (&leaf, fence, doc);
1.193 gully 2588: TtaSetTextContent (leaf, (unsigned char *)text, TtaGetLanguageIdFromScript('L'), doc);
1.158 quint 2589: SetIntAddSpaceAttr (fence, doc);
2590: SetIntVertStretchAttr (fence, doc, 0, NULL);
1.175 quint 2591: CheckFence (fence, doc);
1.124 cvs 2592: }
1.1 cvs 2593:
2594: /*----------------------------------------------------------------------
1.210 gully 2595: TransformMFENCED
2596: Transform the content of a MFENCED element: create elements
2597: OpeningFence, FencedExpression, ClosingFence and FencedSeparator.
1.1 cvs 2598: ----------------------------------------------------------------------*/
1.46 cvs 2599: static void TransformMFENCED (Element el, Document doc)
1.1 cvs 2600: {
1.210 gully 2601: ElementType elType;
2602: Element child, fencedExpression, next, prev, firstChild;
1.1 cvs 2603:
1.210 gully 2604: child = TtaGetFirstChild (el);
2605: if (child != NULL)
2606: elType = TtaGetElementType (child);
2607: if (child != NULL && elType.ElTypeNum == MathML_EL_OpeningFence)
2608: /* The first child of this MFENCED element is an OpeningFence.
2609: This MFENCED expression has already been transformed, possibly
2610: by the Transform command */
2611: {
1.1 cvs 2612: TtaNextSibling (&child);
2613: fencedExpression = child;
2614: if (fencedExpression != NULL)
1.210 gully 2615: elType = TtaGetElementType (fencedExpression);
1.1 cvs 2616: if (elType.ElTypeNum == MathML_EL_FencedExpression)
1.210 gully 2617: /* the second child is a FencedExpression. OK.
2618: Remove all existing FencedSeparator elements */
2619: {
2620: child = TtaGetFirstChild (fencedExpression);
2621: prev = NULL;
2622: while (child != NULL)
2623: {
2624: elType = TtaGetElementType (child);
2625: next = child;
2626: TtaNextSibling (&next);
2627: if (elType.ElTypeNum == MathML_EL_FencedSeparator)
2628: /* Remove this separator */
2629: TtaDeleteTree (child, doc);
2630: child = next;
2631: }
2632: /* create FencedSeparator elements in the FencedExpression */
2633: CreateFencedSeparators (fencedExpression, doc, FALSE);
2634: }
2635: }
2636: else
2637: /* this MFENCED element must be transformed */
2638: {
1.1 cvs 2639: /* create a FencedExpression element as a child of the MFENCED elem. */
2640: elType = TtaGetElementType (el);
2641: elType.ElTypeNum = MathML_EL_FencedExpression;
2642: fencedExpression = TtaNewElement (doc, elType);
2643: TtaInsertFirstChild (&fencedExpression, el, doc);
2644: if (child == NULL)
1.210 gully 2645: /* empty MFENCED element */
2646: {
2647: elType.ElTypeNum = MathML_EL_Construct;
2648: child = TtaNewElement (doc, elType);
2649: TtaInsertFirstChild (&child, fencedExpression, doc);
2650: SetIntPlaceholderAttr (child, doc);
2651: }
1.1 cvs 2652: else
1.210 gully 2653: {
2654: /* move the content of the MFENCED element within the new
2655: FencedExpression element */
2656: prev = NULL;
2657: firstChild = NULL;
2658: while (child != NULL)
2659: {
2660: next = child;
2661: TtaNextSibling (&next);
2662: TtaRemoveTree (child, doc);
2663: if (prev == NULL)
2664: {
2665: TtaInsertFirstChild (&child, fencedExpression, doc);
2666: firstChild = child;
2667: }
2668: else
2669: TtaInsertSibling (child, prev, FALSE, doc);
2670: prev = child;
2671: child = next;
2672: }
2673:
2674: /* create FencedSeparator elements in the FencedExpression */
2675: CreateFencedSeparators (fencedExpression, doc, FALSE);
2676:
2677: /* Create placeholders within the FencedExpression element */
2678: CreatePlaceholders (firstChild, doc);
2679: }
1.1 cvs 2680:
2681: /* create the OpeningFence element according to the open attribute */
1.124 cvs 2682: CreateOpeningOrClosingFence (fencedExpression, el, doc, TRUE);
1.1 cvs 2683:
2684: /* create the ClosingFence element according to close attribute */
1.124 cvs 2685: CreateOpeningOrClosingFence (fencedExpression, el, doc, FALSE);
1.210 gully 2686: }
1.1 cvs 2687: }
2688:
2689: /*----------------------------------------------------------------------
1.210 gully 2690: MathMLScriptShift
2691: The MathML attribute attr (superscriptshift or subscriptshift) is associated
2692: with element el (a msub, msup or msubsup).
2693: If value is not NULL, generate the corresponding Thot VertPos rule for the
2694: Subscript or Superscript child of el.
2695: If value is NULL, remove the Thot VertPos rule.
2696: -----------------------------------------------------------------------*/
1.120 cvs 2697: void MathMLScriptShift (Document doc, Element el, char *value, int attr)
1.59 cvs 2698: {
2699: ElementType elType;
2700: Element script, child;
2701: int scrType;
2702: PresentationValue pval;
2703: PresentationContext ctxt;
2704:
2705: /* get the Superscript or Subscript child of el */
2706: if (attr == MathML_ATTR_superscriptshift)
1.210 gully 2707: scrType = MathML_EL_Superscript;
1.59 cvs 2708: else if (attr == MathML_ATTR_subscriptshift)
1.210 gully 2709: scrType = MathML_EL_Subscript;
1.59 cvs 2710: else
1.210 gully 2711: return;
1.59 cvs 2712: script = NULL;
2713: child = TtaGetFirstChild (el);
2714: while (!script && child)
2715: {
1.210 gully 2716: elType = TtaGetElementType (child);
2717: if (elType.ElTypeNum == scrType)
2718: script = child;
2719: else
2720: TtaNextSibling (&child);
1.59 cvs 2721: }
2722: if (script)
2723: /* Superscript or Subscript element found */
2724: {
1.210 gully 2725: ctxt = TtaGetSpecificStyleContext (doc);
2726: if (!value)
2727: /* remove the presentation rule */
2728: {
2729: ctxt->destroy = TRUE;
2730: pval.typed_data.value = 0;
2731: TtaSetStylePresentation (PRVertPos, script, NULL, ctxt, pval);
2732: }
2733: else
2734: {
2735: ctxt->destroy = FALSE;
2736: /* parse the attribute value (a number followed by a unit) */
2737: value = TtaSkipBlanks (value);
2738: value = ParseCSSUnit (value, &pval);
2739: if (pval.typed_data.unit != UNIT_INVALID)
2740: {
2741: if (pval.typed_data.unit == UNIT_BOX)
2742: pval.typed_data.unit = UNIT_EM;
2743: pval.typed_data.mainValue = TRUE;
2744: /* the specific presentation to be created is not a CSS rule */
2745: ctxt->cssSpecificity = 0;
2746: if (attr == MathML_ATTR_superscriptshift)
2747: pval.typed_data.value = - pval.typed_data.value;
2748: TtaSetStylePresentation (PRVertPos, script, NULL, ctxt, pval);
2749: }
2750: }
2751: TtaFreeMemory (ctxt);
1.59 cvs 2752: }
2753: }
2754:
2755: /*----------------------------------------------------------------------
1.210 gully 2756: SetScriptShift
2757: If element el (which is a msup, msub or msubsup) has an attribute
2758: att (which is subscriptshift or superscriptshift), generate the
2759: corresponding Thot presentation rule.
1.59 cvs 2760: ----------------------------------------------------------------------*/
1.120 cvs 2761: static void SetScriptShift (Element el, Document doc, int att)
1.59 cvs 2762: {
1.210 gully 2763: AttributeType attrType;
2764: ElementType elType;
2765: Attribute attr;
2766: char *value;
2767: int length;
2768:
2769: elType = TtaGetElementType (el);
2770: attrType.AttrSSchema = elType.ElSSchema;
2771: attrType.AttrTypeNum = att;
2772: attr = TtaGetAttribute (el, attrType);
2773: if (attr)
2774: {
1.59 cvs 2775: length = TtaGetTextAttributeLength (attr);
2776: if (length > 0)
1.210 gully 2777: {
2778: value = (char *)TtaGetMemory (length+1);
2779: value[0] = EOS;
2780: TtaGiveTextAttributeValue (attr, value, &length);
2781: MathMLScriptShift (doc, el, value, att);
2782: TtaFreeMemory (value);
2783: }
2784: }
1.59 cvs 2785: }
2786:
2787: /*----------------------------------------------------------------------
1.210 gully 2788: DeleteIntRowAlign
2789: Remove attribute IntRowAlign from element row if there is no rowalign_mtr
2790: attribut on this element.
2791: -----------------------------------------------------------------------*/
1.159 quint 2792: static void DeleteIntRowAlign (Element row, Document doc)
2793: {
2794: ElementType elType;
2795: AttributeType attrType;
2796: Attribute attr;
2797:
2798: elType = TtaGetElementType (row);
2799: attrType.AttrSSchema = elType.ElSSchema;
2800: attrType.AttrTypeNum = MathML_ATTR_rowalign_mtr;
2801: attr = TtaGetAttribute (row, attrType);
2802: if (!attr)
2803: {
2804: attrType.AttrTypeNum = MathML_ATTR_IntRowAlign;
2805: attr = TtaGetAttribute (row, attrType);
2806: if (attr)
1.210 gully 2807: TtaRemoveAttribute (row, attr, doc);
1.159 quint 2808: }
2809: }
2810:
2811: /*----------------------------------------------------------------------
1.210 gully 2812: SetIntRowAlign
2813: Set attribute IntRowAlign for element row unless this element already has
2814: a rowalign_mtr attribute
2815: -----------------------------------------------------------------------*/
1.159 quint 2816: static void SetIntRowAlign (Element row, int val, Document doc)
2817: {
2818: ElementType elType;
2819: AttributeType attrType;
2820: Attribute attr;
2821:
2822: elType = TtaGetElementType (row);
2823: attrType.AttrSSchema = elType.ElSSchema;
2824: attrType.AttrTypeNum = MathML_ATTR_rowalign_mtr;
2825: attr = TtaGetAttribute (row, attrType);
2826: if (!attr)
2827: {
2828: attrType.AttrTypeNum = MathML_ATTR_IntRowAlign;
2829: attr = TtaGetAttribute (row, attrType);
2830: if (!attr)
1.210 gully 2831: {
2832: attr = TtaNewAttribute (attrType);
2833: TtaAttachAttribute (row, attr, doc);
2834: }
1.159 quint 2835: TtaSetAttributeValue (attr, val, row, doc);
2836: }
2837: }
2838:
2839: /*----------------------------------------------------------------------
1.210 gully 2840: HandleRowalignAttribute
2841: An attribute rowalign has been created, updated (if !delete) or deleted
2842: (if delete) for element el in document doc. Update the IntRowAlign
2843: attributes of all enclosed mrow elements accordingly.
1.159 quint 2844: ----------------------------------------------------------------------*/
2845: void HandleRowalignAttribute (Attribute attr, Element el, Document doc,
1.210 gully 2846: ThotBool delete_)
1.159 quint 2847: {
2848: char *value;
2849: char *ptr;
2850: int length, val;
2851: ElementType elType;
2852: Element row;
2853:
2854: elType = TtaGetElementType (el);
2855: if (elType.ElTypeNum != MathML_EL_MTABLE ||
2856: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML"))
2857: /* ignore rowalign attribute on mstyle elements */
2858: /* process it only on mtable elements */
2859: return;
2860:
2861: value = NULL;
1.193 gully 2862: if (!delete_)
1.159 quint 2863: {
2864: length = TtaGetTextAttributeLength (attr);
2865: if (length > 0)
1.210 gully 2866: {
2867: value = (char *)TtaGetMemory (length+1);
2868: value[0] = EOS;
2869: TtaGiveTextAttributeValue (attr, value, &length);
2870: }
1.159 quint 2871: }
2872: /* if attribute rowalign is created or updated but has no value, don't
2873: do anything */
1.193 gully 2874: if (!delete_ && !value)
1.159 quint 2875: return;
2876:
2877: ptr = value;
2878: val = 0;
2879: elType.ElTypeNum = MathML_EL_TableRow;
2880: row = TtaSearchTypedElement (elType, SearchInTree, el);
2881: while (row)
2882: {
1.210 gully 2883: elType = TtaGetElementType (row);
2884: /* skip comments and other non row elements */
2885: if ((elType.ElTypeNum == MathML_EL_MTR ||
2886: elType.ElTypeNum == MathML_EL_MLABELEDTR) &&
2887: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML") == 0)
2888: {
2889: if (delete_)
2890: DeleteIntRowAlign (row, doc);
2891: else
2892: {
2893: if (*ptr != EOS)
2894: {
2895: /* get next word in the attribute value */
2896: ptr = TtaSkipBlanks (ptr);
2897: /* process that word */
2898: if (*ptr != EOS && *ptr != ' ')
2899: {
2900: if (!strncasecmp (ptr, "top", 3))
2901: val = MathML_ATTR_IntRowAlign_VAL_IntTop;
2902: else if (!strncasecmp (ptr, "bottom", 6))
2903: val = MathML_ATTR_IntRowAlign_VAL_IntBottom;
2904: else if (!strncasecmp (ptr, "center", 6))
2905: val = MathML_ATTR_IntRowAlign_VAL_IntCenter;
2906: else if (!strncasecmp (ptr, "baseline", 8))
2907: val = MathML_ATTR_IntRowAlign_VAL_IntBaseline;
2908: else if (!strncasecmp (ptr, "axis", 4))
2909: val = MathML_ATTR_IntRowAlign_VAL_IntAxis;
2910: else
2911: val = 0;
2912: /* skip the word that has been processed */
2913: while (*ptr != EOS && *ptr != ' ')
2914: ptr++;
2915: }
2916: }
2917: if (val > 0)
2918: SetIntRowAlign (row, val, doc);
2919: }
2920: }
2921: TtaNextSibling (&row);
1.159 quint 2922: }
2923: if (value)
2924: TtaFreeMemory (value);
2925: }
2926:
2927: /*----------------------------------------------------------------------
1.210 gully 2928: DeleteIntColAlign
2929: Remove attribute IntColAlign from element cell if there is no columnalign_mtd
2930: attribut on this element.
2931: -----------------------------------------------------------------------*/
1.159 quint 2932: static void DeleteIntColAlign (Element cell, Document doc)
2933: {
2934: ElementType elType;
2935: AttributeType attrType;
2936: Attribute attr;
2937:
2938: elType = TtaGetElementType (cell);
2939: attrType.AttrSSchema = elType.ElSSchema;
2940: attrType.AttrTypeNum = MathML_ATTR_columnalign_mtd;
2941: attr = TtaGetAttribute (cell, attrType);
2942: if (!attr)
2943: {
2944: attrType.AttrTypeNum = MathML_ATTR_IntColAlign;
2945: attr = TtaGetAttribute (cell, attrType);
2946: if (attr)
1.210 gully 2947: TtaRemoveAttribute (cell, attr, doc);
1.159 quint 2948: }
2949: }
2950:
2951: /*----------------------------------------------------------------------
1.210 gully 2952: SetIntColAlign
2953: Set attribute IntColAlign for element cell unless this element already has
2954: a columnalign_mtd attribute
2955: -----------------------------------------------------------------------*/
1.159 quint 2956: static void SetIntColAlign (Element cell, int val, Document doc)
2957: {
2958: ElementType elType;
2959: AttributeType attrType;
2960: Attribute attr;
2961:
2962: elType = TtaGetElementType (cell);
2963: attrType.AttrSSchema = elType.ElSSchema;
2964: attrType.AttrTypeNum = MathML_ATTR_columnalign_mtd;
2965: attr = TtaGetAttribute (cell, attrType);
2966: if (!attr)
2967: {
2968: attrType.AttrTypeNum = MathML_ATTR_IntColAlign;
2969: attr = TtaGetAttribute (cell, attrType);
2970: if (!attr)
1.210 gully 2971: {
2972: attr = TtaNewAttribute (attrType);
2973: TtaAttachAttribute (cell, attr, doc);
2974: }
1.159 quint 2975: TtaSetAttributeValue (attr, val, cell, doc);
2976: }
2977: }
2978:
2979: /*----------------------------------------------------------------------
1.210 gully 2980: RowWithoutColalignAttr
2981: if skip: if element row has a columnalign attribute, get the next sibling row
2982: element without a columnalign attribute and return its first cell
2983: if not skip: always return the first cell in the row, and the columnalign
2984: attribute of that row if there is one.
2985: -----------------------------------------------------------------------*/
1.159 quint 2986: static void RowWithoutColalignAttr (Element *row, Element *cell,
1.210 gully 2987: Attribute *attr, ThotBool skip)
1.159 quint 2988: {
2989: ElementType elType;
2990: AttributeType attrType;
2991:
2992: elType = TtaGetElementType (*row);
2993: attrType.AttrSSchema = elType.ElSSchema;
2994: attrType.AttrTypeNum = MathML_ATTR_columnalign;
2995: *cell = NULL;
2996: *attr = NULL;
2997: while (*row != NULL && *cell == NULL)
2998: {
2999: elType = TtaGetElementType (*row);
3000: if ((elType.ElTypeNum != MathML_EL_MTR &&
1.210 gully 3001: elType.ElTypeNum != MathML_EL_MLABELEDTR) ||
3002: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML"))
3003: /* not a row. Skip it */
3004: TtaNextSibling (row);
1.159 quint 3005: else
1.210 gully 3006: {
3007: /* skip that row if it has a columnalign attribute */
3008: *attr = TtaGetAttribute (*row, attrType);
3009: if (skip && *attr != NULL)
3010: {
3011: TtaNextSibling (row);
3012: *attr = NULL;
3013: }
3014: else
3015: /* it's a row without a columnalign attribute */
3016: *cell = TtaGetFirstChild (*row);
3017: }
1.159 quint 3018: }
3019: }
3020:
3021: /*----------------------------------------------------------------------
1.210 gully 3022: HandleColalignAttribute
3023: An attribute columnalign has been created, updated (if !delete) or deleted
3024: (if delete) for element el in document doc. Update the IntColAlign
3025: attributes of all concerned cells accordingly.
3026: If allRows is TRUE, process also rows that have their own columnalign
3027: attribute, according to that attribute, otherwise skip those rows.
1.159 quint 3028: ----------------------------------------------------------------------*/
3029: void HandleColalignAttribute (Attribute attr, Element el, Document doc,
1.210 gully 3030: ThotBool delete_, ThotBool allRows)
1.159 quint 3031: {
3032: char *value, *localValue;
3033: char *ptr;
3034: int length, val;
3035: ElementType elType;
3036: Element cell, row;
3037: Attribute localAttr;
3038: ThotBool fullTable;
3039:
3040: elType = TtaGetElementType (el);
3041: if ((elType.ElTypeNum != MathML_EL_MTABLE &&
3042: elType.ElTypeNum != MathML_EL_MTR &&
3043: elType.ElTypeNum != MathML_EL_MLABELEDTR) ||
3044: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML"))
3045: /* ignore columnalign attribute on mstyle elements */
3046: /* process it only on mtable elements */
3047: return;
3048:
3049: fullTable = (elType.ElTypeNum == MathML_EL_MTABLE);
3050: value = NULL;
3051: localValue = NULL;
1.193 gully 3052: if (!delete_)
1.159 quint 3053: {
3054: length = TtaGetTextAttributeLength (attr);
3055: if (length > 0)
1.210 gully 3056: {
3057: value = (char *)TtaGetMemory (length+1);
3058: value[0] = EOS;
3059: TtaGiveTextAttributeValue (attr, value, &length);
3060: }
1.159 quint 3061: }
3062: /* if attribute columnalign is created or updated but has no value, don't
3063: do anything */
1.193 gully 3064: if (!delete_ && !value)
1.159 quint 3065: return;
3066:
3067: ptr = value;
3068: val = 0;
3069: /* get the first cell within the element */
3070: elType.ElTypeNum = MathML_EL_MTD;
3071: cell = TtaSearchTypedElement (elType, SearchInTree, el);
3072: if (cell && fullTable)
3073: {
1.210 gully 3074: elType.ElTypeNum = MathML_EL_TableRow;
3075: row = TtaGetTypedAncestor (cell, elType);
3076: RowWithoutColalignAttr (&row, &cell, &localAttr, !allRows);
3077: if (localAttr)
3078: {
3079: length = TtaGetTextAttributeLength (localAttr);
3080: if (length > 0)
3081: {
3082: if (localValue)
3083: TtaFreeMemory (localValue);
3084: localValue = (char *)TtaGetMemory (length+1);
3085: localValue[0] = EOS;
3086: TtaGiveTextAttributeValue (localAttr, localValue, &length);
3087: ptr = localValue;
3088: }
3089: }
1.159 quint 3090: }
3091: while (cell)
3092: {
1.210 gully 3093: elType = TtaGetElementType (cell);
3094: /* skip comments and other non cell elements */
3095: if (elType.ElTypeNum == MathML_EL_MTD &&
3096: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML") == 0)
3097: {
3098: if (delete_)
3099: DeleteIntColAlign (cell, doc);
3100: else
3101: {
3102: if (*ptr != EOS)
3103: {
3104: /* get next word in the attribute value */
3105: ptr = TtaSkipBlanks (ptr);
3106: /* process that word */
3107: if (*ptr != EOS && *ptr != ' ')
3108: {
3109: if (!strncasecmp (ptr, "left", 4))
3110: val = MathML_ATTR_IntColAlign_VAL_IntLeft;
3111: else if (!strncasecmp (ptr, "center", 6))
3112: val = MathML_ATTR_IntColAlign_VAL_IntCenter;
3113: else if (!strncasecmp (ptr, "right", 5))
3114: val = MathML_ATTR_IntColAlign_VAL_IntRight;
3115: else
3116: val = 0;
3117: /* skip the word that has been processed */
3118: while (*ptr != EOS && *ptr != ' ')
3119: ptr++;
3120: }
3121: }
3122: if (val > 0)
3123: SetIntColAlign (cell, val, doc);
3124: }
3125: }
3126: TtaNextSibling (&cell);
3127: if (!cell && fullTable && row)
3128: /* no more sibling cell. If the columnalign attribute is for the
3129: full table, get the first cell in the next row */
3130: {
3131: TtaNextSibling (&row);
3132: if (row)
3133: {
3134: /* parse value of columnalign attribute again from the beginning */
3135: ptr = value;
3136: RowWithoutColalignAttr (&row, &cell, &localAttr, !allRows);
3137: if (localAttr)
3138: {
3139: length = TtaGetTextAttributeLength (localAttr);
3140: if (length > 0)
3141: {
3142: if (localValue)
3143: TtaFreeMemory (localValue);
3144: localValue = (char *)TtaGetMemory (length+1);
3145: localValue[0] = EOS;
3146: TtaGiveTextAttributeValue (localAttr, localValue, &length);
3147: ptr = localValue;
3148: }
3149: }
3150: }
3151: }
1.159 quint 3152: }
3153: if (value)
3154: TtaFreeMemory (value);
3155: if (localValue)
3156: TtaFreeMemory (localValue);
3157: }
3158:
3159: /*----------------------------------------------------------------------
1.210 gully 3160: HandleRowspacingAttribute
3161: An attribute rowspacing has been created, updated or deleted (if delete
3162: is TRUE) for element el in document doc. Update the top and bottom padding
3163: of all cells accordingly.
1.167 quint 3164: ----------------------------------------------------------------------*/
3165: void HandleRowspacingAttribute (Attribute attr, Element el, Document doc,
1.193 gully 3166: ThotBool delete_)
1.167 quint 3167: {
3168: ElementType elType, rowType, cellType;
3169: int length, val, topVal, topValUnit, bottomVal,
1.210 gully 3170: bottomValUnit, rowspan, cellBottomVal, i;
1.167 quint 3171: char *value, *ptr, *spanPtr;
3172: PresentationValue pval;
3173: PresentationContext ctxt;
3174: Element row, nextRow, cell;
3175: ThotBool stop, firstRow;
3176: AttributeType rowspanType;
3177: Attribute rowspanAttr;
3178:
3179: elType = TtaGetElementType (el);
3180: if (elType.ElTypeNum != MathML_EL_MTABLE ||
3181: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML"))
3182: /* ignore rowspacing attribute on mstyle elements */
3183: /* process it only on mtable elements */
3184: return;
3185:
3186: value = NULL;
1.193 gully 3187: if (!delete_ && attr)
1.167 quint 3188: {
3189: length = TtaGetTextAttributeLength (attr);
3190: if (length > 0)
1.210 gully 3191: {
3192: value = (char *)TtaGetMemory (length+1);
3193: value[0] = EOS;
3194: TtaGiveTextAttributeValue (attr, value, &length);
3195: }
1.167 quint 3196: }
3197:
3198: ctxt = TtaGetSpecificStyleContext (doc);
3199: /* the specific presentation to be created is not a CSS rule */
3200: ctxt->cssSpecificity = 0;
3201: ptr = value;
3202: rowspanType.AttrSSchema = elType.ElSSchema;
3203: rowspanType.AttrTypeNum = MathML_ATTR_rowspan_;
3204:
3205: /* check all rows within the table */
3206: firstRow = TRUE;
3207: bottomVal = 0;
1.184 vatton 3208: bottomValUnit = UNIT_PT;
1.167 quint 3209: elType.ElTypeNum = MathML_EL_TableRow;
3210: row = TtaSearchTypedElement (elType, SearchInTree, el);
3211: while (row)
3212: {
3213: /* get the next row to check if the current row is the last one */
3214: nextRow = row;
3215: stop = FALSE;
3216: do
1.210 gully 3217: {
3218: TtaNextSibling (&nextRow);
3219: if (!nextRow)
3220: stop = TRUE;
3221: else
3222: {
3223: rowType = TtaGetElementType (nextRow);
3224: /* skip comments and other non mrow elements */
3225: if ((rowType.ElTypeNum == MathML_EL_MTR ||
3226: rowType.ElTypeNum == MathML_EL_MLABELEDTR) &&
3227: !strcmp (TtaGetSSchemaName (rowType.ElSSchema), "MathML"))
3228: /* it's the next mrow */
3229: stop = TRUE;
3230: }
3231: }
1.167 quint 3232: while (!stop);
3233:
3234: /* prepare the value of the padding to be associated with the cells
1.210 gully 3235: of that row */
1.182 quint 3236: val = 0;
1.193 gully 3237: if (delete_)
1.210 gully 3238: /* remove the presentation rules */
3239: pval.typed_data.value = 0;
1.167 quint 3240: else
1.210 gully 3241: {
3242: if (!value)
3243: {
3244: pval.typed_data.unit = UNIT_PT;
3245: pval.typed_data.value = 0;
3246: pval.typed_data.real = FALSE;
3247: }
3248: else
3249: {
3250: /* get the next field in the attribute value (a number followed
3251: by a unit) */
3252: ptr = TtaSkipBlanks (ptr);
3253: if (*ptr != EOS)
3254: {
3255: ptr = ParseCSSUnit (ptr, &pval);
3256: if (pval.typed_data.unit != UNIT_INVALID)
3257: {
3258: if (pval.typed_data.unit == UNIT_BOX)
3259: pval.typed_data.unit = UNIT_EM;
3260: /* if the value is an integer, make it a real to avoid
3261: errors in dividing small integers, such as "1cm" */
3262: if (!pval.typed_data.real)
3263: {
3264: pval.typed_data.value *= 1000;
3265: pval.typed_data.real = TRUE;
3266: }
3267: val = pval.typed_data.value / 2;
3268: }
3269: else
3270: val = pval.typed_data.value;
3271: }
3272: }
3273: }
1.167 quint 3274:
3275: /* initialize the padding to be set at the top and at the bottom
1.210 gully 3276: of each cell */
1.167 quint 3277: /* the top padding of a row is the same as the bottom padding of the
1.210 gully 3278: previous row */
1.167 quint 3279: topVal = bottomVal;
3280: topValUnit = bottomValUnit;
3281: if (!nextRow)
1.210 gully 3282: /* row is the last in the table. It must not have any padding
3283: at the bottom */
3284: bottomVal = 0;
1.167 quint 3285: else
1.210 gully 3286: {
3287: bottomVal = val;
3288: bottomValUnit = pval.typed_data.unit;
3289: }
1.167 quint 3290:
3291: /* get the first cell of that row (ignoring Label cells) */
3292: elType.ElTypeNum = MathML_EL_MTD;
3293: cell = TtaSearchTypedElement (elType, SearchInTree, row);
3294: /* update attribute MLineBelowtop padding and bottom padding for all
1.210 gully 3295: cells in that row */
1.167 quint 3296: while (cell)
1.210 gully 3297: {
3298: cellType = TtaGetElementType (cell);
3299: /* skip comments and other non mtd elements */
3300: if (cellType.ElTypeNum == MathML_EL_MTD &&
3301: !strcmp (TtaGetSSchemaName (cellType.ElSSchema), "MathML"))
3302: /* that's a mtd element. Process it */
3303: {
3304: /* by default, use the value for the current row */
3305: cellBottomVal = bottomVal;
3306: if (!delete_ && value)
3307: /* take row spanning into account */
3308: {
3309: /* is there a rowspan attribute on that cell? */
3310: rowspanAttr = TtaGetAttribute (cell, rowspanType);
3311: if (!rowspanAttr)
3312: rowspan = 1;
3313: else
3314: rowspan = TtaGetAttributeValue (rowspanAttr);
3315: if (!delete_)
3316: {
3317: /* skip rowspan-1 words in the value of attribute
3318: rowlines */
3319: if (rowspan > 1)
3320: {
3321: spanPtr = ptr;
3322: for (i = 1; i < rowspan && *spanPtr != EOS; i++)
3323: {
3324: spanPtr = TtaSkipBlanks (spanPtr);
3325: spanPtr = ParseCSSUnit (spanPtr, &pval);
3326: }
3327: if (pval.typed_data.unit == UNIT_INVALID)
3328: {
3329: val = 0;
3330: cellBottomVal = 0;
3331: bottomValUnit = UNIT_PT;
3332: }
3333: else
3334: {
3335: if (pval.typed_data.unit == UNIT_BOX)
3336: pval.typed_data.unit = UNIT_EM;
3337: /* if the value is an integer, make it a real to
3338: avoid errors in dividing small integers,
3339: such as "1cm" */
3340: if (!pval.typed_data.real)
3341: {
3342: pval.typed_data.value *= 1000;
3343: pval.typed_data.real = TRUE;
3344: }
3345: val = pval.typed_data.value / 2;
3346: cellBottomVal = val;
3347: bottomValUnit = pval.typed_data.unit;
3348: }
3349: }
3350: }
3351: }
3352:
3353: if ((delete_ || !value) && !firstRow)
3354: ctxt->destroy = TRUE;
3355: else
3356: {
3357: pval.typed_data.value = topVal;
3358: pval.typed_data.unit = topValUnit;
3359: ctxt->destroy = FALSE;
3360: }
3361: TtaSetStylePresentation (PRPaddingTop, cell, NULL, ctxt, pval);
3362: if ((delete_ || !value) && nextRow)
3363: ctxt->destroy = TRUE;
3364: else
3365: {
3366: pval.typed_data.value = cellBottomVal;
3367: pval.typed_data.unit = bottomValUnit;
3368: ctxt->destroy = FALSE;
3369: }
3370: TtaSetStylePresentation (PRPaddingBottom, cell, NULL, ctxt,pval);
3371: }
3372: TtaNextSibling (&cell);
3373: }
1.167 quint 3374: row = nextRow;
3375: firstRow = FALSE;
3376: }
3377:
3378: TtaFreeMemory (ctxt);
3379: if (value)
3380: TtaFreeMemory (value);
3381: }
3382:
3383: /*----------------------------------------------------------------------
3384: ConvertNamedSpace
3385: if name is the name of a space, return the value of this space
3386: in value, otherwise return an empty string in value.
1.210 gully 3387: -----------------------------------------------------------------------*/
1.167 quint 3388: static char* ConvertNamedSpace (char *name, char *value)
1.210 gully 3389: {
3390: if (strcmp (name, "veryverythinmathspace") == 0)
3391: {
3392: strcpy (value, "0.0555556em");
3393: return (name + strlen("veryverythinmathspace"));
3394: }
3395: else if (strcmp (name, "verythinmathspace") == 0)
3396: {
3397: strcpy (value, "0.111111em");
3398: return (name + strlen("verythinmathspace"));
3399: }
3400: else if (strcmp (name, "thinmathspace") == 0)
3401: {
3402: strcpy (value, "0.166667em");
3403: return (name + strlen("thinmathspace"));
3404: }
3405: else if (strcmp (name, "mediummathspace") == 0)
3406: {
3407: strcpy (value, "0.222222em");
3408: return (name + strlen("mediummathspace"));
3409: }
3410: else if (strcmp (name, "thickmathspace") == 0)
3411: {
3412: strcpy (value, "0.277778em");
3413: return (name + strlen("thickmathspace"));
3414: }
3415: else if (strcmp (name, "verythickmathspace") == 0)
3416: {
3417: strcpy (value, "0.333333em");
3418: return (name + strlen("verythickmathspace"));
3419: }
3420: else if (strcmp (name, "veryverythickmathspace") == 0)
3421: {
3422: strcpy (value, "0.388889em");
3423: return (name + strlen("veryverythickmathspace"));
3424: }
3425: else
3426: {
3427: value[0] = EOS;
3428: return name;
3429: }
3430: }
1.167 quint 3431:
3432: /*----------------------------------------------------------------------
1.210 gully 3433: HandleColumnspacingAttribute
3434: An attribute columnspacing has been created, updated or deleted (if delete
3435: is TRUE) for element el in document doc. Update the left and right padding
3436: of all cells accordingly.
1.167 quint 3437: ----------------------------------------------------------------------*/
3438: void HandleColumnspacingAttribute (Attribute attr, Element el, Document doc,
1.210 gully 3439: ThotBool delete_)
1.167 quint 3440: {
3441: ElementType elType;
3442: int length, val, valUnit, leftVal, leftValUnit,
1.210 gully 3443: rightVal, rightValUnit, colspan, i;
1.167 quint 3444: char *value, *ptr, valueOfNamedSpace[20];
3445: PresentationValue pval;
3446: PresentationContext ctxt;
3447: Element row, cell, nextCell;
3448: ThotBool stop, firstCell;
1.168 quint 3449: Attribute spanAttr;
1.167 quint 3450: AttributeType colspanType;
3451:
3452: elType = TtaGetElementType (el);
3453: if (elType.ElTypeNum != MathML_EL_MTABLE ||
3454: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML"))
3455: /* ignore columnspacing attribute on mstyle elements */
3456: /* process it only on mtable elements */
3457: return;
3458:
3459: value = NULL;
1.193 gully 3460: if (!delete_ && attr)
1.167 quint 3461: {
3462: length = TtaGetTextAttributeLength (attr);
3463: if (length > 0)
1.210 gully 3464: {
3465: value = (char *)TtaGetMemory (length+1);
3466: value[0] = EOS;
3467: TtaGiveTextAttributeValue (attr, value, &length);
3468: }
1.167 quint 3469: }
3470:
3471: ctxt = TtaGetSpecificStyleContext (doc);
3472: /* the specific presentation to be created is not a CSS rule */
3473: ctxt->cssSpecificity = 0;
3474: val = 0;
3475: colspanType.AttrSSchema = elType.ElSSchema;
3476: colspanType.AttrTypeNum = MathML_ATTR_columnspan;
3477:
3478: /* check all cells in all rows within the table */
3479: elType.ElTypeNum = MathML_EL_TableRow;
3480: row = TtaSearchTypedElement (elType, SearchInTree, el);
3481: while (row)
3482: {
3483: elType = TtaGetElementType (row);
3484: if ((elType.ElTypeNum == MathML_EL_MTR ||
1.210 gully 3485: elType.ElTypeNum == MathML_EL_MLABELEDTR) &&
3486: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML") == 0)
3487: /* that's a table row. check all its cells */
3488: {
3489: firstCell = TRUE;
3490: rightVal = 0;
1.167 quint 3491: val = 0;
1.210 gully 3492: valUnit = UNIT_PT;
3493: ptr = value;
3494: /* get the first cell of that row (ignoring Label cells) */
3495: elType.ElTypeNum = MathML_EL_MTD;
3496: cell = TtaSearchTypedElement (elType, SearchInTree, row);
3497: while (cell)
3498: {
3499: /* prepare the value of the padding to be associated with the
3500: cells */
3501: if (delete_)
3502: /* remove the presentation rules */
3503: {
3504: pval.typed_data.value = 0;
3505: val = 0;
3506: valUnit = UNIT_PT;
3507: }
3508: else
3509: {
3510: if (!value)
3511: {
3512: pval.typed_data.unit = UNIT_PT;
3513: pval.typed_data.value = 0;
3514: pval.typed_data.real = FALSE;
3515: val = 0;
3516: valUnit = UNIT_PT;
3517: }
3518: else
3519: {
3520: /* parse the next field in the attribute value (a number
3521: followed by a unit or a named space) */
3522: ptr = TtaSkipBlanks (ptr);
3523: if (*ptr != EOS)
3524: {
3525: /* is there a columnspan attribute on that cell? */
3526: spanAttr = TtaGetAttribute (cell, colspanType);
3527: if (!spanAttr)
3528: colspan = 1;
3529: else
3530: colspan = TtaGetAttributeValue (spanAttr);
3531: /* skip (colspan - 1) words in the attribute */
3532: for (i = 1; i <= colspan && *ptr != EOS; i++)
3533: {
3534: ptr = TtaSkipBlanks (ptr);
3535: ptr = ConvertNamedSpace (ptr, valueOfNamedSpace);
3536: if (valueOfNamedSpace[0] != EOS)
3537: /* it's a named space */
3538: ptr = ParseCSSUnit (valueOfNamedSpace, &pval);
3539: else
3540: ptr = ParseCSSUnit (ptr, &pval);
3541: if (pval.typed_data.unit == UNIT_INVALID)
3542: {
3543: val = 0;
3544: valUnit = UNIT_PT;
3545: }
3546: else
3547: {
3548: if (pval.typed_data.unit == UNIT_BOX)
3549: pval.typed_data.unit = UNIT_EM;
3550: /* if the value is an integer, make it a real
3551: to avoid errors in dividing small
3552: integers, such as "1cm" */
3553: if (!pval.typed_data.real)
3554: {
3555: pval.typed_data.value *= 1000;
3556: pval.typed_data.real = TRUE;
3557: }
3558: val = pval.typed_data.value / 2;
3559: valUnit = pval.typed_data.unit;
3560: }
3561: }
3562: }
3563: }
3564: }
3565:
3566: /* get the next cell in the current row to check if the current
3567: cell is the last one in the row */
3568: nextCell = cell;
3569: stop = FALSE;
3570: do
3571: {
3572: TtaNextSibling (&nextCell);
3573: if (!nextCell)
3574: stop = TRUE;
3575: else
3576: {
3577: elType = TtaGetElementType (nextCell);
3578: /* skip comments and other non mtd elements */
3579: if (elType.ElTypeNum == MathML_EL_MTD &&
3580: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML") == 0)
3581: /* it's the next cell */
3582: stop = TRUE;
3583: }
3584: }
3585: while (!stop);
3586:
3587: /* initialize the padding to be set at the right and at the left
3588: of each cell */
3589: /* the leftPadding of a cell is the same as the right padding
3590: of the previous cell */
3591: leftVal = rightVal;
3592: leftValUnit = rightValUnit = valUnit;
3593: if (!nextCell)
3594: /* it's the last cell in the row. It must not have any
3595: padding on the right */
3596: {
3597: rightVal = 0;
3598: rightValUnit = UNIT_PT;
3599: }
3600: else
3601: {
3602: rightVal = val;
3603: rightValUnit = valUnit;
3604: }
3605:
3606: /* set the left and right padding for this cell */
3607: if ((delete_ || !value) && !firstCell)
3608: ctxt->destroy = TRUE;
3609: else
3610: {
3611: pval.typed_data.value = leftVal;
3612: pval.typed_data.unit = leftValUnit;
3613: ctxt->destroy = FALSE;
3614: }
3615: TtaSetStylePresentation (PRPaddingLeft, cell, NULL, ctxt, pval);
3616: if ((delete_ || !value) && nextCell)
3617: ctxt->destroy = TRUE;
3618: else
3619: {
3620: pval.typed_data.value = rightVal;
3621: pval.typed_data.unit = rightValUnit;
3622: ctxt->destroy = FALSE;
3623: }
3624: TtaSetStylePresentation (PRPaddingRight, cell, NULL, ctxt, pval);
3625: cell = nextCell;
3626: firstCell = FALSE;
3627: }
3628: }
1.167 quint 3629: TtaNextSibling (&row);
3630: }
1.203 vatton 3631: TtaFreeMemory (ctxt);
1.167 quint 3632: if (value)
3633: TtaFreeMemory (value);
3634: }
3635:
3636: /*----------------------------------------------------------------------
1.210 gully 3637: HandleRowlinesAttribute
3638: An attribute rowlines has been created, updated or deleted (if delete
3639: is TRUE) for element el in document doc. Update attribute MLineBelow
3640: of all cells accordingly.
1.159 quint 3641: ----------------------------------------------------------------------*/
3642: void HandleRowlinesAttribute (Attribute attr, Element el, Document doc,
1.210 gully 3643: ThotBool delete_)
1.159 quint 3644: {
3645: char *value;
1.160 quint 3646: char *ptr, *spanPtr;
3647: int length, val, rowspan, i, cellVal;
1.159 quint 3648: ElementType elType, rowType, cellType;
3649: Element row, nextRow, cell;
3650: ThotBool stop;
1.160 quint 3651: AttributeType attrType, rowspanType;
3652: Attribute intAttr, rowspanAttr;
1.159 quint 3653:
3654: elType = TtaGetElementType (el);
3655: if (elType.ElTypeNum != MathML_EL_MTABLE ||
3656: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML"))
3657: /* ignore rowlines attribute on mstyle elements */
3658: /* process it only on mtable elements */
3659: return;
3660:
3661: value = NULL;
1.193 gully 3662: if (!delete_)
1.159 quint 3663: {
3664: length = TtaGetTextAttributeLength (attr);
3665: if (length > 0)
1.210 gully 3666: {
3667: value = (char *)TtaGetMemory (length+1);
3668: value[0] = EOS;
3669: TtaGiveTextAttributeValue (attr, value, &length);
3670: }
1.159 quint 3671: }
3672: /* if attribute rowlines is created or updated but has no value, don't
3673: do anything */
1.193 gully 3674: if (!delete_ && !value)
1.159 quint 3675: return;
3676:
3677: ptr = value;
3678: val = 0;
3679: attrType.AttrSSchema = elType.ElSSchema;
1.160 quint 3680: rowspanType.AttrSSchema = elType.ElSSchema;
3681: rowspanType.AttrTypeNum = MathML_ATTR_rowspan_;
1.159 quint 3682:
3683: /* check all rows within the table */
3684: elType.ElTypeNum = MathML_EL_TableRow;
3685: row = TtaSearchTypedElement (elType, SearchInTree, el);
3686: while (row)
3687: {
3688: /* get the next row to check if the current row is the last one */
3689: nextRow = row;
3690: stop = FALSE;
3691: do
1.210 gully 3692: {
3693: TtaNextSibling (&nextRow);
3694: if (!nextRow)
3695: stop = TRUE;
3696: else
3697: {
3698: rowType = TtaGetElementType (nextRow);
3699: /* skip comments and other non mrow elements */
3700: if ((rowType.ElTypeNum == MathML_EL_MTR ||
3701: rowType.ElTypeNum == MathML_EL_MLABELEDTR) &&
3702: !strcmp (TtaGetSSchemaName (rowType.ElSSchema), "MathML"))
3703: /* it's the next mrow */
3704: stop = TRUE;
3705: }
3706: }
1.159 quint 3707: while (!stop);
3708:
3709: if (!nextRow)
1.210 gully 3710: /* row is the last in the table. It must not have a line
3711: at the bottom. Delete it if there is one */
3712: val = 0;
1.159 quint 3713: else
1.210 gully 3714: {
3715: if (delete_)
3716: val = 0;
3717: else
3718: if (*ptr != EOS)
3719: {
3720: /* get next word in the attribute value */
3721: ptr = TtaSkipBlanks (ptr);
3722: /* process that word */
3723: if (*ptr != EOS && *ptr != ' ')
3724: {
3725: if (!strncasecmp (ptr, "none", 4))
3726: val = 0;
3727: else if (!strncasecmp (ptr, "solid", 5))
3728: val = MathML_ATTR_MLineBelow_VAL_solid_;
3729: else if (!strncasecmp (ptr, "dashed", 6))
3730: val = MathML_ATTR_MLineBelow_VAL_dashed_;
3731: else
3732: val = 0;
3733: /* skip the word that has been processed */
3734: while (*ptr != EOS && *ptr != ' ')
3735: ptr++;
3736: }
3737: }
3738: }
1.159 quint 3739: /* get the first cell of that row (ignoring Label cells) */
3740: elType.ElTypeNum = MathML_EL_MTD;
3741: cell = TtaSearchTypedElement (elType, SearchInTree, row);
3742: /* update attribute MLineBelow for all cells in that row */
3743: while (cell)
1.210 gully 3744: {
3745: cellType = TtaGetElementType (cell);
3746: /* skip comments and other non mtd elements */
3747: if (cellType.ElTypeNum == MathML_EL_MTD &&
3748: !strcmp (TtaGetSSchemaName (cellType.ElSSchema), "MathML"))
3749: /* that's a mtd element. Process it */
3750: {
3751: /* is there a rowspan attribute on that cell? */
3752: rowspanAttr = TtaGetAttribute (cell, rowspanType);
3753: if (!rowspanAttr)
3754: rowspan = 1;
3755: else
3756: rowspan = TtaGetAttributeValue (rowspanAttr);
3757: /* by default, use the value for the current row */
3758: cellVal = val;
3759: if (!delete_)
3760: {
3761: /* skip rowspan-1 words in the value of attribute rowlines */
3762: if (rowspan > 1)
3763: {
3764: spanPtr = ptr;
3765: for (i = 1; i < rowspan && *spanPtr != EOS; i++)
3766: {
3767: spanPtr = TtaSkipBlanks (spanPtr);
3768: if (*spanPtr != EOS && *spanPtr != ' ')
3769: {
3770: if (!strncasecmp (spanPtr, "none", 4))
3771: cellVal = 0;
3772: else if (!strncasecmp (spanPtr, "solid", 5))
3773: cellVal = MathML_ATTR_MLineBelow_VAL_solid_;
3774: else if (!strncasecmp (spanPtr, "dashed", 6))
3775: cellVal = MathML_ATTR_MLineBelow_VAL_dashed_;
3776: else
3777: cellVal = 0;
3778: }
3779: /* skip the word that has been processed */
3780: while (*spanPtr != EOS && *spanPtr != ' ')
3781: spanPtr++;
3782: }
3783: }
3784: }
3785: if (rowspan == 1)
3786: attrType.AttrTypeNum = MathML_ATTR_MLineBelow;
3787: else
3788: attrType.AttrTypeNum = MathML_ATTR_MLineBelowExt;
3789: intAttr = TtaGetAttribute (cell, attrType);
3790: if (cellVal == 0)
3791: {
3792: if (intAttr)
3793: /* remove attribute MLineBelow */
3794: TtaRemoveAttribute (cell, intAttr, doc);
3795: }
3796: else
3797: /* set attribute MLineBelow */
3798: {
3799: if (!intAttr)
3800: {
3801: intAttr = TtaNewAttribute (attrType);
3802: TtaAttachAttribute (cell, intAttr, doc);
3803: }
3804: TtaSetAttributeValue (intAttr, cellVal, cell, doc);
3805: }
3806: }
3807: TtaNextSibling (&cell);
3808: }
1.159 quint 3809: row = nextRow;
3810: }
3811: if (value)
3812: TtaFreeMemory (value);
3813: }
3814:
3815: /*----------------------------------------------------------------------
1.210 gully 3816: HandleColumnlinesAttribute
3817: An attribute columnlines has been created, updated or deleted (if delete
3818: is TRUE) for element el in document doc. Update attribute MLineOnTheRight
3819: of all cells accordingly.
1.159 quint 3820: ----------------------------------------------------------------------*/
3821: void HandleColumnlinesAttribute (Attribute attr, Element el, Document doc,
1.210 gully 3822: ThotBool delete_)
1.159 quint 3823: {
3824: char *value;
3825: char *ptr;
1.161 quint 3826: int length, val, colspan, rowspan, i;
1.159 quint 3827: ElementType elType;
3828: Element row, cell, nextCell;
3829: ThotBool stop;
1.161 quint 3830: AttributeType attrType, colspanType, rowspanType;
3831: Attribute intAttr, spanAttr;
1.159 quint 3832:
3833: elType = TtaGetElementType (el);
3834: if (elType.ElTypeNum != MathML_EL_MTABLE ||
3835: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML"))
3836: /* ignore rowlines attribute on mstyle elements */
3837: /* process it only on mtable elements */
3838: return;
3839:
3840: value = NULL;
1.193 gully 3841: if (!delete_)
1.159 quint 3842: {
3843: length = TtaGetTextAttributeLength (attr);
3844: if (length > 0)
1.210 gully 3845: {
3846: value = (char *)TtaGetMemory (length+1);
3847: value[0] = EOS;
3848: TtaGiveTextAttributeValue (attr, value, &length);
3849: }
1.159 quint 3850: }
3851: /* if attribute columnlines is created or updated but has no value, don't
3852: do anything */
1.193 gully 3853: if (!delete_ && !value)
1.159 quint 3854: return;
3855:
3856: val = 0;
3857: attrType.AttrSSchema = elType.ElSSchema;
1.160 quint 3858: colspanType.AttrSSchema = elType.ElSSchema;
3859: colspanType.AttrTypeNum = MathML_ATTR_columnspan;
1.161 quint 3860: rowspanType.AttrSSchema = elType.ElSSchema;
3861: rowspanType.AttrTypeNum = MathML_ATTR_rowspan_;
1.159 quint 3862:
3863: /* check all cells in all rows in the table */
3864: elType.ElTypeNum = MathML_EL_TableRow;
3865: row = TtaSearchTypedElement (elType, SearchInTree, el);
3866: while (row)
3867: {
3868: elType = TtaGetElementType (row);
3869: if ((elType.ElTypeNum == MathML_EL_MTR ||
1.210 gully 3870: elType.ElTypeNum == MathML_EL_MLABELEDTR) &&
3871: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML") == 0)
3872: /* that's a table row. check all its cells */
3873: {
3874: /* start from the beginning of the columnlines attribute */
3875: ptr = value;
3876: val = 0;
3877: /* get the first cell of that row (ignoring Label cells) */
3878: elType.ElTypeNum = MathML_EL_MTD;
3879: cell = TtaSearchTypedElement (elType, SearchInTree, row);
3880: while (cell)
3881: {
3882: /* get the next cell in the current row to check if the current
3883: cell is the last one in the row */
3884: nextCell = cell;
3885: stop = FALSE;
3886: do
3887: {
3888: TtaNextSibling (&nextCell);
3889: if (!nextCell)
3890: stop = TRUE;
3891: else
3892: {
3893: elType = TtaGetElementType (nextCell);
3894: /* skip comments and other non mtd elements */
3895: if (elType.ElTypeNum == MathML_EL_MTD &&
3896: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML") == 0)
3897: /* it's the next cell */
3898: stop = TRUE;
3899: }
3900: }
3901: while (!stop);
3902:
3903: /* is there a rowspan attribute on that cell? */
3904: spanAttr = TtaGetAttribute (cell, rowspanType);
3905: if (!spanAttr)
3906: rowspan = 1;
3907: else
3908: rowspan = TtaGetAttributeValue (spanAttr);
3909:
3910: if (!nextCell)
3911: /* it's the last cell in the row. It must not have a line
3912: on its right edge. Delete it if there is noe. */
3913: val = 0;
3914: else
3915: /* set the attribute MLineOnTheRight for this cell */
3916: {
3917: if (delete_)
3918: val = 0;
3919: else
3920: if (*ptr != EOS)
3921: {
3922: /* is there a columnspan attribute on that cell? */
3923: spanAttr = TtaGetAttribute (cell, colspanType);
3924: if (!spanAttr)
3925: colspan = 1;
3926: else
3927: colspan = TtaGetAttributeValue (spanAttr);
3928: /* skip (colspan - 1) words in the attribute */
3929: for (i = 1; i <= colspan && *ptr != EOS; i++)
3930: {
3931: /* get next word in the attribute value */
3932: ptr = TtaSkipBlanks (ptr);
3933: /* process that word */
3934: if (*ptr != EOS && *ptr != ' ')
3935: {
3936: if (!strncasecmp (ptr, "none", 4))
3937: val = 0;
3938: else if (!strncasecmp (ptr, "solid", 5))
3939: val = MathML_ATTR_MLineOnTheRight_VAL_solid_;
3940: else if (!strncasecmp (ptr, "dashed", 6))
3941: val = MathML_ATTR_MLineOnTheRight_VAL_dashed_;
3942: else
3943: val = 0;
3944: /* skip the word that has been processed */
3945: while (*ptr != EOS && *ptr != ' ')
3946: ptr++;
3947: }
3948: }
3949: }
3950: }
3951: if (rowspan == 1)
3952: attrType.AttrTypeNum = MathML_ATTR_MLineOnTheRight;
3953: else
3954: attrType.AttrTypeNum = MathML_ATTR_MLineOnTheRightExt;
3955: intAttr = TtaGetAttribute (cell, attrType);
3956: if (val == 0)
3957: {
3958: if (intAttr)
3959: /* remove attribute MLineOnTheRight */
3960: TtaRemoveAttribute (cell, intAttr, doc);
3961: }
3962: else
3963: /* set attribute MLineOnTheRight */
3964: {
3965: if (!intAttr)
3966: {
3967: intAttr = TtaNewAttribute (attrType);
3968: TtaAttachAttribute (cell, intAttr, doc);
3969: }
3970: TtaSetAttributeValue (intAttr, val, cell, doc);
3971: }
3972: cell = nextCell;
3973: }
3974: }
1.159 quint 3975: TtaNextSibling (&row);
3976: }
3977: if (value)
3978: TtaFreeMemory (value);
3979: }
3980:
3981: /*----------------------------------------------------------------------
1.210 gully 3982: HandleFramespacingAttribute
3983: An attribute framespacing has been created, updated or deleted (if delete
3984: is TRUE) for element el in document doc. Update attribute the padding
3985: properties of the concerned table(s).
1.168 quint 3986: ----------------------------------------------------------------------*/
3987: void HandleFramespacingAttribute (Attribute attr, Element el, Document doc,
1.210 gully 3988: ThotBool delete_)
1.168 quint 3989: {
3990: ElementType elType;
3991: char *value, *ptr, valueOfNamedSpace[20];
3992: int length, vertPadding, horizPadding, vertPaddingUnit,
1.210 gully 3993: horizPaddingUnit;
1.168 quint 3994: Attribute attrFrame;
3995: AttributeType attrType;
3996: PresentationValue pval;
3997: PresentationContext ctxt;
3998: ThotBool vertPaddingReal, horizPaddingReal;
3999:
1.193 gully 4000: if ((!delete_ && !attr) || !el)
1.168 quint 4001: return;
4002: elType = TtaGetElementType (el);
4003: if (elType.ElTypeNum != MathML_EL_MTABLE ||
4004: strcmp (TtaGetSSchemaName (elType.ElSSchema), "MathML"))
4005: /* ignore framespacing attribute on mstyle elements */
4006: /* process it only on mtable elements */
4007: return;
4008:
4009: value = NULL;
1.193 gully 4010: if (!delete_)
1.168 quint 4011: {
4012: length = TtaGetTextAttributeLength (attr);
4013: if (length > 0)
1.210 gully 4014: {
4015: value = (char *)TtaGetMemory (length+1);
4016: value[0] = EOS;
4017: TtaGiveTextAttributeValue (attr, value, &length);
4018: }
1.168 quint 4019: }
4020: ctxt = TtaGetSpecificStyleContext (doc);
4021: /* the specific presentation to be created is not a CSS rule */
4022: ctxt->cssSpecificity = 0;
4023: vertPadding = 0;
4024: horizPadding = 0;
1.184 vatton 4025: vertPaddingUnit = UNIT_PT;
4026: horizPaddingUnit = UNIT_PT;
1.168 quint 4027: vertPaddingReal = FALSE;
4028: horizPaddingReal = FALSE;
4029: /* is there a frame attribute? */
4030: attrType.AttrSSchema = elType.ElSSchema;
4031: attrType.AttrTypeNum = MathML_ATTR_frame;
4032: attrFrame = TtaGetAttribute (el, attrType);
1.193 gully 4033: if (!delete_ && value && attrFrame)
1.168 quint 4034: {
4035: ptr = value;
4036: /* parse the first part: horizontal spacing */
4037: ptr = TtaSkipBlanks (ptr);
4038: if (*ptr != EOS)
1.210 gully 4039: {
4040: ptr = ConvertNamedSpace (ptr, valueOfNamedSpace);
4041: if (valueOfNamedSpace[0] != EOS)
4042: /* it's a named space */
4043: ptr = ParseCSSUnit (valueOfNamedSpace, &pval);
4044: else
4045: ptr = ParseCSSUnit (ptr, &pval);
4046: if (pval.typed_data.unit != UNIT_INVALID)
4047: {
4048: if (pval.typed_data.unit == UNIT_BOX)
4049: pval.typed_data.unit = UNIT_EM;
4050: horizPadding = pval.typed_data.value;
4051: horizPaddingUnit = pval.typed_data.unit;
4052: horizPaddingReal = pval.typed_data.real;
4053: /* if there is no second part, the vertical spacing is the same
4054: as the horizontal spacing */
4055: vertPadding = horizPadding;
4056: vertPaddingUnit = horizPaddingUnit;
4057: vertPaddingReal = horizPaddingReal;
4058: /* parse the second part, if any */
4059: ptr = TtaSkipBlanks (ptr);
4060: if (*ptr != EOS)
4061: {
4062: ptr = ConvertNamedSpace (ptr, valueOfNamedSpace);
4063: if (valueOfNamedSpace[0] != EOS)
4064: /* it's a named space */
4065: ptr = ParseCSSUnit (valueOfNamedSpace, &pval);
4066: else
4067: ptr = ParseCSSUnit (ptr, &pval);
4068: if (pval.typed_data.unit != UNIT_INVALID)
4069: {
4070: if (pval.typed_data.unit == UNIT_BOX)
4071: pval.typed_data.unit = UNIT_EM;
4072: vertPadding = pval.typed_data.value;
4073: vertPaddingUnit = pval.typed_data.unit;
4074: vertPaddingReal = pval.typed_data.real;
4075: }
4076: }
4077: }
4078: }
1.168 quint 4079: }
1.193 gully 4080: if (delete_)
1.168 quint 4081: ctxt->destroy = TRUE;
4082: else
4083: {
4084: ctxt->destroy = FALSE;
4085: pval.typed_data.value = horizPadding;
4086: pval.typed_data.unit = horizPaddingUnit;
4087: pval.typed_data.real = horizPaddingReal;
4088: }
4089: TtaSetStylePresentation (PRPaddingLeft, el, NULL, ctxt, pval);
4090: TtaSetStylePresentation (PRPaddingRight, el, NULL, ctxt, pval);
1.193 gully 4091: if (!delete_)
1.168 quint 4092: {
4093: pval.typed_data.value = vertPadding;
4094: pval.typed_data.unit = vertPaddingUnit;
4095: pval.typed_data.real = vertPaddingReal;
4096: }
4097: TtaSetStylePresentation (PRPaddingTop, el, NULL, ctxt, pval);
4098: TtaSetStylePresentation (PRPaddingBottom, el, NULL, ctxt, pval);
4099:
4100: if (value)
4101: TtaFreeMemory (value);
1.175 quint 4102: }
4103:
4104: /*----------------------------------------------------------------------
1.210 gully 4105: SetDisplaystyleMathElement
4106: Associate a IntDisplaystyle attribute with element el (which is a
4107: <math> element), and set its value depending on the surrounding context.
1.169 quint 4108: ----------------------------------------------------------------------*/
4109: void SetDisplaystyleMathElement (Element el, Document doc)
4110: {
4111: Element parent, sibling;
4112: ElementType elType, parentType;
4113: Attribute attr;
4114: AttributeType attrType;
4115: int display, val;
4116:
4117: display = MathML_ATTR_IntDisplaystyle_VAL_true;
4118: /* is there an attribute display? */
4119: elType = TtaGetElementType (el);
4120: attrType.AttrSSchema = elType.ElSSchema;
1.197 quint 4121: attrType.AttrTypeNum = MathML_ATTR_display_;
1.169 quint 4122: attr = TtaGetAttribute (el, attrType);
4123: if (attr)
4124: /* there is an attribute display. Take its value */
4125: {
4126: val = TtaGetAttributeValue (attr);
1.197 quint 4127: if (val == MathML_ATTR_display__VAL_block_)
1.210 gully 4128: display = MathML_ATTR_IntDisplaystyle_VAL_true;
1.169 quint 4129: else
1.210 gully 4130: display = MathML_ATTR_IntDisplaystyle_VAL_false;
1.169 quint 4131: }
4132: else
4133: /* no attribute display. Look at the context */
4134: {
4135: parent = TtaGetParent (el);
4136: parentType = TtaGetElementType (parent);
4137: if (elType.ElSSchema == parentType.ElSSchema)
1.210 gully 4138: /* it's the only <math> element in a MathML document */
4139: display = MathML_ATTR_IntDisplaystyle_VAL_true;
1.169 quint 4140: else
1.210 gully 4141: /* it's a MathML expression within another vocabulary */
4142: {
4143: if (!strcmp (TtaGetSSchemaName (parentType.ElSSchema), "SVG"))
4144: /* a <math> element in a SVG element */
4145: display = MathML_ATTR_IntDisplaystyle_VAL_true;
4146: else if (!strcmp (TtaGetSSchemaName (parentType.ElSSchema), "HTML"))
4147: /* a <math> element in a HTML element */
4148: {
4149: display = MathML_ATTR_IntDisplaystyle_VAL_false;
4150: if (parentType.ElTypeNum == HTML_EL_BODY ||
4151: parentType.ElTypeNum == HTML_EL_Division)
4152: /* the <math> element is a child of a <body> or <div> */
4153: display = MathML_ATTR_IntDisplaystyle_VAL_true;
4154: else if (parentType.ElTypeNum == HTML_EL_Pseudo_paragraph ||
4155: parentType.ElTypeNum == HTML_EL_Paragraph)
4156: /* the <math> element is a child of a <p> or equivalent */
4157: {
4158: sibling = el;
4159: TtaPreviousSibling (&sibling);
4160: if (!sibling)
4161: {
4162: sibling = el;
4163: TtaNextSibling (&sibling);
4164: if (!sibling)
4165: /* the <math> element is alone in its paragraph */
4166: display = MathML_ATTR_IntDisplaystyle_VAL_true;
4167: }
4168: }
4169: }
4170: }
1.169 quint 4171: }
4172: /* create the IntDisplastyle attribute and set its value */
4173: attrType.AttrTypeNum = MathML_ATTR_IntDisplaystyle;
4174: attr = TtaGetAttribute (el, attrType);
4175: if (!attr)
4176: {
4177: attr = TtaNewAttribute (attrType);
4178: TtaAttachAttribute (el, attr, doc);
4179: }
4180: TtaSetAttributeValue (attr, display, el, doc);
1.175 quint 4181: ApplyDisplaystyle (el, doc);
1.169 quint 4182: }
4183:
4184: /*----------------------------------------------------------------------
1.210 gully 4185: MathMLElementCreated
4186: The XML parser has just inserted a new element in the abstract tree.
1.169 quint 4187: ----------------------------------------------------------------------*/
4188: void MathMLElementCreated (Element el, Document doc)
4189: {
4190: ElementType elType;
4191:
4192: elType = TtaGetElementType (el);
4193: if (elType.ElTypeNum == MathML_EL_MathML)
4194: /* associate a IntDisplaystyle attribute with the element depending
4195: on its context */
4196: SetDisplaystyleMathElement (el, doc);
4197: }
4198:
4199: /*----------------------------------------------------------------------
1.186 vatton 4200: EvaluateChildRendering tests what children should be displayed
4201: ----------------------------------------------------------------------*/
4202: void EvaluateChildRendering (Element el, Document doc)
4203: {
4204: ElementType elType;
4205: Element child, renderedChild;
1.187 vatton 4206: SSchema MathMLSSchema;
4207: AttributeType attrType;
4208: Attribute attr;
1.186 vatton 4209: PresentationValue pval;
4210: PresentationContext ctxt;
1.187 vatton 4211: char *value;
4212: int length;
1.186 vatton 4213:
4214: ctxt = TtaGetSpecificStyleContext (doc);
4215: ctxt->cssSpecificity = 0; /* the presentation rule to be set is not a CSS rule */
4216: pval.typed_data.unit = UNIT_PX;
4217: pval.typed_data.value = 0;
4218: pval.typed_data.real = FALSE;
1.187 vatton 4219: MathMLSSchema = TtaGetElementType(el).ElSSchema;
1.186 vatton 4220: /* process all children in order */
4221: child = TtaGetFirstChild (el);
4222: renderedChild = NULL;
4223: while (child)
4224: {
4225: /* if this child is a comment or a processing instruction, skip it */
4226: elType = TtaGetElementType (child);
1.187 vatton 4227: ctxt->destroy = FALSE; /* we will most probably create a PRule
1.210 gully 4228: Visibility: 0; for this child */
1.187 vatton 4229: if (elType.ElSSchema == MathMLSSchema &&
1.210 gully 4230: elType.ElTypeNum != MathML_EL_XMLcomment &&
4231: elType.ElTypeNum != MathML_EL_XMLPI &&
4232: elType.ElTypeNum != MathML_EL_Unknown_namespace &&
4233: elType.ElTypeNum != MathML_EL_ANNOTATION)
4234: {
4235: if (!renderedChild && elType.ElTypeNum == MathML_EL_ANNOTATION_XML)
4236: {
4237: /* check if the mime type is known */
4238: attrType.AttrSSchema = MathMLSSchema;
4239: attrType.AttrTypeNum = MathML_ATTR_encoding;
4240: attr = TtaGetAttribute (child, attrType);
4241: if (attr)
4242: {
4243: length = TtaGetTextAttributeLength (attr);
4244: if (length > 0)
4245: {
4246: value = (char *)TtaGetMemory (length+1);
4247: value[0] = EOS;
4248: TtaGiveTextAttributeValue (attr, value, &length);
4249: if (!strncmp (value, "image/svg", 9) ||
4250: !strcmp (value, AM_SVG_MIME_TYPE) ||
4251: !strncmp (value, "text/htm", 8) ||
4252: !strcmp (value, AM_XHTML_MIME_TYPE))
4253: {
4254: /* display that child */
4255: renderedChild = child;
4256: ctxt->destroy = TRUE;
4257: }
4258: }
4259: }
4260: }
4261: /* set or remove a visibility PRule for this child */
4262: TtaSetStylePresentation (PRVisibility, child, NULL, ctxt, pval);
4263: }
1.186 vatton 4264: TtaNextSibling (&child);
4265: }
4266: }
4267:
4268: /*----------------------------------------------------------------------
1.210 gully 4269: MathMLElementComplete
4270: Element el has just been completed by the XML parser.
4271: Check the Thot structure of the MathML element el.
1.1 cvs 4272: ----------------------------------------------------------------------*/
1.156 cvs 4273: void MathMLElementComplete (ParserData *context, Element el, int *error)
1.1 cvs 4274: {
1.210 gully 4275: Document doc;
4276: ElementType elType, parentType;
4277: Element child, parent, new_, prev, next;
4278: AttributeType attrType;
4279: Attribute attr;
4280: SSchema MathMLSSchema;
4281: ThotBool ok;
4282:
4283: ok = TRUE;
4284: *error = 0;
4285: doc = context->doc;
4286: elType = TtaGetElementType (el);
4287: MathMLSSchema = GetMathMLSSchema (doc);
4288:
4289: if (elType.ElSSchema == MathMLSSchema)
4290: {
4291: switch (elType.ElTypeNum)
4292: {
4293: case MathML_EL_MathML:
4294: /* Create placeholders within the MathML element */
4295: CreatePlaceholders (TtaGetFirstChild (el), doc);
4296: break;
4297: case MathML_EL_MTEXT:
4298: if (TtaGetFirstChild (el) == NULL)
4299: /* empty <mtext>. It will have to be parsed when the user enters
4300: some content */
4301: SetAttrParseMe (el, doc);
4302: case MathML_EL_MI:
4303: if (TtaGetFirstChild (el) == NULL)
4304: /* empty <mi> Replace it by an empty Construct */
4305: TtaChangeTypeOfElement (el, doc, MathML_EL_Construct);
4306: else
4307: SetFontstyleAttr (el, doc);
4308: break;
4309: case MathML_EL_MO:
4310: SetIntAddSpaceAttr (el, doc);
4311: SetIntVertStretchAttr (el, doc, 0, NULL);
4312: /* if the MO element is a child of a MROW (or equivalent) and if it
4313: contains a fence character, transform this MO into MF and
4314: transform the fence character into a Thot SYMBOL */
4315: CheckFence (el, doc);
4316: /* if the MO element contains an operator that should be
4317: large (∑ for instance), enlarge it */
4318: CheckLargeOp (el, doc);
4319: break;
4320: case MathML_EL_MSPACE:
4321: break;
4322: case MathML_EL_MROW:
4323: /* Create placeholders within the MROW */
1.55 cvs 4324: CreatePlaceholders (TtaGetFirstChild (el), doc);
1.210 gully 4325: break;
4326: case MathML_EL_MFRAC:
4327: case MathML_EL_BevelledMFRAC:
4328: /* end of a fraction. Create a Numerator and a Denominator */
4329: ok = CheckMathSubExpressions (el, MathML_EL_Numerator,
4330: MathML_EL_Denominator, 0, doc);
4331: break;
4332: case MathML_EL_MSQRT:
4333: /* end of a Square Root */
4334: /* Create placeholders within the element */
1.50 cvs 4335: CreatePlaceholders (TtaGetFirstChild (el), doc);
1.210 gully 4336: /* Create a SqrtBase that contains all children of the MSQRT */
4337: CreateWrapper (el, MathML_EL_SqrtBase, doc);
4338: break;
4339: case MathML_EL_MROOT:
4340: /* end of a Root. Create a RootBase and an Index */
4341: ok = CheckMathSubExpressions (el, MathML_EL_RootBase,
4342: MathML_EL_Index, 0, doc);
4343: break;
4344: case MathML_EL_MENCLOSE:
4345: /* Create placeholders within the element */
1.50 cvs 4346: CreatePlaceholders (TtaGetFirstChild (el), doc);
1.210 gully 4347: break;
4348: case MathML_EL_MSTYLE:
4349: case MathML_EL_MERROR:
4350: case MathML_EL_MPADDED:
4351: case MathML_EL_MPHANTOM:
4352: /* Create placeholders within the element */
1.39 cvs 4353: CreatePlaceholders (TtaGetFirstChild (el), doc);
1.210 gully 4354: break;
4355: case MathML_EL_MFENCED:
4356: TransformMFENCED (el, doc);
4357: break;
4358: case MathML_EL_MSUB:
4359: /* end of a MSUB. Create Base and Subscript */
4360: ok = CheckMathSubExpressions (el, MathML_EL_Base,
4361: MathML_EL_Subscript, 0, doc);
4362: SetScriptShift (el, doc, MathML_ATTR_subscriptshift);
4363: SetIntVertStretchAttr (el, doc, MathML_EL_Base, NULL);
4364: break;
4365: case MathML_EL_MSUP:
4366: /* end of a MSUP. Create Base and Superscript */
4367: ok = CheckMathSubExpressions (el, MathML_EL_Base,
4368: MathML_EL_Superscript, 0, doc);
4369: SetScriptShift (el, doc, MathML_ATTR_superscriptshift);
4370: SetIntVertStretchAttr (el, doc, MathML_EL_Base, NULL);
4371: break;
4372: case MathML_EL_MSUBSUP:
4373: /* end of a MSUBSUP. Create Base, Subscript, and Superscript */
4374: ok = CheckMathSubExpressions (el, MathML_EL_Base,
4375: MathML_EL_Subscript,
4376: MathML_EL_Superscript, doc);
4377: SetScriptShift (el, doc, MathML_ATTR_subscriptshift);
4378: SetScriptShift (el, doc, MathML_ATTR_superscriptshift);
4379: SetIntVertStretchAttr (el, doc, MathML_EL_Base, NULL);
4380: break;
4381: case MathML_EL_MUNDER:
4382: /* end of a MUNDER. Create UnderOverBase, and Underscript */
4383: ok = CheckMathSubExpressions (el, MathML_EL_UnderOverBase,
4384: MathML_EL_Underscript, 0, doc);
4385: SetIntHorizStretchAttr (el, doc);
4386: SetIntVertStretchAttr (el, doc, MathML_EL_UnderOverBase, NULL);
4387: SetIntMovelimitsAttr (el, doc);
4388: break;
4389: case MathML_EL_MOVER:
4390: /* end of a MOVER. Create UnderOverBase, and Overscript */
4391: ok = CheckMathSubExpressions (el, MathML_EL_UnderOverBase,
4392: MathML_EL_Overscript, 0, doc);
4393: SetIntHorizStretchAttr (el, doc);
4394: SetIntVertStretchAttr (el, doc, MathML_EL_UnderOverBase, NULL);
4395: SetIntMovelimitsAttr (el, doc);
4396: break;
4397: case MathML_EL_MUNDEROVER:
4398: /* end of a MUNDEROVER. Create UnderOverBase, Underscript, and
4399: Overscript */
4400: ok = CheckMathSubExpressions (el, MathML_EL_UnderOverBase,
4401: MathML_EL_Underscript,
4402: MathML_EL_Overscript, doc);
4403: SetIntHorizStretchAttr (el, doc);
4404: SetIntVertStretchAttr (el, doc, MathML_EL_UnderOverBase, NULL);
4405: SetIntMovelimitsAttr (el, doc);
4406: break;
4407: case MathML_EL_MMULTISCRIPTS:
4408: /* end of a MMULTISCRIPTS. Create all elements defined in the
4409: MathML S schema */
4410: BuildMultiscript (el, doc);
4411: break;
4412: case MathML_EL_MTABLE:
4413: /* end of a MTABLE. Create all elements defined in the MathML S
1.5 cvs 4414: schema */
1.210 gully 4415: CheckMTable (el, doc, TRUE);
4416: /* if the table has a rowalign attribute, process it */
1.101 cvs 4417: attrType.AttrSSchema = MathMLSSchema;
4418: attrType.AttrTypeNum = MathML_ATTR_rowalign;
1.210 gully 4419: attr = TtaGetAttribute (el, attrType);
4420: if (attr)
4421: HandleRowalignAttribute (attr, el, doc, FALSE);
4422: /* if the table has a columnalign attribute, process it */
1.101 cvs 4423: attrType.AttrTypeNum = MathML_ATTR_columnalign;
1.210 gully 4424: attr = TtaGetAttribute (el, attrType);
4425: if (attr)
4426: HandleColalignAttribute (attr, el, doc, FALSE, FALSE);
4427: /* process the rowspacing attribute, or set the top padding of the
4428: first row and the bottom padding of the last row to 0. */
1.167 quint 4429: attrType.AttrSSchema = MathMLSSchema;
4430: attrType.AttrTypeNum = MathML_ATTR_rowspacing;
1.210 gully 4431: attr = TtaGetAttribute (el, attrType);
4432: HandleRowspacingAttribute (attr, el, doc, FALSE);
4433: /* process the columnspacing attribute, or set the left padding of
4434: the first column and the right padding of the last column to 0 */
1.167 quint 4435: attrType.AttrSSchema = MathMLSSchema;
4436: attrType.AttrTypeNum = MathML_ATTR_columnspacing;
1.210 gully 4437: attr = TtaGetAttribute (el, attrType);
4438: HandleColumnspacingAttribute (attr, el, doc, FALSE);
4439: /* if the table has a rowlines attribute, process it */
1.159 quint 4440: attrType.AttrSSchema = MathMLSSchema;
4441: attrType.AttrTypeNum = MathML_ATTR_rowlines;
1.210 gully 4442: attr = TtaGetAttribute (el, attrType);
4443: if (attr)
4444: HandleRowlinesAttribute (attr, el, doc, FALSE);
4445: /* if the table has a columnlines attribute, process it */
1.159 quint 4446: attrType.AttrTypeNum = MathML_ATTR_columnlines;
1.210 gully 4447: attr = TtaGetAttribute (el, attrType);
4448: if (attr)
4449: HandleColumnlinesAttribute (attr, el, doc, FALSE);
4450: break;
4451: case MathML_EL_MTR:
4452: /* if the row has a columnalign attribute, process it */
1.101 cvs 4453: attrType.AttrSSchema = MathMLSSchema;
4454: attrType.AttrTypeNum = MathML_ATTR_columnalign;
1.210 gully 4455: attr = TtaGetAttribute (el, attrType);
4456: if (attr)
4457: HandleColalignAttribute (attr, el, doc, FALSE, TRUE);
4458: break;
4459: case MathML_EL_MLABELEDTR:
4460: /* if the row has a columnalign attribute, process it */
1.101 cvs 4461: attrType.AttrSSchema = MathMLSSchema;
4462: attrType.AttrTypeNum = MathML_ATTR_columnalign;
1.210 gully 4463: attr = TtaGetAttribute (el, attrType);
4464: if (attr)
4465: HandleColalignAttribute (attr, el, doc, FALSE, TRUE);
4466: break;
4467: case MathML_EL_MTD:
4468: /* Create placeholders within the table cell */
1.39 cvs 4469: CreatePlaceholders (TtaGetFirstChild (el), doc);
1.210 gully 4470: break;
4471: case MathML_EL_MACTION:
4472: /* Create placeholders within the MACTION element */
1.39 cvs 4473: CreatePlaceholders (TtaGetFirstChild (el), doc);
1.210 gully 4474: break;
4475: case MathML_EL_SEMANTICS:
4476: /* it's a ANNOTATION_XML element */
4477: /* Evaluate what direct child element to be rendered */
4478: EvaluateChildRendering (el, doc);
4479: break;
1.213 vatton 4480: case MathML_EL_MGLYPH:
4481: CheckMandatoryAttribute (el, doc, MathML_ATTR_alt);
4482: break;
1.210 gully 4483: default:
4484: break;
4485: }
4486: parent = TtaGetParent (el);
4487: if (parent)
4488: {
4489: parentType = TtaGetElementType (parent);
4490: if (parentType.ElSSchema != elType.ElSSchema)
4491: /* root of a MathML (sub-)tree, Create a MathML element if it is
4492: not present */
4493: if (elType.ElTypeNum != MathML_EL_MathML)
4494: {
4495: elType.ElSSchema = MathMLSSchema;
4496: elType.ElTypeNum = MathML_EL_MathML;
4497: new_ = TtaNewElement (doc, elType);
4498: TtaInsertSibling (new_, el, TRUE, doc);
4499: next = el;
4500: TtaNextSibling (&next);
4501: TtaRemoveTree (el, doc);
4502: TtaInsertFirstChild (&el, new_, doc);
4503: prev = el;
4504: while (next != NULL)
4505: {
4506: child = next;
4507: TtaNextSibling (&next);
4508: TtaRemoveTree (child, doc);
4509: TtaInsertSibling (child, prev, FALSE, doc);
4510: prev = child;
4511: }
4512: /* associate a IntDisplaystyle attribute with the element
4513: depending on its context */
4514: SetDisplaystyleMathElement (new_, doc);
4515: /* Create placeholders within the MathML element */
4516: CreatePlaceholders (new_, doc);
4517: }
4518: }
4519: }
4520: if (!ok)
4521: /* send an error message */
4522: *error = 1;
1.1 cvs 4523: }
4524:
4525: /*----------------------------------------------------------------------
1.210 gully 4526: UnknownMathMLNameSpace
4527: The element doesn't belong to a supported namespace
1.126 cvs 4528: ----------------------------------------------------------------------*/
1.149 cvs 4529: void UnknownMathMLNameSpace (ParserData *context,
1.210 gully 4530: Element *unknownEl,
4531: char* content)
1.126 cvs 4532: {
1.210 gully 4533: ElementType elType;
4534: Element elText;
1.126 cvs 4535:
1.210 gully 4536: /* Create a new Invalid_element */
4537: elType.ElSSchema = GetXMLSSchema (MATH_TYPE, context->doc);
4538: elType.ElTypeNum = MathML_EL_Unknown_namespace;
4539: *unknownEl = TtaNewElement (context->doc, elType);
4540: if (*unknownEl != NULL)
4541: {
4542: XmlSetElemLineNumber (*unknownEl);
4543: InsertXmlElement (unknownEl);
4544: context->lastElementClosed = TRUE;
4545: elType.ElTypeNum = MathML_EL_TEXT_UNIT;
4546: elText = TtaNewElement (context->doc, elType);
4547: XmlSetElemLineNumber (elText);
4548: TtaInsertFirstChild (&elText, *unknownEl, context->doc);
4549: TtaSetTextContent (elText, (unsigned char *)content, context->language, context->doc);
4550: TtaSetAccessRight (elText, ReadOnly, context->doc);
4551: }
1.126 cvs 4552: }
4553:
4554: /*----------------------------------------------------------------------
1.210 gully 4555: SetFontfamily
4556: -----------------------------------------------------------------------*/
1.120 cvs 4557: void SetFontfamily (Document doc, Element el, char *value)
1.24 cvs 4558: {
4559: #define buflen 50
1.116 cvs 4560: char css_command[buflen+20];
1.24 cvs 4561:
1.116 cvs 4562: sprintf (css_command, "font-family: %s", value);
1.222 quint 4563: ParseHTMLSpecificStyle (el, css_command, doc, 2000, FALSE);
1.24 cvs 4564: }
4565:
4566: /*----------------------------------------------------------------------
1.210 gully 4567: MathMLlinethickness
4568: The MathML attribute linthickness is associated with element el. Generate
4569: the corresponding style property for this element.
4570: -----------------------------------------------------------------------*/
1.120 cvs 4571: void MathMLlinethickness (Document doc, Element el, char *value)
1.83 cvs 4572: {
4573: #define buflen 50
1.116 cvs 4574: char css_command[buflen+20];
1.83 cvs 4575:
1.116 cvs 4576: if (strcmp (value, "thin") == 0)
1.210 gully 4577: strcpy (value, "1pt");
1.116 cvs 4578: else if (strcmp (value, "medium") == 0)
1.210 gully 4579: strcpy (value, "1pt");
1.116 cvs 4580: else if (strcmp (value, "thick") == 0)
1.210 gully 4581: strcpy (value, "2pt");
1.116 cvs 4582: sprintf (css_command, "stroke-width: %s", value);
1.222 quint 4583: ParseHTMLSpecificStyle (el, css_command, doc, 2000, FALSE);
1.83 cvs 4584: }
4585:
4586: /*----------------------------------------------------------------------
1.210 gully 4587: MathMLAttrToStyleProperty
4588: The MathML attribute attr is associated with element el. Generate
4589: the corresponding style property for this element.
4590: -----------------------------------------------------------------------*/
1.138 cvs 4591: void MathMLAttrToStyleProperty (Document doc, Element el, char *value,
1.210 gully 4592: int attr)
1.24 cvs 4593: {
1.167 quint 4594: char css_command[buflen+20], namedSpaceVal[20];
1.141 quint 4595: int i;
1.58 cvs 4596:
4597: switch (attr)
4598: {
4599: case MathML_ATTR_fontsize:
1.210 gully 4600: sprintf (css_command, "font-size: %s", value);
4601: break;
1.93 cvs 4602: case MathML_ATTR_mathsize:
1.210 gully 4603: if (strcmp (value, "small") == 0)
4604: strcpy (value, "80%");
4605: else if (strcmp (value, "normal") == 0)
4606: strcpy (value, "100%");
4607: else if (strcmp (value, "big") == 0)
4608: strcpy (value, "125%");
4609: sprintf (css_command, "font-size: %s", value);
4610: break;
1.58 cvs 4611: case MathML_ATTR_lspace:
4612: case MathML_ATTR_rspace:
1.210 gully 4613: if (attr == MathML_ATTR_lspace)
4614: strcpy (css_command, "padding-left: ");
4615: else
4616: strcpy (css_command, "padding-right: ");
4617: ConvertNamedSpace (value, namedSpaceVal);
4618: if (namedSpaceVal[0] != EOS)
4619: /* it's a named space */
4620: strcat (css_command, namedSpaceVal);
4621: else
4622: {
4623: strcat (css_command, value);
4624: /* does the value contain an unit at the end? */
4625: i = strlen (value) - 1;
4626: if ((value[i] <= '9' && value[i] >= '0') ||
4627: value[i] == '.')
4628: /* it's just a number. Add the (implicit) unit: em */
4629: strcat (css_command, "em");
4630: }
4631: break;
1.58 cvs 4632: }
1.222 quint 4633: ParseHTMLSpecificStyle (el, css_command, doc, 2000, FALSE);
1.24 cvs 4634: }
4635:
4636: /*----------------------------------------------------------------------
1.210 gully 4637: MathMLSetScriptLevel
4638: A scriptlevel attribute with value value is associated with element el.
4639: Generate the corresponding style property for this element.
4640: -----------------------------------------------------------------------*/
1.120 cvs 4641: void MathMLSetScriptLevel (Document doc, Element el, char *value)
1.60 cvs 4642: {
4643: PresentationValue pval;
4644: PresentationContext ctxt;
4645: ThotBool relative;
4646: int percentage;
4647:
4648: ctxt = TtaGetSpecificStyleContext (doc);
4649: if (!value)
1.210 gully 4650: /* remove the presentation rule */
4651: {
4652: ctxt->destroy = TRUE;
4653: pval.typed_data.value = 0;
4654: TtaSetStylePresentation (PRSize, el, NULL, ctxt, pval);
4655: }
1.60 cvs 4656: else
1.210 gully 4657: {
4658: ctxt->destroy = FALSE;
4659: /* parse the attribute value (an optional sign and an integer) */
4660: value = TtaSkipBlanks (value);
4661: relative = (value[0] == '-' || value[0] == '+');
4662: value = ParseCSSUnit (value, &pval);
4663: if (pval.typed_data.unit != UNIT_REL &&
4664: pval.typed_data.real)
4665: /* this is an error: it should be an integer without any unit name */
4666: /* error */;
4667: else
4668: {
4669: if (relative)
4670: {
4671: percentage = 100;
4672: if (pval.typed_data.value == 0)
4673: /* scriptlevel="+0" */
4674: percentage = 100;
4675: else if (pval.typed_data.value == 1)
4676: /* scriptlevel="+1" */
4677: percentage = 71;
4678: else if (pval.typed_data.value == 2)
4679: /* scriptlevel="+2" */
4680: percentage = 50;
4681: else if (pval.typed_data.value >= 3)
4682: /* scriptlevel="+3" or more */
4683: percentage = 35;
4684: else if (pval.typed_data.value == -1)
4685: /* scriptlevel="-1" */
4686: percentage = 141;
4687: else if (pval.typed_data.value == -2)
4688: /* scriptlevel="-2" */
4689: percentage = 200;
4690: else if (pval.typed_data.value <= -3)
4691: /* scriptlevel="-3" or less */
4692: percentage = 282;
4693: pval.typed_data.value = percentage;
4694: pval.typed_data.unit = UNIT_PERCENT;
4695: /* the specific presentation to be created is not a CSS rule */
4696: ctxt->cssSpecificity = 0;
4697: TtaSetStylePresentation (PRSize, el, NULL, ctxt, pval);
4698: }
4699: else
4700: /* absolute value */
4701: {
4702: /**** ****/;
4703: }
4704: }
4705: }
1.60 cvs 4706: TtaFreeMemory (ctxt);
4707: }
4708:
4709: /*----------------------------------------------------------------------
1.210 gully 4710: MathMLSpacingAttr
4711: The MathML attribute attr (height, width or depth) is associated
4712: with element el (a mspace or mpadding).
4713: If value is not NULL, generate the corresponding Thot presentation rule for
4714: the element.
4715: If value is NULL, remove the corresponding Thot presentation rule.
4716: -----------------------------------------------------------------------*/
1.120 cvs 4717: void MathMLSpacingAttr (Document doc, Element el, char *value, int attr)
1.60 cvs 4718: {
4719: ElementType elType;
4720: PresentationValue pval;
4721: PresentationContext ctxt;
4722: int ruleType;
4723:
4724: /* provisionally, handles only mspace elements */
4725: elType = TtaGetElementType (el);
1.96 cvs 4726: if (elType.ElTypeNum != MathML_EL_MSPACE &&
1.97 cvs 4727: elType.ElTypeNum != MathML_EL_MPADDED &&
4728: elType.ElTypeNum != MathML_EL_MTABLE)
1.210 gully 4729: return;
1.60 cvs 4730: switch (attr)
4731: {
4732: case MathML_ATTR_width_:
4733: ruleType = PRWidth;
4734: break;
4735: case MathML_ATTR_height_:
4736: ruleType = PRPaddingTop;
4737: break;
4738: case MathML_ATTR_depth_:
4739: ruleType = PRPaddingBottom;
4740: break;
4741: default:
4742: return;
4743: }
4744: ctxt = TtaGetSpecificStyleContext (doc);
1.116 cvs 4745: if (!value || (strcmp (value, "auto") == 0))
1.60 cvs 4746: /* remove the presentation rule */
4747: {
4748: ctxt->destroy = TRUE;
1.75 cvs 4749: pval.typed_data.value = 0;
1.60 cvs 4750: TtaSetStylePresentation (ruleType, el, NULL, ctxt, pval);
4751: }
4752: else
4753: {
4754: ctxt->destroy = FALSE;
4755: /* parse the attribute value (a number followed by a unit) */
1.119 cvs 4756: value = TtaSkipBlanks (value);
1.60 cvs 4757: value = ParseCSSUnit (value, &pval);
4758: /***** we should accept namedspace for width *****/
1.184 vatton 4759: if (pval.typed_data.unit != UNIT_INVALID)
1.210 gully 4760: {
4761: if (pval.typed_data.unit == UNIT_BOX)
4762: pval.typed_data.unit = UNIT_PX;
4763: /* the specific presentation to be created is not a CSS rule */
4764: ctxt->cssSpecificity = 0;
4765: TtaSetStylePresentation (ruleType, el, NULL, ctxt, pval);
4766: }
1.60 cvs 4767: }
4768: TtaFreeMemory (ctxt);
4769: }
4770:
4771: /*----------------------------------------------------------------------
1.210 gully 4772: MathMLSetDisplaystyleAttr
4773: The attribute displaystyle is associated with element el (which
4774: should be a <mstyle> or a <mtable> element).
4775: Generate or set the corresponding internal attribute accordingly.
1.169 quint 4776: ----------------------------------------------------------------------*/
4777: void MathMLSetDisplaystyleAttr (Element el, Attribute attr, Document doc,
1.210 gully 4778: ThotBool delete_)
1.169 quint 4779: {
4780: int val, intVal;
4781: ElementType elType;
4782: AttributeType attrType;
4783: Attribute intAttr;
1.153 quint 4784:
1.175 quint 4785: intVal = 0;
1.169 quint 4786: /* get the internal attribute */
4787: elType = TtaGetElementType (el);
4788: attrType.AttrSSchema = elType.ElSSchema;
4789: attrType.AttrTypeNum = MathML_ATTR_IntDisplaystyle;
4790: intAttr = TtaGetAttribute (el, attrType);
1.193 gully 4791: if (delete_)
1.169 quint 4792: /* attribute displaystyle has been deleted */
4793: {
4794: if (elType.ElTypeNum == MathML_EL_MSTYLE)
1.210 gully 4795: /* it's a mstyle element. Just remove the internal attribute */
4796: {
4797: if (intAttr)
4798: TtaRemoveAttribute (el, intAttr, doc);
4799: }
1.169 quint 4800: else if (elType.ElTypeNum == MathML_EL_MTABLE)
1.210 gully 4801: /* it's a matable element, set the default value (false) */
4802: intVal = MathML_ATTR_IntDisplaystyle_VAL_false;
1.169 quint 4803: }
4804: else
4805: {
4806: val = TtaGetAttributeValue (attr);
4807: if (val == MathML_ATTR_displaystyle_VAL_true)
1.210 gully 4808: intVal = MathML_ATTR_IntDisplaystyle_VAL_true;
1.169 quint 4809: else
1.210 gully 4810: intVal = MathML_ATTR_IntDisplaystyle_VAL_false;
1.169 quint 4811: }
4812: /* create the IntDisplaystyle attribute if needed and set its value */
1.175 quint 4813: if (intVal)
1.169 quint 4814: {
1.175 quint 4815: if (!intAttr)
1.210 gully 4816: {
4817: intAttr = TtaNewAttribute (attrType);
4818: TtaAttachAttribute (el, intAttr, doc);
4819: }
1.175 quint 4820: TtaSetAttributeValue (intAttr, intVal, el, doc);
1.169 quint 4821: }
1.175 quint 4822: ApplyDisplaystyle (el, doc);
1.153 quint 4823: }
4824:
4825: /*----------------------------------------------------------------------
1.210 gully 4826: MathMLAttributeComplete
4827: The XML parser has completed parsing attribute attr (as well as its value)
4828: that is associated with element el in document doc.
1.1 cvs 4829: ----------------------------------------------------------------------*/
1.120 cvs 4830: void MathMLAttributeComplete (Attribute attr, Element el, Document doc)
1.1 cvs 4831: {
1.210 gully 4832: AttributeType attrType, depAttrType;
4833: int attrKind;
4834: ElementType elType;
4835: char *value;
4836: int val, length;
4837: Attribute intAttr;
4838:
4839: /* first get the type of that attribute */
4840: TtaGiveAttributeType (attr, &attrType, &attrKind);
4841:
4842: if (attrType.AttrTypeNum == MathML_ATTR_bevelled)
4843: /* it's a bevelled attribute */
4844: {
4845: val = TtaGetAttributeValue (attr);
4846: if (val == MathML_ATTR_bevelled_VAL_true)
4847: /* bevelled = true. Transform MFRAC into BevelledMFRAC */
4848: {
4849: elType = TtaGetElementType (el);
4850: if (elType.ElTypeNum == MathML_EL_MFRAC)
4851: TtaChangeTypeOfElement (el, doc, MathML_EL_BevelledMFRAC);
4852: }
4853: }
4854:
4855: else if (attrType.AttrTypeNum == MathML_ATTR_rowalign_mtr)
4856: {
4857: /* create an equivalent IntRowAlign attribute on the same element */
4858: attrType.AttrTypeNum = MathML_ATTR_IntRowAlign;
4859: intAttr = TtaGetAttribute (el, attrType);
4860: if (!intAttr)
4861: /* no IntRowAlign attribute, create one */
4862: {
4863: intAttr = TtaNewAttribute (attrType);
4864: TtaAttachAttribute (el, intAttr, doc);
4865: }
4866: val = TtaGetAttributeValue (attr);
4867: TtaSetAttributeValue (intAttr, val, el, doc);
4868: }
4869:
4870: else if (attrType.AttrTypeNum == MathML_ATTR_columnalign_mtd)
4871: {
4872: /* create an equivalent IntColAlign attribute on the same element */
4873: attrType.AttrTypeNum = MathML_ATTR_IntColAlign;
4874: intAttr = TtaGetAttribute (el, attrType);
4875: if (!intAttr)
4876: /* no IntColAlign attribute, create one */
4877: {
4878: intAttr = TtaNewAttribute (attrType);
4879: TtaAttachAttribute (el, intAttr, doc);
4880: }
4881: val = TtaGetAttributeValue (attr);
4882: TtaSetAttributeValue (intAttr, val, el, doc);
4883: }
4884:
4885: /* don't handle attributes columnalign, rowalign, columnlines and rowlines
4886: now: the table or the row is not complete yet. Handle them when the
4887: element is complete.
4888: */
4889:
4890: else if (attrType.AttrTypeNum == MathML_ATTR_display_)
4891: /* it's a display attribute on element <math>, set the corresponding
4892: internal attribute IntDisplaystyle */
4893: SetDisplaystyleMathElement (el, doc);
4894:
4895: else if (attrType.AttrTypeNum == MathML_ATTR_displaystyle)
4896: /* it's a displaystyle attribute */
4897: MathMLSetDisplaystyleAttr (el, attr, doc, FALSE);
4898:
4899: else if (attrType.AttrTypeNum == MathML_ATTR_framespacing)
4900: /* it's a framespacing attribute */
4901: HandleFramespacingAttribute (attr, el, doc, FALSE);
4902:
4903: else if (attrType.AttrTypeNum == MathML_ATTR_Language)
4904: {
4905: if (el == TtaGetRootElement (doc))
4906: /* it's the lang attribute on the root element */
4907: /* set the RealLang attribute */
4908: {
4909: depAttrType.AttrSSchema = attrType.AttrSSchema ;
4910: depAttrType.AttrTypeNum = MathML_ATTR_RealLang;
4911: if (!TtaGetAttribute (el, depAttrType))
4912: /* it's not present. Add it */
4913: {
4914: intAttr = TtaNewAttribute (depAttrType);
4915: TtaAttachAttribute (el, intAttr, doc);
4916: TtaSetAttributeValue (intAttr, MathML_ATTR_RealLang_VAL_Yes_,
4917: el, doc);
4918: }
4919: }
4920: }
4921:
4922: else if (attrType.AttrTypeNum == MathML_ATTR_color ||
4923: attrType.AttrTypeNum == MathML_ATTR_mathcolor ||
4924: attrType.AttrTypeNum == MathML_ATTR_background_ ||
4925: attrType.AttrTypeNum == MathML_ATTR_mathbackground ||
4926: attrType.AttrTypeNum == MathML_ATTR_fontsize ||
4927: attrType.AttrTypeNum == MathML_ATTR_mathsize ||
4928: attrType.AttrTypeNum == MathML_ATTR_fontfamily ||
4929: attrType.AttrTypeNum == MathML_ATTR_linethickness ||
4930: attrType.AttrTypeNum == MathML_ATTR_lspace ||
4931: attrType.AttrTypeNum == MathML_ATTR_rspace ||
4932: attrType.AttrTypeNum == MathML_ATTR_scriptlevel ||
4933: attrType.AttrTypeNum == MathML_ATTR_width_ ||
4934: attrType.AttrTypeNum == MathML_ATTR_height_ ||
4935: attrType.AttrTypeNum == MathML_ATTR_depth_)
4936: {
1.23 cvs 4937: length = TtaGetTextAttributeLength (attr);
4938: if (length >= buflen)
1.210 gully 4939: length = buflen - 1;
1.23 cvs 4940: if (length > 0)
1.210 gully 4941: {
4942: value = (char *)TtaGetMemory (buflen);
4943: value[0] = EOS;
4944: TtaGiveTextAttributeValue (attr, value, &length);
4945: switch (attrType.AttrTypeNum)
4946: {
4947: case MathML_ATTR_color:
4948: /* deprecated attribute */
4949: /* if the same element has a mathcolor attribute, ignore
4950: the color attribute */
4951: depAttrType.AttrSSchema = attrType.AttrSSchema ;
4952: depAttrType.AttrTypeNum = MathML_ATTR_mathcolor;
4953: if (!TtaGetAttribute (el, depAttrType))
1.222 quint 4954: HTMLSetForegroundColor (doc, el, 2000, value);
1.210 gully 4955: break;
4956: case MathML_ATTR_mathcolor:
1.222 quint 4957: HTMLSetForegroundColor (doc, el, 2000, value);
1.210 gully 4958: break;
4959: case MathML_ATTR_background_:
4960: /* deprecated attribute */
4961: /* if the same element has a mathbackground attribute, ignore
4962: the background attribute */
4963: depAttrType.AttrSSchema = attrType.AttrSSchema;
4964: depAttrType.AttrTypeNum = MathML_ATTR_mathbackground;
4965: if (!TtaGetAttribute (el, depAttrType))
1.222 quint 4966: HTMLSetBackgroundColor (doc, el, 2000, value);
1.210 gully 4967: break;
4968: case MathML_ATTR_mathbackground:
1.222 quint 4969: HTMLSetBackgroundColor (doc, el, 2000, value);
1.210 gully 4970: break;
4971: case MathML_ATTR_fontfamily:
4972: SetFontfamily (doc, el, value);
4973: break;
4974: case MathML_ATTR_linethickness:
4975: MathMLlinethickness (doc, el, value);
4976: break;
4977: case MathML_ATTR_fontsize:
4978: /* deprecated attribute */
4979: /* if the same element has a mathsize attribute, ignore
4980: the fontsize attribute */
4981: depAttrType.AttrSSchema = attrType.AttrSSchema;
4982: depAttrType.AttrTypeNum = MathML_ATTR_mathsize;
4983: if (!TtaGetAttribute (el, depAttrType))
4984: MathMLAttrToStyleProperty (doc, el, value,
4985: attrType.AttrTypeNum);
4986: break;
4987: case MathML_ATTR_mathsize:
4988: case MathML_ATTR_lspace:
4989: case MathML_ATTR_rspace:
4990: MathMLAttrToStyleProperty (doc, el, value,attrType.AttrTypeNum);
4991: break;
4992: case MathML_ATTR_scriptlevel:
4993: MathMLSetScriptLevel (doc, el, value);
4994: break;
4995: case MathML_ATTR_width_:
4996: case MathML_ATTR_height_:
4997: case MathML_ATTR_depth_:
4998: MathMLSpacingAttr (doc, el, value, attrType.AttrTypeNum);
4999: break;
5000: case MathML_ATTR_id:
5001: CheckUniqueName (el, doc, attr, attrType);
5002: break;
5003: default:
5004: break;
5005: }
5006: TtaFreeMemory (value);
5007: }
5008: }
1.1 cvs 5009: }
5010:
5011: /*----------------------------------------------------------------------
1.210 gully 5012: MathMLGetDTDName
1.1 cvs 5013: ----------------------------------------------------------------------*/
1.120 cvs 5014: void MathMLGetDTDName (char *DTDname, char *elementName)
1.1 cvs 5015: {
1.210 gully 5016: /* no other DTD allowed within MathML elements */
5017: strcpy (DTDname, "");
1.1 cvs 5018: }
5019:
5020: /* end of module */
Webmaster