]> git.decadent.org.uk Git - ion3.git/blobdiff - ioncore/gr.c
Update cfg_kludge_flash for Flash 10
[ion3.git] / ioncore / gr.c
index d4f5a151959e6c7242284647a50e8bc2b1da9f7c..b1712a1afe83fd47de4c5a7379a8596b24b0aaa7 100644 (file)
@@ -1,17 +1,15 @@
 /*
  * ion/ioncore/gr.c
  *
- * Copyright (c) Tuomo Valkonen 1999-2006
+ * Copyright (c) Tuomo Valkonen 1999-2009
  *
- * 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>
 
 #include <libtu/objp.h>
+#include <libtu/minmax.h>
 #include <libextl/readconfig.h>
 #include <libmainloop/hooks.h>
 #include "common.h"
@@ -97,7 +95,7 @@ static bool gr_do_select_engine(const char *engine)
 
 
 /*EXTL_DOC
- * Future requests for ''brushes'' are to be forwarded to the drawing engine
+ * Future requests for ``brushes'' are to be forwarded to the drawing engine
  * \var{engine}. If no engine of such name is known, a module with that name
  * is attempted to be loaded. This function is only intended to be called from
  * colour scheme etc. configuration files and can not be used to change the
@@ -147,68 +145,303 @@ GrBrush *gr_get_brush(Window win, WRootWin *rootwin, const char *style)
 /*{{{ Scoring */
 
 
-uint gr_stylespec_score2(const char *spec, const char *attrib, 
-                         const char *attrib_p2)
+static GrAttr star_id=STRINGID_NONE;
+
+
+static int cmp(const void *a_, const void *b_)
 {
-    uint score=0;
-    uint a=0;
-    uint mult=1;
+    StringId a=*(const StringId*)a_;
+    StringId b=((const GrAttrScore*)b_)->attr;
+    
+    return (a < b ? -1 : ((a == b) ? 0 : 1));
+}
 
