/* * * (c) COPYRIGHT MIT and INRIA, 1996. * Please first read the full copyright statement in file COPYRIGHT. * */ /* verbose mode */ /* #define DEBUG_CSS */ /* included headers */ #include "thot_gui.h" #include "thot_sys.h" #include "appaction.h" #include "application.h" #include "attribute.h" #include "document.h" #include "fileaccess.h" #include "genericdriver.h" #include "interface.h" #include "message.h" #include "pschema.h" #include "presentdriver.h" #include "thotmsg.h" #include "view.h" #include "StyleCss.h" #include "CssMsgTable.h" #include "UIcss.h" #include "StyleCss_f.h" #include "StyleRules_f.h" #include "StyleParser_f.h" #include "UIcss_f.h" CSSInfoPtr ListCSS[DocumentTableLength+1]; /* list of CSSInfos per doc */ int CssMsgTable; /* message table */ Document currentDocument = -1; /* id of current document */ int cssbasedlg; /* dialogs handles' min number */ extern CSSInfoPtr activecss[]; /* active(edited) CSS for each doc */ #ifdef DEBUG_CSS #define MSG(msg) fprintf(stderr,msg) #else static char *last_message = NULL; #define MSG(msg) last_message = msg #endif /************************************************************************* * * * CSS INIT AND CLOSURE FUNCTIONS * * * *************************************************************************/ /*------------------------------------------------------------------------ InitCSS : Called once at the begining of the program ----------------------------------------------------------------------*/ #ifdef __STDC__ void InitCSS (void) #else void InitCSS () #endif { int i; /* initialize the dialogs callback numbers base*/ cssbasedlg = TtaSetCallback (CSSCallbackHandle, NB_CSS_CALLBACKS); /* initialize misc vars */ for (i=0; i <= DocumentTableLength; i++) activecss[i] = NULL; } /*---------------------------------------------------------------------- CloseCSS ----------------------------------------------------------------------*/ #ifdef __STDC__ void CloseCSS (void) #else void CloseCSS () #endif { } /************************************************************************* * * * CSSInfo MANIPULATION FUNCTIONS * * * *************************************************************************/ /*------------------------------------------------------------------------ GetNewDocumentStyle : Creates a new CSS document style, inserts in the list and returns it. The pschema field remains NULL. params : doc : the document to which is applied the style name : the name given to this style sheet refcss : the css next to which the given css is inserted. if NULL, the css is inserted at the begining. before : tells if the css must be inserted before or after refcss. returns : a ptr on the CSSInfo when created, NULL otherwise. ------------------------------------------------------------------------*/ #ifdef __STDC__ CSSInfoPtr GetNewDocumentStyle (Document doc, char *name, CSSInfoPtr refcss, boolean before) #else CSSInfoPtr GetNewDocumentStyle (doc, name, refcss, before) Document doc; char *name; CSSInfoPtr refcss; boolean before; #endif { CSSInfoPtr css = NULL; CSSInfoPtr extcss = NULL; int i; if (GetCSSFromName (name, doc) != NULL) { /* a CSS with this name already exists */ #ifdef DEBUG_CSS fprintf (stderr, "GetNewDocumentStyle: This CSS already exists in document.\n"); #endif return css; } css = NewCSS (); if (css != NULL) { css->name = TtaStrdup(name); css->documents[doc] = TRUE; for (i=1; i<=DocumentTableLength; i++) if ((i != doc) && (extcss = GetCSSFromName (name, doc)) != NULL) { css->documents[i] = TRUE; extcss->documents[doc] = TRUE; } AddCSS (css, refcss, before, doc); } #ifdef DEBUG_CSS else fprintf (stderr, "GetNewDocumentStyle: The CSS hasn't been created.\n"); #endif return (css); } /*---------------------------------------------------------------------- AddCSS : adds a CSSInfo to the CSSInfo List, before or after a given css. If this one is null, the other one is added at the begining of the list. params : css : ptr on the CSSInfo to add. refcss : the css next to which the given css is inserted. if NULL, the css is inserted at the begining. before : tells if the css must be inserted before or after refcss. doc : document concerned by the style sheet ----------------------------------------------------------------------*/ #ifdef __STDC__ void AddCSS (CSSInfoPtr css, CSSInfoPtr refcss, boolean before, Document doc) #else void AddCSS (css, refcss, before, doc) CSSInfoPtr css; CSSInfoPtr refcss; boolean before; Document doc; #endif { if (css == NULL) return; if ((refcss == NULL) || (ListCSS[doc] == NULL) || (before && (refcss == ListCSS[doc]))) { css->nextcss = ListCSS[doc]; ListCSS[doc] = css; } else { if (before) /* refcss != ListCSS[doc] */ refcss = GetPrevCSS (doc, refcss); css->nextcss = refcss->nextcss; refcss->nextcss = css; } } /*---------------------------------------------------------------------- DeleteCSS : Deletes a CSSInfo from the list, remove the associated PSchemas and CSSRuleSchemas, frees memory, and updates views. params : css : ptr on the CSSInfo to delete. doc : the document refering to this Css ----------------------------------------------------------------------*/ #ifdef __STDC__ void DeleteCSS (CSSInfoPtr css, Document doc) #else void DeleteCSS (css, doc) CSSInfoPtr css; Document doc; #endif { CSSInfoPtr prevcss; CSSRuleSchemasPtr nextschemas; CSSRulePtr nextrules; DisplayMode dm; int i; dm = TtaGetDisplayMode (doc); TtaSetDisplayMode (doc, NoComputedDisplay); if (css) { /* removing CSSInfo from list */ if (css == ListCSS[doc]) ListCSS[doc] = css->nextcss; else { prevcss = ListCSS[doc]; while ((prevcss != NULL) && (prevcss->nextcss != css)) prevcss = prevcss->nextcss; if (prevcss != NULL) prevcss->nextcss = css->nextcss; else MSG ("DeleteCSS : given CSSInfo wasn't in list\n"); } /* deleting reference of this css in other documents */ for (i=1; i<=DocumentTableLength; i++) if ((i != doc) && (css->documents[i] == TRUE)) GetCSSFromName (css->name, (Document)i)->documents[doc] = FALSE; /* freeing memory */ if (css->css_rule) TtaFreeMemory (css->css_rule); while (css->ruleslist != NULL) DeleteRule(css->ruleslist, css, doc); while ((nextrules = css->badruleslist) != NULL) { css->badruleslist = css->badruleslist->nextrule; FreeRule(nextrules); } while (css->schemas != NULL) { TtaRemovePSchema (css->schemas->CssPSchema, doc, css->schemas->CssSSchema); RefreshDocViews(doc, css->schemas->CssSSchema); nextschemas = css->schemas->NextSchemas; TtaFreeMemory((char*)css->schemas); css->schemas = nextschemas; } TtaFreeMemory ((char*)css); } TtaSetDisplayMode (doc, dm); } /*---------------------------------------------------------------------- FreeCSS : Simply blasts a css from memory. Made to be used when closing a document, no coherence is kept, but with the other documents. params : css : ptr on the CSSInfo to delete. doc : the document refering to this Css ----------------------------------------------------------------------*/ #ifdef __STDC__ void FreeCSS (CSSInfoPtr css, Document doc) #else void FreeCSS (css, doc) CSSInfoPtr css; Document doc; #endif { CSSRuleSchemasPtr nextschemas; CSSRulePtr nextrules; int i; if (css) { /* deleting reference of this css in other documents */ for (i=1; i<=DocumentTableLength; i++) if ((i != doc) && (css->documents[i] == TRUE)) GetCSSFromName (css->name, (Document)i)->documents[doc] = FALSE; /* freeing memory */ if (css->css_rule) TtaFreeMemory (css->css_rule); while ((nextrules = css->ruleslist) != NULL) { css->ruleslist = css->ruleslist->nextrule; FreeRule(nextrules); } while ((nextrules = css->badruleslist) != NULL) { css->badruleslist = css->badruleslist->nextrule; FreeRule(nextrules); } while (css->schemas != NULL) { TtaRemovePSchema (css->schemas->CssPSchema, doc, css->schemas->CssSSchema); RefreshDocViews(doc, css->schemas->CssSSchema); nextschemas = css->schemas->NextSchemas; TtaFreeMemory((char*)css->schemas); css->schemas = nextschemas; } TtaFreeMemory ((char*)css); } } /*---------------------------------------------------------------------- FreeAllCSS : Deletes all CSSInfo from the list, remove the associated PSchemas and CSSRuleSchemas, and frees memory params : doc : the document refering to this Css ----------------------------------------------------------------------*/ #ifdef __STDC__ void FreeAllCSS (Document doc) #else void FreeAllCSS (doc) Document doc; #endif { CSSInfoPtr css; while ((css = ListCSS[doc]) != NULL) DeleteCSS(css, doc); } /*---------------------------------------------------------------------- FreeAllCSSForClose : Simply params : doc : the document refering to this Css ----------------------------------------------------------------------*/ #ifdef __STDC__ void FreeAllCSSForClose (Document doc) #else void FreeAllCSSForClose (doc) Document doc; #endif { CSSInfoPtr css; while ((css = ListCSS[doc]) != NULL) { ListCSS[doc] = css->nextcss; FreeCSS(css, doc); } } /*---------------------------------------------------------------------- NewCSS : allocates a new CSSInfo and initializes it. returns : a ptr on the created CSSInfo. ----------------------------------------------------------------------*/ #ifdef __STDC__ CSSInfoPtr NewCSS (void) #else CSSInfoPtr NewCSS () #endif { CSSInfoPtr css; int i; css = (CSSInfoPtr) TtaGetMemory (sizeof (CSSInfo)); if (css != NULL) { css->nextcss = NULL; css->name = NULL; css->filename = NULL; css->schemas = NULL; css->css_rule = NULL; css->ruleslist = NULL; css->badruleslist = NULL; for (i = 0; i <= DocumentTableLength; i++) css->documents[i] = FALSE; css->modified = FALSE; css->view_background_color = -1; css->magnification = -1000; } else { TtaDisplaySimpleMessage (INFO, CssMsgTable, CSS_OUT_OF_MEMORY); #ifdef DEBUG_CSS fprintf (stderr, "NewCSS: The CSS hasn't been created.\n"); #endif } return (css); } /*---------------------------------------------------------------------- GetCSSFromName : search for a CSS having a given name in the given document CSS' infos. params : name : string containing the name of the searched CSS doc : the document on whitch may be applyed the CSS. returns : a ptr on the CSSInfo having this name, NULL if not found ----------------------------------------------------------------------*/ #ifdef __STDC__ CSSInfoPtr GetCSSFromName(char *name, Document doc) #else CSSInfoPtr GetCSSFromName(name, doc) char *name; Document *doc; #endif { CSSInfoPtr css=ListCSS[doc]; if (name == NULL) return (NULL); while ((css !=NULL) && (strcmp (css->name, name))) css = css->nextcss; return (css); } /*---------------------------------------------------------------------- GetCSSName : returns the name of a css from its filename. params : filename : string containing the filename of the CSS returns : the name built, NULL if impossible to get it. ----------------------------------------------------------------------*/ #ifdef __STDC__ char *GetCSSName(char *filename) #else char *GetCSSName(filename) char *filename; #endif { char *name, *scanfile, safe; if (filename == NULL) return (NULL); scanfile = filename; while (*scanfile != EOS) if (*scanfile++ == '/') name = scanfile; scanfile = name + strlen(name) - strlen(CSS_FILE_EXTENSION); safe = *scanfile; *scanfile = EOS; name = TtaStrdup(name); *scanfile = safe; return (name); } /*---------------------------------------------------------------------- GetLastCSS : returns the last css of a document params : doc : the document whose last css is asked returns : a ptr on the last css, NULL if not found ----------------------------------------------------------------------*/ #ifdef __STDC__ CSSInfoPtr GetLastCSS(Document doc) #else CSSInfoPtr GetLastCSS(doc) Document doc; #endif { CSSInfoPtr css; if ((css=ListCSS[doc])==NULL) return (NULL); while (css->nextcss != NULL) css = css->nextcss; return (css); } /*---------------------------------------------------------------------- GetPrevCSS : returns the css before the given css of a document params : doc : the document whose last css is asked css : the css following the one searched returns : a ptr on the searched css, NULL if not found ----------------------------------------------------------------------*/ #ifdef __STDC__ CSSInfoPtr GetPrevCSS(Document doc, CSSInfoPtr css) #else CSSInfoPtr GetPrevCSS(doc, css) Document doc; CSSInfoPtr css; #endif { CSSInfoPtr scancss; if ((scancss=ListCSS[doc])==NULL) return (NULL); while ((scancss->nextcss != NULL)&&(scancss->nextcss !=css)) scancss = scancss->nextcss; if (scancss->nextcss != NULL) return (scancss); else return (NULL); } /*---------------------------------------------------------------------- MakeNamesList : recursive function that bulids the list of sheets names params : css : first css of sub-list scan : ptr on built string (where to append names) nb : nb of names copied size : size of previous css names returns : built string, number of names is modified, NULL if error. ----------------------------------------------------------------------*/ #ifdef __STDC__ static char *MakeNamesList(CSSInfoPtr css, char **scan, int *nb, int size) #else static char *MakeNamesList(css, scan, nb, size) CSSInfoPtr css; char *scan; int *nb; int size; #endif { char *names, *namescan, *myscan; if (css->nextcss == NULL) { /* alloc memory */ myscan = names = TtaGetMemory(size + strlen(css->name) + 1); if (myscan == NULL) { TtaDisplaySimpleMessage (INFO, CssMsgTable, CSS_OUT_OF_MEMORY); *nb=0; return (NULL); } /* copy name*/ namescan = css->name; while ((*myscan++ = *namescan++)!= EOS); *nb=1; } else /* not last */ { names = MakeNamesList(css->nextcss, scan, nb, size + strlen(css->name) + 1); if (names == NULL) return (NULL); namescan = css->name; myscan = *scan; while ((*myscan++ = *namescan++)!= EOS); (*nb)++; } *scan = myscan; return names; } /*---------------------------------------------------------------------- GetSheetsNames : collapse the name of every CSS of a document in a string, using '\0' as separator, and return the number of names in the generated string. params : doc : the document whose css names are listed. names : ptr on the string that will contain the names returns : number of names listed ----------------------------------------------------------------------*/ #ifdef __STDC__ int GetSheetsNames(Document doc, char **names) #else int GetSheetsNames(doc, names) char **names; Document doc; #endif { int nbnames; char *scan; if (ListCSS[doc] == NULL) { #ifdef DEBUG_CSS fprintf (stderr, "GetSheetsName: The list of names is empty.\n"); #endif *names = NULL; return (0); } *names = MakeNamesList(ListCSS[doc], &scan, &nbnames, 0); return (nbnames); } /************************************************************************* * * * CSSInfo MOVING FUNCTIONS * * * *************************************************************************/ /*------------------------------------------------------------------------ MoveCSSToFirst : moves a CSSInfo to the first place of the sheets list of the document : it will have the smallest priority. Doesn't do anything if the CSSInfo isn't already in the list. params : css : ptr on the CSSInfo to move doc : the document to which is applied the CSS. ------------------------------------------------------------------------*/ #ifdef __STDC__ void MoveCSSToFirst (CSSInfoPtr css, Document doc) #else void MoveCSSToFirst (css, doc) CSSInfoPtr css; Document doc; #endif { MoveCSSInList (css, ListCSS[doc], TRUE, doc); } /*------------------------------------------------------------------------ MoveCSSToLast : moves a CSSInfo to the last place of the sheets list of the document : it will have the bigest priority. Doesn't do anything if the CSSInfo isn't already in the list. params : css : ptr on the CSSInfo to move doc : the document to which is applied the CSS. ------------------------------------------------------------------------*/ #ifdef __STDC__ void MoveCSSToLast (CSSInfoPtr css, Document doc) #else void MoveCSSToLast (css, doc) CSSInfoPtr css; Document doc; #endif { CSSInfoPtr scancss; scancss = GetLastCSS(doc); if (scancss != NULL) MoveCSSInList (css, scancss, FALSE, doc); } /*------------------------------------------------------------------------ MoveCSSToNext : moves a CSSInfo to the next place of the sheets list of the document : it will have a bigger priority. Doesn't do anything if the CSSInfo isn't already in the list. params : css : ptr on the CSSInfo to move doc : the document to which is applied the CSS. ------------------------------------------------------------------------*/ #ifdef __STDC__ void MoveCSSToNext (CSSInfoPtr css, Document doc) #else void MoveCSSToNext (css, doc) CSSInfoPtr css; Document doc; #endif { if (css->nextcss != NULL) MoveCSSInList (css, css->nextcss, FALSE, doc); } /*------------------------------------------------------------------------ MoveCSSToPrev : moves a CSSInfo to the next place of the sheets list of the document : it will have a smaller priority. Doesn't do anything if the CSSInfo isn't already in the list. params : css : ptr on the CSSInfo to move doc : the document to which is applied the CSS. ------------------------------------------------------------------------*/ #ifdef __STDC__ void MoveCSSToPrev (CSSInfoPtr css, Document doc) #else void MoveCSSToPrev (css, doc) CSSInfoPtr css; Document doc; #endif { CSSInfoPtr prevcss; prevcss = GetPrevCSS(doc, css); if (prevcss != NULL) MoveCSSInList (css, prevcss, TRUE, doc); } /*------------------------------------------------------------------------ MoveCSSInList : moves a CSSInfo to the given place of the sheets list of the document. Doesn't do anything if the CSSInfo isn't already in the list. params : css : ptr on the CSSInfo to move oldcss : ptr on the CSSInfo css will be next to before : true if css must be placed before oldcss doc : the document to which is applied the CSS. ------------------------------------------------------------------------*/ #ifdef __STDC__ void MoveCSSInList (CSSInfoPtr css, CSSInfoPtr oldcss, boolean before, Document doc) #else void MoveCSSInList (css, oldcss, before, doc) CSSInfoPtr css; CSSInfoPtr oldcss; boolean before; Document doc; #endif { CSSInfoPtr prevcss, nextcss, newcss; DisplayMode dm; CSSRuleSchemasPtr nextschemas; CSSRulePtr rule, nextrules; char *scanname, *buffer; int i, namesnb; #ifdef STYLE_DEBUG fprintf(stderr, "MoveCSSInList: enter \n"); #endif /* verifying parameters */ if ((css == NULL)||(oldcss == NULL)) { #ifdef STYLE_DEBUG fprintf(stderr, "MoveCSSInList: leave: css or oldcss is null.\n"); #endif return; } else if ((doc > DocumentTableLength) || (doc <1)) { #ifdef STYLE_DEBUG fprintf(stderr, "MoveCSSInList: leave: bad document number: %d.\n", doc); #endif return; } else if (css == oldcss) { #ifdef STYLE_DEBUG fprintf(stderr, "MoveCSSInList: leave: css and oldcss are the same\n"); #endif return; } else { prevcss = ListCSS[doc]; while ((prevcss !=NULL) && (prevcss != css)) prevcss = prevcss->nextcss; if (prevcss == NULL) { #ifdef STYLE_DEBUG fprintf(stderr, "MoveCSSInList: leave: css not in list.\n"); #endif return; } prevcss = ListCSS[doc]; while ((prevcss !=NULL) && (prevcss != oldcss)) prevcss = prevcss->nextcss; if (prevcss == NULL) { #ifdef STYLE_DEBUG fprintf(stderr, "MoveCSSInList: leave: oldcss not in list.\n"); #endif return; } } /* ensuring the job is useful */ if ((before && (css->nextcss == oldcss))|| (!before && (oldcss->nextcss == css))) { #ifdef STYLE_DEBUG fprintf(stderr, "MoveCSSInList: leave: move css to same place.\n"); #endif return; } /* switching screen update off */ dm = TtaGetDisplayMode (doc); TtaSetDisplayMode (doc, NoComputedDisplay); /* * The css is moved beeing removed from list and re-applied * at its new location. */ /* unapplying rules */ SetHTMLStyleParserDestructiveMode(TRUE); rule = css->ruleslist; while (rule != NULL) { StyleParser(rule->rule, doc, FALSE, css); rule = rule->nextrule; } SetHTMLStyleParserDestructiveMode(FALSE); /* removing css from list */ GetPrevCSS(doc, css)->nextcss = css->nextcss; /* searching for both sides of destination */ if (before) { nextcss = oldcss; prevcss = GetPrevCSS(doc, nextcss); } else { prevcss = oldcss; nextcss = prevcss->nextcss; } #ifdef DEBUG_CSS PrintListCSS(stderr); if (prevcss != NULL) fprintf (stderr, "prevcss = %d: %s\n", (int)prevcss, prevcss->name); else fprintf (stderr, "prevcss is null\n"); if (nextcss != NULL) fprintf (stderr, "nextcss = %d: %s\n", (int)nextcss, nextcss->name); else fprintf (stderr, "nextcss is null\n"); #endif /* preparing string that will be parsed for css rebuild */ namesnb = GetRulesNames(css, &buffer); scanname = buffer; for (i=1; iname, nextcss, TRUE); else newcss = GetNewDocumentStyle (doc, css->name, prevcss, FALSE); if (newcss == NULL) return; newcss->filename = TtaStrdup(css->filename); newcss->schemas = NULL; for (i=1; i<=DocumentTableLength; i++) newcss->documents[i] = css->documents[i]; newcss->css_rule = TtaStrdup (buffer); newcss->badruleslist = css->badruleslist; css->badruleslist = NULL; /* freeing memory */ if (css->css_rule) TtaFreeMemory (css->css_rule); while ((nextrules = css->ruleslist) != NULL) { css->ruleslist = css->ruleslist->nextrule; FreeRule(nextrules); } while ((nextrules = css->badruleslist) != NULL) { css->badruleslist = css->badruleslist->nextrule; FreeRule(nextrules); } while (css->schemas != NULL) { TtaRemovePSchema (css->schemas->CssPSchema, doc, css->schemas->CssSSchema); nextschemas = css->schemas->NextSchemas; TtaFreeMemory((char*)css->schemas); css->schemas = nextschemas; } TtaFreeMemory ((char*)css); /* applying styles */ StyleParser(buffer, doc, TRUE, newcss); #ifdef STYLE_DEBUG PrintListCSS(stderr); #endif #if 0 /* !!!!! --------------------------------------------------------- */ /* moving the CSSInfo PSchemas */ #ifdef DEBUG_CSS fprintf(stderr, "MoveCSSInList: getting PSchemas list.\n"); #endif schemas = css->schemas; if ((firstcssschemaslist = GetFirstCssSchemasList(css, doc)) == NULL) return; #ifdef DEBUG_CSS fprintf(stderr, "MoveCSSInList: moving PSchemas.\n"); #endif while (schemas != NULL) { attach = NULL; #ifdef DEBUG_CSS fprintf(stderr, "[step 1] "); #endif if (prevcss != NULL) attach = GetPrevCSSPschema(schemas->CssSSchema, prevcss, css, doc); #ifdef DEBUG_CSS fprintf(stderr, "[step 2] "); #endif if (attach != NULL) { #ifdef DEBUG_CSS fprintf(stderr, "[step 2a: found on left] "); PrintListCSS(stderr); #endif TtaRemovePSchema(schemas->CssPSchema, doc, schemas->CssSSchema); rebuilt = RebuildCSSPSchema(schemas->CssSSchema, css, doc); if (rebuilt != NULL) TtaAddPSchema (rebuilt, attach, FALSE, doc, schemas->CssSSchema); } else if (nextcss != NULL) { #ifdef DEBUG_CSS fprintf(stderr, "[step 2b] "); #endif attach = GetNextCSSPschema(schemas->CssSSchema, nextcss); if (attach != NULL) { #ifdef DEBUG_CSS fprintf(stderr, "[step 2c: found on right] "); #endif TtaRemovePSchema(schemas->CssPSchema, doc, schemas->CssSSchema); rebuilt = RebuildCSSPSchema(schemas->CssSSchema, css, doc); if (rebuilt != NULL) TtaAddPSchema (rebuilt, attach, FALSE, doc, schemas->CssSSchema); } } schemas = schemas->NextSchemas; #ifdef DEBUG_CSS fprintf(stderr, "ok, "); #endif } #ifdef DEBUG_CSS fprintf(stderr, "done.\n"); #endif /* moving the CSSInfo */ #ifdef DEBUG_CSS fprintf(stderr, "MoveCSSInList: moving CSSInfo.\n"); #endif if (css == ListCSS[doc]) ListCSS[doc] = css->nextcss; else { prevcss = ListCSS[doc]; while (prevcss->nextcss != css) prevcss = prevcss->nextcss; prevcss->nextcss = css->nextcss; } if (!before) { css->nextcss = oldcss->nextcss; oldcss->nextcss = css; } else if (prevcss == ListCSS[doc]) { css->nextcss = ListCSS[doc]; } else { prevcss = ListCSS[doc]; while (prevcss->nextcss != oldcss) prevcss = prevcss->nextcss; css->nextcss = oldcss; prevcss->nextcss = css; } #endif /* 0 !!!!! ------------------------------------------------------ */ /* switching screen update on */ TtaSetDisplayMode (doc, dm); #ifdef STYLE_DEBUG fprintf(stderr, "MoveCSSInList: leave\n"); #endif } /************************************************************************* * * * CSS FILE OPERATIONS * * * *************************************************************************/ /*---------------------------------------------------------------------- ApplySheetsFromList : Applies a list of style sheets from CSS files to a document, and sets the document's default css to the last of the list. params : doc : the target document on which stylesheets are applied sheetattr : a string containing the list of filenames, without path and separated with ':' NOTE : FILE_BUF_LENGTH is the length of the buffer containing a complete css filename (file+path) ----------------------------------------------------------------------*/ #define FILE_BUF_LENGTH 512 #ifdef __STDC__ void ApplySheetsFromList(Document doc, char *filenames) #else /* __STDC__*/ void ApplySheetsFromList(doc, filenames) Document doc; char *filenames; #endif /*__STDC__*/ { char *path, cssfile[FILE_BUF_LENGTH]=""; char *pathscan, *filenamescan, *cssscan, *filename, namecopy[256], *namescan; int nbdirs; #ifdef DEBUG_CSS fprintf (stderr, "ApplySheetsFromList enter: %s\n", filenames); #endif activecss[doc] = NULL; GetCSSDirectories(':', &path, &nbdirs); filenamescan = filename = filenames; while (*filenamescan != EOS) { /* making file and path */ pathscan = path; while (*pathscan != EOS) { /* copying next path in css buffer */ cssscan = cssfile; while ((*pathscan != EOS) && (*pathscan != ':')) *cssscan++ = *pathscan++; if (*(pathscan-1) != '/') *cssscan++ = '/'; if (*(pathscan) == ':') pathscan++; /* copying filename in css buffer */ filenamescan = filename; while ((*filenamescan != EOS) && (*filenamescan != ':')) *cssscan++ = *filenamescan++; if (*(filenamescan) == ':') filenamescan++; /* adding extension */ strcpy(cssscan, CSS_FILE_EXTENSION); /* parsing file if possible */ #ifdef DEBUG_CSS fprintf (stderr, "\nSearching file: %s .", cssfile); #endif if (TtaFileExist(cssfile)) { #ifdef DEBUG_CSS fprintf (stderr, "Found.\n"); #endif /* copying filename in namecopy buffer */ filenamescan = filename; namescan = namecopy; while ((*filenamescan != EOS) && (*filenamescan != ':')) *namescan++ = *filenamescan++; if (*(filenamescan) == ':') filenamescan++; *namescan = EOS; CSSFileParser (doc, cssfile, NULL, FALSE); activecss[doc] = GetCSSFromName(namecopy, doc); break; } else if (*pathscan == EOS) { #ifdef DEBUG_CSS fprintf (stderr, "Never found.\n"); #endif TtaDisplaySimpleMessage (INFO, CssMsgTable, CSS_FILE_NOT_FOUND); } } filename = filenamescan; } #ifdef DEBUG_CSS fprintf (stderr, "ApplySheetsFromList leave\n"); #endif } /*---------------------------------------------------------------------- SaveCSSToFile : saves the rules of a css in the associated file, and update the 'modified' css mention for each document. params: CSSInfo: the css info that must be saved. ----------------------------------------------------------------------*/ #ifdef __STDC__ void SaveCSSToFile(CSSInfoPtr css) #else /* __STDC__*/ void SaveCSSToFile(css) CSSInfoPtr css; #endif /*__STDC__*/ { BinFile cssfile; char header[] = "\ /* \n\ * This CSS file was generated by Thot.\n * \n\ * You may edit this file only when not used by \ Thot, or changes will be lost.\n */\n"; char separator[] = "\ /* These CSS rules were not recognised by Thot\ the last time they were read. */\n"; char *scan; CSSRulePtr rule; int i; if ((css != NULL) && (css->filename != NULL)) { cssfile = TtaWriteOpen (css->filename); if (cssfile != NULL) { /* copying header */ scan = header; while (*scan != EOS) TtaWriteByte (cssfile, *scan++); /* copying rules */ rule=css->ruleslist; while (rule != NULL) { scan = rule->rule; while (*scan != EOS) TtaWriteByte (cssfile, *scan++); rule = rule->nextrule; TtaWriteByte (cssfile, '\n'); } if (css->badruleslist != NULL) { /* copying separator */ scan = separator; while (*scan != EOS) TtaWriteByte (cssfile, *scan++); /* copying bad rules */ rule=css->badruleslist; while (rule != NULL) { scan = rule->rule; while (*scan != EOS) TtaWriteByte (cssfile, *scan++); rule = rule->nextrule; TtaWriteByte (cssfile, '\n'); } } TtaWriteClose (cssfile); for (i=1; i<=DocumentTableLength; i++) if (css->documents[i]) GetCSSFromName(css->name, (Document)i)->modified = FALSE; } else { TtaDisplaySimpleMessage (INFO, CssMsgTable, CANT_WRITE_IN_FILE); #ifdef STYLE_DEBUG fprintf(stderr, "SaveCSSToFile: Oops! Can't open in write mode the file:\n\t%s.\n", css->filename); #endif } } #ifdef STYLE_DEBUG else fprintf(stderr, "SaveCSSToFile: Hu Ho... You want to save a NULL Css!\n"); #endif } /*---------------------------------------------------------------------- SaveDocCSS : saves the css files of a document. params: doc: the document that must have css info saved. ----------------------------------------------------------------------*/ #ifdef __STDC__ void SaveDocCSS(Document doc) #else /* __STDC__*/ void SaveDocCSS(doc) Document doc; #endif /*__STDC__*/ { CSSInfoPtr css; #ifdef DEBUG_CSS fprintf (stderr, "hello from SaveDocCSS!\n"); #endif css = ListCSS[doc]; while (css != NULL) { SaveCSSToFile(css); css = css->nextcss; } #ifdef DEBUG_CSS fprintf (stderr, "bye from SaveDocCSS!\n"); #endif } /*---------------------------------------------------------------------- GetCSSDirectories : builds the list of directories in which CSS files should be found. params: sep : char used as separator between 2 directories. dirs : returned string nbdirs : returned int = nb of directories in string NOTE : PATH_BUF_LENGTH is the length of a path buffer. ----------------------------------------------------------------------*/ #define PATH_BUF_LENGTH 1000 #ifdef __STDC__ void GetCSSDirectories(char sep, char **dirs, int *nbdirs) #else /*__STDC__*/ void GetCSSDirectories(sep, dirs, nbdirs) char sep; char **dirs; int *nbdirs; #endif /*__STDC__*/ { int length, count = 0; char docpath[PATH_BUF_LENGTH], schemapath[PATH_BUF_LENGTH]; char *path, *scansrc, *scandest; /* getting source directories */ TtaGetDocumentPath (docpath, PATH_BUF_LENGTH); TtaGetSchemaPath (schemapath, PATH_BUF_LENGTH); length = strlen(docpath) + strlen(schemapath) + 1; scandest = path = TtaGetMemory(length); /* copying directories to buffer, with new separator */ scansrc = docpath; while (*scansrc != EOS) { if (*scansrc == ':') { scansrc++; *scandest++ = sep; count++; } else *scandest++ = *scansrc++; } if (docpath != EOS) { count++; if (schemapath != EOS) *scandest++ = sep; } scansrc = schemapath; while (*scansrc != EOS) { if (*scansrc == ':') { scansrc++; *scandest++ = sep; count++; } else *scandest++ = *scansrc++; } *scandest++ = EOS; if (schemapath != EOS) count++; *dirs = path; *nbdirs = count; } /************************************************************************* * * * CSS SCHEMAS RELATED FUNCTIONS * * * *************************************************************************/ /*---------------------------------------------------------------------- GetRulePSchema : returns the curent PSchema associated with the given SSchema in the css info. If necessary, creates a new PSchema and associates it to the document and to the SSchema. params: schema: the searched SSchema doc: the document to which the PSchema is associated if necessary CSSInfo: the css info in which the SSchema is searched. returns: the PSchema found or created if possible, NULL otherwise ----------------------------------------------------------------------*/ #ifdef __STDC__ PSchema GetRulePSchema(SSchema schema, Document doc, CSSInfoPtr cssInfo) #else PSchema GetRulePSchema(schema, doc, cssInfo) SSchema schema; Document doc; CSSInfoPtr cssInfo; #endif { PSchema gPres = NULL, prev = NULL; CSSRuleSchemasPtr ruleSchemas, prevRuleSchemas; /* searching for the given SSchema in the list */ ruleSchemas = prevRuleSchemas = cssInfo->schemas; while ((ruleSchemas != NULL) && (ruleSchemas->CssSSchema != schema)) { prevRuleSchemas = ruleSchemas; ruleSchemas = ruleSchemas->NextSchemas; } if (ruleSchemas != NULL) /* the SSchema is found, the PSchema exists */ return (ruleSchemas->CssPSchema); /* the schema hasn't been used yet. Creating a new one */ ruleSchemas = TtaGetMemory(sizeof(CSSRuleSchemas)); if (ruleSchemas == NULL) { TtaDisplaySimpleMessage (INFO, CssMsgTable, CSS_OUT_OF_MEMORY); return NULL; } gPres = TtaNewPSchema (); if (gPres == NULL) { TtaDisplaySimpleMessage (INFO, CssMsgTable, CSS_OUT_OF_MEMORY); TtaFreeMemory(ruleSchemas); return NULL; } /* searching for previous document PSchemas to add gPres */ prev = GetPrevCSSPschema (schema, cssInfo, NULL, doc); TtaAddPSchema (gPres, prev, FALSE, doc, schema); /* initializing the CSSRuleSchemas */ ruleSchemas->CssPSchema = gPres; ruleSchemas->CssSSchema = schema; ruleSchemas->NextSchemas = NULL; /* linking CSSRuleSchemas to CSSInfo */ if (cssInfo->schemas == NULL) cssInfo->schemas = ruleSchemas; else prevRuleSchemas->NextSchemas = ruleSchemas; /* finished */ return gPres; } /*---------------------------------------------------------------------- GetFirstCssSchemasList : returns a list containing the first PSchemas used by the document's style sheets for each schemas used by the given CSS. The given css MUST be in the document's list, to ensure all schemas exist in the document's css list params: css: the css info in which the SSchema is searched. doc: the document in which the schemas have to be found. returns: a ptr on the first CSSRuleSchemas of the list, NULL if an error occured. The list is sorted the same way as is the given css' SSchemas list. ----------------------------------------------------------------------*/ #ifdef __STDC__ CSSRuleSchemasPtr GetFirstCssSchemasList(CSSInfoPtr css, Document doc) #else CSSRuleSchemasPtr GetFirstCssSchemasList(css, doc) CSSInfoPtr css; Document doc; #endif { CSSInfoPtr scancss; CSSRuleSchemasPtr firstschemaslist, schemas, scanschemas, cssschemas; SSchema sschema; if ((doc > DocumentTableLength) || (doc <1)) { #ifdef STYLE_DEBUG fprintf(stderr, "GetFirstCssPSchemasList:\ leave: bad document number: %d.\n", doc); #endif return NULL; } else { scancss = ListCSS[doc]; while ((scancss !=NULL) && (scancss != css)) scancss = scancss->nextcss; if (scancss == NULL) { #ifdef STYLE_DEBUG fprintf(stderr, "GetFirstCssPSchemasList: leave: css not in list.\n"); #endif return NULL; } } if (css->schemas == NULL) return NULL; firstschemaslist = NULL; cssschemas = css->schemas; while (cssschemas != NULL) /* for each SSchema,... */ { /* adds a new CSSRuleSchemas in list */ schemas = TtaGetMemory(sizeof(CSSRuleSchemas)); schemas->NextSchemas = firstschemaslist; firstschemaslist = schemas; /* search for the first document's CSSRuleSchemas */ sschema = cssschemas->CssSSchema; scancss = ListCSS[doc]; while (scancss->schemas == NULL) scancss = scancss->nextcss; /* search for the first document's CSSRuleSchemas maching the SSchema*/ scanschemas = scancss->schemas; while (scanschemas->CssSSchema != sschema) { scanschemas = scanschemas->NextSchemas; if (scanschemas == NULL) { scancss = scancss->nextcss; scanschemas = scancss->schemas; continue; } } /* copying schemas info */ schemas->CssPSchema = scanschemas->CssPSchema; schemas->CssSSchema = scanschemas->CssSSchema; cssschemas = cssschemas->NextSchemas; } /* reverting list to sort it as the given css. */ schemas = firstschemaslist->NextSchemas; firstschemaslist->NextSchemas = NULL; while (schemas != NULL) { scanschemas = schemas->NextSchemas; schemas->NextSchemas = firstschemaslist; firstschemaslist = schemas; schemas = scanschemas; } return (firstschemaslist); } /*---------------------------------------------------------------------- GetNextCSSPschema : returns the first PSchema matching the given SSchema in the CSS list, searching from the given CSS. params : sschema : the SSchema to match, css : the css to start from returns : the first matching PSchema, NULL if not found. ----------------------------------------------------------------------*/ #ifdef __STDC__ PSchema GetNextCSSPschema (SSchema sschema, CSSInfoPtr css) #else PSchema GetNextCSSPschema (sschema, css) SSchema sschema; CSSInfoPtr css; #endif { CSSRuleSchemasPtr scanschemas; CSSInfoPtr scancss; scancss = css; scanschemas = scancss->schemas; while (scanschemas->CssSSchema != sschema) { scanschemas = scanschemas->NextSchemas; if (scanschemas == NULL) { if ((scancss = scancss->nextcss)== NULL) /* Not found ! */ return NULL; scanschemas = scancss->schemas; } } return (scanschemas->CssPSchema); } /*---------------------------------------------------------------------- GetPrevCSSPschema : returns the last PSchema matching the given SSchema in the CSS list, searching from the beginning to the given CSS (included). params : sschema : the SSchema to match. css : the css to stop to. skipcss : one css that won't be analysed, can be NULL. doc : the target document. returns : the last matching PSchema, NULL if not found. ----------------------------------------------------------------------*/ #ifdef __STDC__ PSchema GetPrevCSSPschema (SSchema sschema, CSSInfoPtr css, CSSInfoPtr skipcss, Document doc) #else PSchema GetPrevCSSPschema (sschema, css, skipcss, doc) SSchema sschema; CSSInfoPtr css; CSSInfoPtr skipcss; Document doc; #endif { CSSRuleSchemasPtr scanschemas; CSSInfoPtr scancss; PSchema ans = NULL; #ifdef DEBUG_CSS fprintf(stderr, "GetPrevCSSPschema: enter.\n"); #endif if ((scancss = ListCSS[doc]) == NULL) return (NULL); do { if (scancss != skipcss) { scanschemas = scancss->schemas; /* searching for the schema in this css */ while ((scanschemas != NULL) && (scanschemas->CssSSchema != sschema)) scanschemas = scanschemas->NextSchemas; if (scanschemas != NULL) /* found a good schema */ ans = scanschemas->CssPSchema; } if (scancss == css) break; scancss = scancss->nextcss; } while (scancss != NULL); #ifdef DEBUG_CSS if (scancss == NULL) fprintf(stderr, "GetPrevCSSPschema: given css not found.\n"); fprintf(stderr, "GetPrevCSSPschema: leave.\n"); #endif return (ans); } #if 0 /*---------------------------------------------------------------------- AddLastPschema : adds a PSchema at the end of the PSchema list of a document. params : pschema : the PSchema to add, sschema : the associated SSchema, doc : the target document ----------------------------------------------------------------------*/ #ifdef __STDC__ void AddLastPschema (PSchema pschema, SSchema sschema, Document doc) #else void AddLastPschema (pschema, sschema, doc) PSchema pschema; SSchema sschema; Document doc; #endif { PSchema scanpschema, prevpschema = NULL; scanpschema = TtaGetFirstPSchema (doc, sschema); while (scanpschema != NULL) { prevpschema = scanpschema; TtaNextPSchema (&scanpschema, doc, sschema); } TtaAddPSchema (pschema, prevpschema, FALSE, doc, sschema); } #endif /*---------------------------------------------------------------------- GetLastPschema : Returns the PSchema at the end of the PSchema list of a document. params : sschema : the associated SSchema, doc : the target document returns : the last pschema, NULL if not found ----------------------------------------------------------------------*/ #ifdef __STDC__ PSchema GetLastPschema (SSchema sschema, Document doc) #else PSchema GetLastPschema (sschema, doc) SSchema sschema; Document doc; #endif { PSchema scanpschema, prevpschema = NULL; scanpschema = TtaGetFirstPSchema (doc, sschema); while (scanpschema != NULL) { prevpschema = scanpschema; TtaNextPSchema (&scanpschema, doc, sschema); } return (prevpschema); } /*---------------------------------------------------------------------- RebuildCSSPSchema : Rebuilds the PSchema associated to the given SSchema of the given CSS, and store it in the apropriated CSSRuleSchemas. params : sschema : the associated SSchema, css : the CSS in which rules are taken, doc : the document on which this CSS is applied. returns : the built pschema, NULL if not created. ----------------------------------------------------------------------*/ #ifdef __STDC__ PSchema RebuildCSSPSchema (SSchema sschema, CSSInfoPtr css, Document doc) #else PSchema RebuildCSSPSchema (sschema, css, doc) SSchema sschema; CSSInfoPtr css; Document doc; #endif { PSchema newpschema; CSSRuleSchemasPtr schemas; CSSRulePtr rule; schemas = css->schemas; while ((schemas != NULL) && (schemas->CssSSchema != sschema)) schemas = schemas->NextSchemas; if (schemas == NULL) { #ifdef DEBUG_CSS fprintf(stderr, "RebuildCSSPschema: SSchema not used in CSS.\n"); #endif return (NULL); } if (schemas->CssPSchema != NULL) { #ifdef DEBUG_CSS fprintf(stderr, "RebuildCSSPschema: Warning: Existing PSchema for given \ SSchema. Overwrite.\n"); #endif TtaRemovePSchema(schemas->CssPSchema, doc, sschema); schemas->CssPSchema = NULL; } newpschema = schemas->CssPSchema = TtaNewPSchema (); /* applying rules to PSchema */ rule = css->ruleslist; while (rule != NULL) { if (rule->cssSSchema == sschema) StyleDeclarationParser (rule->rule, doc, FALSE, css); rule = rule->nextrule; } return (newpschema); } /************************************************************************* * * * MISC. CSS RELATED FUNCTIONS * * * *************************************************************************/ /*---------------------------------------------------------------------- RefreshDocViews : Refresh the views of a structure of a document after manipulating a CSS to show the result to user. params : doc : the document to refresh sschema : the structure of the document to refresh. ----------------------------------------------------------------------*/ #ifdef __STDC__ void RefreshDocViews (Document doc, SSchema sschema) #else void RefreshDocViews (doc, sschema) Document doc; PSchema pschema; #endif { GenericContext ctxt; int i, noupdate; PresentationValue unused; PSchema pschema; ctxt = GetGenericContext (doc); if (ctxt == NULL) return; for (i = 0; i < MAX_ANCESTORS; i++) { ctxt->ancestors[i] = 0; ctxt->ancestors_nb[i] = 0; } pschema = GetLastPschema(sschema, doc); noupdate = ctxt->drv->UpdatePresentation ((PresentationTarget)pschema, (PresentationContext)ctxt, unused); FreeGenericContext (ctxt); } /*---------------------------------------------------------------------- SetAttributeValue : sets the value of the sheet attribute of the specified document, from the list of CSS infos associated to this document. If the schema extension doesn't exists, it is created if the list isn't empty. On the oposite, if it exists and if no CSS is applied, the schema extension is destroyed. params : doc : the document whose attribute has to be set ----------------------------------------------------------------------*/ #ifdef __STDC__ void SetAttributeValue (Document doc) #else void SetAttributeValue (doc) Document doc; #endif { CSSInfoPtr info = ListCSS[doc]; char *names, *scan1, *scan2; int nameslength; Element mainroot; SSchema sheetextension; int removedElements, removedAttributes; AttributeType sheetattrtype; int sheetattrkind; Attribute sheetattr; char presname[] = "\0"; mainroot = TtaGetMainRoot(doc); sheetextension = TtaGetSchemaExtension(doc, SHEET_EXT_NAME); if (info == NULL) { /* no css applied, destroying schema extension if it exists */ if (sheetextension != NULL) TtaRemoveSchemaExtension (doc, sheetextension, &removedElements, &removedAttributes); } else { /* some css applied, setting the attribute. */ /* first step: getting string length */ nameslength = 0; while (info != NULL) { nameslength += strlen(info->name); info = info->nextcss; } /* second step: creating string */ names = TtaGetMemory(nameslength); if (names == NULL) { TtaDisplaySimpleMessage (INFO, CssMsgTable, CSS_OUT_OF_MEMORY); #ifdef STYLE_DEBUG fprintf(stderr, "SetAttributeValue: out of memory\n"); #endif return; } info = ListCSS[doc]; scan1 = names; while (info != NULL) { /* adding a name */ scan2 = info->name; while (*scan2 != EOS) *scan1++ = *scan2++; if ((info = info->nextcss) != NULL) *scan1++ = ':'; else *scan1++ = EOS; } if (sheetextension == NULL) /* the extension must be created before setting the attribute */ sheetextension = TtaNewSchemaExtension (doc, SHEET_EXT_NAME, presname); TtaGiveAttributeTypeFromName(SHEET_ATTR_NAME, mainroot, &sheetattrtype, &sheetattrkind); if ((sheetattr = TtaGetAttribute (mainroot, sheetattrtype )) == NULL) { sheetattr = TtaNewAttribute(sheetattrtype); TtaAttachAttribute(mainroot, sheetattr, doc); } /* setting the attribute value */ TtaSetAttributeText(sheetattr, names, mainroot, doc); } } /************************************************************************* * * * CSSInfo HELPFUL TOOLS * * * *************************************************************************/ /*---------------------------------------------------------------------- PrintCSS : Print in the given output some of the informations contained in a CSSInfo. params : css : the printed CSSInfo output : the output stream where infos are written. ----------------------------------------------------------------------*/ #ifdef __STDC__ void PrintCSS (CSSInfoPtr css, FILE * output) #else void PrintCSS (css, output) CSSInfoPtr css; FILE *output; #endif { int i; CSSRulePtr rule; if (css->name) fprintf (output, "name %s", css->name); else fprintf (output, "noname"); fprintf (output, "\ndocs : "); for (i = 0; i <= DocumentTableLength; i++) if (css->documents[i]) fprintf (output, "%d ", i); rule = css->ruleslist; fprintf (output, "\n\trules : {"); while (rule != NULL) { fprintf (output, "\"%s\"", rule->rule); rule = rule->nextrule; if (rule != NULL) fprintf (output, ",\n\t\t"); } rule = css->badruleslist; fprintf (output, "}\n\tbad rules : {"); while (rule != NULL) { fprintf (output, "\"%s\"", rule->rule); rule = rule->nextrule; if (rule != NULL) fprintf (output, ", "); } fprintf (output, "}\n"); } /*---------------------------------------------------------------------- PrintListCSS : Print in the given output some informations about all CSSInfos in the list. params : output : the output stream where infos are written. ----------------------------------------------------------------------*/ #ifdef __STDC__ void PrintListCSS (FILE *output) #else void PrintListCSS (output) FILE *output; #endif { CSSInfoPtr css; int i; fprintf (output, "ListCSS :\n"); for(i=0; inextcss; } } }