In some cases, an option of "50%" would be preferable over fixed value
configuration - especially if the actual values are autoprobed.
Add a new set of functions to parse percent values from configurations.

The percent value parsing differs slightly - if the option is not to marked
as used (e.g. xf86CheckPercentOption()), no warning is emitted to the log
file if the value is not a percent value. This allows double-options (either
as % or as absolute number) without warnings.

Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net>
---

Changes to v2:
- xwin pieces added (untested). John, Yaakov, can you please give this a
  quick test?
- optionTypeToString missing bits added
- DESIGN.sgml updated to list the new option

 hw/xfree86/common/xf86Configure.c |    5 +++-
 hw/xfree86/common/xf86Opt.h       |    4 +++
 hw/xfree86/common/xf86Option.c    |   47 +++++++++++++++++++++++++++++++++++++
 hw/xfree86/common/xf86ShowOpts.c  |    2 +
 hw/xfree86/doc/sgml/DESIGN.sgml   |    6 ++++
 hw/xwin/winconfig.c               |   37 +++++++++++++++++++++++++++++
 hw/xwin/winconfig.h               |    2 +
 7 files changed, 102 insertions(+), 1 deletions(-)

diff --git a/hw/xfree86/common/xf86Configure.c 
b/hw/xfree86/common/xf86Configure.c
index 67bf08b..1573cc6 100644
--- a/hw/xfree86/common/xf86Configure.c
+++ b/hw/xfree86/common/xf86Configure.c
@@ -339,6 +339,8 @@ optionTypeToSting(OptionValueType type)
         return "[<bool>]";
     case OPTV_FREQ:
         return "<freq>";
+    case OPTV_PERCENT:
+        return "<percent>";
     default:
         return "";
     }
@@ -384,7 +386,8 @@ configureDeviceSection (int screennum)
            "        ### Available Driver options are:-\n"
            "        ### Values: <i>: integer, <f>: float, "
                        "<bool>: \"True\"/\"False\",\n"
-           "        ### <string>: \"String\", <freq>: \"<f> Hz/kHz/MHz\"\n"
+           "        ### <string>: \"String\", <freq>: \"<f> Hz/kHz/MHz\",\n"
+           "        ### <percent>: \"<f>%\"\n"
            "        ### [arg]: arg optional\n";
        ptr->dev_comment = xstrdup(descrip);
        if (ptr->dev_comment) {
diff --git a/hw/xfree86/common/xf86Opt.h b/hw/xfree86/common/xf86Opt.h
index ce3d767..d75d3bf 100644
--- a/hw/xfree86/common/xf86Opt.h
+++ b/hw/xfree86/common/xf86Opt.h
@@ -51,6 +51,7 @@ typedef enum {
     OPTV_ANYSTR,                /* Any string, including an empty one */
     OPTV_REAL,
     OPTV_BOOLEAN,
+    OPTV_PERCENT,
     OPTV_FREQ
 } OptionValueType;
 
@@ -72,10 +73,12 @@ extern _X_EXPORT int xf86SetIntOption(pointer optlist, 
const char *name, int def
 extern _X_EXPORT double xf86SetRealOption(pointer optlist, const char *name, 
double deflt);
 extern _X_EXPORT char *xf86SetStrOption(pointer optlist, const char *name, 
char *deflt);
 extern _X_EXPORT int xf86SetBoolOption(pointer list, const char *name, int 
deflt );
+extern _X_EXPORT double xf86SetPercentOption(pointer list, const char *name, 
double deflt );
 extern _X_EXPORT int xf86CheckIntOption(pointer optlist, const char *name, int 
deflt);
 extern _X_EXPORT double xf86CheckRealOption(pointer optlist, const char *name, 
double deflt);
 extern _X_EXPORT char *xf86CheckStrOption(pointer optlist, const char *name, 
char *deflt);
 extern _X_EXPORT int xf86CheckBoolOption(pointer list, const char *name, int 
deflt );
+extern _X_EXPORT double xf86CheckPercentOption(pointer list, const char *name, 
double deflt );
 extern _X_EXPORT pointer xf86AddNewOption(pointer head, const char *name, 
const char *val );
 extern _X_EXPORT pointer xf86NewOption(char *name, char *value );
 extern _X_EXPORT pointer xf86NextOption(pointer list );
@@ -109,5 +112,6 @@ extern _X_EXPORT char *xf86NormalizeName(const char *s);
 extern _X_EXPORT pointer xf86ReplaceIntOption(pointer optlist,  const char 
*name, const int val);
 extern _X_EXPORT pointer xf86ReplaceRealOption(pointer optlist,  const char 
*name, const double val);
 extern _X_EXPORT pointer xf86ReplaceBoolOption(pointer optlist, const char 
*name, const Bool val);
+extern _X_EXPORT pointer xf86ReplacePercentOption(pointer optlist, const char 
*name, const double val);
 extern _X_EXPORT pointer xf86ReplaceStrOption(pointer optlist,  const char 
*name, const char* val);
 #endif
diff --git a/hw/xfree86/common/xf86Option.c b/hw/xfree86/common/xf86Option.c
index a2868bf..7971837 100644
--- a/hw/xfree86/common/xf86Option.c
+++ b/hw/xfree86/common/xf86Option.c
@@ -223,6 +223,18 @@ LookupBoolOption(pointer optlist, const char *name, int 
deflt, Bool markUsed)
     return deflt;
 }
 
+static int
+LookupPercentOption(pointer optlist, const char *name, double deflt, Bool 
markUsed)
+{
+    OptionInfoRec o;
+
+    o.name = name;
+    o.type = OPTV_PERCENT;
+    if (ParseOptionValue(-1, optlist, &o, markUsed))
+       deflt = o.value.realnum;
+    return deflt;
+}
+
 /* These xf86Set* functions are intended for use by non-screen specific code */
 
 int
@@ -252,6 +264,12 @@ xf86SetBoolOption(pointer optlist, const char *name, int 
deflt)
     return LookupBoolOption(optlist, name, deflt, TRUE);
 }
 
+double
+xf86SetPercentOption(pointer optlist, const char *name, double deflt)
+{
+    return LookupPercentOption(optlist, name, deflt, TRUE);
+}
+
 /*
  * These are like the Set*Option functions, but they don't mark the options
  * as used.
@@ -283,6 +301,12 @@ xf86CheckBoolOption(pointer optlist, const char *name, int 
deflt)
     return LookupBoolOption(optlist, name, deflt, FALSE);
 }
 
+
+double
+xf86CheckPercentOption(pointer optlist, const char *name, double deflt)
+{
+    return LookupPercentOption(optlist, name, deflt, FALSE);
+}
 /*
  * addNewOption() has the required property of replacing the option value
  * if the option is already present.
@@ -310,6 +334,14 @@ xf86ReplaceBoolOption(pointer optlist, const char *name, 
const Bool val)
 }
 
 pointer
+xf86ReplacePercentOption(pointer optlist, const char *name, const double val)
+{
+    char tmp[16];
+    sprintf(tmp, "%lf%%", val);
+    return xf86AddNewOption(optlist,name,tmp);
+}
+
+pointer
 xf86ReplaceStrOption(pointer optlist, const char *name, const char* val)
 {
       return xf86AddNewOption(optlist,name,val);
@@ -533,6 +565,21 @@ ParseOptionValue(int scrnIndex, pointer options, 
OptionInfoPtr p,
                p->found = FALSE;
            }
            break;
+       case OPTV_PERCENT:
+           {
+               char tmp = 0;
+               /* awkward match, but %% doesn't increase the match counter,
+                * hence 100 looks the same as 100% to the caller of sccanf
+                */
+               if (sscanf(s, "%lf%c", &p->value.realnum, &tmp) != 2 || tmp != 
'%') {
+                   xf86DrvMsg(scrnIndex, X_WARNING,
+                              "Option \"%s\" requires a percent value\n", 
p->name);
+                   p->found = FALSE;
+               } else {
+                   p->found = TRUE;
+               }
+           }
+           break;
        case OPTV_FREQ: 
            if (*s == '\0') {
                xf86DrvMsg(scrnIndex, X_WARNING,
diff --git a/hw/xfree86/common/xf86ShowOpts.c b/hw/xfree86/common/xf86ShowOpts.c
index 04a9a8b..bd9b3d7 100644
--- a/hw/xfree86/common/xf86ShowOpts.c
+++ b/hw/xfree86/common/xf86ShowOpts.c
@@ -70,6 +70,8 @@ optionTypeToSting(OptionValueType type)
         return "<bool>";
     case OPTV_FREQ:
         return "<freq>";
+    case OPTV_PERCENT:
+        return "<percent>";
     default:
         return "<undef>";
     }
diff --git a/hw/xfree86/doc/sgml/DESIGN.sgml b/hw/xfree86/doc/sgml/DESIGN.sgml
index e95df79..8999e0c 100644
--- a/hw/xfree86/doc/sgml/DESIGN.sgml
+++ b/hw/xfree86/doc/sgml/DESIGN.sgml
@@ -2528,6 +2528,7 @@ Next, the higher level functions that most drivers would 
use.
           OPTV_ANYSTR,  /* Any string, including an empty one */
           OPTV_REAL,
           OPTV_BOOLEAN,
+          OPTV_PERCENT,
           OPTV_FREQ
       } OptionValueType;
 
