Annotation of Amaya/amaya/XHTMLbuilder.c, revision 1.46

1.1       cvs         1: /*
                      2:  *
1.30      cvs         3:  *  (c) COPYRIGHT MIT and INRIA, 1996-2001.
1.1       cvs         4:  *  Please first read the full copyright statement in file COPYRIGHT.
                      5:  *
                      6:  */
                      7: 
                      8: /*
1.30      cvs         9:  * XHTMLbuilder.c
1.23      cvs        10:  * Builds the corresponding abstract tree for a Thot document of type HTML.
1.1       cvs        11:  *
1.20      cvs        12:  * Authors: L. Carcone
                     13:  *          V. Quint 
1.1       cvs        14:  */
                     15: 
                     16: #define THOT_EXPORT extern
                     17: #include "amaya.h"
                     18: #include "css.h"
1.2       cvs        19: #include "parser.h"
                     20: #include "HTML.h"
1.30      cvs        21: #include "fetchHTMLname.h"
1.2       cvs        22: 
1.13      cvs        23: #include "css_f.h"
                     24: #include "fetchXMLname_f.h"
1.30      cvs        25: #include "fetchHTMLname_f.h"
1.22      cvs        26: #include "html2thot_f.h"
1.1       cvs        27: #include "HTMLactions_f.h"
                     28: #include "HTMLedit_f.h"
1.22      cvs        29: #include "HTMLform_f.h"
1.1       cvs        30: #include "HTMLimage_f.h"
                     31: #include "HTMLtable_f.h"
                     32: #include "HTMLimage_f.h"
                     33: #include "UIcss_f.h"
1.13      cvs        34: #include "styleparser_f.h"
1.2       cvs        35: #include "XHTMLbuilder_f.h"
1.13      cvs        36: #include "Xml2thot_f.h"
1.1       cvs        37: 
                     38: /* maximum length of a Thot structure schema name */
                     39: #define MAX_SS_NAME_LENGTH 32
                     40: 
1.30      cvs        41: #define MaxMsgLength 200
                     42: 
1.14      cvs        43: /* Mapping table of HTML attribute values */
                     44: AttrValueMapping XhtmlAttrValueMappingTable[] =
1.1       cvs        45: {
1.36      cvs        46:    {HTML_ATTR_dir, "ltr", HTML_ATTR_dir_VAL_ltr},
                     47:    {HTML_ATTR_dir, "rtl", HTML_ATTR_dir_VAL_rtl},
1.1       cvs        48: 
1.36      cvs        49:    {HTML_ATTR_TextAlign, "left", HTML_ATTR_TextAlign_VAL_left_},
                     50:    {HTML_ATTR_TextAlign, "center", HTML_ATTR_TextAlign_VAL_center_},
                     51:    {HTML_ATTR_TextAlign, "right", HTML_ATTR_TextAlign_VAL_right_},
                     52:    {HTML_ATTR_TextAlign, "justify", HTML_ATTR_TextAlign_VAL_justify_},
                     53: 
                     54:    {HTML_ATTR_Align, "left", HTML_ATTR_Align_VAL_left_},
                     55:    {HTML_ATTR_Align, "center", HTML_ATTR_Align_VAL_center_},
                     56:    {HTML_ATTR_Align, "right", HTML_ATTR_Align_VAL_right_},
                     57: 
                     58:    {HTML_ATTR_LAlign, "top", HTML_ATTR_LAlign_VAL_Top_},
                     59:    {HTML_ATTR_LAlign, "bottom", HTML_ATTR_LAlign_VAL_Bottom_},
                     60:    {HTML_ATTR_LAlign, "left", HTML_ATTR_LAlign_VAL_Left_},
                     61:    {HTML_ATTR_LAlign, "right", HTML_ATTR_LAlign_VAL_Right_},
                     62: 
                     63:    {HTML_ATTR_Clear, "left", HTML_ATTR_Clear_VAL_Left_},
                     64:    {HTML_ATTR_Clear, "right", HTML_ATTR_Clear_VAL_Right_},
                     65:    {HTML_ATTR_Clear, "all", HTML_ATTR_Clear_VAL_All_},
                     66:    {HTML_ATTR_Clear, "none", HTML_ATTR_Clear_VAL_None_},
                     67: 
                     68:    {HTML_ATTR_NumberStyle, "1", HTML_ATTR_NumberStyle_VAL_Arabic_},
                     69:    {HTML_ATTR_NumberStyle, "a", HTML_ATTR_NumberStyle_VAL_LowerAlpha},
                     70:    {HTML_ATTR_NumberStyle, "A", HTML_ATTR_NumberStyle_VAL_UpperAlpha},
                     71:    {HTML_ATTR_NumberStyle, "i", HTML_ATTR_NumberStyle_VAL_LowerRoman},
                     72:    {HTML_ATTR_NumberStyle, "I", HTML_ATTR_NumberStyle_VAL_UpperRoman},
                     73: 
                     74:    {HTML_ATTR_BulletStyle, "disc", HTML_ATTR_BulletStyle_VAL_disc},
                     75:    {HTML_ATTR_BulletStyle, "square", HTML_ATTR_BulletStyle_VAL_square},
                     76:    {HTML_ATTR_BulletStyle, "circle", HTML_ATTR_BulletStyle_VAL_circle},
                     77: 
                     78:    {HTML_ATTR_ItemStyle, "1", HTML_ATTR_ItemStyle_VAL_Arabic_},
                     79:    {HTML_ATTR_ItemStyle, "a", HTML_ATTR_ItemStyle_VAL_LowerAlpha},
                     80:    {HTML_ATTR_ItemStyle, "A", HTML_ATTR_ItemStyle_VAL_UpperAlpha},
                     81:    {HTML_ATTR_ItemStyle, "i", HTML_ATTR_ItemStyle_VAL_LowerRoman},
                     82:    {HTML_ATTR_ItemStyle, "I", HTML_ATTR_ItemStyle_VAL_UpperRoman},
                     83:    {HTML_ATTR_ItemStyle, "disc", HTML_ATTR_ItemStyle_VAL_disc},
                     84:    {HTML_ATTR_ItemStyle, "square", HTML_ATTR_ItemStyle_VAL_square},
                     85:    {HTML_ATTR_ItemStyle, "circle", HTML_ATTR_ItemStyle_VAL_circle},
                     86: 
                     87:    {HTML_ATTR_Button_type, "button", HTML_ATTR_Button_type_VAL_button},
                     88:    {HTML_ATTR_Button_type, "submit", HTML_ATTR_Button_type_VAL_submit},
                     89:    {HTML_ATTR_Button_type, "reset", HTML_ATTR_Button_type_VAL_reset},
                     90: 
                     91:    {HTML_ATTR_frame, "void", HTML_ATTR_frame_VAL_void},
                     92:    {HTML_ATTR_frame, "above", HTML_ATTR_frame_VAL_above},
                     93:    {HTML_ATTR_frame, "below", HTML_ATTR_frame_VAL_below},
                     94:    {HTML_ATTR_frame, "hsides", HTML_ATTR_frame_VAL_hsides},
                     95:    {HTML_ATTR_frame, "lhs", HTML_ATTR_frame_VAL_lhs},
                     96:    {HTML_ATTR_frame, "rhs", HTML_ATTR_frame_VAL_rhs},
                     97:    {HTML_ATTR_frame, "vsides", HTML_ATTR_frame_VAL_vsides},
                     98:    {HTML_ATTR_frame, "box", HTML_ATTR_frame_VAL_box},
                     99:    {HTML_ATTR_frame, "border", HTML_ATTR_frame_VAL_border},
                    100: 
                    101:    {HTML_ATTR_frameborder, "0", HTML_ATTR_frameborder_VAL_Border0},
                    102:    {HTML_ATTR_frameborder, "1", HTML_ATTR_frameborder_VAL_Border1},
                    103: 
                    104:    {HTML_ATTR_scrolling, "yes", HTML_ATTR_scrolling_VAL_Yes_},
                    105:    {HTML_ATTR_scrolling, "no", HTML_ATTR_scrolling_VAL_No_},
                    106:    {HTML_ATTR_scrolling, "auto", HTML_ATTR_scrolling_VAL_auto_},
                    107: 
                    108:    {HTML_ATTR_rules_, "none", HTML_ATTR_rules__VAL_none_},
                    109:    {HTML_ATTR_rules_, "groups", HTML_ATTR_rules__VAL_groups},
                    110:    {HTML_ATTR_rules_, "rows", HTML_ATTR_rules__VAL_rows},
                    111:    {HTML_ATTR_rules_, "cols", HTML_ATTR_rules__VAL_cols},
                    112:    {HTML_ATTR_rules_, "all", HTML_ATTR_rules__VAL_all},
                    113: 
                    114:    {HTML_ATTR_Cell_align, "left", HTML_ATTR_Cell_align_VAL_Cell_left},
                    115:    {HTML_ATTR_Cell_align, "center", HTML_ATTR_Cell_align_VAL_Cell_center},
                    116:    {HTML_ATTR_Cell_align, "right", HTML_ATTR_Cell_align_VAL_Cell_right},
                    117:    {HTML_ATTR_Cell_align, "justify", HTML_ATTR_Cell_align_VAL_Cell_justify},
                    118:    {HTML_ATTR_Cell_align, "char", HTML_ATTR_Cell_align_VAL_Cell_char},
                    119: 
                    120:    {HTML_ATTR_Alignment, "top", HTML_ATTR_Alignment_VAL_Top_},
                    121:    {HTML_ATTR_Alignment, "middle", HTML_ATTR_Alignment_VAL_Middle_},
                    122:    {HTML_ATTR_Alignment, "bottom", HTML_ATTR_Alignment_VAL_Bottom_},
                    123:    {HTML_ATTR_Alignment, "left", HTML_ATTR_Alignment_VAL_Left_},
                    124:    {HTML_ATTR_Alignment, "right", HTML_ATTR_Alignment_VAL_Right_},
                    125: 
                    126:    {HTML_ATTR_METHOD, "get", HTML_ATTR_METHOD_VAL_Get_},
                    127:    {HTML_ATTR_METHOD, "post", HTML_ATTR_METHOD_VAL_Post_},
                    128: 
                    129:    {HTML_ATTR_Position, "top", HTML_ATTR_Position_VAL_Position_top},
                    130:    {HTML_ATTR_Position, "bottom", HTML_ATTR_Position_VAL_Position_bottom},
                    131:    {HTML_ATTR_Position, "left", HTML_ATTR_Position_VAL_Position_left},
                    132:    {HTML_ATTR_Position, "right", HTML_ATTR_Position_VAL_Position_right},
                    133: 
                    134:    {HTML_ATTR_Row_valign, "top", HTML_ATTR_Row_valign_VAL_Row_top},
                    135:    {HTML_ATTR_Row_valign, "middle", HTML_ATTR_Row_valign_VAL_Row_middle},
                    136:    {HTML_ATTR_Row_valign, "bottom", HTML_ATTR_Row_valign_VAL_Row_bottom},
                    137:    {HTML_ATTR_Row_valign, "baseline", HTML_ATTR_Row_valign_VAL_Row_baseline},
                    138: 
                    139:    {HTML_ATTR_Cell_valign, "top", HTML_ATTR_Cell_valign_VAL_Cell_top},
                    140:    {HTML_ATTR_Cell_valign, "middle", HTML_ATTR_Cell_valign_VAL_Cell_middle},
                    141:    {HTML_ATTR_Cell_valign, "bottom", HTML_ATTR_Cell_valign_VAL_Cell_bottom},
                    142:    {HTML_ATTR_Cell_valign, "baseline", HTML_ATTR_Cell_valign_VAL_Cell_baseline},
                    143: 
                    144:    {HTML_ATTR_shape, "rect", HTML_ATTR_shape_VAL_rectangle},
                    145:    {HTML_ATTR_shape, "circle", HTML_ATTR_shape_VAL_circle},
                    146:    {HTML_ATTR_shape, "poly", HTML_ATTR_shape_VAL_polygon},
                    147: 
                    148:    {HTML_ATTR_valuetype, "data", HTML_ATTR_valuetype_VAL_data_},
                    149:    {HTML_ATTR_valuetype, "ref", HTML_ATTR_valuetype_VAL_ref},
                    150:    {HTML_ATTR_valuetype, "object", HTML_ATTR_valuetype_VAL_object_},
1.1       cvs       151: 
                    152: /* HTML attribute TYPE generates a Thot element */
1.36      cvs       153:    {DummyAttribute, "button", HTML_EL_Button_Input},
                    154:    {DummyAttribute, "checkbox", HTML_EL_Checkbox_Input},
                    155:    {DummyAttribute, "file", HTML_EL_File_Input},
                    156:    {DummyAttribute, "hidden", HTML_EL_Hidden_Input},
                    157:    {DummyAttribute, "image", HTML_EL_PICTURE_UNIT},
                    158:    {DummyAttribute, "password", HTML_EL_Password_Input},
                    159:    {DummyAttribute, "radio", HTML_EL_Radio_Input},
                    160:    {DummyAttribute, "reset", HTML_EL_Reset_Input},
                    161:    {DummyAttribute, "submit", HTML_EL_Submit_Input},
                    162:    {DummyAttribute, "text", HTML_EL_Text_Input},
1.1       cvs       163: 
                    164: /* The following declarations allow the parser to accept boolean attributes */
                    165: /* written "checked=CHECKED"), for instance */
1.36      cvs       166:    {HTML_ATTR_ISMAP, "ismap", HTML_ATTR_ISMAP_VAL_Yes_},
                    167:    {HTML_ATTR_nohref, "nohref", HTML_ATTR_nohref_VAL_Yes_},
                    168:    {HTML_ATTR_COMPACT, "compact", HTML_ATTR_COMPACT_VAL_Yes_},
                    169:    {HTML_ATTR_Multiple, "multiple", HTML_ATTR_Multiple_VAL_Yes_},
                    170:    {HTML_ATTR_Selected, "selected", HTML_ATTR_Selected_VAL_Yes_},
                    171:    {HTML_ATTR_Checked, "checked", HTML_ATTR_Checked_VAL_Yes_},
                    172:    {HTML_ATTR_No_wrap, "nowrap", HTML_ATTR_No_wrap_VAL_no_wrap},
                    173:    {HTML_ATTR_NoShade, "noshade", HTML_ATTR_NoShade_VAL_NoShade_},
                    174:    {HTML_ATTR_declare, "declare", HTML_ATTR_declare_VAL_Yes_},
                    175:    {HTML_ATTR_defer, "defer", HTML_ATTR_defer_VAL_Yes_},
                    176:    {HTML_ATTR_disabled, "disabled", HTML_ATTR_disabled_VAL_Yes_},
                    177:    {HTML_ATTR_readonly, "readonly", HTML_ATTR_readonly_VAL_Yes_},
                    178:    {HTML_ATTR_no_resize, "noresize", HTML_ATTR_no_resize_VAL_Yes_},
1.21      cvs       179: 
                    180:    /* XML attribute xml:space */
1.36      cvs       181:    {HTML_ATTR_xml_space, "default", HTML_ATTR_xml_space_VAL_xml_space_default},
                    182:    {HTML_ATTR_xml_space, "preserve", HTML_ATTR_xml_space_VAL_xml_space_preserve},
1.21      cvs       183: 
1.36      cvs       184:    {0, "", 0}                  /* Last entry. Mandatory */
1.1       cvs       185: };
1.6       cvs       186: 
1.28      cvs       187: /* Define a pointer to let parser functions access the HTML entity table */
                    188: extern XmlEntity *pXhtmlEntityTable;
