Annotation of Amaya/amaya/templates.c, revision 1.145

1.1       cvs         1: /*
                      2:  *
1.100     vatton      3:  *  COPYRIGHT INRIA and W3C, 1996-2007
1.1       cvs         4:  *  Please first read the full copyright statement in file COPYRIGHT.
                      5:  *
                      6:  */
1.14      cvs         7:  
1.1       cvs         8: /*
1.51      francesc    9:  * Authors: Francesc Campoy Flores
1.1       cvs        10:  *
                     11:  */
                     12: 
                     13: #define THOT_EXPORT extern
                     14: #include "amaya.h"
                     15: #include "document.h"
1.99      kia        16: #include "undo.h"
1.90      kia        17: #include "containers.h"
                     18: #include "Elemlist.h"
1.92      kia        19: #include "templates.h"
                     20: 
1.90      kia        21: 
1.46      vatton     22: #ifdef TEMPLATES
                     23: #include "Template.h"
1.52      vatton     24: #include "templateDeclarations.h"
1.140     vatton     25: 
                     26: #include "html2thot_f.h"
1.122     kia        27: #include "templates_f.h"
1.89      kia        28: #include "templateUtils_f.h"
1.67      quint      29: #include "templateLoad_f.h"
                     30: #include "templateDeclarations_f.h"
1.76      vatton     31: #include "templateInstantiate_f.h"
1.145   ! kia        32: #include "Templatebuilder_f.h"
1.28      tollenae   33: #include "appdialogue_wx.h"
1.29      tollenae   34: #include "init_f.h"
1.46      vatton     35: #include "wxdialogapi_f.h"
1.60      francesc   36: #include "AHTURLTools_f.h"
1.52      vatton     37: #endif /* TEMPLATES */
1.1       cvs        38: 
1.87      kia        39: #include "fetchXMLname_f.h"
1.83      kia        40: #include "MENUconf.h"
                     41: 
                     42: /* Paths from which looking for templates.*/
                     43: static Prop_Templates_Path *TemplateRepositoryPaths;
                     44: 
1.87      kia        45: /*----------------------------------------------------------------------
                     46:   IsTemplateInstanceDocument: Test if a document is a template instance
                     47:   doc : Document to test
                     48:   return : TRUE if the document is a template instance
                     49:   ----------------------------------------------------------------------*/
1.106     vatton     50: ThotBool IsTemplateInstanceDocument(Document doc)
                     51: {
1.87      kia        52: #ifdef TEMPLATES
1.138     vatton     53:   return (DocumentMeta[doc] != NULL) && (DocumentMeta[doc]->template_url != NULL);
1.87      kia        54: #else  /* TEMPLATES */
1.88      cvs        55:   return FALSE;
1.87      kia        56: #endif /* TEMPLATES */
                     57: }
                     58: 
1.83      kia        59: /*----------------------------------------------------------------------
1.109     kia        60:   IsTemplateDocument: Test if a document is a template (not an instance)
                     61:   doc : Document to test
                     62:   return : TRUE if the document is an instance
                     63:   ----------------------------------------------------------------------*/
                     64: ThotBool IsTemplateDocument(Document doc)
                     65: {
                     66: #ifdef TEMPLATES
1.143     kia        67:   return (DocumentMeta[doc] != NULL && DocumentMeta[doc]->isTemplate);
1.109     kia        68: #else  /* TEMPLATES */
                     69:   return FALSE;
                     70: #endif /* TEMPLATES */
                     71: }
                     72: 
                     73: 
                     74: /*----------------------------------------------------------------------
1.108     vatton     75:   AllocTemplateRepositoryListElement: allocates an element for the list
                     76:   of template repositories.
1.83      kia        77:   path : path of the new element
                     78:   return : address of the new element
                     79:   ----------------------------------------------------------------------*/
                     80: void* AllocTemplateRepositoryListElement (const char* path, void* prevElement)
                     81: {
1.129     vatton     82:   Prop_Templates_Path *element;
                     83: 
                     84:   element  = (Prop_Templates_Path*)TtaGetMemory (sizeof(Prop_Templates_Path));
                     85:   memset (element, 0, sizeof(Prop_Templates_Path));
                     86:   strncpy (element->Path, path, MAX_LENGTH - 1);
1.83      kia        87:   if (prevElement)
1.129     vatton     88:     {
                     89:       element->NextPath = ((Prop_Templates_Path*)prevElement)->NextPath;
                     90:       ((Prop_Templates_Path*)prevElement)->NextPath = element;
                     91:     }
1.83      kia        92:   return element;
                     93: }
                     94: 
                     95: 
                     96: /*----------------------------------------------------------------------
                     97:   FreeTemplateRepositoryList: Free the list of template repositories.
                     98:   list : address of the list (address of the first element).
                     99:   ----------------------------------------------------------------------*/
                    100: void FreeTemplateRepositoryList (void* list)
                    101: {
1.131     vatton    102:   Prop_Templates_Path **l = (Prop_Templates_Path**) list;
                    103:   Prop_Templates_Path  *element = *l;
                    104: 
1.83      kia       105:   l = NULL;
                    106:   while (element)
                    107:   {
                    108:     Prop_Templates_Path* next = element->NextPath;
1.131     vatton    109:     TtaFreeMemory (element);
1.83      kia       110:     element = next;
                    111:   }
                    112: }
                    113: 
                    114: /*----------------------------------------------------------------------
                    115:   CopyTemplateRepositoryList: Copy a list of template repositories.
                    116:   src : address of the list (address of the first element).
                    117:   dst : address where copy the list
                    118:   ----------------------------------------------------------------------*/
1.91      vatton    119: static void CopyTemplateRepositoryList (const Prop_Templates_Path** src,
                    120:                                         Prop_Templates_Path** dst)
1.83      kia       121: {
                    122:   Prop_Templates_Path *element=NULL, *current=NULL;
                    123:   
1.131     vatton    124:   if (*src)
1.83      kia       125:   {
                    126:     *dst = (Prop_Templates_Path*) TtaGetMemory (sizeof(Prop_Templates_Path));
                    127:     (*dst)->NextPath = NULL;
                    128:     strcpy((*dst)->Path, (*src)->Path);
                    129:     
                    130:     element = (*src)->NextPath;
                    131:     current = *dst;
                    132:   }
                    133: 
1.106     vatton    134:   while (element)
                    135:     {
1.83      kia       136:     current->NextPath = (Prop_Templates_Path*) TtaGetMemory (sizeof(Prop_Templates_Path));
                    137:     current = current->NextPath; 
                    138:     current->NextPath = NULL;
                    139:     strcpy(current->Path, element->Path);
                    140:     element = element->NextPath;
1.106     vatton    141:     }
1.83      kia       142: }
                    143: 
                    144: /*----------------------------------------------------------------------
                    145:   LoadTemplateRepositoryList: Load the list of template repositories.
                    146:   list   : address of the list (address of the first element).
                    147:   return : the number of readed repository paths.
                    148:   ----------------------------------------------------------------------*/
                    149: static int LoadTemplateRepositoryList (Prop_Templates_Path** list)
                    150: {
                    151:   Prop_Templates_Path *element, *current = NULL;
                    152:   char *path, *homePath;
                    153:   unsigned char *c;
                    154:   int nb = 0;
                    155:   FILE *file;
                    156:   
1.131     vatton    157:   //clean up the curent list
                    158:   FreeTemplateRepositoryList (list);
                    159: 
                    160:   // open the file
1.83      kia       161:   path = (char *) TtaGetMemory (MAX_LENGTH);
1.86      vatton    162:   homePath       = TtaGetEnvString ("APP_HOME");
1.106     vatton    163:   sprintf (path, "%s%ctemplates.dat", homePath, DIR_SEP);
1.83      kia       164:   file = TtaReadOpen ((char *)path);
1.84      kia       165:   if (!file)
                    166:   {
                    167:     /* The config file dont exist, create it. */
                    168:     file = TtaWriteOpen ((char *)path);
1.122     kia       169:     fprintf (file, "http://www.w3.org/Amaya/Templates/cv.xtd\n");
1.144     vatton    170:     fprintf (file, "http://www.w3.org/Amaya/Templates/slides.xtd\n");
                    171:     fprintf (file, "http://www.w3.org/Amaya/Templates/ACM-Proc-Article.xtd\n");
1.84      kia       172:     TtaWriteClose (file);
                    173:     /* Retry to open it.*/
                    174:     file = TtaReadOpen ((char *)path);
                    175:   }
                    176:   
1.83      kia       177:   if (file)
1.129     vatton    178:     {
1.131     vatton    179:       // read the file
1.129     vatton    180:       c = (unsigned char*)path;
                    181:       *c = EOS;
                    182:       while (TtaReadByte (file, c))
                    183:         {
                    184:           if (*c == 13 || *c == EOL)
                    185:             *c = EOS;
                    186:           if (*c == EOS && c != (unsigned char*)path )
                    187:             {
                    188:               element = (Prop_Templates_Path*) TtaGetMemory (sizeof(Prop_Templates_Path));
                    189:               element->NextPath = NULL;
                    190:               strcpy (element->Path, path);
1.83      kia       191:         
1.129     vatton    192:               if (*list == NULL)
                    193:                 *list = element; 
                    194:               else
                    195:                 current->NextPath = element;
                    196:               current = element;
                    197:               nb++;
1.83      kia       198: 
1.129     vatton    199:               c = (unsigned char*) path;
                    200:               *c = EOS;
                    201:             }
                    202:           else
                    203:             c++;
                    204:         }
                    205:       if (c != (unsigned char*)path && *path != EOS)
                    206:         {
                    207:           element = (Prop_Templates_Path*) TtaGetMemory (sizeof(Prop_Templates_Path));
                    208:           *(c+1) = EOS;
                    209:           strcpy (element->Path, path);
                    210:           element->NextPath = NULL;
1.83      kia       211:       
1.129     vatton    212:           if (*list == NULL)
                    213:             *list = element; 
                    214:           else
                    215:             current->NextPath = element;
                    216:           nb++;
                    217:         }
                    218:       TtaReadClose (file);
1.83      kia       219:     }
                    220:   TtaFreeMemory(path);
                    221:   return nb;
                    222: }
                    223: 
                    224: /*----------------------------------------------------------------------
                    225:   SaveTemplateRepositoryList: Save the list of template repositories.
                    226:   list   : address of the list (address of the first element).
                    227:   ----------------------------------------------------------------------*/
                    228: static void SaveTemplateRepositoryList (const Prop_Templates_Path** list)
                    229: {
                    230:   const Prop_Templates_Path *element;
                    231:   char *path, *homePath;
                    232:   unsigned char *c;
                    233:   FILE *file;
                    234: 
                    235:   path = (char *) TtaGetMemory (MAX_LENGTH);
                    236:   homePath       = TtaGetEnvString ("APP_HOME");
1.106     vatton    237:   sprintf (path, "%s%ctemplates.dat", homePath, DIR_SEP);
1.83      kia       238: 
                    239:   file = TtaWriteOpen ((char *)path);
                    240:   c = (unsigned char*)path;
                    241:   *c = EOS;
                    242:   if (file)
                    243:   {
                    244:     element = *list;
                    245:     while (element)
                    246:     {
                    247:       fprintf(file, "%s\n", element->Path);
                    248:       element = element->NextPath;
                    249:     }
                    250:     TtaWriteClose (file);
                    251:   }
                    252: }
                    253: 
                    254: /*----------------------------------------------------------------------
                    255:   GetTemplateRepositoryList: Get the list of template repositories from template environment.
                    256:   list : address of the list (address of the first element).
                    257:   ----------------------------------------------------------------------*/
                    258: void GetTemplateRepositoryList (void* list)
                    259: {
                    260:   Prop_Templates_Path** l = (Prop_Templates_Path**) list;
                    261:   CopyTemplateRepositoryList((const Prop_Templates_Path**)&TemplateRepositoryPaths, l);
                    262: }
                    263: 
                    264: /*----------------------------------------------------------------------
                    265:   SetTemplateRepositoryList: Set the list of template repositories environment.
                    266:   list : address of the list (address of the first element).
                    267:   ----------------------------------------------------------------------*/
                    268: void SetTemplateRepositoryList (const void* list)
                    269: {
                    270:   const Prop_Templates_Path** l = (const Prop_Templates_Path**) list;
                    271:   CopyTemplateRepositoryList((const Prop_Templates_Path**)l, &TemplateRepositoryPaths);
                    272:   SaveTemplateRepositoryList((const Prop_Templates_Path**)&TemplateRepositoryPaths);
                    273: }
                    274: 
                    275: /*-----------------------------------------------------------------------
                    276:    InitTemplates
                    277:    Initializes the annotation library
                    278:   -----------------------------------------------------------------------*/
                    279: void InitTemplates ()
                    280: {
                    281:   TtaSetEnvBoolean ("SHOW_TEMPLATES", TRUE, FALSE);
1.131     vatton    282:   LoadTemplateRepositoryList (&TemplateRepositoryPaths);
1.83      kia       283: }
                    284: 
                    285: 
