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