1.6       cvs       189: 
1.30      cvs       190: /* maximum size of error messages */
                    191: #define MaxMsgLength 200
                    192: 
1.6       cvs       193: /*----------------------------------------------------------------------
1.15      cvs       194:   ParseCharset:
1.6       cvs       195:   Parses the element HTTP-EQUIV and looks for the charset value.
                    196:   ----------------------------------------------------------------------*/
1.30      cvs       197: void             ParseCharset (Element el, Document doc) 
                    198: 
1.6       cvs       199: {
1.15      cvs       200:    AttributeType attrType;
                    201:    Attribute     attr;
                    202:    SSchema       docSSchema;
                    203:    CHARSET       charset;
1.39      cvs       204:    char         *text, *text2, *ptrText, *str;
                    205:    char          charsetname[MAX_LENGTH];
1.15      cvs       206:    int           length;
1.6       cvs       207:    int           pos, index = 0;
                    208: 
1.15      cvs       209:    charset = TtaGetDocumentCharset (doc);
                    210:    if (charset != UNDEFINED_CHARSET)
                    211:      /* the charset was already defined by the http header */
                    212:      return;
1.6       cvs       213: 
                    214:    docSSchema = TtaGetDocumentSSchema (doc);
                    215:    attrType.AttrSSchema = docSSchema;
                    216:    attrType.AttrTypeNum = HTML_ATTR_http_equiv;
                    217:    attr = TtaGetAttribute (el, attrType);
                    218:    if (attr != NULL)
                    219:      {
                    220:        /* There is a HTTP-EQUIV attribute */
                    221:        length = TtaGetTextAttributeLength (attr);
                    222:        if (length > 0)
                    223:         {
1.37      cvs       224:           text = TtaGetMemory (length + 1);
1.6       cvs       225:           TtaGiveTextAttributeValue (attr, text, &length);
1.37      cvs       226:           if (!strcasecmp (text, "content-type"))
1.6       cvs       227:             {
                    228:               attrType.AttrTypeNum = HTML_ATTR_meta_content;
                    229:               attr = TtaGetAttribute (el, attrType);
                    230:               if (attr != NULL)
                    231:                 {
                    232:                   length = TtaGetTextAttributeLength (attr);
                    233:                   if (length > 0)
                    234:                     {
1.37      cvs       235:                       text2 = TtaGetMemory (length + 1);
1.6       cvs       236:                       TtaGiveTextAttributeValue (attr, text2, &length);
                    237:                       ptrText = text2;
                    238:                       while (*ptrText)
                    239:                         {
                    240:                           *ptrText = utolower (*ptrText);
                    241:                           ptrText++;
                    242:                         }
                    243:                       
1.37      cvs       244:                       str = strstr (text2, "charset=");
1.6       cvs       245:                       if (str)
                    246:                         {
                    247:                           pos = str - text2 + 8;
1.37      cvs       248:                           while (text2[pos] != SPACE &&
                    249:                                  text2[pos] != TAB && text2[pos] != EOS)
1.6       cvs       250:                             charsetname[index++] = text2[pos++];
1.37      cvs       251:                           charsetname[index] = EOS;
1.15      cvs       252:                           charset = TtaGetCharset (charsetname);
                    253:                           if (charset != UNDEFINED_CHARSET)
                    254:                             TtaSetDocumentCharset (doc, charset);
1.6       cvs       255:                         }
                    256:                       TtaFreeMemory (text2);
                    257:                     }       
                    258:                 } 
                    259:             }
                    260:           TtaFreeMemory (text);
                    261:         }
                    262:      }
                    263: }
                    264: 
