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