1.1       cvs       286: /*----------------------------------------------------------------------
1.51      francesc  287:   NewTemplate: Create the "new document from template" dialog
1.1       cvs       288:   ----------------------------------------------------------------------*/
1.18      cvs       289: void NewTemplate (Document doc, View view)
1.1       cvs       290: {
1.51      francesc  291: #ifdef TEMPLATES
1.76      vatton    292:   ThotBool     created;
1.28      tollenae  293: 
1.134     kia       294:   if (Templates_Map == NULL)
1.76      vatton    295:     InitializeTemplateEnvironment ();
                    296:   created = CreateNewTemplateDocDlgWX (BaseDialog + OpenTemplate,
1.61      francesc  297:                                       /*TtaGetViewFrame (doc, view)*/NULL, doc,
1.131     vatton    298:                                       TtaGetMessage (AMAYA, AM_NEW_TEMPLATE));
1.51      francesc  299:   
1.28      tollenae  300:   if (created)
1.25      vatton    301:     {
1.28      tollenae  302:       TtaSetDialoguePosition ();
                    303:       TtaShowDialogue (BaseDialog + OpenTemplate, TRUE);
1.25      vatton    304:     }
1.51      francesc  305: 
1.52      vatton    306: #endif /* TEMPLATES */
1.1       cvs       307: }
1.25      vatton    308: 
1.108     vatton    309: /*----------------------------------------------------------------------
                    310:   Load a template and create the instance file - update images and 
                    311:   stylesheets related to the template.
                    312:   ----------------------------------------------------------------------*/
                    313: void CreateInstanceOfTemplate (Document doc, char *templatename, char *docname)
                    314: {
                    315: #ifdef TEMPLATES
                    316: 
                    317:   char *s;
                    318:   ThotBool dontReplace = DontReplaceOldDoc;
                    319: 
                    320:   if (!IsW3Path (docname) && TtaFileExist (docname))
                    321:     {
                    322:       s = (char *)TtaGetMemory (strlen (docname) +
                    323:                                 strlen (TtaGetMessage (AMAYA, AM_OVERWRITE_CHECK)) + 2);
                    324:       sprintf (s, TtaGetMessage (AMAYA, AM_OVERWRITE_CHECK), docname);
                    325:       InitConfirm (0, 0, s);
                    326:       TtaFreeMemory (s);
                    327:       if (!UserAnswer)
                    328:         return;
                    329:     }
                    330: 
                    331:   LoadTemplate (0, templatename);
                    332:   DontReplaceOldDoc = dontReplace;
1.144     vatton    333:   CreateInstance (templatename, docname, doc);
1.108     vatton    334: #endif /* TEMPLATES */
                    335: }
                    336: 
1.53      vatton    337: 
1.109     kia       338: 
1.52      vatton    339: /*----------------------------------------------------------------------
1.107     kia       340:   PreventReloadingTemplate
                    341:   Prevent reloading a template.
                    342:   You must call AllowReloadingTemplate when finish.
                    343:   Usefull for reload an instance without reloading the template.
                    344:   ----------------------------------------------------------------------*/
                    345: void PreventReloadingTemplate(char* template_url)
                    346: {
                    347: #ifdef TEMPLATES
1.134     kia       348:   XTigerTemplate t = GetXTigerTemplate (template_url);
1.112     vatton    349:   if (t)
1.107     kia       350:     t->users++;
                    351: #endif /* TEMPLATES */
                    352: }
                    353: 
                    354: /*----------------------------------------------------------------------
                    355:   AllowReloadingTemplate
                    356:   Allow reloading a template.
                    357:   You must call it after each PreventReloadingTemplate call.
                    358:   ----------------------------------------------------------------------*/
                    359: void AllowReloadingTemplate(char* template_url)
                    360: {
                    361: #ifdef TEMPLATES
1.134     kia       362:   XTigerTemplate t = GetXTigerTemplate (template_url);
1.112     vatton    363:   if (t)
1.107     kia       364:     t->users--;  
                    365: #endif /* TEMPLATES */  
                    366: }
                    367: 
                    368: 
1.137     vatton    369: /*----------------------------------------------------------------------
                    370:   ----------------------------------------------------------------------*/
1.134     kia       371: ThotBool isEOSorWhiteSpace (const char c)
                    372: {
1.137     vatton    373:   return c == SPACE || c == TAB || c ==  EOL || c ==__CR__ || c == EOS;
                    374: }
                    375: ThotBool isWhiteSpace (const char c)
                    376: {
                    377:   return c == SPACE || c == TAB || c == EOL || c ==__CR__;
1.134     kia       378: }
                    379: 