1.23      cvs       265: /*----------------------------------------------------------------------
                    266:    XhtmlEntityCreated
                    267:    A XTHML entity has been created by the XML parser.
                    268:   ----------------------------------------------------------------------*/
1.33      cvs       269: void             XhtmlEntityCreated (int         entityValue,
1.39      cvs       270:                                     char       *entityName,
1.33      cvs       271:                                     ThotBool    entityFound,
1.30      cvs       272:                                     ParserData *context)
                    273: 
1.23      cvs       274: { 
1.29      cvs       275:   ElementType   elType;
1.33      cvs       276:   Element       elLeaf;
1.29      cvs       277:   AttributeType  attrType;
                    278:   Attribute     attr;
                    279:   Language      lang;
                    280:   int           len;
                    281: #define MAX_ENTITY_LENGTH 80
1.39      cvs       282:   char          buffer[MAX_ENTITY_LENGTH];
                    283:   char          bufName[MAX_ENTITY_LENGTH];
                    284:   char           msgBuffer[MAX_ENTITY_LENGTH + 50];
1.29      cvs       285:   
1.33      cvs       286:   if (entityValue <= 255 && entityFound)
1.23      cvs       287:     {
1.33      cvs       288:       /* It is an ISO latin1 character */
1.37      cvs       289:       buffer[0] = ((unsigned char) entityValue);
                    290:       buffer[1] = EOS;
1.29      cvs       291:       lang = TtaGetLanguageIdFromAlphabet('L');
1.33      cvs       292:       PutInXmlElement (buffer);
1.23      cvs       293:     }
1.29      cvs       294:   else
1.33      cvs       295:     {
                    296:       if (entityFound)
                    297:        {
                    298:          /* try to find a fallback character */
                    299:          GetFallbackCharacter (entityValue, buffer, &lang);
                    300:        }
1.37      cvs       301:       len = strlen (entityName);
1.35      cvs       302:       bufName[0] = (char) START_ENTITY;
1.37      cvs       303:       strncpy (&bufName[1], entityName, len);
1.34      cvs       304:       bufName[len+1] = ';';
1.37      cvs       305:       bufName[len+2] = EOS;
1.34      cvs       306:       
1.33      cvs       307:       /* Create a new text leaf */
                    308:       elType.ElSSchema = GetXMLSSchema (XHTML_TYPE, context->doc);
                    309:       elType.ElTypeNum = HTML_EL_TEXT_UNIT;
                    310:       elLeaf = TtaNewElement (context->doc, elType);
                    311:       XmlSetElemLineNumber (elLeaf);
                    312:       InsertXmlElement (&elLeaf);
                    313:       if (buffer[0] == '?' || !entityFound)
1.34      cvs       314:        {
                    315:          /* Character not found in the fallback table or not supported */
                    316:          /* Put the entity name into the new text leaf */
1.38      cvs       317:          lang = TtaGetLanguageIdFromAlphabet('L');
1.34      cvs       318:          TtaSetTextContent (elLeaf, bufName, lang, context->doc);
                    319:          if (entityFound)
                    320:            {
1.37      cvs       321:              sprintf (msgBuffer, "XHTML entity not supported : &%s", bufName);
1.34      cvs       322:              XmlParseError (errorParsing, msgBuffer, 0);
                    323:            }
                    324:        }
1.33      cvs       325:       else
1.34      cvs       326:        {
                    327:          /* Character found in the fallback table */
                    328:          TtaSetTextContent (elLeaf, buffer, lang, context->doc);
                    329:          /* Associate an attribute EntityName with the new text leaf */
                    330:          attrType.AttrSSchema = elType.ElSSchema;
                    331:          attrType.AttrTypeNum = HTML_ATTR_EntityName;
                    332:          attr = TtaNewAttribute (attrType);
                    333:          TtaAttachAttribute (elLeaf, attr, context->doc);
                    334:          TtaSetAttributeText (attr, bufName, elLeaf, context->doc);
                    335:        }
1.33      cvs       336:       context->lastElement = elLeaf;
                    337:       context->lastElementClosed = TRUE;
                    338:       context->mergeText = FALSE;
                    339:       /* Make that text leaf read-only */
                    340:       TtaSetAccessRight (elLeaf, ReadOnly, context->doc);
                    341:     }
1.23      cvs       342: }
                    343: 
1.6       cvs       344: /*----------------------------------------------------------------------
                    345:   XhtmlElementComplete
1.20      cvs       346:   Complete Xhtml elements.
1.6       cvs       347:   Check its attributes and its contents.
                    348:   ----------------------------------------------------------------------*/
