summaryrefslogtreecommitdiffstats
path: root/WWW/Library/Implementation/HTStyle.c
diff options
context:
space:
mode:
Diffstat (limited to 'WWW/Library/Implementation/HTStyle.c')
-rw-r--r--WWW/Library/Implementation/HTStyle.c378
1 files changed, 378 insertions, 0 deletions
diff --git a/WWW/Library/Implementation/HTStyle.c b/WWW/Library/Implementation/HTStyle.c
new file mode 100644
index 0000000..54c0bc5
--- /dev/null
+++ b/WWW/Library/Implementation/HTStyle.c
@@ -0,0 +1,378 @@
+/*
+ * $LynxId: HTStyle.c,v 1.16 2009/11/27 13:01:48 tom Exp $
+ *
+ * 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>
+
+/* Create a new style
+*/
+HTStyle *HTStyleNew(void)
+{
+ HTStyle *self = typecalloc(HTStyle);
+
+ if (self == NULL)
+ outofmem(__FILE__, "HTStyleNew");
+ return self;
+}
+
+/* Create a new style with a name
+*/
+HTStyle *HTStyleNewNamed(const char *name)
+{
+ HTStyle *self = HTStyleNew();
+
+ StrAllocCopy(self->w_name, name);
+ self->id = -1; /* <0 */
+ return self;
+}
+
+/* Free a style
+*/
+HTStyle *HTStyleFree(HTStyle *self)
+{
+ FREE(self->w_name);
+ FREE(self->w_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)));
+ if (!style->paragraph)
+ outofmem(__FILE__, "HTStyleRead");
+ 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]));
+ if (!p->tabs)
+ outofmem(__FILE__, "HTStyleRead");
+ 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_DUMP_FONT,
+ style,
+ style->name,
+ style->SGMLTag,
+ [style->font name],
+ style->fontSize);
+ if (p) {
+ printf(STYLE_DUMP_IDENT,
+ p->indent1st,
+ p->indent2nd,
+ p->lineHt,
+ p->descentLine);
+ printf(STYLE_DUMP_ALIGN,
+ p->alignment,
+ p->numTabs,
+ style->spaceBefore,
+ style->spaceAfter);
+
+ for (tab = 0; tab < p->numTabs; tab++) {
+ printf(STYLE_DUMP_TAB,
+ p->tabs[tab].kind,
+ p->tabs[tab].x);
+ }
+ printf("\n");
+ } /* if paragraph */
+ return style;
+}
+#endif /* SUPPRESS */
+
+/* StyleSheet Functions
+ * ====================
+ */
+
+/* Searching for styles:
+*/
+HTStyle *HTStyleNamed(HTStyleSheet *self, const char *name)
+{
+ HTStyle *scan;
+
+ for (scan = self->styles; scan; scan = scan->next)
+ if (0 == strcmp(GetHTStyleName(scan), name))
+ return scan;
+ CTRACE((tfp, "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;
+ }
+ }
+ }
+ CTRACE((tfp, "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(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(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(void)
+{
+ HTStyleSheet *self = typecalloc(HTStyleSheet);
+
+ if (self == NULL)
+ outofmem(__FILE__, "HTStyleSheetNew");
+ return self;
+}
+
+/* Free off a style sheet pointer
+*/
+HTStyleSheet *HTStyleSheetFree(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);
+ CTRACE((tfp, "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);
+
+ CTRACE((tfp, "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 */