📄 keditcl1.cpp
字号:
/* $Id: keditcl1.cpp,v 1.1 2003/09/08 19:42:08 jasonk Exp $ KEdit, a simple text editor for the KDE project Copyright (C) 1997 Bernd Johannes Wuebben wuebben@math.cornell.edu This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. KEdit, simple editor class, hacked version of the original by */#include "keditcl.h"#include <klocale.h>#include <kapp.h>#include "keditcl.h"KEdit::KEdit(KApplication *a, QWidget *parent, const char *name, const char *fname) : QMultiLineEdit(parent, name){ mykapp = a; filename = fname; filename.detach(); rb_popup = 0L; modified = FALSE; // fancy optimized refreshing (Matthias and Paul)#if QT_VERSION >= 142 repaintTimer = new QTimer(this); connect(repaintTimer, SIGNAL(timeout()), this, SLOT(repaintAll()));#endif // set some defaults line_pos = col_pos = 0; fill_column_is_set = TRUE; word_wrap_is_set = TRUE; fill_column_value = 80; autoIndentMode = false; reduce_white_on_justify = true; current_directory = QDir::currentDirPath(); make_backup_copies = TRUE; installEventFilter( this ); srchdialog = NULL; replace_dialog= NULL; file_dialog = NULL; gotodialog = NULL; connect(this, SIGNAL(textChanged()), this, SLOT(setModified())); setContextSens();}KEdit::~KEdit(){}void KEdit::repaintAll(){ repaint(FALSE);}int KEdit::currentLine(){ computePosition(); return line_pos;};int KEdit::currentColumn(){ computePosition(); return col_pos;}bool KEdit::WordWrap(){ return word_wrap_is_set;}void KEdit::setWordWrap(bool flag ){ word_wrap_is_set = flag;}bool KEdit::FillColumnMode(){ return fill_column_is_set;}void KEdit::setFillColumnMode(int line, bool set){ fill_column_is_set = set; fill_column_value = line;}int KEdit::loadFile(QString name, int mode){ int fdesc; struct stat s; char *addr; QFileInfo info(name); if(!info.exists()){ QMessageBox::warning( this, klocale->translate("Sorry"), klocale->translate("The specified File does not exist"), klocale->translate("OK"), "", "", 0,0 ); return KEDIT_RETRY; } if(info.isDir()){ QMessageBox::warning( this, klocale->translate("Sorry:"), klocale->translate("You have specificated a directory"), klocale->translate("OK"), "", "", 0,0 ); return KEDIT_RETRY; } if(!info.isReadable()){ QMessageBox::warning( this, klocale->translate("Sorry"), klocale->translate("You do not have read permission to this file."), klocale->translate("OK"), "", "", 0,0 ); return KEDIT_RETRY; } fdesc = open(name, O_RDONLY); if(fdesc == -1) { switch(errno) { case EACCES: QMessageBox::warning( this, klocale->translate("Sorry"), klocale->translate("You do not have read permission to this file."), klocale->translate("OK"), "", "", 0,0 ); return KEDIT_OS_ERROR; default: QMessageBox::warning( this, klocale->translate("Sorry"), klocale->translate("An Error occured while trying to open this Document"), klocale->translate("OK"), "", "", 0,0 ); return KEDIT_OS_ERROR; } } emit loading(); mykapp->processEvents(); fstat(fdesc, &s); addr = (char *)mmap(0, s.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fdesc, 0); setAutoUpdate(FALSE); disconnect(this, SIGNAL(textChanged()), this, SLOT(setModified()));// The following is a horrible hack that we need to put up with until// Qt 1.3 comes along. The problem is that QMultiLineEdit::setText(char*)// is O(n^2) which makes loading larger files very slow. We resort here to// a workaroud which load the file line by line. I use a memmap construction// but probably a QTextStream is just about as fast. if(mode & OPEN_INSERT) { register long int i; char *beginning_of_line; beginning_of_line = addr; int line, col; char c = '\n'; if(s.st_size != 0){ c = *(addr + s.st_size - 1 ); // save the last character of the file } // this boolean will indicate whether we already have inserted the first line. bool past_first_line = false; getCursorPosition(&line,&col); // let's save the position of the cursor int save_line = line; int save_col = col; for(i = 0; i < s.st_size; i++){ if( *(addr + i) == '\n' ){ *(addr + i) = '\0'; if(!past_first_line){ QString string; string = beginning_of_line; string += '\n'; insertAt(string,line,col); past_first_line = true; } else{ insertLine(beginning_of_line,line); } line ++; beginning_of_line = addr + i + 1; } } // What if the last char of the file wasn't a newline? // In this case we have to manually insert the last "couple" of characters. // This routine could be avoided if I knew for sure that I could // memmap a file into a block of memory larger than the file size. // In that case I would simply put a zero after the last char in the file. // and the above would go through almost unmodified. Well, I don't, so // here we go: if( c != '\n'){ // we're in here if s.st_size != 0 and last char != '\n' char* buf = (char*)malloc(addr + i - 1 - beginning_of_line + 2); strncpy(buf, beginning_of_line, addr + i - 1 - beginning_of_line +1); buf[ addr + i - 1 - beginning_of_line + 1 ] = '\0'; append(buf); free(buf); } // restore the initial Curosor Position setCursorPosition(save_line,save_col); } else{ // Not inserting but loading a completely new file. register long int i; char *beginning_of_line; beginning_of_line = addr; // eradicate the old text. this->clear(); char c = '\n'; if(s.st_size != 0){ c = *(addr + s.st_size - 1 ); // save the last character of the file } for(i = 0; i < s.st_size; i++){ if( *(addr + i) == '\n' ){ *(addr + i) = '\0'; append(beginning_of_line); beginning_of_line = addr + i + 1; } } // Same consideration as above: if( c != '\n'){ // we're in here if s.st_size != 0 and last char != '\n' char* buf = (char*)malloc(addr + i - 1 - beginning_of_line + 2); strncpy(buf, beginning_of_line, addr + i - 1 - beginning_of_line +1); buf[ addr + i - 1 - beginning_of_line + 1 ] = '\0'; append(buf); free(buf); } } setAutoUpdate(TRUE);#if QT_VERSION < 142 repaint();#else if (!repaintTimer->isActive()) repaintTimer->start(0,TRUE);#endif connect(this, SIGNAL(textChanged()), this, SLOT(setModified())); munmap(addr, s.st_size); if ( mode == OPEN_INSERT) toggleModified(TRUE); else toggleModified(FALSE); if(!(mode == OPEN_INSERT)){ filename = name; filename.detach(); } if( mode == OPEN_READONLY) this->setReadOnly(TRUE); else this->setReadOnly(FALSE); emit(fileChanged()); setFocus(); return KEDIT_OK;}int KEdit::insertFile(){ QFileDialog *box; QString file_to_insert; box = getFileDialog(klocale->translate("Select Document to Insert")); box->show(); if (!box->result()) { return KEDIT_USER_CANCEL; } if(box->selectedFile().isEmpty()) { /* no selection */ return KEDIT_USER_CANCEL; } file_to_insert = box->selectedFile(); file_to_insert.detach(); int result = loadFile(file_to_insert, OPEN_INSERT); if (result == KEDIT_OK ) setModified(); return result;}int KEdit::openFile(int mode){ QString fname; QFileDialog *box; int result; if( isModified() ) { switch( QMessageBox::warning( this, klocale->translate("Warning:"), klocale->translate("The current Document has been modified.\n"\ "Would you like to save it?"), klocale->translate("Yes"), klocale->translate("No"), klocale->translate("Cancel"), 0, 2 ) ) { case 0: // Yes or Enter result = doSave(); if ( result == KEDIT_USER_CANCEL) return KEDIT_USER_CANCEL; if (result != KEDIT_OK){ switch(QMessageBox::warning( this, klocale->translate("Sorry:"), klocale->translate("Could not save the document.\n"\ "Open a new document anyways?"), klocale->translate("Yes"), klocale->translate("No"), "", 0,1 ) ) { case 0: break; case 1: return KEDIT_USER_CANCEL; break; } } break; case 1: // No break; case 2: // cancel return KEDIT_USER_CANCEL; break; } } box = getFileDialog(klocale->translate("Select Document to Open")); box->show(); if (!box->result()) /* cancelled */ return KEDIT_USER_CANCEL; if(box->selectedFile().isEmpty()) { /* no selection */ return KEDIT_USER_CANCEL; } fname = box->selectedFile(); int result2 = loadFile(fname, mode); if ( result2 == KEDIT_OK ) toggleModified(FALSE); return result2; }int KEdit::newFile(){ int result; if( isModified() ) { switch( QMessageBox::warning( this, klocale->translate("Warning:"), klocale->translate("The current Document has been modified.\n"\ "Would you like to save it?"), klocale->translate("Yes"), klocale->translate("No"), klocale->translate("Cancel"), 0, 2 ) ) { case 0: // Yes or Enter result = doSave(); if ( result == KEDIT_USER_CANCEL) return KEDIT_USER_CANCEL; if (result != KEDIT_OK){ switch(QMessageBox::warning(this, klocale->translate("Sorry:"), klocale->translate("Could not save the document.\n"\ "Create a new document anyways?"), klocale->translate("Yes"), klocale->translate("No"), "", 0,1 )){ case 0: break; case 1: return KEDIT_USER_CANCEL; break; } } break; case 1: // No break; case 2: // cancel return KEDIT_USER_CANCEL; break; } } this->clear(); toggleModified(FALSE); setFocus(); filename = klocale->translate("Untitled"); computePosition(); emit(fileChanged()); return KEDIT_OK;}void KEdit::computePosition(){ int line, col, coltemp; getCursorPosition(&line,&col); QString linetext = textLine(line); // O.K here is the deal: The function getCursorPositoin returns the character // position of the cursor, not the screenposition. I.e,. assume the line // consists of ab\tc then the character c will be on the screen on position 8 // whereas getCursorPosition will return 3 if the cursors is on the character c. // Therefore we need to compute the screen position from the character position. // That's what all the following trouble is all about: coltemp = col; int pos = 0; int find = 0; int mem = 0; bool found_one = false; // if you understand the following algorithm you are worthy to look at the // kedit+ sources -- if not, go away ;-) while(find >=0 && find <= coltemp- 1 ){ find = linetext.find('\t', find, TRUE ); if( find >=0 && find <= coltemp - 1 ){ found_one = true; pos = pos + find - mem; pos = pos + 8 - pos % 8; mem = find; find ++; } } pos = pos + coltemp - mem ; // add the number of characters behind the // last tab on the line. if (found_one){ pos = pos - 1; } line_pos = line; col_pos = pos;}void KEdit::keyPressEvent ( QKeyEvent *e){ if ((e->state() & ControlButton ) && (e->key() == Key_K) ){ int line = 0; int col = 0; QString killstring; if(!killing){ killbufferstring = ""; killtrue = false; lastwasanewline = false; } getCursorPosition(&line,&col); killstring = textLine(line);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -