PageRenderTime 53ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

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