1.107     kia       380: /*----------------------------------------------------------------------
1.87      kia       381:   giveItems : Lists type items from string
                    382:   example : "one two three" is extracted to {one, two, three}
                    383:   note : item type are setted to SimpleTypeNat
                    384:   text : text from which list items
                    385:   size : size of text in characters
                    386:   items : address of exctracted item list
                    387:   nbitems : items number in items list
1.52      vatton    388:   ----------------------------------------------------------------------*/
1.76      vatton    389: void giveItems (char *text, int size, struct menuType **items, int *nbitems)
1.1       cvs       390: {
1.70      quint     391: #ifdef TEMPLATES
1.52      vatton    392:        ThotBool         inElement = TRUE;
                    393:   struct menuType *menu;
                    394:   char            *iter;
                    395:        char             temp[128];
                    396:   int              i;
                    397:        int              labelSize;
1.28      tollenae  398: 
1.52      vatton    399:        *nbitems = 1;
                    400:        for (i = 0; i < size; i++)
                    401:     {
                    402:       if (isEOSorWhiteSpace (text[i]))
                    403:         {
                    404:           if (inElement)
                    405:             inElement = FALSE;
                    406:         }
                    407:       else if (!inElement)
                    408:         {
                    409:           inElement = TRUE;
                    410:           (*nbitems)++;
                    411:         }
                    412:     }
1.51      francesc  413: 
1.76      vatton    414:        menu = (struct menuType*) TtaGetMemory (sizeof (struct menuType)* *nbitems);
1.52      vatton    415:        iter = text;
                    416:        for (i = 0; i < *nbitems; i++)
                    417:     {          
                    418:       labelSize = 0;
1.137     vatton    419:       while (isWhiteSpace (*iter))
1.52      vatton    420:         iter++;
1.137     vatton    421:       if (*iter != EOS)
                    422:         {
                    423:           while (!isEOSorWhiteSpace (*iter))
                    424:             {
                    425:               temp[labelSize++] = *iter;
                    426:               iter++;
                    427:             }
1.52      vatton    428: 
1.137     vatton    429:           temp[labelSize] = EOS;
                    430:           menu[i].label = (char *) TtaStrdup (temp);
                    431:           menu[i].type = SimpleTypeNat;  /* @@@@@ ???? @@@@@ */
1.52      vatton    432:         }
                    433:     }
1.137     vatton    434:   *items = menu;
1.70      quint     435: #endif /* TEMPLATES */
1.28      tollenae  436: }
1.37      tollenae  437: 
1.70      quint     438: #ifdef TEMPLATES
1.52      vatton    439: /*----------------------------------------------------------------------
                    440:   ----------------------------------------------------------------------*/
                    441: static char *createMenuString (const struct menuType* items, const int nbItems)
                    442: {
                    443:   char *result, *iter;
                    444:        int   size = 0;
                    445:   int   i;
                    446: 
                    447:        for (i=0; i < nbItems; i++)
                    448:                size += 2 + strlen (items[i].label);
                    449: 
1.76      vatton    450:        result = (char *) TtaGetMemory (size);
1.52      vatton    451:        iter = result;
                    452:        for (i=0; i < nbItems; i++)
                    453:     {
                    454:       *iter = 'B';
                    455:       ++iter;
1.51      francesc  456:                
1.52      vatton    457:       strcpy (iter, items[i].label);
                    458:       iter += strlen (items[i].label)+1;
                    459:     }
1.51      francesc  460:        return result;
1.36      tollenae  461: }
1.71      quint     462: #endif /* TEMPLATES */
1.29      tollenae  463: 
1.71      quint     464: /*----------------------------------------------------------------------
                    465:   UseToBeCreated
                    466:   An new use element will be created by the user through some generic editing
                    467:   command
                    468:   -----------------------------------------------------------------------*/
                    469: ThotBool UseToBeCreated (NotifyElement *event)
                    470: {
                    471: #ifdef TEMPLATES
1.122     kia       472:   ElementType   parentType;
1.138     vatton    473:   SSchema       templateSSchema = TtaGetSSchema ("Template", event->document);  
1.130     vatton    474:   if (templateSSchema)
1.122     kia       475:   {
1.130     vatton    476:     parentType = TtaGetElementType (event->element);
                    477:     if (parentType.ElSSchema == templateSSchema &&
                    478:         parentType.ElTypeNum == Template_EL_repeat)
                    479:       return !Template_CanInsertRepeatChild (event->element);
                    480:     return TemplateElementWillBeCreated (event);
1.122     kia       481:   }
1.52      vatton    482: #endif /* TEMPLATES */
1.71      quint     483:   return FALSE; /* let Thot perform normal operation */
                    484: }
                    485: 
                    486: /*----------------------------------------------------------------------
                    487:   UseCreated
                    488:   A new "use" element has just been created by the user with a generic editing
                    489:   command.
                    490:   -----------------------------------------------------------------------*/
                    491: void UseCreated (NotifyElement *event)
                    492: {
                    493: #ifdef TEMPLATES
1.117     kia       494:        Document        doc = event->document;
                    495:        Element         el = event->element;
                    496:   Element         parent;
                    497:   Element         first;
                    498:   ElementType     parentType;
                    499:   XTigerTemplate  t;
                    500:   SSchema         templateSSchema;
1.130     vatton    501:   char*           types, *text = NULL;
1.117     kia       502:   
1.112     vatton    503:   if (!TtaGetDocumentAccessMode(doc))
1.110     kia       504:     return;
                    505: 
1.72      quint     506:   if (TtaGetFirstChild (el))
                    507:     /* this Use element has already some content. It has already been
                    508:        instanciated */
                    509:     return;
1.117     kia       510: 
1.134     kia       511:   t = GetXTigerTemplate (DocumentMeta[doc]->template_url);
1.71      quint     512:   if (!t)
                    513:     return; // no template ?!?!
1.101     kia       514: 
1.138     vatton    515:   templateSSchema = TtaGetSSchema ("Template", doc);
1.117     kia       516:   parent = TtaGetParent(el);
                    517:   parentType = TtaGetElementType(parent);
                    518:   
1.130     vatton    519:   if (parentType.ElSSchema == templateSSchema &&
                    520:       parentType.ElTypeNum == Template_EL_repeat)
1.117     kia       521:   {
1.130     vatton    522:     first = TtaGetFirstChild (parent);
                    523:     if (first)
1.117     kia       524:     {
1.130     vatton    525:       types = GetAttributeStringValueFromNum (first, Template_ATTR_types, NULL);
                    526:       if (types)
1.117     kia       527:       {
1.130     vatton    528:         SetAttributeStringValueWithUndo (el, Template_ATTR_types, types);
                    529:         text = GetAttributeStringValueFromNum (el, Template_ATTR_title, NULL);
                    530:         SetAttributeStringValueWithUndo (first, Template_ATTR_title, text);
                    531:         TtaFreeMemory (text);
                    532:         text = GetAttributeStringValueFromNum (el, Template_ATTR_currentType, NULL);
                    533:         SetAttributeStringValueWithUndo (first, Template_ATTR_currentType, text);
                    534:         TtaFreeMemory (text);
                    535:         TtaFreeMemory (types);
1.117     kia       536:       }
                    537:     }
                    538:   }
                    539: 
1.76      vatton    540:   InstantiateUse (t, el, doc, TRUE);
1.71      quint     541: #endif /* TEMPLATES */
                    542: }
1.29      tollenae  543: 
1.98      kia       544: /*----------------------------------------------------------------------
                    545:   Template_IncrementRepeatOccurNumber
                    546:   Increment the number of occurs of a xt:repeat
                    547:   @param el element (xt:repeat)
                    548:   ----------------------------------------------------------------------*/
                    549: void Template_IncrementRepeatOccurNumber(Element el)
                    550: {
                    551: #ifdef TEMPLATES
                    552:   char* current;
                    553:   char  newVal[8];
                    554:   int curVal;
                    555:   
1.104     kia       556:   current = GetAttributeStringValueFromNum(el, Template_ATTR_currentOccurs, NULL);
1.112     vatton    557:   if (current)
1.104     kia       558:   {
                    559:     curVal = atoi(current);
                    560:     curVal++;
                    561:     TtaFreeMemory(current);
                    562:     sprintf(newVal, "%d", curVal);
                    563:     SetAttributeStringValue(el, Template_ATTR_currentOccurs, newVal);
                    564:   }
1.98      kia       565: #endif /* TEMPLATES */
                    566: }
                    567: 
                    568: /*----------------------------------------------------------------------
                    569:   Template_DecrementRepeatOccurNumber
                    570:   Decrement the number of occurs of a xt:repeat
                    571:   @param el element (xt:repeat)
                    572:   ----------------------------------------------------------------------*/
                    573: void Template_DecrementRepeatOccurNumber(Element el)
                    574: {
                    575: #ifdef TEMPLATES
                    576:   char* current;
                    577:   char  newVal[8];
                    578:   int curVal;
                    579:   
1.104     kia       580:   current = GetAttributeStringValueFromNum(el, Template_ATTR_currentOccurs, NULL);
1.112     vatton    581:   if (current)
1.104     kia       582:   {
                    583:     curVal = atoi(current);
                    584:     curVal--;
                    585:     TtaFreeMemory(current);
                    586:     sprintf(newVal, "%d", curVal);
                    587:     SetAttributeStringValue(el, Template_ATTR_currentOccurs, newVal);
                    588:   }
1.98      kia       589: #endif /* TEMPLATES */
                    590: }
                    591: 
1.89      kia       592: 
1.98      kia       593: /*----------------------------------------------------------------------
                    594:   Template_CanInsertRepeatChild
                    595:   Test if a xt:repeat child can be inserted (number between params min and max).
                    596:   @param el element (xt:repeat) to test
                    597:   @return True if an element can be inserted.
                    598:   ----------------------------------------------------------------------*/
                    599: ThotBool Template_CanInsertRepeatChild(Element el)
                    600: {
                    601: #ifdef TEMPLATES
                    602:   char* max;
                    603:   char* current;
                    604:   int maxVal, curVal;
1.104     kia       605:   Element child;
1.98      kia       606:   
1.104     kia       607:   max = GetAttributeStringValueFromNum(el, Template_ATTR_maxOccurs, NULL);
1.105     vatton    608:   if (max)
1.104     kia       609:   {
1.112     vatton    610:     if (!strcmp(max, "*"))
1.105     vatton    611:       {
                    612:         TtaFreeMemory(max);
                    613:         return TRUE;
                    614:       }
                    615:     maxVal = atoi (max);
                    616:     TtaFreeMemory (max);
1.104     kia       617: 
                    618:     current = GetAttributeStringValueFromNum(el, Template_ATTR_currentOccurs, NULL);
1.105     vatton    619:     if (current)
1.104     kia       620:     {
1.105     vatton    621:       curVal = atoi (current);
                    622:       TtaFreeMemory (current);
1.104     kia       623:     }
                    624:     else
                    625:     {
                    626:       curVal = 0;
1.105     vatton    627:       for (child = TtaGetFirstChild(el); child; TtaNextSibling(&child))
1.104     kia       628:       {
                    629:         curVal++;
                    630:       }
                    631:     }
                    632:   
                    633:     return curVal<maxVal;
                    634:   }
                    635:   else
1.98      kia       636:     return TRUE;
                    637: #endif /* TEMPLATES */
                    638:   return FALSE;
                    639: }
