PageRenderTime 144ms CodeModel.GetById 30ms app.highlight 70ms RepoModel.GetById 35ms app.codeStats 0ms

/thotlib/dialogue/profiles.c

https://github.com/pffy/Amaya-Editor
C | 997 lines | 670 code | 92 blank | 235 comment | 218 complexity | 906e2ebde624dfd4b091941e7ad99eb0 MD5 | raw file
  1/*
  2 *
  3 *  COPYRIGHT MIT and INRIA, 1996-2008
  4 *  Please first read the full copyright statement in file COPYRIGHT.
  5 *
  6 */
  7
  8/*
  9 * profile.c: This module contains all the functions used to handle
 10 * the profile configuration in Amaya. Each function beginning with
 11 * "Prof_" prefix is called by an extern module.
 12 * Profile files are coded in ISO-latin
 13 *
 14 * Authors: I. Vatton, L. Bonameau
 15 *
 16 */
 17
 18/* Included headerfiles */
 19#include "thot_gui.h"
 20#include "thot_sys.h"
 21#include "string.h"
 22#include "constmedia.h"
 23#include "typemedia.h"
 24#include "appdialogue.h"
 25#include "application.h"
 26#include "registry.h"
 27#include "profiles.h"
 28
 29#include "containers.h"
 30
 31#define PROFILE_START              '<'
 32#define PROFILE_END                '>'
 33#define DOCTYPE_START              '{'
 34#define DOCTYPE_END                '}'
 35#define MODULE_START               '['
 36#define MODULE_END                 ']'
 37#define MODULE_REF                 '+'
 38#define EDITING_REF                '&'
 39#define GUI_REF                    '*'
 40
 41#define MAX_ENTRIES 10
 42
 43typedef struct _Profile_Ctl *PtrProCtl;
 44typedef struct _ProElement
 45{
 46  char                *ProName;      /* Name of the entry */
 47  PtrProCtl            ProSubModule; /* Pointer to a sub-module context */
 48  ThotBool             ProIsModule;  /* TRUE if it is a sub-module */
 49  ThotBool             ProEdit;      /* TRUE if it's a editing function */
 50  ThotBool             ProGui;       /* TRUE if it's a gui */
 51} ProElement;
 52
 53
 54
 55typedef struct _Profile_Ctl
 56{
 57  ProElement           ProEntries[MAX_ENTRIES]; /* list of names */
 58  PtrProCtl            ProNext;                 /* next list */
 59} Profile_Ctl;
 60
 61
 62/*--------------------------
 63  Static vars
 64  ---------------------------*/
 65/* Profiles table contains the name of all the available profiles */
 66static PtrProCtl            ProfileTable = NULL;
 67static int                  NbProfiles = 0;
 68/* Doctypes table contains the name of all the available doctypes */
 69static PtrProCtl            DoctypeTable = NULL;
 70static int                  NbDoctypes = 0;
 71/* Modules table contains the name of all the available modules */
 72static PtrProCtl            ModuleTable = NULL;
 73static int                  NbModules = 0;
 74/* Functions table contains current list of available functions */
 75static PtrProCtl            FunctionTable = NULL;
 76static int                  NbFunctions = 0;
 77static char               **SortedFunctionTable = NULL;
 78static int                 *FunctionMask = NULL;
 79static ThotBool            *FunctionRO = NULL;
 80
 81/* The first context of the current module or profile in progress */
 82static PtrProCtl            CurrentModule;
 83static int                  CurrentEntries;
 84
 85/* Determine either a profile is defined or not */
 86static ThotBool             CheckProfile = FALSE;
 87/* User Profile (taken from the thot.rc) */
 88static char                 UserProfile[MAX_PRO_LENGTH];
 89static PtrProCtl            UserProfContext = NULL;
 90static char                 ProfileBuff[MAX_PRO_LENGTH];
 91/* This boolean goes FALSE if the profile only contains browsing functions */
 92static ThotBool             EnableEdit = TRUE;
 93
 94
 95/* List containing names of GUI allowed elements.*/
 96static DLList               GuiList = NULL;
 97
 98#include "registry_f.h"
 99
