diff options
Diffstat (limited to 'WWW/Library/Implementation/HTStyle.c')
-rw-r--r-- | WWW/Library/Implementation/HTStyle.c | 363 |
1 files changed, 363 insertions, 0 deletions
diff --git a/WWW/Library/Implementation/HTStyle.c b/WWW/Library/Implementation/HTStyle.c new file mode 100644 index 00000000..5b31e252 --- /dev/null +++ b/WWW/Library/Implementation/HTStyle.c @@ -0,0 +1,363 @@ +/* Style Implementation for Hypertext HTStyle.c +** ================================== +** +** Styles allow the translation between a logical property +** of a piece of text and its physical representation. +** +** A StyleSheet is a collection of styles, defining the +** translation necessary to +** represent a document. It is a linked list of styles. +*/ +#include "HTUtils.h" +#include "HTStyle.h" + +#include "LYLeaks.h" + +#define FREE(x) if (x) {free(x); x = NULL;} + +/* Create a new style +*/ +PUBLIC HTStyle* HTStyleNew NOARGS +{ + HTStyle * self = (HTStyle *)malloc(sizeof(*self)); + memset((void *)self, 0, sizeof(*self)); + self->font = (HTFont) 0; + self->color = 0; + return self; +} + +/* Create a new style with a name +*/ +PUBLIC HTStyle* HTStyleNewNamed ARGS1 (CONST char *,name) +{ + HTStyle * self = HTStyleNew(); + StrAllocCopy(self->name, name); + return self; +} + + +/* Free a style +*/ +PUBLIC HTStyle * HTStyleFree ARGS1 (HTStyle *,self) +{ + FREE(self->name); + FREE(self->SGMLTag); + FREE(self); + return NULL; +} + + +#ifdef SUPPRESS /* Only on the NeXT */ +/* Read a style from a stream (without its name) +** -------------------------- +** +** Reads a style with paragraph information from a stream. +** The style name is not read or written by these routines. +*/ +#define NONE_STRING "(None)" +#define HTStream NXStream + +HTStyle * HTStyleRead (HTStyle * style, HTStream * stream) +{ + char myTag[STYLE_NAME_LENGTH]; + char fontName[STYLE_NAME_LENGTH]; + NXTextStyle *p; + int tab; + int gotpara; /* flag: have we got a paragraph definition? */ + + NXScanf(stream, "%s%s%f%d", + myTag, + fontName, + &style->fontSize, + &gotpara); + if (gotpara) { + if (!style->paragraph) { + style->paragraph = malloc(sizeof(*(style->paragraph))); + style->paragraph->tabs = 0; + } + p = style->paragraph; + NXScanf(stream, "%f%f%f%f%hd%f%f%hd", + &p->indent1st, + &p->indent2nd, + &p->lineHt, + &p->descentLine, + &p->alignment, + &style->spaceBefore, + &style->spaceAfter, + &p->numTabs); + FREE(p->tabs); + p->tabs = malloc(p->numTabs * sizeof(p->tabs[0])); + for (tab=0; tab < p->numTabs; tab++) { + NXScanf(stream, "%hd%f", + &p->tabs[tab].kind, + &p->tabs[tab].x); + } + } else { /* No paragraph */ + FREE(style->paragraph); + } /* if no paragraph */ + StrAllocCopy(style->SGMLTag, myTag); + if (strcmp(fontName, NONE_STRING)==0) + style->font = 0; + else + style->font = [Font newFont:fontName size:style->fontSize]; + return NULL; +} + + +/* Write a style to a stream in a compatible way +*/ +HTStyle * HTStyleWrite (HTStyle * style, NXStream * stream) +{ + int tab; + NXTextStyle *p = style->paragraph; + NXPrintf(stream, "%s %s %f %d\n", + style->SGMLTag, + style->font ? [style->font name] : NONE_STRING, + style->fontSize, + p!=0); + + if (p) { + NXPrintf(stream, "\t%f %f %f %f %d %f %f\t%d\n", + p->indent1st, + p->indent2nd, + p->lineHt, + p->descentLine, + p->alignment, + style->spaceBefore, + style->spaceAfter, + p->numTabs); + + for (tab=0; tab < p->numTabs; tab++) + NXPrintf(stream, "\t%d %f\n", + p->tabs[tab].kind, + p->tabs[tab].x); + } + return style; +} + + +/* Write a style to stdout for diagnostics +*/ +HTStyle * HTStyleDump (HTStyle * style) +{ + int tab; + NXTextStyle *p = style->paragraph; + printf("Style %d `%s' SGML:%s. Font %s %.1f point.\n", + style, + style->name, + style->SGMLTag, + [style->font name], + style->fontSize); + if (p) { + printf( + "\tIndents: first=%.0f others=%.0f, Height=%.1f Desc=%.1f\n" + "\tAlign=%d, %d tabs. (%.0f before, %.0f after)\n", + p->indent1st, + p->indent2nd, + p->lineHt, + p->descentLine, + p->alignment, + p->numTabs, + style->spaceBefore, + style->spaceAfter); + + for (tab=0; tab < p->numTabs; tab++) { + printf("\t\tTab kind=%d at %.0f\n", + p->tabs[tab].kind, + p->tabs[tab].x); + } + printf("\n"); + } /* if paragraph */ + return style; +} +#endif /* SUPPRESS */ + + +/* StyleSheet Functions +** ==================== +*/ + +/* Searching for styles: +*/ +HTStyle * HTStyleNamed ARGS2 (HTStyleSheet *,self, CONST char *,name) +{ + HTStyle * scan; + for (scan=self->styles; scan; scan=scan->next) + if (0==strcmp(scan->name, name)) return scan; + if (TRACE) fprintf(stderr, "StyleSheet: No style named `%s'\n", name); + return NULL; +} + +#ifdef NEXT_SUPRESS /* Not in general common code */ + +HTStyle * HTStyleMatching (HTStyleSheet * self, HTStyle *style) +{ + HTStyle * scan; + for (scan=self->styles; scan; scan=scan->next) + if (scan->paragraph == para) return scan; + return NULL; +} + +/* Find the style which best fits a given run +** ------------------------------------------ +** +** This heuristic is used for guessing the style for a run of +** text which has been pasted in. In order, we try: +** +** A style whose paragraph structure is actually used by the run. +** A style matching in font +** A style matching in paragraph style exactly +** A style matching in paragraph to a degree +*/ + +HTStyle * HTStyleForRun (HTStyleSheet *self, NXRun *run) +{ + HTStyle * scan; + HTStyle * best = 0; + int bestMatch = 0; + NXTextStyle * rp = run->paraStyle; + for (scan=self->styles; scan; scan=scan->next) + if (scan->paragraph == run->paraStyle) return scan; /* Exact */ + + for (scan=self->styles; scan; scan=scan->next){ + NXTextStyle * sp = scan->paragraph; + if (sp) { + int match = 0; + if (sp->indent1st == rp->indent1st) match = match+1; + if (sp->indent2nd == rp->indent2nd) match = match+2; + if (sp->lineHt == rp->lineHt) match = match+1; + if (sp->numTabs == rp->numTabs) match = match+1; + if (sp->alignment == rp->alignment) match = match+3; + if (scan->font == run->font) match = match+10; + if (match>bestMatch) { + best=scan; + bestMatch=match; + } + } + } + if (TRACE) fprintf(stderr, "HTStyleForRun: Best match for style is %d out of 18\n", + bestMatch); + return best; +} +#endif /* NEXT_SUPRESS */ + + +/* Add a style to a sheet +** ---------------------- +*/ +HTStyleSheet * HTStyleSheetAddStyle ARGS2 + (HTStyleSheet *,self, HTStyle *,style) +{ + style->next = 0; /* The style will go on the end */ + if (!self->styles) { + self->styles = style; + } else { + HTStyle * scan; + for(scan=self->styles; scan->next; scan=scan->next); /* Find end */ + scan->next=style; + } + return self; +} + + +/* Remove the given object from a style sheet if it exists +*/ +HTStyleSheet * HTStyleSheetRemoveStyle ARGS2 + (HTStyleSheet *,self, HTStyle *,style) +{ + if (self->styles = style) { + self->styles = style->next; + return self; + } else { + HTStyle * scan; + for(scan = self->styles; scan; scan = scan->next) { + if (scan->next = style) { + scan->next = style->next; + return self; + } + } + } + return NULL; +} + +/* Create new style sheet +*/ + +HTStyleSheet * HTStyleSheetNew NOARGS +{ + HTStyleSheet * self = (HTStyleSheet *)malloc(sizeof(*self)); + + memset((void*)self, 0, sizeof(*self)); /* ANSI */ +/* Harbison c ref man says (char*)self + but k&r ansii and abc books and Think_C say (void*) */ + +/* bzero(self, sizeof(*self)); */ /* BSD */ + return self; +} + + +/* Free off a style sheet pointer +*/ +HTStyleSheet * HTStyleSheetFree ARGS1 (HTStyleSheet *,self) +{ + HTStyle * style; + while((style=self->styles)!=0) { + self->styles = style->next; + HTStyleFree(style); + } + FREE(self); + return NULL; +} + + +/* Read a stylesheet from a typed stream +** ------------------------------------- +** +** Reads a style sheet from a stream. If new styles have the same names +** as existing styles, they replace the old ones without changing the ids. +*/ + +#ifdef NEXT_SUPRESS /* Only on the NeXT */ +HTStyleSheet * HTStyleSheetRead(HTStyleSheet * self, NXStream * stream) +{ + int numStyles; + int i; + HTStyle * style; + char styleName[80]; + NXScanf(stream, " %d ", &numStyles); + if (TRACE) fprintf(stderr, "Stylesheet: Reading %d styles\n", numStyles); + for (i=0; i<numStyles; i++) { + NXScanf(stream, "%s", styleName); + style = HTStyleNamed(self, styleName); + if (!style) { + style = HTStyleNewNamed(styleName); + (void) HTStyleSheetAddStyle(self, style); + } + (void) HTStyleRead(style, stream); + if (TRACE) HTStyleDump(style); + } + return self; +} + +/* Write a stylesheet to a typed stream +** ------------------------------------ +** +** Writes a style sheet to a stream. +*/ + +HTStyleSheet * HTStyleSheetWrite(HTStyleSheet * self, NXStream * stream) +{ + int numStyles = 0; + HTStyle * style; + + for(style=self->styles; style; style=style->next) numStyles++; + NXPrintf(stream, "%d\n", numStyles); + + if (TRACE) fprintf(stderr, "StyleSheet: Writing %d styles\n", numStyles); + for (style=self->styles; style; style=style->next) { + NXPrintf(stream, "%s ", style->name); + (void) HTStyleWrite(style, stream); + } + return self; +} +#endif /* NEXT_SUPRESS */ |