1.96      kia       640: 
1.89      kia       641: 
                    642: /*----------------------------------------------------------------------
                    643:   Template_InsertRepeatChildAfter
                    644:   Insert a child to a xt:repeat
                    645:   The decl parameter must be valid and will not be verified. It must be a
                    646:     direct child element or the "use in the use" for union elements.
                    647:   @param el element (xt:repeat) in which insert a new element
                    648:   @param decl Template declaration of the element to insert
                    649:   @param elPrev Element (xt:use) after which insert the new elem, NULL if first.
                    650:   @return The inserted element 
                    651:   ----------------------------------------------------------------------*/
1.138     vatton    652: Element Template_InsertRepeatChildAfter (Document doc, Element el,
                    653:                                          Declaration decl, Element elPrev)
1.89      kia       654: {
                    655: #ifdef TEMPLATES
1.132     vatton    656:   Element     useFirst; /* First xt:use of the repeat.*/
                    657:   Element     use;      /* xt:use to insert.*/
1.89      kia       658:   ElementType useType;  /* type of xt:use.*/
                    659:   
1.138     vatton    660:   if (!TtaGetDocumentAccessMode (doc))
1.110     kia       661:     return NULL;
                    662: 
1.89      kia       663:   /* Copy xt:use with xt:types param */
1.138     vatton    664:   useFirst = TtaGetFirstChild (el);
                    665:   useType = TtaGetElementType (useFirst);
                    666:   use = TtaCopyElement (useFirst, doc, doc, el);
1.89      kia       667: 
                    668:   /* insert it */
1.112     vatton    669:   if (elPrev)
1.89      kia       670:     TtaInsertSibling(use, elPrev, FALSE, doc);
                    671:   else
                    672:     TtaInsertSibling(use, useFirst, TRUE, doc);
1.132     vatton    673:   Template_InsertUseChildren(doc, use, decl);
1.99      kia       674: 
1.138     vatton    675:   TtaRegisterElementCreate (use, doc);
                    676:   Template_IncrementRepeatOccurNumber (el);
1.89      kia       677:   return use;
1.93      cvs       678: #else /* TEMPLATES */
                    679:   return NULL;
1.89      kia       680: #endif /* TEMPLATES */
                    681: }
                    682: 
                    683: /*----------------------------------------------------------------------
                    684:   Template_InsertRepeatChild
                    685:   Insert a child to a xt:repeat
                    686:   The decl parameter must be valid and will not be verified. It must be a
                    687:     direct child element or the "use in the use" for union elements.
                    688:   @param el element (repeat) in which insert a new element
                    689:   @param decl Template declaration of the element to insert
                    690:   @param pos Position of insertion (0 before all, 1 after first ... -1 after all)
                    691:   @return The inserted element
                    692:   ----------------------------------------------------------------------*/
1.138     vatton    693: Element Template_InsertRepeatChild (Document doc, Element el, Declaration decl, int pos)
1.89      kia       694: {
1.118     kia       695: #ifdef TEMPLATES
1.116     kia       696:   if (!TtaGetDocumentAccessMode(doc) || !decl)
1.110     kia       697:     return NULL;
                    698:   
1.132     vatton    699:   if (pos == 0)
                    700:     return Template_InsertRepeatChildAfter (doc, el, decl, NULL);
                    701:   else if (pos == -1)
                    702:     return Template_InsertRepeatChildAfter (doc, el, decl, TtaGetLastChild(el));
1.89      kia       703:   else
                    704:   {
                    705:     Element elem = TtaGetFirstChild(el);
                    706:     pos--;
1.132     vatton    707:     while (pos > 0)
                    708:       {
                    709:         TtaNextSibling(&elem);
                    710:         pos--;
                    711:       }
1.138     vatton    712:     return Template_InsertRepeatChildAfter (doc, el, decl, elem);
1.89      kia       713:   }
1.118     kia       714: #else /* TEMPLATES */
1.116     kia       715:   return NULL;
1.118     kia       716: #endif /* TEMPLATES */
1.89      kia       717: }
                    718: 
1.116     kia       719: 
                    720: /*----------------------------------------------------------------------
                    721:   Template_InsertBagChild
                    722:   Insert a child to a xt:bag at the current insertion point.
                    723:   The decl parameter must be valid and will not be verified.
                    724:   @param el element (xt:bag) in which insert a new element
                    725:   @param decl Template declaration of the element to insert
                    726:   @return The inserted element
                    727:   ----------------------------------------------------------------------*/
1.138     vatton    728: Element Template_InsertBagChild (Document doc, Element el, Declaration decl)
1.116     kia       729: {
                    730: #ifdef TEMPLATES
1.138     vatton    731:   Element     sel;
1.116     kia       732:   ElementType newElType, selType;
                    733:   int start, end;
                    734: 
1.138     vatton    735:   if (!TtaGetDocumentAccessMode (doc) || !decl)
1.117     kia       736:     return NULL;
1.116     kia       737:   
1.138     vatton    738:   TtaGiveFirstSelectedElement (doc, &sel, &start, &end);
                    739:   if (TtaIsAncestor (sel, el))
1.116     kia       740:   {
1.138     vatton    741:     newElType.ElSSchema = TtaGetSSchema ("Template", doc);
                    742:     if (decl->nature == UnionNat)
1.116     kia       743:       newElType.ElTypeNum = Template_EL_useEl;
                    744:     else
                    745:       newElType.ElTypeNum = Template_EL_useSimple;
1.141     vatton    746: 
                    747:     selType = TtaGetElementType (sel);
                    748:     if (decl->blockLevel && 
                    749:         (TtaIsLeaf (selType) || !IsTemplateElement (sel)))
1.140     vatton    750:       {
                    751:         // force the insertion of a block level element at the right position
1.141     vatton    752:         while (sel && IsCharacterLevelElement (sel))
                    753:           sel = TtaGetParent (sel);
                    754:         if (sel)
                    755:           TtaSelectElement (doc, sel);
1.140     vatton    756:         TtaInsertAnyElement (doc, FALSE);
                    757:       }
1.138     vatton    758:     TtaInsertElement (newElType, doc);
                    759:     TtaGiveFirstSelectedElement (doc, &sel, &start, &end);
                    760:     if (sel)
1.116     kia       761:     {
1.138     vatton    762:       selType = TtaGetElementType (sel);
                    763:       TtaUnselect (doc);
1.117     kia       764:       
1.138     vatton    765:       if (selType.ElSSchema == newElType.ElSSchema &&
                    766:           selType.ElTypeNum == Template_EL_useSimple)
1.116     kia       767:       {
1.138     vatton    768:         SetAttributeStringValueWithUndo (sel, Template_ATTR_types, decl->name);
                    769:         SetAttributeStringValueWithUndo (sel, Template_ATTR_title, decl->name);
                    770:         Template_InsertUseChildren (doc, sel, decl);
1.116     kia       771:       }
1.117     kia       772:       return sel;
1.138     vatton    773:     }   
1.116     kia       774:   }
                    775: #endif /* TEMPLATES */
1.117     kia       776:   return NULL;
1.116     kia       777: }
                    778: 
                    779: 
1.92      kia       780: #ifdef TEMPLATES
1.99      kia       781: /*----------------------------------------------------------------------
                    782:   QueryStringFromMenu
                    783:   Show a context menu to query a choice.
                    784:   @param items space-separated choice list string.
                    785:   @return The choosed item string or NULL if none.
                    786:   ----------------------------------------------------------------------*/
1.138     vatton    787: static char* QueryStringFromMenu (Document doc, char* items)
1.90      kia       788: {
                    789:   int nbitems, size;
                    790:   struct menuType *itemlist;
                    791:   char *menuString;
                    792:   char *result = NULL;
                    793:   
1.138     vatton    794:   if (!TtaGetDocumentAccessMode (doc))
1.112     vatton    795:     return NULL;
                    796:   if (items == NULL)
1.110     kia       797:     return NULL;
1.138     vatton    798:   size = strlen (items);
                    799:   if (size == 0)
                    800:     return NULL;
1.90      kia       801:   giveItems (items, size, &itemlist, &nbitems);
                    802:   menuString = createMenuString (itemlist, nbitems);
                    803:   TtaNewScrollPopup (BaseDialog + OptionMenu, TtaGetViewFrame (doc, 1), NULL, 
                    804:                      nbitems, menuString , NULL, false, 'L');
                    805:   TtaFreeMemory (menuString);
                    806:   ReturnOption = -1;
                    807:   TtaShowDialogue (BaseDialog + OptionMenu, FALSE);
                    808:   TtaWaitShowProcDialogue ();
                    809:   TtaDestroyDialogue (BaseDialog + OptionMenu);
                    810:   
1.112     vatton    811:   if (ReturnOption!=-1)
1.90      kia       812:   {
                    813:     result = TtaStrdup(itemlist[ReturnOption].label);
                    814:   }
                    815:   
                    816:   TtaFreeMemory (itemlist);
                    817:   return result;
                    818: }
