]> git.decadent.org.uk Git - ion3.git/blobdiff - de/init.c
[svn-upgrade] Integrating new upstream version, ion3 (20070506)
[ion3.git] / de / init.c
index bc771d08144a2407022505bf282c4e47bf7f0ac9..60c87156375883d50a5b872b2d85ce34f6dd97d6 100644 (file)
--- a/de/init.c
+++ b/de/init.c
@@ -3,10 +3,7 @@
  *
  * Copyright (c) Tuomo Valkonen 1999-2007. 
  *
- * Ion is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
+ * See the included file LICENSE for details.
  */
 
 #include <string.h>
@@ -130,45 +127,58 @@ void de_get_border(DEBorder *border, ExtlTab tab)
 /*{{{ Colours */
 
 
-bool de_get_colour(WRootWin *rootwin, DEColour *ret, 
-                   ExtlTab tab, DEStyle *based_on,
-                   const char *what, DEColour substitute)
+static bool de_get_colour_(WRootWin *rootwin, DEColour *ret, 
+                           ExtlTab tab, const char *what, 
+                           DEColour substitute, DEColour inherit)
 {
     char *name=NULL;
-    bool ok=FALSE;
+    bool set=FALSE;
     
     if(extl_table_gets_s(tab, what, &name)){
-        ok=de_alloc_colour(rootwin, ret, name);
+        if(strcmp(name, "inherit")==0){
+            set=de_duplicate_colour(rootwin, inherit, ret);
+        }else{
+            set=de_alloc_colour(rootwin, ret, name);
     
-        if(!ok)
-            warn(TR("Unable to allocate colour \"%s\"."), name);
-
+            if(!set)
+                warn(TR("Unable to allocate colour \"%s\"."), name);
+        }
         free(name);
-    }else if(based_on!=NULL){
-        return de_get_colour(rootwin, ret, based_on->data_table,
-                             based_on->based_on, what, substitute);
     }
     
-    if(!ok)
-        ok=de_duplicate_colour(rootwin, substitute, ret);
+    if(!set)
+        de_duplicate_colour(rootwin, substitute, ret);
     
-    return ok;
+    return set;
 }
 
 
+static bool de_get_colour(WRootWin *rootwin, DEColour *ret, 
+                          ExtlTab tab, const char *what, DEColour substitute)
+{
+    return de_get_colour_(rootwin, ret, tab, what, substitute, substitute);
+}
+                          
+
 void de_get_colour_group(WRootWin *rootwin, DEColourGroup *cg, 
                          ExtlTab tab, DEStyle *based_on)
 {
-    de_get_colour(rootwin, &(cg->hl), tab, based_on, "highlight_colour",
-                  DE_WHITE(rootwin));
-    de_get_colour(rootwin, &(cg->sh), tab, based_on, "shadow_colour",
-                  DE_WHITE(rootwin));
-    de_get_colour(rootwin, &(cg->bg), tab, based_on, "background_colour",
-                  DE_BLACK(rootwin));
-    de_get_colour(rootwin, &(cg->fg), tab, based_on, "foreground_colour",
-                  DE_WHITE(rootwin));
-    de_get_colour(rootwin, &(cg->pad), tab, based_on, "padding_colour", 
-                  cg->bg);
+    bool bgset;
+    DEColour padinh;
+    
+    de_get_colour(rootwin, &(cg->hl), tab, "highlight_colour",
+                  (based_on ? based_on->cgrp.hl : DE_WHITE(rootwin)));
+    de_get_colour(rootwin, &(cg->sh), tab, "shadow_colour",
+                  (based_on ? based_on->cgrp.sh : DE_WHITE(rootwin)));
+    de_get_colour(rootwin, &(cg->fg), tab, "foreground_colour",
+                  (based_on ? based_on->cgrp.fg : DE_WHITE(rootwin)));
+    bgset=de_get_colour(rootwin, &(cg->bg), tab, "background_colour",
+                        (based_on ? based_on->cgrp.bg : DE_BLACK(rootwin)));
+                        
+    padinh=(based_on ? based_on->cgrp.pad : DE_WHITE(rootwin));
+    
+    de_get_colour_(rootwin, &(cg->pad), tab, "padding_colour", 
+                   (bgset ? cg->bg : padinh), padinh);
 }
 
 
@@ -258,6 +268,63 @@ void de_get_transparent_background(uint *mode, ExtlTab tab)
 /*}}}*/
 
 