-    if(attrib==NULL){
-        if(spec==NULL || strcmp(spec, "*")==0)
-            return 1;
+
+static uint scorefind(const GrStyleSpec *attr, const GrAttrScore *spec)
+{
+    GrAttrScore *res;
+    
+    if(attr->attrs==NULL)
         return 0;
+    
+    if(star_id==STRINGID_NONE)
+        star_id=stringstore_alloc("*");
+    
+    if(spec->attr==star_id){
+        /* Since every item occurs only once on the list, with a score,
+         * return the score of the star in the spec, instead of one.
+         */
+        return spec->score;
+    }
+    
+    res=bsearch(&spec->attr, attr->attrs, attr->n, sizeof(GrAttrScore), cmp);
+    
+    return (res==NULL ? 0 : 2*res->score);
+}
+
+
+uint gr_stylespec_score2(const GrStyleSpec *spec, const GrStyleSpec *attr1, 
+                         const GrStyleSpec *attr2)
+{
+    uint score=0;
+    uint i;
+    
+    for(i=0; i<spec->n; i++){
+        int sc=scorefind(attr1, &spec->attrs[i]);
+        
+        if(attr2!=NULL)
+            sc=maxof(sc, scorefind(attr2, &spec->attrs[i]));
+        
+        if(sc==0){
+            score=0;
+            break;
+        }
+        
+        score+=sc;
     }
     
-    while(1){
-        if(*spec=='*'){
-            score=score+mult;
-            spec++;
-            attrib=strchr(attrib, '-');
+    return score;
+}
+
+
+uint gr_stylespec_score(const GrStyleSpec *spec, const GrStyleSpec *attr)
+{
+    return gr_stylespec_score2(spec, attr, NULL);
+}
+
+
+static uint count_dashes(const char *str)
+{
+    uint n=0;
+    
+    if(str!=NULL){
+        while(1){
+            const char *p=strchr(str, '-');
+            if(p==NULL)
+                break;
+            n++;
+            str=p+1;
+        }
+    }
+    
+    return n;
+}
+    
+    
+bool gr_stylespec_load_(GrStyleSpec *spec, const char *str, bool no_order_score)
+{
+    uint score=(no_order_score ? 1 : count_dashes(str)+1);
+    
+    gr_stylespec_init(spec);
+    
+    while(str!=NULL){
+        GrAttr a;
+        const char *p=strchr(str, '-');
+    
+        if(p==NULL){
+            a=stringstore_alloc(str);
+            str=p;
         }else{
-            while(1){
-                if(*attrib=='\0'){
-                    attrib=NULL;
-                    break;
-                }
-                if(*attrib=='-')
-                    break;
-                if(*spec!=*attrib)
-                    return 0;
-                attrib++;
-                spec++;
-            }
-            score=score+2*mult;
+            a=stringstore_alloc_n(str, p-str);
+            str=p+1;
         }
         
-        if(*spec=='\0')
-            return score;
-        else if(*spec!='-')
-            return 0;
+        if(a==STRINGID_NONE)
+            goto fail;
+            
+        if(!gr_stylespec_add(spec, a, score))
+            goto fail;
+            
+        stringstore_free(a);
         
-        if(attrib==NULL){
-            if(a==0 && attrib_p2!=NULL){
-                attrib=attrib_p2;
-                a++;
-            }else{
-                return 0;
-            }
-        }else{
-            attrib++;
+        if(!no_order_score)
+            score--;
+    }
+    
+    return TRUE;
+    
+fail:
+    gr_stylespec_unalloc(spec);
+    
+    return FALSE;
+}
+
+
+bool gr_stylespec_load(GrStyleSpec *spec, const char *str)
+{
+    return gr_stylespec_load_(spec, str, FALSE);
+}
+
+
+void gr_stylespec_unalloc(GrStyleSpec *spec)
+{
+    uint i;
+    
+    for(i=0; i<spec->n; i++)
+        stringstore_free(spec->attrs[i].attr);
+    
+    if(spec->attrs!=NULL){
+        free(spec->attrs);
+        spec->attrs=NULL;
+    }
+    
+    spec->n=0;
+}
+
+
+void gr_stylespec_init(GrStyleSpec *spec)
+{
+    spec->attrs=NULL;
+    spec->n=0;
+}
+
+
+static bool gr_stylespec_find_(const GrStyleSpec *spec, GrAttr a, int *idx_ge)
+{
+    bool found=FALSE;
+    uint i;
+    
+    for(i=0; i<spec->n; i++){
+        if(spec->attrs[i].attr>=a){
+            found=(spec->attrs[i].attr==a);
+            break;
         }
+    }
+    
+    *idx_ge=i;
+    return found;
+}
 
-        spec++;
-        mult=mult*3;
+
+bool gr_stylespec_isset(const GrStyleSpec *spec, GrAttr a)
+{
+    int idx_ge;
+    
+    return gr_stylespec_find_(spec, a, &idx_ge);
+}
+
+
+bool gr_stylespec_add(GrStyleSpec *spec, GrAttr a, uint score)
+{
+    static const uint sz=sizeof(GrAttrScore);
+    GrAttrScore *idsn;
+    int idx_ge;
+    
+    if(a==GRATTR_NONE || score==0)
+        return TRUE;
+    
+    if(gr_stylespec_find_(spec, a, &idx_ge)){
+        spec->attrs[idx_ge].score+=score;
+        return TRUE;
     }
+    
+    idsn=(GrAttrScore*)realloc(spec->attrs, (spec->n+1)*sz);
+    
+    if(idsn==NULL)
+        return FALSE;
+        
+    stringstore_ref(a);
+        
+    memmove(idsn+idx_ge+1, idsn+idx_ge, (spec->n-idx_ge)*sz);
+    
+    idsn[idx_ge].attr=a;
+    idsn[idx_ge].score=score;
+    spec->attrs=idsn;
+    spec->n++;
+    
+    return TRUE;
 }
 
 
-uint gr_stylespec_score(const char *spec, const char *attrib)
+bool gr_stylespec_set(GrStyleSpec *spec, GrAttr a)
 {
-    return gr_stylespec_score2(spec, attrib, NULL);
+    return gr_stylespec_add(spec, a, 1);
 }
 
 
+void gr_stylespec_unset(GrStyleSpec *spec, GrAttr a)
+{
+    static const uint sz=sizeof(GrAttrScore);
+    GrAttrScore *idsn;
+    int idx_ge;
+    
+    if(a==GRATTR_NONE)
+        return;
+    
+    if(!gr_stylespec_find_(spec, a, &idx_ge))
+        return;
+    
+    stringstore_free(spec->attrs[idx_ge].attr);
+    
+    memmove(spec->attrs+idx_ge, spec->attrs+idx_ge+1,
+            (spec->n-idx_ge-1)*sz);
+            
+    spec->n--;
+    
+    idsn=(GrAttrScore*)realloc(spec->attrs, (spec->n)*sz);
+    
+    if(idsn!=NULL || spec->n==0)
+        spec->attrs=idsn;
+}
+
+
+static bool gr_stylespec_do_init_from(GrStyleSpec *dst, const GrStyleSpec *src)
+{
+    uint i;
+    
+    if(src->n==0)
+        return TRUE;
+        
+    dst->attrs=ALLOC_N(GrAttrScore, src->n);
+    
+    if(dst->attrs==NULL)
+        return FALSE;
+    
+    for(i=0; i<src->n; i++){
+        dst->attrs[i]=src->attrs[i];
+        stringstore_ref(dst->attrs[i].attr);
+    }
+    
+    dst->n=src->n;
+    
+    return TRUE;
+}
+
+
+bool gr_stylespec_append(GrStyleSpec *dst, const GrStyleSpec *src)
+{
+    uint i;
+    bool ok=TRUE;
+    
+    if(dst->attrs==NULL){
+        ok=gr_stylespec_do_init_from(dst, src);
+    }else{
+        for(i=0; i<src->n; i++){
+            if(!gr_stylespec_add(dst, src->attrs[i].attr, src->attrs[i].score))
+                ok=FALSE;
+        }
+    }
+    
+    return ok;
+}
+
+
+bool gr_stylespec_equals(const GrStyleSpec *s1, const GrStyleSpec *s2)
+{
+    uint i;
+    
+    if(s1->n!=s2->n)
+        return FALSE;
+        
+    for(i=0; i<s1->n; i++){
+        if(s1->attrs[i].attr!=s2->attrs[i].attr)
+            return FALSE;
+    }
+    
+    return TRUE;
+}
+    
+
 /*}}}*/
 
 
@@ -294,17 +527,16 @@ DYNFUN bool grbrush_get_extra(GrBrush *brush, const char *key,
 /*{{{ Dynfuns/Borders */
 
 
-void grbrush_draw_border(GrBrush *brush, const WRectangle *geom,
-                         const char *attrib)
+void grbrush_draw_border(GrBrush *brush, const WRectangle *geom)
 {
-    CALL_DYN(grbrush_draw_border, brush, (brush, geom, attrib));
+    CALL_DYN(grbrush_draw_border, brush, (brush, geom));
 }
 
 
 void grbrush_draw_borderline(GrBrush *brush, const WRectangle *geom,
-                             const char *attrib, GrBorderLine line)
+                             GrBorderLine line)
 {
-    CALL_DYN(grbrush_draw_borderline, brush, (brush, geom, attrib, line));
+    CALL_DYN(grbrush_draw_borderline, brush, (brush, geom, line));
 }
 
 
@@ -315,11 +547,9 @@ void grbrush_draw_borderline(GrBrush *brush, const WRectangle *geom,
 
 
 void grbrush_draw_string(GrBrush *brush, int x, int y,
-                         const char *str, int len, bool needfill,
-                         const char *attrib)
+                         const char *str, int len, bool needfill)
 {
-    CALL_DYN(grbrush_draw_string, brush, 
-             (brush, x, y, str, len, needfill, attrib));
+    CALL_DYN(grbrush_draw_string, brush, (brush, x, y, str, len, needfill));
 }
 
 
@@ -339,19 +569,16 @@ uint grbrush_get_text_width(GrBrush *brush, const char *text, uint len)
 
 
 void grbrush_draw_textbox(GrBrush *brush, const WRectangle *geom,
-                          const char *text, const char *attr,
-                          bool needfill)
+                          const char *text, bool needfill)
 {
-    CALL_DYN(grbrush_draw_textbox, brush, 
-             (brush, geom, text, attr, needfill));
+    CALL_DYN(grbrush_draw_textbox, brush, (brush, geom, text, needfill));
 }
 
 void grbrush_draw_textboxes(GrBrush *brush, const WRectangle *geom,
                             int n, const GrTextElem *elem, 
-                            bool needfill, const char *common_attrib)
+                            bool needfill)
 {
-    CALL_DYN(grbrush_draw_textboxes, brush, 
-             (brush, geom, n, elem, needfill, common_attrib));
+    CALL_DYN(grbrush_draw_textboxes, brush, (brush, geom, n, elem, needfill));
 }
 
 
@@ -374,10 +601,9 @@ void grbrush_enable_transparency(GrBrush *brush, GrTransparency tr)
 }
 
 
-void grbrush_fill_area(GrBrush *brush, const WRectangle *geom,
-                       const char *attr)
+void grbrush_fill_area(GrBrush *brush, const WRectangle *geom)
 {
-    CALL_DYN(grbrush_fill_area, brush, (brush, geom, attr));
+    CALL_DYN(grbrush_fill_area, brush, (brush, geom));
 }
 
 
@@ -387,6 +613,24 @@ void grbrush_clear_area(GrBrush *brush, const WRectangle *geom)
 }
 
 
+void grbrush_init_attr(GrBrush *brush, const GrStyleSpec *spec)
+{
+    CALL_DYN(grbrush_init_attr, brush, (brush, spec));
+}
+
+
+void grbrush_set_attr(GrBrush *brush, GrAttr attr)
+{
+    CALL_DYN(grbrush_set_attr, brush, (brush, attr));
+}
+
+
+void grbrush_unset_attr(GrBrush *brush, GrAttr attr)
+{
+    CALL_DYN(grbrush_unset_attr, brush, (brush, attr));
+}
+
+
 /*}}}*/
 
 
@@ -394,7 +638,7 @@ void grbrush_clear_area(GrBrush *brush, const WRectangle *geom)
 
 
 /*EXTL_DOC
- * Read drawing engine configuration file \file{draw.lua}.
+ * Read drawing engine configuration file \file{look.lua}.
  */
 EXTL_EXPORT_AS(gr, read_config)
 void gr_read_config()