1.42      cvs       349: void XhtmlElementComplete (Element el, Document doc, int *error)
1.30      cvs       350: 
                    351: {
                    352:    ElementType    elType, newElType, childType;
                    353:    Element        constElem, child, desc, leaf, prev, next, last,
1.41      cvs       354:                  elFrames, lastFrame, lastChild, parent;
1.30      cvs       355:    Attribute      attr;
                    356:    AttributeType  attrType;
                    357:    Language       lang;
1.41      cvs       358:    char           *text;
1.39      cvs       359:    char           lastChar[2];
                    360:    char           *name1;
1.30      cvs       361:    int            length;
                    362:    SSchema        docSSchema;
1.6       cvs       363: 
                    364:    *error = 0;
                    365:    docSSchema = TtaGetDocumentSSchema (doc);
                    366: 
                    367:    elType = TtaGetElementType (el);
                    368:    /* is this a block-level element in a character-level element? */
1.27      cvs       369:    if (!IsXMLElementInline (elType) &&
1.24      cvs       370:        elType.ElTypeNum != HTML_EL_Comment_ &&
                    371:        elType.ElTypeNum != HTML_EL_XMLPI)
1.6       cvs       372:        BlockInCharLevelElem (el);
                    373: 
                    374:    newElType.ElSSchema = elType.ElSSchema;
                    375:    switch (elType.ElTypeNum)
                    376:      {
                    377:      case HTML_EL_Object:      /*  it's an object */
                    378:        /* create Object_Content */
                    379:        child = TtaGetFirstChild (el);
                    380:        if (child != NULL)
                    381:           elType = TtaGetElementType (child);
                    382:         
                    383:        /* is it the PICTURE element ? */
                    384:        if (child == NULL || elType.ElTypeNum != HTML_EL_PICTURE_UNIT)
                    385:         {
                    386:           desc = child;
                    387:           /* create the PICTURE element */
                    388:           elType.ElTypeNum = HTML_EL_PICTURE_UNIT;
                    389:           child = TtaNewTree (doc, elType, "");
                    390:           if (desc == NULL)
                    391:               TtaInsertFirstChild (&child, el, doc);
                    392:           else
                    393:               TtaInsertSibling (child, desc, TRUE, doc);
                    394:         }
                    395: 
                    396:        /* copy attribute data into SRC attribute of Object_Image */
                    397:        attrType.AttrSSchema = docSSchema;
                    398:        attrType.AttrTypeNum = HTML_ATTR_data;
                    399:        attr = TtaGetAttribute (el, attrType);
                    400:        if (attr != NULL)
                    401:         {
                    402:           length = TtaGetTextAttributeLength (attr);
                    403:           if (length > 0)
                    404:             {
1.37      cvs       405:               name1 = TtaGetMemory (length + 1);
1.6       cvs       406:               TtaGiveTextAttributeValue (attr, name1, &length);
                    407:               attrType.AttrTypeNum = HTML_ATTR_SRC;
                    408:               attr = TtaGetAttribute (child, attrType);
                    409:               if (attr == NULL)
                    410:                 {
                    411:                   attr = TtaNewAttribute (attrType);
                    412:                   TtaAttachAttribute (child, attr, doc);
                    413:                 }
                    414:               TtaSetAttributeText (attr, name1, child, doc);
                    415:               TtaFreeMemory (name1);
                    416:             }
                    417:         }
                    418: 
                    419:        /* is the Object_Content element already created ? */
                    420:        desc = child;
                    421:        TtaNextSibling(&desc);
                    422:        if (desc != NULL)
                    423:           elType = TtaGetElementType (desc);
                    424:         
                    425:        /* is it the Object_Content element ? */
                    426:        if (desc == NULL || elType.ElTypeNum != HTML_EL_Object_Content)
                    427:         {
                    428:           /* create Object_Content */
                    429:           elType.ElTypeNum = HTML_EL_Object_Content;
                    430:           desc = TtaNewTree (doc, elType, "");
                    431:           TtaInsertSibling (desc, child, FALSE, doc);
                    432:           /* move previous existing children into Object_Content */
                    433:           child = TtaGetLastChild(el);
                    434:           while (child != desc)
                    435:             {
                    436:               TtaRemoveTree (child, doc);
                    437:               TtaInsertFirstChild (&child, desc, doc);
                    438:               child = TtaGetLastChild(el);
                    439:             }
                    440:         }
                    441:        break;
                    442:        
                    443:      case HTML_EL_Unnumbered_List:
                    444:      case HTML_EL_Numbered_List:
                    445:      case HTML_EL_Menu:
                    446:      case HTML_EL_Directory:
                    447:        /* It's a List element. It should only have List_Item children.
                    448:          If it has List element chidren, move these List elements
                    449:          within their previous List_Item sibling.  This is to fix
                    450:          a bug in document generated by Mozilla. */
                    451:        prev = NULL;
                    452:        next = NULL;
                    453:        child = TtaGetFirstChild (el);
                    454:        while (child != NULL)
                    455:         {
                    456:           next = child;
                    457:           TtaNextSibling (&next);
                    458:           elType = TtaGetElementType (child);
                    459:           if (elType.ElTypeNum == HTML_EL_Unnumbered_List ||
                    460:               elType.ElTypeNum == HTML_EL_Numbered_List ||
                    461:               elType.ElTypeNum == HTML_EL_Menu ||
                    462:               elType.ElTypeNum == HTML_EL_Directory)
                    463:             /* this list element is a child of another list element */
                    464:             if (prev)
                    465:               {
                    466:                 elType = TtaGetElementType (prev);
                    467:                 if (elType.ElTypeNum == HTML_EL_List_Item)
                    468:                   {
                    469:                     /* get the last child of the previous List_Item */
                    470:                     desc = TtaGetFirstChild (prev);
                    471:                     last = NULL;
                    472:                     while (desc)
                    473:                       {
                    474:                         last = desc;
                    475:                         TtaNextSibling (&desc);
                    476:                       }
                    477:                     /* move the list element after the last child of the
                    478:                        previous List_Item */
                    479:                     TtaRemoveTree (child, doc);
                    480:                     if (last)
                    481:                       TtaInsertSibling (child, last, FALSE, doc);
                    482:                     else
                    483:                       TtaInsertFirstChild (&child, prev, doc);
                    484:                     child = prev;
                    485:                   }
                    486:               }
                    487:           prev = child;
                    488:           child = next;
                    489:         }
                    490:        break;
                    491:        
                    492:      case HTML_EL_FRAMESET:
                    493:        /* The FRAMESET element is now complete.  Gather all its FRAMESET
                    494:          and FRAME children and wrap them up in a Frames element */
                    495:        elFrames = NULL; lastFrame = NULL;
                    496:        lastChild = NULL;
                    497:        child = TtaGetFirstChild (el);
                    498:        while (child != NULL)
                    499:         {
                    500:           next = child;
                    501:           TtaNextSibling (&next);
                    502:           elType = TtaGetElementType (child);
                    503:           if (elType.ElTypeNum == HTML_EL_FRAMESET ||
                    504:               elType.ElTypeNum == HTML_EL_FRAME ||
                    505:               elType.ElTypeNum == HTML_EL_Comment_)
                    506:             {
                    507:               /* create the Frames element if it does not exist */
                    508:               if (elFrames == NULL)
                    509:                 {
                    510:                   newElType.ElSSchema = docSSchema;
                    511:                   newElType.ElTypeNum = HTML_EL_Frames;
                    512:                   elFrames = TtaNewElement (doc, newElType);
                    513:                   XmlSetElemLineNumber (elFrames);
                    514:                   TtaInsertSibling (elFrames, child, TRUE, doc);
                    515:                 }
                    516:               /* move the element as the last child of the Frames element */
                    517:               TtaRemoveTree (child, doc);
                    518:               if (lastFrame == NULL)
                    519:                 TtaInsertFirstChild (&child, elFrames, doc);
                    520:               else
                    521:                 TtaInsertSibling (child, lastFrame, FALSE, doc);
                    522:               lastFrame = child;
                    523:             }
                    524:           child = next;
                    525:         }
                    526:        break;
                    527:        
                    528:      case HTML_EL_Input:       /* it's an INPUT without any TYPE attribute */
                    529:        /* Create a child of type Text_Input */
                    530:        elType.ElTypeNum = HTML_EL_Text_Input;
                    531:        child = TtaNewTree (doc, elType, "");
                    532:        XmlSetElemLineNumber (child);
                    533:        TtaInsertFirstChild (&child, el, doc);
                    534:        /* now, process it like a Text_Input element */
                    535: 
                    536:      case HTML_EL_Text_Input:
                    537:      case HTML_EL_Password_Input:
                    538:      case HTML_EL_File_Input:
                    539:        /* get element Inserted_Text */
                    540:        child = TtaGetFirstChild (el);
                    541:        if (child != NULL)
                    542:         {
                    543:           attrType.AttrSSchema = docSSchema;
                    544:           attrType.AttrTypeNum = HTML_ATTR_Value_;
                    545:           attr = TtaGetAttribute (el, attrType);
                    546:           if (attr != NULL)
                    547:             {
                    548:               /* copy the value of attribute "value" into the first text
                    549:                  leaf of element */
                    550:               length = TtaGetTextAttributeLength (attr);
                    551:               if (length > 0)
                    552:                 {
                    553:                   /* get the text leaf */
                    554:                   leaf = TtaGetFirstChild (child);
                    555:                   if (leaf != NULL)
                    556:                     {
                    557:                       childType = TtaGetElementType (leaf);
                    558:                       if (childType.ElTypeNum == HTML_EL_TEXT_UNIT)
                    559:                         {
                    560:                           /* copy attribute value into the text leaf */
1.37      cvs       561:                           text = TtaGetMemory (length + 1);
1.6       cvs       562:                           TtaGiveTextAttributeValue (attr, text, &length);
                    563:                           TtaSetTextContent (leaf, text, 
                    564:                                              TtaGetDefaultLanguage (), doc);
                    565:                           TtaFreeMemory (text);
                    566:                         }
                    567:                     }
                    568:                 }
                    569:             }
                    570:         }
                    571:        break;
                    572:        
                    573:      case HTML_EL_META:
1.15      cvs       574:        ParseCharset (el, doc);
1.6       cvs       575:        break;
                    576: 
                    577:      case HTML_EL_STYLE_:      /* it's a STYLE element */
1.8       cvs       578:      case HTML_EL_SCRIPT:      /* it's a SCRIPT element */
1.6       cvs       579:      case HTML_EL_Preformatted:        /* it's a PRE */
                    580:        /* if the last line of the Preformatted is empty, remove it */
                    581:        leaf = XmlLastLeafInElement (el);
                    582:        if (leaf != NULL)
                    583:         {
                    584:           elType = TtaGetElementType (leaf);
                    585:           if (elType.ElTypeNum == HTML_EL_TEXT_UNIT)
                    586:             /* the last leaf is a TEXT element */
                    587:             {
                    588:               length = TtaGetTextLength (leaf);
                    589:               if (length > 0)
                    590:                 {
                    591:                   TtaGiveSubString (leaf, lastChar, length, 1);
                    592:                   if (lastChar[0] == EOL)
                    593:                     /* last character is new line, delete it */
                    594:                     {
                    595:                       if (length == 1)
                    596:                         /* empty TEXT element */
                    597:                         TtaDeleteTree (leaf, doc);
                    598:                       else
                    599:                         /* remove the last character */
                    600:                         TtaDeleteTextContent (leaf, length, 1, doc);
                    601:                     }
                    602:                 }
                    603:             }
                    604:         }
                    605:        if (IsParsingCSS ())
                    606:         {
                    607:           text = GetStyleContents (el);
                    608:           if (text)
                    609:             {
1.42      cvs       610:               ReadCSSRules (doc, NULL, text,
                    611:                             TtaGetElementLineNumber (el), FALSE);
1.6       cvs       612:               TtaFreeMemory (text);
                    613:             }
                    614:           SetParsingCSS (FALSE);
                    615:         }
                    616:        /* and continue as if it were a Preformatted or a Script */
                    617:        break;
                    618:        
                    619:      case HTML_EL_Text_Area:   /* it's a Text_Area */
                    620:        SetParsingTextArea (FALSE);
                    621:        child = TtaGetFirstChild (el);
                    622:        if (child == NULL)
                    623:         /* it's an empty Text_Area */
                    624:         /* insert a Inserted_Text element in the element */
                    625:         {
                    626:           newElType.ElTypeNum = HTML_EL_Inserted_Text;
                    627:           child = TtaNewTree (doc, newElType, "");
                    628:           TtaInsertFirstChild (&child, el, doc);
                    629:         }
                    630:        else
                    631:         {
                    632:           /* save the text into Default_Value attribute */
                    633:           attrType.AttrSSchema = docSSchema;
                    634:           attrType.AttrTypeNum = HTML_ATTR_Default_Value;
                    635:           if (TtaGetAttribute (el, attrType) == NULL)
                    636:             /* attribute Default_Value is missing */
                    637:             {
                    638:               attr = TtaNewAttribute (attrType);
                    639:               TtaAttachAttribute (el, attr, doc);
                    640:               desc = TtaGetFirstChild (child);
                    641:               length = TtaGetTextLength (desc) + 1;
1.37      cvs       642:               text = TtaGetMemory (length);
1.6       cvs       643:               TtaGiveTextContent (desc, text, &length, &lang);
                    644:               TtaSetAttributeText (attr, text, el, doc);
                    645:               TtaFreeMemory (text);
                    646:             }
                    647:         }
                    648:        /* insert a Frame element */
                    649:        newElType.ElTypeNum = HTML_EL_Frame;
                    650:        constElem = TtaNewTree (doc, newElType, "");
                    651:        TtaInsertSibling (constElem, child, FALSE, doc);
                    652:        break;
                    653:        
                    654:      case HTML_EL_Radio_Input:
                    655:      case HTML_EL_Checkbox_Input:
                    656:        /* put an attribute Checked if it is missing */
                    657:        attrType.AttrSSchema = docSSchema;
                    658:        attrType.AttrTypeNum = HTML_ATTR_Checked;
                    659:        if (TtaGetAttribute (el, attrType) == NULL)
                    660:         /* attribute Checked is missing */
                    661:         {
                    662:           attr = TtaNewAttribute (attrType);
                    663:           TtaAttachAttribute (el, attr, doc);
                    664:           TtaSetAttributeValue (attr, HTML_ATTR_Checked_VAL_No_, el, doc);
                    665:         }
                    666:        break;
                    667:        
                    668:      case HTML_EL_Option_Menu:
                    669:        /* Check that at least one option has a SELECTED attribute */
                    670:        OnlyOneOptionSelected (el, doc, TRUE);
                    671:        break;
                    672: 
                    673:      case HTML_EL_PICTURE_UNIT:
                    674:        break;
                    675:        
                    676:      case HTML_EL_LINK:
                    677:        CheckCSSLink (el, doc, docSSchema);
                    678:        break;
                    679:        
                    680:      case HTML_EL_Data_cell:
                    681:      case HTML_EL_Heading_cell:
                    682:        /* insert a pseudo paragraph into empty cells */
                    683:        child = TtaGetFirstChild (el);
                    684:        if (child == NULL)
                    685:         {
                    686:           elType.ElTypeNum = HTML_EL_Pseudo_paragraph;
                    687:           child = TtaNewTree (doc, elType, "");
                    688:           if (child != NULL)
                    689:               TtaInsertFirstChild (&child, el, doc);
                    690:         }
                    691:        
                    692:        /* detect whether we're parsing a whole table or just a cell */
                    693:        if (IsWithinTable ())
                    694:           NewCell (el, doc, FALSE);
                    695:        break;
                    696:        
                    697:      case HTML_EL_Table:
                    698:        CheckTable (el, doc);
                    699:        SubWithinTable ();
                    700:        break;
                    701:        
                    702:      case HTML_EL_TITLE:
                    703:        /* show the TITLE in the main window */
                    704:        UpdateTitle (el, doc);
                    705:        break;
1.41      cvs       706: 
                    707:      case HTML_EL_rbc:
                    708:        /* an rbc element has been read. Its parent should be a complex_ruby.
                    709:          Change the type of the parent, as simple_ruby are created by
                    710:          default */
                    711:        parent = TtaGetParent (el);
                    712:        if (parent)
                    713:         {
                    714:           newElType = TtaGetElementType (parent);
                    715:           if (newElType.ElSSchema == elType.ElSSchema &&
                    716:               newElType.ElTypeNum == HTML_EL_simple_ruby)
                    717:              ChangeElementType (parent, HTML_EL_complex_ruby);
                    718:         }
                    719:        break;
                    720: 
                    721:      case HTML_EL_rtc1:
                    722:        /* an rtc element has been parsed. If it has already a rtc1 sibling,
                    723:          change its type to rtc2 */
                    724:        prev = el;
                    725:        do
                    726:         {
                    727:           TtaPreviousSibling(&prev);
                    728:           if (prev)
                    729:             {
                    730:               newElType = TtaGetElementType (prev);
                    731:               if (newElType.ElSSchema == elType.ElSSchema &&
                    732:                   newElType.ElTypeNum == HTML_EL_rtc1)
                    733:                 {
                    734:                   ChangeElementType (el, HTML_EL_rtc2);
                    735:                   prev = NULL;
                    736:                 }
                    737:             }
                    738:         }
                    739:        while (prev);
                    740:        break;
                    741: 
1.6       cvs       742:      default:
                    743:        break;
                    744:      }
                    745: }