+/*{{{ Extras filter/copy */
+
+
+static const char * const known_values[]={
+    "based_on",
+    "font",
+    "shadow_pixels",
+    "highlight_pixels",
+    "padding_pixels",
+    "border_style",
+    "border_sides",
+    "spacing",
+    "foreground_colour",
+    "background_colour",
+    "shadow_colour",
+    "highlight_colour",
+    "padding_colour",
+    "text_align",
+    NULL
+};
+
+
+static bool filter_extras_iter_fn(ExtlAny k, ExtlAny v, void *p)
+{
+    ExtlTab *tgt=(ExtlTab*)p;
+    const char *s;
+    int i;
+    
+    if(k.type!='s' && k.type!='S')
+        return TRUE;
+    
+    for(i=0; known_values[i]; i++){
+        if(strcmp(known_values[i], k.value.s)==0)
+            return TRUE;
+    }
+    
+    if(*tgt==extl_table_none())
+        *tgt=extl_create_table();
+        
+    extl_table_set(*tgt, 'a', 'a', k, v);
+    
+    return TRUE;
+}
+
+
+static void filter_extras(ExtlTab *tgt, ExtlTab src)
+{
+    /* Copy any unknown string-keyed values from src to tgt,
+     * possibly creating tgt.
+     */
+    extl_table_iter(src, filter_extras_iter_fn, tgt);
+}
+
+
+/*}}}*/
+
+
 /*{{{ de_defstyle */
 
 
@@ -265,8 +332,6 @@ void de_get_nonfont(WRootWin *rootwin, DEStyle *style, ExtlTab tab)
 {
     DEStyle *based_on=style->based_on;
     
-    style->data_table=extl_ref_table(tab);
-
     if(based_on!=NULL){
         style->border=based_on->border;
         style->transparency_mode=based_on->transparency_mode;
@@ -295,40 +360,37 @@ void de_get_nonfont(WRootWin *rootwin, DEStyle *style, ExtlTab tab)
 EXTL_EXPORT
 bool de_defstyle_rootwin(WRootWin *rootwin, const char *name, ExtlTab tab)
 {
-    DEStyle *style;
-    char *fnt;
+    DEStyle *style, *based_on=NULL;
+    int based_on_score=-1;
+    char *fnt, *bss;
     uint n;
-    char *based_on_name;
-    DEStyle *based_on=NULL;
-    GrStyleSpec based_on_spec;
 
     if(name==NULL)
         return FALSE;
     
     style=de_create_style(rootwin, name);
-
+    
     if(style==NULL)
         return FALSE;
-
-    if(get_spec(tab, "based_on", &based_on_spec, &based_on_name)){
-        based_on=de_get_style(rootwin, &based_on_spec);
+    
+    if(extl_table_gets_s(tab, "based_on", &bss)){
+        GrStyleSpec bs;
         
-        gr_stylespec_unalloc(&based_on_spec);
-
-        if(based_on==style){
-            warn(TR("'based_on' for %s points back to the style itself."),
-                 name);
-        }else if(based_on==NULL){
-            warn(TR("Unknown base style. \"%s\""), based_on_name);
-        }else{
-            style->based_on=based_on;
-            based_on->usecount++;
-            /* Copy simple parameters */
-        }
+        gr_stylespec_load(&bs, bss);
+        
+        based_on=de_get_style(rootwin, &bs);
         
-        free(based_on_name);
+        gr_stylespec_unalloc(&bs);
+        free(bss);
+    }else{
+        based_on=de_get_style(rootwin, &style->spec);
     }
-
+    
+    if(based_on!=NULL){
+        style->based_on=based_on;
+        based_on->usecount++;
+    }
+    
     de_get_nonfont(rootwin, style, tab);
 
     if(extl_table_gets_s(tab, "font", &fnt)){
@@ -341,6 +403,54 @@ bool de_defstyle_rootwin(WRootWin *rootwin, const char *name, ExtlTab tab)
     if(style->font==NULL)
         de_load_font_for_style(style, CF_FALLBACK_FONT_NAME);
     
+    if(based_on!=NULL && 
+       gr_stylespec_equals(&based_on->spec, &style->spec)){
+       
+        /* The new style replaces based_on, so it may be dumped. */
+        if(!based_on->is_fallback)
+            destyle_dump(based_on);
+        
+        if(based_on->usecount==1){
+            uint nb=based_on->n_extra_cgrps;
+            uint ns=style->n_extra_cgrps;
+            /* Nothing else is using based_on: optimise and move
+             * extra colour groups here, so that based_on can be freed.
+             */
+            
+            if(nb>0){
+                DEColourGroup *cgs=ALLOC_N(DEColourGroup, nb+ns);
+                
+                if(cgs!=NULL){
+                    memcpy(cgs, based_on->extra_cgrps, sizeof(DEColourGroup)*nb);
+                    memcpy(cgs+nb, style->extra_cgrps, sizeof(DEColourGroup)*ns);
+                
+                    free(style->extra_cgrps);
+                    style->extra_cgrps=cgs;
+                    style->n_extra_cgrps=nb+ns;
+                
+                    free(based_on->extra_cgrps);
+                    based_on->extra_cgrps=NULL;
+                    based_on->n_extra_cgrps=0;
+                    
+                }
+            }
+            
+            /* style->extras_table should be none still */
+            style->extras_table=based_on->extras_table;
+            based_on->extras_table=extl_table_none();
+            
+            style->based_on=based_on->based_on;
+            based_on->based_on=NULL;
+            
+            destyle_unref(based_on);
+        }
+        
+    }
+    
+    filter_extras(&style->extras_table, tab);
+    
+    destyle_add(style);
+    
     return TRUE;
 }