1.92      kia       819: #endif /* TEMPLATES */
1.90      kia       820: 
1.56      francesc  821: /*----------------------------------------------------------------------
1.138     vatton    822:   BagButtonClicked
                    823:   Called when a bag button is clicked.
                    824:   Can be called for useEl, useSimple or bag.
                    825:   If called for useEl or useSimple, the new element must be added after.
                    826:   If called for bag, the element must be added before all.
                    827:    
                    828:   Shows a menu with all the types that can be used in the bag.
                    829:   ----------------------------------------------------------------------*/
                    830: ThotBool BagButtonClicked (NotifyElement *event)
                    831: {
                    832: #ifdef TEMPLATES
                    833:   Document        doc = event->document;
                    834:   Element         el = event->element;
                    835:   ElementType     elType;
                    836:   XTigerTemplate  t;
                    837:   Declaration     decl;
                    838:   Element         bagEl = el;
                    839:   Element         firstEl;
                    840:   Element         newEl = NULL;
                    841:   View            view;
                    842:   SSchema         templateSSchema;
                    843:   char*           types;
                    844:   char*           listtypes = NULL;
                    845:   char*           result = NULL;
                    846:   ThotBool        oldStructureChecking;
                    847:   DisplayMode     dispMode;
                    848: 
                    849:   if (!TtaGetDocumentAccessMode(doc))
                    850:     return TRUE;
                    851:   
                    852:   TtaGetActiveView (&doc, &view);
                    853:   if (view != 1)
                    854:     return FALSE; /* let Thot perform normal operation */
                    855: 
                    856:   TtaCancelSelection (doc);
                    857:   templateSSchema = TtaGetSSchema ("Template", doc);  
                    858:   t = GetXTigerTemplate (DocumentMeta[doc]->template_url);
                    859:   elType = TtaGetElementType (el);
                    860:   while (bagEl &&
                    861:          (elType.ElSSchema != templateSSchema ||
                    862:           elType.ElTypeNum != Template_EL_bag))
                    863:     {
                    864:       bagEl = TtaGetParent (bagEl);
                    865:       elType = TtaGetElementType (bagEl);
                    866:     }
                    867: 
                    868:   if (bagEl)
                    869:   {
                    870:     types = GetAttributeStringValueFromNum (bagEl, Template_ATTR_types, NULL);
                    871:     if (types)
                    872:       {
1.142     kia       873:         listtypes = Template_ExpandTypes (t, types, bagEl, FALSE);
1.138     vatton    874:         result = QueryStringFromMenu (doc, listtypes);
                    875:         TtaFreeMemory (listtypes);
                    876:         if (result)
                    877:           {
                    878:             decl = Template_GetDeclaration (t, result);
                    879:             if (decl)
                    880:               {
                    881:                 dispMode = TtaGetDisplayMode (doc);
                    882:                 if (dispMode == DisplayImmediately)
                    883:                   /* don't set NoComputedDisplay
                    884:                      -> it breaks down views formatting when Enter generates new elements  */
1.139     vatton    885:                   TtaSetDisplayMode (doc, DeferredDisplay);
1.138     vatton    886: 
                    887:                 /* Prepare insertion.*/          
                    888:                 oldStructureChecking = TtaGetStructureChecking (doc);
                    889:                 TtaSetStructureChecking (FALSE, doc);
                    890:                 TtaOpenUndoSequence (doc, NULL, NULL, 0, 0);
                    891: 
                    892:                 /* Insert */
                    893:                 if (el == bagEl)
                    894:                   {
                    895:                     el = TtaGetFirstChild (el);
                    896:                     TtaSelectElement (doc, el);
                    897:                     TtaInsertAnyElement (doc, TRUE);
                    898:                   }
                    899:                 else
                    900:                   {
                    901:                     TtaSelectElement (doc, el);
                    902:                     TtaInsertAnyElement (doc, FALSE);
                    903:                   }
                    904:                 newEl = Template_InsertBagChild (doc, bagEl, decl);
                    905: 
                    906:                 /* Finish insertion.*/
                    907:                 TtaCloseUndoSequence (doc);
                    908:                 TtaSetDocumentModified (doc);
                    909:                 TtaSetStructureChecking (oldStructureChecking, doc);
                    910:                 // restore the display
                    911:                 TtaSetDisplayMode (doc, dispMode);
                    912:                 firstEl = GetFirstEditableElement (newEl);
                    913:                 if (firstEl)
                    914:                   {
                    915:                     TtaSelectElement (doc, firstEl);
                    916:                     TtaSetStatusSelectedElement (doc, view, firstEl);
                    917:                   }
                    918:                 else
                    919:                   {
                    920:                     TtaSelectElement (doc, newEl);
                    921:                     TtaSetStatusSelectedElement (doc, view, newEl);
                    922:                   }
                    923:               }
                    924:           }
                    925:       }
                    926:     TtaFreeMemory (types);
                    927:     TtaFreeMemory (result);
                    928:   }
                    929: #endif /* TEMPLATES */
                    930:   return TRUE; /* don't let Thot perform normal operation */
                    931: }
                    932: 
                    933: /*----------------------------------------------------------------------
1.79      quint     934:   RepeatButtonClicked
1.89      kia       935:   Called when a repeat button is clicked.
                    936:   Can be called for useEl, useSimple or repeat.
                    937:   If called for useEl or useSimple, the new element must be added after.
                    938:   If called for repeat, the element must be added before all.
                    939:    
1.56      francesc  940:   Shows a menu with all the types that can be used in a use element.
                    941:   ----------------------------------------------------------------------*/
