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