shithub: choc

Download patch

ref: be3d314a61d68281f02af1248a85e6aa069c4980
parent: ceefbc0827e321edb67aeed63a25beb458ffaeca
author: Simon Howard <[email protected]>
date: Fri Oct 6 20:59:03 EDT 2006

Add float spin control and use it for the acceleration controller in setup.

Subversion-branch: /trunk/chocolate-doom
Subversion-revision: 692

--- a/setup/mouse.c
+++ b/setup/mouse.c
@@ -30,7 +30,7 @@
 
 int novert;
 int speed;
-int accel;
+float accel;
 int threshold;
 int grabmouse = 1;
 
@@ -100,7 +100,7 @@
                    TXT_NewLabel("Speed"),
                    TXT_NewSpinControl(&speed, 1, 256),
                    TXT_NewLabel("Acceleration"),
-                   TXT_NewSpinControl(&accel, 1, 5),
+                   TXT_NewFloatSpinControl(&accel, 1.0, 5.0),
                    TXT_NewLabel("Acceleration threshold"),
                    TXT_NewSpinControl(&threshold, 0, 32),
                    NULL);
--- a/textscreen/txt_spinctrl.c
+++ b/textscreen/txt_spinctrl.c
@@ -33,11 +33,29 @@
 #include "txt_main.h"
 #include "txt_window.h"
 
+// Generate the format string to be used for displaying floats
+
+static void FloatFormatString(float step, char *buf)
+{
+    int precision;
+
+    precision = (int) ceil(-log(step) / log(10));
+
+    if (precision > 0)
+    {
+        sprintf(buf, "%%.%if", precision);
+    }
+    else
+    {
+        strcpy(buf, "%.1f");
+    }
+}
+
 // Number of characters needed to represent a character 
 
 static int IntWidth(int val)
 {
-    char buf[15];
+    char buf[25];
 
     sprintf(buf, "%i", val);
 
@@ -44,6 +62,27 @@
     return strlen(buf);
 }
 
+static int FloatWidth(float val, float step)
+{
+    int precision;
+    int result;
+
+    // Calculate the width of the int value
+
+    result = IntWidth((int) val);
+
+    // Add a decimal part if the precision specifies it
+
+    precision = (int) ceil(-log(step) / log(10));
+
+    if (precision > 0)
+    {
+        result += precision + 1;
+    }    
+
+    return result;
+}
+
 // Returns the minimum width of the input box
 
 static int SpinControlWidth(txt_spincontrol_t *spincontrol)
@@ -50,8 +89,20 @@
 {
     int minw, maxw;
 
-    minw = IntWidth(spincontrol->min);
-    maxw = IntWidth(spincontrol->max);
+    switch (spincontrol->type)
+    {
+        case TXT_SPINCONTROL_FLOAT:
+            minw = FloatWidth(spincontrol->min.f, spincontrol->step.f);
+            maxw = FloatWidth(spincontrol->max.f, spincontrol->step.f);
+            break;
+
+        default:
+        case TXT_SPINCONTROL_INT:
+            minw = IntWidth(spincontrol->min.i);
+            maxw = IntWidth(spincontrol->max.i);
+            break;
+
+    }
     
     // Choose the wider of the two values.  Add one so that there is always
     // space for the cursor when editing.
@@ -74,10 +125,26 @@
     spincontrol->widget.h = 1;
 }
 
+static void SetBuffer(txt_spincontrol_t *spincontrol)
+{
+    char format[25];
+
+    switch (spincontrol->type)
+    {
+        case TXT_SPINCONTROL_INT:
+            sprintf(spincontrol->buffer, "%i", spincontrol->value->i);
+            break;
+
+        case TXT_SPINCONTROL_FLOAT:
+            FloatFormatString(spincontrol->step.f, format);
+            sprintf(spincontrol->buffer, format, spincontrol->value->f);
+            break;
+    }
+}
+
 static void TXT_SpinControlDrawer(TXT_UNCAST_ARG(spincontrol), int selected)
 {
     TXT_CAST_ARG(txt_spincontrol_t, spincontrol);
-    char buf[15];
     unsigned int i;
     unsigned int padding;
 
@@ -103,18 +170,14 @@
         TXT_BGColor(TXT_COLOR_BLUE, 0);
     }
 
-    if (spincontrol->editing)
+    if (!spincontrol->editing)
     {
-        strcpy(buf, spincontrol->buffer);
+        SetBuffer(spincontrol);
     }
-    else
-    {
-        sprintf(buf, "%i", *spincontrol->value);
-    }
-
+    
     i = 0;
 
-    padding = spincontrol->widget.w - strlen(buf) - 4;
+    padding = spincontrol->widget.w - strlen(spincontrol->buffer) - 4;
 
     while (i < padding)
     {
@@ -122,8 +185,8 @@
         ++i;
     }
 