1.1       cvs       746: 
                    747: /*----------------------------------------------------------------------
1.30      cvs       748:    PutInContent    
                    749:    Put the string ChrString in the leaf of current element.
                    750:   ----------------------------------------------------------------------*/
1.39      cvs       751: Element         PutInContent (char *ChrString, ParserData *context)
1.30      cvs       752: 
                    753: {
                    754:    Element      el, child;
                    755:    ElementType  elType;
                    756:    int          length;
                    757: 
                    758:    el = NULL;
                    759:    if (context->lastElement != NULL)
                    760:      {
                    761:        /* search first leaf of current element */
                    762:        el = context->lastElement;
                    763:        do
                    764:          {
                    765:             child = TtaGetFirstChild (el);
                    766:             if (child != NULL)
                    767:                el = child;
                    768:          }
                    769:        while (child != NULL);
                    770:        elType = TtaGetElementType (el);
                    771:        length = 0;
                    772:        if (elType.ElTypeNum == 1)
                    773:           length = TtaGetTextLength (el);
                    774:        if (length == 0)
                    775:           TtaSetTextContent (el, ChrString, context->language, context->doc);
                    776:        else
                    777:           TtaAppendTextContent (el, ChrString, context->doc);
                    778:      }
                    779:    return el;
                    780: }
                    781: 
                    782: /*----------------------------------------------------------------------
                    783:    CreateHTMLAttribute
                    784:    create an attribute of type attrType for the element el.
                    785:   ----------------------------------------------------------------------*/
                    786: void           CreateHTMLAttribute (Element       el,
                    787:                                    AttributeType attrType,
1.46    ! cvs       788:                                    char*         text,
1.30      cvs       789:                                    ThotBool      isInvalid,
                    790:                                    Document      doc,
                    791:                                    Attribute    *lastAttribute,
                    792:                                    Element      *lastAttrElement)
                    793:      
                    794: {
                    795:    int         attrKind;
                    796:    int         length;
1.39      cvs       797:    char       *buffer;
1.30      cvs       798:    Attribute   attr, oldAttr;
                    799: 
                    800:    if (attrType.AttrTypeNum != 0)
                    801:      {
                    802:        oldAttr = TtaGetAttribute (el, attrType);
                    803:        if (oldAttr != NULL)
                    804:         /* this attribute already exists */
                    805:         attr = oldAttr;
                    806:        else
                    807:         /* create a new attribute and attach it to the element */
                    808:         {
                    809:           attr = TtaNewAttribute (attrType);
                    810:           TtaAttachAttribute (el, attr, doc);
                    811:         }
                    812:        *lastAttribute = attr;
                    813:        *lastAttrElement = el;
                    814: 
                    815:        TtaGiveAttributeType (attr, &attrType, &attrKind);
                    816:        if (attrKind == 0)      /* enumerate */
                    817:         TtaSetAttributeValue (attr, 1, el, doc);
                    818: 
                    819:        /* attribute BORDER without any value (ThotBool attribute) is */
                    820:        /* considered as BORDER=1 */
                    821:        if (attrType.AttrTypeNum == HTML_ATTR_Border)
                    822:         TtaSetAttributeValue (attr, 1, el, doc);
                    823: 
                    824:        if (isInvalid)
                    825:         /* Copy the name of the invalid attribute as the content */
                    826:         /* of the Invalid_attribute attribute. */
                    827:         {
1.37      cvs       828:           length = strlen (text) + 2;
1.30      cvs       829:           length += TtaGetTextAttributeLength (attr);
1.37      cvs       830:           buffer = TtaGetMemory (length + 1);
1.30      cvs       831:           TtaGiveTextAttributeValue (attr, buffer, &length);
1.37      cvs       832:           strcat (buffer, " ");
                    833:           strcat (buffer, text);
1.30      cvs       834:           TtaSetAttributeText (attr, buffer, el, doc);
                    835:           TtaFreeMemory (buffer);
                    836:         }
                    837:      }
                    838: }
                    839: 
                    840: /*----------------------------------------------------------------------
                    841:    HTMLTypeAttrValue
                    842:    Value val has been read for the HTML attribute TYPE.
                    843:    Create a child for the current Thot element INPUT accordingly.
                    844:   ----------------------------------------------------------------------*/
1.46    ! cvs       845: void               HTMLTypeAttrValue (char       *val,
1.30      cvs       846:                                      Attribute   lastAttribute,
                    847:                                      Element     lastAttrElement,
                    848:                                      ParserData *context)
                    849: 
                    850: {
                    851:   ElementType      elType;
                    852:   Element          newChild;
                    853:   AttributeType    attrType;
                    854:   Attribute        attr;
1.39      cvs       855:   char             msgBuffer[MaxMsgLength];
1.30      cvs       856:   int              value;
                    857:   int              numberOfLinesRead;
                    858: 
                    859:   value = MapAttrValue (DummyAttribute, val);
                    860:   if (value < 0)
                    861:     {
1.37      cvs       862:       if (strlen (val) > MaxMsgLength - 40)
                    863:          val[MaxMsgLength - 40] = EOS;
                    864:       sprintf (msgBuffer, "Unknown attribute value \"type = %s\"", val);
1.42      cvs       865:       HTMLParseError (context->doc, msgBuffer);
1.30      cvs       866:       attrType.AttrSSchema = TtaGetDocumentSSchema (context->doc);
                    867:       attrType.AttrTypeNum = pHTMLAttributeMapping[0].ThotAttribute;
1.37      cvs       868:       sprintf (msgBuffer, "type=%s", val);
1.30      cvs       869:       CreateHTMLAttribute (context->lastElement, attrType, msgBuffer, TRUE,
                    870:                           context->doc, &lastAttribute, &lastAttrElement);
                    871:     }
                    872:   else
                    873:     {
                    874:       elType = TtaGetElementType (context->lastElement);
                    875:       if (elType.ElTypeNum != HTML_EL_Input)
                    876:        {
1.37      cvs       877:          if (strlen (val) > MaxMsgLength - 40)
                    878:            val[MaxMsgLength - 40] = EOS;
                    879:          sprintf (msgBuffer, "Duplicate attribute \"type = %s\"", val);
1.30      cvs       880:        }
                    881:       else
                    882:        {
                    883:          elType.ElSSchema = TtaGetDocumentSSchema (context->doc);
                    884:          elType.ElTypeNum = value;
                    885:          newChild = TtaNewTree (context->doc, elType, "");
                    886:          numberOfLinesRead = 0;
                    887:          TtaSetElementLineNumber (newChild, numberOfLinesRead);
                    888:          TtaInsertFirstChild (&newChild, context->lastElement, context->doc);
                    889:          if (value == HTML_EL_PICTURE_UNIT)
                    890:            {
                    891:              /* add the attribute IsInput to input pictures */
                    892:              attrType.AttrSSchema = elType.ElSSchema;
                    893:              attrType.AttrTypeNum = HTML_ATTR_IsInput;
                    894:              attr = TtaNewAttribute (attrType);
                    895:              TtaAttachAttribute (newChild, attr, context->doc);
                    896:            }
                    897:        }
                    898:     }
                    899: }
                    900: 
                    901: /*----------------------------------------------------------------------
                    902:    XhtmlTypeAttrValue 
                    903:    Value val has been read for the HTML attribute TYPE.
                    904:    Create a child for the current Thot element INPUT accordingly.
                    905:   ----------------------------------------------------------------------*/
