home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / lynx2.8.1dev.10.tar.gz / lynx2.8.1dev.10.tar / lynx2-8 / src / LYStyle.c < prev    next >
C/C++ Source or Header  |  1998-04-23  |  10KB  |  400 lines

  1. /* character level styles for Lynx
  2.  * (c) 1996 Rob Partington -- donated to the Lyncei (if they want it :-)
  3.  * $Id: LYStyle.c 1.18 Thu, 23 Apr 1998 06:35:21 -0600 dickey $
  4.  */
  5. #include <HTUtils.h>
  6. #include <HTML.h>
  7. #include <tcp.h>
  8. #include <LYSignal.h>
  9. #include <LYGlobalDefs.h>
  10.  
  11. #include <LYStructs.h>
  12. #include <LYReadCFG.h>
  13. #include <LYCurses.h>
  14. #include <LYCharUtils.h>
  15. #include <AttrList.h>
  16. #include <SGML.h>
  17. #include <HTMLDTD.h>
  18.  
  19. /* Hash table definitions */
  20. #include <LYHash.h>
  21. #include <LYStyle.h>
  22.  
  23. #include <LYexit.h>
  24. #include <LYLeaks.h>
  25.  
  26. #ifdef USE_COLOR_STYLE
  27.  
  28. PUBLIC bucket hashStyles[CSHASHSIZE];
  29.  
  30. /* definitions for the mono attributes we can use */
  31. static int ncursesMono[7] = {
  32.  A_NORMAL, A_BOLD, A_REVERSE, A_UNDERLINE, A_STANDOUT, A_BLINK, A_DIM
  33. };
  34.  
  35. /*
  36.  * If these strings don't match the meanings of the above attributes,
  37.  * you'll confuse the hell out of people, so make them the same. - RP
  38.  */
  39. static char *Mono_Strings[7] =
  40. {
  41.  "normal", "bold", "reverse", "underline", "standout", "blink", "dim"
  42. };
  43.  
  44. /* Remember the hash codes for common elements */
  45. PUBLIC int    s_alink  = NOSTYLE, s_a     = NOSTYLE, s_status = NOSTYLE,
  46.         s_label  = NOSTYLE, s_value = NOSTYLE, s_high   = NOSTYLE,
  47.         s_normal = NOSTYLE, s_alert = NOSTYLE, s_title  = NOSTYLE;
  48.  
  49. /* start somewhere safe */
  50. PRIVATE int colorPairs = 0;
  51. PRIVATE int last_fA = COLOR_WHITE, last_bA = COLOR_BLACK;
  52.  
  53.  
  54. #define FREE(x) if (x) {free(x); x = NULL;}
  55.  
  56. /* icky parsing of the style options */
  57. PRIVATE void parse_attributes ARGS5(char*,mono,char*,fg,char*,bg,int,style,char*,element)
  58. {
  59.     int i;
  60.     int mA = 0, fA = default_fg, bA = default_bg, cA = A_NORMAL;
  61.     int newstyle = hash_code(element);
  62.  
  63.     CTRACE(tfp, "CSS(PA):style d=%d / h=%d, e=%s\n", style, newstyle,element);
  64.  
  65.     for (i = 0; i <7; i++)
  66.     {
  67.     if (!strcasecomp(Mono_Strings[i], mono))
  68.     {
  69.         mA = ncursesMono[i];
  70.     }
  71.     }
  72.     CTRACE(tfp, "CSS(CP):%d\n", colorPairs);
  73.  
  74.     fA = check_color(fg, default_fg);
  75.     bA = check_color(bg, default_bg);
  76.     if (fA == NO_COLOR) {
  77.     bA = NO_COLOR;
  78.     } else if (COLORS) {
  79.     if (fA >= COLORS || bA >= COLORS)
  80.         cA = A_BOLD;
  81.     if (fA >= COLORS)
  82.         fA %= COLORS;
  83.     if (bA > COLORS)
  84.         bA %= COLORS;
  85.     } else {
  86.     cA = A_BOLD;
  87.     fA = NO_COLOR;
  88.     bA = NO_COLOR;
  89.     }
  90.  
  91.     /*
  92.      * If we have colour, and space to create a new colour attribute,
  93.      * and we have a valid colour description, then add this style
  94.      */
  95.     if (lynx_has_color && colorPairs < COLOR_PAIRS-1 && fA != NO_COLOR)
  96.     {
  97.     if (colorPairs <= 0 || fA != last_fA || bA != last_bA) {
  98.         colorPairs++;
  99.         init_pair(colorPairs, fA, bA);
  100.         last_fA = fA;
  101.         last_bA = bA;
  102.     }
  103.     if (style < DSTYLE_ELEMENTS)
  104.         setStyle(style, COLOR_PAIR(colorPairs)|cA, cA, mA);
  105.     setHashStyle(newstyle, COLOR_PAIR(colorPairs)|cA, cA, mA, element);
  106.     }
  107.     else
  108.     {
  109.     /* only mono is set */
  110.     if (style < DSTYLE_ELEMENTS)
  111.         setStyle(style, -1, -1, mA);
  112.     setHashStyle(newstyle, -1, -1, mA, element);
  113.     }
  114. }
  115.  
  116. /* parse a style option of the format
  117.  * STYLE:<OBJECT>:FG:BG
  118.  */
  119. PRIVATE void parse_style ARGS1(char*,buffer)
  120. {
  121.     char *tmp = strchr(buffer, ':');
  122.     char *element, *mono, *fg, *bg;
  123.  
  124.     if(!tmp)
  125.     {
  126.     fprintf (stderr, "\
  127. Syntax Error parsing style in lss file:\n\
  128. [%s]\n\
  129. The line must be of the form:\n\
  130. OBJECT:MONO:COLOR (ie em:bold:brightblue:white)\n\
  131. where OBJECT is one of EM,STRONG,B,I,U,BLINK etc.\n\n", buffer);
  132.     if (!dump_output_immediately) {
  133. #ifndef NOSIGHUP
  134.         (void) signal(SIGHUP, SIG_DFL);
  135. #endif /* NOSIGHUP */
  136.         (void) signal(SIGTERM, SIG_DFL);
  137. #ifndef VMS
  138.         (void) signal(SIGINT, SIG_DFL);
  139. #endif /* !VMS */
  140. #ifdef SIGTSTP
  141.         if (no_suspend)
  142.         (void) signal(SIGTSTP,SIG_DFL);
  143. #endif /* SIGTSTP */
  144.         exit(-1);
  145.     }
  146.     exit(1);
  147.     }
  148.     {
  149.     char *i;
  150.     for (i = buffer; *i; i++)
  151.         *i = tolower(*i);
  152.     }
  153.     *tmp = '\0';
  154.     element = buffer;
  155.  
  156.     mono = tmp + 1;
  157.     tmp = strchr(mono, ':');
  158.  
  159.     if (!tmp)
  160.     {
  161.     fg = "nocolor";
  162.     bg = "nocolor";
  163.     }
  164.     else
  165.     {
  166.     *tmp = '\0';
  167.     fg = tmp+1;
  168.     tmp = strchr(fg, ':');
  169.     if (!tmp)
  170.         bg = "default";
  171.     else
  172.     {
  173.         *tmp = '\0';
  174.         bg = tmp + 1;
  175.     }
  176.     }
  177.  
  178.     CTRACE(tfp, "CSSPARSE:%s => %d %s\n",
  179.         element, hash_code(element),
  180.         (hashStyles[hash_code(element)].name ? "used" : ""));
  181.  
  182.     strtolower(element);
  183.  
  184.     /*
  185.     * We use some pseudo-elements, so catch these first
  186.     */
  187.     if (!strncasecomp(element, "alink", 5)) /* active link */
  188.     {
  189.     parse_attributes(mono,fg,bg,DSTYLE_ALINK,"alink");
  190.     }
  191.     else if (!strcasecomp(element, "a")) /* normal link */
  192.     {
  193.     parse_attributes(mono,fg,bg, DSTYLE_LINK,"a");
  194.     parse_attributes(mono,fg,bg, HTML_A,"a");
  195.     }
  196.     else if (!strncasecomp(element, "status", 4)) /* status bar */
  197.     {
  198.     parse_attributes(mono,fg,bg, DSTYLE_STATUS,"status");
  199.     }
  200.     else if (!strncasecomp(element, "label", 6)) /* [INLINE]'s */
  201.     {
  202.     parse_attributes(mono,fg,bg,DSTYLE_OPTION,"label");
  203.     }
  204.     else if (!strncasecomp(element, "value", 5)) /* [INLINE]'s */
  205.     {
  206.     parse_attributes(mono,fg,bg,DSTYLE_VALUE,"value");
  207.     }
  208.     else if (!strncasecomp(element, "high", 4)) /* [INLINE]'s */
  209.     {
  210.     parse_attributes(mono,fg,bg,DSTYLE_HIGH,"high");
  211.     }
  212.     else if (!strcasecomp(element, "normal")) /* added - kw */
  213.     {
  214.     parse_attributes(mono,fg,bg,DSTYLE_NORMAL,"html");
  215.     }
  216.     /* this may vanish */
  217.     else if (!strncasecomp(element, "candy", 5)) /* [INLINE]'s */
  218.     {
  219.     parse_attributes(mono,fg,bg,DSTYLE_CANDY,"candy");
  220.     }
  221.     /* Ok, it must be a HTML element, so look through the list until we
  222.     * find it
  223.     */
  224.     else
  225.     {
  226. #if !defined(USE_HASH)
  227.     int i;
  228.     for (i = 0; i <HTML_ELEMENTS; i++)
  229.     {
  230.         if (!strcasecomp (HTML_dtd.tags[i].name, element))
  231.         {
  232.         CTRACE(tfp, "PARSECSS:applying style <%s,%s,%s> for HTML_%s\n",mono,fg,bg,HTML_dtd.tags[i].name);
  233.             parse_attributes(mono,fg,bg,i+STARTAT,element);
  234.         break;
  235.         }
  236.     }
  237. #else
  238.     int element_number = -1;
  239.     HTTag * t = SGMLFindTag(&HTML_dtd, element);
  240.     if (t && t->name) {
  241.         element_number = t - HTML_dtd.tags;
  242.     }
  243.     if (element_number >= HTML_A &&
  244.         element_number < HTML_ELEMENTS)
  245.         parse_attributes(mono,fg,bg, element_number+STARTAT,element);
  246.     else
  247.         parse_attributes(mono,fg,bg, DSTYLE_ELEMENTS,element);
  248. #endif
  249.     }
  250. }
  251.  
  252. PRIVATE void free_colorstylestuff NOARGS
  253. {
  254.     style_initialiseHashTable();
  255.     style_deleteStyleList();
  256. }
  257.  
  258. /*
  259.  * initialise the default style sheet
  260.  * This should be able to be read from a file in CSS format :-)
  261.  */
  262. PRIVATE void initialise_default_stylesheet NOARGS
  263. {
  264. }
  265.  
  266. /* Set all the buckets in the hash table to be empty */
  267. PUBLIC void style_initialiseHashTable NOARGS
  268. {
  269.     int i;
  270.     static int firsttime = 1;
  271.  
  272.     for (i = 0; i <CSHASHSIZE; i++)
  273.     {
  274.         if (firsttime)
  275.         hashStyles[i].name = NULL;
  276.         else
  277.         FREE(hashStyles[i].name);
  278.         hashStyles[i].color = -1;
  279.         hashStyles[i].cattr = -1;
  280.         hashStyles[i].mono  = -1;
  281.     }
  282.     if (firsttime) {
  283.         firsttime = 0;
  284.         atexit(free_colorstylestuff);
  285.     }
  286.     s_high   = hash_code("high");
  287.     s_alink  = hash_code("alink");
  288.     s_value  = hash_code("value");
  289.     s_label  = hash_code("label");
  290.     s_a      = hash_code("a");
  291.     s_status = hash_code("status");
  292.     s_alert  = hash_code("alert");
  293.     s_title  = hash_code("title");
  294. }
  295.  
  296. /* because curses isn't started when we parse the config file, we
  297.  * need to remember the STYLE: lines we encounter and parse them
  298.  * after curses has started
  299.  */
  300. HTList *lss_styles = NULL;
  301.  
  302. PUBLIC void parse_userstyles NOARGS
  303. {
  304.     char *name;
  305.     HTList *cur = lss_styles;
  306.     colorPairs = 0;
  307.     style_initialiseHashTable();
  308.  
  309.     /* set our styles to be the same as vanilla-curses-lynx */
  310.     initialise_default_stylesheet();
  311.  
  312.     while ((name = HTList_nextObject(cur)) != NULL)
  313.     {
  314.         CTRACE(tfp, "LSS:%s\n", name ? name : "!?! empty !?!");
  315.         if (name != NULL)
  316.             parse_style(name);
  317.     }
  318. }
  319.  
  320.  
  321. /* Add a STYLE: option line to our list */
  322. PUBLIC void HStyle_addStyle ARGS1(char*,buffer)
  323. {
  324.     char *name = NULL;
  325.     StrAllocCopy(name, buffer);
  326.     if (lss_styles == NULL)
  327.         lss_styles = HTList_new();
  328.     strtolower(name);
  329.     CTRACE(tfp, "READCSS:%s\n", name ? name : "!?! empty !?!");
  330.     HTList_addObject (lss_styles, name);
  331. }
  332.  
  333. PUBLIC void style_deleteStyleList NOARGS
  334. {
  335.     char *name;
  336.     while ((name = HTList_removeLastObject(lss_styles)) != NULL)
  337.     FREE(name);
  338.     HTList_delete (lss_styles);
  339.     lss_styles = NULL;
  340. }
  341.  
  342. char* default_stylesheet[] = {
  343.     "a:bold", "em:bold", "strong:bold", "b:bold", "i:bold",
  344.     "alink:reverse", "status:reverse", NULL
  345. };
  346.  
  347. PUBLIC void style_defaultStyleSheet NOARGS
  348. {
  349.     int i;
  350.     for (i = 0; default_stylesheet[i]; i++)
  351.         HStyle_addStyle(default_stylesheet[i]);
  352. }
  353.  
  354. PUBLIC int style_readFromFile ARGS1(char*, file)
  355. {
  356.     FILE *fh;
  357.     char buffer[1024];
  358.     int len;
  359.  
  360.     CTRACE(tfp, "CSS:Reading styles from file: %s\n", file ? file : "?!? empty ?!?");
  361.     if (file == NULL || *file == '\0')
  362.     return -1;
  363.     fh = fopen(file, "r");
  364.     if (!fh)
  365.     {
  366.     /* this should probably be an alert or something */
  367.     CTRACE(tfp, "CSS:Can't open style file %s, using defaults\n", file);
  368.     return -1;
  369.     }
  370.  
  371.     style_initialiseHashTable();
  372.     style_deleteStyleList();
  373.  
  374.     while (!feof(fh)
  375.     && fgets(buffer, sizeof(buffer)-1, fh) != NULL)
  376.     {
  377.     len = strlen(buffer);
  378.     if (len > 0) {
  379.         if (buffer[len-1] == '\n' || buffer[len-1] == '\r')
  380.         buffer[len-1] = '\0'; /* hack */
  381.         else
  382.         buffer[sizeof(buffer)-1] = '\0'; /* hack */
  383.     }
  384.     LYTrimTail(buffer);
  385.     LYTrimHead(buffer);
  386.     if (buffer[0] != '#' && (len = strlen(buffer)) > 0)
  387.         HStyle_addStyle(buffer);
  388.     }
  389.     /* the default styles are added after the user styles in order
  390.     ** that they come before them  <grin>  RP
  391.     */
  392.     /*    style_defaultStyleSheet(); */
  393.  
  394.     fclose (fh);
  395.     if (LYCursesON)
  396.     parse_userstyles();
  397.     return 0;
  398. }
  399. #endif /* USE_COLOR_STYLE */
  400.