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, 2002 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., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, 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 "htmlinterval.h"
35 #include "htmltable.h"
36 #include "htmltablecell.h"
37 #include "htmltablepriv.h"
38 #include "htmlselection.h"
39 #include "htmlundo.h"
40
41 HTMLTable *
html_engine_get_table(HTMLEngine * e)42 html_engine_get_table (HTMLEngine *e)
43 {
44 if (!e->cursor->object->parent
45 || !e->cursor->object->parent->parent
46 || !e->cursor->object->parent->parent->parent
47 || !HTML_IS_TABLE (e->cursor->object->parent->parent->parent))
48 return NULL;
49 else
50 return HTML_TABLE (e->cursor->object->parent->parent->parent);
51 }
52
53 HTMLTableCell *
html_engine_new_cell(HTMLEngine * e,HTMLTable * table)54 html_engine_new_cell (HTMLEngine *e,
55 HTMLTable *table)
56 {
57 HTMLObject *cell;
58 HTMLObject *text;
59 HTMLObject *flow;
60
61 cell = html_table_cell_new (1, 1, table->padding);
62 flow = html_clueflow_new (HTML_CLUEFLOW_STYLE_NORMAL, g_byte_array_new (),
63 HTML_LIST_TYPE_UNORDERED, 0, HTML_CLEAR_NONE);
64 text = html_engine_new_text_empty (e);
65
66 html_clue_append (HTML_CLUE (flow), text);
67 html_clue_append (HTML_CLUE (cell), flow);
68
69 return HTML_TABLE_CELL (cell);
70 }
71
72 /*
73 * Table insertion
74 */
75
76 /**
77 * html_engine_insert_table_1_1:
78 * @e: An html engine
79 *
80 * Inserts new table with one cell containing an empty flow with an empty text. Inserted table has 1 row and 1 column.
81 **/
82
83 void
html_engine_insert_table_1_1(HTMLEngine * e)84 html_engine_insert_table_1_1 (HTMLEngine *e)
85 {
86 HTMLObject *table;
87
88 table = html_table_new (0, 100, 1, 2, 1);
89
90 html_table_add_cell (HTML_TABLE (table), html_engine_new_cell (e, HTML_TABLE (table)));
91
92 html_engine_append_object (e, table, 2);
93 html_cursor_backward (e->cursor, e);
94 html_engine_table_set_align (e, (HTMLTable *) table, HTML_HALIGN_CENTER);
95 }
96
97 /**
98 * html_engine_insert_table_1_1:
99 * @e: An html engine
100 *
101 * Inserts new table with @cols columns and @rows rows. Cells contain an empty flow with an empty text.
102 **/
103
104 void
html_engine_insert_table(HTMLEngine * e,gint cols,gint rows,gint width,gint percent,gint padding,gint spacing,gint border)105 html_engine_insert_table (HTMLEngine *e,
106 gint cols,
107 gint rows,
108 gint width,
109 gint percent,
110 gint padding,
111 gint spacing,
112 gint border)
113 {
114 HTMLObject *table;
115 gint r, c;
116
117 g_return_if_fail (cols >= 0);
118 g_return_if_fail (rows >= 0);
119
120 table = html_table_new (width, percent, padding, spacing, border);
121
122 for (r = 0; r < rows; r++) {
123 html_table_start_row (HTML_TABLE (table));
124 for (c = 0; c < cols; c++)
125 html_table_add_cell (HTML_TABLE (table), html_engine_new_cell (e, HTML_TABLE (table)));
126 html_table_end_row (HTML_TABLE (table));
127 }
128
129 html_engine_append_object (e, table, 1 + rows * cols);
130 html_cursor_backward_n (e->cursor, e, rows * cols);
131 }
132
133 /*
134 * Insert Column
135 */
136
137 struct _InsertCellsUndo {
138 HTMLUndoData data;
139
140 gint pos;
141 };
142 typedef struct _InsertCellsUndo InsertCellsUndo;
143 #define INSERT_UNDO(x) ((InsertCellsUndo *) x)
144
145 static HTMLUndoData *
insert_undo_data_new(gint pos)146 insert_undo_data_new (gint pos)
147 {
148 InsertCellsUndo *ud = g_new0 (InsertCellsUndo, 1);
149
150 html_undo_data_init (HTML_UNDO_DATA (ud));
151 ud->pos = pos;
152
153 return HTML_UNDO_DATA (ud);
154 }
155
156 static void
insert_column_undo_action(HTMLEngine * e,HTMLUndoData * data,HTMLUndoDirection dir,guint position_after)157 insert_column_undo_action (HTMLEngine *e,
158 HTMLUndoData *data,
159 HTMLUndoDirection dir,
160 guint position_after)
161 {
162 html_table_delete_column (html_engine_get_table (e), e, INSERT_UNDO (data)->pos, html_undo_direction_reverse (dir));
163 }
164
165 static void
insert_column_setup_undo(HTMLEngine * e,gint col,guint position_before,HTMLUndoDirection dir)166 insert_column_setup_undo (HTMLEngine *e,
167 gint col,
168 guint position_before,
169 HTMLUndoDirection dir)
170 {
171 html_undo_add_action (e->undo, e,
172 html_undo_action_new ("Insert table column", insert_column_undo_action,
173 insert_undo_data_new (col), html_cursor_get_position (e->cursor),
174 position_before),
175 dir);
176 }
177
178 gboolean
html_engine_goto_table_0(HTMLEngine * e,HTMLTable * table)179 html_engine_goto_table_0 (HTMLEngine *e,
180 HTMLTable *table)
181 {
182 return html_cursor_jump_to (e->cursor, e, HTML_OBJECT (table), 0);
183 }
184
185 gboolean
html_engine_goto_table(HTMLEngine * e,HTMLTable * table,gint row,gint col)186 html_engine_goto_table (HTMLEngine *e,
187 HTMLTable *table,
188 gint row,
189 gint col)
190 {
191 HTMLTableCell *cell;
192
193 html_engine_goto_table_0 (e, table);
194 do {
195 cell = html_engine_get_table_cell (e);
196 if (cell && HTML_OBJECT (cell)->parent && HTML_OBJECT (cell)->parent == HTML_OBJECT (table)
197 && cell->col == col && cell->row == row)
198 return TRUE;
199 } while (cell && html_cursor_forward (e->cursor, e));
200
201 return FALSE;
202 }
203
204 gboolean
html_engine_table_goto_col(HTMLEngine * e,HTMLTable * table,gint col)205 html_engine_table_goto_col (HTMLEngine *e,
206 HTMLTable *table,
207 gint col)
208 {
209 HTMLTableCell *cell;
210
211 if (html_engine_goto_table_0 (e, table)) {
212 html_cursor_forward (e->cursor, e);
213 cell = html_engine_get_table_cell (e);
214 while (cell && cell->col != col && HTML_OBJECT (cell)->parent == HTML_OBJECT (table)) {
215 html_engine_next_cell (e, FALSE);
216 cell = html_engine_get_table_cell (e);
217 }
218
219 return cell != NULL && HTML_OBJECT (cell)->parent == HTML_OBJECT (table);
220 }
221
222 return FALSE;
223 }
224
225 gboolean
html_engine_table_goto_row(HTMLEngine * e,HTMLTable * table,gint row)226 html_engine_table_goto_row (HTMLEngine *e,
227 HTMLTable *table,
228 gint row)
229 {
230 HTMLTableCell *cell;
231
232 if (html_engine_goto_table_0 (e, table)) {
233 html_cursor_forward (e->cursor, e);
234 cell = html_engine_get_table_cell (e);
235 while (cell && cell->row != row && HTML_OBJECT (cell)->parent == HTML_OBJECT (table)) {
236 html_engine_next_cell (e, FALSE);
237 cell = html_engine_get_table_cell (e);
238 }
239
240 return cell != NULL && HTML_OBJECT (cell)->parent == HTML_OBJECT (table);
241 }
242
243 return FALSE;
244 }
245
246 void
html_table_insert_column(HTMLTable * t,HTMLEngine * e,gint col,HTMLTableCell ** column,HTMLUndoDirection dir)247 html_table_insert_column (HTMLTable *t,
248 HTMLEngine *e,
249 gint col,
250 HTMLTableCell **column,
251 HTMLUndoDirection dir)
252 {
253 HTMLTableCell *cell;
254 HTMLPoint pos;
255 gint c, r;
256 guint position_before;
257
258 html_engine_freeze (e);
259
260 position_before = e->cursor->position;
261 pos.object = e->cursor->object;
262 pos.offset = e->cursor->offset;
263
264 html_engine_goto_table_0 (e, t);
265
266 html_table_alloc_cell (t, 0, t->totalCols);
267 for (c = t->totalCols - 1; c > col; c--) {
268 for (r = 0; r < t->totalRows; r++) {
269 HTMLTableCell *cell = t->cells[r][c - 1];
270
271 if (cell) {
272 if (cell->col == c - 1) {
273 html_table_cell_set_position (cell, cell->row, c);
274 t->cells[r][c - 1] = NULL;
275 } else if (c == col + 1 && cell->row == r)
276 cell->cspan++;
277 if (cell->col > c - 1)
278 t->cells[r][c - 1] = NULL;
279 t->cells[r][c] = cell;
280 }
281 }
282 }
283 for (r = 0; r < t->totalRows; r++) {
284 if (!t->cells[r][col]) {
285 guint len;
286
287 cell = column
288 ? HTML_TABLE_CELL (html_object_op_copy (HTML_OBJECT (column[r]), HTML_OBJECT (t),
289 e, NULL, NULL, &len))
290 : html_engine_new_cell (e, t);
291 html_table_set_cell (t, r, col, cell);
292 html_table_cell_set_position (t->cells[r][col], r, col);
293 }
294 }
295
296 html_cursor_jump_to (e->cursor, e, pos.object, pos.offset);
297 insert_column_setup_undo (e, col, position_before, dir);
298 html_object_change_set (HTML_OBJECT (t), HTML_CHANGE_ALL_CALC);
299 html_engine_queue_draw (e, HTML_OBJECT (t));
300 html_engine_thaw (e);
301 }
302
303 /**
304 * html_engine_insert_table_column:
305 * @e: An HTML engine.
306 * @after: If TRUE then inserts new column after current one, defined by current cursor position.
307 * If FALSE then inserts before current one.
308 *
309 * Inserts new column into table after/before current column.
310 **/
311
312 void
html_engine_insert_table_column(HTMLEngine * e,gboolean after)313 html_engine_insert_table_column (HTMLEngine *e,
314 gboolean after)
315 {
316 HTMLTable *table;
317 HTMLTableCell *cell;
318
319 table = html_engine_get_table (e);
320 cell = html_engine_get_table_cell (e);
321 if (table && cell)
322 html_table_insert_column (table, e, cell->col + (after ? cell->cspan : 0), NULL, HTML_UNDO_UNDO);
323 }
324
325 /*
326 * Delete column
327 */
328
329 struct _DeleteCellsUndo {
330 HTMLUndoData data;
331
332 HTMLTableCell **cells;
333 gint size;
334 gint pos;
335 };
336 typedef struct _DeleteCellsUndo DeleteCellsUndo;
337
338 static void
delete_cells_undo_destroy(HTMLUndoData * undo_data)339 delete_cells_undo_destroy (HTMLUndoData *undo_data)
340 {
341 DeleteCellsUndo *data = (DeleteCellsUndo *) undo_data;
342 gint i;
343
344 for (i = 0; i < data->size; i++)
345 if (data->cells[i])
346 html_object_destroy (HTML_OBJECT (data->cells[i]));
347 g_free (data->cells);
348 }
349
350 static DeleteCellsUndo *
delete_cells_undo_new(HTMLTableCell ** cells,gint size,gint pos)351 delete_cells_undo_new (HTMLTableCell **cells,
352 gint size,
353 gint pos)
354 {
355 DeleteCellsUndo *data;
356
357 data = g_new0 (DeleteCellsUndo, 1);
358
359 html_undo_data_init (HTML_UNDO_DATA (data));
360
361 data->data.destroy = delete_cells_undo_destroy;
362 data->cells = cells;
363 data->pos = pos;
364 data->size = size;
365
366 return data;
367 }
368
369 static void
delete_column_undo_action(HTMLEngine * e,HTMLUndoData * undo_data,HTMLUndoDirection dir,guint position_after)370 delete_column_undo_action (HTMLEngine *e,
371 HTMLUndoData *undo_data,
372 HTMLUndoDirection dir,
373 guint position_after)
374 {
375 DeleteCellsUndo *data = (DeleteCellsUndo *) undo_data;
376 HTMLTable *table;
377
378 table = html_engine_get_table (e);
379 if (!table) {
380 html_cursor_jump_to_position (e->cursor, e, position_after + 1);
381 table = html_engine_get_table (e);
382 }
383 g_assert (table);
384 g_assert (data->size == table->totalRows);
385 html_table_insert_column (table, e, data->pos, data->cells, html_undo_direction_reverse (dir));
386 }
387
388 static void
delete_column_setup_undo(HTMLEngine * e,HTMLTableCell ** column,gint size,guint position_after,gint col,HTMLUndoDirection dir)389 delete_column_setup_undo (HTMLEngine *e,
390 HTMLTableCell **column,
391 gint size,
392 guint position_after,
393 gint col,
394 HTMLUndoDirection dir)
395 {
396 html_undo_add_action (e->undo, e,
397 html_undo_action_new ("Delete table column", delete_column_undo_action,
398 HTML_UNDO_DATA (delete_cells_undo_new (column, size, col)),
399 html_cursor_get_position (e->cursor),
400 position_after), dir);
401 }
402
403 static void
backward_before_col(HTMLEngine * e,HTMLTable * table,gint col)404 backward_before_col (HTMLEngine *e,
405 HTMLTable *table,
406 gint col)
407 {
408 HTMLObject *cell;
409
410 do {
411 if (!html_cursor_backward (e->cursor, e))
412 return;
413 cell = html_cursor_child_of (e->cursor, HTML_OBJECT (table));
414 } while (cell && HTML_IS_TABLE_CELL (cell) && HTML_TABLE_CELL (cell)->col >= col);
415 }
416
417 void
html_table_delete_column(HTMLTable * t,HTMLEngine * e,gint col,HTMLUndoDirection dir)418 html_table_delete_column (HTMLTable *t,
419 HTMLEngine *e,
420 gint col,
421 HTMLUndoDirection dir)
422 {
423 HTMLTableCell **column;
424 HTMLTableCell *cell;
425 HTMLPoint pos;
426 gint r, c;
427 guint position_after;
428
429 /* this command is valid only in table and when this table has > 1 column */
430 if (!t || t->totalCols < 2)
431 return;
432
433 html_engine_freeze (e);
434
435 column = g_new0 (HTMLTableCell *, t->totalRows);
436
437 backward_before_col (e, t, col);
438 pos.object = e->cursor->object;
439 pos.offset = e->cursor->offset;
440
441 html_engine_goto_table_0 (e, t);
442 for (r = 0; r < t->totalRows; r++) {
443 cell = t->cells[r][col];
444
445 /* remove & keep old one */
446 if (cell && cell->col == col) {
447 HTML_OBJECT (cell)->parent = NULL;
448 column[r] = cell;
449 t->cells[r][col] = NULL;
450 }
451
452 for (c = col + 1; c < t->totalCols; c++) {
453 cell = t->cells[r][c];
454 if (cell && cell->col != col) {
455 if (cell->row == r && cell->col == c)
456 html_table_cell_set_position (cell, r, c - 1);
457 t->cells[r][c - 1] = cell;
458 t->cells[r][c] = NULL;
459 }
460 }
461 }
462
463 html_cursor_jump_to (e->cursor, e, pos.object, pos.offset);
464 position_after = e->cursor->position;
465 delete_column_setup_undo (e, column, t->totalRows, position_after, col, dir);
466 t->totalCols--;
467
468 html_object_change_set (HTML_OBJECT (t), HTML_CHANGE_ALL_CALC);
469 html_engine_queue_draw (e, HTML_OBJECT (t));
470 html_engine_thaw (e);
471 }
472
473 static gboolean
html_engine_get_table_start_end_cells(HTMLEngine * e,HTMLTableCell ** start_cell,HTMLTableCell ** end_cell)474 html_engine_get_table_start_end_cells (HTMLEngine *e,
475 HTMLTableCell **start_cell,
476 HTMLTableCell **end_cell)
477 {
478 if (!e->cursor->object->parent ||
479 !e->cursor->object->parent->parent ||
480 !HTML_IS_TABLE_CELL (e->cursor->object->parent->parent))
481 return FALSE;
482 if (html_engine_is_selection_active (e)) {
483 if (!e->mark->object->parent ||
484 !e->mark->object->parent->parent ||
485 !HTML_IS_TABLE_CELL (e->mark->object->parent->parent) ||
486 HTML_TABLE (e->mark->object->parent->parent->parent) != html_engine_get_table (e))
487 return FALSE;
488 if (html_cursor_precedes (e->cursor, e->mark)) {
489 *start_cell = HTML_TABLE_CELL (e->cursor->object->parent->parent);
490 *end_cell = HTML_TABLE_CELL (e->mark->object->parent->parent);
491 } else {
492 *start_cell = HTML_TABLE_CELL (e->mark->object->parent->parent);
493 *end_cell = HTML_TABLE_CELL (e->cursor->object->parent->parent);
494 }
495 } else {
496 *start_cell = *end_cell = html_engine_get_table_cell (e);
497 }
498
499 return TRUE;
500 }
501
502 /**
503 * html_engine_delete_table_column:
504 * @e: An HTML engine.
505 *
506 * Deletes current table column.
507 **/
508
509 void
html_engine_delete_table_column(HTMLEngine * e)510 html_engine_delete_table_column (HTMLEngine *e)
511 {
512 HTMLTableCell *start_cell, *end_cell;
513 gint start_col, end_col;
514 HTMLTable *table;
515
516 table = html_engine_get_table (e);
517 if (!table || !HTML_IS_TABLE (table) ||
518 !html_engine_get_table_start_end_cells (e, &start_cell, &end_cell)) {
519 g_warning ("Invalid table object! Row deletion failed!");
520 return;
521 }
522
523 start_col = start_cell->col;
524 end_col = end_cell->col;
525 html_engine_disable_selection (e);
526 if (start_cell->row == end_cell->row)
527 while (start_col <= end_col--)
528 html_table_delete_column (table, e, start_col, HTML_UNDO_UNDO);
529 else
530 if ((start_cell->row == end_cell->row - 1) &&
531 (start_col > end_col + 1)) {
532 while (start_col < table->totalCols)
533 html_table_delete_column (table, e, start_col, HTML_UNDO_UNDO);
534 while (0 <= end_col--)
535 html_table_delete_column (table, e, 0, HTML_UNDO_UNDO);
536 }
537 else
538 html_engine_delete_table (e);
539 }
540
541 /*
542 * Insert Row
543 */
544
545 static void
insert_row_undo_action(HTMLEngine * e,HTMLUndoData * data,HTMLUndoDirection dir,guint position_after)546 insert_row_undo_action (HTMLEngine *e,
547 HTMLUndoData *data,
548 HTMLUndoDirection dir,
549 guint position_after)
550 {
551 html_table_delete_row (html_engine_get_table (e), e, INSERT_UNDO (data)->pos, html_undo_direction_reverse (dir));
552 }
553
554 static void
insert_row_setup_undo(HTMLEngine * e,gint row,guint position_before,HTMLUndoDirection dir)555 insert_row_setup_undo (HTMLEngine *e,
556 gint row,
557 guint position_before,
558 HTMLUndoDirection dir)
559 {
560 html_undo_add_action (e->undo, e,
561 html_undo_action_new ("Insert table row", insert_row_undo_action,
562 insert_undo_data_new (row),
563 html_cursor_get_position (e->cursor),
564 html_cursor_get_position (e->cursor)),
565 dir);
566 }
567
568 void
html_table_insert_row(HTMLTable * t,HTMLEngine * e,gint row,HTMLTableCell ** row_cells,HTMLUndoDirection dir)569 html_table_insert_row (HTMLTable *t,
570 HTMLEngine *e,
571 gint row,
572 HTMLTableCell **row_cells,
573 HTMLUndoDirection dir)
574 {
575 HTMLTableCell *cell;
576 HTMLPoint pos;
577 gint r, c;
578 guint position_before;
579
580 html_engine_freeze (e);
581 position_before = e->cursor->position;
582 pos.object = e->cursor->object;
583 pos.offset = e->cursor->offset;
584 html_engine_goto_table_0 (e, t);
585
586 html_table_alloc_cell (t, t->totalRows, 0);
587 for (r = t->totalRows; r > row; r--) {
588 for (c = 0; c < t->totalCols; c++) {
589 HTMLTableCell *cell = t->cells[r - 1][c];
590
591 if (cell) {
592 if (cell->row == r - 1) {
593 html_table_cell_set_position (cell, r, cell->col);
594 t->cells[r - 1][c] = NULL;
595 } else if (r == row + 1 && cell->col == c)
596 cell->rspan++;
597 if (cell->row > r - 1)
598 t->cells[r - 1][c] = NULL;
599 t->cells[r][c] = cell;
600 }
601 }
602 }
603 for (c = 0; c < t->totalCols; c++) {
604 if (!t->cells[row][c]) {
605 guint len;
606
607 cell = row_cells
608 ? HTML_TABLE_CELL (html_object_op_copy (HTML_OBJECT (row_cells[c]), HTML_OBJECT (t),
609 e, NULL, NULL, &len))
610 : html_engine_new_cell (e, t);
611 html_table_set_cell (t, row, c, cell);
612 html_table_cell_set_position (t->cells[row][c], row, c);
613 }
614 }
615
616 html_cursor_jump_to (e->cursor, e, pos.object, pos.offset);
617 insert_row_setup_undo (e, row, position_before, dir);
618 html_object_change_set (HTML_OBJECT (t), HTML_CHANGE_ALL_CALC);
619 html_engine_queue_draw (e, HTML_OBJECT (t));
620 html_engine_thaw (e);
621 }
622
623 /**
624 * html_engine_insert_table_row:
625 * @e: An HTML engine.
626 * @after: If TRUE then inserts new row after current one, defined by current cursor position.
627 * If FALSE then inserts before current one.
628 *
629 * Inserts new row into table after/before current row.
630 **/
631
632 void
html_engine_insert_table_row(HTMLEngine * e,gboolean after)633 html_engine_insert_table_row (HTMLEngine *e,
634 gboolean after)
635 {
636 HTMLTable *table;
637 HTMLTableCell *cell;
638
639 table = html_engine_get_table (e);
640 cell = html_engine_get_table_cell (e);
641 if (table && cell)
642 html_table_insert_row (table, e, cell->row + (after ? cell->rspan : 0), NULL, HTML_UNDO_UNDO);
643 }
644
645 /*
646 * Delete row
647 */
648
649 static void
delete_row_undo_action(HTMLEngine * e,HTMLUndoData * undo_data,HTMLUndoDirection dir,guint position_after)650 delete_row_undo_action (HTMLEngine *e,
651 HTMLUndoData *undo_data,
652 HTMLUndoDirection dir,
653 guint position_after)
654 {
655 DeleteCellsUndo *data = (DeleteCellsUndo *) undo_data;
656 HTMLTable *table;
657
658 table = html_engine_get_table (e);
659 if (!table) {
660 html_cursor_jump_to_position (e->cursor, e, position_after + 1);
661 table = html_engine_get_table (e);
662 }
663 g_assert (table);
664 g_assert (data->size == table->totalCols);
665 html_table_insert_row (table, e, data->pos, data->cells, html_undo_direction_reverse (dir));
666 }
667
668 static void
delete_row_setup_undo(HTMLEngine * e,HTMLTableCell ** row_cells,gint size,guint position_after,gint row,HTMLUndoDirection dir)669 delete_row_setup_undo (HTMLEngine *e,
670 HTMLTableCell **row_cells,
671 gint size,
672 guint position_after,
673 gint row,
674 HTMLUndoDirection dir)
675 {
676 html_undo_add_action (e->undo, e,
677 html_undo_action_new ("Delete table row", delete_row_undo_action,
678 HTML_UNDO_DATA (delete_cells_undo_new (row_cells, size, row)),
679 html_cursor_get_position (e->cursor),
680 position_after), dir);
681 }
682
683 static void
backward_before_row(HTMLEngine * e,HTMLTable * table,gint row)684 backward_before_row (HTMLEngine *e,
685 HTMLTable *table,
686 gint row)
687 {
688 HTMLObject *cell;
689
690 do {
691 if (!html_cursor_backward (e->cursor, e))
692 return;
693 cell = html_cursor_child_of (e->cursor, HTML_OBJECT (table));
694 } while (cell && HTML_IS_TABLE_CELL (cell) && HTML_TABLE_CELL (cell)->row >= row);
695 }
696
697 void
html_table_delete_row(HTMLTable * t,HTMLEngine * e,gint row,HTMLUndoDirection dir)698 html_table_delete_row (HTMLTable *t,
699 HTMLEngine *e,
700 gint row,
701 HTMLUndoDirection dir)
702 {
703 HTMLTableCell **row_cells;
704 HTMLTableCell *cell;
705 HTMLPoint pos;
706 gint r, c;
707 guint position_after;
708
709 /* this command is valid only in table and when this table has > 1 row */
710 if (!t || t->totalRows < 2)
711 return;
712
713 html_engine_freeze (e);
714
715 row_cells = g_new0 (HTMLTableCell *, t->totalCols);
716
717 backward_before_row (e, t, row);
718 pos.object = e->cursor->object;
719 pos.offset = e->cursor->offset;
720
721 html_engine_goto_table_0 (e, t);
722 for (c = 0; c < t->totalCols; c++) {
723 cell = t->cells[row][c];
724
725 /* remove & keep old one */
726 if (cell && cell->row == row) {
727 HTML_OBJECT (cell)->parent = NULL;
728 row_cells[c] = cell;
729 t->cells[row][c] = NULL;
730 }
731
732 for (r = row + 1; r < t->totalRows; r++) {
733 cell = t->cells[r][c];
734 if (cell && cell->row != row) {
735 if (cell->row == r && cell->col == c)
736 html_table_cell_set_position (cell, r - 1, c);
737 t->cells[r - 1][c] = cell;
738 t->cells[r][c] = NULL;
739 }
740 }
741 }
742
743 html_cursor_jump_to (e->cursor, e, pos.object, pos.offset);
744 t->totalRows--;
745 position_after = e->cursor->position;
746 delete_row_setup_undo (e, row_cells, t->totalCols, position_after, row, dir);
747 html_object_change_set (HTML_OBJECT (t), HTML_CHANGE_ALL_CALC);
748 html_engine_queue_draw (e, HTML_OBJECT (t));
749 html_engine_thaw (e);
750 }
751
752 /**
753 * html_engine_delete_table_row:
754 * @e: An HTML engine.
755 *
756 * Deletes current table row.
757 **/
758
759 void
html_engine_delete_table_row(HTMLEngine * e)760 html_engine_delete_table_row (HTMLEngine *e)
761 {
762 HTMLTableCell *start_cell, *end_cell;
763 gint start_row, end_row;
764 HTMLTable *table;
765
766 table = html_engine_get_table (e);
767 if (!table || !HTML_IS_TABLE (table) ||
768 !html_engine_get_table_start_end_cells (e, &start_cell, &end_cell)) {
769 g_warning ("Invalid table object! Row deletion failed!");
770 return;
771 }
772
773 start_row = start_cell->row;
774 end_row = end_cell->row;
775 html_engine_disable_selection (e);
776 if (end_row - start_row == table->totalRows - 1)
777 html_engine_delete_table (e);
778 else
779 while (start_row <= end_row--)
780 html_table_delete_row (table, e, start_row, HTML_UNDO_UNDO);
781 }
782
783 typedef enum {
784 HTML_TABLE_BORDER,
785 HTML_TABLE_PADDING,
786 HTML_TABLE_SPACING,
787 HTML_TABLE_WIDTH,
788 HTML_TABLE_BGCOLOR,
789 HTML_TABLE_BGPIXMAP,
790 HTML_TABLE_ALIGN
791 } HTMLTableAttrType;
792
793 union _HTMLTableUndoAttr {
794 gint border;
795 gint spacing;
796 gint padding;
797
798 gchar *pixmap;
799
800 struct {
801 gint width;
802 gboolean percent;
803 } width;
804
805 struct {
806 GdkColor color;
807 gboolean has_bg_color;
808 } color;
809
810 HTMLHAlignType align;
811 };
812 typedef union _HTMLTableUndoAttr HTMLTableUndoAttr;
813
814 struct _HTMLTableSetAttrUndo {
815 HTMLUndoData data;
816
817 HTMLTableUndoAttr attr;
818 HTMLTableAttrType type;
819 };
820 typedef struct _HTMLTableSetAttrUndo HTMLTableSetAttrUndo;
821
822 static void
attr_destroy(HTMLUndoData * undo_data)823 attr_destroy (HTMLUndoData *undo_data)
824 {
825 HTMLTableSetAttrUndo *data = (HTMLTableSetAttrUndo *) undo_data;
826
827 switch (data->type) {
828 case HTML_TABLE_BGPIXMAP:
829 g_free (data->attr.pixmap);
830 break;
831 default:
832 ;
833 }
834 }
835
836 static HTMLTableSetAttrUndo *
attr_undo_new(HTMLTableAttrType type)837 attr_undo_new (HTMLTableAttrType type)
838 {
839 HTMLTableSetAttrUndo *undo = g_new (HTMLTableSetAttrUndo, 1);
840
841 html_undo_data_init (HTML_UNDO_DATA (undo));
842 undo->data.destroy = attr_destroy;
843 undo->type = type;
844
845 return undo;
846 }
847
848 /*
849 * Border width
850 */
851
852 static void table_set_border_width (HTMLEngine *e, HTMLTable *t, gint border_width, gboolean relative, HTMLUndoDirection dir);
853
854 static void
table_set_border_width_undo_action(HTMLEngine * e,HTMLUndoData * undo_data,HTMLUndoDirection dir,guint position_after)855 table_set_border_width_undo_action (HTMLEngine *e,
856 HTMLUndoData *undo_data,
857 HTMLUndoDirection dir,
858 guint position_after)
859 {
860 table_set_border_width (e, html_engine_get_table (e), ((HTMLTableSetAttrUndo *) undo_data)->attr.border, FALSE,
861 html_undo_direction_reverse (dir));
862 }
863
864 static void
table_set_border_width(HTMLEngine * e,HTMLTable * t,gint border_width,gboolean relative,HTMLUndoDirection dir)865 table_set_border_width (HTMLEngine *e,
866 HTMLTable *t,
867 gint border_width,
868 gboolean relative,
869 HTMLUndoDirection dir)
870 {
871 HTMLTableSetAttrUndo *undo;
872 gint new_border;
873
874 if (!t || !HTML_IS_TABLE (t))
875 return;
876
877 if (relative)
878 new_border = t->border + border_width;
879 else
880 new_border = border_width;
881 if (new_border < 0)
882 new_border = 0;
883 if (new_border == t->border)
884 return;
885
886 undo = attr_undo_new (HTML_TABLE_BORDER);
887 undo->attr.border = t->border;
888
889 html_engine_freeze (e);
890 t->border = new_border;
891
892 html_object_change_set (HTML_OBJECT (t), HTML_CHANGE_ALL_CALC);
893 html_engine_thaw (e);
894
895 html_undo_add_action (e->undo, e,
896 html_undo_action_new ("Set table border width", table_set_border_width_undo_action,
897 HTML_UNDO_DATA (undo), html_cursor_get_position (e->cursor),
898 html_cursor_get_position (e->cursor)), dir);
899 }
900
901 void
html_engine_table_set_border_width(HTMLEngine * e,HTMLTable * t,gint border_width,gboolean relative)902 html_engine_table_set_border_width (HTMLEngine *e,
903 HTMLTable *t,
904 gint border_width,
905 gboolean relative)
906 {
907 table_set_border_width (e, t, border_width, relative, HTML_UNDO_UNDO);
908 }
909
910 /*
911 * bg color
912 *
913 */
914
915 static void table_set_bg_color (HTMLEngine *e, HTMLTable *t, GdkColor *c, HTMLUndoDirection dir);
916
917 static void
table_set_bg_color_undo_action(HTMLEngine * e,HTMLUndoData * undo_data,HTMLUndoDirection dir,guint position_after)918 table_set_bg_color_undo_action (HTMLEngine *e,
919 HTMLUndoData *undo_data,
920 HTMLUndoDirection dir,
921 guint position_after)
922 {
923 HTMLTableSetAttrUndo *data = (HTMLTableSetAttrUndo *) undo_data;
924 HTMLTable *table = html_engine_get_table (e);
925
926 if (!table)
927 return;
928
929 table_set_bg_color (e, table, data->attr.color.has_bg_color
930 ? &data->attr.color.color : NULL, html_undo_direction_reverse (dir));
931 }
932
933 static void
table_set_bg_color(HTMLEngine * e,HTMLTable * t,GdkColor * c,HTMLUndoDirection dir)934 table_set_bg_color (HTMLEngine *e,
935 HTMLTable *t,
936 GdkColor *c,
937 HTMLUndoDirection dir)
938 {
939 HTMLTableSetAttrUndo *undo;
940
941 undo = attr_undo_new (HTML_TABLE_BGCOLOR);
942 if (t->bgColor) {
943 undo->attr.color.color = *t->bgColor;
944 undo->attr.color.has_bg_color = TRUE;
945 } else
946 undo->attr.color.has_bg_color = FALSE;
947 html_undo_add_action (e->undo, e,
948 html_undo_action_new ("Set table background color", table_set_bg_color_undo_action,
949 HTML_UNDO_DATA (undo),
950 html_cursor_get_position (e->cursor),
951 html_cursor_get_position (e->cursor)), dir);
952 if (c) {
953 if (!t->bgColor)
954 t->bgColor = gdk_color_copy (c);
955 *t->bgColor = *c;
956 } else {
957 if (t->bgColor)
958 gdk_color_free (t->bgColor);
959 t->bgColor = NULL;
960 }
961 html_engine_queue_draw (e, HTML_OBJECT (t));
962 }
963
964 void
html_engine_table_set_bg_color(HTMLEngine * e,HTMLTable * t,GdkColor * c)965 html_engine_table_set_bg_color (HTMLEngine *e,
966 HTMLTable *t,
967 GdkColor *c)
968 {
969 table_set_bg_color (e, t, c, HTML_UNDO_UNDO);
970 }
971
972 /*
973 * bg pixmap
974 *
975 */
976
977 static void table_set_bg_pixmap (HTMLEngine *e, HTMLTable *t, gchar *url, HTMLUndoDirection dir);
978
979 static void
table_set_bg_pixmap_undo_action(HTMLEngine * e,HTMLUndoData * undo_data,HTMLUndoDirection dir,guint position_after)980 table_set_bg_pixmap_undo_action (HTMLEngine *e,
981 HTMLUndoData *undo_data,
982 HTMLUndoDirection dir,
983 guint position_after)
984 {
985 HTMLTableSetAttrUndo *data = (HTMLTableSetAttrUndo *) undo_data;
986
987 table_set_bg_pixmap (e, html_engine_get_table (e), data->attr.pixmap, html_undo_direction_reverse (dir));
988 }
989
990 static void
table_set_bg_pixmap(HTMLEngine * e,HTMLTable * t,gchar * url,HTMLUndoDirection dir)991 table_set_bg_pixmap (HTMLEngine *e,
992 HTMLTable *t,
993 gchar *url,
994 HTMLUndoDirection dir)
995 {
996 HTMLImagePointer *iptr;
997 HTMLTableSetAttrUndo *undo;
998
999 undo = attr_undo_new (HTML_TABLE_BGPIXMAP);
1000 undo->attr.pixmap = t->bgPixmap ? g_strdup (t->bgPixmap->url) : NULL;
1001 html_undo_add_action (e->undo, e,
1002 html_undo_action_new ("Set table background pixmap", table_set_bg_pixmap_undo_action,
1003 HTML_UNDO_DATA (undo),
1004 html_cursor_get_position (e->cursor),
1005 html_cursor_get_position (e->cursor)), dir);
1006
1007 iptr = t->bgPixmap;
1008 t->bgPixmap = url ? html_image_factory_register (e->image_factory, NULL, url, TRUE) : NULL;
1009 if (iptr)
1010 html_image_factory_unregister (e->image_factory, iptr, NULL);
1011 html_engine_queue_draw (e, HTML_OBJECT (t));
1012 }
1013
1014 void
html_engine_table_set_bg_pixmap(HTMLEngine * e,HTMLTable * t,gchar * url)1015 html_engine_table_set_bg_pixmap (HTMLEngine *e,
1016 HTMLTable *t,
1017 gchar *url)
1018 {
1019 table_set_bg_pixmap (e, t, url, HTML_UNDO_UNDO);
1020 }
1021
1022 /*
1023 * spacing
1024 *
1025 */
1026
1027 static void table_set_spacing (HTMLEngine *e, HTMLTable *t, gint spacing, gboolean relative, HTMLUndoDirection dir);
1028
1029 static void
table_set_spacing_undo_action(HTMLEngine * e,HTMLUndoData * undo_data,HTMLUndoDirection dir,guint position_after)1030 table_set_spacing_undo_action (HTMLEngine *e,
1031 HTMLUndoData *undo_data,
1032 HTMLUndoDirection dir,
1033 guint position_after)
1034 {
1035 HTMLTableSetAttrUndo *data = (HTMLTableSetAttrUndo *) undo_data;
1036
1037 table_set_spacing (e, html_engine_get_table (e), data->attr.spacing, FALSE, html_undo_direction_reverse (dir));
1038 }
1039
1040 static void
table_set_spacing(HTMLEngine * e,HTMLTable * t,gint spacing,gboolean relative,HTMLUndoDirection dir)1041 table_set_spacing (HTMLEngine *e,
1042 HTMLTable *t,
1043 gint spacing,
1044 gboolean relative,
1045 HTMLUndoDirection dir)
1046 {
1047 HTMLTableSetAttrUndo *undo;
1048 gint new_spacing;
1049
1050 if (!t || !HTML_IS_TABLE (t))
1051 return;
1052
1053 if (relative)
1054 new_spacing = t->spacing + spacing;
1055 else
1056 new_spacing = spacing;
1057 if (new_spacing < 0)
1058 new_spacing = 0;
1059 if (new_spacing == t->spacing)
1060 return;
1061
1062 undo = attr_undo_new (HTML_TABLE_SPACING);
1063 undo->attr.spacing = t->spacing;
1064 html_undo_add_action (e->undo, e,
1065 html_undo_action_new ("Set table spacing", table_set_spacing_undo_action,
1066 HTML_UNDO_DATA (undo),
1067 html_cursor_get_position (e->cursor),
1068 html_cursor_get_position (e->cursor)), dir);
1069 t->spacing = new_spacing;
1070 html_object_change_set (HTML_OBJECT (t), HTML_CHANGE_ALL_CALC);
1071 html_engine_schedule_update (e);
1072 }
1073
1074 void
html_engine_table_set_spacing(HTMLEngine * e,HTMLTable * t,gint spacing,gboolean relative)1075 html_engine_table_set_spacing (HTMLEngine *e,
1076 HTMLTable *t,
1077 gint spacing,
1078 gboolean relative)
1079 {
1080 table_set_spacing (e, t, spacing, relative, HTML_UNDO_UNDO);
1081 }
1082
1083 /*
1084 * padding
1085 *
1086 */
1087
1088 static void table_set_padding (HTMLEngine *e, HTMLTable *t, gint padding, gboolean relative, HTMLUndoDirection dir);
1089
1090 static void
table_set_padding_undo_action(HTMLEngine * e,HTMLUndoData * undo_data,HTMLUndoDirection dir,guint position_after)1091 table_set_padding_undo_action (HTMLEngine *e,
1092 HTMLUndoData *undo_data,
1093 HTMLUndoDirection dir,
1094 guint position_after)
1095 {
1096 HTMLTableSetAttrUndo *data = (HTMLTableSetAttrUndo *) undo_data;
1097
1098 table_set_padding (e, html_engine_get_table (e), data->attr.padding, FALSE, html_undo_direction_reverse (dir));
1099 }
1100
1101 static void
table_set_padding(HTMLEngine * e,HTMLTable * t,gint padding,gboolean relative,HTMLUndoDirection dir)1102 table_set_padding (HTMLEngine *e,
1103 HTMLTable *t,
1104 gint padding,
1105 gboolean relative,
1106 HTMLUndoDirection dir)
1107 {
1108 HTMLTableSetAttrUndo *undo;
1109 gint r, c;
1110 gint new_padding;
1111
1112 if (!t || !HTML_IS_TABLE (t))
1113 return;
1114
1115 if (relative)
1116 new_padding = t->padding + padding;
1117 else
1118 new_padding = padding;
1119 if (new_padding < 0)
1120 new_padding = 0;
1121 if (new_padding == t->padding)
1122 return;
1123
1124 undo = attr_undo_new (HTML_TABLE_PADDING);
1125 undo->attr.padding = t->padding;
1126 html_undo_add_action (e->undo, e,
1127 html_undo_action_new ("Set table padding", table_set_padding_undo_action,
1128 HTML_UNDO_DATA (undo),
1129 html_cursor_get_position (e->cursor),
1130 html_cursor_get_position (e->cursor)), dir);
1131
1132 t->padding = new_padding;
1133 for (r = 0; r < t->totalRows; r++)
1134 for (c = 0; c < t->totalCols; c++)
1135 if (t->cells[r][c]->col == c && t->cells[r][c]->row == r) {
1136 HTML_CLUEV (t->cells[r][c])->padding = new_padding;
1137 HTML_OBJECT (t->cells[r][c])->change |= HTML_CHANGE_ALL_CALC;
1138 }
1139 html_object_change_set (HTML_OBJECT (t), HTML_CHANGE_ALL_CALC);
1140 html_engine_schedule_update (e);
1141 }
1142
1143 void
html_engine_table_set_padding(HTMLEngine * e,HTMLTable * t,gint padding,gboolean relative)1144 html_engine_table_set_padding (HTMLEngine *e,
1145 HTMLTable *t,
1146 gint padding,
1147 gboolean relative)
1148 {
1149 table_set_padding (e, t, padding, relative, HTML_UNDO_UNDO);
1150 }
1151
1152 /*
1153 * align
1154 *
1155 */
1156
1157 static void table_set_align (HTMLEngine *e, HTMLTable *t, HTMLHAlignType align, HTMLUndoDirection dir);
1158
1159 static void
table_set_align_undo_action(HTMLEngine * e,HTMLUndoData * undo_data,HTMLUndoDirection dir,guint position_after)1160 table_set_align_undo_action (HTMLEngine *e,
1161 HTMLUndoData *undo_data,
1162 HTMLUndoDirection dir,
1163 guint position_after)
1164 {
1165 HTMLTableSetAttrUndo *data = (HTMLTableSetAttrUndo *) undo_data;
1166
1167 table_set_align (e, html_engine_get_table (e), data->attr.align, html_undo_direction_reverse (dir));
1168 }
1169
1170 static void
table_set_align(HTMLEngine * e,HTMLTable * t,HTMLHAlignType align,HTMLUndoDirection dir)1171 table_set_align (HTMLEngine *e,
1172 HTMLTable *t,
1173 HTMLHAlignType align,
1174 HTMLUndoDirection dir)
1175 {
1176 HTMLTableSetAttrUndo *undo;
1177
1178 /* table gone */
1179 if (!t)
1180 return;
1181
1182 g_return_if_fail (HTML_OBJECT (t)->parent);
1183
1184 undo = attr_undo_new (HTML_TABLE_ALIGN);
1185 undo->attr.align = HTML_CLUE (HTML_OBJECT (t)->parent)->halign;
1186
1187 if (align == HTML_HALIGN_NONE || align == HTML_HALIGN_CENTER) {
1188 if (HTML_IS_CLUEALIGNED (HTML_OBJECT (t)->parent)) {
1189 HTMLObject *aclue = HTML_OBJECT (t)->parent;
1190
1191 html_clue_remove (HTML_CLUE (aclue), HTML_OBJECT (t));
1192 html_clue_append_after (HTML_CLUE (aclue->parent), HTML_OBJECT (t), aclue);
1193 html_clue_remove (HTML_CLUE (aclue->parent), aclue);
1194 html_object_destroy (aclue);
1195 }
1196 } else if (align == HTML_HALIGN_LEFT || align == HTML_HALIGN_RIGHT) {
1197 if (HTML_IS_CLUEFLOW (HTML_OBJECT (t)->parent)) {
1198 HTMLObject *aclue, *flow = HTML_OBJECT (t)->parent;
1199
1200 html_clue_remove (HTML_CLUE (flow), HTML_OBJECT (t));
1201 aclue = html_cluealigned_new (NULL, 0, 0, flow->max_width, 100);
1202 html_clue_append (HTML_CLUE (flow), aclue);
1203 html_clue_append (HTML_CLUE (aclue), HTML_OBJECT (t));
1204 }
1205 } else
1206 g_assert_not_reached ();
1207
1208 html_undo_add_action (e->undo, e,
1209 html_undo_action_new ("Set table align", table_set_align_undo_action,
1210 HTML_UNDO_DATA (undo),
1211 html_cursor_get_position (e->cursor),
1212 html_cursor_get_position (e->cursor)), dir);
1213
1214 HTML_CLUE (HTML_OBJECT (t)->parent)->halign = align;
1215 html_object_change_set (HTML_OBJECT (t)->parent, HTML_CHANGE_ALL_CALC);
1216 html_engine_schedule_update (e);
1217 }
1218
1219 void
html_engine_table_set_align(HTMLEngine * e,HTMLTable * t,HTMLHAlignType align)1220 html_engine_table_set_align (HTMLEngine *e,
1221 HTMLTable *t,
1222 HTMLHAlignType align)
1223 {
1224 table_set_align (e, t, align, HTML_UNDO_UNDO);
1225 }
1226
1227 /*
1228 * width
1229 *
1230 */
1231
1232 static void table_set_width (HTMLEngine *e, HTMLTable *t, gint width, gboolean percent, HTMLUndoDirection dir);
1233
1234 static void
table_set_width_undo_action(HTMLEngine * e,HTMLUndoData * undo_data,HTMLUndoDirection dir,guint position_after)1235 table_set_width_undo_action (HTMLEngine *e,
1236 HTMLUndoData *undo_data,
1237 HTMLUndoDirection dir,
1238 guint position_after)
1239 {
1240 HTMLTableSetAttrUndo *data = (HTMLTableSetAttrUndo *) undo_data;
1241
1242 table_set_width (e, html_engine_get_table (e), data->attr.width.width, data->attr.width.percent,
1243 html_undo_direction_reverse (dir));
1244 }
1245
1246 static void
table_set_width(HTMLEngine * e,HTMLTable * t,gint width,gboolean percent,HTMLUndoDirection dir)1247 table_set_width (HTMLEngine *e,
1248 HTMLTable *t,
1249 gint width,
1250 gboolean percent,
1251 HTMLUndoDirection dir)
1252 {
1253 HTMLTableSetAttrUndo *undo;
1254
1255 undo = attr_undo_new (HTML_TABLE_WIDTH);
1256 undo->attr.width.width = HTML_OBJECT (t)->percent
1257 ? HTML_OBJECT (t)->percent
1258 : (HTML_OBJECT (t)->flags & HTML_OBJECT_FLAG_FIXEDWIDTH
1259 ? t->specified_width : 0);
1260 undo->attr.width.percent = HTML_OBJECT (t)->percent != 0;
1261 html_undo_add_action (e->undo, e,
1262 html_undo_action_new ("Set table width", table_set_width_undo_action,
1263 HTML_UNDO_DATA (undo),
1264 html_cursor_get_position (e->cursor),
1265 html_cursor_get_position (e->cursor)), dir);
1266
1267 if (percent) {
1268 HTML_OBJECT (t)->percent = width;
1269 HTML_OBJECT (t)->flags &= ~ HTML_OBJECT_FLAG_FIXEDWIDTH;
1270 t->specified_width = 0;
1271 } else {
1272 HTML_OBJECT (t)->percent = 0;
1273 t->specified_width = width;
1274 if (width)
1275 HTML_OBJECT (t)->flags |= HTML_OBJECT_FLAG_FIXEDWIDTH;
1276 else
1277 HTML_OBJECT (t)->flags &= ~ HTML_OBJECT_FLAG_FIXEDWIDTH;
1278 }
1279 html_object_change_set (HTML_OBJECT (t), HTML_CHANGE_ALL_CALC);
1280 html_engine_schedule_update (e);
1281 }
1282
1283 void
html_engine_table_set_width(HTMLEngine * e,HTMLTable * t,gint width,gboolean percent)1284 html_engine_table_set_width (HTMLEngine *e,
1285 HTMLTable *t,
1286 gint width,
1287 gboolean percent)
1288 {
1289 table_set_width (e, t, width, percent, HTML_UNDO_UNDO);
1290 }
1291
1292 /*
1293 * set number of columns in current table
1294 */
1295
1296 void
html_engine_table_set_cols(HTMLEngine * e,gint cols)1297 html_engine_table_set_cols (HTMLEngine *e,
1298 gint cols)
1299 {
1300 HTMLTable *table = html_engine_get_table (e);
1301
1302 if (!table)
1303 return;
1304
1305 if (table->totalCols == cols)
1306 return;
1307
1308 if (table->totalCols < cols) {
1309 gint n = cols - table->totalCols;
1310
1311 for (; n > 0; n--)
1312 html_table_insert_column (table, e, table->totalCols, NULL, HTML_UNDO_UNDO);
1313 } else {
1314 gint n = table->totalCols - cols;
1315
1316 for (; n > 0; n--)
1317 html_table_delete_column (table, e, table->totalCols - 1, HTML_UNDO_UNDO);
1318 }
1319 }
1320
1321 /*
1322 * set number of rows in current table
1323 */
1324
1325 void
html_engine_table_set_rows(HTMLEngine * e,gint rows)1326 html_engine_table_set_rows (HTMLEngine *e,
1327 gint rows)
1328 {
1329 HTMLTable *table = html_engine_get_table (e);
1330
1331 if (!table)
1332 return;
1333
1334 if (table->totalRows == rows)
1335 return;
1336
1337 if (table->totalRows < rows) {
1338 gint n = rows - table->totalRows;
1339
1340 for (; n > 0; n--)
1341 html_table_insert_row (table, e, table->totalRows, NULL, HTML_UNDO_UNDO);
1342 } else {
1343 gint n = table->totalRows - rows;
1344
1345 for (; n > 0; n--)
1346 html_table_delete_row (table, e, table->totalRows - 1, HTML_UNDO_UNDO);
1347 }
1348 }
1349
1350 void
html_engine_delete_table(HTMLEngine * e)1351 html_engine_delete_table (HTMLEngine *e)
1352 {
1353 HTMLTable *table;
1354
1355 html_engine_disable_selection (e);
1356
1357 table = html_engine_get_table (e);
1358
1359 if (!table)
1360 return;
1361 while (e->cursor->object != HTML_OBJECT (table) || e->cursor->offset)
1362 html_cursor_backward (e->cursor, e);
1363 html_engine_set_mark (e);
1364 html_cursor_end_of_line (e->cursor, e);
1365 html_engine_delete (e);
1366 }
1367