]> git.lyx.org Git - lyx.git/blob - src/TableLayout.C
Lots of fixes for text/tabular insets. Now tabular insets work quite good
[lyx.git] / src / TableLayout.C
1 #include <config.h>
2
3 #include <cstdlib>
4 #include FORMS_H_LOCATION
5
6 #include "layout_forms.h"
7 #include "lyx_main.h"
8 #include "lyxrc.h"
9 #include "LString.h"
10 #include "support/filetools.h"
11 #include "buffer.h"
12 #include "vspace.h"
13 #include "lyx_gui_misc.h"
14 #include "BufferView.h"
15 #include "gettext.h"
16 #include "lyxtext.h"
17 #include "layout.h"
18
19
20 // Prototypes
21 extern FD_form_table_options * fd_form_table_options;
22 extern FD_form_table_extra * fd_form_table_extra;
23 extern BufferView * current_view;
24
25 extern bool UpdateLayoutTabular(int);
26 extern void TabularOptionsCB(FL_OBJECT * ob, long l);
27 extern void SetPWidthTabularCB(FL_OBJECT * ob, long l);
28
29
30 static int Confirmed = false;
31 static int ActCell;
32
33 // hack to keep the cursor from jumping to the end of the text in the Extra
34 // form input fields during editing. The values in LyXTable itself is
35 // changed in real-time, but we have no callbacks for the input fields,
36 // so I simply store and restore the cursor position for now.
37 // (too much of a hazzle to do it proper; we'll trash all this code
38 // in 1.1 anyway)
39 static int extra_col_cursor_x; // need no y's, one-line input fields
40 static int extra_multicol_cursor_x;
41 // Joacim
42
43 #define IS_TABULAR  (current_view->the_locking_inset != 0)
44
45 bool UpdateLayoutTable(int flag)
46 {
47     bool update = true;
48     if (!current_view->available())
49         update = false;
50     
51     if (update && current_view->text->cursor.par->table) {
52         char buf[12];
53         string pwidth, special;
54    
55         LyXTable * table = current_view->text->cursor.par->table;
56
57         int cell = current_view->text->
58             NumberOfCell(current_view->text->cursor.par, 
59                          current_view->text->cursor.pos);
60         ActCell = cell;
61         int column = table->column_of_cell(cell)+1;
62         fl_set_object_label(fd_form_table_options->text_warning, "");
63         Confirmed = false;
64         fl_activate_object(fd_form_table_extra->input_special_alignment);
65         fl_activate_object(fd_form_table_extra->input_special_multialign);
66         fl_activate_object(fd_form_table_options->input_column_width);
67         sprintf(buf, "%d", column);
68         fl_set_input(fd_form_table_options->input_table_column, buf);
69         fl_deactivate_object(fd_form_table_options->input_table_column);
70         int row = table->row_of_cell(cell)+1;
71         sprintf(buf, "%d", row);
72         fl_set_input(fd_form_table_options->input_table_row, buf);
73         fl_deactivate_object(fd_form_table_options->input_table_row);
74         if (table->IsMultiColumn(cell))
75             fl_set_button(fd_form_table_options->radio_multicolumn, 1);
76         else
77             fl_set_button(fd_form_table_options->radio_multicolumn, 0);
78         if (table->RotateCell(cell))
79             fl_set_button(fd_form_table_options->radio_rotate_cell, 1);
80         else
81             fl_set_button(fd_form_table_options->radio_rotate_cell, 0);
82         if (table->TopLine(cell))
83             fl_set_button(fd_form_table_options->radio_border_top, 1);
84         else
85             fl_set_button(fd_form_table_options->radio_border_top, 0);
86         if (table->BottomLine(cell))
87             fl_set_button(fd_form_table_options->radio_border_bottom, 1);
88         else
89             fl_set_button(fd_form_table_options->radio_border_bottom, 0);
90         if (table->LeftLine(cell))
91             fl_set_button(fd_form_table_options->radio_border_left, 1);
92         else
93             fl_set_button(fd_form_table_options->radio_border_left, 0);
94         if (table->RightLine(cell))
95             fl_set_button(fd_form_table_options->radio_border_right, 1);
96         else
97             fl_set_button(fd_form_table_options->radio_border_right, 0);
98         int align = table->GetAlignment(cell);
99         fl_set_button(fd_form_table_options->radio_align_left, 0);
100         fl_set_button(fd_form_table_options->radio_align_right, 0);
101         fl_set_button(fd_form_table_options->radio_align_center, 0);
102         special = table->GetAlignSpecial(cell, LyXTable::SET_SPECIAL_COLUMN);
103         if (flag)
104         {
105             fl_set_input(fd_form_table_extra->input_special_alignment,
106                          special.c_str());
107             fl_set_input_cursorpos(fd_form_table_extra->input_special_alignment,
108                     extra_col_cursor_x, 0); // restore the cursor
109         }
110         if (current_view->buffer()->isReadonly()) 
111             fl_deactivate_object(fd_form_table_extra->input_special_alignment);
112         special = table->GetAlignSpecial(cell, LyXTable::SET_SPECIAL_MULTI);
113         if (flag)
114         {
115             fl_set_input(fd_form_table_extra->input_special_multialign,
116                          special.c_str());
117             fl_set_input_cursorpos(fd_form_table_extra->input_special_multialign,
118                     extra_multicol_cursor_x, 0); // restore the cursor
119         }
120         if (current_view->buffer()->isReadonly()) 
121             fl_deactivate_object(fd_form_table_extra->input_special_multialign);
122         pwidth = table->GetPWidth(cell);
123         if (flag)
124             fl_set_input(fd_form_table_options->input_column_width, pwidth.c_str());
125         if (current_view->buffer()->isReadonly()) 
126             fl_deactivate_object(fd_form_table_options->input_column_width);
127         if (!pwidth.empty()) {
128             fl_activate_object(fd_form_table_options->radio_linebreak_cell);
129             fl_set_object_lcol(fd_form_table_options->radio_linebreak_cell,
130                                FL_BLACK);
131             fl_set_button(fd_form_table_options->radio_linebreak_cell,
132                           table->Linebreaks(table->FirstVirtualCell(cell)));
133         } else {
134             fl_deactivate_object(fd_form_table_options->radio_linebreak_cell);
135             fl_set_object_lcol(fd_form_table_options->radio_linebreak_cell,
136                                FL_INACTIVE);
137             fl_set_button(fd_form_table_options->radio_linebreak_cell, 0);
138         }
139         if ((!pwidth.empty() && !table->IsMultiColumn(cell)) ||
140             (align == LYX_ALIGN_LEFT))
141             fl_set_button(fd_form_table_options->radio_align_left, 1);
142         else if (align == LYX_ALIGN_RIGHT)
143             fl_set_button(fd_form_table_options->radio_align_right, 1);
144         else
145             fl_set_button(fd_form_table_options->radio_align_center, 1);
146         if (!pwidth.empty() && !table->IsMultiColumn(cell)) {
147             fl_deactivate_object(fd_form_table_options->radio_align_left);
148             fl_deactivate_object(fd_form_table_options->radio_align_right);
149             fl_deactivate_object(fd_form_table_options->radio_align_center);
150             fl_set_object_lcol(fd_form_table_options->radio_align_left,
151                                FL_INACTIVE);
152             fl_set_object_lcol(fd_form_table_options->radio_align_right,
153                                FL_INACTIVE);
154             fl_set_object_lcol(fd_form_table_options->radio_align_center,
155                                FL_INACTIVE);
156         } else {
157             fl_activate_object(fd_form_table_options->radio_align_left);
158             fl_activate_object(fd_form_table_options->radio_align_right);
159             fl_activate_object(fd_form_table_options->radio_align_center);
160             fl_set_object_lcol(fd_form_table_options->radio_align_left,
161                                FL_BLACK);
162             fl_set_object_lcol(fd_form_table_options->radio_align_right,
163                                FL_BLACK);
164             fl_set_object_lcol(fd_form_table_options->radio_align_center,
165                                FL_BLACK);
166         }
167         fl_set_button(fd_form_table_options->radio_longtable, table->IsLongTable());
168         if (table->IsLongTable()) {
169             fl_activate_object(fd_form_table_options->radio_lt_firsthead);
170             fl_activate_object(fd_form_table_options->radio_lt_head);
171             fl_activate_object(fd_form_table_options->radio_lt_foot);
172             fl_activate_object(fd_form_table_options->radio_lt_lastfoot);
173             fl_activate_object(fd_form_table_options->radio_lt_newpage);
174             fl_set_object_lcol(fd_form_table_options->radio_lt_firsthead,
175                                FL_BLACK);
176             fl_set_object_lcol(fd_form_table_options->radio_lt_head,
177                                FL_BLACK);
178             fl_set_object_lcol(fd_form_table_options->radio_lt_foot,
179                                FL_BLACK);
180             fl_set_object_lcol(fd_form_table_options->radio_lt_lastfoot,
181                                FL_BLACK);
182             fl_set_object_lcol(fd_form_table_options->radio_lt_newpage,
183                                FL_BLACK);
184             fl_set_button(fd_form_table_options->radio_lt_firsthead,
185                           table->RowOfLTFirstHead(cell));
186             fl_set_button(fd_form_table_options->radio_lt_head,
187                           table->RowOfLTHead(cell));
188             fl_set_button(fd_form_table_options->radio_lt_foot,
189                           table->RowOfLTFoot(cell));
190             fl_set_button(fd_form_table_options->radio_lt_lastfoot,
191                           table->RowOfLTLastFoot(cell));
192             fl_set_button(fd_form_table_options->radio_lt_newpage,
193                           table->LTNewPage(cell));
194         } else {
195             fl_deactivate_object(fd_form_table_options->radio_lt_firsthead);
196             fl_deactivate_object(fd_form_table_options->radio_lt_head);
197             fl_deactivate_object(fd_form_table_options->radio_lt_foot);
198             fl_deactivate_object(fd_form_table_options->radio_lt_lastfoot);
199             fl_deactivate_object(fd_form_table_options->radio_lt_newpage);
200             fl_set_button(fd_form_table_options->radio_lt_firsthead, 0);
201             fl_set_button(fd_form_table_options->radio_lt_head, 0);
202             fl_set_button(fd_form_table_options->radio_lt_foot, 0);
203             fl_set_button(fd_form_table_options->radio_lt_lastfoot, 0);
204             fl_set_button(fd_form_table_options->radio_lt_newpage, 0);
205             fl_set_object_lcol(fd_form_table_options->radio_lt_firsthead,
206                                FL_INACTIVE);
207             fl_set_object_lcol(fd_form_table_options->radio_lt_head,
208                                FL_INACTIVE);
209             fl_set_object_lcol(fd_form_table_options->radio_lt_foot,
210                                FL_INACTIVE);
211             fl_set_object_lcol(fd_form_table_options->radio_lt_lastfoot,
212                                FL_INACTIVE);
213             fl_set_object_lcol(fd_form_table_options->radio_lt_newpage,
214                                FL_INACTIVE);
215         }
216         fl_set_button(fd_form_table_options->radio_rotate_table,
217                       table->RotateTable());
218         fl_set_focus_object(fd_form_table_options->form_table_options,
219                             fd_form_table_options->button_table_delete);
220     } else if (fd_form_table_options->form_table_options->visible) {
221         fl_set_focus_object(fd_form_table_options->form_table_options,
222                             fd_form_table_options->button_table_delete);
223         fl_hide_form(fd_form_table_options->form_table_options);
224     }
225     return update;
226 }
227
228
229 void OpenLayoutTableExtra()
230 {
231
232         if (fd_form_table_extra->form_table_extra->visible) {
233                 fl_raise_form(fd_form_table_extra->form_table_extra);
234         } else {
235                 static int ow = -1, oh;
236                 fl_show_form(fd_form_table_extra->form_table_extra,
237                              FL_PLACE_MOUSE | FL_FREE_SIZE, FL_FULLBORDER,
238                              _("Table Extra Form"));
239                 if (ow < 0) {
240                         ow = fd_form_table_extra->form_table_extra->w;
241                         oh = fd_form_table_extra->form_table_extra->h;
242                 }
243                 fl_set_form_minsize(fd_form_table_extra->form_table_extra,
244                                     ow, oh);
245         }
246 }
247
248 void MenuLayoutTable(int flag)
249 {
250     if (UpdateLayoutTable(flag)) {
251         if (fd_form_table_options->form_table_options->visible) {
252             fl_raise_form(fd_form_table_options->form_table_options);
253         }
254         else {
255             fl_show_form(fd_form_table_options->form_table_options,
256                          FL_PLACE_MOUSE, FL_FULLBORDER,
257                          _("Table Layout"));
258         }
259     }
260 }
261
262
263 void TableOptionsCB(FL_OBJECT * ob, long l)
264 {
265     if (IS_TABULAR) {
266         TabularOptionsCB(ob, l);
267         return;
268     }
269
270     LyXTable * table = 0;
271     int s, num = 0;
272     string special, str;
273
274     if (!current_view->available()
275         || !(table = current_view->text->cursor.par->table)) {
276         MenuLayoutTable(0);
277         return;
278       }
279     int cell = current_view->text->
280         NumberOfCell(current_view->text->cursor.par, 
281                      current_view->text->cursor.pos);
282     if (ActCell != cell) {
283         MenuLayoutTable(0);
284         fl_set_object_label(fd_form_table_options->text_warning,
285                             _("Warning: Wrong Cursor position, updated window"));
286         fl_show_object(fd_form_table_options->text_warning);
287         extra_col_cursor_x = 0; // would rather place it at the end, but...
288         extra_multicol_cursor_x = 0;
289         return;
290     }
291
292     // No point in processing directives that you can't do anything with
293     // anyhow, so exit now if the buffer is read-only.
294     if (current_view->buffer()->isReadonly()) {
295       MenuLayoutTable(0);
296       return;
297     }
298     
299     if (ob != fd_form_table_options->button_table_delete) {
300         fl_set_object_label(fd_form_table_options->text_warning, "");
301         Confirmed = false;
302     }
303     str = fl_get_input(fd_form_table_options->input_column_width);
304     if (!str.empty() && !isValidLength(str)) {
305         fl_set_object_label(fd_form_table_options->text_warning,
306                             _("Warning: Invalid Length (valid example: 10mm)"));
307         fl_show_object(fd_form_table_options->text_warning);
308         return;
309     }
310     if (((ob == fd_form_table_options->button_delete_row) && (table->rows<= 1)) ||
311         ((ob == fd_form_table_options->button_delete_column) && (table->columns<= 1)))
312         ob = fd_form_table_options->button_table_delete;
313     if (ob == fd_form_table_options->button_append_row)
314         num = LyXTable::APPEND_ROW;
315     else if (ob == fd_form_table_options->button_append_column)
316         num = LyXTable::APPEND_COLUMN;
317     else if (ob == fd_form_table_options->button_delete_row)
318         num = LyXTable::DELETE_ROW;
319     else if (ob == fd_form_table_options->button_delete_column)
320         num = LyXTable::DELETE_COLUMN;
321     else if (ob == fd_form_table_options->button_set_borders)
322         num = LyXTable::SET_ALL_LINES;
323     else if (ob == fd_form_table_options->button_unset_borders)
324         num = LyXTable::UNSET_ALL_LINES;
325     else if (ob == fd_form_table_options->radio_border_top)
326         num = LyXTable::TOGGLE_LINE_TOP;
327     else if (ob == fd_form_table_options->radio_border_bottom)
328         num = LyXTable::TOGGLE_LINE_BOTTOM;
329     else if (ob == fd_form_table_options->radio_border_left)
330         num = LyXTable::TOGGLE_LINE_LEFT;
331     else if (ob == fd_form_table_options->radio_border_right)
332         num = LyXTable::TOGGLE_LINE_RIGHT;
333     else if (ob == fd_form_table_options->radio_align_left)
334         num = LyXTable::ALIGN_LEFT;
335     else if (ob == fd_form_table_options->radio_align_right)
336         num = LyXTable::ALIGN_RIGHT;
337     else if (ob == fd_form_table_options->radio_align_center)
338         num = LyXTable::ALIGN_CENTER;
339     else if ((ob == fd_form_table_options->button_table_delete) && !Confirmed) {
340         fl_set_object_label(fd_form_table_options->text_warning,
341                             _("Confirm: press Delete-Button again"));
342         Confirmed = true;
343         return;
344     } else if ((ob == fd_form_table_options->button_table_delete) 
345                && Confirmed) {
346         num = LyXTable::DELETE_TABLE;
347         Confirmed = false;
348     } else if (ob == fd_form_table_options->radio_multicolumn)
349         num = LyXTable::MULTICOLUMN;
350     else if (ob == fd_form_table_options->radio_longtable) {
351         s = fl_get_button(fd_form_table_options->radio_longtable);
352         if (s) {
353             num = LyXTable::SET_LONGTABLE;
354             fl_activate_object(fd_form_table_options->radio_lt_firsthead);
355             fl_activate_object(fd_form_table_options->radio_lt_head);
356             fl_activate_object(fd_form_table_options->radio_lt_foot);
357             fl_activate_object(fd_form_table_options->radio_lt_lastfoot);
358             fl_activate_object(fd_form_table_options->radio_lt_newpage);
359             fl_set_button(fd_form_table_options->radio_lt_firsthead,
360                           table->RowOfLTFirstHead(cell));
361             fl_set_button(fd_form_table_options->radio_lt_head,
362                           table->RowOfLTHead(cell));
363             fl_set_button(fd_form_table_options->radio_lt_foot,
364                           table->RowOfLTFoot(cell));
365             fl_set_button(fd_form_table_options->radio_lt_lastfoot,
366                           table->RowOfLTLastFoot(cell));
367             fl_set_button(fd_form_table_options->radio_lt_firsthead,
368                           table->LTNewPage(cell));
369         } else {
370             num = LyXTable::UNSET_LONGTABLE;
371             fl_deactivate_object(fd_form_table_options->radio_lt_firsthead);
372             fl_deactivate_object(fd_form_table_options->radio_lt_head);
373             fl_deactivate_object(fd_form_table_options->radio_lt_foot);
374             fl_deactivate_object(fd_form_table_options->radio_lt_lastfoot);
375             fl_deactivate_object(fd_form_table_options->radio_lt_newpage);
376             fl_set_button(fd_form_table_options->radio_lt_firsthead, 0);
377             fl_set_button(fd_form_table_options->radio_lt_firsthead, 0);
378             fl_set_button(fd_form_table_options->radio_lt_firsthead, 0);
379             fl_set_button(fd_form_table_options->radio_lt_firsthead, 0);
380             fl_set_button(fd_form_table_options->radio_lt_firsthead, 0);
381             fl_set_object_lcol(fd_form_table_options->radio_lt_firsthead,
382                                FL_INACTIVE);
383             fl_set_object_lcol(fd_form_table_options->radio_lt_head,
384                                FL_INACTIVE);
385             fl_set_object_lcol(fd_form_table_options->radio_lt_foot,
386                                FL_INACTIVE);
387             fl_set_object_lcol(fd_form_table_options->radio_lt_lastfoot,
388                                FL_INACTIVE);
389             fl_set_object_lcol(fd_form_table_options->radio_lt_newpage,
390                                FL_INACTIVE);
391         }
392     } else if (ob == fd_form_table_options->radio_rotate_table) {
393         s = fl_get_button(fd_form_table_options->radio_rotate_table);
394         if (s)
395             num = LyXTable::SET_ROTATE_TABLE;
396         else
397             num = LyXTable::UNSET_ROTATE_TABLE;
398     } else if (ob == fd_form_table_options->radio_rotate_cell) {
399         s = fl_get_button(fd_form_table_options->radio_rotate_cell);
400         if (s)
401             num = LyXTable::SET_ROTATE_CELL;
402         else
403             num = LyXTable::UNSET_ROTATE_CELL;
404     } else if (ob == fd_form_table_options->radio_linebreak_cell) {
405         num = LyXTable::SET_LINEBREAKS;
406     } else if (ob == fd_form_table_options->radio_lt_firsthead) {
407         num = LyXTable::SET_LTFIRSTHEAD;
408     } else if (ob == fd_form_table_options->radio_lt_head) {
409         num = LyXTable::SET_LTHEAD;
410     } else if (ob == fd_form_table_options->radio_lt_foot) {
411         num = LyXTable::SET_LTFOOT;
412     } else if (ob == fd_form_table_options->radio_lt_lastfoot) {
413         num = LyXTable::SET_LTLASTFOOT;
414     } else if (ob == fd_form_table_options->radio_lt_newpage) {
415         num = LyXTable::SET_LTNEWPAGE;
416     } else if (ob == fd_form_table_options->button_table_extra) {
417         OpenLayoutTableExtra();
418         return;
419     } else if (ob == fd_form_table_extra->input_special_alignment) {
420         special = fl_get_input(fd_form_table_extra->input_special_alignment);
421         int dummy;
422         fl_get_input_cursorpos(ob, &extra_col_cursor_x, &dummy);
423         num = LyXTable::SET_SPECIAL_COLUMN;
424     } else if (ob == fd_form_table_extra->input_special_multialign) {
425         special = fl_get_input(fd_form_table_extra->input_special_multialign);
426         int dummy;
427         fl_get_input_cursorpos(ob, &extra_multicol_cursor_x, &dummy);
428         num = LyXTable::SET_SPECIAL_MULTI;
429     } else
430         return;
431     if (current_view->available()) {
432         current_view->hideCursor();
433         if (!current_view->text->selection){
434             current_view->beforeChange();
435             current_view->update(-2);
436         }
437         if ((num == LyXTable::SET_SPECIAL_COLUMN) ||
438             (num == LyXTable::SET_SPECIAL_MULTI))
439             current_view->text->TableFeatures(num, special);
440         else
441             current_view->text->TableFeatures(num);
442         current_view->update(1);
443     }
444     if (num == LyXTable::DELETE_TABLE) {
445         fl_set_focus_object(fd_form_table_options->form_table_options,
446                             fd_form_table_options->button_table_delete);
447         fl_hide_form(fd_form_table_options->form_table_options);
448     } else
449         UpdateLayoutTable(true);
450     return;
451 }
452
453
454 void TableOptCloseCB(FL_OBJECT *, long)
455 {
456     fl_set_focus_object(fd_form_table_options->form_table_options,
457                         fd_form_table_options->button_table_delete);
458     fl_hide_form(fd_form_table_options->form_table_options);
459     return;
460 }
461
462 void TableSpeCloseCB(FL_OBJECT *, long)
463 {
464     fl_set_focus_object(fd_form_table_options->form_table_options,
465                         fd_form_table_options->button_table_delete);
466     fl_hide_form(fd_form_table_extra->form_table_extra);
467     return;
468 }
469
470 void SetPWidthCB(FL_OBJECT * ob, long l)
471 {
472     if (IS_TABULAR) {
473         SetPWidthTabularCB(ob, l);
474         return;
475     }
476
477     fl_set_object_label(fd_form_table_options->text_warning, "");
478     Confirmed = false;
479     if (ob == fd_form_table_options->input_column_width) {
480         string str = fl_get_input(ob);
481         if (!str.empty() && !isValidLength(str)) {
482             fl_set_object_label(fd_form_table_options->text_warning,
483                            _("Warning: Invalid Length (valid example: 10mm)"));
484             fl_show_object(fd_form_table_options->text_warning);
485             return;
486         }
487         if (current_view->available()){
488             current_view->hideCursor();
489             if (!current_view->text->selection) {
490                 current_view->beforeChange(); 
491                 current_view->update(-2);
492             }
493             current_view->text->TableFeatures(LyXTable::SET_PWIDTH, str);
494             current_view->update(1);
495         }
496         MenuLayoutTable(0); // update for alignment
497     }
498 }