1.79      quint     942: ThotBool RepeatButtonClicked (NotifyElement *event)
1.56      francesc  943: {
                    944: #ifdef TEMPLATES
1.89      kia       945:   Document        doc = event->document;
                    946:   Element         el = event->element;
                    947:   ElementType     elType;
1.90      kia       948:   XTigerTemplate  t;
                    949:   Declaration     decl;
                    950:   Element         repeatEl = el;
                    951:   Element         firstEl;
                    952:   Element         newEl = NULL;
1.95      kia       953:   View            view;
1.124     kia       954:   char*           listtypes = NULL;
                    955:   char*           result = NULL;
1.138     vatton    956:   char*           types;
                    957:   ThotBool        oldStructureChecking;
                    958:   DisplayMode     dispMode;
1.104     kia       959: 
1.112     vatton    960:   if (!TtaGetDocumentAccessMode(doc))
1.110     kia       961:     return TRUE;
1.89      kia       962:   
1.95      kia       963:   TtaGetActiveView (&doc, &view);
                    964:   if (view != 1)
                    965:     return FALSE; /* let Thot perform normal operation */
                    966: 
1.89      kia       967:   TtaCancelSelection(doc);
1.90      kia       968:   
1.134     kia       969:   t = GetXTigerTemplate (DocumentMeta[doc]->template_url);
1.89      kia       970:   elType = TtaGetElementType(el);
1.138     vatton    971:   while (elType.ElTypeNum != Template_EL_repeat)
1.89      kia       972:   {
1.90      kia       973:     repeatEl = TtaGetParent(repeatEl);
1.138     vatton    974:     if (repeatEl == NULL)
1.89      kia       975:       break;
1.90      kia       976:     elType = TtaGetElementType(repeatEl);
1.89      kia       977:   }
1.112     vatton    978:   if (repeatEl)
1.89      kia       979:   {
1.138     vatton    980:     if (Template_CanInsertRepeatChild (repeatEl))
1.90      kia       981:     {
1.138     vatton    982:       firstEl = TtaGetFirstChild (repeatEl);
                    983:       types = GetAttributeStringValueFromNum (firstEl, Template_ATTR_types, NULL);
1.112     vatton    984:       if (types)
1.90      kia       985:       {
1.142     kia       986:         listtypes = Template_ExpandTypes (t, types, NULL, FALSE);
1.138     vatton    987:         result = QueryStringFromMenu (doc, listtypes);
                    988:         TtaFreeMemory (listtypes);
1.112     vatton    989:         if (result)
1.98      kia       990:         {
1.138     vatton    991:           decl = Template_GetDeclaration (t, result);
1.112     vatton    992:           if (decl)
1.104     kia       993:           {
1.138     vatton    994:             dispMode = TtaGetDisplayMode (doc);
                    995:             if (dispMode == DisplayImmediately)
                    996:               /* don't set NoComputedDisplay
                    997:                  -> it breaks down views formatting when Enter generates new elements  */
1.139     vatton    998:               TtaSetDisplayMode (doc, DeferredDisplay);
1.138     vatton    999: 
1.104     kia      1000:             /* Prepare insertion.*/          
                   1001:             oldStructureChecking = TtaGetStructureChecking (doc);
                   1002:             TtaSetStructureChecking (FALSE, doc);
1.138     vatton   1003:             TtaOpenUndoSequence (doc, NULL, NULL, 0, 0);
1.104     kia      1004:             /* Insert. */
1.138     vatton   1005:             if (el == repeatEl)
                   1006:               newEl = Template_InsertRepeatChildAfter (doc, repeatEl, decl, NULL);
1.104     kia      1007:             else
1.138     vatton   1008:               newEl = Template_InsertRepeatChildAfter (doc, repeatEl, decl, el);
1.104     kia      1009:               
                   1010:             /* Finish insertion.*/
                   1011:             TtaCloseUndoSequence(doc);
1.114     vatton   1012:             TtaSetDocumentModified (doc);
1.104     kia      1013:             TtaSetStructureChecking (oldStructureChecking, doc);
1.138     vatton   1014: 
                   1015:             // restore the display
                   1016:             TtaSetDisplayMode (doc, dispMode);
                   1017:             firstEl = GetFirstEditableElement (newEl);
1.112     vatton   1018:             if (firstEl)
1.104     kia      1019:             {
                   1020:               TtaSelectElement (doc, firstEl);
1.138     vatton   1021:               TtaSetStatusSelectedElement (doc, view, firstEl);
1.104     kia      1022:             }
                   1023:             else
                   1024:             {
                   1025:               TtaSelectElement (doc, newEl);
1.138     vatton   1026:               TtaSetStatusSelectedElement (doc, view, newEl);
1.104     kia      1027:             }
1.98      kia      1028:           }
                   1029:         }
1.90      kia      1030:       }
1.104     kia      1031:       TtaFreeMemory(types);
1.98      kia      1032:       TtaFreeMemory(result);
                   1033:     }
1.112     vatton   1034:     else /* if (Template_CanInsertRepeatChild(repeatEl)) */
1.98      kia      1035:     {
                   1036:       TtaSetStatus(doc, view, TtaGetMessage (AMAYA, AM_NUMBER_OCCUR_HAVE_MAX), NULL);
1.90      kia      1037:     }
1.89      kia      1038:   }
1.77      vatton   1039:   return TRUE; /* don't let Thot perform normal operation */
1.57      francesc 1040: #endif /* TEMPLATES */
1.94      kia      1041:   return TRUE;
                   1042: }
                   1043: 
                   1044: /*----------------------------------------------------------------------
                   1045:   UseButtonClicked
                   1046:   Shows a menu with all the types that can be used in a use element.
                   1047:   ----------------------------------------------------------------------*/
                   1048: ThotBool UseButtonClicked (NotifyElement *event)
                   1049: {
                   1050: #ifdef TEMPLATES
                   1051:   Document        doc = event->document;
                   1052:   Element         el = event->element;
1.99      kia      1053:   Element         child;
1.94      kia      1054:   ElementType     elType;
                   1055:   XTigerTemplate  t;
                   1056:   Declaration     decl;
                   1057:   Element         firstEl;
                   1058:   Element         newEl = NULL;
                   1059:   char*           types;
                   1060:   ThotBool        oldStructureChecking;
1.95      kia      1061:   View            view;
1.133     vatton   1062:   char*           listtypes = NULL;
                   1063:   char*           result = NULL;
1.95      kia      1064: 
1.112     vatton   1065:   if (!TtaGetDocumentAccessMode(doc))
1.110     kia      1066:     return TRUE;
                   1067:     
1.95      kia      1068:   TtaGetActiveView (&doc, &view);
                   1069:   if (view != 1)
                   1070:     return FALSE; /* let Thot perform normal operation */
1.94      kia      1071:   
                   1072:   TtaCancelSelection(doc);
                   1073:   
1.134     kia      1074:   t = GetXTigerTemplate (DocumentMeta[doc]->template_url);
1.94      kia      1075:   if (!t)
                   1076:     return FALSE; /* let Thot perform normal operation */
                   1077:   elType = TtaGetElementType(el);
                   1078: 
                   1079:   firstEl = TtaGetFirstChild(el);
1.112     vatton   1080:   if (firstEl)
1.94      kia      1081:   {
                   1082:     RepeatButtonClicked(event);
                   1083:   }
                   1084:   else
                   1085:   {
1.104     kia      1086:     types = GetAttributeStringValueFromNum(el, Template_ATTR_types, NULL);
1.112     vatton   1087:     if (types)
1.94      kia      1088:     {
1.142     kia      1089:       listtypes = Template_ExpandTypes(t, types, NULL, FALSE);
1.104     kia      1090:       result = QueryStringFromMenu(doc, listtypes);
1.112     vatton   1091:       if (result)
1.94      kia      1092:       {
1.104     kia      1093:         decl = Template_GetDeclaration(t, result);
1.112     vatton   1094:         if (decl)
1.99      kia      1095:         {
1.104     kia      1096:           /* Prepare insertion.*/
                   1097:           oldStructureChecking = TtaGetStructureChecking (doc);
                   1098:           TtaSetStructureChecking (FALSE, doc);
1.138     vatton   1099:           TtaOpenUndoSequence (doc, NULL, NULL, 0, 0);
1.104     kia      1100:           
                   1101:           /* Insert */
                   1102:           newEl = Template_InsertUseChildren(doc, el, decl);
                   1103:           for(child = TtaGetFirstChild(newEl); child; TtaNextSibling(&child))
                   1104:           {
                   1105:             TtaRegisterElementCreate(child, doc);
                   1106:           }
                   1107:           
                   1108:           TtaChangeTypeOfElement(el, doc, Template_EL_useSimple);
                   1109:           TtaRegisterElementTypeChange(el, Template_EL_useEl, doc);
                   1110:           
1.117     kia      1111:           /* xt:currentType attribute.*/
                   1112:           SetAttributeStringValueWithUndo(el, Template_ATTR_currentType, result);
                   1113:           
1.104     kia      1114:           /* Finish insertion. */
                   1115:           TtaCloseUndoSequence(doc);
1.114     vatton   1116:           TtaSetDocumentModified (doc);
1.104     kia      1117:           TtaSetStructureChecking (oldStructureChecking, doc);
                   1118:           
                   1119:           firstEl = GetFirstEditableElement(newEl);
1.112     vatton   1120:           if (firstEl)
1.104     kia      1121:           {
                   1122:             TtaSelectElement (doc, firstEl);
                   1123:             TtaSetStatusSelectedElement(doc, view, firstEl);
                   1124:           }
                   1125:           else
                   1126:           {
                   1127:             TtaSelectElement (doc, newEl);
                   1128:             TtaSetStatusSelectedElement(doc, view, newEl);
                   1129:           }
1.98      kia      1130:         }
1.94      kia      1131:       }
                   1132:     }
1.104     kia      1133:     TtaFreeMemory(types);
1.94      kia      1134:     TtaFreeMemory(listtypes);
                   1135:     TtaFreeMemory(result);
                   1136:   }
                   1137:   
                   1138:   return TRUE;
                   1139: #endif /* TEMPLATES */
1.56      francesc 1140:        return TRUE;
                   1141: }
1.64      francesc 1142: 
1.89      kia      1143: 
1.103     kia      1144: /*----------------------------------------------------------------------
                   1145:   UseSimpleButtonClicked
                   1146:   ----------------------------------------------------------------------*/
                   1147: ThotBool UseSimpleButtonClicked (NotifyElement *event)
                   1148: {
                   1149: #ifdef TEMPLATES
1.112     vatton   1150:   if (!TtaGetDocumentAccessMode(event->document))
1.110     kia      1151:     return TRUE;
                   1152: 
1.138     vatton   1153:   ElementType parentType = TtaGetElementType (TtaGetParent( event->element));
1.112     vatton   1154:   if (parentType.ElTypeNum == Template_EL_repeat)
1.138     vatton   1155:     return RepeatButtonClicked (event);
                   1156:   else if (parentType.ElTypeNum == Template_EL_bag)
                   1157:     return BagButtonClicked (event);
1.103     kia      1158: #endif /* TEMPLATES */  
                   1159:   return FALSE;
                   1160: }
1.94      kia      1161: 
                   1162: /*----------------------------------------------------------------------
                   1163:   OptionButtonClicked
                   1164:   ----------------------------------------------------------------------*/
                   1165: ThotBool OptionButtonClicked (NotifyElement *event)
                   1166: {
                   1167: #ifdef TEMPLATES
1.145   ! kia      1168:   Element         useEl, contentEl, next;
        !          1169:   ElementType     useType, optType;
1.94      kia      1170:   Document        doc;
                   1171:   XTigerTemplate  t;
                   1172:   View            view;
                   1173: 
1.112     vatton   1174:   if (!TtaGetDocumentAccessMode(event->document))
1.110     kia      1175:     return TRUE;
                   1176: 
1.94      kia      1177:   TtaGetActiveView (&doc, &view);
                   1178:   if (view != 1)
                   1179:     return FALSE; /* let Thot perform normal operation */
1.110     kia      1180: 
1.94      kia      1181:   doc = event->document;
1.145   ! kia      1182:   useEl = TtaGetFirstChild (event->element);
        !          1183:   if (!useEl)
1.94      kia      1184:     return FALSE; /* let Thot perform normal operation */
1.145   ! kia      1185:   useType = TtaGetElementType (useEl);
        !          1186:   optType = TtaGetElementType (event->element);
        !          1187:   if ((useType.ElTypeNum != Template_EL_useEl &&
        !          1188:                  useType.ElTypeNum != Template_EL_useSimple) ||
        !          1189:                  useType.ElSSchema != optType.ElSSchema)
1.94      kia      1190:     return FALSE;
                   1191: 
1.145   ! kia      1192:   TtaOpenUndoSequence(doc, NULL, NULL, 0, 0);
        !          1193:   
1.94      kia      1194:   TtaCancelSelection (doc);
1.145   ! kia      1195:   
        !          1196:   contentEl = TtaGetFirstChild (useEl);
        !          1197:   if (!contentEl)
1.94      kia      1198:     /* the "use" element is empty. Instantiate it */
                   1199:     {
1.134     kia      1200:       t = GetXTigerTemplate (DocumentMeta[doc]->template_url);
1.94      kia      1201:       if (!t)
                   1202:         return FALSE; // no template ?!?!
1.145   ! kia      1203:       InstantiateUse (t, useEl, doc, TRUE);
1.94      kia      1204:     }
                   1205:   else
                   1206:     /* remove the content of the "use" element */
                   1207:     {
                   1208:       do
                   1209:         {
1.145   ! kia      1210:           next = contentEl;
1.94      kia      1211:           TtaNextSibling (&next);
1.145   ! kia      1212:           TtaRegisterElementDelete(contentEl, doc);
        !          1213:           TtaDeleteTree (contentEl, doc);
        !          1214:           contentEl = next;
1.94      kia      1215:         }
                   1216:       while (next);
1.145   ! kia      1217:       if (NeedAMenu (useEl, doc))
        !          1218:         {
        !          1219:           TtaChangeTypeOfElement (useEl, doc, Template_EL_useEl);
        !          1220:           TtaRegisterElementTypeChange(useEl, Template_EL_useSimple, doc);
        !          1221:         }
1.94      kia      1222:     }
                   1223:   TtaSelectElement (doc, event->element);
1.145   ! kia      1224:   TtaCloseUndoSequence(doc);
1.94      kia      1225:   return TRUE; /* don't let Thot perform normal operation */
                   1226: #endif /* TEMPLATES */
                   1227:   return TRUE;
                   1228: }
                   1229: 
