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