-    TXT_DrawString(buf);
-    i += strlen(buf);
+    TXT_DrawString(spincontrol->buffer);
+    i += strlen(spincontrol->buffer);
 
     while (i < spincontrol->widget.w - 4)
     {
@@ -162,10 +225,22 @@
 
 static void EnforceLimits(txt_spincontrol_t *spincontrol)
 {
-    if (*spincontrol->value > spincontrol->max)
-        *spincontrol->value = spincontrol->max;
-    else if (*spincontrol->value < spincontrol->min)
-        *spincontrol->value = spincontrol->min;
+    switch (spincontrol->type)
+    {
+        case TXT_SPINCONTROL_INT:
+            if (spincontrol->value->i > spincontrol->max.i)
+                spincontrol->value->i = spincontrol->max.i;
+            else if (spincontrol->value->i < spincontrol->min.i)
+                spincontrol->value->i = spincontrol->min.i;
+            break;
+
+        case TXT_SPINCONTROL_FLOAT:
+            if (spincontrol->value->f > spincontrol->max.f)
+                spincontrol->value->f = spincontrol->max.f;
+            else if (spincontrol->value->f < spincontrol->min.f)
+                spincontrol->value->f = spincontrol->min.f;
+            break;
+    }
 }
 
 static int TXT_SpinControlKeyPress(TXT_UNCAST_ARG(spincontrol), int key)
@@ -178,7 +253,17 @@
     {
         if (key == KEY_ENTER)
         {
-            *spincontrol->value = atoi(spincontrol->buffer);
+            switch (spincontrol->type)
+            {
+                case TXT_SPINCONTROL_INT:
+                    spincontrol->value->i = atoi(spincontrol->buffer);
+                    break;
+
+                case TXT_SPINCONTROL_FLOAT:
+                    spincontrol->value->f = (float) atof(spincontrol->buffer);
+                    break;
+            }
+
             spincontrol->editing = 0;
             EnforceLimits(spincontrol);
             return 1;
@@ -191,7 +276,7 @@
             return 1;
         }
 
-        if (isdigit(key) || key == '-')
+        if (isdigit(key) || key == '-' || key == '.')
         {
             AddCharacter(spincontrol, key);
             return 1;
@@ -209,14 +294,23 @@
 
         if (key == KEY_ENTER)
         {
-            sprintf(spincontrol->buffer, "%i", *spincontrol->value);
             spincontrol->editing = 1;
+            SetBuffer(spincontrol);
             return 1;
         }
         if (key == KEY_LEFTARROW)
         {
-            --*spincontrol->value;
+            switch (spincontrol->type)
+            {
+                case TXT_SPINCONTROL_INT:
+                    spincontrol->value->i -= spincontrol->step.i;
+                    break;
 
+                case TXT_SPINCONTROL_FLOAT:
+                    spincontrol->value->f -= spincontrol->step.f;
+                    break;
+            }
+
             EnforceLimits(spincontrol);
 
             return 1;
@@ -224,8 +318,17 @@
         
         if (key == KEY_RIGHTARROW)
         {
-            ++*spincontrol->value;
+            switch (spincontrol->type)
+            {
+                case TXT_SPINCONTROL_INT:
+                    spincontrol->value->i += spincontrol->step.i;
+                    break;
 
+                case TXT_SPINCONTROL_FLOAT:
+                    spincontrol->value->f += spincontrol->step.f;
+                    break;
+            }
+
             EnforceLimits(spincontrol);
 
             return 1;
@@ -263,7 +366,7 @@
     NULL,
 };
 
-txt_spincontrol_t *TXT_NewSpinControl(int *value, int min, int max)
+static txt_spincontrol_t *TXT_BaseSpinControl(void)
 {
     txt_spincontrol_t *spincontrol;
 
@@ -270,10 +373,7 @@
     spincontrol = malloc(sizeof(txt_spincontrol_t));
 
     TXT_InitWidget(spincontrol, &txt_spincontrol_class);
-    spincontrol->value = value;
-    spincontrol->min = min;
-    spincontrol->max = max;
-    spincontrol->buffer = malloc(15);
+    spincontrol->buffer = malloc(25);
     strcpy(spincontrol->buffer, "");
     spincontrol->editing = 0;
 
@@ -280,4 +380,31 @@
     return spincontrol;
 }
 
+txt_spincontrol_t *TXT_NewSpinControl(int *value, int min, int max)
+{
+    txt_spincontrol_t *spincontrol;
+
+    spincontrol = TXT_BaseSpinControl();
+    spincontrol->type = TXT_SPINCONTROL_INT;
+    spincontrol->value = (void *) value;
+    spincontrol->min.i = min;
+    spincontrol->max.i = max;
+    spincontrol->step.i = 1;
+
+    return spincontrol;
+}
+
+txt_spincontrol_t *TXT_NewFloatSpinControl(float *value, float min, float max)
+{
+    txt_spincontrol_t *spincontrol;
+
+    spincontrol = TXT_BaseSpinControl();
+    spincontrol->type = TXT_SPINCONTROL_FLOAT;
+    spincontrol->value = (void *) value;
+    spincontrol->min.f = min;
+    spincontrol->max.f = max;
+    spincontrol->step.f = 0.1;
+
+    return spincontrol;
+}
 
--- a/textscreen/txt_spinctrl.h
+++ b/textscreen/txt_spinctrl.h
@@ -23,6 +23,11 @@
 #define TXT_SPINCONTROL_H
 
 typedef struct txt_spincontrol_s txt_spincontrol_t;
+typedef enum
+{
+    TXT_SPINCONTROL_INT,
+    TXT_SPINCONTROL_FLOAT,
+} txt_spincontrol_type_t;
 
 #include "txt_widget.h"
 
@@ -29,13 +34,14 @@
 struct txt_spincontrol_s
 {
     txt_widget_t widget;
-    int min, max;
-    int *value;
+    txt_spincontrol_type_t type;
+    union { float f; int i; } min, max, *value, step; 
     int editing;
     char *buffer;
 };
 
 txt_spincontrol_t *TXT_NewSpinControl(int *value, int min, int max);
+txt_spincontrol_t *TXT_NewFloatSpinControl(float *value, float min, float max);
 
 #endif /* #ifndef TXT_SPINCONTROL_H */