100/*********************************************************
101  String functions : set of useful functions for strings
102***********************************************************/
103
104
105/*----------------------------------------------------------------------
106  SkipAllBlanks:  Remove all the spaces, tabulations and return
107  returns (CR) and "end of line" characters.
108  ----------------------------------------------------------------------*/
109static void SkipAllBlanks (char *Astring)
110{
111  int         c = 0;
112  int         nbsp = 0;
113
114  /* locate the biginning of the string */
115  while (Astring[c + nbsp] != EOS &&
116         (Astring[c + nbsp] == SPACE || Astring[c + nbsp] == TAB ||
117          Astring[c + nbsp] == __CR__))
118    nbsp++;
119  /* suppress blanks before */
120  while (Astring[c] != EOS)
121    {
122      Astring[c] = Astring[c + nbsp];
123      c++;
124    }
125  /* suppress blanks after the string */
126  while (c > 0 &&
127         (Astring[c - 1] == SPACE || Astring[c - 1] == TAB ||
128          Astring[c - 1] == __CR__ || Astring[c - 1] == EOL))
129    {
130      c--;
131      Astring[c] = EOS;
132    }
133  do
134    {
135      while (Astring[c + nbsp] == SPACE || Astring[c + nbsp] == TAB ||
136             Astring[c + nbsp] == __CR__)
137        nbsp++;
138      Astring[c] = Astring[c + nbsp];
139    }
140  while (Astring[c++] != EOS);
141}
142
143/*----------------------------------------------------------------------
144  AddInTable inserts an element in a table.
145  The parameter name is the name of the new entry.
146  The parameter isModule is TRUE if that entry is the name of a module.
147  The parameter edit is TRUE if that entry is an editable function.
148  The parameter gui is TRUE if that entry is gui.
149  The parameter subModule points to the first ctxt of the sub-module. If
150  t is NULL and isModule is TRUE the context is created.
151  The parameter number give the current number of entries in the table.
152  The parameter ctxt points to the first ctxt of the table.
153  Return the first context of the new module.
154  ----------------------------------------------------------------------*/
155static PtrProCtl AddInTable (char *name, ThotBool isModule, ThotBool edit,
156                             ThotBool gui,
157                             PtrProCtl subModule, int number,
158                             PtrProCtl ctxt)
159{
160  PtrProCtl           current, prev, new_;
161  int                 i;
162
163  i = number;
164  current = ctxt;
165  new_ = NULL;
166  prev = NULL;
167  /* skip full contexts */
168  while (i >= MAX_ENTRIES && current)
169    {
170      prev = current;
171      current = current->ProNext;
172      i -= MAX_ENTRIES;
173    }
174  /* add a next context if it is necessary */
175  if (prev && i == 0)
176    {
177      i = 0;
178      current = (PtrProCtl) TtaGetMemory (sizeof (Profile_Ctl));
179      memset (current, 0, sizeof (Profile_Ctl));
180      prev->ProNext = current;
181    }
182
183  /* add the new entry */
184  if (current && i < MAX_ENTRIES)
185    {
186      if (name)
187        {
188          current->ProEntries[i].ProName = TtaStrdup (name);
189          current->ProEntries[i].ProIsModule = isModule;
190          current->ProEntries[i].ProEdit = edit;
191          current->ProEntries[i].ProGui = gui;
192          if (isModule && subModule == NULL)
193            {
194              /* allocate the context of the sub-module */
195              new_ = (PtrProCtl) TtaGetMemory (sizeof (Profile_Ctl));
196              memset (new_, 0, sizeof (Profile_Ctl));
197              current->ProEntries[i].ProSubModule = new_;
198            }
199          else
200            current->ProEntries[i].ProSubModule = subModule;
201        }
202    }
203  return new_;
204}
205
206/*----------------------------------------------------------------------
207  AddModule inserts a new module in the module table.
208  Return the first context of the new module.
209  ----------------------------------------------------------------------*/
210static PtrProCtl AddModule (char *name)
211{
212  PtrProCtl     new_ = NULL;
213
214  /* Register the new module */
215  if (NbModules == 0)
216    {
217      ModuleTable = (PtrProCtl) TtaGetMemory (sizeof (Profile_Ctl));
218      memset (ModuleTable, 0, sizeof (Profile_Ctl));
219    }
220  new_ = AddInTable (name, TRUE, FALSE, FALSE, NULL, NbModules, ModuleTable);
221  NbModules++;
222  return new_;
223}
224
225/*----------------------------------------------------------------------
226  AddProfile inserts a new profile in the profile table.
227  Return the first context of the new profile.
228  ----------------------------------------------------------------------*/
229static PtrProCtl AddProfile (char *name)
230{
231  PtrProCtl     new_ = NULL;
232
233  if (!strcmp (name, UserProfile))
234    {
235      /* Register the new profile */
236      if (NbProfiles == 0)
237        {
238          ProfileTable = (PtrProCtl) TtaGetMemory (sizeof (Profile_Ctl));
239          memset (ProfileTable, 0, sizeof (Profile_Ctl));
240        }
241       new_ = AddInTable (name, TRUE, FALSE, FALSE, NULL, NbProfiles, ProfileTable);
242       NbProfiles++;
243       /* store the context of the user profile */
244       if (UserProfContext == NULL)
245         UserProfContext = new_;
246    }
247  return new_;
248}
249
250/*----------------------------------------------------------------------
251  AddDoctype inserts a new doctype profile in the table.
252  Return the first context of the new profile.
253  ----------------------------------------------------------------------*/
254static PtrProCtl AddDoctype (char *name)
255{
256  PtrProCtl     new_ = NULL;
257
258  /* Register the new profile */
259  if (NbDoctypes == 0)
260    {
261      DoctypeTable = (PtrProCtl) TtaGetMemory (sizeof (Profile_Ctl));
262      memset (DoctypeTable, 0, sizeof (Profile_Ctl));
263    }
264  new_ = AddInTable (name, TRUE, FALSE, FALSE, NULL, NbDoctypes, DoctypeTable);
265  NbDoctypes++;
266  return new_;
267}
268
269
270
271/*----------------------------------------------------------------------
272  DeleteTable frees all contexts allocated for the table.
273  The parameter ctxt points to the first context of the table.
274  The parameter recursive is TRUE if the referred context must be freed.
275  ----------------------------------------------------------------------*/
276static void DeleteTable (PtrProCtl ctxt, ThotBool recursive)
277{
278  PtrProCtl           next;
279  int                 i;
280
281  while (ctxt)
282    {
283      i = 0;
284      while (i < MAX_ENTRIES && ctxt->ProEntries[i].ProName)
285        {
286          TtaFreeMemory (ctxt->ProEntries[i].ProName);
287          if (recursive)
288            DeleteTable (ctxt->ProEntries[i].ProSubModule, FALSE);
289          i++;
290        }
291      /* free the current context and manage the next one */
292      next = ctxt->ProNext;
293      TtaFreeMemory (ctxt);
294      ctxt = next;
295    }
296}
297
298
299/*----------------------------------------------------------------------
300  SearchModule searchs a module in the module table and return the
301  pointer to current entry.
302  ----------------------------------------------------------------------*/
303static ProElement *SearchModule (char *name)
304{
305  PtrProCtl        current;
306  int              i = 0;
307  ThotBool         found;
308
309  if (name == NULL)
310    return NULL;
311
312  /* check the current list of modules */
313  current = ModuleTable;
314  found = FALSE;
315  while (!found && current)
316    {
317      i = 0;
318      while (i < MAX_ENTRIES && current->ProEntries[i].ProName &&
319             strcmp (name, current->ProEntries[i].ProName))
320        i++;
321      found = (i < MAX_ENTRIES && current->ProEntries[i].ProName);
322      if (!found)
323        current = current->ProNext;
324    }
325  if (found)
326    return &(current->ProEntries[i]);
327  else
328    return NULL;
329}
330
331
332/*----------------------------------------------------------------------
333  ProcessDefinition : Recursive function that helps
334  building the profile table
335  ----------------------------------------------------------------------*/
336static void ProcessDefinition (char *element)
337{
338  ProElement      *pEntry;
339  PtrProCtl        ctxt;
340  int              i;
341  
342  if (*element == PROFILE_START)
343    {
344      /*
345       * It's a profile definition -> insert it in the Profile table
346       * Remove the start tag and the end tag
347       */
348      i = 1;
349      while (element[i] != PROFILE_END)
350        i++;
351      element[i] = EOS;
352      /* The new profile in progress */
353      CurrentModule = AddProfile (&element[1]);
354      CurrentEntries = 0;
355    }
356  else if (*element == DOCTYPE_START)
357    {
358      /*
359       * It's a document profile definition -> insert it in the doctype table
360       * Remove the start tag and the end tag
361       */
362      i = 1;
363      while (element[i] != DOCTYPE_END)
364        i++;
365      element[i] = EOS;
366      /* The new profile in progress */
367      CurrentModule = AddDoctype (&element[1]);
368      CurrentEntries = 0;
369    }
370  else if (*element == MODULE_START)
371    {
372      /*
373       * It's a module definition -> insert it in the Definiton table
374       * Remove the start tag and the end tag
375       */
376      i = 1;
377      while (element[i] != MODULE_END)
378        i++;
379      element[i] = EOS;
380
381      /* Is the module already declared? */
382      pEntry = SearchModule (&element[1]);
383      if (pEntry == NULL)
384        /* The new profile in progress */
385        CurrentModule = AddModule (&element[1]);
386      else
387        /* The new profile in progress */
388        CurrentModule = pEntry->ProSubModule;
389      CurrentEntries = 0;
390    }
391  else if (*element == MODULE_REF)
392    {
393      /*
394       * The element is a module inclusion -> insert it in the module
395       * or the profile in progress.
396       * Skip the MODULE_REF tag
397       */
398      pEntry = SearchModule (&element[1]);
399      if (pEntry == NULL)
400        {
401          /* the module is not already declared */
402          ctxt = AddModule (&element[1]);
403        }
404      else
405        ctxt = pEntry->ProSubModule;
406      /* add the new entry in the current profile or module */
407      AddInTable (&element[1], TRUE, FALSE, FALSE, ctxt, CurrentEntries, CurrentModule);
408      CurrentEntries++;
409    }
410  else if (*element == GUI_REF)
411    {
412      /*
413       * The element is a gui -> insert it in the module
414       * or the profile in progress.
415       * Skip the GUI_REF tag
416       */
417
418      /* add the new entry in the current profile or module */
419      AddInTable (&element[1], FALSE, FALSE, TRUE, NULL, CurrentEntries, CurrentModule);
420      CurrentEntries++;
421    }
422  else
423    {
424      /*
425       * The element is a function -> insert it in the module
426       * or the profile in progress.
427       * Look for and skip the EDITION_REF tag
428       */
429
430      /* add the new entry in the current profile or module */
431      if (*element == EDITING_REF)
432        AddInTable (&element[1], FALSE, TRUE, FALSE, NULL, CurrentEntries, CurrentModule);
433      else
434        AddInTable (element, FALSE, FALSE, FALSE, NULL, CurrentEntries, CurrentModule);
435      CurrentEntries++;
436    }
437}
438
439/*-----------------------------------------------------------------------
440  AddFunctionsAndGuis keep in the function table (resp. gui) the list of
441  functions (resp. gui)declared in the list of contexts.
442  ----------------------------------------------------------------------*/
443static void AddFunctionsAndGuis (PtrProCtl ctxt, PtrProCtl functionTable)
444{
445  int           i;
446
447  while (ctxt)
448    {
449      i = 0;
450      while (i < MAX_ENTRIES && ctxt->ProEntries[i].ProName)
451        {
452          if (ctxt->ProEntries[i].ProIsModule)
453            /* add functions and gui of the sub-module */
454            AddFunctionsAndGuis (ctxt->ProEntries[i].ProSubModule, functionTable);
455          else
456            {
457              if(ctxt->ProEntries[i].ProGui)
458                  DLList_Append(GuiList, TtaStrdup(ctxt->ProEntries[i].ProName));
459              else
460                {
461                  AddInTable (ctxt->ProEntries[i].ProName, FALSE,
462                              ctxt->ProEntries[i].ProEdit, FALSE, NULL,
463                              NbFunctions, functionTable);
464                  NbFunctions++;
465                }
466            }
467          /* next entry */
468          i++;
469        }
470      /* next context */
471      ctxt = ctxt->ProNext;
472    }
473}
474
475/*----------------------------------------------------------------------
476  SortFunctionTable generates the function table in ascending
477  order.
478  The parameter checkEdit will return TRUE if alomst one editing function
479  is available in the generated table.
480  ----------------------------------------------------------------------*/
481static void SortFunctionTable (PtrProCtl ctxt)
482{
483  char         *ptr;
484  int           i, j, index;
485  ThotBool      RO;
486
487  /* copy the list of contexts in a large table */
488  SortedFunctionTable = (char **) TtaGetMemory (NbFunctions * sizeof (char *));
489  FunctionRO = (ThotBool *) TtaGetMemory (NbFunctions * sizeof (ThotBool));
490  index = 0;
491  EnableEdit = FALSE;
492  while (ctxt && index < NbFunctions)
493    {
494      i = 0;
495      while (i < MAX_ENTRIES && ctxt->ProEntries[i].ProName)
496        {
497          if (ctxt->ProEntries[i].ProEdit)
498            {
499              /* there is almost one editing function */
500              EnableEdit = TRUE;
501              FunctionRO[index] = FALSE;
502            }
503          else
504            FunctionRO[index] = TRUE;
505          SortedFunctionTable[index] = TtaStrdup (ctxt->ProEntries[i].ProName);
506          index++;
507          /* next entry */
508          i++;
509        }
510      /* next context */
511      ctxt = ctxt->ProNext;
512    }
513
514  /* sort the large table */
515  for (i = 0 ; i < NbFunctions; i++)
516    {
517      index = i;
518      for (j = i+1; j < NbFunctions; j++)
519        if (strcmp (SortedFunctionTable[j], SortedFunctionTable[index]) <= 0)
520          index = j;
521      ptr = SortedFunctionTable[index];
522      SortedFunctionTable[index] = SortedFunctionTable[i];
523      SortedFunctionTable[i] = ptr;
524      RO =  FunctionRO[index];
525      FunctionRO[index] =  FunctionRO[i];
526      FunctionRO[i] = RO;
527    }
528}
529
530
531/*-----------------------------------------------------------------------
532  FunctionInProfile returns TRUE if the function is defined in the
533  document profile.
534  ----------------------------------------------------------------------*/
535static ThotBool FunctionInProfile (char *name, PtrProCtl ctxt)
536{
537  int           i;
538
539  while (ctxt)
540    {
541      i = 0;
542      while (i < MAX_ENTRIES && ctxt->ProEntries[i].ProName)
543        {
544          if (ctxt->ProEntries[i].ProIsModule)
545            {
546              if (FunctionInProfile (name, ctxt->ProEntries[i].ProSubModule))
547                /* stop if the function is founs this sub-module */
548                return TRUE;
549            }
550          else if (!strcmp (name, ctxt->ProEntries[i].ProName))
551            {
552              /* the function is declared in that document profile */
553              return TRUE;
554            }
555          /* next entry */
556          i++;
557        }
558      /* next context */
559      ctxt = ctxt->ProNext;
560    }
561  return FALSE;
562}
563
564/*----------------------------------------------------------------------
565  Prof_BelongTable searchs a function in the function table and returns
566  TRUE if the function exists.
567  ----------------------------------------------------------------------*/
568ThotBool Prof_BelongTable (const char *name)
569{
570  int              left, right, middle, i;
571  ThotBool         found = FALSE;
572
573  if (NbFunctions == 0)
574    /* All functions are allowed */
575    return TRUE;
576
577  /* Dichotomic search */
578  left = middle = 0;
579  right = NbFunctions - 1;
580 
581  while (left <= right && !found)
582    {
583      middle = (right + left) / 2;
584      i = strcmp (SortedFunctionTable[middle], name);
585      if (i == 0)
586        found = TRUE;
587      else if (i < 0)
588        left = middle + 1;
589      else
590        right = middle - 1;
591    }
592  return found;
593}
594
595
596/*----------------------------------------------------------------------
597  Prof_BelongDoctype searchs a function in the function table.
598  Returns:
599  -1: the function is unknown
600  0: the function must be hidden
601  1: the function is accepted
602  ----------------------------------------------------------------------*/
603int Prof_BelongDoctype (const char *name, int docProfile, ThotBool RO)
604{
605  int     left, right, middle, i;
606
607  if (NbFunctions == 0 || docProfile == 0 || name == NULL)
608    /* no specific profile */
609    return -1;
610
611  /* Dichotomic search */
612  left = middle = 0;
613  right = NbFunctions - 1;
614  if (!strcmp (name, "CreateRuby") && docProfile == L_Strict)
615    /* refused */
616    return 0;
617  if (!strcmp (name, "TtcUndo") ||
618      !strcmp (name, "TtcRedo") ||
619      !strcmp (name, "StopTransfer"))
620    // don't change the current status
621    return -1;
622  if (!strcmp (name, "TtcCopySelection"))
623    return 1; /* always active */
624  if (!strcmp (name, "TtcCutSelection") ||
625      !strcmp (name, "TtcDeleteSelection") ||
626      !strcmp (name, "ZoomIn") ||
627      !strcmp (name, "ZoomOut") ||
628      !strcmp (name, "ZoomNormal") ||
629      !strcmp (name, "SpellCheck") ||
630      !strcmp (name, "PasteBuffer"))
631    {
632      if (RO)
633        return 0; /* refused */
634      else
635        return 1; /* always active */
636    }
637
638  while (left <= right)
639    {
640      middle = (right + left) / 2;
641      i = strcmp (SortedFunctionTable[middle], name);
642      if (i == 0)
643        {
644          /* check the profile value */
645          if (FunctionMask[middle] == 0)
646            /* not defined */
647            return -1;
648          else if (FunctionMask[middle] & docProfile)
649            {
650              if (RO && !FunctionRO[middle])
651                /* refused */
652                return 0;
653              else
654                /* accepted */
655                return 1;
656            }
657          else
658            /* refused */
659            return 0;
660        }
661      else if (i < 0)
662        left = middle + 1;
663      else
664        right = middle - 1;
665    }
666  return -1;
667}
668
669/*-----------------------------------------------------------------------
670  Prof_InitTable: Seek the current profile file and init tables
671  ----------------------------------------------------------------------*/
672void Prof_InitTable (char *profile)
673{
674  FILE               *profFile;
675  char               *ptr, *prof;
676  char                buffer[MAX_LENGTH];
677  int                 i, j;
678  
679  /* open the profile file */
680  ptr = TtaGetEnvString ("Profiles_File");
681  if (ptr && *ptr)
682    {
683      if (SearchFile (ptr, 2, buffer))
684        {
685          profFile = TtaReadOpen (buffer);
686          /* if the caller didn't specify any profile, we use the one
687             given in the registry */
688          strcpy (UserProfile, "Editor");
689          if (profile && *profile)
690            {
691              if (strstr (profile, "(editor)"))
692                /* avoid to use a dead profile */
693                strcpy (UserProfile, "Editor");
694              else if (strstr (profile, "browser"))
695                /* avoid to use a dead profile */
696                strcpy (UserProfile, "Browser");
697              else if (strstr (profile, "display"))
698                /* avoid to use a dead profile */
699                strcpy (UserProfile, "Display");
700              else
701                strcpy (UserProfile, profile);
702            }
703
704          prof = TtaGetEnvString ("CURRENT_PROFILE");
705          ptr = NULL;
706          if (prof)
707            ptr = strstr (prof, "Lite");
708          if (ptr)
709            {
710              strcat (UserProfile, "_Lite");
711              i = 0;
712              do
713                {
714                  ptr = strstr (++ptr, "+");
715                  i++;
716                }
717              while (ptr);
718              if (i > 1)
719                {
720                   sprintf (buffer, "%d", i);
721                   strcat (UserProfile, buffer);
722                }
723             }
724
725          /* Fill a profile and module tables */
726          while (fgets (ProfileBuff, sizeof (ProfileBuff), profFile))
727            {
728              SkipAllBlanks (ProfileBuff);
729              /* skip comments */
730              if (strlen (ProfileBuff) >=2 && ProfileBuff[0] != '#')
731                ProcessDefinition (ProfileBuff);
732            }
733          TtaReadClose (profFile);
734        }
735    }
736
737  
738  /* All functions are available when:
739   * - the profiles file doesn't exist
740   * - or there is no specific user profile
741   * - or the user profile is None
742   */
743  if (NbProfiles > 0 && UserProfile[0] != EOS &&  strcmp (UserProfile, "None"))
744    {
745      CheckProfile = TRUE;
746      /* Now build the list of current available functions */
747      if (UserProfContext)
748        {
749
750          FunctionTable = (PtrProCtl) TtaGetMemory (sizeof (Profile_Ctl));
751          memset (FunctionTable, 0, sizeof (Profile_Ctl));
752
753          GuiList = DLList_Create();
754          GuiList->destroyElement = (Container_DestroyElementFunction)TtaFreeMemory;
755          
756          AddFunctionsAndGuis (UserProfContext, FunctionTable);
757
758          /* generate a sorted list of available functions */
759          SortFunctionTable (FunctionTable);
760          /* delete the function table */
761          if (FunctionTable)
762            {
763              DeleteTable (FunctionTable, FALSE);
764              FunctionTable = NULL;
765            }
766        }
767    }
768
769  /* associate a mask to each function in the table */
770  FunctionMask = (int *) TtaGetMemory (NbFunctions * sizeof (int));
771  for (i = 0; i < NbFunctions; i++)
772    {
773      FunctionMask[i] = 0;
774      for (j = 0; j < NbDoctypes; j++)
775        {
776          if (FunctionInProfile (SortedFunctionTable[i],
777                                 DoctypeTable->ProEntries[j].ProSubModule))
778            {
779              if (strstr (DoctypeTable->ProEntries[j].ProName, "Transitional"))
780                FunctionMask[i] = (FunctionMask[i] | L_TransitionalValue);
781              else if (strstr (DoctypeTable->ProEntries[j].ProName, "Strict"))
782                FunctionMask[i] = (FunctionMask[i] | L_StrictValue);
783              else if (strstr (DoctypeTable->ProEntries[j].ProName, "Basic"))
784                FunctionMask[i] = (FunctionMask[i] | L_BasicValue);
785              else if (strstr (DoctypeTable->ProEntries[j].ProName, "1.1"))
786                FunctionMask[i] = (FunctionMask[i] | L_StrictValue | L_RubyValue);
787              else if (strstr (DoctypeTable->ProEntries[j].ProName, "Ruby"))
788                FunctionMask[i] = (FunctionMask[i] | L_RubyValue);
789              else if (strstr (DoctypeTable->ProEntries[j].ProName, "MathML"))
790                FunctionMask[i] = (FunctionMask[i] | L_MathML);
791              else if (strstr (DoctypeTable->ProEntries[j].ProName, "SVG"))
792                FunctionMask[i] = (FunctionMask[i] | L_SVG);
793              else if (strstr (DoctypeTable->ProEntries[j].ProName, "Annot"))
794                FunctionMask[i] = (FunctionMask[i] | L_Annot);
795              else if (strstr (DoctypeTable->ProEntries[j].ProName, "Bookmarks"))
796                FunctionMask[i] = (FunctionMask[i] | L_Bookmarks);
797              else if (strstr (DoctypeTable->ProEntries[j].ProName, "CSS"))
798                FunctionMask[i] = (FunctionMask[i] | L_CSS);
799              else if (strstr (DoctypeTable->ProEntries[j].ProName, "Text"))
800                FunctionMask[i] = (FunctionMask[i] | L_TEXT);
801            }
802        }
803    }
804  /* delete the modules table */
805  DeleteTable (ModuleTable, TRUE);
806  ModuleTable = NULL;
807  NbModules = 0;
808  /* delete the doctype table */
809  DeleteTable (DoctypeTable, TRUE);
810  DoctypeTable = NULL;
811  NbDoctypes = 0;
812}
813
814
815/*-----------------------------------------------------------------------
816  Prof_FreeTable: Remove profile tables
817  ----------------------------------------------------------------------*/
818void Prof_FreeTable ()
819{
820  int i;
821
822  /* delete the profiles table */
823  DeleteTable (ProfileTable, TRUE);
824  ProfileTable = NULL;
825  NbProfiles = 0;
826  UserProfContext = NULL;
827  /* delete the function table */
828  for (i = 0; i < NbFunctions; i++)
829    TtaFreeMemory (SortedFunctionTable[i]);
830  TtaFreeMemory (SortedFunctionTable);
831  SortedFunctionTable = NULL;
832  TtaFreeMemory (FunctionMask);
833  FunctionMask = NULL;
834  TtaFreeMemory (FunctionRO);
835  FunctionRO = NULL;
836  NbFunctions = 0;
837  
838  /* delete the gui list */
839  DLList_Destroy(GuiList);
840}
841
842/*----------------------------------------------------------------------
843  TtaCanEdit returns TRUE if there is almost one editing function active.
844  ----------------------------------------------------------------------*/
845ThotBool TtaCanEdit ()
846{
847  return (EnableEdit);
848}
849
850/*----------------------------------------------------------------------
851  TtaGetProfileFileName:  Get the text for the profile file name.
852  name is a provided buffer of length characters to receive the name.
853  ----------------------------------------------------------------------*/
854void TtaGetProfileFileName (char *name, int length)
855{
856  char   *ptr;
857  char    buffer[MAX_LENGTH];
858
859  name[0] = EOS;
860  ptr = TtaGetEnvString ("Profiles_File");
861  if (ptr && *ptr)
862    {
863      SearchFile (ptr, 2, buffer);
864      if (strlen (buffer) < (size_t)length)
865        strcpy (name, buffer);
866    }
867}
868
869/*----------------------------------------------------------------------
870  TtaGetProfilesItems:  Get the text for the profile menu items.
871  listEntries is a provided list of length pointers.
872  Returns the number of items
873  ----------------------------------------------------------------------*/
874int TtaGetProfilesItems (char **listEntries, int length)
875{
876  PtrProCtl     ctxt;
877  int           nbelem = 0;
878  int           i;
879
880  ctxt = ProfileTable;
881  while (ctxt && nbelem < NbProfiles && nbelem < length)
882    {
883      i = 0;
884      while (i < MAX_ENTRIES && ctxt->ProEntries[i].ProName)
885        {
886          listEntries[nbelem] = ctxt->ProEntries[i].ProName;
887          i++;
888          nbelem++;
889        }
890      ctxt = ctxt->ProNext;
891    }
892  return nbelem;
893}
894
895
896/*----------------------------------------------------------------------
897  Prof_ShowSeparator : determines if a separator must be displayed
898  in the menu interface. Two consecutive separators musn't be displayed
899  ----------------------------------------------------------------------*/
900ThotBool Prof_ShowSeparator (Menu_Ctl *ptrmenu, int item, char LastItemType)
901{  
902  return !(LastItemType == 'S' || item == 0);
903}
904
905
906/*-----------------------------------------------------------------------
907  Prof_ShowButton : Add a button if the function associated to that button
908  belongs to the user profile
909  ----------------------------------------------------------------------*/
910ThotBool Prof_ShowButton (char *FunctionName)
911{
912  return (Prof_BelongTable (FunctionName));
913}
914
915
916/*----------------------------------------------------------------------
917  Prof_ShowSubMenu : Check if a submenu has to be displayed.
918  A submenu musn't be displayed if it contains no entry
919  ----------------------------------------------------------------------*/
920ThotBool Prof_ShowSubMenu (Menu_Ctl *ptrsubmenu)
921{
922  int      item    = 0;
923  
924  if (ptrsubmenu->ItemsNb == 0 || ptrsubmenu == NULL)
925    return FALSE;
926  while (item < ptrsubmenu->ItemsNb)
927    {
928      if (ptrsubmenu->ItemsList[item].ItemType != 'S')
929        return TRUE;
930      item ++;
931    }
932  return FALSE;
933}
934
935/*----------------------------------------------------------------------
936  Prof_ShowMenu : Check if a menu has to be displayed. A menu mustn't be
937  displayed if it contains no entry.
938  -----------------------------------------------------------------------*/
939ThotBool Prof_ShowMenu (Menu_Ctl *ptrmenu)
940{
941  int      item    = 0;
942
943  if (!CheckProfile)
944    /* there is no user profile, do not erase any menu */
945    return TRUE;
946  else if (ptrmenu == NULL)
947    /* this should not happen... */
948    return FALSE;
949  else if (ptrmenu->MenuAttr)
950    /* check if the attr and select menu are in the profile */
951    return (Prof_BelongTable ("MenuAttribute"));
952  else if (ptrmenu->MenuSelect)
953    return (Prof_BelongTable ("MenuSelection"));    
954  else if (ptrmenu->ItemsNb == 0)
955    /* an empty menu has to be removed */
956    return FALSE;
957
958  /* check if the menu is only composed of empty sub menus and separators */
959  while (item < ptrmenu->ItemsNb)
960    {
961      if (ptrmenu->ItemsList[item].ItemType != 'S')
962        {
963          if (ptrmenu->ItemsList[item].ItemType == 'M')
964            {
965              if (Prof_ShowSubMenu (ptrmenu->ItemsList[item].SubMenu)) 
966                /* there is at least a non empty sub menu */
967                return TRUE;
968            } 
969          else
970            /* there is at least a standard item */
971            return TRUE;
972        }
973      item ++;
974    }
975  return FALSE;
976}
977
978
979/*----------------------------------------------------------------------
980  Prof_ShowGUI : Check if a GUI element has to be displayed.
981  -----------------------------------------------------------------------*/
982ThotBool Prof_ShowGUI (const char* name)
983{
984  ThotBool res = FALSE;
985  ForwardIterator iter = DLList_GetForwardIterator(GuiList);
986  DLListNode      node;
987  ITERATOR_FOREACH(iter, DLListNode, node)
988    {
989      if(!strcmp((const char*)node->elem, name))
990        {
991          res = TRUE;
992          break;
993        }
994    }
995  TtaFreeMemory(iter);
996  return res;
997}