1.111     vatton   1230: /*----------------------------------------------------------------------
                   1231:   CheckTemplate checks if the template of the instance is loaded
1.126     vatton   1232:   Return TRUE if the template is loaded
1.111     vatton   1233:   ----------------------------------------------------------------------*/
                   1234: void CheckTemplate (Document doc)
                   1235: {
                   1236: #ifdef TEMPLATES
1.144     vatton   1237:   Element    root;
                   1238: 
                   1239:   if (DocumentMeta[doc] && DocumentMeta[doc]->template_url)
1.111     vatton   1240:     {
1.144     vatton   1241:       XTigerTemplate   t;
                   1242: 
                   1243:       root = TtaGetRootElement (doc);
                   1244:       TtaSetAccessRight (root, ReadOnly, doc);
                   1245:       t = GetXTigerTemplate (DocumentMeta[doc]->template_url);
                   1246:       if (t == NULL)
                   1247:         {
                   1248:           // the template cannot be loaded
                   1249:           InitConfirm (doc, 1, TtaGetMessage (AMAYA, AM_BAD_TEMPLATE));
                   1250:           TtaSetDocumentAccessMode (doc, 0); // document readonly
                   1251:         }
                   1252:       else
                   1253:         {
                   1254:           // fix all access rights in the instance
                   1255:           Template_FixAccessRight (t, root, doc);
                   1256:           TtaUpdateAccessRightInViews (doc, root);
                   1257:         }
1.111     vatton   1258:     }
                   1259: #endif /* TEMPLATES */
                   1260: }
1.94      kia      1261: 
1.66      vatton   1262: /*----------------------------------------------------------------------
1.108     vatton   1263:   OpeningInstance checks if it is a template instance needs.
                   1264:   If it's an instance and the template is not loaded, load it into a
                   1265:   temporary file
1.66      vatton   1266:   ----------------------------------------------------------------------*/
1.76      vatton   1267: void OpeningInstance (char *fileName, Document doc)
1.65      francesc 1268: {
                   1269: #ifdef TEMPLATES
1.76      vatton   1270:   XTigerTemplate   t;
1.103     kia      1271:   char            *content, *ptr, *begin;
1.76      vatton   1272:   gzFile           stream;
                   1273:   char             buffer[2000];
1.77      vatton   1274:   int              res;
1.65      francesc 1275: 
1.76      vatton   1276:   stream = TtaGZOpen (fileName);
                   1277:   if (stream != 0)
1.65      francesc 1278:     {
1.76      vatton   1279:       res = gzread (stream, buffer, 1999);
                   1280:       if (res >= 0)
1.65      francesc 1281:         {
1.81      vatton   1282:           buffer[res] = EOS;
1.103     kia      1283:           begin = strstr (buffer, "<?xtiger");
                   1284:           
1.112     vatton   1285:           if (begin)
1.103     kia      1286:           {
                   1287:             // Search for template version
                   1288:             ptr = strstr (begin, "templateVersion");
                   1289:             if (ptr)
                   1290:               ptr = strstr (ptr, "=");
                   1291:             if (ptr)
                   1292:               ptr = strstr (ptr, "\"");
                   1293:             if (ptr)
                   1294:               {
                   1295:                 // template URI
                   1296:                 content = &ptr[1];
                   1297:                 ptr = strstr (content, "\"");
                   1298:               }
                   1299:             if (ptr)
                   1300:               {
                   1301:                 *ptr = EOS;
                   1302:                 //Get now the template URI
                   1303:                 DocumentMeta[doc]->template_version = TtaStrdup (content);
                   1304:                 *ptr = '"';
                   1305:               }
                   1306:            
                   1307:             // Search for template uri
                   1308:             ptr = strstr (begin, "template");
                   1309:             if (ptr && ptr[8] != 'V')
                   1310:               ptr = strstr (ptr, "=");
                   1311:             if (ptr)
                   1312:               ptr = strstr (ptr, "\"");
                   1313:             if (ptr)
                   1314:               {
                   1315:                 // template URI
                   1316:                 content = &ptr[1];
                   1317:                 ptr = strstr (content, "\"");
                   1318:               }
                   1319:             if (ptr)
                   1320:               {
                   1321:                 *ptr = EOS;
                   1322:                 //Get now the template URI
                   1323:                 DocumentMeta[doc]->template_url = TtaStrdup (content);
1.134     kia      1324:                 if (Templates_Map == NULL)
1.103     kia      1325:                   InitializeTemplateEnvironment ();
1.134     kia      1326:                 t = GetXTigerTemplate (content);
1.103     kia      1327:                 if (!t)
                   1328:                   {
1.108     vatton   1329:                     LoadTemplate (doc, content);
1.134     kia      1330:                     t = GetXTigerTemplate(content);
1.103     kia      1331:                   }
                   1332:                 AddUser (t);
                   1333:                 *ptr = '"';
                   1334:               }
                   1335:           }
1.65      francesc 1336:         }
                   1337:     }
1.76      vatton   1338:   TtaGZClose (stream);
1.65      francesc 1339: #endif /* TEMPLATES */
                   1340: }
                   1341: 
1.64      francesc 1342: /*----------------------------------------------------------------------
1.65      francesc 1343:   ClosingInstance
1.64      francesc 1344:   Callback called before closing a document. Checks for unused templates.
                   1345:   ----------------------------------------------------------------------*/
1.65      francesc 1346: ThotBool ClosingInstance(NotifyDialog* dialog)
1.64      francesc 1347: {
1.65      francesc 1348: #ifdef TEMPLATES
                   1349:   //If it is a template all has been already freed
1.76      vatton   1350:   if (DocumentMeta[dialog->document] == NULL)
                   1351:     return FALSE;
1.65      francesc 1352: 
                   1353:   char *turl = DocumentMeta[dialog->document]->template_url;
1.73      vatton   1354:   if (turl)
1.104     kia      1355:   {
1.134     kia      1356:     XTigerTemplate t = GetXTigerTemplate(turl);
1.104     kia      1357:     if (t)
                   1358:       RemoveUser (t);
                   1359:     TtaFreeMemory (turl);
                   1360:     DocumentMeta[dialog->document]->template_url = NULL;
                   1361:   }
                   1362:   
1.112     vatton   1363:   if (DocumentMeta[dialog->document]->template_version)
1.104     kia      1364:   {
                   1365:     TtaFreeMemory(DocumentMeta[dialog->document]->template_version);
                   1366:     DocumentMeta[dialog->document]->template_version = NULL;
                   1367:   }
1.65      francesc 1368: #endif /* TEMPLATES */
                   1369:   return FALSE;
1.64      francesc 1370: }
1.87      kia      1371: 
                   1372: 
                   1373: /*----------------------------------------------------------------------
1.120     kia      1374:   IsTemplateElement
1.138     vatton   1375:   Test if an element is a template element.
1.87      kia      1376:   ----------------------------------------------------------------------*/
1.140     vatton   1377: ThotBool IsTemplateElement (Element elem)
1.87      kia      1378: {
                   1379: #ifdef TEMPLATES
1.138     vatton   1380:   ElementType     elType;
                   1381: 
                   1382:   elType = TtaGetElementType(elem);
                   1383:   if (elType.ElSSchema)
                   1384:     return (strcmp(TtaGetSSchemaName(elType.ElSSchema) , "Template") != 0);
                   1385: #endif /* TEMPLATES */
1.87      kia      1386:   return FALSE;
                   1387: }
                   1388: 
                   1389: 
                   1390: /*----------------------------------------------------------------------
                   1391:   GetFirstTemplateParentElement
1.138     vatton   1392:   Return the first element which has "Template" as schema name or null.
1.87      kia      1393:   ----------------------------------------------------------------------*/
                   1394: Element GetFirstTemplateParentElement(Element elem)
                   1395: {
                   1396: #ifdef TEMPLATES
1.138     vatton   1397:   ElementType     elType;
                   1398: 
                   1399:   elem = TtaGetParent (elem);
                   1400:   elType = TtaGetElementType(elem);
                   1401:   while (elem && strcmp(TtaGetSSchemaName(elType.ElSSchema), "Template"))
                   1402: {
                   1403:     elem = TtaGetParent (elem);
                   1404:     elType = TtaGetElementType(elem);
1.87      kia      1405:   }
                   1406:   return elem;
                   1407: #else
                   1408:   return NULL;
                   1409: #endif /* TEMPLATES */
                   1410: }
