]> git.sur5r.net Git - i3/i3/blobdiff - src/table.c
Put documentation for each function in the header files, doxygen-compatible
[i3/i3] / src / table.c
index 91aabbac554c4120cc8f61395067990d0aae45ed..222ebdcca089c1dc13f43dff288d2475c5d6f393 100644 (file)
@@ -72,6 +72,27 @@ void expand_table_rows(Workspace *workspace) {
         }
 }
 
+/*
+ * Adds one row at the head of the table
+ *
+ */
+void expand_table_rows_at_head(Workspace *workspace) {
+        workspace->rows++;
+
+        for (int cols = 0; cols < workspace->cols; cols++)
+                workspace->table[cols] = realloc(workspace->table[cols], sizeof(Container*) * workspace->rows);
+
+        /* Move the other rows */
+        for (int cols = 0; cols < workspace->cols; cols++)
+                for (int rows = workspace->rows - 1; rows > 0; rows--) {
+                        LOG("Moving row %d to %d\n", rows-1, rows);
+                        workspace->table[cols][rows] = workspace->table[cols][rows-1];
+                        workspace->table[cols][rows]->row = rows;
+                }
+        for (int cols = 0; cols < workspace->cols; cols++)
+                new_container(workspace, &(workspace->table[cols][0]), cols, 0);
+}
+
 /*
  * Add one column to the table
  *
@@ -85,12 +106,38 @@ void expand_table_cols(Workspace *workspace) {
                 new_container(workspace, &(workspace->table[workspace->cols-1][c]), workspace->cols-1, c);
 }
 
-static void shrink_table_cols(Workspace *workspace) {
-        workspace->cols--;
+/*
+ * Inserts one column at the table’s head
+ *
+ */
+void expand_table_cols_at_head(Workspace *workspace) {
+        workspace->cols++;
+
+        workspace->table = realloc(workspace->table, sizeof(Container**) * workspace->cols);
+        workspace->table[workspace->cols-1] = calloc(sizeof(Container*) * workspace->rows, 1);
 
-        /* Free the containers */
+        /* Move the other columns */
         for (int rows = 0; rows < workspace->rows; rows++)
-                free(workspace->table[workspace->cols][rows]);
+                for (int cols = workspace->cols - 1; cols > 0; cols--) {
+                        LOG("Moving col %d to %d\n", cols-1, cols);
+                        workspace->table[cols][rows] = workspace->table[cols-1][rows];
+                        workspace->table[cols][rows]->col = cols;
+                }
+
+        for (int rows = 0; rows < workspace->rows; rows++)
+                new_container(workspace, &(workspace->table[0][rows]), 0, rows);
+}
+
+/*
+ * Shrinks the table by one column.
+ *
+ * The containers themselves are freed in move_columns_from() or move_rows_from(). Therefore, this
+ * function may only be called from move_*() or after making sure that the containers are freed
+ * properly.
+ *
+ */
+static void shrink_table_cols(Workspace *workspace) {
+        workspace->cols--;
 
         /* Free the container-pointers */
         free(workspace->table[workspace->cols]);
@@ -99,12 +146,14 @@ static void shrink_table_cols(Workspace *workspace) {
         workspace->table = realloc(workspace->table, sizeof(Container**) * workspace->cols);
 }
 
+/*
+ * See shrink_table_cols()
+ *
+ */
 static void shrink_table_rows(Workspace *workspace) {
         workspace->rows--;
-        for (int cols = 0; cols < workspace->cols; cols++) {
-                free(workspace->table[cols][workspace->rows]);
+        for (int cols = 0; cols < workspace->cols; cols++)
                 workspace->table[cols] = realloc(workspace->table[cols], sizeof(Container*) * workspace->rows);
-        }
 }
 
 
@@ -117,18 +166,21 @@ bool cell_exists(int col, int row) {
                (row >= 0 && row < c_ws->rows);
 }
 
-static void move_columns_from(xcb_connection_t *conn, Workspace *workspace, int cols) {
-        LOG("firstly freeing \n");
+static void free_container(xcb_connection_t *conn, Workspace *workspace, int col, int row) {
+        Container *old_container = workspace->table[col][row];
 
-        /* Clean up the column to be freed */
-        for (int rows = 0; rows < workspace->rows; rows++) {
-                Container *old_container = workspace->table[cols-1][rows];
+        if (old_container->mode == MODE_STACK)
+                leave_stack_mode(conn, old_container);
 
-                if (old_container->mode == MODE_STACK)
-                        leave_stack_mode(conn, old_container);
+        free(old_container);
+}
 
-                free(old_container);
-        }
+static void move_columns_from(xcb_connection_t *conn, Workspace *workspace, int cols) {
+        LOG("firstly freeing \n");
+
+        /* Free the columns which are cleaned up */
+        for (int rows = 0; rows < workspace->rows; rows++)
+                free_container(conn, workspace, cols-1, rows);
 
         for (; cols < workspace->cols; cols++)
                 for (int rows = 0; rows < workspace->rows; rows++) {
@@ -144,14 +196,9 @@ static void move_columns_from(xcb_connection_t *conn, Workspace *workspace, int
 }
 
 static void move_rows_from(xcb_connection_t *conn, Workspace *workspace, int rows) {
-        for (int cols = 0; cols < workspace->cols; cols++) {
-                Container *old_container = workspace->table[cols][rows-1];
-
-                if (old_container->mode == MODE_STACK)
-                        leave_stack_mode(conn, old_container);
+        for (int cols = 0; cols < workspace->cols; cols++)
+                free_container(conn, workspace, cols, rows-1);
 
-                free(old_container);
-        }
         for (; rows < workspace->rows; rows++)
                 for (int cols = 0; cols < workspace->cols; cols++) {
                         Container *new_container = workspace->table[cols][rows];
@@ -164,20 +211,22 @@ static void move_rows_from(xcb_connection_t *conn, Workspace *workspace, int row
                 }
 }
 
+/*
+ * Prints the table’s contents in human-readable form for debugging
+ *
+ */
 void dump_table(xcb_connection_t *conn, Workspace *workspace) {
         LOG("dump_table()\n");
-        for (int cols = 0; cols < workspace->cols; cols++) {
-                for (int rows = 0; rows < workspace->rows; rows++) {
-                        Container *con = workspace->table[cols][rows];
-                        LOG("----\n");
-                        LOG("at col=%d, row=%d\n", cols, rows);
-                        LOG("currently_focused = %p\n", con->currently_focused);
-                        Client *loop;
-                        CIRCLEQ_FOREACH(loop, &(con->clients), clients) {
-                                LOG("got client %08x / %s\n", loop->child, loop->name);
-                        }
-                        LOG("----\n");
+        FOR_TABLE(workspace) {
+                Container *con = workspace->table[cols][rows];
+                LOG("----\n");
+                LOG("at col=%d, row=%d\n", cols, rows);
+                LOG("currently_focused = %p\n", con->currently_focused);
+                Client *loop;
+                CIRCLEQ_FOREACH(loop, &(con->clients), clients) {
+                        LOG("got client %08x / %s\n", loop->child, loop->name);
                 }
+                LOG("----\n");
         }
         LOG("done\n");
 }
@@ -201,6 +250,10 @@ void cleanup_table(xcb_connection_t *conn, Workspace *workspace) {
                         LOG("Removing completely empty column %d\n", cols);
                         if (cols < (workspace->cols - 1))
                                 move_columns_from(conn, workspace, cols+1);
+                        else {
+                                for (int rows = 0; rows < workspace->rows; rows++)
+                                        free_container(conn, workspace, cols, rows);
+                        }
                         shrink_table_cols(workspace);
 
                         if (workspace->current_col >= workspace->cols)
@@ -208,9 +261,10 @@ void cleanup_table(xcb_connection_t *conn, Workspace *workspace) {
                 } else cols++;
         }
 
-        /* Check for empty rows if we got more than one row*/
+        /* Check for empty rows if we got more than one row */
         for (int rows = 0; (workspace->rows > 1) && (rows < workspace->rows);) {
                 bool completely_empty = true;
+                LOG("Checking row %d\n", rows);
                 for (int cols = 0; cols < workspace->cols; cols++)
                         if (workspace->table[cols][rows]->currently_focused != NULL) {
                                 completely_empty = false;
@@ -220,6 +274,10 @@ void cleanup_table(xcb_connection_t *conn, Workspace *workspace) {
                         LOG("Removing completely empty row %d\n", rows);
                         if (rows < (workspace->rows - 1))
                                 move_rows_from(conn, workspace, rows+1);
+                        else {
+                                for (int cols = 0; cols < workspace->cols; cols++)
+                                        free_container(conn, workspace, cols, rows);
+                        }
                         shrink_table_rows(workspace);
 
                         if (workspace->current_row >= workspace->rows)
@@ -235,7 +293,7 @@ void cleanup_table(xcb_connection_t *conn, Workspace *workspace) {
                 current_row = c_ws->rows-1;
 
         if (CUR_CELL->currently_focused != NULL)
-                set_focus(conn, CUR_CELL->currently_focused);
+                set_focus(conn, CUR_CELL->currently_focused, true);
 }
 
 /*
@@ -245,22 +303,21 @@ void cleanup_table(xcb_connection_t *conn, Workspace *workspace) {
 void fix_colrowspan(xcb_connection_t *conn, Workspace *workspace) {
         LOG("Fixing col/rowspan\n");
 
-        for (int cols = 0; cols < workspace->cols; cols++)
-                for (int rows = 0; rows < workspace->rows; rows++) {
-                        Container *con = workspace->table[cols][rows];
-                        if (con->colspan > 1) {
-                                LOG("gots one with colspan %d\n", con->colspan);
-                                while (con->colspan > 1 &&
-                                       workspace->table[cols + (con->colspan - 1)][rows]->currently_focused != NULL)
-                                        con->colspan--;
-                                LOG("fixed it to %d\n", con->colspan);
-                        }
-                        if (con->rowspan > 1) {
-                                LOG("gots one with rowspan %d\n", con->rowspan);
-                                while (con->rowspan > 1 &&
-                                       workspace->table[cols][rows + (con->rowspan - 1)]->currently_focused != NULL)
-                                        con->rowspan--;
-                                LOG("fixed it to %d\n", con->rowspan);
-                        }
+        FOR_TABLE(workspace) {
+                Container *con = workspace->table[cols][rows];
+                if (con->colspan > 1) {
+                        LOG("gots one with colspan %d\n", con->colspan);
+                        while (con->colspan > 1 &&
+                               workspace->table[cols + (con->colspan - 1)][rows]->currently_focused != NULL)
+                                con->colspan--;
+                        LOG("fixed it to %d\n", con->colspan);
+                }
+                if (con->rowspan > 1) {
+                        LOG("gots one with rowspan %d\n", con->rowspan);
+                        while (con->rowspan > 1 &&
+                               workspace->table[cols][rows + (con->rowspan - 1)]->currently_focused != NULL)
+                                con->rowspan--;
+                        LOG("fixed it to %d\n", con->rowspan);
                 }
+        }
 }