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/tableeditor.h>
00031 #include <cxxtls/viewermanager.h>
00032 #include <iostream>
00033 #include <fstream>
00034 #include <cxxtls/strtool.h>
00035 #include <cxxtls/file.h>
00036
00037 using namespace std;
00038
00039 namespace cxxtls
00040 {
00041
00044 TableEditor::~TableEditor()
00045 {
00046 }
00049 TableEditor::TableEditor(ViewerManager *vm, int delimiter)
00050 : TableViewer(vm)
00051 , fieldEditColumn_(0)
00052 , delimiter_(delimiter)
00053 , keyKludge_(0)
00054 {
00055 set_data_dirty(false);
00056 }
00059 TableViewer::CellInfo *TableEditor::editCell()
00060 {
00061 if(rows() && cols())
00062 {
00063 CursorInfo cursor = cursorInfo();
00064
00065 return cellInfo(cursor.row_, cursor.col_);
00066
00067 }
00068
00069 return 0;
00070 }
00075 bool TableEditor::handle_event( CursorWindow::input_event const * e,
00076 CursorWindow::viewport * vp
00077 )
00078 {
00079 if( e->type_ == CursorWindow::input_event::DataKey
00080 || e->type_ == CursorWindow::input_event::FunctionKey
00081 )
00082 {
00083
00084
00085
00086 if(keyKludge_)
00087 {
00088 keyKludge_ = false;
00089
00090 switch(e->value_)
00091 {
00092 case 0x03:
00093 return true;
00094
00095
00096 default: vp->beep(); break;
00097 }
00098
00099 return false;
00100 }
00101
00102
00103
00104 if(isTableEditKey(e) && !fieldEditable(cursorInfo()))
00105 {
00106 vp->beep();
00107 return false;
00108 }
00109
00110
00111 switch(e->value_)
00112 {
00113 case 0x18:
00114 {
00115 keyKludge_ = true;
00116 }
00117 return false;
00118
00119 case 0x10:
00120 {
00121 pageRight(vp);
00122 }
00123 return false;
00124
00125 case 0x11:
00126 {
00127 pageLeft(vp);
00128 }
00129 return false;
00130
00131 case 0x09:
00132 {
00133 moveRight(vp);
00134 }
00135 return false;
00136
00137 case CursorWindow::key_btab:
00138 {
00139 moveLeft(vp);
00140 }
00141 return false;
00142
00143
00144
00145 case 0x01:
00146 {
00147 CellInfo *cell = editCell();
00148
00149 if(cell)
00150 {
00151 if(cell->text_.size())
00152 {
00153
00154
00155 fieldEditColumn_ = 0;
00156 paintCursor(vp);
00157 }
00158 }
00159
00160 }
00161 return false;
00162
00163 case 0x05:
00164 {
00165 CellInfo *cell = editCell();
00166
00167 if(cell)
00168 {
00169 if(cell->text_.size())
00170 {
00171
00172
00173 fieldEditColumn_ = cell->text_[0].size();
00174 paintCursor(vp);
00175 }
00176 }
00177
00178 }
00179 return false;
00180
00181
00182 case CursorWindow::key_dc:
00183 {
00184
00185 CellInfo *cell = editCell();
00186
00187 if(cell)
00188 {
00189 if(cell->text_.size())
00190 {
00191
00192
00193 string &text = cell->text_[0];
00194
00195 if(fieldEditColumn_ < text.size())
00196 {
00197 set_data_dirty(true);
00198
00199 text.erase(fieldEditColumn_, 1);
00200
00201 checkLayoutRecompute();
00202
00203 paintCursor(vp);
00204 }
00205
00206 }
00207 }
00208
00209 }
00210 return false;
00211
00212 case CursorWindow::key_bs:
00213 {
00214
00215 CellInfo *cell = editCell();
00216
00217 if(cell)
00218 {
00219 if(cell->text_.size())
00220 {
00221
00222
00223 string &text = cell->text_[0];
00224
00225 if(fieldEditColumn_ <= text.size() && fieldEditColumn_ > 0)
00226 {
00227 set_data_dirty(true);
00228
00229 --fieldEditColumn_;
00230
00231 text.erase(fieldEditColumn_, 1);
00232
00233 checkLayoutRecompute();
00234
00235 paintCursor(vp);
00236 }
00237
00238 }
00239 }
00240
00241 }
00242 return false;
00243
00244 case CursorWindow::key_left:
00245 {
00246
00247
00248
00249
00250
00251
00252
00253 CellInfo *cell = editCell();
00254
00255 if(cell)
00256 {
00257
00258
00259 if(fieldEditColumn_)
00260 {
00261 --fieldEditColumn_;
00262 paintCursor(vp);
00263 return false;
00264 }
00265 }
00266
00267 }
00268 break;
00269
00270 case CursorWindow::key_right:
00271 {
00272
00273
00274
00275
00276
00277
00278
00279 CellInfo *cell = editCell();
00280
00281 if(cell)
00282 {
00283
00284 if(cell->text_.size())
00285 {
00286
00287
00288 string &text = cell->text_[0];
00289
00290 if(fieldEditColumn_ < text.size())
00291 {
00292 ++fieldEditColumn_;
00293
00294 paintCursor(vp);
00295
00296 return false;
00297 }
00298
00299 }
00300 }
00301
00302 }
00303 break;
00304
00305
00306 case CursorWindow::key_f9:
00307 {
00308 RowInfo ri;
00309
00310 TableViewer::CursorInfo info = cursorInfo();
00311
00312 ri.setRowTitleNumber(info.row_+1);
00313
00314
00315 TableViewer::insertRowAbove(vp, ri);
00316
00317 for(size_t i = 0; i < rows(); ++i)
00318 {
00319 ri = rowInfo(i);
00320
00321 ri.setRowTitleNumber(i+1);
00322
00323 setRowInfo(i, ri);
00324
00325 }
00326
00327
00328 (*this)(vp, CursorWindow::viewport::repaint_handler::activate);
00329
00330 TableViewer::setCursorInfo(vp, info);
00331
00332
00333 }
00334 return false;
00335
00336
00337 case 0x0d:
00338 case 0x0a:
00339 {
00340
00341 RowInfo ri;
00342
00343 TableViewer::CursorInfo info = cursorInfo();
00344
00345 ri.setRowTitleNumber(info.row_+2);
00346
00347
00348 TableViewer::insertRowBelow(vp, ri);
00349
00350 for(size_t i = 0; i < rows(); ++i)
00351 {
00352 ri = rowInfo(i);
00353
00354 ri.setRowTitleNumber(i+1);
00355
00356
00357 setRowInfo(i, ri);
00358
00359 }
00360
00361 (*this)(vp, CursorWindow::viewport::repaint_handler::activate);
00362
00363 TableViewer::setCursorInfo(vp, info);
00364 }
00365 return false;
00366
00367 case CursorWindow::key_f8:
00368 {
00369 TableViewer::CursorInfo info = cursorInfo();
00370
00371 if(info.row_ < rows_.size())
00372 {
00373
00374 RowInfo ri;
00375
00376
00377 TableViewer::deleteRow(vp);
00378
00379 for(size_t i = 0; i < rows(); ++i)
00380 {
00381 ri = rowInfo(i);
00382
00383 ri.setRowTitleNumber(i+1);
00384
00385 setRowInfo(i, ri);
00386
00387 }
00388
00389 (*this)(vp, CursorWindow::viewport::repaint_handler::activate);
00390
00391 TableViewer::setCursorInfo(vp, info);
00392 }
00393 }
00394 return false;
00395
00396
00397 default:
00398
00399 if(e->type_ == CursorWindow::input_event::DataKey)
00400 {
00401 set_data_dirty(true);
00402
00403 if(e->value_ >= ' ' && e->value_ < 0x7f)
00404 {
00405 char data = e->value_;
00406
00407 if(data == delimiter_)
00408 {
00409 vp->beep();
00410 data = ' ';
00411 }
00412
00413 CellInfo *cell = editCell();
00414
00415 if(cell)
00416 {
00417
00418 if(cell->text_.empty())
00419 {
00420 cell->text_.push_back("");
00421 }
00422
00423 {
00424
00425
00426 string &text = cell->text_[0];
00427
00428 if(fieldEditColumn_ > text.size())
00429 {
00430 fieldEditColumn_ = text.size();
00431 }
00432
00433 text.insert(fieldEditColumn_, 1, data);
00434
00435 ++fieldEditColumn_;
00436
00437 checkLayoutRecompute();
00438
00439 paintCursor(vp);
00440
00441 return false;
00442 }
00443 }
00444 }
00445 }
00446
00447 break;
00448
00449 }
00450 }
00451
00452
00453
00454
00455 bool quitNow = TableViewer::handle_event(e,vp);
00456
00457 return quitNow;
00458 }
00459
00462 void TableEditor::snatchEdit(CursorWindow::viewport *vp, FileName const &directory)
00463 {
00464
00465
00466
00467
00468 CellInfo *cell = editCell();
00469
00470 if(cell)
00471 {
00472
00473 string &text = cell->text_[0];
00474
00475 if(fieldEditColumn_ < text.size())
00476 {
00477 string operand( text.begin() + fieldEditColumn_, text.end() );
00478
00479 FileName filename;
00480 int lineNo = 0;
00481
00482 string tmp;
00483
00484 bool success = StrTool::snatch_file_info(operand, tmp, lineNo);
00485
00486 if(success)
00487 {
00488 filename = manager_->find_file_in_standard_locations(tmp, directory);
00489
00490 if(!filename.empty())
00491 {
00492
00493 Viewer* oldie = manager_->find_viewer(filename);
00494
00495 if(oldie)
00496 {
00497 if(lineNo > 0)
00498 oldie->set_row_col_hint(lineNo-1,0);
00499
00500 manager_->activate(oldie);
00501 }
00502 else
00503 {
00504 if(!filename.exists())
00505 {
00506 CursorWindow::Message m(filename + " does not exist");
00507
00508 m += "Sorry, can't find it";
00509 m += "";
00510 m += "Press Enter to continue";
00511
00512 m.popup(manager_->window());
00513
00514 return;
00515 }
00516
00517 Viewer *newbie = manager_->edit(filename);
00518
00519 if(!newbie)
00520 manager_->window()->beep();
00521 else
00522 {
00523 if(lineNo > 0)
00524 newbie->set_row_col_hint(lineNo-1, 0);
00525
00526 manager_->vsplit(newbie, filename);
00527 }
00528
00529 }
00530
00531
00532 }
00533 else
00534 {
00535 CursorWindow::Message m(string("Error: ") + tmp);
00536
00537 m += "File cannot be found";
00538 m += "";
00539 m += "Press Enter to continue";
00540
00541 m.popup(manager_->window());
00542 }
00543
00544 }
00545 else
00546 {
00547 CursorWindow::Message m("Error");
00548
00549 m += "The cell you are in does not contain a file name";
00550 m += "at the current cursor position.";
00551 m += "";
00552 m += "Press Enter to continue";
00553
00554 m.popup(manager_->window());
00555 }
00556 }
00557 }
00558
00559
00560
00561
00562 vp->beep();
00563 }
00564
00565
00566
00569 void TableEditor::setCursorInfo(CursorWindow::viewport *vp,
00570 size_t worldRow,
00571 size_t worldCol,
00572 bool displayed
00573 )
00574 {
00575 terminateInput();
00576
00577 TableViewer::setCursorInfo(vp, worldRow, worldCol, displayed);
00578 }
00579
00582 void TableEditor::terminateInput()
00583 {
00584 fieldEditColumn_ = 0;
00585 }
00586
00589 void TableEditor::paintField(CursorWindow::viewport *vp,
00590 size_t vpRow,
00591 size_t vpCol,
00592 TableViewer::CellInfo const *cell,
00593 size_t cellRow,
00594 size_t vpColumns,
00595 bool editCursor
00596 )
00597 {
00598
00599
00600 CursorWindow::row_col vpSize = vp->size();
00601
00602 size_t vpRemainingColumns = vpSize.col_ - vpCol;
00603
00604 if(vpColumns > vpRemainingColumns)
00605 {
00606 vpColumns = vpRemainingColumns;
00607 }
00608
00609
00610 if(cell == 0 )
00611 return;
00612
00613 if( cell->text_.size() <= cellRow
00614 || cell->text_[cellRow].size() < vpColumns
00615 )
00616 {
00617 TableViewer::paintField(vp, vpRow, vpCol, cell, cellRow, vpColumns, editCursor);
00618
00619 setTextInputPointer(vpRow, vpCol + 1 + fieldEditColumn_);
00620 }
00621 else
00622 {
00623
00624
00625 string const &text = cell->text_[cellRow];
00626
00627 if(fieldEditColumn_ == text.size())
00628 {
00629
00630
00631
00632 char const *p = text.data() + text.size() - vpColumns + 2;
00633
00634 vp->write(p, vpColumns-2);
00635
00636 *vp << " ";
00637
00638 setTextInputPointer(vpRow, vpCol + vpColumns-1);
00639
00640 }
00641 else
00642 {
00643
00644
00645 char const *p = text.data();
00646
00647 size_t charOffset = 0;
00648
00649 if(fieldEditColumn_ > text.size())
00650 {
00651 fieldEditColumn_ = text.size();
00652 }
00653
00654 if(fieldEditColumn_+1 >= vpColumns)
00655 {
00656 charOffset = (fieldEditColumn_+2) - vpColumns;
00657 }
00658
00659 size_t remainingLength = text.size() - charOffset;
00660
00661 if(remainingLength > vpColumns)
00662 remainingLength = vpColumns;
00663
00664 vp->write(p + charOffset, remainingLength);
00665
00666 CursorWindow::row_col curpos;
00667
00668 if(remainingLength < vpColumns)
00669 {
00670
00671 curpos = vp->curpos();
00672
00673 vp->write(' ', vpColumns - remainingLength);
00674
00675 curpos = vp->curpos();
00676
00677 }
00678
00679 CursorWindow::row_col cp= vp->curpos();
00680
00681
00682 setTextInputPointer(vpRow, vpCol + 1 + fieldEditColumn_ - charOffset);
00683
00684 if(editCursor)
00685 {
00686 if(size_t(cp.row_) != vpRow || cp.col_ >= vpSize.col_)
00687 {
00688
00689
00690 vp->set_curpos(vpRow, vpCol + vpColumns-1);
00691
00692 }
00693 else
00694 {
00695 vp->set_curpos(vpRow, vpCol + 1 + fieldEditColumn_ - charOffset);
00696 }
00697 }
00698
00699 }
00700 }
00701
00702 }
00703
00704 bool TableEditor::isTableEditKey(CursorWindow::input_event const * e)
00705 {
00706 if(e->value_ >= ' ' && e->value_ <= '~')
00707 return true;
00708
00709 switch(e->value_)
00710 {
00711 case 0x08: return true;
00712 case CursorWindow::key_dc: return true;
00713 case CursorWindow::key_bs: return true;
00714
00715 }
00716
00717
00718 return false;
00719 }
00720
00721 }