shithub: choc

Download patch

ref: c754eaf364e411a6903948069727be8c157e538c
parent: e365e664d767d41ef10a14c22be4964c0f6c8ea1
author: Simon Howard <fraggle@soulsphere.org>
date: Thu Jul 9 21:18:23 EDT 2015

textscreen: Add TXT_SetTableColumns() function.

It's common to want to divide a window into columns, but this has
until now only been possible by adding an inner table with multiple
columns. To simplify laying out windows, this function allows the
number of columns in a window (or any table) to be changed after it
is allocated.

--- a/textscreen/txt_table.c
+++ b/textscreen/txt_table.c
@@ -999,6 +999,66 @@
     return 0;
 }
 
+void TXT_SetTableColumns(TXT_UNCAST_ARG(table), int new_columns)
+{
+    TXT_CAST_ARG(txt_table_t, table);
+    txt_widget_t **new_widgets;
+    txt_widget_t *widget;
+    int new_num_widgets;
+    int i, j, x;
+
+    // We need as many full rows as are in the current list, plus the
+    // remainder from the last row.
+    new_num_widgets = (table->num_widgets / table->columns) * new_columns
+                    + (table->num_widgets % table->columns);
+    new_widgets = calloc(new_num_widgets, sizeof(txt_widget_t *));
+
+    // Reset and add one by one from the old table.
+    new_num_widgets = 0;
+
+    for (i = 0; i < table->num_widgets; ++i)
+    {
+        widget = table->widgets[i];
+        x = i % table->columns;
+
+        if (x < new_columns)
+        {
+            new_widgets[new_num_widgets] = widget;
+            ++new_num_widgets;
+        }
+        else if (IsActualWidget(widget))
+        {
+            TXT_DestroyWidget(widget);
+        }
+
+        // When we reach the last column of a row, we must pad it out with
+        // extra widgets to reach the next row.
+        if (x == table->columns - 1)
+        {
+            for (j = table->columns; j < new_columns; ++j)
+            {
+                // First row? We need to add struts that are used to apply
+                // the column widths.
+                if (i < table->columns)
+                {
+                    widget = &TXT_NewStrut(0, 0)->widget;
+                }
+                else
+                {
+                    widget = &txt_table_overflow_right;
+                }
+                new_widgets[new_num_widgets] = widget;
+                ++new_num_widgets;
+            }
+        }
+    }
+
+    free(table->widgets);
+    table->widgets = new_widgets;
+    table->num_widgets = new_num_widgets;
+    table->columns = new_columns;
+}
+
 // Sets the widths of columns in a table.
 
 void TXT_SetColumnWidths(TXT_UNCAST_ARG(table), ...)
--- a/textscreen/txt_table.h
+++ b/textscreen/txt_table.h
@@ -173,6 +173,22 @@
 int TXT_SelectWidget(TXT_UNCAST_ARG(table), TXT_UNCAST_ARG(widget));
 
 /**
+ * Change the number of columns in the table.
+ *
+ * Existing widgets in the table will be preserved, unless the change
+ * reduces the number of columns, in which case the widgets from the
+ * 'deleted' columns will be freed.
+ *
+ * This function can be useful for changing the number of columns in
+ * a window, which by default are tables containing a single column.
+ *
+ * @param table         The table.
+ * @param new_columns   The new number of columns.
+ */
+
+void TXT_SetTableColumns(TXT_UNCAST_ARG(table), int new_columns);
+
+/**
  * Set the widths of the columns of the table.
  *
  * The arguments to this function are variable, and correspond