1.46    ! cvs       906: void              XhtmlTypeAttrValue (char       *val,
1.30      cvs       907:                                      Attribute   currentAttribute,
                    908:                                      Element     lastAttrElement,
                    909:                                      ParserData *context)
                    910: 
                    911: {
                    912:   ElementType     elType;
                    913:   Element         newChild;
                    914:   AttributeType   attrType;
                    915:   Attribute       attr;
1.39      cvs       916:   char            msgBuffer[MaxMsgLength];
1.30      cvs       917:   int             value;
                    918:   int             attrKind;
                    919:   ThotBool        level;
                    920: 
                    921:   attrType.AttrTypeNum = DummyAttribute;
                    922:   MapHTMLAttributeValue (val, attrType, &value);
                    923:   if (value < 0)
                    924:     {
1.37      cvs       925:       sprintf (msgBuffer, "Unknown attribute value \"type=%s\"", val);
1.30      cvs       926:       XmlParseError (errorParsing, msgBuffer, 0);
1.36      cvs       927:       MapHTMLAttribute ("unknown_attr", &attrType, NULL,
1.30      cvs       928:                        &level, context->doc);
1.37      cvs       929:       sprintf (msgBuffer, "type=%s", val);
1.30      cvs       930:       CreateHTMLAttribute (context->lastElement, attrType, msgBuffer, TRUE,
                    931:                           context->doc, &currentAttribute, &lastAttrElement);
                    932:     }
                    933:   else
                    934:     {
                    935:       elType = TtaGetElementType (context->lastElement);
                    936:       if (elType.ElTypeNum != HTML_EL_Input)
                    937:        {
1.37      cvs       938:          sprintf (msgBuffer, "Duplicate attribute \"type = %s\"", val);
1.30      cvs       939:          XmlParseError (errorParsing, msgBuffer, 0);
                    940:        }
                    941:       else
                    942:        {
                    943:          elType.ElTypeNum = value;
                    944:          newChild = TtaNewTree (context->doc, elType, "");
                    945:          XmlSetElemLineNumber (newChild);
                    946:          TtaInsertFirstChild (&newChild, context->lastElement, context->doc);
                    947:          if (value == HTML_EL_PICTURE_UNIT)
                    948:            {
                    949:              /* add the attribute IsInput to input pictures */
                    950:              attrType.AttrSSchema = elType.ElSSchema;
                    951:              attrType.AttrTypeNum = HTML_ATTR_IsInput;
                    952:              attr = TtaNewAttribute (attrType);
                    953:              TtaAttachAttribute (newChild, attr, context->doc);
                    954:            }
                    955:        }
                    956:     }
                    957: }
                    958: 
                    959: /*----------------------------------------------------------------------
                    960:    CreateAttrWidthPercentPxl
                    961:    an HTML attribute "width" has been created for a Table of a HR.
                    962:    Create the corresponding attribute IntWidthPercent or IntWidthPxl.
                    963:    oldWidth is -1 or the old image width.
                    964:   ----------------------------------------------------------------------*/
1.39      cvs       965: void              CreateAttrWidthPercentPxl (char *buffer, Element el,
1.30      cvs       966:                                             Document doc, int oldWidth)
                    967: 
                    968: {
                    969:   AttributeType   attrTypePxl, attrTypePercent;
                    970:   Attribute       attrOld, attrNew;
                    971:   int             length, val;
1.39      cvs       972:   char            msgBuffer[MaxMsgLength];
1.30      cvs       973:   ElementType    elType;
                    974:   int             w, h;
                    975:   ThotBool        isImage;
                    976: 
                    977:   elType = TtaGetElementType (el);
                    978:   isImage = (elType.ElTypeNum == HTML_EL_PICTURE_UNIT ||
                    979:             elType.ElTypeNum == HTML_EL_Data_cell ||
                    980:             elType.ElTypeNum == HTML_EL_Heading_cell);
                    981: 
                    982:   /* remove trailing spaces */
1.37      cvs       983:   length = strlen (buffer) - 1;
1.30      cvs       984:   while (length > 0 && buffer[length] <= SPACE)
                    985:     length--;
                    986:   attrTypePxl.AttrSSchema = TtaGetDocumentSSchema (doc);
                    987:   attrTypePercent.AttrSSchema = TtaGetDocumentSSchema (doc);
                    988:   attrTypePxl.AttrTypeNum = HTML_ATTR_IntWidthPxl;
                    989:   attrTypePercent.AttrTypeNum = HTML_ATTR_IntWidthPercent;
                    990:   /* is the last character a '%' ? */
                    991:   if (buffer[length] == '%')
                    992:     {
                    993:       /* remove IntWidthPxl */
                    994:       attrOld = TtaGetAttribute (el, attrTypePxl);
                    995:       /* update IntWidthPercent */
                    996:       attrNew = TtaGetAttribute (el, attrTypePercent);
                    997:       if (attrNew == NULL)
                    998:        {
                    999:          attrNew = TtaNewAttribute (attrTypePercent);
                   1000:          TtaAttachAttribute (el, attrNew, doc);
                   1001:        }
                   1002:       else if (isImage && oldWidth == -1)
                   1003:        {
                   1004:          if (attrOld == NULL)
                   1005:            oldWidth = TtaGetAttributeValue (attrNew);
                   1006:          else
                   1007:            oldWidth = TtaGetAttributeValue (attrOld);
                   1008:        }
                   1009:     }
                   1010:   else
                   1011:     {
                   1012:       /* remove IntWidthPercent */
                   1013:       attrOld = TtaGetAttribute (el, attrTypePercent);
                   1014:       /* update IntWidthPxl */
                   1015:       attrNew = TtaGetAttribute (el, attrTypePxl);
                   1016:       if (attrNew == NULL)
                   1017:        {
                   1018:          attrNew = TtaNewAttribute (attrTypePxl);
                   1019:          TtaAttachAttribute (el, attrNew, doc);
                   1020:        }
                   1021:       else if (isImage && oldWidth == -1)
                   1022:        {
                   1023:          TtaGiveBoxSize (el, doc, 1, UnPixel, &w, &h);
                   1024:          if (attrOld == NULL)
                   1025:            oldWidth = w * TtaGetAttributeValue (attrNew) / 100;
                   1026:          else
                   1027:            oldWidth = w * TtaGetAttributeValue (attrOld) / 100;          
                   1028:        }
                   1029:     }
                   1030: 
                   1031:   if (attrOld != NULL)
                   1032:     TtaRemoveAttribute (el, attrOld, doc);
1.43      cvs      1033:   if (sscanf (buffer, "%d", &val))
1.30      cvs      1034:     TtaSetAttributeValue (attrNew, val, el, doc);
                   1035:   else
                   1036:     /* its not a number. Delete attribute and send an error message */
                   1037:     {
                   1038:     TtaRemoveAttribute (el, attrNew, doc);
1.37      cvs      1039:     if (strlen (buffer) > MaxMsgLength - 30)
1.30      cvs      1040:         buffer[MaxMsgLength - 30] = EOS;
1.37      cvs      1041:     sprintf (msgBuffer, "Invalid attribute value \"%s\"", buffer);
1.42      cvs      1042:     HTMLParseError (doc, msgBuffer);
1.30      cvs      1043:     }
                   1044:   if (isImage)
                   1045:     UpdateImageMap (el, doc, oldWidth, -1);
                   1046: }
                   1047: 
                   1048: /*----------------------------------------------------------------------
                   1049:    CreateAttrIntSize
                   1050:    an HTML attribute "size" has been created for a Font element.
                   1051:    Create the corresponding internal attribute.
                   1052:   ----------------------------------------------------------------------*/
