1 /********************************************************************\
2  * cellblock.c -- group of cells that act as cursor within a table  *
3  *                                                                  *
4  * This program is free software; you can redistribute it and/or    *
5  * modify it under the terms of the GNU General Public License as   *
6  * published by the Free Software Foundation; either version 2 of   *
7  * the License, or (at your option) any later version.              *
8  *                                                                  *
9  * This program is distributed in the hope that it will be useful,  *
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
12  * GNU General Public License for more details.                     *
13  *                                                                  *
14  * You should have received a copy of the GNU General Public License*
15  * along with this program; if not, contact:                        *
16  *                                                                  *
17  * Free Software Foundation           Voice:  +1-617-542-5942       *
18  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
19  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
20  *                                                                  *
21 \********************************************************************/
22 
23 /*
24  * FILE:
25  * cellblock.c
26  *
27  * FUNCTION:
28  * implements a rectangular array of cells. See the header file for
29  * additional documentation.
30  *
31  * HISTORY:
32  * Copyright (c) 1998 Linas Vepstas
33  * Copyright (c) 2000-2001 Dave Peticolas <dave@krondo.com>
34  */
35 
36 #include <config.h>
37 
38 #include "cellblock.h"
39 
40 static void gnc_cellblock_init (CellBlock *cellblock, int rows, int cols);
41 
42 
43 CellBlock *
gnc_cellblock_new(int rows,int cols,const char * cursor_name)44 gnc_cellblock_new (int rows, int cols, const char *cursor_name)
45 {
46     CellBlock *cellblock;
47 
48     g_return_val_if_fail (rows > 0, NULL);
49     g_return_val_if_fail (cols > 0, NULL);
50     g_return_val_if_fail (cursor_name != NULL, NULL);
51 
52     cellblock = g_new0 (CellBlock, 1);
53 
54     gnc_cellblock_init (cellblock, rows, cols);
55 
56     cellblock->cursor_name = g_strdup (cursor_name);
57 
58     return cellblock;
59 }
60 
61 static void
gnc_cellblock_init(CellBlock * cellblock,int rows,int cols)62 gnc_cellblock_init (CellBlock *cellblock, int rows, int cols)
63 {
64     /* record new size */
65     cellblock->num_rows = rows;
66     cellblock->num_cols = cols;
67 
68     cellblock->start_col = cols;
69     cellblock->stop_col  = -1;
70 
71     /* malloc new cell table */
72     cellblock->cells = g_ptr_array_new ();
73 
74     g_ptr_array_set_size (cellblock->cells, rows * cols);
75 }
76 
77 void
gnc_cellblock_destroy(CellBlock * cellblock)78 gnc_cellblock_destroy (CellBlock *cellblock)
79 {
80     if (!cellblock) return;
81 
82     g_ptr_array_free (cellblock->cells, FALSE);
83     cellblock->cells = NULL;
84 
85     g_free (cellblock->cursor_name);
86     cellblock->cursor_name = NULL;
87 
88     g_free (cellblock);
89 }
90 
91 void
gnc_cellblock_set_cell(CellBlock * cellblock,int row,int col,BasicCell * cell)92 gnc_cellblock_set_cell (CellBlock *cellblock,
93                         int row, int col,
94                         BasicCell *cell)
95 {
96     if (cellblock == NULL)
97         return;
98 
99     if (row < 0 || row >= cellblock->num_rows)
100         return;
101 
102     if (col < 0 || col >= cellblock->num_cols)
103         return;
104 
105     cellblock->cells->pdata[(row * cellblock->num_cols) + col] = cell;
106 }
107 
108 BasicCell *
gnc_cellblock_get_cell(CellBlock * cellblock,int row,int col)109 gnc_cellblock_get_cell (CellBlock *cellblock, int row, int col)
110 {
111     if (cellblock == NULL)
112         return NULL;
113 
114     if (row < 0 || row >= cellblock->num_rows)
115         return NULL;
116 
117     if (col < 0 || col >= cellblock->num_cols)
118         return NULL;
119 
120     return cellblock->cells->pdata[(row * cellblock->num_cols) + col];
121 }
122 
123 BasicCell *
gnc_cellblock_get_cell_by_name(CellBlock * cellblock,const char * cell_name,int * row,int * col)124 gnc_cellblock_get_cell_by_name(CellBlock *cellblock,
125                                const char *cell_name,
126                                int *row, int *col)
127 {
128     int r, c, num_rows, num_cols;
129 
130     if (cellblock == NULL)
131         return NULL;
132 
133     if (cell_name == NULL)
134         return NULL;
135 
136     num_rows = cellblock->num_rows;
137     num_cols = cellblock->num_cols;
138     for (r = 0; r < num_rows; r++)
139         for (c = 0; c < num_cols; c++)
140         {
141             BasicCell *cell = cellblock->cells->pdata[(r * num_cols) + c];
142             if (!cell) continue;
143             if (gnc_cell_name_equal(cell->cell_name, cell_name))
144             {
145                 if (row)
146                     *row = r;
147                 if (col)
148                     *col = c;
149                 return cell;
150             }
151         }
152 
153     return NULL;
154 }
155 
156 int
gnc_cellblock_changed(CellBlock * cursor,gboolean include_conditional)157 gnc_cellblock_changed (CellBlock *cursor, gboolean include_conditional)
158 {
159     int changed = 0;
160     int r, c;
161 
162     if (!cursor)
163         return FALSE;
164 
165     for (r = 0; r < cursor->num_rows; r++)
166         for (c = 0; c < cursor->num_cols; c++)
167         {
168             BasicCell *cell;
169 
170             cell = gnc_cellblock_get_cell (cursor, r, c);
171             if (cell == NULL)
172                 continue;
173 
174             if (gnc_basic_cell_get_changed (cell))
175             {
176                 changed++;
177                 continue;
178             }
179 
180             if (include_conditional &&
181                     gnc_basic_cell_get_conditionally_changed (cell))
182                 changed++;
183         }
184 
185     return changed;
186 }
187 
188 void
gnc_cellblock_clear_changes(CellBlock * cursor)189 gnc_cellblock_clear_changes (CellBlock *cursor)
190 {
191     int r, c;
192 
193     if (!cursor)
194         return;
195 
196     for (r = 0; r < cursor->num_rows; r++)
197         for (c = 0; c < cursor->num_cols; c++)
198         {
199             BasicCell *cell;
200 
201             cell = gnc_cellblock_get_cell (cursor, r, c);
202             if (cell == NULL)
203                 continue;
204 
205             gnc_basic_cell_set_changed (cell, FALSE);
206             gnc_basic_cell_set_conditionally_changed (cell, FALSE);
207         }
208 }
209