1.101     kia      1411: 
1.103     kia      1412: 
1.101     kia      1413: /*----------------------------------------------------------------------
1.102     vatton   1414:   TemplateElementWillBeCreated
1.101     kia      1415:   Processed when an element will be created in a template context.
                   1416:   ----------------------------------------------------------------------*/
1.102     vatton   1417: ThotBool TemplateElementWillBeCreated (NotifyElement *event)
1.101     kia      1418: {
1.103     kia      1419: #ifdef TEMPLATES
                   1420:   ElementType elType = event->elementType;
                   1421:   Element     parent = event->element;
                   1422:   ElementType parentType = TtaGetElementType(parent);
1.113     kia      1423:   Element     ancestor;
                   1424:   ElementType ancestorType;
                   1425:   SSchema     templateSSchema;
                   1426:   char*       types;
                   1427:   ThotBool    b;
1.101     kia      1428: 
1.115     kia      1429:   if(event->info==1)
                   1430:     return FALSE;
                   1431: 
1.112     vatton   1432:   if (!TtaGetDocumentAccessMode(event->document))
1.110     kia      1433:     return TRUE;
                   1434: 
1.138     vatton   1435:   templateSSchema = TtaGetSSchema ("Template", event->document);
1.102     vatton   1436:   if (templateSSchema == NULL)
                   1437:     return FALSE; // let Thot do the job
1.115     kia      1438: 
1.113     kia      1439:   // Fisrt, test if in a xt:bag or in a base-element xt:use
                   1440:   if(parentType.ElSSchema==templateSSchema)
                   1441:     ancestor = parent;
                   1442:   else
                   1443:     ancestor = GetFirstTemplateParentElement(parent);
                   1444: 
                   1445:   if(ancestor)
                   1446:   {
                   1447:     ancestorType = TtaGetElementType(ancestor);
                   1448: 
                   1449:     if(ancestorType.ElTypeNum==Template_EL_bag)
                   1450:     {
1.116     kia      1451:       if(elType.ElSSchema==templateSSchema &&
                   1452:           (elType.ElTypeNum==Template_EL_useSimple || elType.ElTypeNum==Template_EL_useEl))
                   1453:         return FALSE;
1.125     kia      1454:       return !Template_CanInsertElementInBagElement(event->document, elType, ancestor);      
1.113     kia      1455:     }
1.121     vatton   1456:     else if(ancestorType.ElTypeNum==Template_EL_useSimple ||
                   1457:             ancestorType.ElTypeNum==Template_EL_useEl)
1.113     kia      1458:     {
1.121     vatton   1459:       // only check the use child
                   1460:       if (ancestor != parent)
                   1461:         return  FALSE; // let Thot do the job
1.113     kia      1462:       types = GetAttributeStringValueFromNum(ancestor, Template_ATTR_currentType, NULL);
1.128     kia      1463:       b = Template_CanInsertElementInUse(event->document, elType, types, parent, event->position);
                   1464:       TtaFreeMemory(types);
1.115     kia      1465:       return !b;
1.113     kia      1466:       
                   1467:     }
                   1468:   }
1.115     kia      1469:   
                   1470:   if(elType.ElSSchema==templateSSchema && elType.ElTypeNum==Template_EL_TEXT_UNIT)
                   1471:   {
                   1472:     return FALSE;
                   1473:   }
                   1474:   
1.113     kia      1475:   // Can not insert.
                   1476:   return TRUE;
1.101     kia      1477: #endif /* TEMPLATES*/
1.102     vatton   1478:   return FALSE;
1.101     kia      1479: }
                   1480: 
                   1481: /*----------------------------------------------------------------------
                   1482:   TemplateElementWillBeDeleted
                   1483:   Processed when an element will be deleted in a template context.
                   1484:   ----------------------------------------------------------------------*/
                   1485: ThotBool TemplateElementWillBeDeleted (NotifyElement *event)
                   1486: {
1.107     kia      1487: #ifdef TEMPLATES
                   1488:   Document       doc = event->document;
                   1489:   Element        elem = event->element;
                   1490:   Element        xtElem, parent;
1.109     kia      1491:   Element        sibling;
1.117     kia      1492:   ElementType    xtType, elType;
1.107     kia      1493:   char*          type;
                   1494:   Declaration    dec;
1.115     kia      1495:   SSchema        templateSSchema;
1.107     kia      1496:   XTigerTemplate t;
                   1497: 
1.115     kia      1498:   if(event->info==1)
                   1499:     return FALSE;
                   1500: 
1.112     vatton   1501:   if (!TtaGetDocumentAccessMode(event->document))
1.110     kia      1502:     return TRUE;
                   1503: 
1.138     vatton   1504:   templateSSchema = TtaGetSSchema ("Template", event->document);
1.107     kia      1505:   if (templateSSchema == NULL)
                   1506:     return FALSE; // let Thot do the job
1.122     kia      1507: 
1.107     kia      1508:   xtElem = GetFirstTemplateParentElement(elem);
1.112     vatton   1509:   if (xtElem)
1.107     kia      1510:   {
                   1511:     xtType = TtaGetElementType(xtElem);
1.117     kia      1512:     
1.134     kia      1513:     t = GetXTigerTemplate(DocumentMeta[doc]->template_url);
1.109     kia      1514: 
1.112     vatton   1515:     if (xtType.ElTypeNum==Template_EL_bag)
1.117     kia      1516:     {
                   1517:       elType = TtaGetElementType(elem);
                   1518:       if(elType.ElSSchema==templateSSchema &&
                   1519:         (elType.ElTypeNum==Template_EL_useSimple || elType.ElTypeNum==Template_EL_useEl))
                   1520:       {
                   1521:         // Remove element manually.
                   1522:         TtaOpenUndoSequence(doc, elem, elem, 0, 0);
                   1523:         TtaRegisterElementDelete(elem, doc);
                   1524:         TtaDeleteTree(elem, doc);
                   1525:         TtaCloseUndoSequence(doc);
                   1526:         return TRUE;
                   1527:       }
                   1528:       else
                   1529:         return FALSE; // xt:bag always allow remove children.
                   1530:     }
1.112     vatton   1531:     else if (xtType.ElTypeNum==Template_EL_useSimple || xtType.ElTypeNum==Template_EL_useEl)
1.107     kia      1532:     {
1.109     kia      1533:       parent = TtaGetParent(elem);
1.117     kia      1534:       if (xtElem!=parent)
                   1535:       {
                   1536:         type = GetAttributeStringValueFromNum(xtElem, Template_ATTR_currentType, NULL);
                   1537:         dec = Template_GetDeclaration(t, type);
                   1538:         TtaFreeMemory(type);
                   1539:         
                   1540:         if (dec && dec->nature == XmlElementNat)
                   1541:           return FALSE; // Can remove element only if in xt:use current type is base language element. 
                   1542:         else
                   1543:           return TRUE;
1.107     kia      1544:       }
1.109     kia      1545:     }
1.112     vatton   1546:     else if (xtType.ElTypeNum==Template_EL_repeat)
1.109     kia      1547:     {
                   1548:       sibling = TtaGetSuccessor(elem);
                   1549:       TtaRegisterElementDelete(elem, doc);
                   1550:       TtaDeleteTree(elem, doc);
1.123     kia      1551:       Template_DecrementRepeatOccurNumber(xtElem);
1.109     kia      1552:       InstantiateRepeat(t, xtElem, doc, TRUE);
                   1553:       TtaSelectElement(doc, sibling);
                   1554:       return TRUE;
1.107     kia      1555:     }
                   1556:   }
1.109     kia      1557:   
                   1558:   //TODO Test if current element is use or repeat.
                   1559:   // Because if an element is delete and it is the unique child of its parent,
                   1560:   // the parent intends to destroy itself. 
                   1561:   
1.107     kia      1562:   return TRUE;
                   1563: #else /* TEMPLATES */
1.101     kia      1564:   return FALSE;
1.107     kia      1565: #endif /* TEMPLATES */
1.101     kia      1566: }
                   1567: 
1.109     kia      1568: /*----------------------------------------------------------------------
                   1569:   CurrentTypeWillBeExported
                   1570:   Check if the xt:currentType attribute can be exported
                   1571:   ----------------------------------------------------------------------*/
                   1572: ThotBool CurrentTypeWillBeExported (NotifyAttribute *event)
                   1573: {
                   1574: #ifdef TEMPLATES
1.110     kia      1575: 
1.112     vatton   1576:   if (!TtaGetDocumentAccessMode(event->document))
1.110     kia      1577:     return TRUE;
                   1578: 
1.112     vatton   1579:   if (IsTemplateDocument(event->document))
1.109     kia      1580:     return TRUE;
                   1581: #endif /* TEMPLATES */
                   1582:   return FALSE;
                   1583: }
1.127     kia      1584: 
                   1585: /*----------------------------------------------------------------------
                   1586:   TemplateAttrInMenu
                   1587:   Called by Thot when building the Attributes menu for template elements.
                   1588:   ----------------------------------------------------------------------*/
                   1589: ThotBool TemplateAttrInMenu (NotifyAttribute * event)
                   1590: {
                   1591: #ifdef TEMPLATES
                   1592:   // Prevent from showing attributes for template instance but not templates.
                   1593:   if(IsTemplateInstanceDocument(event->document))
                   1594:     return TRUE;
                   1595:   else
                   1596: #endif /* TEMPLATES */
                   1597:     return FALSE;
                   1598: }
                   1599: 

Webmaster