1.46    ! cvs      1053: void              CreateAttrIntSize (char *buffer, Element el, Document doc)
1.30      cvs      1054: 
                   1055: {
                   1056:    AttributeType  attrType;
                   1057:    int            val, ind, factor, delta;
                   1058:    Attribute      attr;
1.37      cvs      1059:    char         msgBuffer[MaxMsgLength];
1.30      cvs      1060: 
                   1061:    /* is the first character a '+' or a '-' ? */
                   1062:    ind = 0;
                   1063:    factor = 1;
                   1064:    delta = 0;
                   1065:    if (buffer[0] == '+')
                   1066:      {
                   1067:        attrType.AttrTypeNum = HTML_ATTR_IntSizeIncr;
                   1068:        ind++;
                   1069:        factor = 2;
                   1070:      }
                   1071:    else if (buffer[0] == '-')
                   1072:      {
                   1073:        attrType.AttrTypeNum = HTML_ATTR_IntSizeDecr;
                   1074:        ind++;
                   1075:        factor = 2;
                   1076:      }
                   1077:    else
                   1078:      {
                   1079:        attrType.AttrTypeNum = HTML_ATTR_IntSizeRel;
                   1080:        delta = 1;
                   1081:      }
                   1082:    attrType.AttrSSchema = TtaGetDocumentSSchema (doc);
                   1083:    attr = TtaGetAttribute (el, attrType);
1.43      cvs      1084:    if (sscanf (&buffer[ind], "%d", &val))
1.30      cvs      1085:      {
                   1086:        val = val * factor + delta;
                   1087:        if (attr == NULL)
                   1088:         {
                   1089:           /* this attribute doesn't exist, create it */
                   1090:           attr = TtaNewAttribute (attrType);
                   1091:           TtaAttachAttribute (el, attr, doc);
                   1092:         }
                   1093:        TtaSetAttributeValue (attr, val, el, doc);
                   1094:      }
                   1095:    else
                   1096:      /* its not a number. Delete attribute and send an error message */
                   1097:      {
                   1098:        if (attr)
                   1099:          TtaRemoveAttribute (el, attr, doc);
1.37      cvs      1100:        if (strlen (buffer) > MaxMsgLength - 30)
1.30      cvs      1101:          buffer[MaxMsgLength - 30] = EOS;
1.37      cvs      1102:        sprintf (msgBuffer, "Invalid attribute value \"%s\"", buffer);
1.42      cvs      1103:        HTMLParseError (doc, msgBuffer);
1.30      cvs      1104:      }
                   1105: }
                   1106: /*----------------------------------------------------------------------
                   1107:    EndOfHTMLAttributeValue
                   1108:    Filling of an HTML attribute value
                   1109:   ----------------------------------------------------------------------*/
