📄 qeditor.cpp
字号:
/*************************************************************************** qeditor.cpp (c) 2000-2003 Beno� Minisini <gambas@users.sourceforge.net> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.***************************************************************************//************************************************************************ $Id: qt/src/widgets/qeditor.cpp 2.3.1 edited 2001-03-30 $**** Implementation of QEditor widget class**** Created : 961005**** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.**** This file is part of the widgets module of the Qt GUI Toolkit.**** This file may be distributed under the terms of the Q Public License** as defined by Trolltech AS of Norway and appearing in the file** LICENSE.QPL included in the packaging of this file.**** This file may be distributed and/or modified under the terms of the** GNU General Public License version 2 as published by the Free Software** Foundation and appearing in the file LICENSE.GPL included in the** packaging of this file.**** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition** licenses may use this file in accordance with the Qt Commercial License** Agreement provided with the Software.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.**** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for** information about Qt Commercial License Agreements.** See http://www.trolltech.com/qpl/ for QPL licensing information.** See http://www.trolltech.com/gpl/ for GPL licensing information.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#include <qeditor.h>#include <qpainter.h>#include <qscrollbar.h>#include <qclipboard.h>#include <qpixmap.h>#include <qregexp.h>#include <qapplication.h>#include <qdragobject.h>#include <qpopupmenu.h>#include <qtimer.h>#include <qdict.h>#include <qcursor.h>#include <qstyle.h>#include <ctype.h>#include "main.h"/* I want windows shortcuts */#define _WS_WIN_#define xOffset() contentsX()#define yOffset() contentsY()#define viewWidth() visibleWidth()#define viewHeight() visibleHeight()#define totalHeight() contentsHeight()//#define updateContents() viewport()->repaint()#undef QMAX#undef QMINstatic int QMAX(int a, int b){ return a >= b ? a : b;}static int QMIN(int a, int b){ return a <= b ? a : b;}int QEditor::topCell() const{ return rowAt(contentsY());}void QEditor::setTopCell(int row){ updateScrollBars(); setContentsPos(contentsX(), row * cellHeight()); emit scrolled();}void QEditor::setBottomCell(int row){ updateScrollBars(); setContentsPos(contentsX(), QMAX(0, (row + 1) * cellHeight() - visibleHeight())); emit scrolled();}void QEditor::ensureLineVisible(int row){ //setContentsPos(contentsX(), QMAX(0, row * cellHeight() + (cellHeight() - visibleHeight()) / 2)); ensureVisible(0, row * cellHeight() + cellHeight() / 2, 0, 100);}void QEditor::setXOffset(int x){ setContentsPos(x, contentsY());}void QEditor::setYOffset(int y){ //qDebug("setYOffset(%d) -> topCell = %d", y, topCell()); setContentsPos(contentsX(), y);}bool QEditor::rowIsVisible(int row) const{ return (row >= rowAt(contentsY()) && row <= rowAt(contentsY() + visibleHeight() - 1));}int QEditor::lastRowVisible() const{ return rowAt(contentsY() + visibleHeight() - cellHeight());}bool QEditor::rowYPos(int row, int *yPos) const{ int y = row * cellHeight() - contentsY(); *yPos = y; return !(y < 0 || y >= (visibleHeight() - cellHeight()));}int QEditor::findRow(int y) const{ if (y < 0 || y >= visibleHeight()) return -1; else return rowAt(contentsY() + y);}QRect QEditor::viewRect() const{ return QRect(0, 0, visibleWidth(), visibleHeight());}int QEditor::posX(int x, int y) const{ if (x < 0) x = cursorX; if (y < 0) y = cursorY; return mapToView(x, y) - contentsX();}int QEditor::posY(int x, int y) const{ if (y < 0) y = cursorY; return y * cellHeight() - contentsY();}void QEditor::setY(int newY){ if (newY < 0) newY = 0; if (newY >= numLines()) newY = numLines() - 1; if (cursorY != newY) colorize(cursorY); cursorY = newY;}static void addData(ColorDataArray *data, int state, bool nocompress = false){ unsigned int pos; pos = data->count(); if (nocompress || data->isNull() || (*data)[pos - 1].state != (unsigned int)state || (*data)[pos - 1].len == 4095) { data->resize(pos + 1); (*data)[pos].state = state; (*data)[pos].len = 1; } else { (*data)[pos - 1].len = (*data)[pos - 1].len + 1; } //qDebug("addData: data->count() = %d", data->count());}static void changeData(ColorDataArray *data, int state){ if (data->isNull()) return; (*data)[data->count() - 1].state = state;}bool QEditorRow::isProc(QString &s){ uint i; QChar c; QString symbol; for (i = 0; i < s.length(); i++) { c = s[i]; if (!c.isLetter() && symbol.length() > 0) { symbol = symbol.upper(); if (symbol == "PRIVATE" || symbol == "PUBLIC" || symbol == "STATIC") { symbol = ""; continue; } else break; } if (c.isLetter()) symbol += c; else if (!c.isSpace()) return false; } return (symbol == "SUB" || symbol == "PROCEDURE" || symbol == "FUNCTION");}void QEditorRow::analyze(QString &s, ColorDataArray &data){ enum { Decimal, Binary, Hexa }; unsigned int i; QChar c, cn; QString sc; int state = Normal; int prev_state = Normal; int sub_type = 0; QChar last_op; unsigned int start = 0; bool first_symbol = true; bool esc = false; bool nocompress; bool first_keyword = false; bool last_decl = false; bool decl_keyword = false; data.resize(0); for (i = 0; i < s.length(); i++) { if (i == 0) c = s[0]; else c = cn; if (i < s.length()) cn = s[i + 1]; else cn = '\n'; prev_state = state; nocompress = false; if (state == Normal && !c.isSpace()) { if (c.isLetter() || c == '$' || c == '_') { state = Symbol; start = i; } else if (c == '"') { state = String; } else if (c == '\'') state = Commentary; else if (c == '&') { if (cn.lower() == 'x') { state = Number; sub_type = Binary; } else if (cn.lower() == 'h' || cn.isDigit() || (cn.lower() >= 'a' && cn.lower() <= 'f')) { state = Number; sub_type = Hexa; } else state = Operator; } else if (c.isDigit()) { state = Number; sub_type = Decimal; } else if ((c == '+' || c == '-') && cn.isDigit()) { state = Number; sub_type = Decimal; } else if (c == '?') { sc = "PRINT"; if (cn != ' ') sc = sc + ' '; s = s.replace(i, 1, sc); start = i; state = Symbol; cn = 'R'; } else { state = Operator; last_op = c; nocompress = (c != '>' && c != '/' && c != '='); } } addData(&data, state, nocompress); switch (state) { case Symbol: if (cn.isLetter() || cn.isDigit() || cn == '_' || cn == '?' || cn == '$') { // continue } else { unsigned int len = i - start + 1; sc = s.mid(start, len).lower(); const char *look = sc.latin1(); const char *repl = NULL; //qDebug("Symbol = '%s'", (s.mid(start, len)).latin1();); if (last_decl) { last_decl = false; } else if (last_op != "." && last_op != "!") { if (cn != '(') { if (!first_keyword) { repl = QEditor::firstDict[look]; if (repl) { last_decl = true; state = Keyword; } } if (!repl) { repl = QEditor::keywordDict[look]; if (repl) { if ((cn != '.' && cn != '[') || qstrcmp(repl, "ME") == 0 || qstrcmp(repl, "LAST") == 0) { state = Keyword; decl_keyword = qstrcmp(repl, "AS") == 0 || qstrcmp(repl, "NEW") == 0; } else repl = NULL; } } } if (!repl && decl_keyword) { repl = QEditor::typeDict[look]; if (repl && (i < (s.length() - 2)) && (cn == '[') && (s[i + 2] == ']')) { //qDebug("repl = %s", repl); addData(&data, state); addData(&data, state); len += 2; sc = s.mid(start, len); look = sc.latin1(); repl = QEditor::typeDict[look]; i += 2; } state = Datatype; } if (!repl && decl_keyword) decl_keyword = false; if (!repl) { repl = QEditor::subrDict[look]; state = Subr; } if (repl) { s = s.replace(start, len, repl); changeData(&data, state); first_keyword = true; } } first_symbol = false; state = Normal; last_op = 0; } break; case Number: if (sub_type != Decimal && c == '&' && prev_state != Normal) state = Normal; else if (!(cn.isLetter() || cn.isDigit() || (sub_type == Decimal && (cn == '.' || cn.lower() == 'e' || cn == '+' || cn == '-')) || (sub_type != Decimal && cn == '&'))) state = Normal; break; case String: if ((prev_state == String) && c == '"' && !esc) state = Normal; else if (esc) esc = false; else esc = (c == '\\'); break; case Commentary: break; default: state = Normal; break; } }}void QEditorRow::colorize(void){ unsigned int i; QChar c; if (!modify) return; modify = false; for (i = s.length() - 1; i >= 0; i--) { if (!s[i].isSpace()) break; } //if (i >= 0) // s = s.left(i + 1); /*for (i = 0; i < s.length(); i++) { c = s[i]; if (!c.isSpace()) { if (c == '?') s.replace(i, 1, "PRINT "); break; } }*/ analyze(s, data); line = isProc(s); //qDebug("colorize, data.count() = %d", data.count());}void QEditorRow::drawBack(QPainter & p, int x, int y, int w, int h, QColor *color, bool current){ if (type) { if (type == TypeCurrent) p.fillRect(x, y, w, h, color[Current]); else if (type == TypeBreakpoint) p.fillRect(x, y, w, h, color[Breakpoint]); else { p.fillRect(x, y, w, h, QColor((color[Current].red() + color[Breakpoint].red()) / 2, (color[Current].green() + color[Breakpoint].green()) / 2, (color[Current].blue() + color[Breakpoint].blue()) / 2)); } } else if (current) p.fillRect(x, y, w, h, color[Line]);}void QEditorRow::draw(QPainter & p, int x, int y, int w, int h, QColor color[], bool useRelief){ unsigned int i, pos; int len, wd, style; QString sd; y += p.fontMetrics().ascent(); if (type) { if (useRelief) { p.setPen(color[Normal]); p.drawText(x + 1, y + 1, s); } p.setPen(color[Background]); p.drawText(x, y, s); return; } if (modify) { p.setPen(color[Normal]); p.drawText(x, y, s); return; } pos = 0; for (i = 0; i < data.count(); i ++) { style = data[i].state; len = data[i].len; sd = s.mid(pos, len); //if (style == Keyword) // sd = sd.upper(); //p.drawText(x, y, w, h, Qt::ExpandTabs, sd); if (style == Keyword && useRelief) { p.setPen(color[Normal]); p.drawText(x + 1, y + 1, sd); p.setPen(color[style]); p.drawText(x, y, sd); } else { p.setPen(color[style]); p.drawText(x, y, sd); } pos += len; wd = p.fontMetrics().width(sd); //p.boundingRect(x, y, w, h, Qt::ExpandTabs, sd).width(); x += wd; w -= wd; } if (pos < s.length()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -