source: trunk/third/gtkhtml/src/htmlengine-edit-table.c @ 19027

Revision 19027, 29.7 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r19026, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2/*  This file is part of the GtkHTML library.
3
4    Copyright (C) 2000 Helix Code, Inc.
5    Copyright (C) 2001 Ximian, Inc.
6    Authors: Radek Doulik
7
8    This library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Library General Public
10    License as published by the Free Software Foundation; either
11    version 2 of the License, or (at your option) any later version.
12
13    This library is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Library General Public License for more details.
17
18    You should have received a copy of the GNU Library General Public License
19    along with this library; see the file COPYING.LIB.  If not, write to
20    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21    Boston, MA 02111-1307, USA.
22*/
23
24#include <config.h>
25#include "htmlcluealigned.h"
26#include "htmlclueflow.h"
27#include "htmlcursor.h"
28#include "htmlimage.h"
29#include "htmlengine.h"
30#include "htmlengine-edit.h"
31#include "htmlengine-edit-cut-and-paste.h"
32#include "htmlengine-edit-table.h"
33#include "htmlengine-edit-tablecell.h"
34#include "htmltable.h"
35#include "htmltablecell.h"
36#include "htmltablepriv.h"
37#include "htmlundo.h"
38
39static void delete_table_column (HTMLEngine *e, HTMLUndoDirection dir);
40static void insert_table_column (HTMLEngine *e, gboolean after, HTMLTableCell **column_cells, HTMLUndoDirection dir);
41static void delete_table_row    (HTMLEngine *e, HTMLUndoDirection dir);
42static void insert_table_row    (HTMLEngine *e, gboolean after, HTMLTableCell **row_cells, HTMLUndoDirection dir);
43
44HTMLTable *
45html_engine_get_table (HTMLEngine *e)
46{
47        if (!e->cursor->object->parent
48            || !e->cursor->object->parent->parent
49            || !e->cursor->object->parent->parent->parent
50            || !HTML_IS_TABLE (e->cursor->object->parent->parent->parent))
51                return NULL;
52        else
53                return HTML_TABLE (e->cursor->object->parent->parent->parent);
54}
55
56HTMLTableCell *
57html_engine_new_cell (HTMLEngine *e, HTMLTable *table)
58{
59        HTMLObject    *cell;
60        HTMLObject    *text;
61        HTMLObject    *flow;
62       
63        cell  = html_table_cell_new (1, 1, table->padding);
64        flow  = html_clueflow_new (HTML_CLUEFLOW_STYLE_NORMAL, g_byte_array_new (),
65                                   HTML_LIST_TYPE_UNORDERED, 0, HTML_CLEAR_NONE);
66        text  = html_engine_new_text_empty (e);
67
68        html_clue_append (HTML_CLUE (flow), text);
69        html_clue_append (HTML_CLUE (cell), flow);
70
71        return HTML_TABLE_CELL (cell);
72}
73
74/*
75 * Table insertion
76 */
77
78/**
79 * html_engine_insert_table_1_1:
80 * @e: An html engine
81 *
82 * Inserts new table with one cell containing an empty flow with an empty text. Inserted table has 1 row and 1 column.
83 **/
84
85void
86html_engine_insert_table_1_1 (HTMLEngine *e)
87{
88        HTMLObject    *table;
89
90        table = html_table_new (0, 100, 1, 2, 1);
91
92        html_table_add_cell (HTML_TABLE (table), html_engine_new_cell (e, HTML_TABLE (table)));
93
94        html_engine_append_object (e, table, 2);
95        html_cursor_backward (e->cursor, e);
96}
97
98/**
99 * html_engine_insert_table_1_1:
100 * @e: An html engine
101 *
102 * Inserts new table with @cols columns and @rows rows. Cells contain an empty flow with an empty text.
103 **/
104
105void
106html_engine_insert_table (HTMLEngine *e, gint cols, gint rows, gint width, gint percent,
107                          gint padding, gint spacing, gint border)
108{
109        HTMLObject *table;
110        gint r, c;
111
112        g_return_if_fail (cols >= 0);
113        g_return_if_fail (rows >= 0);
114
115        table = html_table_new (width, percent, padding, spacing, border);
116
117        for (r = 0; r < rows; r ++) {
118                html_table_start_row (HTML_TABLE (table));
119                for (c = 0; c < cols; c ++)
120                        html_table_add_cell (HTML_TABLE (table), html_engine_new_cell (e, HTML_TABLE (table)));
121                html_table_end_row (HTML_TABLE (table));
122        }
123
124        html_engine_append_object (e, table, 1 + rows*cols);
125        html_cursor_backward_n (e->cursor, e, rows*cols);
126}
127
128/*
129 *  Insert Column
130 */
131
132static void
133insert_column_undo_action (HTMLEngine *e, HTMLUndoData *data, HTMLUndoDirection dir, guint position_after)
134{
135        delete_table_column (e, html_undo_direction_reverse (dir));
136}
137
138static void
139insert_column_setup_undo (HTMLEngine *e, guint position_before, HTMLUndoDirection dir)
140{
141        html_undo_add_action (e->undo,
142                              html_undo_action_new ("Insert table column", insert_column_undo_action,
143                                                    NULL, html_cursor_get_position (e->cursor),
144                                                    position_before),
145                              dir);
146}
147
148static void
149go_table_0 (HTMLEngine *e, HTMLObject *table)
150{
151        while ((e->cursor->offset || e->cursor->object != table) && e->cursor->position)
152                        html_cursor_backward (e->cursor, e);
153}
154
155static void
156go_after_col (HTMLEngine *e, HTMLObject *table, gint col)
157{
158        HTMLObject *cell;
159
160        do {
161                cell = html_object_nth_parent (e->cursor->object, 2);
162                if (cell && HTML_IS_TABLE_CELL (cell) && HTML_TABLE_CELL (cell)->col == col)
163                        break;
164        } while (html_cursor_forward (e->cursor, e));
165}
166
167static void
168go_after_row (HTMLEngine *e, HTMLObject *table, gint row)
169{
170        HTMLObject *cell;
171
172        do {
173                cell = html_object_nth_parent (e->cursor->object, 2);
174                if (cell && HTML_IS_TABLE_CELL (cell) && HTML_TABLE_CELL (cell)->row == row)
175                        break;
176        } while (html_cursor_forward (e->cursor, e));
177}
178
179static void
180insert_table_column (HTMLEngine *e, gint col, HTMLTableCell **column, HTMLUndoDirection dir)
181{
182        HTMLTable *t;
183        HTMLTableCell *cell;
184        gint c, r;
185        guint position_before;
186
187        t = HTML_TABLE (html_object_nth_parent (e->cursor->object, 3));
188        if (!t)
189                return;
190
191        html_engine_freeze (e);
192
193        position_before = e->cursor->position;
194        go_table_0 (e, HTML_OBJECT (t));
195
196        html_table_alloc_cell (t, 0, t->totalCols);
197        for (r = 0; r < t->totalRows; r ++) {
198                for (c = t->totalCols - 1; c >= col; c --) {
199                        HTMLTableCell *cell = t->cells [r][c - 1];
200
201                        if (cell && cell->col >= col) {
202                                if (cell->row == r && cell->col == c - 1)
203                                        html_table_cell_set_position (cell, r, c);
204                                t->cells [r][c] = cell;
205                                t->cells [r][c - 1] = NULL;
206                        }
207                }
208                if (!t->cells [r][col]) {
209                        guint len;
210
211                        cell = column
212                                ? HTML_TABLE_CELL (html_object_op_copy (HTML_OBJECT (column [r]), HTML_OBJECT (t),
213                                                                        e, NULL, NULL, &len))
214                                : html_engine_new_cell (e, t);
215                        html_table_set_cell (t, r, col, cell);
216                        html_table_cell_set_position (t->cells [r][col], r, col);
217                }
218        }
219
220        go_after_col (e, HTML_OBJECT (t), col);
221        insert_column_setup_undo (e, position_before, dir);
222        html_object_change_set (HTML_OBJECT (t), HTML_CHANGE_ALL_CALC);
223        html_engine_queue_draw (e, HTML_OBJECT (t));
224        html_engine_thaw (e);
225}
226
227/**
228 * html_engine_insert_table_column:
229 * @e: An HTML engine.
230 * @after: If TRUE then inserts new column after current one, defined by current cursor position.
231 *         If FALSE then inserts before current one.
232 *
233 * Inserts new column into table after/before current column.
234 **/
235
236void
237html_engine_insert_table_column (HTMLEngine *e, gboolean after)
238{
239        HTMLObject *cell;
240
241        cell = html_object_nth_parent (e->cursor->object, 2);
242        if (cell && HTML_IS_TABLE_CELL (cell))
243                insert_table_column (e, HTML_TABLE_CELL (cell)->col + (after ? 1 : 0), NULL, HTML_UNDO_UNDO);
244}
245
246/*
247 * Delete column
248 */
249
250struct _DeleteCellsUndo {
251        HTMLUndoData data;
252
253        HTMLTableCell **cells;
254        gint size;
255        gint pos;
256};
257typedef struct _DeleteCellsUndo DeleteCellsUndo;
258
259static void
260delete_cells_undo_destroy (HTMLUndoData *undo_data)
261{
262        DeleteCellsUndo *data = (DeleteCellsUndo *) undo_data;
263        gint i;
264
265        for (i = 0; i < data->size; i ++)
266                html_object_destroy (HTML_OBJECT (data->cells [i]));
267}
268
269static DeleteCellsUndo *
270delete_cells_undo_new (HTMLTableCell **cells, gint size, gint pos)
271{
272        DeleteCellsUndo *data;
273
274        data = g_new0 (DeleteCellsUndo, 1);
275
276        html_undo_data_init (HTML_UNDO_DATA (data));
277
278        data->data.destroy = delete_cells_undo_destroy;
279        data->cells        = cells;
280        data->pos          = pos;
281        data->size         = size;
282
283        return data;
284}
285
286static void
287delete_column_undo_action (HTMLEngine *e, HTMLUndoData *undo_data, HTMLUndoDirection dir, guint position_after)
288{
289        DeleteCellsUndo *data = (DeleteCellsUndo *) undo_data;
290
291        g_assert (data->size == HTML_TABLE (html_object_nth_parent (e->cursor->object, 3))->totalRows);
292        insert_table_column (e, data->pos, data->cells, html_undo_direction_reverse (dir));
293}
294
295static void
296delete_column_setup_undo (HTMLEngine *e, HTMLTableCell **column, gint size, guint position_before, gint col, HTMLUndoDirection dir)
297{
298        html_undo_add_action (e->undo,
299                              html_undo_action_new ("Delete table column", delete_column_undo_action,
300                                                    HTML_UNDO_DATA (delete_cells_undo_new (column, size, col)),
301                                                    html_cursor_get_position (e->cursor),
302                                                    position_before), dir);
303}
304
305static void
306delete_table_column (HTMLEngine *e, HTMLUndoDirection dir)
307{
308        HTMLTable *t;
309        HTMLTableCell *cell;
310        HTMLTableCell **column;
311        gint r, c, col;
312        guint position_before;
313
314        t = HTML_TABLE (html_object_nth_parent (e->cursor->object, 3));
315
316        /* this command is valid only in table and when this table has > 1 column */
317        if (!t || !HTML_IS_TABLE (HTML_OBJECT (t)) || t->totalCols < 2)
318                return;
319
320        html_engine_freeze (e);
321
322        position_before = e->cursor->position;
323        cell   = HTML_TABLE_CELL (html_object_nth_parent (e->cursor->object, 2));
324        col    = cell->col;
325        column = g_new0 (HTMLTableCell *, t->totalRows);
326
327        go_table_0 (e, HTML_OBJECT (t));
328        for (r = 0; r < t->totalRows; r ++) {
329                cell = t->cells [r][col];
330
331                /* remove & keep old one */
332                if (cell && cell->col == col) {
333                        HTML_OBJECT (cell)->parent = NULL;
334                        column [r] = cell;
335                        t->cells [r][col] = NULL;
336                }
337
338                for (c = col + 1; c < t->totalCols; c ++) {
339                        cell = t->cells [r][c];
340                        if (cell && cell->col != col) {
341                                if (cell->row == r && cell->col == c)
342                                        html_table_cell_set_position (cell, r, c - 1);
343                                t->cells [r][c - 1] = cell;
344                                t->cells [r][c]     = NULL;
345                        }
346                }
347        }
348        go_after_col (e, HTML_OBJECT (t), MIN (col, t->totalCols - 1));
349        delete_column_setup_undo (e, column, t->totalRows, position_before, col, dir);
350        t->totalCols --;
351
352        html_object_change_set (HTML_OBJECT (t), HTML_CHANGE_ALL_CALC);
353        html_engine_queue_draw (e, HTML_OBJECT (t));
354        html_engine_thaw (e);
355}
356
357/**
358 * html_engine_delete_table_column:
359 * @e: An HTML engine.
360 *
361 * Deletes current table column.
362 **/
363
364void
365html_engine_delete_table_column (HTMLEngine *e)
366{
367        delete_table_column (e, HTML_UNDO_UNDO);
368}
369
370/*
371 *  Insert Row
372 */
373
374static void
375insert_row_undo_action (HTMLEngine *e, HTMLUndoData *data, HTMLUndoDirection dir, guint position_after)
376{
377        delete_table_row (e, html_undo_direction_reverse (dir));
378}
379
380static void
381insert_row_setup_undo (HTMLEngine *e, guint position_before, HTMLUndoDirection dir)
382{
383        html_undo_add_action (e->undo,
384                              html_undo_action_new ("Insert table row", insert_row_undo_action,
385                                                    NULL,
386                                                    html_cursor_get_position (e->cursor),
387                                                    html_cursor_get_position (e->cursor)),
388                              dir);
389}
390
391static void
392insert_table_row (HTMLEngine *e, gint row, HTMLTableCell **row_cells, HTMLUndoDirection dir)
393{
394        HTMLTable *t;
395        HTMLTableCell *cell;
396        gint r, c;
397        guint position_before;
398
399        t = HTML_TABLE (html_object_nth_parent (e->cursor->object, 3));
400        if (!t)
401                return;
402
403        html_engine_freeze (e);
404        position_before = e->cursor->position;
405        go_table_0 (e, HTML_OBJECT (t));
406
407        html_table_alloc_cell (t, t->totalRows, 0);
408        for (c = 0; c < t->totalCols; c ++) {
409                for (r = t->totalRows; r > row; r --) {
410                        HTMLTableCell *cell = t->cells [r - 1][c];
411
412                        if (cell && cell->row >= row) {
413                                if (cell->row == r - 1 && cell->col == c)
414                                        html_table_cell_set_position (cell, r, c);
415                                t->cells [r][c]     = cell;
416                                t->cells [r - 1][c] = NULL;
417                        }
418                }
419                if (!t->cells [row][c]) {
420                        guint len;
421
422                        cell = row_cells
423                                ? HTML_TABLE_CELL (html_object_op_copy (HTML_OBJECT (row_cells [c]), HTML_OBJECT (t),
424                                                                        e, NULL, NULL, &len))
425                                :  html_engine_new_cell (e, t);
426                        html_table_set_cell (t, row, c, cell);
427                        html_table_cell_set_position (t->cells [row][c], row, c);
428                }
429        }
430
431        go_after_row (e, HTML_OBJECT (t), row);
432        insert_row_setup_undo (e, position_before, dir);
433        html_object_change_set (HTML_OBJECT (t), HTML_CHANGE_ALL_CALC);
434        html_engine_queue_draw (e, HTML_OBJECT (t));
435        html_engine_thaw (e);
436}
437
438/**
439 * html_engine_insert_table_row:
440 * @e: An HTML engine.
441 * @after: If TRUE then inserts new row after current one, defined by current cursor position.
442 *         If FALSE then inserts before current one.
443 *
444 * Inserts new row into table after/before current row.
445 **/
446
447void
448html_engine_insert_table_row (HTMLEngine *e, gboolean after)
449{
450        HTMLObject *cell;
451
452        cell = html_object_nth_parent (e->cursor->object, 2);
453        if (cell && HTML_IS_TABLE_CELL (cell))
454                insert_table_row (e, HTML_TABLE_CELL (cell)->row + (after ? 1 : 0), NULL, HTML_UNDO_UNDO);
455}
456
457/*
458 * Delete row
459 */
460
461static void
462delete_row_undo_action (HTMLEngine *e, HTMLUndoData *undo_data, HTMLUndoDirection dir, guint position_after)
463{
464        DeleteCellsUndo *data = (DeleteCellsUndo *) undo_data;
465
466        g_assert (data->size == HTML_TABLE (html_object_nth_parent (e->cursor->object, 3))->totalCols);
467        insert_table_row (e, data->pos, data->cells, html_undo_direction_reverse (dir));
468}
469
470static void
471delete_row_setup_undo (HTMLEngine *e, HTMLTableCell **row_cells, gint size, guint position_before,
472                       gint row, HTMLUndoDirection dir)
473{
474        html_undo_add_action (e->undo,
475                              html_undo_action_new ("Delete table row", delete_row_undo_action,
476                                                    HTML_UNDO_DATA (delete_cells_undo_new (row_cells, size, row)),
477                                                    html_cursor_get_position (e->cursor),
478                                                    position_before), dir);
479}
480
481static void
482delete_table_row (HTMLEngine *e, HTMLUndoDirection dir)
483{
484        HTMLTable *t;
485        HTMLTableCell *cell;
486        HTMLTableCell **row_cells;
487        gint r, c, row;
488        guint position_before;
489
490        t = HTML_TABLE (html_object_nth_parent (e->cursor->object, 3));
491
492        /* this command is valid only in table and when this table has > 1 row */
493        if (!t || !HTML_IS_TABLE (HTML_OBJECT (t)) || t->totalRows < 2)
494                return;
495
496        html_engine_freeze (e);
497
498        position_before = e->cursor->position;
499        cell      = HTML_TABLE_CELL (html_object_nth_parent (e->cursor->object, 2));
500        row       = cell->row;
501        row_cells = g_new0 (HTMLTableCell *, t->totalCols);
502
503        go_table_0 (e, HTML_OBJECT (t));
504        for (c = 0; c < t->totalCols; c ++) {
505                cell = t->cells [row][c];
506
507                /* remove & keep old one */
508                if (cell && cell->row == row) {
509                        HTML_OBJECT (cell)->parent = NULL;
510                        row_cells [c] = cell;
511                        t->cells [row][c] = NULL;
512                }
513
514                for (r = row + 1; r < t->totalRows; r ++) {
515                        cell = t->cells [r][c];
516                        if (cell && cell->row != row) {
517                                if (cell->row == r && cell->col == c)
518                                        html_table_cell_set_position (cell, r - 1, c);
519                                t->cells [r - 1][c] = cell;
520                                t->cells [r][c]     = NULL;
521                        }
522                }
523        }
524
525        go_after_row (e, HTML_OBJECT (t), MIN (row, t->totalCols - 1));
526        t->totalRows --;
527        delete_row_setup_undo (e, row_cells, t->totalCols, position_before, row, dir);
528        html_object_change_set (HTML_OBJECT (t), HTML_CHANGE_ALL_CALC);
529        html_engine_queue_draw (e, HTML_OBJECT (t));
530        html_engine_thaw (e);
531}
532
533/**
534 * html_engine_delete_table_row:
535 * @e: An HTML engine.
536 *
537 * Deletes current table row.
538 **/
539
540void
541html_engine_delete_table_row (HTMLEngine *e)
542{
543        delete_table_row (e, HTML_UNDO_UNDO);
544}
545
546typedef enum {
547        HTML_TABLE_BORDER,
548        HTML_TABLE_PADDING,
549        HTML_TABLE_SPACING,
550        HTML_TABLE_WIDTH,
551        HTML_TABLE_BGCOLOR,
552        HTML_TABLE_BGPIXMAP,
553        HTML_TABLE_ALIGN,
554} HTMLTableAttrType;
555
556union _HTMLTableUndoAttr {
557        gint border;
558        gint spacing;
559        gint padding;
560
561        gchar *pixmap;
562
563        struct {
564                gint width;
565                gboolean percent;
566        } width;
567
568        struct {
569                GdkColor color;
570                gboolean has_bg_color;
571        } color;
572
573        HTMLHAlignType align;
574};
575typedef union _HTMLTableUndoAttr HTMLTableUndoAttr;
576
577struct _HTMLTableSetAttrUndo {
578        HTMLUndoData data;
579
580        HTMLTableUndoAttr attr;
581        HTMLTableAttrType type;
582};
583typedef struct _HTMLTableSetAttrUndo HTMLTableSetAttrUndo;
584
585static void
586attr_destroy (HTMLUndoData *undo_data)
587{
588        HTMLTableSetAttrUndo *data = (HTMLTableSetAttrUndo *) undo_data;
589
590        switch (data->type) {
591        case HTML_TABLE_BGPIXMAP:
592                g_free (data->attr.pixmap);
593                break;
594        default:
595                ;
596        }
597}
598
599static HTMLTableSetAttrUndo *
600attr_undo_new (HTMLTableAttrType type)
601{
602        HTMLTableSetAttrUndo *undo = g_new (HTMLTableSetAttrUndo, 1);
603
604        html_undo_data_init (HTML_UNDO_DATA (undo));
605        undo->data.destroy = attr_destroy;
606        undo->type         = type;
607
608        return undo;
609}
610
611/*
612 * Border width
613 */
614
615static void table_set_border_width (HTMLEngine *e, HTMLTable *t, gint border_width, gboolean relative, HTMLUndoDirection dir);
616
617static void
618table_set_border_width_undo_action (HTMLEngine *e, HTMLUndoData *undo_data, HTMLUndoDirection dir, guint position_after)
619{
620        table_set_border_width (e, html_engine_get_table (e), ((HTMLTableSetAttrUndo *) undo_data)->attr.border, FALSE,
621                                html_undo_direction_reverse (dir));
622}
623
624static void
625table_set_border_width (HTMLEngine *e, HTMLTable *t, gint border_width, gboolean relative, HTMLUndoDirection dir)
626{
627        HTMLTableSetAttrUndo *undo;
628        gint new_border;
629
630        if (!t || !HTML_IS_TABLE (t))
631                return;
632
633        if (relative)
634                new_border = t->border + border_width;
635        else
636                new_border = border_width;
637        if (new_border < 0)
638                new_border = 0;
639        if (new_border == t->border)
640                return;
641
642        undo = attr_undo_new (HTML_TABLE_BORDER);
643        undo->attr.border = t->border;
644
645        html_engine_freeze (e);
646        t->border = new_border;
647
648        html_object_change_set (HTML_OBJECT (t), HTML_CHANGE_ALL_CALC);
649        html_engine_thaw (e);
650
651        html_undo_add_action (e->undo,
652                              html_undo_action_new ("Set table border width", table_set_border_width_undo_action,
653                                                    HTML_UNDO_DATA (undo), html_cursor_get_position (e->cursor),
654                                                    html_cursor_get_position (e->cursor)), dir);
655}
656
657void
658html_engine_table_set_border_width (HTMLEngine *e, HTMLTable *t, gint border_width, gboolean relative)
659{
660        table_set_border_width (e, t, border_width, relative, HTML_UNDO_UNDO);
661}
662
663/*
664 * bg color
665 *
666 */
667
668static void table_set_bg_color (HTMLEngine *e, HTMLTable *t, GdkColor *c, HTMLUndoDirection dir);
669
670static void
671table_set_bg_color_undo_action (HTMLEngine *e, HTMLUndoData *undo_data, HTMLUndoDirection dir, guint position_after)
672{
673        HTMLTableSetAttrUndo *data = (HTMLTableSetAttrUndo *) undo_data;
674
675        table_set_bg_color (e, html_engine_get_table (e), data->attr.color.has_bg_color
676                            ? &data->attr.color.color : NULL, html_undo_direction_reverse (dir));
677}
678
679static void
680table_set_bg_color (HTMLEngine *e, HTMLTable *t, GdkColor *c, HTMLUndoDirection dir)
681{
682        HTMLTableSetAttrUndo *undo;
683
684        undo = attr_undo_new (HTML_TABLE_BGCOLOR);
685        if (t->bgColor) {
686                undo->attr.color.color        = *t->bgColor;
687                undo->attr.color.has_bg_color = TRUE;
688        } else
689                undo->attr.color.has_bg_color = FALSE;
690        html_undo_add_action (e->undo,
691                              html_undo_action_new ("Set table background color", table_set_bg_color_undo_action,
692                                                    HTML_UNDO_DATA (undo),
693                                                    html_cursor_get_position (e->cursor),
694                                                    html_cursor_get_position (e->cursor)), dir);
695        if (c) {
696                if (!t->bgColor)
697                        t->bgColor = gdk_color_copy (c);
698                *t->bgColor = *c;
699        } else {
700                if (t->bgColor)
701                        gdk_color_free (t->bgColor);
702                t->bgColor = NULL;
703        }
704        html_engine_queue_draw (e, HTML_OBJECT (t));
705}
706
707void
708html_engine_table_set_bg_color (HTMLEngine *e, HTMLTable *t, GdkColor *c)
709{
710        table_set_bg_color (e, t, c, HTML_UNDO_UNDO);
711}
712
713/*
714 * bg pixmap
715 *
716 */
717
718void table_set_bg_pixmap (HTMLEngine *e, HTMLTable *t, gchar *url, HTMLUndoDirection dir);
719
720static void
721table_set_bg_pixmap_undo_action (HTMLEngine *e, HTMLUndoData *undo_data, HTMLUndoDirection dir, guint position_after)
722{
723        HTMLTableSetAttrUndo *data = (HTMLTableSetAttrUndo *) undo_data;
724
725        table_set_bg_pixmap (e, html_engine_get_table (e), data->attr.pixmap, html_undo_direction_reverse (dir));
726}
727
728void
729table_set_bg_pixmap (HTMLEngine *e, HTMLTable *t, gchar *url, HTMLUndoDirection dir)
730{
731        HTMLImagePointer *iptr;
732        HTMLTableSetAttrUndo *undo;
733
734        undo = attr_undo_new (HTML_TABLE_BGPIXMAP);
735        undo->attr.pixmap = t->bgPixmap ? g_strdup (t->bgPixmap->url) : NULL;
736        html_undo_add_action (e->undo,
737                              html_undo_action_new ("Set table background pixmap", table_set_bg_pixmap_undo_action,
738                                                    HTML_UNDO_DATA (undo),
739                                                    html_cursor_get_position (e->cursor),
740                                                    html_cursor_get_position (e->cursor)), dir);
741
742        iptr = t->bgPixmap;
743        t->bgPixmap = url ? html_image_factory_register (e->image_factory, NULL, url, TRUE) : NULL;
744        if (iptr)
745                html_image_factory_unregister (e->image_factory, iptr, NULL);
746        html_engine_queue_draw (e, HTML_OBJECT (t));
747}
748
749void
750html_engine_table_set_bg_pixmap (HTMLEngine *e, HTMLTable *t, gchar *url)
751{
752        table_set_bg_pixmap (e, t, url, HTML_UNDO_UNDO);
753}
754
755/*
756 * spacing
757 *
758 */
759
760static void table_set_spacing (HTMLEngine *e, HTMLTable *t, gint spacing, gboolean relative, HTMLUndoDirection dir);
761
762static void
763table_set_spacing_undo_action (HTMLEngine *e, HTMLUndoData *undo_data, HTMLUndoDirection dir, guint position_after)
764{
765        HTMLTableSetAttrUndo *data = (HTMLTableSetAttrUndo *) undo_data;
766
767        table_set_spacing (e, html_engine_get_table (e), data->attr.spacing, FALSE, html_undo_direction_reverse (dir));
768}
769
770static void
771table_set_spacing (HTMLEngine *e, HTMLTable *t, gint spacing, gboolean relative, HTMLUndoDirection dir)
772{
773        HTMLTableSetAttrUndo *undo;
774        gint new_spacing;
775
776        if (!t || !HTML_IS_TABLE (t))
777                return;
778
779        if (relative)
780                new_spacing = t->spacing + spacing;
781        else
782                new_spacing = spacing;
783        if (new_spacing < 0)
784                new_spacing = 0;
785        if (new_spacing == t->spacing)
786                return;
787
788        undo = attr_undo_new (HTML_TABLE_SPACING);
789        undo->attr.spacing = t->spacing;
790        html_undo_add_action (e->undo,
791                              html_undo_action_new ("Set table spacing", table_set_spacing_undo_action,
792                                                    HTML_UNDO_DATA (undo),
793                                                    html_cursor_get_position (e->cursor),
794                                                    html_cursor_get_position (e->cursor)), dir);
795        t->spacing = new_spacing;
796        html_object_change_set (HTML_OBJECT (t), HTML_CHANGE_ALL_CALC);
797        html_engine_schedule_update (e);
798}
799
800void
801html_engine_table_set_spacing (HTMLEngine *e, HTMLTable *t, gint spacing, gboolean relative)
802{
803        table_set_spacing (e, t, spacing, relative, HTML_UNDO_UNDO);
804}
805
806/*
807 * padding
808 *
809 */
810
811static void table_set_padding (HTMLEngine *e, HTMLTable *t, gint padding, gboolean relative, HTMLUndoDirection dir);
812
813static void
814table_set_padding_undo_action (HTMLEngine *e, HTMLUndoData *undo_data, HTMLUndoDirection dir, guint position_after)
815{
816        HTMLTableSetAttrUndo *data = (HTMLTableSetAttrUndo *) undo_data;
817
818        table_set_padding (e, html_engine_get_table (e), data->attr.padding, FALSE, html_undo_direction_reverse (dir));
819}
820
821static void
822table_set_padding (HTMLEngine *e, HTMLTable *t, gint padding, gboolean relative, HTMLUndoDirection dir)
823{
824        HTMLTableSetAttrUndo *undo;
825        gint r, c;
826        gint new_padding;
827
828        if (!t || !HTML_IS_TABLE (t))
829                return;
830
831        if (relative)
832                new_padding = t->padding + padding;
833        else
834                new_padding = padding;
835        if (new_padding < 0)
836                new_padding = 0;
837        if (new_padding == t->padding)
838                return;
839
840        undo = attr_undo_new (HTML_TABLE_PADDING);
841        undo->attr.padding = t->padding;
842        html_undo_add_action (e->undo,
843                              html_undo_action_new ("Set table padding", table_set_padding_undo_action,
844                                                    HTML_UNDO_DATA (undo),
845                                                    html_cursor_get_position (e->cursor),
846                                                    html_cursor_get_position (e->cursor)), dir);
847
848        t->padding = new_padding;
849        for (r = 0; r < t->totalRows; r ++)
850                for (c = 0; c < t->totalCols; c ++)
851                        if (t->cells [r][c]->col == c && t->cells [r][c]->row == r) {
852                                HTML_CLUEV (t->cells [r][c])->padding = new_padding;
853                                HTML_OBJECT (t->cells [r][c])->change |= HTML_CHANGE_ALL_CALC;
854                        }
855        html_object_change_set (HTML_OBJECT (t), HTML_CHANGE_ALL_CALC);
856        html_engine_schedule_update (e);
857}
858
859void
860html_engine_table_set_padding (HTMLEngine *e, HTMLTable *t, gint padding, gboolean relative)
861{
862        table_set_padding (e, t, padding, relative, HTML_UNDO_UNDO);
863}
864
865/*
866 * align
867 *
868 */
869
870static void table_set_align (HTMLEngine *e, HTMLTable *t, HTMLHAlignType align, HTMLUndoDirection dir);
871
872static void
873table_set_align_undo_action (HTMLEngine *e, HTMLUndoData *undo_data, HTMLUndoDirection dir, guint position_after)
874{
875        HTMLTableSetAttrUndo *data = (HTMLTableSetAttrUndo *) undo_data;
876
877        table_set_align (e, html_engine_get_table (e), data->attr.align, html_undo_direction_reverse (dir));
878}
879
880static void
881table_set_align (HTMLEngine *e, HTMLTable *t, HTMLHAlignType align, HTMLUndoDirection dir)
882{
883        HTMLTableSetAttrUndo *undo;
884
885        g_return_if_fail (HTML_OBJECT (t)->parent);
886
887        undo = attr_undo_new (HTML_TABLE_ALIGN);
888        undo->attr.align = HTML_CLUE (HTML_OBJECT (t)->parent)->halign;
889
890        if (align == HTML_HALIGN_NONE || align == HTML_HALIGN_CENTER) {
891                if (HTML_IS_CLUEALIGNED (HTML_OBJECT (t)->parent)) {
892                        HTMLObject *aclue = HTML_OBJECT (t)->parent;
893
894                        html_clue_remove (HTML_CLUE (aclue), HTML_OBJECT (t));
895                        html_clue_append_after (HTML_CLUE (aclue->parent), HTML_OBJECT (t), aclue);
896                        html_clue_remove (HTML_CLUE (aclue->parent), aclue);
897                        html_object_destroy (aclue);
898                }
899        } else if (align == HTML_HALIGN_LEFT || align == HTML_HALIGN_RIGHT) {
900                if (HTML_IS_CLUEFLOW (HTML_OBJECT (t)->parent)) {
901                        HTMLObject *aclue, *flow = HTML_OBJECT (t)->parent;
902
903                        html_clue_remove (HTML_CLUE (flow), HTML_OBJECT (t));
904                        aclue = html_cluealigned_new (NULL, 0, 0, flow->max_width, 100);
905                        html_clue_append (HTML_CLUE (flow), aclue);
906                        html_clue_append (HTML_CLUE (aclue), HTML_OBJECT (t));
907                }
908        } else
909                g_assert_not_reached ();
910
911        html_undo_add_action (e->undo,
912                              html_undo_action_new ("Set table align", table_set_align_undo_action,
913                                                    HTML_UNDO_DATA (undo),
914                                                    html_cursor_get_position (e->cursor),
915                                                    html_cursor_get_position (e->cursor)), dir);
916
917        HTML_CLUE (HTML_OBJECT (t)->parent)->halign = align;
918        html_object_change_set (HTML_OBJECT (t)->parent, HTML_CHANGE_ALL_CALC);
919        html_engine_schedule_update (e);
920}
921
922void
923html_engine_table_set_align (HTMLEngine *e, HTMLTable *t, HTMLHAlignType align)
924{
925        table_set_align (e, t, align, HTML_UNDO_UNDO);
926}
927
928/*
929 * width
930 *
931 */
932
933static void table_set_width (HTMLEngine *e, HTMLTable *t, gint width, gboolean percent, HTMLUndoDirection dir);
934
935static void
936table_set_width_undo_action (HTMLEngine *e, HTMLUndoData *undo_data, HTMLUndoDirection dir, guint position_after)
937{
938        HTMLTableSetAttrUndo *data = (HTMLTableSetAttrUndo *) undo_data;
939
940        table_set_width (e, html_engine_get_table (e), data->attr.width.width, data->attr.width.percent,
941                         html_undo_direction_reverse (dir));
942}
943
944static void
945table_set_width (HTMLEngine *e, HTMLTable *t, gint width, gboolean percent, HTMLUndoDirection dir)
946{
947        HTMLTableSetAttrUndo *undo;
948
949        undo = attr_undo_new (HTML_TABLE_WIDTH);
950        undo->attr.width.width = HTML_OBJECT (t)->percent
951                ? HTML_OBJECT (t)->percent
952                : (HTML_OBJECT (t)->flags & HTML_OBJECT_FLAG_FIXEDWIDTH
953                   ? t->specified_width : 0);
954        undo->attr.width.percent = HTML_OBJECT (t)->percent != 0;
955        html_undo_add_action (e->undo,
956                              html_undo_action_new ("Set table width", table_set_width_undo_action,
957                                                    HTML_UNDO_DATA (undo),
958                                                    html_cursor_get_position (e->cursor),
959                                                    html_cursor_get_position (e->cursor)), dir);
960
961        if (percent) {
962                HTML_OBJECT (t)->percent = width;
963                HTML_OBJECT (t)->flags  &= ~ HTML_OBJECT_FLAG_FIXEDWIDTH;
964                t->specified_width       = 0;
965        } else {
966                HTML_OBJECT (t)->percent = 0;
967                t->specified_width       = width;
968                if (width)
969                        HTML_OBJECT (t)->flags |= HTML_OBJECT_FLAG_FIXEDWIDTH;
970                else
971                        HTML_OBJECT (t)->flags &= ~ HTML_OBJECT_FLAG_FIXEDWIDTH;
972        }
973        html_object_change_set (HTML_OBJECT (t), HTML_CHANGE_ALL_CALC);
974        html_engine_schedule_update (e);
975}
976
977void
978html_engine_table_set_width (HTMLEngine *e, HTMLTable *t, gint width, gboolean percent)
979{
980        table_set_width (e, t, width, percent, HTML_UNDO_UNDO);
981}
982
983gboolean
984html_engine_table_goto_0_0 (HTMLEngine *e)
985{
986        HTMLTableCell *cell;
987
988        cell = html_engine_get_table_cell (e);
989        while (cell && (cell->row != 0 || cell->col != 0)) {
990                html_engine_prev_cell (e);
991                cell = html_engine_get_table_cell (e);
992        }
993
994        return cell != NULL;
995}
996
997gboolean
998html_engine_table_goto_col (HTMLEngine *e, gint col)
999{
1000        HTMLTableCell *cell;
1001
1002        if (html_engine_table_goto_0_0 (e)) {
1003                cell = html_engine_get_table_cell (e);
1004                while (cell && cell->col != col) {
1005                        html_engine_next_cell (e, FALSE);
1006                        cell = html_engine_get_table_cell (e);
1007                }
1008
1009                return cell != NULL;
1010        }
1011
1012        return FALSE;
1013}
1014
1015gboolean
1016html_engine_table_goto_row (HTMLEngine *e, gint row)
1017{
1018        HTMLTableCell *cell;
1019
1020        if (html_engine_table_goto_0_0 (e)) {
1021                cell = html_engine_get_table_cell (e);
1022                while (cell && cell->row != row) {
1023                        html_engine_next_cell (e, FALSE);
1024                        cell = html_engine_get_table_cell (e);
1025                }
1026
1027                return cell != NULL;
1028        }
1029
1030        return FALSE;
1031}
1032
1033
1034gboolean
1035html_engine_table_goto_pos (HTMLEngine *e, gint row, gint col)
1036{
1037        HTMLTableCell *cell;
1038
1039        if (html_engine_table_goto_0_0 (e)) {
1040                cell = html_engine_get_table_cell (e);
1041                while (cell && cell->row != row && cell->col != col) {
1042                        html_engine_next_cell (e, FALSE);
1043                        cell = html_engine_get_table_cell (e);
1044                }
1045
1046                return cell != NULL;
1047        }
1048
1049        return FALSE;
1050}
1051
1052/*
1053 * set number of columns in current table
1054 */
1055
1056void
1057html_engine_table_set_cols (HTMLEngine *e, gint cols)
1058{
1059        HTMLTable *table = html_engine_get_table (e);
1060
1061        if (!table)
1062                return;
1063
1064        if (table->totalCols == cols)
1065                return;
1066
1067        if (table->totalCols < cols) {
1068                html_engine_table_goto_col (e, table->totalCols - 1);
1069                while (table->totalCols < cols)
1070                        html_engine_insert_table_column (e, TRUE);
1071        } else {
1072                html_engine_table_goto_col (e, table->totalCols - 1);
1073                while (table->totalCols > cols)
1074                        html_engine_delete_table_column (e);
1075        }
1076
1077        /*
1078          FIXME: jump to some well defined position (like the same position as before
1079          or at beginning of 1st new column or to last position in remaining cells
1080        */
1081}
1082
1083/*
1084 * set number of rows in current table
1085 */
1086
1087void
1088html_engine_table_set_rows (HTMLEngine *e, gint rows)
1089{
1090        HTMLTable *table = html_engine_get_table (e);
1091
1092        if (!table)
1093                return;
1094
1095        if (table->totalRows == rows)
1096                return;
1097
1098        if (table->totalRows < rows) {
1099                html_engine_table_goto_row (e, table->totalRows - 1);
1100                while (table->totalRows < rows)
1101                        html_engine_insert_table_row (e, TRUE);
1102        } else {
1103                html_engine_table_goto_row (e, table->totalRows - 1);
1104                while (table->totalRows > rows)
1105                        html_engine_delete_table_row (e);
1106        }
1107
1108        /*
1109          FIXME: like set_cols
1110        */
1111}
1112
1113void
1114html_engine_delete_table (HTMLEngine *e)
1115{
1116        HTMLTable *table;
1117
1118        table = html_engine_get_table (e);
1119
1120        if (!table)
1121                return;
1122        while (e->cursor->object != HTML_OBJECT (table) || e->cursor->offset)
1123                html_cursor_backward (e->cursor, e);
1124        html_engine_set_mark (e);
1125        html_cursor_end_of_line (e->cursor, e);
1126        html_engine_delete (e);
1127}
Note: See TracBrowser for help on using the repository browser.