00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <cxxtls/tableviewer.h>
00031 #include <cxxtls/viewermanager.h>
00032 #include <algorithm>
00033 #include <cxxtls/simple_regex.h>
00034
00035 #include <ctype.h>
00036
00037 using namespace std;
00038
00039 namespace cxxtls
00040 {
00041
00044 TableViewer::~TableViewer()
00045 {
00046 }
00047
00048 void TableViewer::repaintTitle( CursorWindow::viewport *vp )
00049 {
00050 vp->set_curpos(0,0);
00051 vp->set_text_attribute(active_ ? manager_->active_title_att
00052 : manager_->inactive_title_att
00053 );
00054
00055 *vp << application_name();
00056
00057 vp->fill_to_eol();
00058
00059 }
00060
00063 void TableViewer::operator() ( CursorWindow::viewport * vp,
00064 int cmd
00065 )
00066 {
00067
00068
00069
00071
00072
00074
00075 hideCursor(vp);
00076
00077
00078 if(cmd == CursorWindow::viewport::repaint_handler::activate)
00079 active_ = true;
00080 else
00081 if(cmd == CursorWindow::viewport::repaint_handler::deactivate)
00082 {
00083 active_ = false;
00084 }
00085
00087
00089
00090
00091 repaintTitle(vp);
00092
00093
00095
00096
00098
00099
00100 pageWidth_ = 0;
00101 pageHeight_ = 0;
00102
00103 recomputeLayout();
00104
00105 row_col size = vp->size();
00106
00107
00108 int row;
00109
00110 vp->set_text_attribute(manager_->normal_att);
00111
00112
00113 displayOrigin_.row_ = 2;
00114 displayOrigin_.col_ = longestRowTitle();
00115
00116
00117 pageWidth_ = 0;
00118
00119 size_t gutterWidth = 1;
00120
00121
00123
00124
00126
00127
00128 {
00129 size_t col;
00130
00131 colWidths_.resize(0);
00132
00133 for(col=0; col < cols_.size(); ++col)
00134 {
00135
00136
00137 size_t colWidth = columnWidth(col);
00138
00139 colWidths_.push_back(colWidth);
00140 }
00141
00142 size_t paintColumn = displayOrigin_.col_;
00143
00144 vp->set_text_attribute(CursorWindow::bottom_att);
00145 vp->set_curpos(displayOrigin_.row_-1,0);
00146 vp->fill_to_eol();
00147
00148 vp->set_curpos(displayOrigin_.row_-1, paintColumn);
00149
00150
00151 for(col=0; col < cols_.size() - originCol(); ++col)
00152 {
00153 size_t workingCol = originCol() + col;
00154
00155 size_t colWidth = colWidths_[workingCol];
00156
00157
00158 vp->set_curpos(displayOrigin_.row_-1, paintColumn + gutterWidth);
00159
00160
00161 *vp << cols_[workingCol].title_;
00162
00163 if(paintColumn + colWidth + gutterWidth > size_t(size.col_))
00164 {
00165
00166
00167
00168
00169
00170 ++col;
00171
00172
00173
00174 break;
00175 }
00176
00177 paintColumn += colWidth + gutterWidth;
00178
00179 }
00180
00181 pageWidth_ = col;
00182
00183 vp->fill_to_eol();
00184
00185 }
00186
00187
00189
00191
00192 vp->set_text_attribute(manager_->normal_att);
00193
00194
00195 size_t lastPaintedRow=1000;
00196
00197
00198
00199 pageHeight_ = 0;
00200
00201 for(row=0; row < (size.row_ - displayOrigin_.row_); ++row)
00202 {
00203 size_t workingRow = originRow() + row;
00204
00205 if(workingRow >= layout_.size() || workingRow >= rows() )
00206 break;
00207
00208 ++pageHeight_;
00209
00210 LayoutType::value_type &curRow = layout_[workingRow];
00211
00212 vp->set_curpos(row+displayOrigin_.row_, 0);
00213
00214 vp->set_text_attribute(manager_->normal_att);
00215
00216 *vp << rows_[workingRow].title_;
00217
00218 {
00219 row_col curpos = vp->curpos();
00220
00221 int colDelta = displayOrigin_.col_ - curpos.col_;
00222
00223 for(int i = 0; i < colDelta; ++i)
00224 {
00225 *vp << " ";
00226 }
00227
00228 }
00229
00230 if(curRow.size())
00231 {
00232 for(size_t col = 0; col < pageWidth_; ++col)
00233 {
00234 size_t workingCol = originCol() + col;
00235
00236 int worldCol = curRow[workingCol].worldColumn_ -
00237 curRow[originCol()].worldColumn_;
00238
00239 if(worldCol < size.col_)
00240 {
00241 paintCell(vp,
00242 lastPaintedRow = row+displayOrigin_.row_,
00243 worldCol+displayOrigin_.col_,
00244 workingRow,
00245 workingCol,
00246 false,
00247 false
00248 );
00249
00250 }
00251 }
00252 }
00253
00254 vp->set_text_attribute(manager_->normal_att);
00255
00256 vp->fill_to_eol();
00257
00258 }
00259
00261
00263
00264 vp->set_text_attribute(manager_->normal_att);
00265
00266 while(lastPaintedRow < size_t(size.row_))
00267 {
00268 ++lastPaintedRow;
00269 vp->set_curpos(lastPaintedRow, 0);
00270 vp->fill_to_eol();
00271 }
00272
00273
00274
00275
00276
00277
00278
00279 cursorDisplayed_ = active_;
00280
00281 if(cursorRow_ > rows())
00282 cursorRow_ = originRow();
00283
00284 if(cursorCol_ > cols())
00285 cursorCol_ = originCol();
00286
00287 if(pageHeight_ && (cursorRow_ >= originRow() + pageHeight_) )
00288 {
00289 size_t lastRow = originRow() + (pageHeight_ -1);
00290
00291 if(lastRow > 1)
00292 {
00293 cursorRow_ = lastRow-1;
00294 }
00295 else
00296 {
00297 cursorRow_ = 0;
00298 }
00299
00300
00301 }
00302
00303 if(pageWidth_ && (cursorCol_ >= originCol() + pageWidth_) )
00304 {
00305
00306
00307
00308 size_t lastCol = originCol() + (pageWidth_ -1);
00309
00310 if(lastCol > 1)
00311 {
00312 cursorCol_ = lastCol-1;
00313 }
00314 else
00315 {
00316 cursorCol_ = 0;
00317 }
00318
00319
00320 }
00321
00322 if(cursorCol_ < originCol())
00323 cursorCol_ = originCol();
00324
00325 if(cursorRow_ < originRow())
00326 cursorRow_ = originRow();
00327
00328 if(cursorDisplayed_)
00329 showCursor(vp);
00330
00331
00332 }
00333
00336
00337 bool TableViewer::handle_event( CursorWindow::input_event const * e,
00338 CursorWindow::viewport * vp
00339 )
00340 {
00341 vp = vp;
00342
00343 if(e)
00344 {
00345 if( e->type_ == CursorWindow::input_event::DataKey
00346 || e->type_ == CursorWindow::input_event::FunctionKey
00347 )
00348 {
00349 static RowInfo bi;
00350
00351 switch(e->value_)
00352 {
00353 case 'q': return true;
00354 case 'Q': return true;
00355
00356 case CursorWindow::key_up: moveUp(vp); return false;
00357 case CursorWindow::key_down: moveDown(vp); return false;
00358 case CursorWindow::key_left: moveLeft(vp); return false;
00359 case CursorWindow::key_right: moveRight(vp); return false;
00360 case 0x09: pageRight(vp); return false;
00361 case CursorWindow::key_btab: pageLeft(vp); return false;
00362 case CursorWindow::key_home: pageHome(vp); return false;
00363 case CursorWindow::key_next: pageDown(vp); return false;
00364 case CursorWindow::key_prior: pageUp(vp); return false;
00365 case CursorWindow::key_end: pageEnd(vp); return false;
00366 case 0x02: pageBottom(vp); return false;
00367 case 0x14: pageTop(vp); return false;
00368 case 0x13: findFirst(vp); return false;
00369 case 0x0e: findNext(vp,false); return false;
00370
00372 case CursorWindow::key_f9:
00373 {
00374
00375 CursorInfo tmp = cursorInfo();
00376
00377 insertRowAbove(vp,bi);
00378
00379
00380 (*this)(vp, CursorWindow::viewport::repaint_handler::activate);
00381 setCursorInfo(vp, tmp);
00382 }
00383 return false;
00385 case CursorWindow::key_f11:
00386 {
00387 CursorInfo tmp = cursorInfo();
00388
00389 insertRowBelow(vp,bi);
00390 (*this)(vp, CursorWindow::viewport::repaint_handler::activate);
00391 setCursorInfo(vp, tmp);
00392 }
00393 return false;
00395 case CursorWindow::key_f8:
00396 {
00397 CursorInfo tmp = cursorInfo();
00398
00399 deleteRow(vp);
00400 (*this)(vp, CursorWindow::viewport::repaint_handler::activate);
00401 setCursorInfo(vp, tmp);
00402 }
00403 return false;
00404
00405
00406 }
00407 }
00408 }
00409
00410 return true;
00411 }
00412
00415
00416 string const &TableViewer::application_name() const
00417 {
00418 static string empty("some table");
00419
00420 return empty;
00421 }
00424
00425 string TableViewer::description() const
00426 {
00427 return "the table viewer base class";
00428 }
00429
00432
00433 void TableViewer::help()
00434 {
00435 }
00436
00439
00440
00441 bool TableViewer::is_dirty() const
00442 {
00443 return dataDirty_;
00444 }
00445
00448
00449 size_t TableViewer::longestRowTitle() const
00450 {
00451 size_t rv = 0;
00452
00453 vector<RowInfo>::const_iterator first = rows_.begin(), last = rows_.end();
00454
00455 while(first != last)
00456 {
00457 RowInfo const &cur = *first++;
00458
00459 size_t length = cur.title_.size();
00460
00461 if(length > rv)
00462 rv = length;
00463
00464 }
00465
00466 return rv;
00467 }
00468
00471 size_t TableViewer::CellInfo::widestRow() const
00472 {
00473 vector<string>::const_iterator first = text_.begin(), last = text_.end();
00474
00475 size_t rv = 0;
00476
00477 while(first != last)
00478 {
00479 string const &cur = *first++;
00480
00481 size_t length = cur.size();
00482
00483 if(length > rv)
00484 rv = length;
00485
00486 }
00487
00488 return rv;
00489 }
00492 void TableViewer::setRowsAndColumns(size_t rows, size_t cols)
00493 {
00494 layout_.resize(rows);
00495
00496 for(size_t i = 0; i < layout_.size(); ++i)
00497 {
00498 layout_.resize(cols);
00499 }
00500
00501 rows_.resize(rows);
00502 cols_.resize(cols);
00503
00504 recomputeLayout();
00505
00506
00507 }
00510 size_t TableViewer::columnWidth(size_t col) const
00511 {
00512 size_t rv = 0;
00513
00514 if(cols_.size() > col)
00515 {
00516 rv = cols_[col].width_;
00517 }
00518
00519 LayoutType::const_iterator firstRow = layout_.begin(), lastRow = layout_.end();
00520
00521 while(firstRow != lastRow)
00522 {
00523 LayoutType::value_type const &curRow = *firstRow++;
00524
00525 if(curRow.size() > col)
00526 {
00527
00528
00529 size_t width = curRow[col].widestRow();
00530
00531 if(width > rv)
00532 rv = width;
00533
00534 }
00535 }
00536
00537 return rv;
00538
00539 }
00542 TableViewer::CellInfo const *
00543 TableViewer::cellInfo(size_t row, size_t col) const
00544 {
00545 return const_cast<TableViewer*>(this)->cellInfo(row,col);
00546 }
00547
00550 TableViewer::CellInfo *
00551 TableViewer::cellInfo(size_t row, size_t col)
00552 {
00553 if(row < rows())
00554 if(col < cols_.size())
00555 {
00556
00557
00558
00559
00560 while(layout_.size() <= row)
00561 {
00562 layout_.push_back( LayoutType::value_type() );
00563 }
00564
00565 while(layout_[row].size() <= col)
00566 {
00567 layout_[row].push_back( LayoutType::value_type::value_type() );
00568 }
00569
00570 return &layout_[row][col];
00571 }
00572
00573 return 0;
00574
00575 }
00576
00579 void TableViewer::recomputeLayout()
00580 {
00581
00582
00583
00584
00585 if(!layoutDirty_)
00586 return;
00587
00588 layoutDirty_ = false;
00589
00590 LayoutType::iterator firstRow = layout_.begin(), lastRow = layout_.end();
00591
00592 vector<size_t> colWidths_;
00593
00594
00595
00596 for(size_t col=0; col < cols_.size(); ++col)
00597 {
00598 size_t colWidth = columnWidth(col);
00599
00600 colWidths_.push_back(colWidth);
00601 }
00602
00603
00604
00605 size_t worldY = 0;
00606
00607 while(firstRow != lastRow)
00608 {
00609 LayoutType::value_type &curRow = *firstRow++;
00610
00611 size_t worldX = 0;
00612
00613 curRow.resize( cols_.size() );
00614
00615 LayoutType::value_type::iterator firstCol = curRow.begin();
00616 LayoutType::value_type::iterator lastCol = curRow.end();
00617
00618 vector<size_t>::const_iterator widthPtr = colWidths_.begin(), widthEnd = colWidths_.end();
00619
00620 size_t tallestCellHeight=1;
00621
00622 while(firstCol != lastCol && widthPtr != widthEnd )
00623 {
00624 CellInfo &cell = *firstCol++;
00625
00626 ++worldX;
00627
00628 cell.worldColumn_ = worldX;
00629 cell.worldRow_ = worldY;
00630
00631 worldX += *widthPtr++;
00632
00633 size_t cellHeight = cell.text_.size();
00634
00635 if(cellHeight > tallestCellHeight)
00636 tallestCellHeight = cellHeight;
00637
00638 }
00639
00640 worldY += tallestCellHeight;
00641
00642 }
00643 }
00644
00647 void TableViewer::setCursorInfo(CursorWindow::viewport *vp,
00648 size_t r,
00649 size_t c,
00650 bool v)
00651 {
00652 if(r != cursorRow_ || c != cursorCol_ )
00653 {
00654 hideCursor(vp);
00655 }
00656
00657 cursorRow_ = r;
00658 cursorCol_ = c;
00659 cursorDisplayed_ = v;
00660
00661 if(v)
00662 showCursor(vp);
00663 }
00664
00667 void TableViewer::hideCursor(CursorWindow::viewport *vp)
00668 {
00669 cursorDisplayed_ = false;
00670
00671 paintCursor(vp);
00672
00673 }
00676 void TableViewer::showCursor(CursorWindow::viewport *vp)
00677 {
00678 cursorDisplayed_ = true;
00679 paintCursor(vp);
00680
00681 }
00684 void TableViewer::paintCursor(CursorWindow::viewport *vp)
00685 {
00686
00687
00688 if(vp)
00689 {
00690
00691 size_t cursorRowDelta = cursorRow_ - originRow();
00692 size_t cursorColDelta = cursorCol_ - originCol();
00693
00694 if(cursorRowDelta < pageHeight_ && cursorColDelta < pageWidth_)
00695 {
00696
00697
00698 size_t screenRowDelta = 0;
00699
00700 size_t screenColDelta = 0;
00701
00702 if(layout_.size() > cursorRow_ && layout_[cursorRow_].size() > cursorCol_)
00703 {
00704 CellInfo const &cursorCell = layout_[cursorRow_][cursorCol_];
00705
00706 screenRowDelta = cursorCell.worldRow_ -
00707 layout_[originRow()][originCol()].worldRow_;
00708
00709 screenColDelta = cursorCell.worldColumn_ -
00710 layout_[originRow()][originCol()].worldColumn_;
00711
00712 }
00713
00714 int screenRow = screenRowDelta + displayOrigin_.row_;
00715 int screenCol = screenColDelta + displayOrigin_.col_;
00716
00717 setTextInputPointer(screenRow, screenCol+1);
00718
00719 paintCell(vp,
00720 screenRow,
00721 screenCol,
00722 cursorRow_,
00723 cursorCol_,
00724 cursorDisplayed_
00725 );
00726
00727
00728 positionTextInputPointer(vp);
00729
00730
00731
00732
00733 }
00734
00735
00736 }
00737 }
00738
00739 static int textAtt(bool bold, bool underlined, bool reversed)
00740 {
00741 int rv = CursorWindow::normal;
00742
00743 if(bold && underlined && reversed)
00744 {
00745 return CursorWindow::dialog_title_att;
00746 }
00747 else
00748 if(bold && underlined)
00749 {
00750 return CursorWindow::inactive_title_att;
00751 }
00752 else
00753 if(bold && reversed)
00754 {
00755 return CursorWindow::active_title_att;
00756 }
00757 else
00758 if(underlined && reversed)
00759 {
00760 return CursorWindow::active_mark_att;
00761 }
00762 else
00763 if(underlined)
00764 {
00765 return CursorWindow::bottom_att;
00766 }
00767 else
00768 if(reversed)
00769 {
00770 return CursorWindow::highlighted_att;
00771 }
00772 else
00773 if(bold)
00774 {
00775 return CursorWindow::inactive_mark_att;
00776 }
00777
00778 return rv;
00779
00780 }
00781
00782
00785 void TableViewer::paintCell(CursorWindow::viewport *vp,
00786 size_t vpRow,
00787 size_t vpCol,
00788 size_t tbRow,
00789 size_t tbCol,
00790 bool highlight,
00791 bool editCursor
00792 )
00793 {
00794 size_t vpColumns = colWidths_[tbCol];
00795
00796 CellInfo const *cell = cellInfo(tbRow,tbCol);
00797
00798 if(cell == 0)
00799 return;
00800
00801
00802
00803
00804
00805
00806
00807
00808 vp->set_curpos(vpRow, vpCol);
00809
00810 bool bold = rows_[tbRow].bold_ || cols_[tbCol].bold_;
00811
00812 bool underline = rows_[tbRow].bottomBorder_;
00813
00814
00815 if(highlight && cursorDisplayed_)
00816 {
00817 vp->set_text_attribute(textAtt(bold, underline, true));
00818 }
00819 else
00820 vp->set_text_attribute(textAtt(bold, underline, false));
00821
00822 if(cols_[tbCol].leftBorder_)
00823 *vp << "|";
00824 else
00825 *vp << " ";
00826
00827
00828 paintField(vp, vpRow, vpCol, cell, 0, vpColumns, editCursor);
00829
00830
00831 }
00834 void TableViewer::paintField(CursorWindow::viewport *vp,
00835 size_t vpRow,
00836 size_t vpCol,
00837 TableViewer::CellInfo const *cell,
00838 size_t cellRow,
00839 size_t vpColumns,
00840 bool ignored
00841 )
00842 {
00843
00844
00845 char const *data = "";
00846 size_t length= 0;
00847
00848 if(cell)
00849 {
00850 if(cell->text_.size() > cellRow)
00851 {
00852 data = cell->text_[cellRow].data();
00853 length = cell->text_[cellRow].size();
00854 }
00855 }
00856
00857 if(length > vpColumns)
00858 {
00859 length = vpColumns;
00860 }
00861
00862 vp->write(data, length);
00863
00864 if(length < vpColumns)
00865 vp->write(' ', vpColumns - length);
00866 }
00869 void TableViewer::moveUp(CursorWindow::viewport *vp)
00870 {
00871 if(cursorRow_ > originRow_)
00872 {
00873 setCursorInfo(vp, cursorRow_-1, cursorCol_, true);
00874 return;
00875 }
00876
00877
00878
00879
00880
00881 if(originRow())
00882 {
00883 size_t col = cursorCol_;
00884
00885 hideCursor(vp);
00886
00887 setOrigin( originRow() - 1, originCol() );
00888
00889 (*this)(vp, CursorWindow::viewport::repaint_handler::activate);
00890
00891 setCursorInfo(vp, originRow(), col);
00892 }
00893 }
00896 void TableViewer::moveDown(CursorWindow::viewport *vp)
00897 {
00898
00899 size_t pageDeltaRow = cursorRow_ - originRow();
00900
00901 if(pageDeltaRow < pageHeight_-1)
00902 {
00903 setCursorInfo(vp, cursorRow_+1, cursorCol_, true);
00904 return;
00905 }
00906
00907 if(rows() && cursorRow_ < rows() )
00908 {
00909 size_t col = cursorCol_;
00910
00911 hideCursor(vp);
00912
00913 if(originRow() < rows()-1)
00914 setOrigin( originRow() + 1, originCol() );
00915 else
00916 setOrigin( rows()-1, originCol() );
00917
00918 (*this)(vp, CursorWindow::viewport::repaint_handler::activate);
00919
00920
00921
00922 setCursorInfo(vp, originRow() + pageHeight_-1, col );
00923 }
00924
00925
00926
00927 }
00930 void TableViewer::moveLeft(CursorWindow::viewport *vp)
00931 {
00932 if(cursorCol_ > originCol())
00933 {
00934 setCursorInfo(vp, cursorRow_, cursorCol_ - 1);
00935 return;
00936 }
00937
00938 if(originCol())
00939 {
00940 size_t row = cursorRow_;
00941
00942 hideCursor(vp);
00943
00944 setOrigin( originRow(), originCol() - 1 );
00945
00946 (*this)(vp, CursorWindow::viewport::repaint_handler::activate);
00947
00948 setCursorInfo(vp, row, originCol());
00949
00950 }
00951 }
00954 void TableViewer::moveRight(CursorWindow::viewport *vp)
00955 {
00956 if(cursorCol_ < originCol() + pageWidth_ -1)
00957 {
00958 setCursorInfo(vp, cursorRow_, cursorCol_ +1);
00959 return;
00960 }
00961
00962
00963
00964 if(originCol() < cols_.size()-1)
00965 {
00966 size_t row = cursorRow_;
00967
00968 hideCursor(vp);
00969
00970 setOrigin( originRow(), originCol() + 1 );
00971
00972 (*this)(vp, CursorWindow::viewport::repaint_handler::activate);
00973
00974 setCursorInfo(vp, row, originCol() + pageWidth_ -1);
00975 }
00976 }
00977
00980 void TableViewer::pageUp(CursorWindow::viewport *vp)
00981 {
00982 size_t pageHeight = vp->size().row_-1;
00983
00984 {
00985 size_t savedCol = cursorCol_;
00986
00987 if(originRow() < pageHeight)
00988 {
00989 setOrigin( 0, originCol() );
00990 }
00991 else
00992 setOrigin( originRow() - pageHeight, originCol() );
00993
00994 (*this)(vp, CursorWindow::viewport::repaint_handler::activate);
00995
00996 setCursorInfo(vp, originRow(), savedCol);
00997 }
00998 }
01001 void TableViewer::pageDown(CursorWindow::viewport *vp)
01002 {
01003 size_t pageHeight = vp->size().row_-1;
01004
01005 if(rows() && originRow() < layout_.size())
01006 {
01007 size_t targetRow = originRow() + pageHeight;
01008
01009 if( originRow() >= layout_.size()-1-pageHeight )
01010 {
01011 targetRow = layout_.size()-1;
01012 }
01013
01014 size_t savedCol = cursorCol_;
01015
01016 if(targetRow >= layout_.size())
01017 {
01018 if(layout_.size() == 0)
01019 targetRow = 0;
01020 else
01021 targetRow = layout_.size()-1;
01022 }
01023
01024 setOrigin( targetRow, originCol() );
01025
01026 (*this)(vp, CursorWindow::viewport::repaint_handler::activate);
01027
01028 setCursorInfo(vp, originRow(), savedCol);
01029 }
01030
01031 }
01034 void TableViewer::pageRight(CursorWindow::viewport *vp)
01035 {
01036 if(cols_.size())
01037 {
01038 size_t newOrigin = originCol() + pageWidth_-1;
01039
01040 if(newOrigin >= cols_.size())
01041 {
01042
01043
01044 newOrigin = cols_.size()-1;
01045
01046 }
01047
01048 size_t colDelta = cursorCol_ - originCol_;
01049
01050 if(newOrigin + colDelta >= cols_.size())
01051 {
01052 colDelta = 0;
01053 }
01054
01055 size_t row = cursorRow_;
01056
01057 hideCursor(vp);
01058
01059 setOrigin( originRow(), newOrigin );
01060
01061 (*this)(vp, CursorWindow::viewport::repaint_handler::activate);
01062
01063 setCursorInfo(vp, row, originCol() + colDelta);
01064 }
01065 }
01066
01069 void TableViewer::pageLeft(CursorWindow::viewport *vp)
01070 {
01071 size_t colDelta = cursorCol_ - originCol();
01072 size_t row = cursorRow_;
01073
01074 if(originCol() > pageWidth_-1)
01075 {
01076 size_t pageDelta = pageWidth_-1;
01077
01078 if(pageDelta == 0 && originCol() > pageDelta)
01079 pageDelta = 1;
01080
01081 hideCursor(vp);
01082
01083 setOrigin( originRow(), originCol() - pageDelta );
01084
01085 (*this)(vp, CursorWindow::viewport::repaint_handler::activate);
01086
01087 setCursorInfo(vp, row, originCol() + colDelta);
01088
01089 }
01090 else
01091 {
01092 hideCursor(vp);
01093 setOrigin(originRow(), 0);
01094 (*this)(vp, CursorWindow::viewport::repaint_handler::activate);
01095 setCursorInfo(vp, row, 0);
01096 }
01097 }
01098
01101 void TableViewer::pageHome(CursorWindow::viewport *vp)
01102 {
01103 setOrigin( 0, 0);
01104
01105 (*this)(vp, CursorWindow::viewport::repaint_handler::activate);
01106 }
01107
01110 void TableViewer::pageEnd(CursorWindow::viewport *vp)
01111 {
01112 if(cols_.size())
01113 {
01114 setOrigin( originRow(), cols_.size() - 1 );
01115
01116 (*this)(vp, CursorWindow::viewport::repaint_handler::activate);
01117 }
01118 }
01121 void TableViewer::pageBottom(CursorWindow::viewport *vp)
01122 {
01123 if(rows())
01124 {
01125 size_t savedCursorCol = cursorCol_;
01126 size_t targetRow = rows()-1;
01127
01128 setOrigin( targetRow, originCol());
01129
01130 (*this)(vp, CursorWindow::viewport::repaint_handler::activate);
01131
01132 setCursorInfo(vp, targetRow, savedCursorCol);
01133
01134 }
01135 }
01138 void TableViewer::pageTop(CursorWindow::viewport *vp)
01139 {
01140 size_t savedCursorCol = cursorCol_;
01141
01142 setOrigin(0, originCol());
01143
01144 (*this)(vp, CursorWindow::viewport::repaint_handler::activate);
01145
01146 setCursorInfo(vp, 0, savedCursorCol);
01147
01148 }
01151 void TableViewer::clear()
01152 {
01153 rows_.clear();
01154 cols_.clear();
01155 layout_.clear();
01156 colWidths_.clear();
01157
01158 setCursorInfo(0,0,0);
01159 setOrigin(0,0);
01160
01161 }
01164 void TableViewer::positionTextInputPointer(CursorWindow::viewport *vp)
01165 {
01166 vp->refresh();
01167 vp->set_curpos(textInputPointer_.row_, textInputPointer_.col_);
01168 }
01169
01172 void TableViewer::insertRowAbove(CursorWindow::viewport *vp, RowInfo const &info)
01173 {
01174 LayoutType::iterator rowPointer = layout_.begin() + cursorRow_;
01175
01176 layout_.insert(rowPointer, LayoutType::value_type());
01177
01178 for(size_t col=0; col < cols_.size(); ++col)
01179 {
01180 layout_[cursorRow_].push_back(CellInfo());
01181
01182 layout_[cursorRow_].back().text_.push_back("");
01183 }
01184
01185 vector<RowInfo>::iterator rowIterator = rows_.begin()+cursorRow_;
01186
01187 rows_.insert(rowIterator, info);
01188
01189 forceRelayout();
01190
01191 }
01194 void TableViewer::insertRowBelow(CursorWindow::viewport *vp, RowInfo const &info)
01195 {
01196 if(cursorRow_ < layout_.size()-1)
01197 {
01198
01199
01200
01201 ++cursorRow_;
01202
01203 insertRowAbove(vp,info);
01204 }
01205 else
01206 {
01207 layout_.push_back(LayoutType::value_type());
01208
01209 for(size_t col=0; col < cols_.size(); ++col)
01210 {
01211 layout_[cursorRow_].push_back(CellInfo());
01212
01213 layout_[cursorRow_].back().text_.push_back("");
01214 }
01215
01216 vector<RowInfo>::iterator rowIterator = rows_.begin()+cursorRow_;
01217
01218 rows_.insert(rowIterator, info);
01219
01220 ++cursorRow_;
01221
01222
01223 forceRelayout();
01224
01225
01226
01227 }
01228 }
01231 void TableViewer::RowInfo::setRowTitleNumber(size_t row)
01232 {
01233 char buffer[40];
01234
01235 sprintf(buffer, "%lu", (unsigned long)row);
01236
01237 title_ = buffer;
01238 }
01239
01242 void TableViewer::deleteRow(CursorWindow::viewport *vp)
01243 {
01244
01245
01246 if(cursorRow_ < layout_.size())
01247 {
01248 LayoutType::iterator rowIterator = layout_.begin() + cursorRow_;
01249
01250 layout_.erase(rowIterator);
01251
01252 forceRelayout();
01253 }
01254 }
01255
01256
01257 void TableViewer::findFirst(CursorWindow::viewport *vp)
01258 {
01259 CursorWindow::Dialog dialog("Find string");
01260
01261 char const *mix = "Y";
01262
01263 if(mixed_case_ == false)
01264 mix = "N";
01265
01266 dialog += new CursorWindow::Dialog::String("case",
01267 "Mixed case",
01268 mix,
01269 2
01270 );
01271
01272
01273 dialog += new CursorWindow::Dialog::String("mode",
01274 "(W)ord, (R)egexp, or (S)tring",
01275 (is_regex_ ? "R" : (match_words_ ? "W" : "S")),
01276 2
01277 );
01278
01279 dialog += new CursorWindow::Dialog::String("text",
01280 "Search for",
01281 search_text_,
01282 40
01283 );
01284
01285 dialog += new CursorWindow::Dialog::Ok("ok","");
01286
01287 dialog.set_first_input_field("text");
01288
01289
01290 if( dialog.popup(vp->window()) )
01291 return;
01292
01293 std::string mixed_case = dialog.element_value("case");
01294
01295 if( mixed_case.size()
01296 && ( mixed_case[0] == 'n'
01297 || mixed_case[0] == 'N'
01298 )
01299 )
01300 {
01301 mixed_case_ = false;
01302 }
01303 else
01304 if( mixed_case.size()
01305 && (mixed_case[0] == 'y' || mixed_case[0] == 'Y')
01306 )
01307 {
01308 mixed_case_ = true;
01309 }
01310
01311 std::string match_words = dialog.element_value("mode");
01312
01313 match_words_ = false;
01314 is_regex_ = false;
01315
01316 if( match_words.size()
01317 && ( match_words[0] == 'r'
01318 || match_words[0] == 'R'
01319 )
01320 )
01321 {
01322 is_regex_ = true;
01323 }
01324 else
01325 if( match_words.size()
01326 && (match_words[0] == 'w' || mixed_case[0] == 'W')
01327 )
01328 {
01329 match_words_ = true;
01330 }
01331
01332 std::string search_text = dialog.element_value("text");
01333
01334 if(search_text.size() == 0)
01335 return;
01336
01337 search_text_ = search_text;
01338
01339 findNext(vp, true);
01340
01341 }
01342
01343
01344 struct CharCompare
01346 {
01347 TableViewer const *impl_;
01348
01349 bool operator() (char a, char b) const
01350 {
01351 if(impl_->mixed_case())
01352 {
01353 if( isupper(a) )
01354 a = tolower(a);
01355
01356 if( isupper(b) )
01357 b = tolower(b);
01358
01359 return a == b;
01360 }
01361
01362 return a == b;
01363 }
01364
01365 CharCompare(TableViewer const* t)
01366 : impl_(t)
01367 {
01368 }
01369
01370 };
01371
01372
01373 bool TableViewer::findNext(CursorWindow::viewport *vp, bool first)
01374 {
01375 size_t row = cursorRow_;
01376 size_t col = cursorCol_;
01377
01378
01379 if(!first)
01380 ++col;
01381
01382 SimpleRegex regex(search_text_, (mixed_case_ ? "i" : "") );
01383
01384
01385 while(row < layout_.size())
01386 {
01387 while(col < layout_[row].size())
01388 {
01389 if(layout_[row][col].text_.empty())
01390 {
01391 ++col;
01392 continue;
01393 }
01394
01395 string const &cell = layout_[row][col].text_[0];
01396
01397 bool found = false;
01398
01399 if(is_regex_)
01400 {
01401 if( regex(cell, 0, cell.size() ) != 0)
01402 found = true;
01403 }
01404 else
01405 {
01406 string::const_iterator match;
01407
01408 string::const_iterator searchStart = cell.begin();
01409 string::const_iterator searchEnd = cell.end();
01410
01411 do
01412 {
01413 match=search(searchStart,
01414 searchEnd,
01415 search_text_.begin(),
01416 search_text_.end(),
01417 CharCompare(this)
01418 );
01419
01420 if(match_words_)
01421 {
01422 if(match != searchEnd)
01423 {
01424 found = true;
01425
01426
01427
01428
01429
01430 if(match != cell.begin())
01431 {
01432 string::const_iterator before = match; --before;
01433
01434 if(isalnum(*before))
01435 {
01436 found = false;
01437 ++searchStart;
01438 }
01439 }
01440
01441 if(found)
01442 {
01443 string::const_iterator end = match+search_text_.size();
01444
01445 if(end != searchEnd)
01446 {
01447 if(isalnum(*end))
01448 {
01449 found = false;
01450 ++searchStart;
01451 }
01452 }
01453
01454 }
01455 }
01456 }
01457 else
01458 if(match != searchEnd)
01459 found=true;
01460 }
01461 while(!found && match != searchEnd);
01462
01463
01464 }
01465
01466 if(found)
01467 {
01468
01469 hideCursor(vp);
01470
01471 if( row >= originRow() + pageHeight_
01472 || col >= originCol() + pageWidth_
01473 || col < originCol()
01474 )
01475 {
01476 size_t rowBackoff = pageHeight_ / 2;
01477 size_t colBackoff = pageWidth_ / 2;
01478
01479 size_t targetRow = row;
01480 size_t targetCol = col;
01481
01482
01483 if(targetRow > rowBackoff)
01484 targetRow = row - rowBackoff;
01485 else
01486 targetRow = 0;
01487
01488 if(targetCol > colBackoff)
01489 targetCol = col - colBackoff;
01490 else
01491 targetCol = 0;
01492
01493
01494 setOrigin(targetRow, targetCol);
01495
01496 (*this)(vp, CursorWindow::viewport::repaint_handler::activate);
01497 }
01498
01499 setCursorInfo(vp, row, col);
01500
01501 return true;
01502 }
01503
01504 ++col;
01505 }
01506
01507 ++row;
01508 col=0;
01509 }
01510
01511 vp->beep();
01512
01513 return false;
01514
01515 }
01516 }