1.46    ! cvs      1110: void               EndOfHTMLAttributeValue (char       *attrValue,
1.30      cvs      1111:                                            AttributeMapping *lastMappedAttr,
                   1112:                                            Attribute   currentAttribute,
                   1113:                                            Element     lastAttrElement,
                   1114:                                            ThotBool    UnknownAttr,
                   1115:                                            ParserData *context,
                   1116:                                            ThotBool    isXML)
                   1117: 
                   1118: {
                   1119:    AttributeType   attrType, attrType1;
                   1120:    Attribute       attr;
                   1121:    ElementType    elType;
1.39      cvs      1122:    Element         child, root;
1.30      cvs      1123:    Language        lang;
1.39      cvs      1124:    char            translation;
1.30      cvs      1125:    char            shape;
1.39      cvs      1126:    char           *buffer;
                   1127:    char           *attrName;
1.30      cvs      1128:    int             val;
                   1129:    int             length;
                   1130:    int             attrKind;
                   1131:    ThotBool        done = FALSE;
                   1132:    ThotBool        level;
1.39      cvs      1133:    char            msgBuffer[MaxMsgLength];
1.30      cvs      1134: 
                   1135:    /* treatments of some particular HTML attributes */
1.37      cvs      1136:    if (!strcmp (lastMappedAttr->XMLattribute, "style"))
1.30      cvs      1137:      {
                   1138:        TtaSetAttributeText (currentAttribute, attrValue,
                   1139:                            lastAttrElement, context->doc);
                   1140:        ParseHTMLSpecificStyle (context->lastElement, attrValue,
                   1141:                               context->doc, 1, FALSE);
                   1142:        done = TRUE;
                   1143:      }
                   1144:    else
                   1145:      {
1.37      cvs      1146:        if (!strcmp (lastMappedAttr->XMLattribute, "link"))
1.30      cvs      1147:           HTMLSetAlinkColor (context->doc, attrValue);
1.37      cvs      1148:        else if (!strcmp (lastMappedAttr->XMLattribute, "alink"))
1.30      cvs      1149:         HTMLSetAactiveColor (context->doc, attrValue);
1.37      cvs      1150:        else if (!strcmp (lastMappedAttr->XMLattribute, "vlink"))
1.30      cvs      1151:         HTMLSetAvisitedColor (context->doc, attrValue);
                   1152:      }
                   1153: 
                   1154:    if (!done)
                   1155:      {
                   1156:        val = 0;
                   1157:        translation = lastMappedAttr->AttrOrContent;
                   1158: 
                   1159:        switch (translation)
                   1160:         {
                   1161:         case 'C':      /* Content */
                   1162:           child = PutInContent (attrValue, context);
                   1163:           if (child != NULL)
1.36      cvs      1164:               TtaAppendTextContent (child, "\" ", context->doc);
1.30      cvs      1165:           break;
                   1166: 
                   1167:         case 'A':
                   1168:           if (currentAttribute != NULL)
                   1169:             {
                   1170:               TtaGiveAttributeType (currentAttribute, &attrType, &attrKind);
                   1171:               switch (attrKind)
                   1172:                 {
                   1173:                 case 0:        /* enumerate */
                   1174:                   if (isXML)
                   1175:                     MapHTMLAttributeValue (attrValue, attrType, &val);
                   1176:                   else
                   1177:                     val = MapAttrValue (lastMappedAttr->ThotAttribute,
                   1178:                                         attrValue);
                   1179:                   if (val < 0)
                   1180:                     {
                   1181:                       TtaGiveAttributeType (currentAttribute,
                   1182:                                             &attrType, &attrKind);
                   1183:                       attrName = TtaGetAttributeName (attrType);
1.37      cvs      1184:                       sprintf (msgBuffer,
1.36      cvs      1185:                                 "Unknown attribute value \"%s = %s\"",
1.30      cvs      1186:                                 attrName, attrValue);
                   1187:                       if (isXML)
                   1188:                         XmlParseError (errorParsing, msgBuffer, 0);
                   1189:                       else
1.42      cvs      1190:                         HTMLParseError (context->doc, msgBuffer);
1.30      cvs      1191: 
                   1192:                       /* remove the attribute and replace it by an */
                   1193:                       /* Invalid_attribute */
                   1194:                       TtaRemoveAttribute (lastAttrElement,
                   1195:                                           currentAttribute, context->doc);
                   1196:                       if (isXML)
1.36      cvs      1197:                         MapHTMLAttribute ("unknown_attr", &attrType,
1.30      cvs      1198:                                           NULL, &level, context->doc);
                   1199:                       else
                   1200:                         {
                   1201:                           attrType.AttrSSchema = 
                   1202:                             TtaGetDocumentSSchema (context->doc);
                   1203:                           attrType.AttrTypeNum =
                   1204:                             pHTMLAttributeMapping[0].ThotAttribute;
                   1205:                         }
1.37      cvs      1206:                       sprintf (msgBuffer, "%s=%s", attrName, attrValue);
1.30      cvs      1207:                       CreateHTMLAttribute (lastAttrElement, attrType,
                   1208:                                            msgBuffer, TRUE, context->doc,
                   1209:                                            &currentAttribute, &lastAttrElement);
                   1210:                     }
                   1211:                   else
                   1212:                       TtaSetAttributeValue (currentAttribute, val,
                   1213:                                             lastAttrElement, context->doc);
                   1214:                   break;
                   1215:                 case 1:        /* integer */
                   1216:                   if (attrType.AttrTypeNum == HTML_ATTR_Border &&
1.37      cvs      1217:                       !strcasecmp (attrValue, "border"))
1.30      cvs      1218:                     {
                   1219:                       /* border="border" for a table */
                   1220:                       val = 1;
                   1221:                       TtaSetAttributeValue (currentAttribute, val,
                   1222:                                             lastAttrElement, context->doc);
                   1223:                     }
1.40      cvs      1224:                   else if (sscanf (attrValue, "%d", &val))
1.30      cvs      1225:                     TtaSetAttributeValue (currentAttribute, val,
                   1226:                                           lastAttrElement, context->doc);
                   1227:                   else
                   1228:                     {
                   1229:                       TtaRemoveAttribute (lastAttrElement, currentAttribute,
                   1230:                                           context->doc);
1.37      cvs      1231:                       sprintf (msgBuffer,
1.36      cvs      1232:                                 "Unknown attribute value \"%s\"",
1.30      cvs      1233:                                 attrValue);
                   1234:                       if (isXML)
                   1235:                         XmlParseError (errorParsing, msgBuffer, 0);
                   1236:                       else
1.42      cvs      1237:                         HTMLParseError (context->doc, msgBuffer);
1.30      cvs      1238:                     }
                   1239:                   break;
                   1240:                 case 2:        /* text */
                   1241:                   if (!UnknownAttr)
                   1242:                     {
                   1243:                       TtaSetAttributeText (currentAttribute, attrValue,
                   1244:                                            lastAttrElement, context->doc);
                   1245:                       if (attrType.AttrTypeNum == HTML_ATTR_Langue)
                   1246:                         {
                   1247:                           /* it's a LANG attribute value */
                   1248:                           lang = TtaGetLanguageIdFromName (attrValue);
                   1249:                           if (lang == 0)
                   1250:                             {
1.37      cvs      1251:                               sprintf (msgBuffer,
1.40      cvs      1252:                                        "warning - unsupported language: %s",
                   1253:                                        attrValue);
1.30      cvs      1254:                               if (isXML)
                   1255:                                 XmlParseError (errorParsing, msgBuffer, 0);
                   1256:                               else
1.42      cvs      1257:                                 HTMLParseError (context->doc, msgBuffer);
1.30      cvs      1258:                             }
                   1259:                           else
                   1260:                             {
                   1261:                               /* change current language */
                   1262:                               context->language = lang;
                   1263:                               if (isXML)
                   1264:                                 SetLanguagInXmlStack (lang);
                   1265:                               else
                   1266:                                 SetLanguagInHTMLStack (lang);
                   1267:                             }
1.39      cvs      1268:                           root = TtaGetRootElement (context->doc);
                   1269:                           if (lastAttrElement == root)
1.30      cvs      1270:                             /* it's a LANG attribute on the root element */
                   1271:                             /* set the RealLang attribute */
                   1272:                             {
                   1273:                               attrType1.AttrSSchema = TtaGetDocumentSSchema (context->doc);
                   1274:                               attrType1.AttrTypeNum = HTML_ATTR_RealLang;
1.44      cvs      1275:                               /* this attribute could be already present,
                   1276:                                  (lang and xml:lang attributes) */
                   1277:                               if (!TtaGetAttribute (lastAttrElement,
                   1278:                                                     attrType1))
                   1279:                                 /* it's not present. Add it */
                   1280:                                 {
                   1281:                                   attr = TtaNewAttribute (attrType1);
                   1282:                                   TtaAttachAttribute (lastAttrElement,
                   1283:                                                       attr, context->doc);
                   1284:                                   TtaSetAttributeValue (attr,
                   1285:                                                         HTML_ATTR_RealLang_VAL_Yes_,
                   1286:                                                         lastAttrElement,
                   1287:                                                         context->doc);
                   1288:                                 }
1.30      cvs      1289:                             }
                   1290:                         }
                   1291:                       else if (attrType.AttrTypeNum == HTML_ATTR_accesskey)
1.31      cvs      1292:                         TtaAddAccessKey (context->doc, (unsigned int)attrValue[0],
1.30      cvs      1293:                                          lastAttrElement);
                   1294:                     }
                   1295:                   else
                   1296:                     /* this is the content of an invalid attribute */
                   1297:                     /* append it to the current Invalid_attribute */
                   1298:                     {
1.37      cvs      1299:                       length = strlen (attrValue) + 2;
1.30      cvs      1300:                       length += TtaGetTextAttributeLength (currentAttribute);
1.37      cvs      1301:                       buffer = TtaGetMemory (length + 1);
1.30      cvs      1302:                       TtaGiveTextAttributeValue (currentAttribute,
                   1303:                                                  buffer, &length);
1.37      cvs      1304:                       strcat (buffer, "=");
                   1305:                       strcat (buffer, attrValue);
1.30      cvs      1306:                       TtaSetAttributeText (currentAttribute, buffer,
                   1307:                                            lastAttrElement, context->doc);
                   1308:                       TtaFreeMemory (buffer);
                   1309:                     }
                   1310:                   break;
                   1311:                 case 3:        /* reference */
                   1312:                   break;
                   1313:                 }
                   1314:             }
                   1315:           break;
                   1316:           
                   1317:         case SPACE:
                   1318:           if (isXML)
                   1319:             XhtmlTypeAttrValue (attrValue, currentAttribute,
                   1320:                                 lastAttrElement, context);
                   1321:           else
                   1322:             HTMLTypeAttrValue (attrValue, currentAttribute,
                   1323:                                lastAttrElement, context);
                   1324:           break;
                   1325: 
                   1326:         default:
                   1327:           break;
                   1328:         }
                   1329: 
                   1330:       if (lastMappedAttr->ThotAttribute == HTML_ATTR_Width__)
                   1331:         /* HTML attribute "width" for a table or a hr */
                   1332:         /* create the corresponding attribute IntWidthPercent or */
                   1333:         /* IntWidthPxl */
                   1334:         CreateAttrWidthPercentPxl (attrValue, lastAttrElement, context->doc, -1);
                   1335:       else
1.37      cvs      1336:         if (!strcmp (lastMappedAttr->XMLattribute, "size"))
1.30      cvs      1337:           {
                   1338:             TtaGiveAttributeType (currentAttribute, &attrType, &attrKind);
                   1339:             if (attrType.AttrTypeNum == HTML_ATTR_Font_size)
                   1340:                 CreateAttrIntSize (attrValue, lastAttrElement, context->doc);
                   1341:           }
                   1342:       else
1.37      cvs      1343:         if (!strcmp (lastMappedAttr->XMLattribute, "shape"))
1.30      cvs      1344:             {
                   1345:               child = TtaGetFirstChild (lastAttrElement);
                   1346:               if (child != NULL)
                   1347:                 {
                   1348:                   switch (val)
                   1349:                     {
                   1350:                     case HTML_ATTR_shape_VAL_rectangle:
                   1351:                       shape = 'R';
                   1352:                       break;
                   1353:                     case HTML_ATTR_shape_VAL_circle:
                   1354:                       shape = 'a';
                   1355:                       break;
                   1356:                     case HTML_ATTR_shape_VAL_polygon:
                   1357:                       shape = 'p';
                   1358:                       break;
                   1359:                     default:
                   1360:                       shape = SPACE;
                   1361:                       break;
                   1362:                     }
                   1363:                   TtaSetGraphicsShape (child, shape, context->doc);
                   1364:                 }
                   1365:             }
                   1366:           else
1.37      cvs      1367:             if (!strcmp (lastMappedAttr->XMLattribute, "value"))
1.30      cvs      1368:               {
                   1369:                 elType = TtaGetElementType (lastAttrElement);
                   1370:                 if (elType.ElTypeNum == HTML_EL_Text_Input ||
                   1371:                     elType.ElTypeNum == HTML_EL_Password_Input ||
                   1372:                     elType.ElTypeNum == HTML_EL_File_Input ||
                   1373:                     elType.ElTypeNum == HTML_EL_Input)
                   1374:                   /* create a Default_Value attribute with the same content */
                   1375:                   {
                   1376:                     attrType1.AttrSSchema = attrType.AttrSSchema;
                   1377:                     attrType1.AttrTypeNum = HTML_ATTR_Default_Value;
                   1378:                     attr = TtaNewAttribute (attrType1);
                   1379:                     TtaAttachAttribute (lastAttrElement, attr, context->doc);
                   1380:                     TtaSetAttributeText (attr, attrValue,
                   1381:                                          lastAttrElement, context->doc);
                   1382:                   }
                   1383:               }
                   1384: 
                   1385:        /* Some HTML attributes are equivalent to a CSS property:      */
                   1386:        /*      background     ->                   background         */
                   1387:        /*      bgcolor        ->                   background         */
                   1388:        /*      text           ->                   color              */
                   1389:        /*      color          ->                   color              */
                   1390:             else
1.37      cvs      1391:               if (!strcmp (lastMappedAttr->XMLattribute, "background"))
1.30      cvs      1392:                 {
1.37      cvs      1393:                   if (strlen (attrValue) > MaxMsgLength - 30)
                   1394:                       attrValue[MaxMsgLength - 30] = EOS;
                   1395:                   sprintf (msgBuffer, "background: url(%s)", attrValue);
1.30      cvs      1396:                   ParseHTMLSpecificStyle (context->lastElement, msgBuffer,
                   1397:                                           context->doc, 1, FALSE);
                   1398:                 }
                   1399:               else
1.37      cvs      1400:                 if (!strcmp (lastMappedAttr->XMLattribute, "bgcolor"))
1.30      cvs      1401:                     HTMLSetBackgroundColor (context->doc,
                   1402:                                             context->lastElement, attrValue);
                   1403:                 else
1.37      cvs      1404:                   if (!strcmp (lastMappedAttr->XMLattribute, "text") ||
                   1405:                       !strcmp (lastMappedAttr->XMLattribute, "color"))
1.30      cvs      1406:                     HTMLSetForegroundColor (context->doc,
                   1407:                                             context->lastElement, attrValue);
                   1408:      }
                   1409: }
                   1410: 
                   1411: /*----------------------------------------------------------------------
1.16      cvs      1412:    MapHTMLAttributeValue
1.2       cvs      1413:    Search in the Attribute Value Mapping Table the entry for the attribute
                   1414:    ThotAtt and its value AttrVal. Returns the corresponding Thot value.
1.1       cvs      1415:   ----------------------------------------------------------------------*/
1.39      cvs      1416: void    MapHTMLAttributeValue (char          *AttrVal,
1.30      cvs      1417:                               AttributeType  attrType,
                   1418:                               int           *value)
1.1       cvs      1419: {
1.45      cvs      1420:   int  i;
1.2       cvs      1421: 
1.45      cvs      1422:   *value = 0;
                   1423:   i = 0;
                   1424:   while (XhtmlAttrValueMappingTable[i].ThotAttr != attrType.AttrTypeNum &&
                   1425:         XhtmlAttrValueMappingTable[i].ThotAttr != 0)
                   1426:     i++;
                   1427:   if (XhtmlAttrValueMappingTable[i].ThotAttr == attrType.AttrTypeNum)
                   1428:     do
                   1429:       if (!strcmp (XhtmlAttrValueMappingTable[i].XMLattrValue, AttrVal))
                   1430:        *value = XhtmlAttrValueMappingTable[i].ThotAttrValue;
                   1431:       else 
                   1432:        i++;
                   1433:     while (*value <= 0 &&
                   1434:           XhtmlAttrValueMappingTable[i].ThotAttr == attrType.AttrTypeNum);
1.1       cvs      1435: }

Webmaster