1 /*
2
3 copyright (c) 2003-2013 uim Project https://github.com/uim/uim
4
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10
11 1. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
16 3. Neither the name of authors nor the names of its contributors
17 may be used to endorse or promote products derived from this software
18 without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
21 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
24 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 SUCH DAMAGE.
31
32 */
33
34 #include <config.h>
35
36 #include "uim-cand-win-tbl-gtk.h"
37 #include <string.h>
38 #include <stdlib.h>
39 #include <uim/uim.h>
40 #include <uim/uim-scm.h>
41
42 #define DEFAULT_MIN_WINDOW_WIDTH 80
43
44 enum {
45 TERMINATOR = -1,
46 COLUMN_HEADING,
47 COLUMN_CANDIDATE,
48 COLUMN_ANNOTATION,
49 LISTSTORE_NR_COLUMNS
50 };
51
52 #define TABLE_NR_COLUMNS 13
53 #define TABLE_NR_ROWS 8
54 #define TABLE_NR_CELLS (TABLE_NR_COLUMNS * TABLE_NR_ROWS)
55 #define CELLINDEX(row,col) ((row) * TABLE_NR_COLUMNS + (col))
56 /* 106 keyboard */
57 static gchar default_tbl_cell2label[TABLE_NR_CELLS] = {
58 '1','2','3','4','5', '6','7','8','9','0', '-','^','\\',
59 'q','w','e','r','t', 'y','u','i','o','p', '@','[','\0',
60 'a','s','d','f','g', 'h','j','k','l',';', ':',']','\0',
61 'z','x','c','v','b', 'n','m',',','.','/', '\0','\0',' ',
62 '!','"','#','$','%', '&','\'','(',')','\0', '=','~','|',
63 'Q','W','E','R','T', 'Y','U','I','O','P', '`','{','\0',
64 'A','S','D','F','G', 'H','J','K','L','+', '*','}','\0',
65 'Z','X','C','V','B', 'N','M','<','>','?', '_','\0','\0',
66 };
67 /* table consists of four blocks
68 * blockLR blockA
69 * blockLRS blockAS
70 */
71 #define BLOCK_A_ROW_START 0
72 #define BLOCK_A_ROW_END 4
73 #define BLOCK_A_COLUMN_START 10
74 #define BLOCK_A_COLUMN_END TABLE_NR_COLUMNS
75 #define BLOCK_LRS_ROW_START BLOCK_A_ROW_END
76 #define BLOCK_LRS_ROW_END TABLE_NR_ROWS
77 #define BLOCK_LRS_COLUMN_START 0
78 #define BLOCK_LRS_COLUMN_END BLOCK_A_COLUMN_START
79 #define BLOCK_AS_ROW_START BLOCK_LRS_ROW_START
80 #define BLOCK_AS_ROW_END BLOCK_LRS_ROW_END
81 #define BLOCK_AS_COLUMN_START BLOCK_LRS_COLUMN_END
82 #define BLOCK_AS_COLUMN_END TABLE_NR_COLUMNS
83 #define BLOCK_LR_NR_CELLS (BLOCK_A_ROW_END * BLOCK_A_COLUMN_START)
84 #define BLOCK_LRS_NR_CELLS ((BLOCK_LRS_ROW_END - BLOCK_LRS_ROW_START) * (BLOCK_LRS_COLUMN_END - BLOCK_LRS_COLUMN_START))
85
86 #define BLOCK_SPACING 20
87 #define HOMEPOSITION_SPACING 2
88 #define SPACING_LEFT_BLOCK_COLUMN 4
89 #define SPACING_RIGHT_BLOCK_COLUMN (BLOCK_A_COLUMN_START - 1)
90 #define SPACING_UP_BLOCK_ROW (BLOCK_A_ROW_END - 1)
91 #define SPACING_LEFTHAND_FAR_COLUMN 3
92 #define SPACING_RIGHTHAND_FAR_COLUMN 5
93 #define SPACING_UPPER_FAR_ROW 0
94 #define SPACING_SHIFT_UPPER_FAR_ROW 4
95
96 struct index_button {
97 gint cand_index_in_page;
98 GtkButton *button;
99 };
100
101 static void uim_cand_win_tbl_gtk_init (UIMCandWinTblGtk *cwin);
102 static void uim_cand_win_tbl_gtk_class_init (UIMCandWinGtkClass *klass);
103 static void uim_cand_win_tbl_gtk_dispose (GObject *obj);
104 static gchar *init_tbl_cell2label(void);
105 static void button_clicked(GtkButton *button, gpointer data);
106 static void clear_button(struct index_button *idxbutton,
107 const gchar *tbl_cell2label, gint cell_index);
108 static void show_table(GtkTable *view, GPtrArray *buttons);
109 static GtkButton *get_button(GPtrArray *buttons, gint idx);
110
111
112 static GType cand_win_tbl_type = 0;
113 static GTypeInfo const object_info = {
114 sizeof (UIMCandWinTblGtkClass),
115 (GBaseInitFunc) NULL,
116 (GBaseFinalizeFunc) NULL,
117 (GClassInitFunc) uim_cand_win_tbl_gtk_class_init,
118 (GClassFinalizeFunc) NULL,
119 NULL, /* class_data */
120 sizeof (UIMCandWinTblGtk),
121 0, /* n_preallocs */
122 (GInstanceInitFunc) uim_cand_win_tbl_gtk_init,
123 };
124
125 static GtkWindowClass *parent_class = NULL;
126
127 GType
uim_cand_win_tbl_gtk_get_type(void)128 uim_cand_win_tbl_gtk_get_type(void)
129 {
130 if (!cand_win_tbl_type)
131 cand_win_tbl_type = g_type_register_static(UIM_TYPE_CAND_WIN_GTK, "UIMCandWinTblGtk",
132 &object_info, (GTypeFlags)0);
133 return cand_win_tbl_type;
134 }
135
136 GType
uim_cand_win_tbl_gtk_register_type(GTypeModule * module)137 uim_cand_win_tbl_gtk_register_type(GTypeModule *module)
138 {
139 if (!cand_win_tbl_type)
140 cand_win_tbl_type = g_type_module_register_type(module,
141 UIM_TYPE_CAND_WIN_GTK,
142 "UIMCandWinTblGtk",
143 &object_info, 0);
144 return cand_win_tbl_type;
145 }
146
147 static void
uim_cand_win_tbl_gtk_class_init(UIMCandWinGtkClass * klass)148 uim_cand_win_tbl_gtk_class_init (UIMCandWinGtkClass *klass)
149 {
150 GObjectClass *object_class = (GObjectClass *) klass;
151
152 parent_class = g_type_class_peek_parent (klass);
153 object_class->dispose = uim_cand_win_tbl_gtk_dispose;
154
155 klass->set_index = (void (*)(UIMCandWinGtk *, gint))uim_cand_win_tbl_gtk_set_index;
156 klass->set_page = (void (*)(UIMCandWinGtk *, gint))uim_cand_win_tbl_gtk_set_page;
157 }
158
159 static void
uim_cand_win_tbl_gtk_init(UIMCandWinTblGtk * ctblwin)160 uim_cand_win_tbl_gtk_init (UIMCandWinTblGtk *ctblwin)
161 {
162 gint row, col;
163 GtkWidget *viewport;
164 UIMCandWinGtk *cwin;
165 cwin = UIM_CAND_WIN_GTK(ctblwin);
166
167 ctblwin->buttons = g_ptr_array_new();
168 ctblwin->tbl_cell2label = init_tbl_cell2label();
169
170 cwin->view = gtk_table_new(TABLE_NR_ROWS, TABLE_NR_COLUMNS, FALSE);
171 viewport = gtk_viewport_new(NULL, NULL);
172 gtk_container_add(GTK_CONTAINER(viewport), cwin->view);
173 gtk_container_add(GTK_CONTAINER(cwin->scrolled_window), viewport);
174 gtk_container_set_resize_mode(GTK_CONTAINER(viewport), GTK_RESIZE_PARENT);
175 for (row = 0; row < TABLE_NR_ROWS; row++) {
176 for (col = 0; col < TABLE_NR_COLUMNS; col++) {
177 GtkWidget *button;
178 struct index_button *idxbutton;
179 button = gtk_button_new_with_label(" ");
180 g_signal_connect(button, "clicked", G_CALLBACK(button_clicked), ctblwin);
181 gtk_table_attach_defaults(GTK_TABLE(cwin->view), button,
182 col, col + 1, row, row + 1);
183 idxbutton = g_malloc(sizeof(struct index_button));
184 if (idxbutton) {
185 idxbutton->button = GTK_BUTTON(button);
186 clear_button(idxbutton, ctblwin->tbl_cell2label, CELLINDEX(row, col));
187 }
188 g_ptr_array_add(ctblwin->buttons, idxbutton);
189 }
190 }
191 gtk_table_set_col_spacing(GTK_TABLE(cwin->view), SPACING_LEFT_BLOCK_COLUMN,
192 BLOCK_SPACING);
193 gtk_table_set_col_spacing(GTK_TABLE(cwin->view), SPACING_RIGHT_BLOCK_COLUMN,
194 BLOCK_SPACING);
195 gtk_table_set_row_spacing(GTK_TABLE(cwin->view), SPACING_UP_BLOCK_ROW,
196 BLOCK_SPACING);
197 gtk_table_set_col_spacing(GTK_TABLE(cwin->view), SPACING_LEFTHAND_FAR_COLUMN,
198 HOMEPOSITION_SPACING);
199 gtk_table_set_col_spacing(GTK_TABLE(cwin->view), SPACING_RIGHTHAND_FAR_COLUMN,
200 HOMEPOSITION_SPACING);
201 gtk_table_set_row_spacing(GTK_TABLE(cwin->view), SPACING_UPPER_FAR_ROW,
202 HOMEPOSITION_SPACING);
203 gtk_table_set_row_spacing(GTK_TABLE(cwin->view), SPACING_SHIFT_UPPER_FAR_ROW,
204 HOMEPOSITION_SPACING);
205
206 gtk_widget_show_all(cwin->view);
207 gtk_widget_show(viewport);
208
209 gtk_widget_set_size_request(cwin->num_label, DEFAULT_MIN_WINDOW_WIDTH, -1);
210 gtk_window_set_default_size(GTK_WINDOW(cwin), DEFAULT_MIN_WINDOW_WIDTH, -1);
211 gtk_window_set_resizable(GTK_WINDOW(cwin), FALSE);
212 }
213
214 static gchar *
init_tbl_cell2label(void)215 init_tbl_cell2label(void)
216 {
217 gchar *table;
218 uim_lisp list;
219 size_t len = 0;
220 uim_lisp *ary0, *ary;
221 guint i;
222
223 list = uim_scm_symbol_value("uim-candwin-prog-layout");
224 if (list == NULL || !uim_scm_listp(list)) {
225 return default_tbl_cell2label;
226 }
227 ary0 = ary = (uim_lisp *)uim_scm_list2array(list, &len, NULL);
228 if (ary == NULL || len <= 0) {
229 free(ary0);
230 return default_tbl_cell2label;
231 }
232 table = (gchar *)g_malloc0(TABLE_NR_CELLS);
233 if (table == NULL) {
234 free(ary0);
235 return default_tbl_cell2label;
236 }
237 for (i = 0; i < len && i < TABLE_NR_CELLS; i++, ary++) {
238 char *str;
239 if (!uim_scm_strp(*ary)) {
240 /* XXX: output notify message? */
241 g_free(table);
242 free(ary0);
243 return default_tbl_cell2label;
244 }
245 str = uim_scm_c_str(*ary);
246 if (str) {
247 /* XXX: only use first char */
248 table[i] = *str;
249 free(str);
250 }
251 }
252 free(ary0);
253 return table;
254 }
255
256 static void
button_clicked(GtkButton * button,gpointer data)257 button_clicked(GtkButton *button, gpointer data)
258 {
259 UIMCandWinTblGtk *ctblwin = data;
260 UIMCandWinGtk *cwin = UIM_CAND_WIN_GTK(ctblwin);
261 gint i;
262 gint idx = -1;
263
264 for (i = 0; i < TABLE_NR_CELLS; i++) {
265 GtkButton *p;
266 struct index_button *idxbutton;
267 idxbutton = g_ptr_array_index(ctblwin->buttons, i);
268 if (!idxbutton) {
269 continue;
270 }
271 p = idxbutton->button;
272 if (p == button) {
273 idx = idxbutton->cand_index_in_page;
274 break;
275 }
276 }
277 if (idx >= 0 && cwin->display_limit) {
278 if (idx >= (gint)cwin->display_limit) {
279 idx %= cwin->display_limit;
280 }
281 cwin->candidate_index = cwin->page_index * cwin->display_limit + idx;
282 } else {
283 cwin->candidate_index = idx;
284 }
285 if (cwin->candidate_index >= (gint)cwin->nr_candidates) {
286 cwin->candidate_index = -1;
287 }
288 g_signal_emit_by_name(G_OBJECT(cwin), "index-changed");
289 }
290
291 static void
uim_cand_win_tbl_gtk_dispose(GObject * obj)292 uim_cand_win_tbl_gtk_dispose (GObject *obj)
293 {
294 UIMCandWinTblGtk *ctblwin;
295
296 g_return_if_fail(UIM_IS_CAND_WIN_TBL_GTK(obj));
297
298 ctblwin = UIM_CAND_WIN_TBL_GTK(obj);
299
300 if (ctblwin->tbl_cell2label != default_tbl_cell2label) {
301 g_free(ctblwin->tbl_cell2label);
302 ctblwin->tbl_cell2label = NULL;
303 }
304 if (ctblwin->buttons) {
305 guint i;
306 for (i = 0; i < ctblwin->buttons->len; i++) {
307 g_free(ctblwin->buttons->pdata[i]);
308 /* GtkButton is destroyed by container */
309 }
310 g_ptr_array_free(ctblwin->buttons, TRUE);
311 ctblwin->buttons = NULL;
312 }
313
314 if (G_OBJECT_CLASS (parent_class)->dispose)
315 G_OBJECT_CLASS (parent_class)->dispose(obj);
316 }
317
318 UIMCandWinTblGtk *
uim_cand_win_tbl_gtk_new(void)319 uim_cand_win_tbl_gtk_new (void)
320 {
321 GObject *obj = g_object_new(UIM_TYPE_CAND_WIN_TBL_GTK,
322 "type", GTK_WINDOW_POPUP,
323 NULL);
324 return UIM_CAND_WIN_TBL_GTK(obj);
325 }
326
327 static GtkButton*
assign_cellbutton(GPtrArray * buttons,const gchar * tbl_cell2label,const gchar labelchar,gint cand_index,gint display_limit,gboolean * has_label)328 assign_cellbutton(GPtrArray *buttons, const gchar *tbl_cell2label,
329 const gchar labelchar, gint cand_index, gint display_limit,
330 gboolean *has_label)
331 {
332 gint i;
333 struct index_button *idxbutton;
334
335 if (labelchar != '\0') {
336 /* find button by labelchar */
337 for (i = 0; i < TABLE_NR_CELLS; i++) {
338 if (tbl_cell2label[i] == labelchar) {
339 idxbutton = g_ptr_array_index(buttons, i);
340 if (!idxbutton) {
341 continue;
342 }
343 if (idxbutton->cand_index_in_page != -1) {
344 break; /* already used */
345 }
346 idxbutton->cand_index_in_page = cand_index;
347 *has_label = TRUE;
348 return idxbutton->button;
349 }
350 }
351 }
352 /* labelchar not found || already used */
353
354 /* find free cell */
355 for (i = 0; i < TABLE_NR_CELLS; i++) {
356 if (display_limit && display_limit <= BLOCK_LR_NR_CELLS + BLOCK_LRS_NR_CELLS
357 && i % TABLE_NR_COLUMNS >= BLOCK_A_COLUMN_START) {
358 /* skip blockA which is far from home position */
359 i += TABLE_NR_COLUMNS - BLOCK_A_COLUMN_START - 1;
360 continue;
361 }
362 idxbutton = g_ptr_array_index(buttons, i);
363 if (!idxbutton) {
364 continue;
365 }
366 if (idxbutton->cand_index_in_page == -1) {
367 idxbutton->cand_index_in_page = cand_index;
368 *has_label = FALSE;
369 return idxbutton->button;
370 }
371 }
372
373 /* failed to assign button */
374 *has_label = FALSE;
375 return NULL;
376 }
377
378 void
uim_cand_win_tbl_gtk_set_index(UIMCandWinTblGtk * ctblwin,gint index)379 uim_cand_win_tbl_gtk_set_index(UIMCandWinTblGtk *ctblwin, gint index)
380 {
381 gint new_page;
382 UIMCandWinGtk *cwin;
383
384 g_return_if_fail(UIM_IS_CAND_WIN_TBL_GTK(ctblwin));
385 cwin = UIM_CAND_WIN_GTK(ctblwin);
386
387 if (index >= (gint) cwin->nr_candidates)
388 cwin->candidate_index = 0;
389 else
390 cwin->candidate_index = index;
391
392 if (cwin->candidate_index >= 0 && cwin->display_limit)
393 new_page = cwin->candidate_index / cwin->display_limit;
394 else
395 new_page = cwin->page_index;
396
397 if (cwin->page_index != new_page)
398 uim_cand_win_gtk_set_page(cwin, new_page);
399
400 uim_cand_win_gtk_update_label(cwin);
401 }
402
403 static void
clear_button(struct index_button * idxbutton,const gchar * tbl_cell2label,gint cell_index)404 clear_button(struct index_button *idxbutton, const gchar *tbl_cell2label,
405 gint cell_index)
406 {
407 GtkButton *button = NULL;
408 gboolean is_blank_cell = (tbl_cell2label[cell_index] == '\0') ? TRUE : FALSE;
409
410 idxbutton->cand_index_in_page = -1;
411 button = idxbutton->button;
412 gtk_button_set_relief(button,
413 is_blank_cell ? GTK_RELIEF_NONE : GTK_RELIEF_HALF);
414 gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE);
415 gtk_button_set_label(button, " ");
416 }
417
418 static void
clear_all_buttons(GPtrArray * buttons,const gchar * tbl_cell2label)419 clear_all_buttons(GPtrArray *buttons, const gchar *tbl_cell2label)
420 {
421 gint i;
422
423 for (i = 0; i < TABLE_NR_CELLS; i++) {
424 struct index_button *idxbutton;
425
426 idxbutton = g_ptr_array_index(buttons, i);
427 if (idxbutton && idxbutton->cand_index_in_page != -1) {
428 clear_button(idxbutton, tbl_cell2label, i);
429 }
430 }
431 }
432
433 static void
update_table_button(GtkTreeModel * model,GPtrArray * buttons,const gchar * tbl_cell2label,gint display_limit)434 update_table_button(GtkTreeModel *model, GPtrArray *buttons,
435 const gchar *tbl_cell2label, gint display_limit)
436 {
437 GtkTreeIter ti;
438 gboolean has_next;
439 gint cand_index = 0;
440
441 clear_all_buttons(buttons, tbl_cell2label);
442 has_next = gtk_tree_model_get_iter_first(model, &ti);
443 while (has_next) {
444 gchar *heading = NULL;
445 gchar *cand_str = NULL;
446 GtkButton *button = NULL;
447
448 gtk_tree_model_get(model, &ti, COLUMN_HEADING, &heading,
449 COLUMN_CANDIDATE, &cand_str, TERMINATOR);
450 if (cand_str != NULL) {
451 gboolean has_label = FALSE;
452 gchar ch = (heading == NULL) ? '\0' : heading[0];
453 button = assign_cellbutton(buttons, tbl_cell2label, ch, cand_index,
454 display_limit, &has_label);
455 if (button != NULL) {
456 gtk_button_set_relief(button,
457 has_label ? GTK_RELIEF_NORMAL : GTK_RELIEF_HALF);
458 gtk_widget_set_sensitive(GTK_WIDGET(button), TRUE);
459 gtk_button_set_label(button, cand_str);
460 }
461 }
462
463 g_free(cand_str);
464 g_free(heading);
465 cand_index++;
466 has_next = gtk_tree_model_iter_next(model, &ti);
467 }
468 }
469
470 void
uim_cand_win_tbl_gtk_set_page(UIMCandWinTblGtk * ctblwin,gint page)471 uim_cand_win_tbl_gtk_set_page(UIMCandWinTblGtk *ctblwin, gint page)
472 {
473 guint len, new_page;
474 gint new_index;
475 UIMCandWinGtk *cwin;
476
477 g_return_if_fail(UIM_IS_CAND_WIN_TBL_GTK(ctblwin));
478 cwin = UIM_CAND_WIN_GTK(ctblwin);
479 g_return_if_fail(cwin->stores);
480
481 len = cwin->stores->len;
482 g_return_if_fail(len);
483
484 if (page < 0)
485 new_page = len - 1;
486 else if (page >= (gint) len)
487 new_page = 0;
488 else
489 new_page = page;
490
491 if (cwin->stores->pdata[new_page]) {
492 update_table_button(GTK_TREE_MODEL(cwin->stores->pdata[new_page]),
493 ctblwin->buttons, ctblwin->tbl_cell2label,
494 cwin->display_limit);
495 show_table(GTK_TABLE(cwin->view), ctblwin->buttons);
496 }
497
498 cwin->page_index = new_page;
499
500 if (cwin->display_limit) {
501 if (cwin->candidate_index >= 0)
502 new_index
503 = (new_page * cwin->display_limit) + (cwin->candidate_index % cwin->display_limit);
504 else
505 new_index = -1;
506 } else {
507 new_index = cwin->candidate_index;
508 }
509
510 if (new_index >= (gint) cwin->nr_candidates)
511 new_index = cwin->nr_candidates - 1;
512
513 uim_cand_win_gtk_set_index(cwin, new_index);
514 }
515
516 static gboolean
is_empty_block(GPtrArray * buttons,gint rowstart,gint rowend,gint colstart,gint colend)517 is_empty_block(GPtrArray *buttons, gint rowstart, gint rowend, gint colstart, gint colend)
518 {
519 gint row, col;
520 for (row = rowstart; row < rowend; row++) {
521 for (col = colstart; col < colend; col++) {
522 struct index_button *idxbutton;
523 idxbutton = g_ptr_array_index(buttons, CELLINDEX(row, col));
524 if (idxbutton && idxbutton->cand_index_in_page != -1) {
525 return FALSE;
526 }
527 }
528 }
529 return TRUE;
530 }
531
532 static void
show_table(GtkTable * view,GPtrArray * buttons)533 show_table(GtkTable *view, GPtrArray *buttons)
534 {
535 /* hide empty blocks.
536 * pattern0(full table)
537 * blockLR blockA
538 * blockLRS blockAS (for shift key)
539 * pattern1(minimal blocks)
540 * blockLR
541 * pattern2(without shift blocks)
542 * blockLR blockA
543 * pattern3(without symbol blocks)
544 * blockLR
545 * blockLRS
546 */
547 gint row, col;
548 gint hide_row, hide_col;
549 gint row_spacing, col_spacing;
550 gboolean blockA, blockAS, blockLRS;
551 blockA = !is_empty_block(buttons, BLOCK_A_ROW_START, BLOCK_A_ROW_END,
552 BLOCK_A_COLUMN_START, BLOCK_A_COLUMN_END);
553 blockAS = !is_empty_block(buttons, BLOCK_AS_ROW_START, BLOCK_AS_ROW_END,
554 BLOCK_AS_COLUMN_START, BLOCK_AS_COLUMN_END);
555 blockLRS = !is_empty_block(buttons, BLOCK_LRS_ROW_START, BLOCK_LRS_ROW_END,
556 BLOCK_LRS_COLUMN_START, BLOCK_LRS_COLUMN_END);
557
558 hide_row = TABLE_NR_ROWS;
559 hide_col = TABLE_NR_COLUMNS;
560 if (blockAS) { /* pattern0(full table) */
561 hide_row = TABLE_NR_ROWS;
562 hide_col = TABLE_NR_COLUMNS;
563 } else if (blockLRS) {
564 if (blockA) { /* pattern0(full table) */
565 hide_row = TABLE_NR_ROWS;
566 hide_col = TABLE_NR_COLUMNS;
567 } else { /* pattern3(without symbol blocks) */
568 hide_row = TABLE_NR_ROWS;
569 hide_col = BLOCK_A_COLUMN_START;
570 }
571 } else if (blockA) { /* pattern2(without shift blocks) */
572 hide_row = BLOCK_A_ROW_END;
573 hide_col = TABLE_NR_COLUMNS;
574 } else { /* pattern1(minimal blocks) */
575 hide_row = BLOCK_A_ROW_END;
576 hide_col = BLOCK_A_COLUMN_START;
577 }
578
579 for (row = 0; row < TABLE_NR_ROWS; row++) {
580 for (col = 0; col < TABLE_NR_COLUMNS; col++) {
581 GtkButton *button = NULL;
582 button = get_button(buttons, CELLINDEX(row, col));
583 if (row >= hide_row || col >= hide_col) {
584 gtk_widget_hide(GTK_WIDGET(button));
585 } else {
586 gtk_widget_show(GTK_WIDGET(button));
587 }
588 }
589 }
590 if (hide_col <= BLOCK_A_COLUMN_START) {
591 col_spacing = 0;
592 } else {
593 col_spacing = BLOCK_SPACING;
594 }
595 if (hide_row <= BLOCK_LRS_ROW_START) {
596 row_spacing = 0;
597 } else {
598 row_spacing = BLOCK_SPACING;
599 }
600 gtk_table_set_col_spacing(view, SPACING_RIGHT_BLOCK_COLUMN, col_spacing);
601 gtk_table_set_row_spacing(view, SPACING_UP_BLOCK_ROW, row_spacing);
602 if (row_spacing) {
603 gtk_table_set_row_spacing(view, SPACING_SHIFT_UPPER_FAR_ROW,
604 HOMEPOSITION_SPACING);
605 } else {
606 gtk_table_set_row_spacing(view, SPACING_SHIFT_UPPER_FAR_ROW, 0);
607 }
608 /* gtk_table_resize(view, hide_row, hide_col); */
609 gtk_widget_show(GTK_WIDGET(view));
610 }
611
612 static GtkButton *
get_button(GPtrArray * buttons,gint idx)613 get_button(GPtrArray *buttons, gint idx)
614 {
615 GtkButton *button = NULL;
616 struct index_button *idxbutton;
617
618 idxbutton = g_ptr_array_index(buttons, idx);
619 if (idxbutton) {
620 button = idxbutton->button;
621 }
622 return button;
623 }
624