home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / libstyle / stystack.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  12.7 KB  |  587 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /* styleStack used to hold a stack of tags and associated styles
  20.  *
  21.  * Designed and Implemented by Lou Montulli '97
  22.  */
  23.  
  24.  
  25. #include "xp.h"
  26. #include "libmocha.h"
  27. #include "stystruc.h"
  28. #include "stystack.h"
  29. #include "jsspriv.h"
  30.  
  31. /* simple stack implementation for style/tag stack 
  32.  * why don't we have an XP Stack?
  33.  */
  34. #define INITIAL_STACK_SIZE 10
  35. #define INCREASE_STACK_BY  5
  36.  
  37. typedef struct {
  38.  
  39.     StyleStruct *style;
  40.     TagStruct   *tag;
  41.  
  42. } TagAndStyleAssoc;
  43.  
  44. typedef struct _SML_StyleAndTagStack {
  45.     StyleAndTagStackInterface  *vtable;
  46.     int32                       refcount;
  47.  
  48.     /* private data */
  49.     XP_Bool            save_stack;
  50.     TagAndStyleAssoc **tag_stack;
  51.     int32              tag_stack_size;
  52.     int32              tag_stack_first_unused_index;
  53.  
  54.     MWContext         *context;
  55.     StyleObject          *tags;
  56.     StyleObject          *classes;
  57.     StyleObject          *ids;
  58.  
  59. } SML_StyleAndTagStack;
  60.  
  61. /* specify whether to keep the stack or not.
  62.  * when the stack is OFF (as it is at initalization)
  63.  * adding to the stack is a noop
  64.  */
  65. void
  66. SML_SetSaveOn(SML_StyleAndTagStack *self, XP_Bool on_flag)
  67. {
  68.     self->save_stack = on_flag;
  69. }
  70.  
  71. XP_Bool
  72. SML_IsSaveOn(SML_StyleAndTagStack *self)
  73. {
  74.     return self->save_stack;
  75. }
  76.  
  77. /* 
  78.  * allocate TagStrucs from a pool to speed up
  79.  * the application
  80.  */
  81. static XP_AllocStructInfo TagStructAlloc =
  82.   { XP_INITIALIZE_ALLOCSTRUCTINFO(sizeof(TagStruct)) };
  83.  
  84. TagStruct *
  85. SML_NewTagStruct(SML_StyleAndTagStack *self, char *name, char *class_name, char *id)
  86. {
  87.     TagStruct *tag;
  88.  
  89.     if(!name)
  90.         return NULL;
  91.  
  92.     /* 
  93.      * allocate TagStrucs from a pool to speed up
  94.      * the application
  95.      */
  96.     tag = (TagStruct*) XP_AllocStructZero(&TagStructAlloc); 
  97.     if(!tag)
  98.         return(NULL);
  99.  
  100.     
  101.     tag->name = name;
  102.     if(class_name)
  103.         tag->class_name = class_name;
  104.     if(id)
  105.         tag->id = id;
  106.  
  107.     return(tag);
  108. }
  109.  
  110. void
  111. SML_FreeTagStruct(SML_StyleAndTagStack *self, TagStruct *tag)
  112. {
  113.     if(!tag)
  114.         return;
  115.  
  116.     XP_FREEIF(tag->name);
  117.     XP_FREEIF(tag->class_name);
  118.     XP_FREEIF(tag->id);
  119.     /* 
  120.      * return the TagStruct to the pool
  121.      */
  122.     XP_FreeStruct(&TagStructAlloc, tag); 
  123.     tag = NULL; 
  124. }
  125.  
  126.  
  127. /* 
  128.  * allocate TagAndStyleAssoc from a pool to speed up
  129.  * the application
  130.  */
  131. static XP_AllocStructInfo TagAndStyleAssocAlloc =
  132.   { XP_INITIALIZE_ALLOCSTRUCTINFO(sizeof(TagAndStyleAssoc)) };
  133.  
  134. TagAndStyleAssoc *
  135. sml_new_assoc(SML_StyleAndTagStack *self, TagStruct *tag, StyleStruct *style)
  136. {
  137.     TagAndStyleAssoc *new_assoc;
  138.  
  139.     if(!tag || !style)
  140.     {
  141.         XP_ASSERT(0);
  142.         return NULL;
  143.     }
  144.  
  145.     /* 
  146.      * allocate TagAndStyleAssoc from a pool to speed up
  147.      * the application
  148.      */
  149.     new_assoc = (TagAndStyleAssoc*) XP_AllocStructZero(&TagAndStyleAssocAlloc);
  150.  
  151.     if(!new_assoc)
  152.         return NULL;
  153.  
  154.     new_assoc->tag = tag;
  155.     new_assoc->style = style;
  156.  
  157.     return new_assoc;
  158. }
  159.  
  160. void
  161. sml_free_TagAndStyleAssoc(SML_StyleAndTagStack *self,TagAndStyleAssoc *assoc)
  162. {
  163.     if(!assoc)    
  164.         return;
  165.  
  166.     SML_FreeTagStruct(self, assoc->tag);
  167.     STYLESTRUCT_Delete(assoc->style);
  168.  
  169. #ifdef DEBUG
  170.     assoc->tag = (TagStruct   *)-1;
  171.     assoc->style = (StyleStruct *)-1;
  172. #endif 
  173.  
  174.     /* 
  175.      * return the TagAndStyleAssoc to the pool
  176.      */
  177.     XP_FreeStruct(&TagAndStyleAssocAlloc, assoc); 
  178.     assoc = NULL; 
  179. }
  180.  
  181. void
  182. sml_free_stack(SML_StyleAndTagStack *self)
  183. {
  184.     int i;
  185.  
  186.     if(self->tag_stack)
  187.     {
  188.         for(i = 0; i < self->tag_stack_first_unused_index; i++)
  189.         {
  190.             sml_free_TagAndStyleAssoc(self, self->tag_stack[i]);
  191.         }
  192.     
  193.         XP_FREE(self->tag_stack);
  194.     }
  195.                 
  196.     self->tag_stack_size = 0;
  197.     self->tag_stack_first_unused_index = 0;
  198.     self->tag_stack = NULL;
  199.  
  200. }
  201.  
  202.  
  203. void
  204. sml_expand_stack(SML_StyleAndTagStack *self)
  205. {
  206.     if(self->tag_stack)
  207.     {
  208.         self->tag_stack_size += INCREASE_STACK_BY;
  209.         self->tag_stack = XP_REALLOC(self->tag_stack,
  210.                                       self->tag_stack_size*sizeof(TagAndStyleAssoc*));
  211.     }
  212.     else
  213.     {
  214.         self->tag_stack_size = INITIAL_STACK_SIZE;
  215.         self->tag_stack = XP_CALLOC(self->tag_stack_size, sizeof(TagAndStyleAssoc*));
  216.     }
  217.  
  218.     if(!self->tag_stack)
  219.       {
  220.         self->tag_stack_first_unused_index = 0;
  221.         self->tag_stack_size = 0;
  222.       }
  223. }
  224.  
  225. void
  226. ss_add_to_stack(SML_StyleAndTagStack *self, TagAndStyleAssoc *pair)
  227. {
  228.     if(self->tag_stack_size <= self->tag_stack_first_unused_index)
  229.         sml_expand_stack(self);
  230.  
  231.     if(self->tag_stack)
  232.     {
  233.         self->tag_stack[self->tag_stack_first_unused_index++] = pair;
  234.     }
  235.     else
  236.     {
  237.         sml_free_TagAndStyleAssoc(self, pair);
  238.     }
  239. }
  240.  
  241.  
  242. PushTagStatus 
  243. SML_PushTag(SML_StyleAndTagStack *self, char *name, char *class_name, char *id)
  244. {
  245.     TagStruct *new_tag;
  246.     StyleStruct *ss;
  247.     TagAndStyleAssoc *assoc;
  248.  
  249.     if(!self->save_stack)
  250.         return PUSH_TAG_ERROR;
  251.  
  252.     new_tag = SML_NewTagStruct(self, name, class_name, id);
  253.     if(!new_tag)
  254.         return PUSH_TAG_ERROR;
  255.  
  256.      ss = STYLESTRUCT_Factory_Create();
  257.  
  258.     if(!ss)
  259.     {
  260.         SML_FreeTagStruct(self, new_tag);
  261.         return PUSH_TAG_ERROR;
  262.     }
  263.  
  264.     assoc = sml_new_assoc(self, new_tag, ss);
  265.     
  266.     if(!assoc)
  267.     {
  268.         SML_FreeTagStruct(self, new_tag);
  269.         STYLESTRUCT_Delete(ss);
  270.         return PUSH_TAG_ERROR;
  271.     }
  272.     
  273.     ss_add_to_stack(self, assoc);    
  274.  
  275.     /* add call to style sheet parser here to fill in style struct */
  276.     jss_GetStyleForTopTag((StyleAndTagStack*)self);
  277.  
  278.     return(PUSH_TAG_SUCCESS);
  279. }
  280.  
  281. /* pop a tag from within the stack
  282.  * The stack is indexed from the top element.
  283.  * the zero'th element is the top of the stack
  284.  */
  285. void 
  286. SML_PopTagByIndex(SML_StyleAndTagStack *self, char *name, int32 index)
  287. {
  288.  
  289.     TagAndStyleAssoc *assoc;
  290.     /* index from the top of the stack */
  291.     int32 real_index = self->tag_stack_first_unused_index - 1 - index;
  292.  
  293.     if(self->tag_stack_first_unused_index < real_index+1 || real_index < 0)
  294.         return;
  295.  
  296.     assoc = self->tag_stack[real_index];
  297.     sml_free_TagAndStyleAssoc(self, assoc);
  298.  
  299.     /* shift the stack down */
  300.     if(real_index < self->tag_stack_first_unused_index-1)
  301.         XP_MEMMOVE(&self->tag_stack[real_index],
  302.               &self->tag_stack[real_index+1],
  303.               index*sizeof(TagAndStyleAssoc*));
  304.  
  305.     /* zero last unused index for debugging purposes */
  306.     self->tag_stack_first_unused_index--;
  307.     self->tag_stack[self->tag_stack_first_unused_index] = 0;
  308. }
  309.  
  310. void 
  311. SML_PopTag(SML_StyleAndTagStack *self, char *name)
  312. {
  313.     SML_PopTagByIndex(self, name, 0);
  314. }
  315.  
  316. /* the zero'th index is the top of the stack 
  317.  */
  318. TagAndStyleAssoc *
  319. sml_get_index(SML_StyleAndTagStack *self, int32 index)
  320. {
  321.     int32 real_index = (self->tag_stack_first_unused_index-1) - index;
  322.  
  323.     if(real_index < 0)
  324.         return NULL;
  325.  
  326.     return(self->tag_stack[real_index]);
  327. }
  328.  
  329. /* the zero'th index is the bottom of the stack 
  330.  */
  331. TagAndStyleAssoc *
  332. sml_get_reverse_index(SML_StyleAndTagStack *self, int32 index)
  333. {
  334.     if(index >= self->tag_stack_first_unused_index)
  335.         return NULL;
  336.  
  337.     return(self->tag_stack[index]); 
  338. }
  339.  
  340. /* the zero'th index is the top of the stack 
  341.  */
  342. TagStruct * 
  343. SML_GetTagByIndex(SML_StyleAndTagStack *self, int32 index)
  344. {
  345.     TagAndStyleAssoc *assoc = sml_get_index(self, index);
  346.  
  347.     if(!assoc)
  348.         return NULL;
  349.  
  350.     return(assoc->tag);
  351. }
  352.  
  353. /* the zero'th index is the bottom of the stack 
  354.  */
  355. TagStruct * 
  356. SML_GetTagByReverseIndex(SML_StyleAndTagStack *self, int32 index)
  357. {
  358.     TagAndStyleAssoc *assoc = sml_get_reverse_index(self, index);
  359.  
  360.     if(!assoc)
  361.         return NULL;
  362.  
  363.     return(assoc->tag);
  364. }
  365.  
  366. /* the zero'th index is the top of the stack 
  367.  */
  368. StyleStruct * 
  369. SML_GetStyleByIndex(SML_StyleAndTagStack *self, int32 index)
  370. {
  371.     TagAndStyleAssoc *assoc = sml_get_index(self, index);
  372.  
  373.     if(!assoc)
  374.         return NULL;
  375.  
  376.     return(assoc->style);
  377. }
  378.  
  379. /* the zero'th index is the bottom of the stack 
  380.  */
  381. StyleStruct * 
  382. SML_GetStyleByReverseIndex(SML_StyleAndTagStack *self, int32 index)
  383. {
  384.     TagAndStyleAssoc *assoc = sml_get_reverse_index(self, index);
  385.  
  386.     if(!assoc)
  387.         return NULL;
  388.  
  389.     return(assoc->style);
  390. }
  391.  
  392. void
  393. SML_Delete(SML_StyleAndTagStack *self)
  394. {
  395.     self->refcount--;
  396.  
  397.     if(self->refcount > 0)
  398.         return;
  399.  
  400.     sml_free_stack(self);
  401.  
  402.     XP_FREE(self);
  403. }
  404.  
  405. void 
  406. SML_Purge(SML_StyleAndTagStack *self)
  407. {
  408.     sml_free_stack(self);
  409. }
  410.  
  411. void
  412. SML_Init(SML_StyleAndTagStack *self, MWContext *context)
  413. {
  414.     self->context = context;
  415. }
  416.  
  417. /* static vtable */
  418. const StyleAndTagStackInterface StyleAndTagStack_interface = {
  419.  
  420.     (void (*)(StyleAndTagStack *self, MWContext *context))
  421.         SML_Init,
  422.    (TagStruct * (*)(StyleAndTagStack *self, char *name, char *class_name, char *id))
  423.         SML_NewTagStruct,
  424.     (void (*)(StyleAndTagStack *self, TagStruct *tag))
  425.         SML_FreeTagStruct,
  426.     (PushTagStatus (*)(StyleAndTagStack *self, char *name, char *class_name, char *id))
  427.         SML_PushTag,
  428.     (void  (*)(StyleAndTagStack *self, char *name))
  429.         SML_PopTag,
  430.     (void  (*)(StyleAndTagStack *self, char *name, int32 index))
  431.         SML_PopTagByIndex,
  432.     (TagStruct * (*)(StyleAndTagStack *self, int32 index))
  433.         SML_GetTagByIndex,
  434.     (TagStruct * (*)(StyleAndTagStack *self, int32 index))
  435.         SML_GetTagByReverseIndex,
  436.     (StyleStruct * (*)(StyleAndTagStack *self, int32 index))
  437.         SML_GetStyleByIndex,
  438.     (StyleStruct * (*)(StyleAndTagStack *self, int32 index))
  439.         SML_GetStyleByReverseIndex,
  440.     (StyleStruct * (*)(StyleAndTagStack *self))
  441.         SML_Delete,
  442.     (StyleStruct * (*)(StyleAndTagStack *self))
  443.         SML_Purge,
  444.     (void (*)(StyleAndTagStack *self, XP_Bool on_flag))
  445.         SML_SetSaveOn,
  446.     (XP_Bool (*)(StyleAndTagStack *self))
  447.         SML_IsSaveOn
  448. };
  449.  
  450. StyleAndTagStack *
  451. SML_StyleStack_Factory_Create(void)
  452. {
  453.     /* initializer */
  454.     SML_StyleAndTagStack * self = (SML_StyleAndTagStack*)XP_CALLOC(1, sizeof(SML_StyleAndTagStack));
  455.    
  456.     if(!self)
  457.         return NULL;
  458.  
  459.     self->vtable = (void*)&StyleAndTagStack_interface;
  460.     self->refcount = 1;
  461.  
  462.     return (StyleAndTagStack*)self;
  463. }
  464.  
  465. void
  466. SML_SetObjectRefs(StyleAndTagStack *styleStack,
  467.                   StyleObject *tags,
  468.                   StyleObject *classes,
  469.                   StyleObject *ids)
  470. {
  471.     SML_StyleAndTagStack * self = (SML_StyleAndTagStack*)styleStack;
  472.  
  473.     self->tags = tags;
  474.     self->classes = classes;
  475.     self->ids = ids;
  476. }
  477.  
  478. /*
  479.  * Helper routine to assemble the JSSContext
  480.  */
  481. void
  482. sml_GetJSSContext(StyleAndTagStack *styleStack, JSSContext *jc)
  483. {
  484.     SML_StyleAndTagStack * self = (SML_StyleAndTagStack*)styleStack;
  485.  
  486.     /* Lookup document.tags */
  487.     jc->tags = self->tags;
  488.     
  489.     /* Lookup document.classes */
  490.     jc->classes = self->classes;
  491.     
  492.     /* Lookup up document.ids */
  493.     jc->ids = self->ids;
  494. }
  495.  
  496. #ifdef TEST_STYLESTACK
  497.  
  498. typedef struct {
  499.     char name[100];
  500.     char class_name[100];
  501.     char id[100];
  502. } test_struct;
  503.  
  504. test_struct test_table[] = {
  505.  
  506. {"h1", "class1", "id1"},
  507. {"h2", "class2", "id2"},
  508. {"h3", "class3", "id3"},
  509. {"h4", "class4", "id4"},
  510.  
  511. {"h5", "", "id1"},
  512. {"h6", "", "id2"},
  513. {"h7", "", "id3"},
  514. {"h8", "", "id4"},
  515.  
  516. {"h9", "class9", ""},
  517. {"h10", "class10", ""},
  518. {"h11", "class11", ""},
  519. {"h12", "class12", ""},
  520.  
  521. {"h13", "", ""},
  522. {"h14", "", ""},
  523. {"h15", "", ""},
  524. {"h16", "", ""},
  525.  
  526. {"", "", ""}
  527. };
  528.  
  529. void
  530. test_values(StyleAndTagStack * h)
  531. {
  532.     int i;
  533.  
  534.     for(i=0; *test_table[i].name; i++)
  535.         ;  /* null body */
  536.  
  537.     for(i--; i >= 0; i--)
  538.     {
  539.         test_struct *ts = &test_table[i];
  540.  
  541.         TagStruct *tag = STYLESTACK_GetTagByIndex(h, 0);
  542.  
  543.         if(strcmp(tag->name, ts->name))
  544.             printf("Error: names do not match: %s:%s\n", tag->name, ts->name);
  545.         else if(*ts->class && strcmp(tag->class, ts->class))
  546.             printf("Error: class names do not match: %s:%s\n", tag->class_name, ts->class_name);
  547.         else if(*ts->id && strcmp(tag->id, ts->id))
  548.             printf("Error: id names do not match: %s:%s\n", tag->id, ts->id);
  549.         else
  550.             printf("Success: retreival successful: %s\n", tag->name);
  551.  
  552.         STYLESTACK_PopTag(h, ts->name);
  553.     }
  554. }
  555.  
  556. int
  557. main(int argc, char *argv[])
  558. {
  559.     int i;
  560.     StyleAndTagStack * h;
  561.     StyleStruct *style;
  562.  
  563.  
  564.     h = SML_StyleStack_Factory_Create();
  565.  
  566.     if(!h)
  567.         exit(1);
  568.  
  569.     for(i=0; *test_table[i].name; i++)
  570.     {
  571.         test_struct *ts = &test_table[i];
  572.  
  573.         style = STYLESTACK_PushTag(h, ts->name, ts->class_name, ts->id);
  574.  
  575.         if(!style)
  576.             printf("stack (or malloc) error");
  577.     }
  578.  
  579.     test_values(h);
  580.  
  581.     printf("\nAll tests complete\n");
  582.         
  583.     exit(0);
  584. }
  585.  
  586. #endif /* TEST_STYLESTACK */
  587.