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