@@ -2555,6 +2556,11 @@ Next, the higher level functions that most drivers would 
use.
       &s.code;freq.units&e.code; is set to &s.code;0&e.code;, and
       &s.code;freq.freq&e.code; is unscaled.
 
+      &s.code;OPTV_PERCENT&e.code; can be used for option values that are
+      specified in percent (e.g. "20%"). These values are a floating point
+      number with a percent sign appended. If the percent sign is missing,
+      the parser will fail to match the value.
+
       Typical usage is to setup an array of
       &s.code;OptionInfoRecs&e.code; with all fields initialised.
       The &s.code;value&e.code; and &s.code;found&e.code; fields get
diff --git a/hw/xwin/winconfig.c b/hw/xwin/winconfig.c
index b05867b..61be087 100644
--- a/hw/xwin/winconfig.c
+++ b/hw/xwin/winconfig.c
@@ -673,6 +673,18 @@ winSetRealOption (pointer optlist, const char *name, 
double deflt)
     deflt = o.value.realnum;
   return deflt;
 }
+
+double
+winSetPercentOption (pointer optlist, const char *name, double deflt)
+{
+  OptionInfoRec o;
+
+  o.name = name;
+  o.type = OPTV_PERCENT;
+  if (ParseOptionValue (-1, optlist, &o))
+    deflt = o.value.realnum;
+  return deflt;
+}
 #endif
 
 
@@ -851,6 +863,31 @@ ParseOptionValue (int scrnIndex, pointer options, 
OptionInfoPtr p)
              p->found = FALSE;
            }
          break;
+       case OPTV_PERCENT:
+         if (*s == '\0')
+           {
+             winDrvMsg (scrnIndex, X_WARNING,
+                        "Option \"%s\" requires a percent value\n",
+                        p->name);
+             p->found = FALSE;
+           }
+         else
+           {
+              double percent = strtod (s, &end);
+
+              if (end != s && winNameCompare (end, "%"))
+                {
+                  p->found = TRUE;
+                  p->value.realnum = percent;
+                }
+              else
+                {
+                  winDrvMsg (scrnIndex, X_WARNING,
+                             "Option \"%s\" requires a frequency value\n",
+                              p->name);
+                  p->found = FALSE;
+                }
+           }
        case OPTV_FREQ:
          if (*s == '\0')
            {
diff --git a/hw/xwin/winconfig.h b/hw/xwin/winconfig.h
index 058884a..4699ca8 100644
--- a/hw/xwin/winconfig.h
+++ b/hw/xwin/winconfig.h
@@ -256,6 +256,7 @@ typedef enum
   OPTV_ANYSTR,                 /* Any string, including an empty one */
   OPTV_REAL,
   OPTV_BOOLEAN,
+  OPTV_PERCENT,
   OPTV_FREQ
 }
 OptionValueType;
@@ -289,6 +290,7 @@ char *winSetStrOption (pointer optlist, const char *name, 
char *deflt);
 int winSetBoolOption (pointer optlist, const char *name, int deflt);
 int winSetIntOption (pointer optlist, const char *name, int deflt);
 double winSetRealOption (pointer optlist, const char *name, double deflt);
+double winSetPercentOption (pointer optlist, const char *name, double deflt);
 #ifdef XWIN_XF86CONFIG
 XF86OptionPtr winFindOption (XF86OptionPtr list, const char *name);
 char *winFindOptionValue (XF86OptionPtr list, const char *name);
-- 
1.7.0.1

_______________________________________________
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to