home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / lyx-0.13.2.tar.gz / lyx-0.13.2.tar / lyx-0.13.2 / src / table.C < prev    next >
C/C++ Source or Header  |  1998-04-23  |  44KB  |  1,620 lines

  1. /* This file is part of
  2.  * ======================================================
  3.  * 
  4.  *           LyX, The Document Processor
  5.  *      
  6.  *      Copyright (C) 1995 Matthias Ettrich
  7.  *        Copyright (C) 1995-1998 The LyX Team.
  8.  *
  9.  *======================================================
  10.  */
  11.  
  12. #include <stdlib.h>
  13. #include "table.h"
  14. #include "vspace.h"
  15. #include "layout.h"
  16.  
  17. //     $Id: table.C,v 1.1.1.1 1998/04/23 16:02:57 larsbj Exp $    
  18.  
  19. #if !defined(lint) && !defined(WITH_WARNINGS)
  20. static char vcid[] = "$Id: table.C,v 1.1.1.1 1998/04/23 16:02:57 larsbj Exp $";
  21. #endif /* lint */
  22.  
  23. #ifdef __GNUG__
  24. #pragma implementation
  25. #endif
  26.  
  27. #define WIDTH_OF_LINE 5
  28.  
  29. /* konstruktor */
  30. LyXTable::LyXTable(int rows_arg, int columns_arg)
  31. {
  32.     Init(rows_arg, columns_arg);
  33. }
  34.  
  35.  
  36. LyXTable::LyXTable(LyXLex &lex)
  37. {
  38.     FILE *file = lex.getFile();
  39.     Read(file);
  40. }
  41.  
  42.  
  43. LyXTable::~LyXTable() {
  44.     int i;
  45.     delete[] rowofcell;
  46.     delete[] columnofcell;
  47.     delete[] column_info;
  48.         delete[] row_info;
  49.     for (i=0; i<rows; i++) {
  50.         delete[] cell_info[i]; // verify that this shoudn't be freed with delete
  51.     }
  52.     delete[] cell_info;
  53. }
  54.  
  55.  
  56. LyXTable* LyXTable::Clone()
  57. {
  58.     LyXTable *result = new LyXTable(rows, columns);
  59.     int row, column;;
  60.  
  61.     for (row=0; row<rows; row++){
  62.         for (column=0; column<columns;column++){
  63.             result->cell_info[row][column] = cell_info[row][column];
  64.         }
  65.     }
  66.  
  67.     for (row=0; row<rows; row++){
  68.         result->row_info[row] = row_info[row];
  69.     }
  70.  
  71.     for (column=0; column<columns; column++){
  72.         result->column_info[column].left_line = column_info[column].left_line;
  73.         result->column_info[column].right_line = column_info[column].right_line;
  74.         result->column_info[column].alignment = column_info[column].alignment;
  75.         result->column_info[column].p_width = column_info[column].p_width;
  76.     }
  77.   
  78.     result->SetLongTable(is_long_table);
  79.     result->rotate=rotate;
  80.     result->Reinit();
  81.     return result;
  82. }
  83.  
  84.  
  85. /* activates all lines and sets all widths to 0 */ 
  86. void LyXTable::Init(int rows_arg, int columns_arg)
  87. {
  88.     int i,j,cellno;
  89.     rows = rows_arg;
  90.     columns = columns_arg;
  91.     column_info = new columnstruct[columns];
  92.     row_info = new rowstruct[rows];
  93.     cell_info = new cellstruct*[rows];
  94.  
  95.     cellno = 0;
  96.     for (i=0; i<rows;i++) {
  97.         cell_info[i] = new cellstruct[columns];
  98.         row_info[i].top_line = true;
  99.         row_info[i].bottom_line = false;
  100.         row_info[i].is_cont_row = false;
  101.         row_info[i].newpage = false;
  102.         for (j=0; j<columns; j++) {
  103.             cell_info[i][j].cellno = cellno++;
  104.             cell_info[i][j].width_of_cell = 0;
  105.             cell_info[i][j].multicolumn = LyXTable::CELL_NORMAL;
  106.             cell_info[i][j].alignment = LYX_ALIGN_CENTER;
  107.             cell_info[i][j].top_line = row_info[i].top_line;
  108.             cell_info[i][j].bottom_line = row_info[i].bottom_line;
  109.             cell_info[i][j].has_cont_row = false;
  110.             cell_info[i][j].rotate = false;
  111.             cell_info[i][j].linebreaks = false;
  112.         }
  113.     }
  114.     row_info[i-1].bottom_line = true;
  115.     row_info[0].bottom_line = true;
  116.  
  117.     for (i=0; i<columns;i++) {
  118.         column_info[i].left_line = true;
  119.         column_info[i].right_line = false;
  120.         column_info[i].alignment = LYX_ALIGN_CENTER;
  121.         // set width_of_column to zero before it is used in
  122.         // calculate_width_of_column() (thornley)
  123.         column_info[i].width_of_column = 0;
  124.         calculate_width_of_column(i);
  125.     }
  126.     column_info[i-1].right_line = true;
  127.    
  128.     calculate_width_of_table();
  129.  
  130.     rowofcell = NULL;
  131.     columnofcell = NULL;
  132.     set_row_column_number_info();
  133.     is_long_table = false;
  134.     rotate = 0;
  135.     endhead = -1;
  136.     endfirsthead = -1;
  137.     endfoot = -1;
  138.     endlastfoot = -1;
  139. }
  140.  
  141.  
  142. void LyXTable::AppendRow(int cell)
  143. {
  144.     int row = row_of_cell(cell);
  145.     rowstruct *row_info2 = new rowstruct[rows+1];
  146.     cellstruct** cell_info2 = new cellstruct*[rows+1];
  147.     int i;
  148.  
  149.     for (i=0; i <= row; i++) {
  150.         cell_info2[i] = cell_info[i];
  151.         row_info2[i] = row_info[i];
  152.     }
  153.     for (i=rows-1; i >= row; i--) {
  154.         cell_info2[i+1] = cell_info[i];
  155.         row_info2[i+1] = row_info[i];
  156.     }
  157.     for (i=row;row_info[i].is_cont_row;i--);
  158.     if (((row+1)>=rows) || !row_info[row+1].is_cont_row)
  159.         row_info2[row+1].is_cont_row = false;
  160.     row_info2[row+1].top_line = row_info[i].top_line;
  161.     cell_info2[row+1] = new cellstruct[columns];
  162.     for (i=0; i<columns; i++) {
  163.         cell_info2[row+1][i].width_of_cell = 0;
  164.         cell_info2[row+1][i] = cell_info2[row][i];
  165.     }
  166.    
  167.     delete[] cell_info;
  168.     cell_info = cell_info2;
  169.     delete[] row_info;
  170.     row_info = row_info2;
  171.    
  172.     rows++;
  173.    
  174.     Reinit();
  175. }
  176.  
  177.  
  178. void LyXTable::DeleteRow(int cell)
  179. {
  180.     int row = row_of_cell(cell);
  181.         while(!row_info[row].is_cont_row && RowHasContRow(cell))
  182.             DeleteRow(cell_info[row+1][0].cellno);
  183.         rowstruct *row_info2 = new rowstruct[rows-1];
  184.     cellstruct** cell_info2 = new cellstruct*[rows-1];
  185.     int i;
  186.  
  187.     delete[] cell_info[row];
  188.     for (i=0; i < row; i++) {
  189.         cell_info2[i] = cell_info[i];
  190.                 row_info2[i] = row_info[i];
  191.     }
  192.         if (row_info[i].is_cont_row)
  193.             row_info2[i-1].bottom_line = row_info[i].bottom_line;
  194.     for (i=row; i < rows - 1; i++) {
  195.         cell_info2[i] = cell_info[i+1];
  196.                 row_info2[i] = row_info[i+1];
  197.     }
  198.    
  199.  
  200.     delete[] cell_info;
  201.     cell_info = cell_info2;
  202.         delete[] row_info;
  203.         row_info = row_info2;
  204.    
  205.     rows--;
  206.  
  207.     Reinit();
  208. }
  209.  
  210.  
  211. void LyXTable::AppendColumn(int cell)
  212. {
  213.     int i,j;
  214.     columnstruct *column_info2 = new columnstruct[columns+1];
  215.     int column = right_column_of_cell(cell);
  216.    
  217.     for (i=0; i<=column; i++){
  218.         column_info2[i] = column_info[i];
  219.     }
  220.     for (i=columns-1; i>=column; i--){
  221.         column_info2[i+1] = column_info[i];
  222.     }
  223.     
  224.     delete[] column_info;
  225.     column_info = column_info2;
  226.     
  227.     for (i=0; i<rows;i++){
  228.         cellstruct* tmp = cell_info[i];
  229.         cell_info[i] = new cellstruct[columns+1];
  230.         for (j=0; j<=column; j++){
  231.             cell_info[i][j]=tmp[j];
  232.         }
  233.         for (j=column; j<columns; j++){
  234.             cell_info[i][j+1]=tmp[j];
  235.         }
  236.         // care about multicolumns
  237.         if (cell_info[i][column+1].multicolumn
  238.             ==LyXTable::CELL_BEGIN_OF_MULTICOLUMN){
  239.             cell_info[i][column+1].multicolumn =
  240.                 LyXTable::CELL_PART_OF_MULTICOLUMN;
  241.         }
  242.         if (column + 1 == columns
  243.             || cell_info[i][column+2].multicolumn
  244.             !=LyXTable::CELL_PART_OF_MULTICOLUMN){
  245.             cell_info[i][column+1].multicolumn =
  246.                 LyXTable::CELL_NORMAL;
  247.         }
  248.         
  249.         delete[] tmp;
  250.     }
  251.     
  252.     columns++;
  253.     Reinit();
  254. }
  255.  
  256.  
  257. void LyXTable::Reinit()
  258. {   
  259.     int i,j;
  260.  
  261.     for (i=0; i<rows;i++) {
  262.         for (j=0; j<columns; j++) {
  263.             cell_info[i][j].width_of_cell = 0;
  264.                         if ((i+1 < rows) && !row_info[i+1].is_cont_row)
  265.                             cell_info[i][j].has_cont_row = false;
  266.         }
  267.     }
  268.   
  269.     for (i=0; i<columns;i++) {
  270.         calculate_width_of_column(i);
  271.     }
  272.     calculate_width_of_table();
  273.  
  274.     set_row_column_number_info();
  275. }
  276.  
  277.  
  278. void LyXTable::set_row_column_number_info()
  279. {
  280.     int row = 0;
  281.     int c= 0;
  282.     int column = 0;
  283.     numberofcells = 0;
  284.     for (row=0; row<rows; row++){
  285.         for (column=0; column<columns; column++){
  286.                         cell_info[row][column].cellno = numberofcells;
  287.             if (cell_info[row][column].multicolumn
  288.                 != LyXTable::CELL_PART_OF_MULTICOLUMN)
  289.                 numberofcells++;
  290.         }
  291.     }
  292.     row = 0;
  293.     column = 0;
  294.  
  295.     if (rowofcell)
  296.         delete [] rowofcell;
  297.     rowofcell = new int[numberofcells];
  298.     if (columnofcell)
  299.         delete [] columnofcell;
  300.     columnofcell = new int[numberofcells];
  301.   
  302.     while (c < numberofcells && row < rows && column < columns) {
  303.         rowofcell[c]=row;
  304.         columnofcell[c]=column;
  305.         c++;
  306.         do{
  307.             column++;
  308.         } while (column < columns &&
  309.              cell_info[row][column].multicolumn
  310.              == LyXTable::CELL_PART_OF_MULTICOLUMN);
  311.         if (column == columns){
  312.             column = 0;
  313.             row++;
  314.         }
  315.     }
  316. }
  317.  
  318.  
  319. void LyXTable::DeleteColumn(int cell)
  320. {
  321.     int column1 = column_of_cell(cell);
  322.     int column2 = right_column_of_cell(cell);
  323.     int column;
  324.    
  325.     if (column1 == 0 && column2 == columns - 1)
  326.         return;
  327.    
  328.     for (column = column1; column <= column2;column++){
  329.         delete_column(column1);
  330.     }
  331.     Reinit();
  332. }
  333.  
  334.  
  335. int LyXTable::GetNumberOfCells()
  336. {
  337.     return numberofcells;
  338. }
  339.  
  340.  
  341. int LyXTable::NumberOfCellsInRow(int cell)
  342. {
  343.     int row = row_of_cell(cell);
  344.     int i=0;
  345.     int result = 0;
  346.     for (i=0; i<columns; i++){
  347.         if (cell_info[row][i].multicolumn != LyXTable::CELL_PART_OF_MULTICOLUMN)
  348.             result++;
  349.     }
  350.     return result;
  351. }
  352.  
  353.  
  354. int LyXTable::AppendCellAfterCell(int append_cell, int question_cell)
  355. {
  356.     return (right_column_of_cell(append_cell) == 
  357.         right_column_of_cell(question_cell));
  358. }
  359.  
  360.  
  361. int LyXTable::DeleteCellIfColumnIsDeleted(int cell, int delete_column_cell)
  362. {
  363.     if (column_of_cell(delete_column_cell) == 0 && 
  364.         right_column_of_cell(delete_column_cell) == columns - 1)
  365.         return 0;
  366.     else
  367.         return
  368.             (column_of_cell(cell) >= column_of_cell(delete_column_cell) &&
  369.              column_of_cell(cell) <= right_column_of_cell(delete_column_cell));
  370. }
  371.  
  372.  
  373. /* returns 1 if there is a topline, returns 0 if not */ 
  374. bool LyXTable::TopLine(int cell)
  375. {
  376.     int row=row_of_cell(cell);
  377.     
  378.     if (IsContRow(cell))
  379.         return TopLine(cell_info[row-1][column_of_cell(cell)].cellno);
  380.     if (IsMultiColumn(cell))
  381.         return cellinfo_of_cell(cell)->top_line;
  382.     return row_info[row].top_line;
  383. }
  384.  
  385.  
  386. bool LyXTable::BottomLine(int cell)
  387. {
  388.     int row=row_of_cell(cell);
  389.     
  390.     if (RowHasContRow(cell))
  391.         return BottomLine(cell_info[row+1][column_of_cell(cell)].cellno);
  392.     if (IsMultiColumn(cell))
  393.         return cellinfo_of_cell(cell)->bottom_line;
  394.     return row_info[row_of_cell(cell)].bottom_line;
  395. }
  396.  
  397.  
  398. bool LyXTable::LeftLine(int cell)
  399. {
  400.     return column_info[column_of_cell(cell)].left_line;
  401. }
  402.  
  403. bool LyXTable::RightLine(int cell)
  404. {
  405.     return column_info[right_column_of_cell(cell)].right_line;
  406. }
  407.  
  408.  
  409. bool LyXTable::TopAlreadyDrawed(int cell)
  410. {
  411.     if (AdditionalHeight(cell))
  412.         return false;
  413.     int row = row_of_cell(cell);
  414.     if (row > 0){
  415.         int column = column_of_cell(cell);
  416.         while (column
  417.                && cell_info[row-1][column].multicolumn
  418.                == LyXTable::CELL_PART_OF_MULTICOLUMN)
  419.             column--;
  420.         if (cell_info[row-1][column].multicolumn
  421.             == LyXTable::CELL_NORMAL)
  422.             return row_info[row-1].bottom_line;
  423.         else
  424.             return cell_info[row-1][column].bottom_line;
  425.     }
  426.     return false;
  427. }
  428.  
  429.  
  430. bool LyXTable::VeryLastRow(int cell)
  431. {
  432.     return (row_of_cell(cell) == rows-1);
  433. }
  434.  
  435.  
  436. int LyXTable::AdditionalHeight(int cell)
  437. {
  438.     int row = row_of_cell(cell);
  439.     int top = 1;
  440.     int bottom = 1;
  441.     int column;
  442.     if (row){
  443.         for (column=0;column < columns-1 && bottom;column++){
  444.             switch (cell_info[row-1][column].multicolumn){
  445.             case LyXTable::CELL_BEGIN_OF_MULTICOLUMN:
  446.                 bottom = cell_info[row-1][column].bottom_line;
  447.                 break;
  448.             case LyXTable::CELL_NORMAL:
  449.                 bottom = row_info[row-1].bottom_line;
  450.             }
  451.         }
  452.         for (column=0;column < columns-1 && top;column++){
  453.             switch (cell_info[row][column].multicolumn){
  454.             case LyXTable::CELL_BEGIN_OF_MULTICOLUMN:
  455.                 top = cell_info[row][column].top_line;
  456.                 break;
  457.             case LyXTable::CELL_NORMAL:
  458.                 top = row_info[row].top_line;
  459.             }
  460.         }
  461.         if (top && bottom)
  462.             return WIDTH_OF_LINE;
  463.     }
  464.     return 0;
  465. }
  466.  
  467.  
  468. int LyXTable::AdditionalWidth(int cell)
  469. {
  470.     // internally already set in SetWidthOfCell
  471.     // used to get it back in text.C
  472.     int col = right_column_of_cell(cell);
  473.     if (col < columns - 1 && column_info[col].right_line &&
  474.             column_info[col+1].left_line)
  475.         return WIDTH_OF_LINE;
  476.     else
  477.         return 0;
  478. }
  479.  
  480.  
  481. // returns the maximum over all rows 
  482. int LyXTable::WidthOfColumn(int cell)
  483. {
  484.     int column1 = column_of_cell(cell);
  485.     int column2 = right_column_of_cell(cell);
  486.     int i;
  487.     int result=0;
  488.     for (i=column1; i<=column2;i++){
  489.         result += column_info[i].width_of_column;
  490.     }
  491.     return result;
  492. }
  493.  
  494.  
  495. int LyXTable::WidthOfTable()
  496. {
  497.     return width_of_table;
  498. }
  499.  
  500. /* returns 1 if a complete update is necessary, otherwise 0 */ 
  501. bool LyXTable::SetWidthOfMulticolCell(int cell, int new_width)
  502. {
  503.     int row = row_of_cell(cell);
  504.     int column1 = column_of_cell(cell);
  505.     int tmp=0;
  506.     int i;
  507.     int width=0;
  508.  
  509.     if (!IsMultiColumn(cell))
  510.         return 0;
  511.     
  512.     int column2 = right_column_of_cell(cell);
  513.     // first set columns to 0 so we can calculate the right width
  514.     for (i=column1; i<=column2;i++) {
  515.         cell_info[row][i].width_of_cell = 0;
  516.         tmp+=calculate_width_of_column(i);
  517.     }
  518.     // set the width to MAX_WIDTH until width > 0
  519.     width = (new_width + 2*WIDTH_OF_LINE);
  520.     for (i=column1; (i<column2) && (width > 0);i++){
  521.         cell_info[row][i].width_of_cell = column_info[i].width_of_column;
  522.         width -= column_info[i].width_of_column;
  523.         tmp += calculate_width_of_column(i);
  524.     }
  525.     if (i==column2) {
  526.         cell_info[row][i].width_of_cell = width;
  527.         if (column_info[i].right_line && (i < columns-1) &&
  528.             column_info[i+1].left_line) // additional width
  529.             cell_info[row][i].width_of_cell += WIDTH_OF_LINE;
  530.         tmp += calculate_width_of_column(i);
  531.     }
  532.     return tmp;
  533. }
  534.  
  535. /* returns 1 if a complete update is necessary, otherwise 0 */ 
  536. bool LyXTable::SetWidthOfCell(int cell, int new_width)
  537. {
  538.     int row = row_of_cell(cell);
  539.     int column1 = column_of_cell(cell);
  540.     int tmp=0;
  541.     int i;
  542.     int width=0;
  543.  
  544.     if (IsMultiColumn(cell)) {
  545.         tmp = SetWidthOfMulticolCell(cell, new_width);
  546.     } else {
  547.     width = (new_width + 2*WIDTH_OF_LINE);
  548.         i=column1;
  549.         cell_info[row][i].width_of_cell = width;
  550.         if (column_info[i].right_line && (i < columns-1) &&
  551.             column_info[i+1].left_line) // additional width
  552.             cell_info[row][i].width_of_cell += WIDTH_OF_LINE;
  553.         tmp += calculate_width_of_column(i);
  554.     }
  555.     if (tmp){
  556.         for(i=0; i<GetNumberOfCells(); i++)
  557.             SetWidthOfMulticolCell(i,GetWidthOfCell(i)-(2*WIDTH_OF_LINE));
  558.         calculate_width_of_table();
  559.         return true;
  560.     }
  561.     else
  562.         return false;
  563. }
  564.  
  565.  
  566. bool LyXTable::SetAlignment(int cell, char align)
  567. {
  568.     if (!IsMultiColumn(cell))
  569.         column_info[column_of_cell(cell)].alignment = align;
  570.     cellinfo_of_cell(cell)->alignment = align;
  571.     return true;
  572. }
  573.  
  574. bool LyXTable::SetPWidth(int cell, LString width)
  575. {
  576.         column_info[column_of_cell(cell)].p_width = width;
  577.         if (!IsMultiColumn(cell))
  578.             SetAlignment(cell,LYX_ALIGN_LEFT);
  579.     return true;
  580. }
  581.  
  582. bool LyXTable::SetAllLines(int cell, bool line)
  583. {
  584.     SetTopLine(cell,line);
  585.     SetBottomLine(cell,line);
  586.     SetRightLine(cell,line);
  587.     SetLeftLine(cell,line);
  588.     return true;
  589. }
  590.  
  591. bool LyXTable::SetTopLine(int cell, bool line)
  592. {
  593.     int row = row_of_cell(cell);
  594.  
  595.     if (IsContRow(cell))
  596.         SetTopLine(cell_info[row-1][column_of_cell(cell)].cellno,line);
  597.     else if (!IsMultiColumn(cell))
  598.         row_info[row].top_line = line;
  599.     else
  600.         cellinfo_of_cell(cell)->top_line = line;
  601.     return true;
  602. }
  603.  
  604.  
  605. bool LyXTable::SetBottomLine(int cell, bool line)
  606. {
  607.     int row = row_of_cell(cell);
  608.  
  609.     if (RowHasContRow(cell))
  610.         SetBottomLine(cell_info[row+1][column_of_cell(cell)].cellno,line);
  611.     else if (!IsMultiColumn(cell))
  612.         row_info[row_of_cell(cell)].bottom_line = line;
  613.     else
  614.         cellinfo_of_cell(cell)->bottom_line = line;
  615.     return true;
  616. }
  617.  
  618.  
  619. bool LyXTable::SetLeftLine(int cell, bool line)
  620. {
  621.     column_info[column_of_cell(cell)].left_line = line;
  622.     return true;
  623. }
  624.  
  625.  
  626. bool LyXTable::SetRightLine(int cell, bool line)
  627. {
  628.     column_info[right_column_of_cell(cell)].right_line = line;
  629.     return true;
  630. }
  631.  
  632.  
  633. char LyXTable::GetAlignment(int cell)
  634. {
  635.     if (IsMultiColumn(cell))
  636.         return cellinfo_of_cell(cell)->alignment;
  637.     else
  638.         return column_info[column_of_cell(cell)].alignment;
  639. }
  640.  
  641. LString LyXTable::GetPWidth(int cell)
  642. {
  643.     return column_info[column_of_cell(cell)].p_width;
  644. }
  645.  
  646. int LyXTable::GetWidthOfCell(int cell)
  647. {
  648.     int row = row_of_cell(cell);
  649.     int column1 = column_of_cell(cell);
  650.     int column2 = right_column_of_cell(cell);
  651.     int i;
  652.     int result=0;
  653.     for (i=column1; i<=column2;i++){
  654.         result += cell_info[row][i].width_of_cell;
  655.     }
  656.   
  657.     result += AdditionalWidth(cell);
  658.   
  659.     return result;
  660. }
  661.  
  662.  
  663. int LyXTable::GetBeginningOfTextInCell(int cell)
  664. {
  665.     int x = 0;
  666.    
  667.     switch (GetAlignment(cell)){
  668.     case LYX_ALIGN_CENTER:
  669.         x += (WidthOfColumn(cell) - GetWidthOfCell(cell)) / 2;
  670.         break;
  671.     case LYX_ALIGN_RIGHT:
  672.         x += WidthOfColumn(cell) - GetWidthOfCell(cell) + AdditionalWidth(cell);
  673.         break;
  674.     default: /* LYX_ALIGN_LEFT: nothing :-) */ 
  675.         break;
  676.     }
  677.  
  678.     // the LaTeX Way :-(
  679.     x += WIDTH_OF_LINE;
  680.     return x;
  681. }
  682.  
  683.  
  684. bool LyXTable::IsFirstCell(int cell)
  685. {
  686.     return (column_of_cell(cell) == 0);
  687. }
  688.  
  689. bool LyXTable::IsLastCell(int cell)
  690. {
  691.     return (right_column_of_cell(cell) == (columns-1));
  692. }
  693.  
  694.  
  695. bool LyXTable::calculate_width_of_column(int column)
  696. {
  697.     int i, max;
  698.     int old_column_width = column_info[column].width_of_column;
  699.     max = 0;
  700.     for (i=0; i<rows; i++) {
  701.         if (cell_info[i][column].width_of_cell > max) {
  702.             max = cell_info[i][column].width_of_cell;
  703.         }
  704.     }
  705.     column_info[column].width_of_column = max;
  706.     return (column_info[column].width_of_column != old_column_width);
  707. }
  708.  
  709.  
  710. void LyXTable::calculate_width_of_table()
  711. {
  712.     int i;
  713.     width_of_table = 0;
  714.     for (i=0; i<columns;i++) {
  715.         width_of_table += column_info[i].width_of_column;
  716.     }
  717. }
  718.  
  719.  
  720. int LyXTable::row_of_cell(int cell) 
  721. {
  722.     return rowofcell[cell];
  723. }
  724.  
  725.  
  726. int LyXTable::column_of_cell(int cell)
  727. {
  728.     return columnofcell[cell];
  729. }
  730.  
  731.  
  732. int LyXTable::right_column_of_cell(int cell) 
  733. {
  734.     int row = row_of_cell(cell);
  735.     int column = column_of_cell(cell);
  736.     while (column < columns - 1 &&
  737.            cell_info[row][column+1].multicolumn == LyXTable::CELL_PART_OF_MULTICOLUMN)
  738.         column++;
  739.     return column;
  740. }
  741.  
  742.  
  743. void LyXTable::Write(FILE* file)
  744. {
  745.     int i,j;
  746.     fprintf(file, "multicol4\n");
  747.     fprintf(file, "%d %d %d %d %d %d %d %d\n", rows, columns, is_long_table,
  748.             rotate, endhead, endfirsthead, endfoot, endlastfoot);
  749.     for (i=0; i<rows; i++){
  750.         fprintf(file, "%d %d %d %d\n", row_info[i].top_line,
  751.                 row_info[i].bottom_line, row_info[i].is_cont_row,
  752.                 row_info[i].newpage);
  753.     }
  754.     for (i=0; i<columns; i++){
  755.         fprintf(file, "%d %d %d %s\n",
  756.                 column_info[i].alignment, column_info[i].left_line,
  757.                 column_info[i].right_line,
  758.                 VSpace(column_info[i].p_width).asLyXCommand().c_str());
  759.     }
  760.  
  761.     for (i=0; i<rows;i++){
  762.         for (j=0;j<columns;j++){
  763.             fprintf(file, "%d %d %d %d %d %d %d\n",
  764.                     cell_info[i][j].multicolumn,
  765.                     cell_info[i][j].alignment,
  766.                     cell_info[i][j].top_line,
  767.                     cell_info[i][j].bottom_line,
  768.                     cell_info[i][j].has_cont_row,
  769.                     cell_info[i][j].rotate,
  770.                     cell_info[i][j].linebreaks);
  771.         }
  772.     }
  773. }
  774.  
  775. #ifdef WITH_WARNINGS
  776. #warning Clean up this code in 0.13 (Jug)
  777. #endif
  778. void LyXTable::Read(FILE* file)
  779. {
  780.     int version;
  781.     int i,j;
  782.     int rows_arg = 0;
  783.     int columns_arg = 0;
  784.     int is_long_table_arg = false;
  785.     int rotate_arg = false;
  786.     LString s;
  787.     int a = 0;
  788.     int b = 0;
  789.     int c = 0;
  790.     int d = 0;
  791.     int e = 0;
  792.     int f = 0;
  793.     int g = 0;
  794.     int h = 0;
  795.     char vtmp[100], stmp[100];
  796.  
  797.     fscanf(file, "%s\n", vtmp);
  798.     s = vtmp;
  799.     if (s.length() > 8)
  800.         version = atoi(s.c_str()+8);
  801.     else
  802.         version = 1;
  803.     a=b=c=d=-1;
  804.     if (version > 2) {
  805.         fgets(vtmp,sizeof(vtmp),file);
  806.         sscanf(vtmp, "%d %d %d %d %d %d %d %d\n", &rows_arg, &columns_arg,
  807.                &is_long_table_arg, &rotate_arg, &a, &b, &c, &d);
  808.     } else
  809.         fscanf(file, "%d %d\n",
  810.                &rows_arg, &columns_arg);
  811.     Init(rows_arg, columns_arg);
  812.     SetLongTable(is_long_table_arg);
  813.     SetRotateTable(rotate_arg);
  814.     endhead = a;
  815.     endfirsthead = b;
  816.     endfoot = c;
  817.     endlastfoot = d;
  818.     for (i=0; i<rows; i++){
  819.         a=b=c=d=e=f=g=h=0;
  820.         fgets(vtmp,sizeof(vtmp),file);
  821.         sscanf(vtmp, "%d %d %d %d\n",
  822.                &a, &b, &c, &d);
  823.         row_info[i].top_line = a;
  824.         row_info[i].bottom_line = b;
  825.         row_info[i].is_cont_row = c;
  826.         row_info[i].newpage = d;
  827.     }
  828.     for (i=0; i<columns; i++){
  829.         *stmp = 0;
  830.         fgets(vtmp,sizeof(vtmp),file);
  831.         sscanf(vtmp, "%d %d %d %s\n", &a, &b, &c, stmp);
  832.         column_info[i].alignment = (char) a;
  833.         column_info[i].left_line = b;
  834.         column_info[i].right_line = c;
  835.         if (*stmp == '"') { /* strip quotes if they exists */
  836.             if (stmp[strlen(stmp)-1] == '"')
  837.                 stmp[strlen(stmp)-1] = 0;
  838.             memcpy(stmp,stmp+1,strlen(stmp)-1);
  839.             stmp[strlen(stmp)-1] = 0;
  840.         }
  841.         if (*stmp)
  842.             column_info[i].p_width = stmp;
  843.     }
  844.  
  845.     if (version == 1){
  846.         for (i=0; i<rows;i++){
  847.             for (j=0;j<columns;j++){
  848.                 fscanf(file, "%d %d\n", &a, &b);
  849.                 cell_info[i][j].multicolumn = (char) a;
  850.                 cell_info[i][j].alignment = (char) b;
  851.             }
  852.         }
  853.     } else if (version < 4) {
  854.         for (i=0; i<rows;i++){
  855.             for (j=0;j<columns;j++){
  856.                 fscanf(file, "%d %d %d %d\n", &a, &b, &c, &d);
  857.                 cell_info[i][j].multicolumn = (char) a;
  858.                 cell_info[i][j].alignment = (char) b;
  859.                 cell_info[i][j].top_line = (char) c;
  860.                 cell_info[i][j].bottom_line = (char) d;
  861.             }
  862.         }
  863.     } else {
  864.         for (i=0; i<rows;i++){
  865.             for (j=0;j<columns;j++){
  866.                 a=b=c=d=e=f=g=0;
  867.                 fgets(vtmp,sizeof(vtmp),file);
  868.                 sscanf(vtmp, "%d %d %d %d %d %d %d\n",
  869.                        &a, &b, &c, &d, &e, &f, &g);
  870.                 cell_info[i][j].multicolumn = (char) a;
  871.                 cell_info[i][j].alignment = (char) b;
  872.                 cell_info[i][j].top_line = (char) c;
  873.                 cell_info[i][j].bottom_line = (char) d;
  874.                 cell_info[i][j].has_cont_row = (bool) e;
  875.                 cell_info[i][j].rotate = (bool) f;
  876.                 cell_info[i][j].linebreaks = (bool) g;
  877.             }
  878.         }
  879.     }
  880.     set_row_column_number_info();
  881. }
  882.  
  883.  
  884. // cell <0 will tex the preamble
  885. // returns the number of printed newlines
  886. int LyXTable::TexEndOfCell(LString& file, int cell)
  887. {
  888.     int i;
  889.     int ret = 0;
  890.     int tmp; // tmp2;
  891.     int fcell;
  892.     if (cell == GetNumberOfCells() - 1){
  893.         // the very end at the very beginning
  894.         if (Linebreaks(cell) &&
  895.             !column_info[column_of_cell(cell)].p_width.empty())
  896.             file += '}';
  897.         if (IsMultiColumn(cell))
  898.             file += '}';
  899.         if (RotateCell(cell)) {
  900.             file += "\n\\end{sideways}";
  901.             ret++;
  902.         }
  903.         file += "\\\\\n";
  904.         ret++;
  905.     
  906.         tmp = 0;
  907.         fcell = cell; 
  908.         while (!IsFirstCell(fcell))fcell--;
  909.         for (i=0; i < NumberOfCellsInRow(fcell); i++){
  910.             if (BottomLine(fcell+i))
  911.                 tmp++;
  912.         }
  913.         if (tmp == NumberOfCellsInRow(fcell)){
  914.             file += "\\hline ";
  915.         } else {
  916.             tmp = 0;
  917.             for (i=0; i < NumberOfCellsInRow(fcell); i++){
  918.                 if (BottomLine(fcell+i)){
  919.             file += "\\cline{";
  920.             file += column_of_cell(fcell+i)+1;
  921.             file += '-';
  922.             file += right_column_of_cell(fcell+i)+1;
  923.             file += "} ";
  924.                     tmp = 1;
  925.                 }
  926.             }
  927.         }
  928.         if (tmp){
  929.             file += '\n';
  930.             ret++;
  931.         }
  932.         if (is_long_table)
  933.             file += "\\end{longtable}";
  934.         else
  935.             file += "\\end{tabular}";
  936.         if (rotate) {
  937.             file += "\n\\end{sideways}";
  938.             ret++;
  939.         }
  940.     } else {
  941.         if (cell < 0){
  942.             // preamble
  943.             if (rotate) {
  944.                 file += "\\begin{sideways}\n";
  945.                 ret++;
  946.             }
  947.             if (is_long_table)
  948.                 file += "\\begin{longtable}{";
  949.             else
  950.                 file += "\\begin{tabular}{";
  951.             for (i=0; i<columns;i++){
  952.                 if (column_info[i].left_line)
  953.             file += '|';
  954.                 if (!column_info[i].p_width.empty()) {
  955.             file += "p{";
  956.             file += column_info[i].p_width;
  957.             file += '}';
  958.                 } else {
  959.                     switch (column_info[i].alignment) {
  960.                       case LYX_ALIGN_LEFT: file += 'l'; break;
  961.                       case LYX_ALIGN_RIGHT: file += 'r'; break;
  962.                       default:  file += 'c'; break;
  963.                     }
  964.                 }
  965.                 if (column_info[i].right_line)
  966.                     file += '|';
  967.             }
  968.             file += "}\n";
  969.             ret++;
  970.             tmp = 0;
  971.             if (GetNumberOfCells()){
  972.                 fcell = 0;
  973.                 for (i=0; i < NumberOfCellsInRow(fcell); i++){
  974.                     if (TopLine(fcell+i))
  975.                         tmp++;
  976.                 }
  977.                 if (tmp == NumberOfCellsInRow(fcell)){
  978.                     file += "\\hline ";
  979.                 } else {
  980.                     tmp = 0;
  981.                     for (i=0; i < NumberOfCellsInRow(fcell); i++){
  982.                         if (TopLine(fcell+i)){
  983.                 file += "\\cline{";
  984.                 file += column_of_cell(fcell+i)+1;
  985.                 file += '-';
  986.                 file += right_column_of_cell(fcell+i)+1;
  987.                 file += "} ";
  988.                             tmp = 1;
  989.                         }
  990.                     }
  991.                 }
  992.                 if (tmp){
  993.                     file += '\n';
  994.                     ret++;
  995.                 }
  996.             }
  997.             if (RotateCell(0)) {
  998.                 file += "\\begin{sideways}\n";
  999.                 ret++;
  1000.             }
  1001.         } else {
  1002.             // usual cells
  1003.             if (Linebreaks(cell) &&
  1004.                 !column_info[column_of_cell(cell)].p_width.empty())
  1005.                 file += '}';
  1006.             if (IsMultiColumn(cell)){
  1007.                 file += '}';
  1008.             }
  1009.             if (RotateCell(cell)) {
  1010.                 file += "\n\\end{sideways}";
  1011.                 ret++;
  1012.             }
  1013.             if (IsLastCell(cell)) {
  1014.                 int row = row_of_cell(cell);
  1015.                 LString hline1,hline2;
  1016.                 bool print_hline = true;
  1017.                 bool pr_top_hline,flag1,flag2;
  1018.                 flag1 = IsLongTable() &&
  1019.                     ((row == endhead) || (row == endfirsthead) ||
  1020.                      (row == endfoot) || (row == endlastfoot));
  1021.                 row++;
  1022.                 flag2 = IsLongTable() &&
  1023.                     ((row == endhead) || (row == endfirsthead) ||
  1024.                      (row == endfoot) || (row == endlastfoot));
  1025.                 row--;
  1026.                 // print the bottom hline only if (otherwise it is doubled):
  1027.                 // - is no LongTable
  1028.                 // - there IS a first-header
  1029.                 // - the next row is no special header/footer
  1030.                 //   & this row is no special header/footer
  1031.                 // - the next row is a special header/footer
  1032.                 //   & this row is a special header/footer
  1033.                 pr_top_hline = (flag1 && flag2) || (!flag1 && !flag2) ||
  1034.                     (endfirsthead == endhead);
  1035.                 file += "\\\\\n";
  1036.                 ret++;
  1037.                 tmp = 0;
  1038.                 fcell = cell;
  1039.                 while (!IsFirstCell(fcell))
  1040.                     fcell--;
  1041.                 for (i=0; i < NumberOfCellsInRow(cell); i++){
  1042.                     if (BottomLine(fcell+i))
  1043.                         tmp++;
  1044.                 }
  1045.                 if (tmp == NumberOfCellsInRow(cell)){
  1046.                     file += "\\hline ";
  1047.                     hline1 = "\\hline ";
  1048.                 } else {
  1049.                     tmp = 0;
  1050.                     for (i=0; i < NumberOfCellsInRow(fcell); i++){
  1051.                         if (BottomLine(fcell+i)){
  1052.                             file += "\\cline{";
  1053.                             file += column_of_cell(fcell+i)+1;
  1054.                             file += '-';
  1055.                             file += right_column_of_cell(fcell+i)+1;
  1056.                             file += "} ";
  1057.                             hline1 += "\\cline{";
  1058.                             hline1 += column_of_cell(fcell+i)+1;
  1059.                             hline1 += '-';
  1060.                             hline1 += right_column_of_cell(fcell+i)+1;
  1061.                             hline1 += "} ";
  1062.                             tmp = 1;
  1063.                         }
  1064.                     }
  1065.                 }
  1066.                 if (tmp){
  1067.                     file += '\n';
  1068.                     ret++;
  1069.                 }
  1070.                 if (IsLongTable() && (row == endfoot)) {
  1071.                     file += "\\endfoot\n";
  1072.                     ret++;
  1073.                     print_hline = false; // no double line below footer
  1074.                 }
  1075.                 if (IsLongTable() && (row == endlastfoot)) {
  1076.                     file += "\\endlastfoot\n";
  1077.                     ret++;
  1078.                     print_hline = false; // no double line below footer
  1079.                 }
  1080.                 if (IsLongTable() && row_info[row].newpage) {
  1081.                     file += "\\newpage\n";
  1082.                     ret++;
  1083.                     print_hline = false; // no line below a \\newpage-command
  1084.                 }
  1085.                 tmp = 0;
  1086.                 if ((cell < GetNumberOfCells()-1) &&
  1087.                     !ShouldBeVeryLastCell(cell)) {
  1088.                     fcell = cell+1;
  1089.                     // Now jump all ContRows
  1090.                     while (IsContRow(fcell))
  1091.                         fcell++;
  1092.                     while (!IsFirstCell(fcell))
  1093.                         fcell--;
  1094.                     for (i=0; i < NumberOfCellsInRow(fcell); i++){
  1095.                         if (TopLine(fcell+i))
  1096.                             tmp++;
  1097.                     }
  1098.                     if (tmp == NumberOfCellsInRow(fcell)){
  1099.                         if (print_hline)
  1100.                             file += "\\hline ";
  1101.                         hline2 = "\\hline ";
  1102.                     }
  1103.                     else {
  1104.                         tmp = 0;
  1105.                         for (i=0; i < NumberOfCellsInRow(fcell); i++){
  1106.                             if (TopLine(fcell+i)){
  1107.                                 if (print_hline) {
  1108.                     file += "\\cline{";
  1109.                     file += column_of_cell(fcell+i)+1;
  1110.                     file += '-';
  1111.                     file += right_column_of_cell(fcell+i)+1;
  1112.                     file += "} ";
  1113.                 }
  1114.                                 hline2 += "\\cline{";
  1115.                                 hline2 += column_of_cell(fcell+i)+1;
  1116.                                 hline2 += '-';
  1117.                                 hline2 += right_column_of_cell(fcell+i)+1;
  1118.                                 hline2 += "} ";
  1119.                                 tmp = 1;
  1120.                             }
  1121.                         }
  1122.                     }
  1123.                     if (tmp && print_hline){
  1124.                         file += '\n';
  1125.                         ret++;
  1126.                     }
  1127.                 }
  1128.                 // the order here is important as if one defines two
  1129.                 // or more things in one line only the first entry is
  1130.                 // displayed the other are set to an empty-row. This
  1131.                 // is important if I have a footer and want that the
  1132.                 // lastfooter is NOT displayed!!!
  1133.                 bool sflag2 = (row == endhead) || (row == endfirsthead) ||
  1134.                     (row == endfoot) || (row == endlastfoot);
  1135.                 row--;
  1136. //                sflag2 = IsLongTable() && (row >= 0) &&
  1137. //                    (sflag2 || (row == endhead) || (row == endfirsthead));
  1138.                 row += 2;
  1139.                 bool sflag1 = IsLongTable() && (row != endhead) &&
  1140.                     (row != endfirsthead) &&
  1141.                     ((row == endfoot) || (row == endlastfoot));
  1142.                 row--;
  1143.                 if (IsLongTable() && (row == endhead)) {
  1144.             file += "\\endhead\n";
  1145.                     ret++;
  1146.                 }
  1147.                 if (IsLongTable() && (row == endfirsthead)) {
  1148.                     file += "\\endfirsthead\n";
  1149.                     ret++;
  1150.                 }
  1151.                 if (sflag1) { // add the \hline for next foot row
  1152.                     if (!hline1.empty()) {
  1153.                         file += hline1 + '\n';
  1154.                         ret++;
  1155.                     }
  1156.                 }
  1157.                 // add the \hline for the first row
  1158.                 if (pr_top_hline && sflag2) {
  1159.                     if (!hline2.empty()) {
  1160.                         file += hline2 + '\n';
  1161.                         ret++;
  1162.                     }
  1163.                 }
  1164.                 if (RotateCell(cell+1)) {
  1165.                     file += "\\begin{sideways}\n";
  1166.                     ret++;
  1167.                 }
  1168.             } else {
  1169.                 file += "&\n";
  1170.                 ret++;
  1171.                 if (RotateCell(cell+1)) {
  1172.                     file += "\\begin{sideways}\n";
  1173.                     ret++;
  1174.                 }
  1175.             }
  1176.         }
  1177.         if (IsMultiColumn(cell+1)){
  1178.             file += "\\multicolumn{";
  1179.         file += cells_in_multicolumn(cell+1);
  1180.         file += "}{";
  1181.             if (LeftLine(cell+1))
  1182.                 file += '|';
  1183.             switch (GetAlignment(cell+1)) {
  1184.               case LYX_ALIGN_LEFT: file += 'l'; break;
  1185.               case LYX_ALIGN_RIGHT: file += 'r'; break;
  1186.               default:  file += 'c'; break;
  1187.             }
  1188.             if (RightLine(cell+1))
  1189.                 file += '|';
  1190.             //if (column_of_cell(cell+2)!=0 && LeftLine(cell+2))
  1191.             if (((cell+2) < numberofcells) &&
  1192.                 (column_of_cell(cell+2)!=0) && LeftLine(cell+2))    
  1193.                 file += '|';
  1194.             file += "}{";
  1195.         }
  1196.         if (Linebreaks(cell+1) &&
  1197.             !column_info[column_of_cell(cell+1)].p_width.empty()) {
  1198.             file += "\\parbox{";
  1199.         file += column_info[column_of_cell(cell+1)].p_width;
  1200.         file += "}{";
  1201.     }
  1202.     }
  1203.     return ret;
  1204. }
  1205.  
  1206.  
  1207. // cell <0 will tex the preamble
  1208. // returns the number of printed newlines
  1209. int LyXTable::RoffEndOfCell(FILE* file, int cell)
  1210. {
  1211.     int i,j;
  1212.     int ret = 0;
  1213.  
  1214.     if (cell == GetNumberOfCells() - 1){
  1215.         // the very end at the very beginning
  1216.         if (CellHasContRow(cell) >= 0) {
  1217.             fprintf(file,"\nT}");
  1218.             ret++;
  1219.         }
  1220.         fprintf(file, "\n");
  1221.         ret++;
  1222.         if (row_info[row_of_cell(cell)].bottom_line) {
  1223.             fprintf(file, "_\n");
  1224.             ret++;
  1225.         }
  1226.         fprintf(file, ".TE\n.pl 1c");
  1227.     } else {  
  1228.         if (cell < 0){
  1229.             int fcell=0;
  1230.             // preamble
  1231.             fprintf(file, "\n.pl 500c\n.TS\n");
  1232.             for (j=0; j<rows; j++) {
  1233.                 for (i=0; i<columns;i++,fcell++) {
  1234.                     if (column_info[i].left_line)
  1235.                         fprintf(file, " | ");
  1236.                     if (cell_info[j][i].multicolumn==CELL_PART_OF_MULTICOLUMN)
  1237.                         fprintf(file, "s");
  1238.                     else {
  1239.                         switch (column_info[i].alignment) {
  1240.                           case LYX_ALIGN_LEFT:
  1241.                               fprintf(file, "l");
  1242.                               break;
  1243.                           case LYX_ALIGN_RIGHT:
  1244.                               fprintf(file, "r");
  1245.                               break;
  1246.                           default:
  1247.                               fprintf(file, "c");
  1248.                               break;
  1249.                         }
  1250.                     }
  1251.                     if (!column_info[i].p_width.empty())
  1252.                         fprintf(file, "w(%s)", column_info[i].p_width.c_str());
  1253.                     if (column_info[i].right_line)
  1254.                         fprintf(file, " | ");
  1255.                 }
  1256.                 if ((j+1) < rows) {
  1257.                     fprintf(file, "\n");
  1258.                     ret++;
  1259.                 }
  1260.             }
  1261.             fprintf(file, ".\n");
  1262.             ret++;
  1263.             if (row_info[0].top_line) {
  1264.                 fprintf(file,"_\n");
  1265.                 ret++;
  1266.             }
  1267.             if (CellHasContRow(0) >= 0) {
  1268.                 fprintf(file,"T{\n");
  1269.                 ret++;
  1270.             }
  1271.         } else {
  1272.             // usual cells
  1273.             if (CellHasContRow(cell) >= 0) {
  1274.                 fprintf(file,"\nT}");
  1275.                 ret++;
  1276.             }
  1277.             if (right_column_of_cell(cell) == columns -1){
  1278.                 fprintf(file, "\n");
  1279.                 ret++;
  1280.                 int row = row_of_cell(cell);
  1281.                 if (row_info[row++].bottom_line) {
  1282.                     fprintf(file, "_\n");
  1283.                     ret++;
  1284.                 }
  1285.                 if ((row < rows) && row_info[row].top_line) {
  1286.                     fprintf(file, "_\n");
  1287.                     ret++;
  1288.                 }
  1289.             } else
  1290.                 fprintf(file, "\t");
  1291.             if ((cell < GetNumberOfCells() - 1) &&
  1292.                 (CellHasContRow(cell+1) >= 0)) {
  1293.                 fprintf(file,"T{\n");
  1294.                 ret++;
  1295.             }
  1296.         }
  1297.     }
  1298.     return ret;
  1299. }
  1300.  
  1301.  
  1302. bool LyXTable::IsMultiColumn(int cell)
  1303. {
  1304.     return (cellinfo_of_cell(cell)->multicolumn != LyXTable::CELL_NORMAL);
  1305. }
  1306.  
  1307.  
  1308. LyXTable::cellstruct* LyXTable::cellinfo_of_cell(int cell)
  1309. {
  1310.     int row = row_of_cell(cell);
  1311.     int column = column_of_cell(cell);
  1312.     return  &cell_info[row][column];
  1313. }
  1314.    
  1315.  
  1316. void LyXTable::SetMultiColumn(int cell, int number)
  1317. {
  1318.     int new_width = cellinfo_of_cell(cell)->width_of_cell;
  1319.     
  1320.     cellinfo_of_cell(cell)->multicolumn = LyXTable::CELL_BEGIN_OF_MULTICOLUMN;
  1321.     cellinfo_of_cell(cell)->alignment = column_info[column_of_cell(cell)].alignment;
  1322.     cellinfo_of_cell(cell)->top_line = row_info[row_of_cell(cell)].top_line;
  1323.     cellinfo_of_cell(cell)->bottom_line = row_info[row_of_cell(cell)].bottom_line;
  1324.     for (number--;number>0;number--){
  1325.         cellinfo_of_cell(cell+number)->multicolumn =
  1326.             LyXTable::CELL_PART_OF_MULTICOLUMN;
  1327.         new_width += cellinfo_of_cell(cell+number)->width_of_cell;
  1328.     }
  1329.     set_row_column_number_info();
  1330.     SetWidthOfCell(cell,new_width);
  1331. }
  1332.  
  1333.  
  1334. int LyXTable::cells_in_multicolumn(int cell)
  1335. {
  1336.     int row = row_of_cell(cell);
  1337.     int column = column_of_cell(cell);
  1338.     int result = 1;
  1339.     column++;
  1340.     while (column < columns && cell_info[row][column].multicolumn
  1341.            == LyXTable::CELL_PART_OF_MULTICOLUMN){
  1342.         result++;
  1343.         column++;
  1344.     }
  1345.     return result;
  1346. }
  1347.  
  1348.  
  1349. int  LyXTable::UnsetMultiColumn(int cell)
  1350. {
  1351.     int row = row_of_cell(cell);
  1352.     int column = column_of_cell(cell);
  1353.  
  1354.     int result = 0;
  1355.  
  1356.     if (cell_info[row][column].multicolumn
  1357.         == LyXTable::CELL_BEGIN_OF_MULTICOLUMN){
  1358.         cell_info[row][column].multicolumn = LyXTable::CELL_NORMAL;
  1359.         column++;
  1360.         while (column < columns &&
  1361.                cell_info[row][column].multicolumn
  1362.                == LyXTable::CELL_PART_OF_MULTICOLUMN){
  1363.             cell_info[row][column].multicolumn =
  1364.                 LyXTable::CELL_NORMAL;
  1365.             column++;
  1366.             result++;
  1367.         }
  1368.     }
  1369.     set_row_column_number_info();
  1370.     return result;
  1371. }
  1372.  
  1373.  
  1374. void LyXTable::delete_column(int column)
  1375. {
  1376.     int i,j;
  1377.     columnstruct *column_info2 = new columnstruct[columns-1];
  1378.    
  1379.     for (i=0; i<column; i++){
  1380.         column_info2[i] = column_info[i];
  1381.     }
  1382.     for (i=column; i<columns-1; i++){
  1383.         column_info2[i] = column_info[i+1];
  1384.     }
  1385.    
  1386.     delete[] column_info;
  1387.     column_info = column_info2;
  1388.  
  1389.     for (i=0; i<rows;i++){
  1390.         cellstruct* tmp = cell_info[i];
  1391.         cell_info[i] = new cellstruct[columns-1];
  1392.         for (j=0; j<column; j++){
  1393.             cell_info[i][j]=tmp[j];
  1394.         }
  1395.         for (j=column; j<columns-1; j++){
  1396.             cell_info[i][j]=tmp[j+1];
  1397.         }
  1398.         delete[] tmp;
  1399.     }
  1400.  
  1401.     columns--;
  1402.     Reinit();
  1403. }
  1404.  
  1405. void LyXTable::SetLongTable(int what)
  1406. {
  1407.     is_long_table = what;
  1408. }
  1409.  
  1410. bool LyXTable::IsLongTable()
  1411. {
  1412.     return is_long_table;
  1413. }
  1414.  
  1415. void LyXTable::SetRotateTable(int what)
  1416. {
  1417.     rotate = what;
  1418. }
  1419.  
  1420. bool LyXTable::RotateTable()
  1421. {
  1422.     return rotate;
  1423. }
  1424.  
  1425. void LyXTable::SetRotateCell(int cell, int what)
  1426. {
  1427.     cellinfo_of_cell(cell)->rotate = what;
  1428. }
  1429.  
  1430. bool LyXTable::RotateCell(int cell)
  1431. {
  1432.     return cellinfo_of_cell(cell)->rotate;
  1433. }
  1434.  
  1435. bool LyXTable::NeedRotating()
  1436. {
  1437.     if (rotate)
  1438.         return true;
  1439.     for (int i=0; i<rows;i++){
  1440.         for (int j=0;j<columns;j++){
  1441.             if (cell_info[i][j].rotate)
  1442.                 return true;
  1443.         }
  1444.     }
  1445.     return false;
  1446. }
  1447.  
  1448. void LyXTable::AppendContRow(int cell)
  1449. {
  1450.     int row = row_of_cell(cell)+1;
  1451.  
  1452.     if (!RowHasContRow(cell) || (CellHasContRow(cell)>=0))
  1453.         AppendRow(cell);
  1454.     row_info[row].is_cont_row = true;
  1455.     row_info[row].top_line = false;
  1456.     cell_info[row-1][column_of_cell(cell)].has_cont_row = true;
  1457.     Reinit();
  1458. }
  1459.  
  1460. bool LyXTable::IsContRow(int cell)
  1461. {
  1462.     return row_info[row_of_cell(cell)].is_cont_row;
  1463. }
  1464.  
  1465. int LyXTable::CellHasContRow(int cell)
  1466. {
  1467.     int row = row_of_cell(cell);
  1468.  
  1469.     if (VeryLastRow(cell))
  1470.         return -1;
  1471.     if (cell_info[row][column_of_cell(cell)].has_cont_row)
  1472.         return cell_info[row+1][column_of_cell(cell)].cellno;
  1473.     return -1;
  1474. }
  1475.  
  1476. bool LyXTable::RowHasContRow(int cell)
  1477. {
  1478.     int row = row_of_cell(cell) + 1;
  1479.  
  1480.     if (row < rows)
  1481.         return row_info[row].is_cont_row;
  1482.     return false;
  1483. }
  1484.  
  1485. int LyXTable::FirstVirtualCell(int cell)
  1486. {
  1487.     if (!IsContRow(cell))
  1488.         return cell;
  1489.     int row = row_of_cell(cell);
  1490.     int column = column_of_cell(cell);
  1491.     for(;(row>0) && IsContRow(cell_info[row][column].cellno); row--)
  1492.         ;
  1493.     return cell_info[row][column].cellno;
  1494. }
  1495.  
  1496. bool LyXTable::ShouldBeVeryLastCell(int cell)
  1497. {
  1498.     int fcell = cell + 1;
  1499.  
  1500.     if (cell == GetNumberOfCells() - 1)
  1501.         return true; // not really sure if I should return false here
  1502.     if (!IsContRow(fcell))
  1503.         return false;
  1504.     while((fcell < GetNumberOfCells() - 1) && IsContRow(fcell))
  1505.         fcell++;
  1506.     if (fcell < GetNumberOfCells() - 1)
  1507.         return false;
  1508.     return true;
  1509. }
  1510.  
  1511. bool LyXTable::ShouldBeVeryLastRow(int cell)
  1512. {
  1513.     if (CellHasContRow(cell)>=0)
  1514.         return false;
  1515.     int row = row_of_cell(cell)+1;
  1516.     int column = column_of_cell(cell);
  1517.     while((row < rows) && IsContRow(cell_info[row][column].cellno))
  1518.         row++;
  1519.     if (row < rows)
  1520.         return false; // found another valid row
  1521.     // I do not have any valid row after the actual
  1522.     return true;
  1523. }
  1524.  
  1525. int LyXTable::GetCellAbove(int cell)
  1526. {
  1527.     int row = row_of_cell(cell);
  1528.     
  1529.     if (row > 0)
  1530.         return cell_info[row-1][column_of_cell(cell)].cellno;
  1531.     return cell;
  1532. }
  1533.  
  1534. void LyXTable::SetLinebreaks(int cell, bool what)
  1535. {
  1536.     cellinfo_of_cell(FirstVirtualCell(cell))->linebreaks = what;
  1537. }
  1538.  
  1539. bool LyXTable::Linebreaks(int cell)
  1540. {
  1541.     if (IsContRow(cell) ||
  1542.         column_info[column_of_cell(cell)].p_width.empty())
  1543.         return false;
  1544.     return cellinfo_of_cell(cell)->linebreaks;
  1545. }
  1546.  
  1547. void LyXTable::SetLTHead(int cell, bool first)
  1548. {
  1549.     int row = row_of_cell(cell);
  1550.  
  1551.     if (first) {
  1552.         if (row == endfirsthead)
  1553.             endfirsthead = -1;
  1554.         else
  1555.             endfirsthead = row;
  1556.     } else {
  1557.         if (row == endhead)
  1558.             endhead = -1;
  1559.         else
  1560.             endhead = row;
  1561.     }
  1562. }
  1563.  
  1564. bool LyXTable::RowOfLTHead(int cell)
  1565. {
  1566.     if ((endhead+1) > rows)
  1567.         endhead = -1;
  1568.     return (row_of_cell(cell) == endhead);
  1569. }
  1570.  
  1571. bool LyXTable::RowOfLTFirstHead(int cell)
  1572. {
  1573.     if ((endfirsthead+1) > rows)
  1574.         endfirsthead = -1;
  1575.     return (row_of_cell(cell) == endfirsthead);
  1576. }
  1577.  
  1578. void LyXTable::SetLTFoot(int cell, bool last)
  1579. {
  1580.     int row = row_of_cell(cell);
  1581.  
  1582.     if (last) {
  1583.         if (row == endlastfoot)
  1584.             endlastfoot = -1;
  1585.         else
  1586.             endlastfoot = row;
  1587.     } else {
  1588.         if (row == endfoot)
  1589.             endfoot = -1;
  1590.         else
  1591.             endfoot = row;
  1592.     }
  1593. }
  1594.  
  1595. bool LyXTable::RowOfLTFoot(int cell)
  1596. {
  1597.     if ((endfoot+1) > rows) {
  1598.         endfoot = -1;
  1599.         return false;
  1600.     }
  1601.     return (row_of_cell(cell) == endfoot);
  1602. }
  1603.  
  1604. bool LyXTable::RowOfLTLastFoot(int cell)
  1605. {
  1606.     if ((endlastfoot+1) > rows)
  1607.         endlastfoot = -1;
  1608.     return (row_of_cell(cell) == endlastfoot);
  1609. }
  1610.  
  1611. void LyXTable::SetLTNewPage(int cell, bool what)
  1612. {
  1613.     row_info[row_of_cell(cell)].newpage = what;
  1614. }
  1615.  
  1616. bool LyXTable::LTNewPage(int cell)
  1617. {
  1618.     return row_info[row_of_cell(cell)].newpage;
  1619. }
  1620.