merged 2.2 branch

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@7748 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Bryan Petty
2000-07-15 19:51:35 +00:00
parent 8a693e6e04
commit f6bcfd974e
1835 changed files with 237729 additions and 67990 deletions

View File

@@ -5,12 +5,11 @@
# Version: $Id$
###############################################################################
top_srcdir = @top_srcdir@
top_srcdir = @top_srcdir@/..
top_builddir = ../../..
this_dir = $(top_srcdir)/src/stc
scintilla_dir=$(this_dir)/scintilla
VPATH=$(this_dir)@PATH_IFS@$(scintilla_dir)/src # ':' for autoconf
scintilla_dir = $(top_srcdir)/contrib/src/stc/scintilla
libsrc_dir = contrib/src/stc@PATH_IFS@$(scintilla_dir)/src
TARGET_LIBNAME=libstc
@@ -18,23 +17,38 @@ LIBVERSION_CURRENT=1
LIBVERSION_REVISION=0
LIBVERSION_AGE=0
HEADER_PATH=$(top_srcdir)/contrib/include/wx
HEADER_SUBDIR=stc
HEADERS=stc.h
OBJECTS=PlatWX.o ScintillaWX.o stc.o \
Accessor.o \
AutoComplete.o \
DocumentAccessor.o \
LexCPP.o \
LexHTML.o \
LexOthers.o \
LexPerl.o \
LexPython.o \
LexSQL.o \
LexVB.o \
UniConversion.o \
WindowAccessor.o \
AutoComplete.o \
CallTip.o \
CellBuffer.o \
ContractionState.o \
CellBuffer.o \
ContractionState.o \
Document.o \
Editor.o \
Editor.o \
Indicator.o \
KeyMap.o \
KeyMap.o \
KeyWords.o \
LineMarker.o \
LineMarker.o \
PropSet.o \
ScintillaBase.o \
ScintillaBase.o \
Style.o \
ViewStyle.o
APPEXTRADEFS=-D__WX__ -DSCI_LEXER -I$(scintilla_dir)/src -I$(scintilla_dir)/include -I$(top_srcdir)/include -I$(top_srcdir)/../include
ViewStyle.o \
APPEXTRADEFS=-D__WX__ -DSCI_LEXER -I$(scintilla_dir)/src -I$(scintilla_dir)/include -I$(top_srcdir)/contrib/include
include $(top_builddir)/src/makelib.env

View File

@@ -4,12 +4,13 @@
// Robin Dunn <robin@aldunn.com>
// The License.txt file describes the conditions under which this software may be distributed.
#include <ctype.h>
#include "Platform.h"
#include "wx/stc/stc.h"
Point Point::FromLong(long lpoint) {
return Point(lpoint & 0xFFFF, lpoint >> 32);
return Point(lpoint & 0xFFFF, lpoint >> 16);
}
wxRect wxRectFromPRectangle(PRectangle prc) {
@@ -105,14 +106,15 @@ Font::Font() {
Font::~Font() {
}
void Font::Create(const char *faceName, int size, bool bold, bool italic) {
void Font::Create(const char *faceName, int characterSet, int size, bool bold, bool italic) {
Release();
id = new wxFont(size,
wxDEFAULT,
italic ? wxITALIC : wxNORMAL,
bold ? wxBOLD : wxNORMAL,
false,
faceName);
faceName,
wxFONTENCODING_DEFAULT);
}
@@ -167,7 +169,7 @@ void Surface::InitPixMap(int width, int height, Surface *surface_) {
Release();
hdc = new wxMemoryDC(surface_->hdc);
hdcOwned = true;
bitmap = new wxBitmap(width, height);
bitmap = new wxBitmap(width, height+1);
((wxMemoryDC*)hdc)->SelectObject(*bitmap);
// **** ::SetTextAlign(hdc, TA_BASELINE);
}
@@ -181,13 +183,26 @@ void Surface::BrushColor(Colour back) {
}
void Surface::SetFont(Font &font_) {
hdc->SetFont(*font_.GetID());
// I think the following check is valid.
// It eliminates a crash for me. -- eric@sourcegear.com
if (font_.GetID())
{
hdc->SetFont(*font_.GetID());
}
}
int Surface::LogPixelsY() {
return hdc->GetPPI().y;
}
int Surface::DeviceHeightFont(int points) {
return points * LogPixelsY() / 72;
}
void Surface::MoveTo(int x_, int y_) {
x = x_;
y = y_;
@@ -232,7 +247,7 @@ void Surface::FillRectangle(PRectangle rc, Surface &surfacePattern) {
void Surface::RoundedRectangle(PRectangle rc, Colour fore, Colour back) {
PenColour(fore);
BrushColor(back);
hdc->DrawRoundedRectangle(wxRectFromPRectangle(rc), 8);
hdc->DrawRoundedRectangle(wxRectFromPRectangle(rc), 4);
}
void Surface::Ellipse(PRectangle rc, Colour fore, Colour back) {
@@ -242,7 +257,8 @@ void Surface::Ellipse(PRectangle rc, Colour fore, Colour back) {
}
void Surface::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
hdc->Blit(rc.left, rc.top, rc.Width(), rc.Height(),
wxRect r = wxRectFromPRectangle(rc);
hdc->Blit(r.x, r.y, r.width, r.height,
surfaceSource.hdc, from.x, from.y, wxCOPY);
}
@@ -344,7 +360,11 @@ void Surface::SetClip(PRectangle rc) {
hdc->SetClippingRegion(wxRectFromPRectangle(rc));
}
void Surface::FlushCachedState() {
// TODO Is there anything we need to do here? eric@sourcegear.com
// TODO I had to add this method when I merged new Scintilla code
// TODO from Neil.
}
Window::~Window() {
}
@@ -365,7 +385,8 @@ PRectangle Window::GetPosition() {
}
void Window::SetPosition(PRectangle rc) {
id->SetSize(rc.left, rc.top, rc.Width(), rc.Height());
wxRect r = wxRectFromPRectangle(rc);
id->SetSize(r);
}
void Window::SetPositionRelative(PRectangle rc, Window) {
@@ -386,7 +407,8 @@ void Window::InvalidateAll() {
}
void Window::InvalidateRectangle(PRectangle rc) {
id->Refresh(false, &wxRectFromPRectangle(rc));
wxRect r = wxRectFromPRectangle(rc);
id->Refresh(false, &r);
}
void Window::SetFont(Font &font) {
@@ -465,7 +487,12 @@ int ListBox::GetSelection() {
}
int ListBox::Find(const char *prefix) {
return ((wxListBox*)id)->FindString(prefix);
for (int x=0; x < ((wxListBox*)id)->Number(); x++) {
wxString text = ((wxListBox*)id)->GetString(x);
if (text.StartsWith(prefix))
return x;
}
return -1;
}
void ListBox::GetValue(int n, char *value, int len) {

View File

@@ -14,6 +14,8 @@
// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
#include <ctype.h>
#include "ScintillaWX.h"
#include "wx/stc/stc.h"
@@ -60,6 +62,29 @@ void wxSTCDropTarget::OnLeave() {
}
class wxSTCCallTip : public wxWindow {
public:
wxSTCCallTip(wxWindow* parent, int ID, CallTip* ct)
: wxWindow(parent, ID)
{
m_ct = ct;
}
void OnPaint(wxPaintEvent& evt) {
wxPaintDC dc(this);
Surface surfaceWindow;
surfaceWindow.Init(&dc);
m_ct->PaintCT(&surfaceWindow);
surfaceWindow.Release();
}
CallTip* m_ct;
DECLARE_EVENT_TABLE()
};
BEGIN_EVENT_TABLE(wxSTCCallTip, wxWindow)
EVT_PAINT(wxSTCCallTip::OnPaint)
END_EVENT_TABLE()
//----------------------------------------------------------------------
// Constructor/Destructor
@@ -193,9 +218,8 @@ void ScintillaWX::NotifyParent(SCNotification scn) {
void ScintillaWX::Copy() {
if (currentPos != anchor) {
char* text = CopySelectionRange();
textDO.SetText(text);
wxTheClipboard->Open();
wxTheClipboard->SetData(&textDO);
wxTheClipboard->SetData(new wxTextDataObject(text));
wxTheClipboard->Close();
}
}
@@ -236,7 +260,7 @@ bool ScintillaWX::CanPaste() {
}
void ScintillaWX::CreateCallTipWindow(PRectangle) {
ct.wCallTip = new wxWindow(wDraw.GetID(), -1);
ct.wCallTip = new wxSTCCallTip(wDraw.GetID(), -1, &ct);
ct.wDraw = ct.wCallTip;
}
@@ -384,7 +408,10 @@ void ScintillaWX::DoButtonMove(Point pt) {
void ScintillaWX::DoAddChar(char ch) {
//bool acActiveBeforeCharAdded = ac.Active();
AddChar(ch);
//if (acActiveBeforeCharAdded)
// AutoCompleteChanged(ch);
}
int ScintillaWX::DoKeyDown(int key, bool shift, bool ctrl, bool alt) {
@@ -401,6 +428,9 @@ void ScintillaWX::DoContextMenu(Point pt) {
ContextMenu(pt);
}
void ScintillaWX::DoOnListBox() {
AutoCompleteCompleted();
}
//----------------------------------------------------------------------
@@ -433,12 +463,13 @@ void ScintillaWX::DoDragLeave() {
// Redraw all of text area. This paint will not be abandoned.
void ScintillaWX::FullPaint() {
paintState = painting;
rcPaint = GetTextRectangle();
wxClientDC dc(wMain.GetID());
Surface surfaceWindow;
surfaceWindow.Init(&dc);
Paint(&surfaceWindow, rcPaint);
surfaceWindow.Release();
// rcPaint = GetTextRectangle();
// wxClientDC dc(wMain.GetID());
// Surface surfaceWindow;
// surfaceWindow.Init(&dc);
// Paint(&surfaceWindow, rcPaint);
// surfaceWindow.Release();
wMain.GetID()->Refresh(FALSE);
paintState = notPainting;
}

View File

@@ -126,6 +126,7 @@ public:
void DoCommand(int ID);
void DoContextMenu(Point pt);
void DoOnListBox();
// helpers
@@ -139,7 +140,6 @@ private:
bool capturedMouse;
wxStyledTextCtrl* stc;
wxTextDataObject textDO;
wxSTCDropTarget* dropTarget;
wxDragResult dragResult;
};

View File

@@ -1,5 +1,5 @@
# Microsoft Developer Studio Project File - Name="StcVC" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# Microsoft Developer Studio Generated Build File, Format Version 5.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
@@ -22,11 +22,9 @@ CFG=StcVC - Win32 Debug
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "StcVC - Win32 Release"
@@ -40,11 +38,12 @@ RSC=rc.exe
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
RSC=rc.exe
# ADD BASE RSC /l 0x809
# ADD RSC /l 0x809
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O1 /Ob2 /I "../../../include" /I "../../include" /I "scintilla/include" /I "scintilla/src" /D "WIN32" /D "_WINDOWS" /D "__WINDOWS__" /D "__WXMSW__" /D "__WIN95__" /D "__WIN32__" /D WINVER=0x0400 /D "STRICT" /D "__WX__" /D "SCI_LEXER" /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x809
# ADD RSC /l 0x809
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
@@ -64,11 +63,12 @@ LIB32=link.exe -lib
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
RSC=rc.exe
# ADD BASE RSC /l 0x809
# ADD RSC /l 0x809
# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "../../../include" /I "../../include" /I "scintilla/include" /I "scintilla/src" /D "_DEBUG" /D DEBUG=1 /D "__WXDEBUG__" /D "WIN32" /D "_WINDOWS" /D "__WINDOWS__" /D "__WXMSW__" /D "__WIN95__" /D "__WIN32__" /D WINVER=0x0400 /D "STRICT" /D "__WX__" /D "SCI_LEXER" /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x809
# ADD RSC /l 0x809
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
@@ -179,6 +179,34 @@ SOURCE=.\scintilla\src\KeyWords.cxx
# End Source File
# Begin Source File
SOURCE=.\scintilla\src\LexCPP.cxx
# End Source File
# Begin Source File
SOURCE=.\scintilla\src\LexHTML.cxx
# End Source File
# Begin Source File
SOURCE=.\scintilla\src\LexOthers.cxx
# End Source File
# Begin Source File
SOURCE=.\scintilla\src\LexPerl.cxx
# End Source File
# Begin Source File
SOURCE=.\scintilla\src\LexPython.cxx
# End Source File
# Begin Source File
SOURCE=.\scintilla\src\LexSQL.cxx
# End Source File
# Begin Source File
SOURCE=.\scintilla\src\LexVB.cxx
# End Source File
# Begin Source File
SOURCE=.\scintilla\src\LineMarker.cxx
# End Source File
# Begin Source File

View File

@@ -2,7 +2,7 @@
# File: makefile.b32
# Author: Julian Smart
# Created: 1999
# Updated:
# Updated:
# Copyright:
#
# Makefile : Builds wxMMedia library for 32-bit BC++
@@ -21,25 +21,36 @@ STCEXTRACPPFLAGS=-D__WX__ -DSCI_LEXER -I$(SCINTILLA)/include -I$(S)
LIBTARGET=$(WXDIR)\contrib\lib\stc.lib
OBJECTS = \
Accessor.obj \
Accessor.obj \
AutoComplete.obj \
CallTip.obj \
CellBuffer.obj \
ContractionState.obj\
Document.obj \
CallTip.obj \
CellBuffer.obj \
ContractionState.obj \
Document.obj \
DocumentAccessor.obj \
Editor.obj \
Indicator.obj \
Indicator.obj \
KeyMap.obj \
KeyWords.obj \
LineMarker.obj \
PropSet.obj \
KeyWords.obj \
LexCPP.obj \
LexHTML.obj \
LexOthers.obj \
LexPerl.obj \
LexPython.obj \
LexSQL.obj \
LexVB.obj \
LineMarker.obj \
PropSet.obj \
ScintillaBase.obj \
Style.obj \
ViewStyle.obj \
UniConversion.obj \
ViewStyle.obj \
WindowAccessor.obj \
\
PlatWX.obj \
ScintillaWX.obj \
stc.obj \
ScintillaWX.obj \
stc.obj \
!include $(WXDIR)\src\makelib.b32

View File

@@ -25,6 +25,16 @@ OBJECTS = \
$(S)/ScintillaBase.$(OBJSUFF) \
$(S)/Style.$(OBJSUFF) \
$(S)/ViewStyle.$(OBJSUFF) \
$(S)/LexCPP.$(OBJSUFF) \
$(S)/LexHTML.$(OBJSUFF) \
$(S)/LexOthers.$(OBJSUFF) \
$(S)/LexPerl.$(OBJSUFF) \
$(S)/LexPython.$(OBJSUFF) \
$(S)/LexSQL.$(OBJSUFF) \
$(S)/LexVB.$(OBJSUFF) \
$(S)/DocumentAccessor.$(OBJSUFF)\
$(S)/UniConversion.$(OBJSUFF) \
$(S)/WindowAccessor.$(OBJSUFF) \
PlatWX.$(OBJSUFF) \
ScintillaWX.$(OBJSUFF) \
stc.$(OBJSUFF)

View File

@@ -15,21 +15,30 @@ NOPCH=1
!include $(WXDIR)\src\makevc.env
OBJECTS = \
$(D)\Accessor.obj \
$(D)\AutoComplete.obj \
$(D)\CallTip.obj \
$(D)\CellBuffer.obj \
$(D)\ContractionState.obj\
$(D)\Document.obj \
$(D)\DocumentAccessor.obj\
$(D)\Editor.obj \
$(D)\Indicator.obj \
$(D)\KeyMap.obj \
$(D)\KeyWords.obj \
$(D)\LexCPP.obj \
$(D)\LexHTML.obj \
$(D)\LexOthers.obj \
$(D)\LexPerl.obj \
$(D)\LexPython.obj \
$(D)\LexSQL.obj \
$(D)\LexVB.obj \
$(D)\LineMarker.obj \
$(D)\PropSet.obj \
$(D)\ScintillaBase.obj \
$(D)\Style.obj \
$(D)\UniConversion.obj \
$(D)\ViewStyle.obj \
$(D)\WindowAccessor.obj \
\
$(D)\PlatWX.obj \
$(D)\ScintillaWX.obj \

View File

@@ -3,5 +3,6 @@ scintilla/include directories from the Scintilla/SCiTE source
distribution. All other code needed to implement Scintilla on top of
wxWindows is located in the directory above this one.
The current version of the Scintilla code is somewhere between 1.22
and 1.23, (from their CVS.)
The current version of the Scintilla code is 1.25+ (from their CVS on
5-19-2000).

View File

@@ -3,26 +3,30 @@
// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
enum { wsSpace = 1, wsTab = 2, wsSpaceTab = 4, wsInconsistent=8};
class Accessor;
typedef bool (*PFNIsCommentLeader)(Accessor &styler, int pos, int len);
// Interface to data in a Scintilla
class Accessor {
protected:
// bufferSize is a trade off between time taken to copy the characters and SendMessage overhead
enum {extremePosition=0x7FFFFFFF};
// bufferSize is a trade off between time taken to copy the characters and retrieval overhead
// slopSize positions the buffer before the desired position in case there is some backtracking
enum {bufferSize=4000, slopSize=bufferSize/8};
char buf[bufferSize+1];
WindowID id;
PropSet &props;
int startPos;
int endPos;
int lenDoc;
int offset; // Optional but including an offset makes GCC generate better code
void Fill(int position);
int codePage;
virtual bool InternalIsLeadByte(char ch)=0;
virtual void Fill(int position)=0;
public:
Accessor(WindowID id_, PropSet &props_, int offset_=0) :
id(id_), props(props_), startPos(0x7FFFFFFF), endPos(0),
lenDoc(-1), offset(offset_) {
}
Accessor() : startPos(extremePosition), endPos(0), codePage(0) {}
virtual ~Accessor() {}
char operator[](int position) {
position += offset;
if (position < startPos || position >= endPos) {
Fill(position);
}
@@ -30,7 +34,6 @@ public:
}
char SafeGetCharAt(int position, char chDefault=' ') {
// Safe version of operator[], returning a defined value for invalid position
position += offset;
if (position < startPos || position >= endPos) {
Fill(position);
if (position < startPos || position >= endPos) {
@@ -40,37 +43,28 @@ public:
}
return buf[position - startPos];
}
char StyleAt(int position);
int GetLine(int position);
int LineStart(int line);
int LevelAt(int line);
int Length();
void Flush() {
startPos = 0x7FFFFFFF;
lenDoc = -1;
bool IsLeadByte(char ch) {
return codePage && InternalIsLeadByte(ch);
}
int GetLineState(int line);
int SetLineState(int line, int state);
PropSet &GetPropSet() { return props; }
};
class StylingContext : public Accessor {
char styleBuf[bufferSize];
int validLen;
char chFlags;
char chWhile;
unsigned int startSeg;
public:
StylingContext(WindowID id_, PropSet &props_, int offset_=0) :
Accessor(id_,props_,offset_), validLen(0), chFlags(0) {}
void StartAt(unsigned int start, char chMask=31);
void SetFlags(char chFlags_, char chWhile_) {chFlags = chFlags_; chWhile = chWhile_; };
void ColourSegment(unsigned int start, unsigned int end, int chAttr);
unsigned int GetStartSegment() { return startSeg; }
void StartSegment(unsigned int pos);
void ColourTo(unsigned int pos, int chAttr);
int GetLine(int position);
void SetLevel(int line, int level);
void Flush();
void SetCodePage(int codePage_) { codePage = codePage_; }
virtual char StyleAt(int position)=0;
virtual int GetLine(int position)=0;
virtual int LineStart(int line)=0;
virtual int LevelAt(int line)=0;
virtual int Length()=0;
virtual void Flush()=0;
virtual int GetLineState(int line)=0;
virtual int SetLineState(int line, int state)=0;
virtual int GetPropertyInt(const char *key, int defaultValue=0)=0;
// Style setting
virtual void StartAt(unsigned int start, char chMask=31)=0;
virtual void SetFlags(char chFlags_, char chWhile_)=0;
virtual unsigned int GetStartSegment()=0;
virtual void StartSegment(unsigned int pos)=0;
virtual void ColourTo(unsigned int pos, int chAttr)=0;
virtual void SetLevel(int line, int level)=0;
virtual int IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader = 0)=0;
};

View File

@@ -3,6 +3,39 @@
// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
void ColouriseDoc(int codePage, int startPos, int lengthDoc, int initStyle,
int language, WordList *keywordlists[], StylingContext &styler);
typedef void (*LexerFunction)(unsigned int startPos, int lengthDoc, int initStyle,
WordList *keywordlists[], Accessor &styler);
class LexerModule {
static LexerModule *base;
LexerModule *next;
int language;
LexerFunction fn;
public:
LexerModule(int language_, LexerFunction fn_);
static void Colourise(unsigned int startPos, int lengthDoc, int initStyle,
int language, WordList *keywordlists[], Accessor &styler);
};
inline bool iswordchar(char ch) {
return isalnum(ch) || ch == '.' || ch == '_';
}
inline bool iswordstart(char ch) {
return isalnum(ch) || ch == '_';
}
inline bool isoperator(char ch) {
if (isalnum(ch))
return false;
// '.' left out as it is used to make up numbers
if (ch == '%' || ch == '^' || ch == '&' || ch == '*' ||
ch == '(' || ch == ')' || ch == '-' || ch == '+' ||
ch == '=' || ch == '|' || ch == '{' || ch == '}' ||
ch == '[' || ch == ']' || ch == ':' || ch == ';' ||
ch == '<' || ch == '>' || ch == ',' || ch == '/' ||
ch == '?' || ch == '!' || ch == '.' || ch == '~')
return true;
return false;
}

View File

@@ -45,6 +45,7 @@
#pragma warning(disable: 4800 4244 4309)
#endif
#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#endif
@@ -209,16 +210,19 @@ public:
Font();
~Font();
void Create(const char *faceName, int size, bool bold=false, bool italic=false);
void Create(const char *faceName, int characterSet, int size, bool bold, bool italic);
void Release();
FontID GetID() { return id; }
// Alias another font - caller guarantees not to Release
void SetID(FontID id_) { id = id_; }
friend class Surface;
};
// A surface abstracts a place to draw
class Surface {
private:
bool unicodeMode;
#if PLAT_GTK
GdkDrawable *drawable;
GdkGC *gc;
@@ -266,6 +270,7 @@ public:
bool Initialised();
void PenColour(Colour fore);
int LogPixelsY();
int DeviceHeightFont(int points);
void MoveTo(int x_, int y_);
void LineTo(int x_, int y_);
void Polygon(Point *pts, int npts, Colour fore, Colour back);
@@ -290,6 +295,11 @@ public:
int SetPalette(Palette *pal, bool inBackGround);
void SetClip(PRectangle rc);
void FlushCachedState();
void SetUnicodeMode(bool unicodeMode_) {
unicodeMode=unicodeMode_;
}
};
// Class to hide the details of window manipulation
@@ -300,6 +310,7 @@ protected:
WindowID id;
public:
Window() : id(0) {}
Window(const Window &source) : id(source.id) {}
virtual ~Window();
Window &operator=(WindowID id_) {
id = id_;

View File

@@ -75,7 +75,7 @@ public:
else
return 0;
}
char operator[](int i) {
char operator[](int i) const {
if (s)
return s[i];
else
@@ -95,7 +95,7 @@ public:
}
return *this;
}
int value() {
int value() const {
if (s)
return atoi(s);
else
@@ -168,7 +168,7 @@ public:
WordList(bool onlyLineEnds_ = false) :
words(0), list(0), len(0), onlyLineEnds(onlyLineEnds_) {}
~WordList() { Clear(); }
operator bool() { return list; }
operator bool() { return list ? true : false; }
const char *operator[](int ind) { return words[ind]; }
void Clear();
void Set(const char *s);

View File

@@ -21,6 +21,8 @@
#define SCLEX_ERRORLIST 10
#define SCLEX_MAKEFILE 11
#define SCLEX_BATCH 12
#define SCLEX_XCODE 13
#define SCLEX_LATEX 14
// Lexical states for SCLEX_PYTHON
#define SCE_P_DEFAULT 0
@@ -35,6 +37,8 @@
#define SCE_P_DEFNAME 9
#define SCE_P_OPERATOR 10
#define SCE_P_IDENTIFIER 11
#define SCE_P_COMMENTBLOCK 12
#define SCE_P_STRINGEOL 13
// Lexical states for SCLEX_CPP, SCLEX_VB
#define SCE_C_DEFAULT 0
@@ -45,7 +49,7 @@
#define SCE_C_WORD 5
#define SCE_C_STRING 6
#define SCE_C_CHARACTER 7
#define SCE_C_PUNTUATION 8
#define SCE_C_UUID 8
#define SCE_C_PREPROCESSOR 9
#define SCE_C_OPERATOR 10
#define SCE_C_IDENTIFIER 11
@@ -63,49 +67,85 @@
#define SCE_H_OTHER 8
#define SCE_H_COMMENT 9
#define SCE_H_ENTITY 10
// Embedded Javascript
#define SCE_HJ_START 11
#define SCE_HJ_DEFAULT 12
#define SCE_HJ_COMMENT 13
#define SCE_HJ_COMMENTLINE 14
#define SCE_HJ_COMMENTDOC 15
#define SCE_HJ_NUMBER 16
#define SCE_HJ_WORD 17
#define SCE_HJ_KEYWORD 18
#define SCE_HJ_DOUBLESTRING 19
#define SCE_HJ_SINGLESTRING 20
#define SCE_HJ_SYMBOLS 21
#define SCE_HJ_STRINGEOL 28
// XML and ASP
#define SCE_H_TAGEND 22
#define SCE_H_XMLSTART 23
#define SCE_H_XMLEND 24
#define SCE_H_SCRIPT 25
#define SCE_H_ASP 26
#define SCE_H_ASPAT 27
#define SCE_H_TAGEND 11
#define SCE_H_XMLSTART 12
#define SCE_H_XMLEND 13
#define SCE_H_SCRIPT 14
#define SCE_H_ASP 15
#define SCE_H_ASPAT 16
// Embedded Javascript
#define SCE_HJ_START 40
#define SCE_HJ_DEFAULT 41
#define SCE_HJ_COMMENT 42
#define SCE_HJ_COMMENTLINE 43
#define SCE_HJ_COMMENTDOC 44
#define SCE_HJ_NUMBER 45
#define SCE_HJ_WORD 46
#define SCE_HJ_KEYWORD 47
#define SCE_HJ_DOUBLESTRING 48
#define SCE_HJ_SINGLESTRING 49
#define SCE_HJ_SYMBOLS 50
#define SCE_HJ_STRINGEOL 51
// ASP Javascript
#define SCE_HJA_START 55
#define SCE_HJA_DEFAULT 56
#define SCE_HJA_COMMENT 57
#define SCE_HJA_COMMENTLINE 58
#define SCE_HJA_COMMENTDOC 59
#define SCE_HJA_NUMBER 60
#define SCE_HJA_WORD 61
#define SCE_HJA_KEYWORD 62
#define SCE_HJA_DOUBLESTRING 63
#define SCE_HJA_SINGLESTRING 64
#define SCE_HJA_SYMBOLS 65
#define SCE_HJA_STRINGEOL 66
// Embedded VBScript
#define SCE_HB_START 40
#define SCE_HB_DEFAULT 41
#define SCE_HB_COMMENTLINE 42
#define SCE_HB_NUMBER 43
#define SCE_HB_WORD 44
#define SCE_HB_STRING 45
#define SCE_HB_IDENTIFIER 46
#define SCE_HB_STRINGEOL 47
#define SCE_HB_START 70
#define SCE_HB_DEFAULT 71
#define SCE_HB_COMMENTLINE 72
#define SCE_HB_NUMBER 73
#define SCE_HB_WORD 74
#define SCE_HB_STRING 75
#define SCE_HB_IDENTIFIER 76
#define SCE_HB_STRINGEOL 77
// ASP VBScript
#define SCE_HBA_START 80
#define SCE_HBA_DEFAULT 81
#define SCE_HBA_COMMENTLINE 82
#define SCE_HBA_NUMBER 83
#define SCE_HBA_WORD 84
#define SCE_HBA_STRING 85
#define SCE_HBA_IDENTIFIER 86
#define SCE_HBA_STRINGEOL 87
// Embedded Python
#define SCE_HP_START 50
#define SCE_HP_DEFAULT 51
#define SCE_HP_COMMENTLINE 52
#define SCE_HP_NUMBER 53
#define SCE_HP_STRING 54
#define SCE_HP_CHARACTER 55
#define SCE_HP_WORD 56
#define SCE_HP_TRIPLE 57
#define SCE_HP_TRIPLEDOUBLE 58
#define SCE_HP_CLASSNAME 59
#define SCE_HP_DEFNAME 60
#define SCE_HP_OPERATOR 61
#define SCE_HP_IDENTIFIER 62
#define SCE_HP_START 90
#define SCE_HP_DEFAULT 91
#define SCE_HP_COMMENTLINE 92
#define SCE_HP_NUMBER 93
#define SCE_HP_STRING 94
#define SCE_HP_CHARACTER 95
#define SCE_HP_WORD 96
#define SCE_HP_TRIPLE 97
#define SCE_HP_TRIPLEDOUBLE 98
#define SCE_HP_CLASSNAME 99
#define SCE_HP_DEFNAME 100
#define SCE_HP_OPERATOR 101
#define SCE_HP_IDENTIFIER 102
// ASP Python
#define SCE_HPA_START 105
#define SCE_HPA_DEFAULT 106
#define SCE_HPA_COMMENTLINE 107
#define SCE_HPA_NUMBER 108
#define SCE_HPA_STRING 109
#define SCE_HPA_CHARACTER 110
#define SCE_HPA_WORD 111
#define SCE_HPA_TRIPLE 112
#define SCE_HPA_TRIPLEDOUBLE 113
#define SCE_HPA_CLASSNAME 114
#define SCE_HPA_DEFNAME 115
#define SCE_HPA_OPERATOR 116
#define SCE_HPA_IDENTIFIER 117
// Lexical states for SCLEX_PERL
#define SCE_PL_DEFAULT 0
@@ -131,4 +171,11 @@
#define SCE_PL_BACKTICKS 20
#define SCE_PL_DATASECTION 21
// Lexical states for SCLEX_LATEX
#define SCE_L_DEFAULT 0
#define SCE_L_COMMAND 1
#define SCE_L_TAG 2
#define SCE_L_MATH 3
#define SCE_L_COMMENT 4
#endif

View File

@@ -89,7 +89,6 @@ extern "C" {
#define SCI_GETVIEWWS SCI_START + 20
#define SCI_SETVIEWWS SCI_START + 21
#define SCI_CHANGEPOSITION SCI_START + 22
#define SCI_GOTOLINE SCI_START + 24
#define SCI_GOTOPOS SCI_START + 25
#define SCI_SETANCHOR SCI_START + 26
@@ -107,6 +106,9 @@ extern "C" {
#define SCI_STARTSTYLING SCI_START + 32
#define SCI_SETSTYLING SCI_START + 33
// This is the same value as CP_UTF8 in Windows
#define SC_CP_UTF8 65001
#define SCI_SETBUFFEREDDRAW SCI_START + 35
#define SCI_SETTABWIDTH SCI_START + 36
#define SCI_SETCODEPAGE SCI_START + 37
@@ -156,7 +158,11 @@ extern "C" {
#define STYLE_BRACELIGHT 34
#define STYLE_BRACEBAD 35
#define STYLE_CONTROLCHAR 36
#define STYLE_MAX 63
#define STYLE_MAX 127
#define SC_CHARSET_ANSI 0
#define SC_CHARSET_DEFAULT 1
#define SC_CHARSET_RUSSIAN 204
#define SCI_STYLECLEARALL SCI_START + 50
#define SCI_STYLESETFORE SCI_START + 51
@@ -167,6 +173,8 @@ extern "C" {
#define SCI_STYLESETFONT SCI_START + 56
#define SCI_STYLESETEOLFILLED SCI_START + 57
#define SCI_STYLERESETDEFAULT SCI_START + 58
#define SCI_STYLESETUNDERLINE SCI_START + 59
#define SCI_STYLESETCHARACTERSET SCI_START + 66
#define SCI_SETSELFORE SCI_START + 67
#define SCI_SETSELBACK SCI_START + 68
@@ -190,6 +198,8 @@ extern "C" {
#define INDIC_PLAIN 0
#define INDIC_SQUIGGLE 1
#define INDIC_TT 2
#define INDIC_DIAGONAL 3
#define INDIC_STRIKE 4
#define INDIC0_MASK 32
#define INDIC1_MASK 64
@@ -213,6 +223,21 @@ extern "C" {
#define SCI_AUTOCPOSSTART SCI_START + 103
#define SCI_AUTOCCOMPLETE SCI_START + 104
#define SCI_AUTOCSTOPS SCI_START + 105
#define SCI_AUTOCSETSEPARATOR SCI_START + 106
#define SCI_AUTOCGETSEPARATOR SCI_START + 107
#define SCI_AUTOCSELECT SCI_START + 108
#define SCI_GETTABWIDTH SCI_START + 121
#define SCI_SETINDENT SCI_START + 122
#define SCI_GETINDENT SCI_START + 123
#define SCI_SETUSETABS SCI_START + 124
#define SCI_GETUSETABS SCI_START + 125
#define SCI_SETLINEINDENTATION SCI_START + 126
#define SCI_GETLINEINDENTATION SCI_START + 127
#define SCI_GETLINEINDENTPOSITION SCI_START + 128
#define SCI_SETHSCROLLBAR SCI_START + 130
#define SCI_GETHSCROLLBAR SCI_START + 131
#define SCI_CALLTIPSHOW SCI_START + 200
#define SCI_CALLTIPCANCEL SCI_START + 201
@@ -279,6 +304,13 @@ extern "C" {
#define SCI_ZOOMOUT SCI_START + 334
#define SCI_DELWORDLEFT SCI_START + 335
#define SCI_DELWORDRIGHT SCI_START + 336
#define SCI_LINECUT SCI_START + 337
#define SCI_LINEDELETE SCI_START + 338
#define SCI_LINETRANSPOSE SCI_START + 339
#define SCI_LOWERCASE SCI_START + 340
#define SCI_UPPERCASE SCI_START + 341
#define SCI_LINESCROLLDOWN SCI_START + 342
#define SCI_LINESCROLLUP SCI_START + 343
#define SCI_LINELENGTH SCI_START + 350
#define SCI_BRACEHIGHLIGHT SCI_START + 351
@@ -311,6 +343,14 @@ extern "C" {
// OR this with CARET_SLOP to reposition whenever outside slop border
#define SCI_SETCARETPOLICY SCI_START + 369
#define SCI_LINESONSCREEN SCI_START + 370
#define SCI_USEPOPUP SCI_START + 371
#define SCI_SELECTIONISRECTANGLE SCI_START + 372
#define SCI_SETZOOM SCI_START + 373
#define SCI_GETZOOM SCI_START + 374
#define SCI_ADDREFDOC SCI_START + 375
#define SCI_RELEASEDOC SCI_START + 376
// GTK+ Specific
#define SCI_GRABFOCUS SCI_START + 400
@@ -342,8 +382,11 @@ typedef void (tMacroRecorder)(UINT iMessage, WPARAM wParam, LPARAM lParam,
#define SC_PERFORMED_UNDO 0x20
#define SC_PERFORMED_REDO 0x40
#define SC_LASTSTEPINUNDOREDO 0x100
#define SC_MOD_CHANGEMARKER 0x200
#define SC_MOD_BEFOREINSERT 0x400
#define SC_MOD_BEFOREDELETE 0x800
#define SC_MODEVENTMASKALL 0x377
#define SC_MODEVENTMASKALL 0xF77
struct SCNotification {
NMHDR nmhdr;
@@ -394,6 +437,8 @@ void Scintilla_RegisterClasses(HINSTANCE hInstance);
#ifdef INCLUDE_DEPRECATED_FEATURES
#define SCI_CHANGEPOSITION SCI_START + 22
// Default style settings. These are deprecated and will be removed in a future version.
#define SCI_SETFORE SCI_START + 60
#define SCI_SETBACK SCI_START + 61

View File

@@ -20,79 +20,34 @@
#define EM_CANPASTE (1074)
#define EM_CANUNDO (198)
#define EM_CHARFROMPOS (215)
#define EM_DISPLAYBAND (1075)
#define EM_EMPTYUNDOBUFFER (205)
#define EM_EXGETSEL (1076)
#define EM_EXLIMITTEXT (1077)
#define EM_EXLINEFROMCHAR (1078)
#define EM_EXSETSEL (1079)
#define EM_FINDTEXT (1080)
#define EM_FINDTEXTEX (1103)
#define EM_FINDWORDBREAK (1100)
#define EM_FMTLINES (200)
#define EM_FORMATRANGE (1081)
#define EM_GETCHARFORMAT (1082)
#define EM_GETEVENTMASK (1083)
#define EM_GETFIRSTVISIBLELINE (206)
#define EM_GETHANDLE (189)
#define EM_GETLIMITTEXT (213)
#define EM_GETLINE (196)
#define EM_GETLINECOUNT (186)
#define EM_GETMARGINS (212)
#define EM_GETMODIFY (184)
#define EM_GETIMECOLOR (1129)
#define EM_GETIMEOPTIONS (1131)
#define EM_GETOPTIONS (1102)
#define EM_GETOLEINTERFACE (1084)
#define EM_GETPARAFORMAT (1085)
#define EM_GETPASSWORDCHAR (210)
#define EM_GETPUNCTUATION (1125)
#define EM_GETRECT (178)
#define EM_GETSEL (176)
#define EM_GETSELTEXT (1086)
#define EM_GETTEXTRANGE (1099)
#define EM_GETTHUMB (190)
#define EM_GETWORDBREAKPROC (209)
#define EM_GETWORDBREAKPROCEX (1104)
#define EM_GETWORDWRAPMODE (1127)
#define EM_HIDESELECTION (1087)
#define EM_LIMITTEXT (197)
#define EM_LINEFROMCHAR (201)
#define EM_LINEINDEX (187)
#define EM_LINELENGTH (193)
#define EM_LINESCROLL (182)
#define EM_PASTESPECIAL (1088)
#define EM_POSFROMCHAR (214)
#define EM_REPLACESEL (194)
#define EM_REQUESTRESIZE (1089)
#define EM_SCROLL (181)
#define EM_SCROLLCARET (183)
#define EM_SELECTIONTYPE (1090)
#define EM_SETBKGNDCOLOR (1091)
#define EM_SETCHARFORMAT (1092)
#define EM_SETEVENTMASK (1093)
#define EM_SETHANDLE (188)
#define EM_SETIMECOLOR (1128)
#define EM_SETIMEOPTIONS (1130)
#define EM_SETLIMITTEXT (197)
#define EM_SETMARGINS (211)
#define EM_SETMODIFY (185)
#define EM_SETOLECALLBACK (1094)
#define EM_SETOPTIONS (1101)
#define EM_SETPARAFORMAT (1095)
#define EM_SETPASSWORDCHAR (204)
#define EM_SETPUNCTUATION (1124)
#define EM_SETREADONLY (207)
#define EM_SETRECT (179)
#define EM_SETRECTNP (180)
#define EM_SETSEL (177)
#define EM_SETTABSTOPS (203)
#define EM_SETTARGETDEVICE (1096)
#define EM_SETWORDBREAKPROC (208)
#define EM_SETWORDBREAKPROCEX (1105)
#define EM_SETWORDWRAPMODE (1126)
#define EM_STREAMIN (1097)
#define EM_STREAMOUT (1098)
#define EM_UNDO (199)
#define WM_NULL (0)
@@ -132,6 +87,7 @@
#define VK_RETURN GDK_Return
#define VK_ADD GDK_KP_Add
#define VK_SUBTRACT GDK_KP_Subtract
#define VK_DIVIDE GDK_KP_Divide
#endif
#if PLAT_WX
@@ -151,6 +107,8 @@
#define VK_RETURN WXK_RETURN
#define VK_ADD WXK_ADD
#define VK_SUBTRACT WXK_SUBTRACT
//TODO:
#define VK_DIVIDE WXK_DIVIDE
// Are these needed any more
#define LPSTR char *

View File

@@ -0,0 +1,47 @@
// WindowAccessor.h - implementation of BufferAccess and StylingAccess on a Scintilla rapid easy access to contents of a Scintilla
// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
class WindowAccessor : public Accessor {
// Private so WindowAccessor objects can not be copied
WindowAccessor(const WindowAccessor &source) : Accessor(), props(source.props) {}
WindowAccessor &operator=(const WindowAccessor &) { return *this; }
protected:
WindowID id;
PropSet &props;
int lenDoc;
char styleBuf[bufferSize];
int validLen;
char chFlags;
char chWhile;
unsigned int startSeg;
bool InternalIsLeadByte(char ch);
void Fill(int position);
public:
WindowAccessor(WindowID id_, PropSet &props_) :
Accessor(), id(id_), props(props_),
lenDoc(-1), validLen(0), chFlags(0) {
}
~WindowAccessor();
char StyleAt(int position);
int GetLine(int position);
int LineStart(int line);
int LevelAt(int line);
int Length();
void Flush();
int GetLineState(int line);
int SetLineState(int line, int state);
int GetPropertyInt(const char *key, int defaultValue=0) {
return props.GetInt(key, defaultValue);
}
void StartAt(unsigned int start, char chMask=31);
void SetFlags(char chFlags_, char chWhile_) {chFlags = chFlags_; chWhile = chWhile_; };
unsigned int GetStartSegment() { return startSeg; }
void StartSegment(unsigned int pos);
void ColourTo(unsigned int pos, int chAttr);
void SetLevel(int line, int level);
int IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader = 0);
};

View File

@@ -15,6 +15,7 @@ AutoComplete::AutoComplete() {
active = false;
posStart = 0;
strcpy(stopChars, "");
separator = ' ';
}
AutoComplete::~AutoComplete() {
@@ -44,6 +45,14 @@ bool AutoComplete::IsStopChar(char ch) {
return ch && strchr(stopChars, ch);
}
void AutoComplete::SetSeparator(char separator_) {
separator = separator_;
}
char AutoComplete::GetSeparator() {
return separator;
}
int AutoComplete::SetList(const char *list) {
int maxStrLen = 12;
lb.Clear();
@@ -53,7 +62,7 @@ int AutoComplete::SetList(const char *list) {
char *startword = words;
int i = 0;
for (; words && words[i]; i++) {
if (words[i] == ' ') {
if (words[i] == separator) {
words[i] = '\0';
lb.Append(startword);
maxStrLen = Platform::Maximum(maxStrLen, strlen(startword));

View File

@@ -9,6 +9,7 @@
class AutoComplete {
bool active;
char stopChars[256];
char separator;
public:
ListBox lb;
int posStart;
@@ -27,7 +28,11 @@ public:
void SetStopChars(const char *stopChars_);
bool IsStopChar(char ch);
// The list string contains a sequence of words separated by spaces
// The separator character is used when interpreting the list in SetList
void SetSeparator(char separator_);
char GetSeparator();
// The list string contains a sequence of words separated by the separator character
int SetList(const char *list);
void Show();

View File

@@ -8,6 +8,7 @@
#include "Platform.h"
#include "Scintilla.h"
#include "CallTip.h"
CallTip::CallTip() {
@@ -117,7 +118,7 @@ PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn,
Surface surfaceMeasure;
surfaceMeasure.Init();
int deviceHeight = (size * surfaceMeasure.LogPixelsY()) / 72;
font.Create(faceName, deviceHeight);
font.Create(faceName, SC_CHARSET_DEFAULT, deviceHeight, false, false);
if (val)
delete []val;
val = new char[strlen(defn) + 1];

View File

@@ -6,13 +6,14 @@
#ifndef CALLTIP_H
#define CALLTIP_H
const char callClassName[] = "CallTip";
class CallTip {
int startHighlight;
int endHighlight;
char *val;
Font font;
// Private so CallTip objects can not be copied
CallTip(const CallTip &) {}
CallTip &operator=(const CallTip &) { return *this; }
public:
Window wCallTip;
Window wDraw;

View File

@@ -191,11 +191,23 @@ void LineVector::InsertValue(int pos, int value) {
}
}
lines++;
for (int i = lines + 1; i > pos; i--) {
for (int i = lines; i > pos; i--) {
linesData[i] = linesData[i - 1];
}
linesData[pos].startPosition = value;
linesData[pos].handleSet = 0;
if (levels) {
for (int j = lines; j > pos; j--) {
levels[j] = levels[j - 1];
}
if (pos == 0) {
levels[pos] = SC_FOLDLEVELBASE;
} else if (pos == (lines-1)) { // Last line will not be a folder
levels[pos] = SC_FOLDLEVELBASE;
} else {
levels[pos] = levels[pos-1];
}
}
}
void LineVector::SetValue(int pos, int value) {
@@ -221,6 +233,15 @@ void LineVector::Remove(int pos) {
for (int i = pos; i < lines; i++) {
linesData[i] = linesData[i + 1];
}
if (levels) {
// Level information merges back onto previous line
int posAbove = pos-1;
if (posAbove < 0)
posAbove = 0;
for (int j = posAbove; j < lines; j++) {
levels[j] = levels[j + 1];
}
}
lines--;
}
@@ -233,9 +254,8 @@ int LineVector::LineFromPosition(int pos) {
return lines - 1;
int lower = 0;
int upper = lines;
int middle = 0;
do {
middle = (upper + lower + 1) / 2; // Round high
int middle = (upper + lower + 1) / 2; // Round high
if (pos < linesData[middle].startPosition) {
upper = middle - 1;
} else {
@@ -316,12 +336,13 @@ Action::~Action() {
Destroy();
}
void Action::Create(actionType at_, int position_, char *data_, int lenData_) {
void Action::Create(actionType at_, int position_, char *data_, int lenData_, bool mayCoalesce_) {
delete []data;
position = position_;
at = at_;
data = data_;
lenData = lenData_;
mayCoalesce = mayCoalesce_;
}
void Action::Destroy() {
@@ -336,39 +357,222 @@ void Action::Grab(Action *source) {
at = source->at;
data = source->data;
lenData = source->lenData;
mayCoalesce = source->mayCoalesce;
// Ownership of source data transferred to this
source->position = 0;
source->at = startAction;
source->data = 0;
source->lenData = 0;
source->mayCoalesce = true;
}
CellBuffer::CellBuffer(int initialLength) {
body = new char[initialLength];
size = initialLength;
length = 0;
part1len = 0;
gaplen = initialLength;
part2body = body + gaplen;
readOnly = false;
// The undo history stores a sequence of user operations that represent the user's view of the
// commands executed on the text.
// Each user operation contains a sequence of text insertion and text deletion actions.
// All the user operations are stored in a list of individual actions with 'start' actions used
// as delimiters between user operations.
// Initially there is one start action in the history.
// As each action is performed, it is recorded in the history. The action may either become
// part of the current user operation or may start a new user operation. If it is to be part of the
// current operation, then it overwrites the current last action. If it is to be part of a new
// operation, it is appended after the current last action.
// After writing the new action, a new start action is appended at the end of the history.
// The decision of whether to start a new user operation is based upon two factors. If a
// compound operation has been explicitly started by calling BeginUndoAction and no matching
// EndUndoAction (these calls nest) has been called, then the action is coalesced into the current
// operation. If there is no outstanding BeginUndoAction call then a new operation is started
// unless it looks as if the new action is caused by the user typing or deleting a stream of text.
// Sequences that look like typing or deletion are coalesced into a single user operation.
UndoHistory::UndoHistory() {
lenActions = 100;
actions = new Action[lenActions];
maxAction = 0;
currentAction = 0;
collectingUndo = undoCollectAutoStart;
undoSequenceDepth = 0;
savePoint = 0;
actions[currentAction].Create(startAction);
}
UndoHistory::~UndoHistory() {
delete []actions;
actions = 0;
}
void UndoHistory::EnsureUndoRoom() {
//Platform::DebugPrintf("%% %d action %d %d %d\n", at, position, length, currentAction);
if (currentAction >= 2) {
// Have to test that there is room for 2 more actions in the array
// as two actions may be created by this function
if (currentAction >= (lenActions - 2)) {
// Run out of undo nodes so extend the array
int lenActionsNew = lenActions * 2;
Action *actionsNew = new Action[lenActionsNew];
if (!actionsNew)
return;
for (int act = 0; act <= currentAction; act++)
actionsNew[act].Grab(&actions[act]);
delete []actions;
lenActions = lenActionsNew;
actions = actionsNew;
}
}
}
void UndoHistory::AppendAction(actionType at, int position, char *data, int lengthData) {
EnsureUndoRoom();
//Platform::DebugPrintf("%% %d action %d %d %d\n", at, position, lengthData, currentAction);
//Platform::DebugPrintf("^ %d action %d %d\n", actions[currentAction - 1].at,
// actions[currentAction - 1].position, actions[currentAction - 1].lenData);
if (currentAction >= 1) {
if (0 == undoSequenceDepth) {
// Top level actions may not always be coalesced
Action &actPrevious = actions[currentAction - 1];
// See if current action can be coalesced into previous action
// Will work if both are inserts or deletes and position is same
if (at != actPrevious.at) {
currentAction++;
} else if (currentAction == savePoint) {
currentAction++;
} else if ((at == removeAction) &&
((position + lengthData * 2) != actPrevious.position)) {
// Removals must be at same position to coalesce
currentAction++;
} else if ((at == insertAction) &&
(position != (actPrevious.position + actPrevious.lenData*2))) {
// Insertions must be immediately after to coalesce
currentAction++;
} else {
//Platform::DebugPrintf("action coalesced\n");
}
} else {
// Actions not at top level are always coalesced unless this is after return to top level
if (!actions[currentAction].mayCoalesce)
currentAction++;
}
} else {
currentAction++;
}
actions[currentAction].Create(at, position, data, lengthData);
currentAction++;
actions[currentAction].Create(startAction);
maxAction = currentAction;
}
void UndoHistory::BeginUndoAction() {
EnsureUndoRoom();
if (undoSequenceDepth == 0) {
if (actions[currentAction].at != startAction) {
currentAction++;
actions[currentAction].Create(startAction);
maxAction = currentAction;
}
actions[currentAction].mayCoalesce = false;
}
undoSequenceDepth++;
}
void UndoHistory::EndUndoAction() {
EnsureUndoRoom();
undoSequenceDepth--;
if (0 == undoSequenceDepth) {
if (actions[currentAction].at != startAction) {
currentAction++;
actions[currentAction].Create(startAction);
maxAction = currentAction;
}
actions[currentAction].mayCoalesce = false;
}
}
void UndoHistory::DropUndoSequence() {
undoSequenceDepth = 0;
}
void UndoHistory::DeleteUndoHistory() {
for (int i = 1; i < maxAction; i++)
actions[i].Destroy();
maxAction = 0;
currentAction = 0;
actions[currentAction].Create(startAction);
savePoint = 0;
}
void UndoHistory::SetSavePoint() {
savePoint = currentAction;
}
bool UndoHistory::IsSavePoint() const {
return savePoint == currentAction;
}
bool UndoHistory::CanUndo() const {
return (currentAction > 0) && (maxAction > 0);
}
int UndoHistory::StartUndo() {
// Drop any trailing startAction
if (actions[currentAction].at == startAction && currentAction > 0)
currentAction--;
// Count the steps in this action
int act = currentAction;
while (actions[act].at != startAction && act > 0) {
act--;
}
return currentAction - act;
}
const Action &UndoHistory::GetUndoStep() const {
return actions[currentAction];
}
void UndoHistory::CompletedUndoStep() {
currentAction--;
}
bool UndoHistory::CanRedo() const {
return maxAction > currentAction;
}
int UndoHistory::StartRedo() {
// Drop any leading startAction
if (actions[currentAction].at == startAction && currentAction < maxAction)
currentAction++;
// Count the steps in this action
int act = currentAction;
while (actions[act].at != startAction && act < maxAction) {
act++;
}
return act - currentAction;
}
const Action &UndoHistory::GetRedoStep() const {
return actions[currentAction];
}
void UndoHistory::CompletedRedoStep() {
currentAction++;
}
CellBuffer::CellBuffer(int initialLength) {
body = new char[initialLength];
size = initialLength;
length = 0;
part1len = 0;
gaplen = initialLength;
part2body = body + gaplen;
readOnly = false;
collectingUndo = undoCollectAutoStart;
}
CellBuffer::~CellBuffer() {
delete []body;
body = 0;
delete []actions;
actions = 0;
}
void CellBuffer::GapTo(int position) {
@@ -486,7 +690,7 @@ const char *CellBuffer::InsertString(int position, char *s, int insertLength) {
for (int i = 0; i < insertLength / 2; i++) {
data[i] = s[i * 2];
}
AppendAction(insertAction, position, data, insertLength / 2);
uh.AppendAction(insertAction, position, data, insertLength / 2);
}
BasicInsertString(position, s, insertLength);
@@ -504,7 +708,7 @@ void CellBuffer::InsertCharStyle(int position, char ch, char style) {
bool CellBuffer::SetStyleAt(int position, char style, char mask) {
char curVal = ByteAt(position*2 + 1);
if ((curVal & mask) != style) {
SetByteAt(position*2 + 1, (curVal & ~mask) | style);
SetByteAt(position*2 + 1, static_cast<char>((curVal & ~mask) | style));
return true;
} else {
return false;
@@ -517,7 +721,7 @@ bool CellBuffer::SetStyleFor(int position, int lengthStyle, char style, char mas
while (lengthStyle--) {
char curVal = ByteAt(bytePos);
if ((curVal & mask) != style) {
SetByteAt(bytePos, (curVal & ~mask) | style);
SetByteAt(bytePos, static_cast<char>((curVal & ~mask) | style));
changed = true;
}
bytePos += 2;
@@ -525,48 +729,6 @@ bool CellBuffer::SetStyleFor(int position, int lengthStyle, char style, char mas
return changed;
}
void CellBuffer::EnsureUndoRoom() {
//Platform::DebugPrintf("%% %d action %d %d %d\n", at, position, length, currentAction);
if (currentAction >= 2) {
// Have to test that there is room for 2 more actions in the array
// as two actions may be created by this function
if (currentAction >= (lenActions - 2)) {
// Run out of undo nodes so extend the array
int lenActionsNew = lenActions * 2;
Action *actionsNew = new Action[lenActionsNew];
if (!actionsNew)
return;
for (int act = 0; act <= currentAction; act++)
actionsNew[act].Grab(&actions[act]);
delete []actions;
lenActions = lenActionsNew;
actions = actionsNew;
}
}
}
void CellBuffer::AppendAction(actionType at, int position, char *data, int lengthData) {
EnsureUndoRoom();
//Platform::DebugPrintf("%% %d action %d %d %d\n", at, position, lengthData, currentAction);
if (currentAction >= 2) {
// See if current action can be coalesced into previous action
// Will work if both are inserts or deletes and position is same or two different
if ((at != actions[currentAction - 1].at) || (abs(position - actions[currentAction - 1].position) > 2)) {
currentAction++;
} else if (currentAction == savePoint) {
currentAction++;
}
} else {
currentAction++;
}
actions[currentAction].Create(at, position, data, lengthData);
if ((collectingUndo == undoCollectAutoStart) && (0 == undoSequenceDepth)) {
currentAction++;
actions[currentAction].Create(startAction);
}
maxAction = currentAction;
}
const char *CellBuffer::DeleteChars(int position, int deleteLength) {
// InsertString and DeleteChars are the bottleneck though which all changes occur
char *data = 0;
@@ -577,7 +739,7 @@ const char *CellBuffer::DeleteChars(int position, int deleteLength) {
for (int i = 0; i < deleteLength / 2; i++) {
data[i] = ByteAt(position + i * 2);
}
AppendAction(removeAction, position, data, deleteLength / 2);
uh.AppendAction(removeAction, position, data, deleteLength / 2);
}
BasicDeleteChars(position, deleteLength);
@@ -616,11 +778,11 @@ void CellBuffer::SetReadOnly(bool set) {
}
void CellBuffer::SetSavePoint() {
savePoint = currentAction;
uh.SetSavePoint();
}
bool CellBuffer::IsSavePoint() {
return savePoint == currentAction;
return uh.IsSavePoint();
}
int CellBuffer::AddMark(int line, int markerNum) {
@@ -792,7 +954,7 @@ void CellBuffer::BasicDeleteChars(int position, int deleteLength) {
undoCollectionType CellBuffer::SetUndoCollection(undoCollectionType collectUndo) {
collectingUndo = collectUndo;
undoSequenceDepth = 0;
uh.DropUndoSequence();
return collectingUndo;
}
@@ -800,69 +962,32 @@ bool CellBuffer::IsCollectingUndo() {
return collectingUndo;
}
void CellBuffer::AppendUndoStartAction() {
EnsureUndoRoom();
// Finish any currently active undo sequence
undoSequenceDepth = 0;
if (actions[currentAction].at != startAction) {
undoSequenceDepth++;
currentAction++;
actions[currentAction].Create(startAction);
maxAction = currentAction;
}
}
void CellBuffer::BeginUndoAction() {
EnsureUndoRoom();
if (undoSequenceDepth == 0) {
if (actions[currentAction].at != startAction) {
currentAction++;
actions[currentAction].Create(startAction);
maxAction = currentAction;
}
}
undoSequenceDepth++;
uh.BeginUndoAction();
}
void CellBuffer::EndUndoAction() {
EnsureUndoRoom();
undoSequenceDepth--;
if (0 == undoSequenceDepth) {
if (actions[currentAction].at != startAction) {
currentAction++;
actions[currentAction].Create(startAction);
maxAction = currentAction;
}
}
uh.EndUndoAction();
}
void CellBuffer::DeleteUndoHistory() {
for (int i = 1; i < maxAction; i++)
actions[i].Destroy();
maxAction = 0;
currentAction = 0;
savePoint = 0;
uh.DeleteUndoHistory();
}
bool CellBuffer::CanUndo() {
return (!readOnly) && ((currentAction > 0) && (maxAction > 0));
return (!readOnly) && (uh.CanUndo());
}
int CellBuffer::StartUndo() {
// Drop any trailing startAction
if (actions[currentAction].at == startAction && currentAction > 0)
currentAction--;
// Count the steps in this action
int act = currentAction;
while (actions[act].at != startAction && act > 0) {
act--;
}
return currentAction - act;
return uh.StartUndo();
}
const Action &CellBuffer::UndoStep() {
const Action &actionStep = actions[currentAction];
const Action &CellBuffer::GetUndoStep() const {
return uh.GetUndoStep();
}
void CellBuffer::PerformUndoStep() {
const Action &actionStep = uh.GetUndoStep();
if (actionStep.at == insertAction) {
BasicDeleteChars(actionStep.position, actionStep.lenData*2);
} else if (actionStep.at == removeAction) {
@@ -874,29 +999,23 @@ const Action &CellBuffer::UndoStep() {
BasicInsertString(actionStep.position, styledData, actionStep.lenData*2);
delete []styledData;
}
currentAction--;
return actionStep;
uh.CompletedUndoStep();
}
bool CellBuffer::CanRedo() {
return (!readOnly) && (maxAction > currentAction);
return (!readOnly) && (uh.CanRedo());
}
int CellBuffer::StartRedo() {
// Drop any leading startAction
if (actions[currentAction].at == startAction && currentAction < maxAction)
currentAction++;
// Count the steps in this action
int act = currentAction;
while (actions[act].at != startAction && act < maxAction) {
act++;
}
return act - currentAction;
return uh.StartRedo();
}
const Action &CellBuffer::RedoStep() {
const Action &actionStep = actions[currentAction];
const Action &CellBuffer::GetRedoStep() const {
return uh.GetRedoStep();
}
void CellBuffer::PerformRedoStep() {
const Action &actionStep = uh.GetRedoStep();
if (actionStep.at == insertAction) {
char *styledData = new char[actionStep.lenData * 2];
for (int i = 0; i < actionStep.lenData; i++) {
@@ -908,8 +1027,7 @@ const Action &CellBuffer::RedoStep() {
} else if (actionStep.at == removeAction) {
BasicDeleteChars(actionStep.position, actionStep.lenData*2);
}
currentAction++;
return actionStep;
uh.CompletedRedoStep();
}
int CellBuffer::SetLineState(int line, int state) {

View File

@@ -79,16 +79,55 @@ public:
int position;
char *data;
int lenData;
bool mayCoalesce;
Action();
~Action();
void Create(actionType at_, int position_=0, char *data_=0, int lenData_=0);
void Create(actionType at_, int position_=0, char *data_=0, int lenData_=0, bool mayCoalesce_=true);
void Destroy();
void Grab(Action *source);
};
enum undoCollectionType { undoCollectNone, undoCollectAutoStart, undoCollectManualStart };
class UndoHistory {
Action *actions;
int lenActions;
int maxAction;
int currentAction;
int undoSequenceDepth;
int savePoint;
void EnsureUndoRoom();
public:
UndoHistory();
~UndoHistory();
void AppendAction(actionType at, int position, char *data, int length);
void BeginUndoAction();
void EndUndoAction();
void DropUndoSequence();
void DeleteUndoHistory();
// The save point is a marker in the undo stack where the container has stated that
// the buffer was saved. Undo and redo can move over the save point.
void SetSavePoint();
bool IsSavePoint() const;
// To perform an undo, StartUndo is called to retrieve the number of steps, then UndoStep is
// called that many times. Similarly for redo.
bool CanUndo() const;
int StartUndo();
const Action &GetUndoStep() const;
void CompletedUndoStep();
bool CanRedo() const;
int StartRedo();
const Action &GetRedoStep() const;
void CompletedRedoStep();
};
// Holder for an expandable array of characters that supports undo and line markers
// Based on article "Data Structures in a Bit-Mapped Text Editor"
// by Wilfred J. Hansen, Byte January 1987, page 183
@@ -102,13 +141,8 @@ private:
char *part2body;
bool readOnly;
Action *actions;
int lenActions;
int maxAction;
int currentAction;
undoCollectionType collectingUndo;
int undoSequenceDepth;
int savePoint;
UndoHistory uh;
LineVector lv;
@@ -117,9 +151,6 @@ private:
void GapTo(int position);
void RoomFor(int insertionLength);
void EnsureUndoRoom();
void AppendAction(actionType at, int position, char *data, int length);
inline char ByteAt(int position);
void SetByteAt(int position, char ch);
@@ -143,7 +174,7 @@ public:
// Setting styles for positions outside the range of the buffer is safe and has no effect.
// True is returned if the style of a character changed.
bool SetStyleAt(int position, char style, char mask=(char)0xff);
bool SetStyleAt(int position, char style, char mask='\377');
bool SetStyleFor(int position, int length, char style, char mask);
const char *DeleteChars(int position, int deleteLength);
@@ -170,19 +201,20 @@ public:
undoCollectionType SetUndoCollection(undoCollectionType collectUndo);
bool IsCollectingUndo();
void AppendUndoStartAction();
void BeginUndoAction();
void EndUndoAction();
void DeleteUndoHistory();
// To perform an undo, StartUndo is called to retreive the number of steps, then UndoStep is
// To perform an undo, StartUndo is called to retrieve the number of steps, then UndoStep is
// called that many times. Similarly for redo.
bool CanUndo();
int StartUndo();
const Action &UndoStep();
const Action &GetUndoStep() const;
void PerformUndoStep();
bool CanRedo();
int StartRedo();
const Action &RedoStep();
const Action &GetRedoStep() const;
void PerformRedoStep();
int SetLineState(int line, int state);
int GetLineState(int line);

View File

@@ -30,7 +30,6 @@ void ContractionState::MakeValid() const {
if (!valid) {
// Could be cleverer by keeping the index of the last still valid entry
// rather than invalidating all.
int linePrev = -1;
int lineDisplay = 0;
for (int line=0; line<linesInDoc; line++) {
lines[line].displayLine = lineDisplay;
@@ -108,12 +107,12 @@ void ContractionState::InsertLines(int lineDoc, int lineCount) {
return;
}
//Platform::DebugPrintf("InsertLine[%d] = %d\n", lineDoc);
if ((linesInDoc + 2) >= size) {
Grow(size + growSize);
if ((linesInDoc + lineCount + 2) >= size) {
Grow(linesInDoc + lineCount + growSize);
}
linesInDoc += lineCount;
linesInDisplay += lineCount;
for (int i = linesInDoc + 1; i >= lineDoc + lineCount; i--) {
for (int i = linesInDoc; i >= lineDoc + lineCount; i--) {
lines[i].visible = lines[i - lineCount].visible;
lines[i].expanded = lines[i - lineCount].expanded;
}
@@ -130,16 +129,18 @@ void ContractionState::DeleteLines(int lineDoc, int lineCount) {
linesInDisplay -= lineCount;
return;
}
int delta = 0;
for (int d=0;d<lineCount;d++)
int deltaDisplayed = 0;
for (int d=0;d<lineCount;d++) {
if (lines[lineDoc+d].visible)
delta--;
deltaDisplayed--;
}
for (int i = lineDoc; i < linesInDoc-lineCount; i++) {
lines[i].visible = lines[i + lineCount].visible;
if (i != 0) // Line zero is always visible
lines[i].visible = lines[i + lineCount].visible;
lines[i].expanded = lines[i + lineCount].expanded;
}
linesInDoc -= lineCount;
linesInDisplay += delta;
linesInDisplay += deltaDisplayed;
valid = false;
}
@@ -154,8 +155,12 @@ bool ContractionState::GetVisible(int lineDoc) const {
}
bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool visible) {
if (lineDocStart == 0)
lineDocStart++;
if (lineDocStart > lineDocEnd)
return false;
if (size == 0) {
Grow(lineDocEnd + growSize);
Grow(linesInDoc + growSize);
}
// TODO: modify docLine members to mirror displayLine
int delta = 0;
@@ -191,7 +196,7 @@ bool ContractionState::GetExpanded(int lineDoc) const {
bool ContractionState::SetExpanded(int lineDoc, bool expanded) {
if (size == 0) {
Grow(lineDoc + growSize);
Grow(linesInDoc + growSize);
}
if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
if (lines[lineDoc].expanded != expanded) {

View File

@@ -32,7 +32,10 @@ Document::Document() {
}
endStyled = 0;
enteredCount = 0;
enteredReadOnlyCount = 0;
tabInChars = 8;
indentInChars = 0;
useTabs = true;
watchers = 0;
lenWatchers = 0;
}
@@ -65,26 +68,54 @@ void Document::SetSavePoint() {
NotifySavePoint(true);
}
int Document::AddMark(int line, int markerNum) {
int prev = cb.AddMark(line, markerNum);
DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0);
NotifyModified(mh);
return prev;
}
void Document::DeleteMark(int line, int markerNum) {
cb.DeleteMark(line, markerNum);
DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0);
NotifyModified(mh);
}
void Document::DeleteMarkFromHandle(int markerHandle) {
cb.DeleteMarkFromHandle(markerHandle);
DocModification mh(SC_MOD_CHANGEMARKER, 0, 0, 0, 0);
NotifyModified(mh);
}
void Document::DeleteAllMarks(int markerNum) {
cb.DeleteAllMarks(markerNum);
DocModification mh(SC_MOD_CHANGEMARKER, 0, 0, 0, 0);
NotifyModified(mh);
}
int Document::LineStart(int line) {
return cb.LineStart(line);
}
int Document::LineEnd(int line) {
if (line == LinesTotal() - 1) {
return LineStart(line + 1);
} else {
int position = LineStart(line + 1) - 1;
// When line terminator is CR+LF, may need to go back one more
if ((position > LineStart(line)) && (cb.CharAt(position - 1) == '\r')) {
position--;
}
return position;
}
}
int Document::LineFromPosition(int pos) {
return cb.LineFromPosition(pos);
}
int Document::LineEndPosition(int position) {
int line = LineFromPosition(position);
if (line == LinesTotal() - 1) {
position = LineStart(line + 1);
} else {
position = LineStart(line + 1) - 1;
// When line terminator is CR+LF, may need to go back one more
if ((position > LineStart(line)) && (cb.CharAt(position - 1) == '\r')) {
position--;
}
}
return position;
return LineEnd(LineFromPosition(position));
}
int Document::VCHomePosition(int position) {
@@ -124,7 +155,10 @@ int Document::GetLastChild(int lineParent, int level) {
level = GetLevel(lineParent) & SC_FOLDLEVELNUMBERMASK;
int maxLine = LinesTotal();
int lineMaxSubord = lineParent;
while ((lineMaxSubord < maxLine-1) && IsSubordinate(level, GetLevel(lineMaxSubord+1))) {
while (lineMaxSubord < maxLine-1) {
EnsureStyledTo(LineStart(lineMaxSubord+2));
if (!IsSubordinate(level, GetLevel(lineMaxSubord+1)))
break;
lineMaxSubord++;
}
if (lineMaxSubord > lineParent) {
@@ -170,18 +204,23 @@ bool Document::IsCrLf(int pos) {
bool Document::IsDBCS(int pos) {
#if PLAT_WIN
if (dbcsCodePage) {
// Anchor DBCS calculations at start of line because start of line can
// not be a DBCS trail byte.
int startLine = pos;
while (startLine > 0 && cb.CharAt(startLine) != '\r' && cb.CharAt(startLine) != '\n')
startLine--;
while (startLine <= pos) {
if (IsDBCSLeadByteEx(dbcsCodePage, cb.CharAt(startLine))) {
if (SC_CP_UTF8 == dbcsCodePage) {
unsigned char ch = static_cast<unsigned char>(cb.CharAt(pos));
return ch >= 0x80;
} else {
// Anchor DBCS calculations at start of line because start of line can
// not be a DBCS trail byte.
int startLine = pos;
while (startLine > 0 && cb.CharAt(startLine) != '\r' && cb.CharAt(startLine) != '\n')
startLine--;
while (startLine <= pos) {
if (IsDBCSLeadByteEx(dbcsCodePage, cb.CharAt(startLine))) {
startLine++;
if (startLine >= pos)
return true;
}
startLine++;
if (startLine >= pos)
return true;
}
startLine++;
}
}
return false;
@@ -190,6 +229,28 @@ bool Document::IsDBCS(int pos) {
#endif
}
int Document::LenChar(int pos) {
if (IsCrLf(pos)) {
return 2;
} else if (SC_CP_UTF8 == dbcsCodePage) {
unsigned char ch = static_cast<unsigned char>(cb.CharAt(pos));
if (ch < 0x80)
return 1;
int len = 2;
if (ch >= (0x80+0x40+0x20))
len = 3;
int lengthDoc = Length();
if ((pos + len) > lengthDoc)
return lengthDoc-pos;
else
return len;
} else if (IsDBCS(pos)) {
return 2;
} else {
return 1;
}
}
// Normalise a position so that it is not halfway through a two byte character.
// This can occur in two situations -
// When lines are terminated with \r\n pairs which should be treated as one character.
@@ -221,29 +282,41 @@ int Document::MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd) {
#if PLAT_WIN
if (dbcsCodePage) {
// Anchor DBCS calculations at start of line because start of line can
// not be a DBCS trail byte.
int startLine = pos;
while (startLine > 0 && cb.CharAt(startLine) != '\r' && cb.CharAt(startLine) != '\n')
startLine--;
bool atLeadByte = false;
while (startLine < pos) {
if (atLeadByte)
atLeadByte = false;
else if (IsDBCSLeadByteEx(dbcsCodePage, cb.CharAt(startLine)))
atLeadByte = true;
else
atLeadByte = false;
startLine++;
//Platform::DebugPrintf("DBCS %s\n", atlead ? "D" : "-");
}
if (SC_CP_UTF8 == dbcsCodePage) {
unsigned char ch = static_cast<unsigned char>(cb.CharAt(pos));
while ((pos > 0) && (pos < Length()) && (ch >= 0x80) && (ch < (0x80 + 0x40))) {
// ch is a trail byte
if (moveDir > 0)
pos++;
else
pos--;
ch = static_cast<unsigned char>(cb.CharAt(pos));
}
} else {
// Anchor DBCS calculations at start of line because start of line can
// not be a DBCS trail byte.
int startLine = pos;
while (startLine > 0 && cb.CharAt(startLine) != '\r' && cb.CharAt(startLine) != '\n')
startLine--;
bool atLeadByte = false;
while (startLine < pos) {
if (atLeadByte)
atLeadByte = false;
else if (IsDBCSLeadByteEx(dbcsCodePage, cb.CharAt(startLine)))
atLeadByte = true;
else
atLeadByte = false;
startLine++;
//Platform::DebugPrintf("DBCS %s\n", atlead ? "D" : "-");
}
if (atLeadByte) {
// Position is between a lead byte and a trail byte
if (moveDir > 0)
return pos + 1;
else
return pos - 1;
if (atLeadByte) {
// Position is between a lead byte and a trail byte
if (moveDir > 0)
return pos + 1;
else
return pos - 1;
}
}
}
#endif
@@ -261,41 +334,60 @@ void Document::ModifiedAt(int pos) {
// Unlike Undo, Redo, and InsertStyledString, the pos argument is a cell number not a char number
void Document::DeleteChars(int pos, int len) {
if (cb.IsReadOnly() && enteredReadOnlyCount==0) {
enteredReadOnlyCount++;
NotifyModifyAttempt();
enteredReadOnlyCount--;
}
if (enteredCount == 0) {
enteredCount++;
if (cb.IsReadOnly())
NotifyModifyAttempt();
if (!cb.IsReadOnly()) {
NotifyModified(
DocModification(
SC_MOD_BEFOREDELETE | SC_PERFORMED_USER,
pos, len,
0, 0));
int prevLinesTotal = LinesTotal();
bool startSavePoint = cb.IsSavePoint();
const char *text = cb.DeleteChars(pos*2, len * 2);
if (startSavePoint && cb.IsCollectingUndo())
NotifySavePoint(!startSavePoint);
ModifiedAt(pos);
int modFlags = SC_MOD_DELETETEXT | SC_PERFORMED_USER;
DocModification mh(modFlags, pos, len, LinesTotal() - prevLinesTotal, text);
NotifyModified(mh);
NotifyModified(
DocModification(
SC_MOD_DELETETEXT | SC_PERFORMED_USER,
pos, len,
LinesTotal() - prevLinesTotal, text));
}
enteredCount--;
}
}
void Document::InsertStyledString(int position, char *s, int insertLength) {
if (cb.IsReadOnly() && enteredReadOnlyCount==0) {
enteredReadOnlyCount++;
NotifyModifyAttempt();
enteredReadOnlyCount--;
}
if (enteredCount == 0) {
enteredCount++;
if (cb.IsReadOnly())
NotifyModifyAttempt();
if (!cb.IsReadOnly()) {
NotifyModified(
DocModification(
SC_MOD_BEFOREINSERT | SC_PERFORMED_USER,
position / 2, insertLength / 2,
0, 0));
int prevLinesTotal = LinesTotal();
bool startSavePoint = cb.IsSavePoint();
const char *text = cb.InsertString(position, s, insertLength);
if (startSavePoint && cb.IsCollectingUndo())
NotifySavePoint(!startSavePoint);
ModifiedAt(position / 2);
int modFlags = SC_MOD_INSERTTEXT | SC_PERFORMED_USER;
DocModification mh(modFlags, position / 2, insertLength / 2, LinesTotal() - prevLinesTotal, text);
NotifyModified(mh);
NotifyModified(
DocModification(
SC_MOD_INSERTTEXT | SC_PERFORMED_USER,
position / 2, insertLength / 2,
LinesTotal() - prevLinesTotal, text));
}
enteredCount--;
}
@@ -307,9 +399,18 @@ int Document::Undo() {
enteredCount++;
bool startSavePoint = cb.IsSavePoint();
int steps = cb.StartUndo();
//Platform::DebugPrintf("Steps=%d\n", steps);
for (int step=0; step<steps; step++) {
int prevLinesTotal = LinesTotal();
const Action &action = cb.UndoStep();
const Action &action = cb.GetUndoStep();
if (action.at == removeAction) {
NotifyModified(DocModification(
SC_MOD_BEFOREINSERT | SC_PERFORMED_UNDO, action));
} else {
NotifyModified(DocModification(
SC_MOD_BEFOREDELETE | SC_PERFORMED_UNDO, action));
}
cb.PerformUndoStep();
int cellPosition = action.position / 2;
ModifiedAt(cellPosition);
newPos = cellPosition;
@@ -344,10 +445,17 @@ int Document::Redo() {
int steps = cb.StartRedo();
for (int step=0; step<steps; step++) {
int prevLinesTotal = LinesTotal();
const Action &action = cb.RedoStep();
int cellPosition = action.position / 2;
ModifiedAt(cellPosition);
newPos = cellPosition;
const Action &action = cb.GetRedoStep();
if (action.at == insertAction) {
NotifyModified(DocModification(
SC_MOD_BEFOREINSERT | SC_PERFORMED_REDO, action));
} else {
NotifyModified(DocModification(
SC_MOD_BEFOREDELETE | SC_PERFORMED_REDO, action));
}
cb.PerformRedoStep();
ModifiedAt(action.position / 2);
newPos = action.position / 2;
int modFlags = SC_PERFORMED_REDO;
if (action.at == insertAction) {
@@ -358,7 +466,8 @@ int Document::Redo() {
}
if (step == steps-1)
modFlags |= SC_LASTSTEPINUNDOREDO;
NotifyModified(DocModification(modFlags, cellPosition, action.lenData,
NotifyModified(
DocModification(modFlags, action.position / 2, action.lenData,
LinesTotal() - prevLinesTotal, action.data));
}
@@ -395,14 +504,13 @@ void Document::InsertString(int position, const char *s, int insertLength) {
}
}
void Document::ChangeChar(int pos, char ch) {
DeleteChars(pos, 1);
InsertChar(pos, ch);
}
void Document::DelChar(int pos) {
if (IsCrLf(pos)) {
DeleteChars(pos, 2);
} else if (IsDBCS(pos)) {
DeleteChars(pos, 2);
} else if (pos < Length()) {
DeleteChars(pos, 1);
}
DeleteChars(pos, LenChar(pos));
}
int Document::DelCharBack(int pos) {
@@ -411,6 +519,10 @@ int Document::DelCharBack(int pos) {
} else if (IsCrLf(pos - 2)) {
DeleteChars(pos - 2, 2);
return pos - 2;
} else if (SC_CP_UTF8 == dbcsCodePage) {
int startChar = MovePositionOutsideChar(pos-1, -1, false);
DeleteChars(startChar, pos - startChar);
return startChar;
} else if (IsDBCS(pos - 1)) {
DeleteChars(pos - 2, 2);
return pos - 2;
@@ -420,27 +532,80 @@ int Document::DelCharBack(int pos) {
}
}
static bool isindentchar(char ch) {
return (ch == ' ') || (ch == '\t');
}
static int NextTab(int pos, int tabSize) {
return ((pos / tabSize) + 1) * tabSize;
}
static void CreateIndentation(char *linebuf, int length, int indent, int tabSize, bool insertSpaces) {
length--; // ensure space for \0
if (!insertSpaces) {
while ((indent >= tabSize) && (length > 0)) {
*linebuf++ = '\t';
indent -= tabSize;
length--;
}
}
while ((indent > 0) && (length > 0)) {
*linebuf++ = ' ';
indent--;
length--;
}
*linebuf = '\0';
}
int Document::GetLineIndentation(int line) {
int indent = 0;
if ((line >= 0) && (line < LinesTotal())) {
int lineStart = LineStart(line);
int length = Length();
for (int i=lineStart;i<length;i++) {
char ch = cb.CharAt(i);
if (ch == ' ')
indent++;
else if (ch == '\t')
indent = NextTab(indent, tabInChars);
else
return indent;
}
}
return indent;
}
void Document::SetLineIndentation(int line, int indent) {
int indentOfLine = GetLineIndentation(line);
if (indent < 0)
indent = 0;
if (indent != indentOfLine) {
char linebuf[1000];
CreateIndentation(linebuf, sizeof(linebuf), indent, tabInChars, !useTabs);
int thisLineStart = LineStart(line);
int indentPos = GetLineIndentPosition(line);
DeleteChars(thisLineStart, indentPos - thisLineStart);
InsertString(thisLineStart, linebuf);
}
}
int Document::GetLineIndentPosition(int line) {
int pos = LineStart(line);
int length = Length();
while ((pos < length) && isindentchar(cb.CharAt(pos))) {
pos++;
}
return pos;
}
void Document::Indent(bool forwards, int lineBottom, int lineTop) {
if (forwards) {
// Indent by a tab
for (int line = lineBottom; line >= lineTop; line--) {
InsertChar(LineStart(line), '\t');
}
} else {
// Dedent - suck white space off the front of the line to dedent by equivalent of a tab
for (int line = lineBottom; line >= lineTop; line--) {
int ispc = 0;
while (ispc < tabInChars && cb.CharAt(LineStart(line) + ispc) == ' ')
ispc++;
int posStartLine = LineStart(line);
if (ispc == tabInChars) {
DeleteChars(posStartLine, ispc);
} else if (cb.CharAt(posStartLine + ispc) == '\t') {
DeleteChars(posStartLine, ispc + 1);
} else { // Hit a non-white
DeleteChars(posStartLine, ispc);
}
}
// Dedent - suck white space off the front of the line to dedent by equivalent of a tab
for (int line = lineBottom; line >= lineTop; line--) {
int indentOfLine = GetLineIndentation(line);
if (forwards)
SetLineIndentation(line, indentOfLine + IndentSize());
else
SetLineIndentation(line, indentOfLine - IndentSize());
}
}
@@ -485,6 +650,8 @@ void Document::ConvertLineEnds(int eolModeSet) {
}
bool Document::IsWordChar(unsigned char ch) {
if ((SC_CP_UTF8 == dbcsCodePage) && (ch >0x80))
return true;
return wordchars[ch];
}
@@ -551,16 +718,14 @@ long Document::FindText(int minPos, int maxPos, const char *s, bool caseSensitiv
// Compute actual search ranges needed
int lengthFind = strlen(s);
int endSearch = 0;
int endSearch = endPos;
if (startPos <= endPos) {
endSearch = endPos - lengthFind + 1;
} else {
endSearch = endPos;
}
//Platform::DebugPrintf("Find %d %d %s %d\n", startPos, endPos, ft->lpstrText, lengthFind);
char firstChar = s[0];
if (!caseSensitive)
firstChar = toupper(firstChar);
firstChar = static_cast<char>(toupper(firstChar));
int pos = startPos;
while (forward ? (pos < endSearch) : (pos >= endSearch)) {
char ch = CharAt(pos);
@@ -605,6 +770,25 @@ int Document::LinesTotal() {
return cb.Lines();
}
void Document::ChangeCase(Range r, bool makeUpperCase) {
for (int pos=r.start; pos<r.end; pos++) {
char ch = CharAt(pos);
if (dbcsCodePage && IsDBCS(pos)) {
pos += LenChar(pos);
} else {
if (makeUpperCase) {
if (islower(ch)) {
ChangeChar(pos, static_cast<char>(toupper(ch)));
}
} else {
if (isupper(ch)) {
ChangeChar(pos, static_cast<char>(tolower(ch)));
}
}
}
}
}
void Document::SetWordChars(unsigned char *chars) {
int ch;
for (ch = 0; ch < 256; ch++) {
@@ -671,6 +855,13 @@ void Document::SetStyles(int length, char *styles) {
}
}
bool Document::EnsureStyledTo(int pos) {
// Ask the watchers to style, and stop as soon as one responds.
for (int i = 0; pos > GetEndStyled() && i < lenWatchers; i++)
watchers[i].watcher->NotifyStyleNeeded(this, watchers[i].userData, pos);
return pos <= GetEndStyled();
}
bool Document::AddWatcher(DocWatcher *watcher, void *userData) {
for (int i = 0; i < lenWatchers; i++) {
if ((watchers[i].watcher == watcher) &&

View File

@@ -74,9 +74,10 @@ private:
CellBuffer cb;
bool wordchars[256];
int stylingPos;
int stylingMask;
char stylingMask;
int endStyled;
int enteredCount;
int enteredReadOnlyCount;
WatcherWithUserData *watchers;
int lenWatchers;
@@ -86,8 +87,11 @@ public:
int stylingBitsMask;
int eolMode;
// dbcsCodePage can also be SC_CP_UTF8 to enable UTF-8 mode
int dbcsCodePage;
int tabInChars;
int indentInChars;
bool useTabs;
Document();
virtual ~Document();
@@ -98,6 +102,7 @@ public:
int LineFromPosition(int pos);
int ClampPositionIntoDocument(int pos);
bool IsCrLf(int pos);
int LenChar(int pos);
int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true);
// Gateways to modifying document
@@ -111,11 +116,14 @@ public:
undoCollectionType SetUndoCollection(undoCollectionType collectUndo) {
return cb.SetUndoCollection(collectUndo);
}
void AppendUndoStartAction() { cb.AppendUndoStartAction(); }
void BeginUndoAction() { cb.BeginUndoAction(); }
void EndUndoAction() { cb.EndUndoAction(); }
void SetSavePoint();
bool IsSavePoint() { return cb.IsSavePoint(); }
int GetLineIndentation(int line);
void SetLineIndentation(int line, int indent);
int GetLineIndentPosition(int line);
void Indent(bool forwards, int lineBottom, int lineTop);
void ConvertLineEnds(int eolModeSet);
void SetReadOnly(bool set) { cb.SetReadOnly(set); }
@@ -123,6 +131,7 @@ public:
void InsertChar(int pos, char ch);
void InsertString(int position, const char *s);
void InsertString(int position, const char *s, int insertLength);
void ChangeChar(int pos, char ch);
void DelChar(int pos);
int DelCharBack(int pos);
@@ -132,12 +141,13 @@ public:
}
char StyleAt(int position) { return cb.StyleAt(position); }
int GetMark(int line) { return cb.GetMark(line); }
int AddMark(int line, int markerNum) { return cb.AddMark(line, markerNum); }
void DeleteMark(int line, int markerNum) { cb.DeleteMark(line, markerNum); }
void DeleteMarkFromHandle(int markerHandle) { cb.DeleteMarkFromHandle(markerHandle); }
void DeleteAllMarks(int markerNum) { cb.DeleteAllMarks(markerNum); }
int AddMark(int line, int markerNum);
void DeleteMark(int line, int markerNum);
void DeleteMarkFromHandle(int markerHandle);
void DeleteAllMarks(int markerNum);
int LineFromHandle(int markerHandle) { return cb.LineFromHandle(markerHandle); }
int LineStart(int line);
int LineEnd(int line);
int LineEndPosition(int position);
int VCHomePosition(int position);
@@ -154,12 +164,15 @@ public:
long FindText(WORD iMessage,WPARAM wParam,LPARAM lParam);
int LinesTotal();
void ChangeCase(Range r, bool makeUpperCase);
void SetWordChars(unsigned char *chars);
void SetStylingBits(int bits);
void StartStyling(int position, char mask);
void SetStyleFor(int length, char style);
void SetStyles(int length, char *styles);
int GetEndStyled() { return endStyled; }
bool EnsureStyledTo(int pos);
int SetLineState(int line, int state) { return cb.SetLineState(line, state); }
int GetLineState(int line) { return cb.GetLineState(line); }
@@ -175,10 +188,12 @@ private:
bool IsWordChar(unsigned char ch);
bool IsWordAt(int start, int end);
void ModifiedAt(int pos);
void NotifyModifyAttempt();
void NotifySavePoint(bool atSavePoint);
void NotifyModified(DocModification mh);
int IndentSize() { return indentInChars ? indentInChars : tabInChars; }
};
// To optimise processing of document modifications by DocWatchers, a hint is passed indicating the
@@ -205,6 +220,16 @@ public:
line(0),
foldLevelNow(0),
foldLevelPrev(0) {}
DocModification(int modificationType_, const Action &act, int linesAdded_=0) :
modificationType(modificationType_),
position(act.position / 2),
length(act.lenData),
linesAdded(linesAdded_),
text(act.data),
line(0),
foldLevelNow(0),
foldLevelPrev(0) {}
};
// A class that wants to receive notifications from a Document must be derived from DocWatcher
@@ -217,6 +242,7 @@ public:
virtual void NotifySavePoint(Document *doc, void *userData, bool atSavePoint) = 0;
virtual void NotifyModified(Document *doc, DocModification mh, void *userData) = 0;
virtual void NotifyDeleted(Document *doc, void *userData) = 0;
virtual void NotifyStyleNeeded(Document *doc, void *userData, int endPos) = 0;
};
#endif

View File

@@ -0,0 +1,174 @@
// SciTE - Scintilla based Text Editor
// Accessor.cxx - rapid easy access to contents of a Scintilla
// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include "Platform.h"
#include "PropSet.h"
#include "SVector.h"
#include "Accessor.h"
#include "DocumentAccessor.h"
#include "CellBuffer.h"
#include "Scintilla.h"
#include "Document.h"
DocumentAccessor::~DocumentAccessor() {
}
bool DocumentAccessor::InternalIsLeadByte(char ch) {
#if PLAT_GTK
// TODO: support DBCS under GTK+
return false;
#elif PLAT_WIN
if (SC_CP_UTF8 == codePage)
// For lexing, all characters >= 0x80 are treated the
// same so none is considered a lead byte.
return false;
else
return IsDBCSLeadByteEx(codePage, ch);
#elif PLAT_WX
return false;
#endif
}
void DocumentAccessor::Fill(int position) {
if (lenDoc == -1)
lenDoc = pdoc->Length();
startPos = position - slopSize;
if (startPos + bufferSize > lenDoc)
startPos = lenDoc - bufferSize;
if (startPos < 0)
startPos = 0;
endPos = startPos + bufferSize;
if (endPos > lenDoc)
endPos = lenDoc;
pdoc->GetCharRange(buf, startPos, endPos-startPos);
buf[endPos-startPos] = '\0';
}
char DocumentAccessor::StyleAt(int position) {
return pdoc->StyleAt(position);
}
int DocumentAccessor::GetLine(int position) {
return pdoc->LineFromPosition(position);
}
int DocumentAccessor::LineStart(int line) {
return pdoc->LineStart(line);
}
int DocumentAccessor::LevelAt(int line) {
return pdoc->GetLevel(line);
}
int DocumentAccessor::Length() {
if (lenDoc == -1)
lenDoc = pdoc->Length();
return lenDoc;
}
int DocumentAccessor::GetLineState(int line) {
return pdoc->GetLineState(line);
}
int DocumentAccessor::SetLineState(int line, int state) {
return pdoc->SetLineState(line, state);
}
void DocumentAccessor::StartAt(unsigned int start, char chMask) {
pdoc->StartStyling(start, chMask);
}
void DocumentAccessor::StartSegment(unsigned int pos) {
startSeg = pos;
}
void DocumentAccessor::ColourTo(unsigned int pos, int chAttr) {
// Only perform styling if non empty range
if (pos != startSeg - 1) {
if (pos < startSeg) {
Platform::DebugPrintf("Bad colour positions %d - %d\n", startSeg, pos);
}
if (validLen + (pos - startSeg + 1) >= bufferSize)
Flush();
if (validLen + (pos - startSeg + 1) >= bufferSize) {
// Too big for buffer so send directly
pdoc->SetStyleFor(pos - startSeg + 1, static_cast<char>(chAttr));
} else {
if (chAttr != chWhile)
chFlags = 0;
chAttr |= chFlags;
for (unsigned int i = startSeg; i <= pos; i++) {
styleBuf[validLen++] = static_cast<char>(chAttr);
}
}
}
startSeg = pos+1;
}
void DocumentAccessor::SetLevel(int line, int level) {
pdoc->SetLevel(line, level);
}
void DocumentAccessor::Flush() {
startPos = extremePosition;
lenDoc = -1;
if (validLen > 0) {
pdoc->SetStyles(validLen, styleBuf);
validLen = 0;
}
}
int DocumentAccessor::IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader) {
int end = Length();
int spaceFlags = 0;
// Determines the indentation level of the current line and also checks for consistent
// indentation compared to the previous line.
// Indentation is judged consistent when the indentation whitespace of each line lines
// the same or the indentation of one line is a prefix of the other.
int pos = LineStart(line);
char ch = (*this)[pos];
int indent = 0;
bool inPrevPrefix = line > 0;
int posPrev = inPrevPrefix ? LineStart(line-1) : 0;
while ((ch == ' ' || ch == '\t') && (pos < end)) {
if (inPrevPrefix) {
char chPrev = (*this)[posPrev++];
if (chPrev == ' ' || chPrev == '\t') {
if (chPrev != ch)
spaceFlags |= wsInconsistent;
} else {
inPrevPrefix = false;
}
}
if (ch == ' ') {
spaceFlags |= wsSpace;
indent++;
} else { // Tab
spaceFlags |= wsTab;
if (spaceFlags & wsSpace)
spaceFlags |= wsSpaceTab;
indent = (indent / 8 + 1) * 8;
}
ch = (*this)[++pos];
}
*flags = spaceFlags;
indent += SC_FOLDLEVELBASE;
// if completely empty line or the start of a comment...
if (isspace(ch) || (pfnIsCommentLeader && (*pfnIsCommentLeader)(*this, pos, end-pos)) )
return indent | SC_FOLDLEVELWHITEFLAG;
else
return indent;
}

View File

@@ -0,0 +1,49 @@
// DocumentAccessor.h - implementation of BufferAccess and StylingAccess on a Scintilla rapid easy access to contents of a Scintilla
// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
class Document;
class DocumentAccessor : public Accessor {
// Private so DocumentAccessor objects can not be copied
DocumentAccessor(const DocumentAccessor &source) : Accessor(), props(source.props) {}
DocumentAccessor &operator=(const DocumentAccessor &) { return *this; }
protected:
Document *pdoc;
PropSet &props;
int lenDoc;
char styleBuf[bufferSize];
int validLen;
char chFlags;
char chWhile;
unsigned int startSeg;
bool InternalIsLeadByte(char ch);
void Fill(int position);
public:
DocumentAccessor(Document *pdoc_, PropSet &props_) :
Accessor(), pdoc(pdoc_), props(props_),
lenDoc(-1), validLen(0), chFlags(0) {
}
~DocumentAccessor();
char StyleAt(int position);
int GetLine(int position);
int LineStart(int line);
int LevelAt(int line);
int Length();
void Flush();
int GetLineState(int line);
int SetLineState(int line, int state);
int GetPropertyInt(const char *key, int defaultValue=0) {
return props.GetInt(key, defaultValue);
}
void StartAt(unsigned int start, char chMask=31);
void SetFlags(char chFlags_, char chWhile_) {chFlags = chFlags_; chWhile = chWhile_; };
unsigned int GetStartSegment() { return startSeg; }
void StartSegment(unsigned int pos);
void ColourTo(unsigned int pos, int chAttr);
void SetLevel(int line, int level);
int IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader = 0);
};

View File

@@ -69,6 +69,7 @@ Editor::Editor() {
xOffset = 0;
xCaretMargin = 50;
horizontalScrollBarVisible = true;
currentPos = 0;
anchor = 0;
@@ -88,6 +89,8 @@ Editor::Editor() {
modEventMask = SC_MODEVENTMASKALL;
displayPopupMenu = true;
pdoc = new Document();
pdoc ->AddRef();
pdoc->AddWatcher(this, 0);
@@ -187,7 +190,7 @@ bool IsControlCharacter(char ch) {
return ch >= 0 && ch < ' ';
}
const char *ControlCharacterString(char ch) {
const char *ControlCharacterString(unsigned char ch) {
const char *reps[] = {
"NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
"BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
@@ -208,6 +211,7 @@ Point Editor::LocationFromPosition(unsigned int pos) {
//Platform::DebugPrintf("line=%d\n", line);
Surface surface;
surface.Init();
surface.SetUnicodeMode(SC_CP_UTF8 == pdoc->dbcsCodePage);
Point pt;
pt.y = (lineVisible - topLine) * vs.lineHeight; // + half a lineheight?
unsigned int posLineStart = pdoc->LineStart(line);
@@ -250,6 +254,7 @@ int Editor::PositionFromLocation(Point pt) {
//Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine);
Surface surface;
surface.Init();
surface.SetUnicodeMode(SC_CP_UTF8 == pdoc->dbcsCodePage);
unsigned int posLineStart = pdoc->LineStart(line);
LineLayout ll;
@@ -271,6 +276,7 @@ int Editor::PositionFromLineX(int line, int x) {
//Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine);
Surface surface;
surface.Init();
surface.SetUnicodeMode(SC_CP_UTF8 == pdoc->dbcsCodePage);
unsigned int posLineStart = pdoc->LineStart(line);
LineLayout ll;
@@ -483,7 +489,7 @@ void Editor::ScrollTo(int line) {
}
}
void Editor::ScrollText(int linesToMove) {
void Editor::ScrollText(int /* linesToMove */) {
//Platform::DebugPrintf("Editor::ScrollText %d\n", linesToMove);
Redraw();
}
@@ -497,6 +503,19 @@ void Editor::HorizontalScrollTo(int xPos) {
Redraw();
}
void Editor::MoveCaretInsideView() {
PRectangle rcClient = GetTextRectangle();
Point pt = LocationFromPosition(currentPos);
if (pt.y < rcClient.top) {
MovePositionTo(PositionFromLocation(
Point(lastXChosen, rcClient.top)));
} else if ((pt.y + vs.lineHeight - 1) > rcClient.bottom) {
int yOfLastLineFullyDisplayed = rcClient.top + (LinesOnScreen()-1) * vs.lineHeight;
MovePositionTo(PositionFromLocation(
Point(lastXChosen, rcClient.top + yOfLastLineFullyDisplayed)));
}
}
void Editor::EnsureCaretVisible(bool useMargin) {
//Platform::DebugPrintf("EnsureCaretVisible %d\n", xOffset);
PRectangle rcClient = GetTextRectangle();
@@ -631,7 +650,7 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) {
int line = cs.DocFromDisplay(visibleLine);
int yposScreen = 0;
while (line < pdoc->LinesTotal() && yposScreen < rcMargin.bottom) {
while ((visibleLine < cs.LinesDisplayed()) && yposScreen < rcMargin.bottom) {
int marks = pdoc->GetMark(line);
if (pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG) {
if (cs.GetExpanded(line)) {
@@ -648,13 +667,12 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) {
char number[100];
number[0] = '\0';
sprintf(number, "%d", line + 1);
if (foldFlags & 8)
if (foldFlags & 64)
sprintf(number, "%X", pdoc->GetLevel(line));
int xpos = 0;
PRectangle rcNumber=rcMarker;
// Right justify
int width = surface->WidthText(vs.styles[STYLE_LINENUMBER].font, number, strlen(number));
xpos = rcNumber.right - width - 3;
int xpos = rcNumber.right - width - 3;
rcNumber.left = xpos;
if ((visibleLine < cs.LinesDisplayed()) && cs.GetVisible(line)) {
surface->DrawText(rcNumber, vs.styles[STYLE_LINENUMBER].font,
@@ -718,8 +736,8 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou
styleByte = pdoc->StyleAt(charInDoc);
if (vstyle.viewEOL || ((chDoc != '\r') && (chDoc != '\n'))) {
ll.chars[numCharsInLine] = chDoc;
ll.styles[numCharsInLine] = styleByte & styleMask;
ll.indicators[numCharsInLine] = styleByte & ~styleMask;
ll.styles[numCharsInLine] = static_cast<char>(styleByte & styleMask);
ll.indicators[numCharsInLine] = static_cast<char>(styleByte & ~styleMask);
numCharsInLine++;
}
}
@@ -853,7 +871,7 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int xStart,
} else {
rcSegment.left = ll.positions[startseg] + xStart;
rcSegment.right = ll.positions[i + 1] + xStart;
// Only try do draw if really visible - enhances performance by not calling environment to
// Only try to draw if really visible - enhances performance by not calling environment to
// draw strings that are completely past the right side of the window.
if (rcSegment.left <= rcLine.right) {
surface->DrawText(rcSegment, textFont,
@@ -871,6 +889,12 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int xStart,
}
}
}
if (vsDraw.styles[styleMain].underline) {
PRectangle rcUL = rcSegment;
rcUL.top = rcUL.top + vsDraw.maxAscent + 1;
rcUL.bottom = rcUL.top + 1;
surface->FillRectangle(rcUL, textFore);
}
}
startseg = i + 1;
}
@@ -991,10 +1015,9 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
ypos += screenLinePaintFirst * vs.lineHeight;
int yposScreen = screenLinePaintFirst * vs.lineHeight;
if (endPosPaint > pdoc->GetEndStyled()) {
// Notify container to do some more styling
NotifyStyleNeeded(endPosPaint);
}
// Ensure we are styled as far as we are painting.
pdoc->EnsureStyledTo(endPosPaint);
if (needUpdateUI) {
NotifyUpdateUI();
needUpdateUI = false;
@@ -1009,21 +1032,20 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
}
if (paintState == paintAbandoned) {
// Either NotifyStyleNeeded or NotifyUpdateUI noticed that painting is needed
// Either styling or NotifyUpdateUI noticed that painting is needed
// outside the current painting rectangle
//Platform::DebugPrintf("Abandoning paint\n");
return;
}
//Platform::DebugPrintf("start display %d, offset = %d\n", pdoc->Length(), xOffset);
Surface *surface = 0;
if (rcArea.right > vs.fixedColumnWidth) {
Surface *surface = surfaceWindow;
if (bufferedDraw) {
surface = &pixmapLine;
} else {
surface = surfaceWindow;
}
surface->SetUnicodeMode(SC_CP_UTF8 == pdoc->dbcsCodePage);
int visibleLine = topLine + screenLinePaintFirst;
int line = cs.DocFromDisplay(visibleLine);
@@ -1059,27 +1081,38 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
// Highlight the current braces if any
if ((braces[0] >= posLineStart) && (braces[0] < posLineEnd))
ll.styles[braces[0] - posLineStart] = bracesMatchStyle;
ll.styles[braces[0] - posLineStart] =
static_cast<char>(bracesMatchStyle);
if ((braces[1] >= posLineStart) && (braces[1] < posLineEnd))
ll.styles[braces[1] - posLineStart] = bracesMatchStyle;
ll.styles[braces[1] - posLineStart] =
static_cast<char>(bracesMatchStyle);
// Draw the line
if (cs.GetVisible(line))
DrawLine(surface, vs, line, xStart, rcLine, ll);
if (foldFlags & 2) {
bool expanded = cs.GetExpanded(line);
if ( (expanded && (foldFlags & 2)) || (!expanded && (foldFlags & 4)) ) {
if (pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG) {
PRectangle rcFoldLine = rcLine;
rcFoldLine.bottom = rcFoldLine.top + 1;
surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore.allocated);
}
}
if ( (expanded && (foldFlags & 8)) || (!expanded && (foldFlags & 16)) ) {
if (pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG) {
PRectangle rcFoldLine = rcLine;
rcFoldLine.top = rcFoldLine.bottom - 1;
surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore.allocated);
}
}
// Draw the Caret
if (line == lineCaret) {
int xposCaret = ll.positions[posCaret - posLineStart] + xStart;
int offset = Platform::Minimum(posCaret - posLineStart, LineLayout::maxLineLength);
int xposCaret = ll.positions[offset] + xStart;
int widthOverstrikeCaret =
ll.positions[posCaret - posLineStart + 1] - ll.positions[posCaret - posLineStart];
ll.positions[offset + 1] - ll.positions[offset];
if (posCaret == pdoc->Length()) // At end of document
widthOverstrikeCaret = vs.aveCharWidth;
if ((posCaret - posLineStart) >= ll.numCharsInLine) // At end of line
@@ -1154,8 +1187,10 @@ long Editor::FormatRange(bool draw, FORMATRANGE *pfr) {
Surface *surface = new Surface();
surface->Init(pfr->hdc);
surface->SetUnicodeMode(SC_CP_UTF8 == pdoc->dbcsCodePage);
Surface *surfaceMeasure = new Surface();
surfaceMeasure->Init(pfr->hdcTarget);
surfaceMeasure->SetUnicodeMode(SC_CP_UTF8 == pdoc->dbcsCodePage);
ViewStyle vsPrint(vs);
@@ -1204,10 +1239,9 @@ long Editor::FormatRange(bool draw, FORMATRANGE *pfr) {
if (linePrintLast < pdoc->LinesTotal())
endPosPrint = pdoc->LineStart(linePrintLast + 1);
if (endPosPrint > pdoc->GetEndStyled()) {
// Notify container to do some more styling
NotifyStyleNeeded(endPosPrint);
}
// Ensure we are styled to where we are formatting.
pdoc->EnsureStyledTo(endPosPrint);
int xStart = vsPrint.fixedColumnWidth + pfr->rc.left + lineNumberWidth;
int ypos = pfr->rc.top;
int line = linePrintStart;
@@ -1228,20 +1262,27 @@ long Editor::FormatRange(bool draw, FORMATRANGE *pfr) {
PRectangle rcNumber = rcLine;
rcNumber.right = rcNumber.left + lineNumberWidth;
// Right justify
rcNumber.left += lineNumberWidth -
rcNumber.left -=
surface->WidthText(vsPrint.styles[STYLE_LINENUMBER].font, number, strlen(number));
surface->DrawText(rcNumber, vsPrint.styles[STYLE_LINENUMBER].font,
ypos + vsPrint.maxAscent, number, strlen(number),
vsPrint.styles[STYLE_LINENUMBER].fore.allocated,
vsPrint.styles[STYLE_LINENUMBER].back.allocated);
}
// When printing, the hdc and hdcTarget may be the same, so
// changing the state of surfaceMeasure may change the underlying
// state of surface. Therefore, any cached state is discarded before
// using each surface.
// Copy this line and its styles from the document into local arrays
// and determine the x position at which each character starts.
surfaceMeasure->FlushCachedState();
LineLayout ll;
LayoutLine(line, surfaceMeasure, vsPrint, ll);
// Draw the line
surface->FlushCachedState();
DrawLine(surface, vsPrint, line, xStart, rcLine, ll);
ypos += vsPrint.lineHeight;
@@ -1255,6 +1296,10 @@ long Editor::FormatRange(bool draw, FORMATRANGE *pfr) {
return endPosPrint;
}
// Empty method is overridden on GTK+ to show / hide scrollbars
void Editor::ReconfigureScrollBars() {
}
void Editor::SetScrollBarsTo(PRectangle) {
RefreshStyleData();
@@ -1280,6 +1325,13 @@ void Editor::SetScrollBars() {
}
void Editor::AddChar(char ch) {
char s[2];
s[0] = ch;
s[1] = '\0';
AddCharUTF(s, 1);
}
void Editor::AddCharUTF(char *s, unsigned int len) {
bool wasSelection = currentPos != anchor;
ClearSelection();
if (inOverstrike && !wasSelection) {
@@ -1289,11 +1341,11 @@ void Editor::AddChar(char ch) {
}
}
}
pdoc->InsertChar(currentPos, ch);
SetEmptySelection(currentPos + 1);
pdoc->InsertString(currentPos, s, len);
SetEmptySelection(currentPos + len);
EnsureCaretVisible();
SetLastXChosen();
NotifyChar(ch);
NotifyChar(s[0]);
}
void Editor::ClearSelection() {
@@ -1302,8 +1354,7 @@ void Editor::ClearSelection() {
int lineStart = pdoc->LineFromPosition(SelectionStart());
int lineEnd = pdoc->LineFromPosition(SelectionEnd());
int startPos = SelectionStart();
int line;
for (line=lineStart; line <= lineEnd; line++) {
for (int line=lineEnd; line >= lineStart; line--) {
startPos = SelectionStart(line);
unsigned int chars = SelectionEnd(line) - startPos;
if (0 != chars) {
@@ -1414,13 +1465,17 @@ void Editor::DelCharBack() {
void Editor::NotifyFocus(bool) {
}
void Editor::NotifyStyleNeeded(int endStyleNeeded) {
void Editor::NotifyStyleToNeeded(int endStyleNeeded) {
SCNotification scn;
scn.nmhdr.code = SCN_STYLENEEDED;
scn.position = endStyleNeeded;
NotifyParent(scn);
}
void Editor::NotifyStyleNeeded(Document*, void *, int endStyleNeeded) {
NotifyStyleToNeeded(endStyleNeeded);
}
void Editor::NotifyChar(char ch) {
SCNotification scn;
scn.nmhdr.code = SCN_CHARADDED;
@@ -1563,13 +1618,17 @@ void Editor::NotifyModified(Document*, DocModification mh, void *) {
}
}
}
if (mh.modificationType & SC_MOD_BEFOREINSERT) {
NotifyNeedShown(mh.position, 0);
} else if (mh.modificationType & SC_MOD_BEFOREDELETE) {
NotifyNeedShown(mh.position, mh.length);
}
if (mh.linesAdded != 0) {
// Update contraction state for inserted and removed lines
// lineOfPos should be calculated in context of state before modification, shouldn't it
int lineOfPos = pdoc->LineFromPosition(mh.position);
if (mh.linesAdded > 0) {
NotifyNeedShown(mh.position, mh.length);
cs.InsertLines(lineOfPos, mh.linesAdded);
} else {
cs.DeleteLines(lineOfPos, -mh.linesAdded);
@@ -1599,6 +1658,10 @@ void Editor::NotifyModified(Document*, DocModification mh, void *) {
SetScrollBars();
}
if (mh.modificationType & SC_MOD_CHANGEMARKER) {
RedrawSelMargin();
}
// If client wants to see this modification
if (mh.modificationType & modEventMask) {
if ((mh.modificationType & SC_MOD_CHANGESTYLE) == 0) {
@@ -1619,7 +1682,7 @@ void Editor::NotifyModified(Document*, DocModification mh, void *) {
}
}
void Editor::NotifyDeleted(Document *document, void *userData) {
void Editor::NotifyDeleted(Document *, void *) {
/* Do nothing */
}
@@ -1677,6 +1740,11 @@ void Editor::NotifyMacroRecord(UINT iMessage, WPARAM wParam, LPARAM lParam) {
case SCI_VCHOMEEXTEND:
case SCI_DELWORDLEFT:
case SCI_DELWORDRIGHT:
case SCI_LINECUT:
case SCI_LINEDELETE:
case SCI_LINETRANSPOSE:
case SCI_LOWERCASE:
case SCI_UPPERCASE:
break;
// Filter out all others (display changes, etc)
@@ -1712,6 +1780,60 @@ void Editor::PageMove(int direction, bool extend) {
}
}
void Editor::ChangeCaseOfSelection(bool makeUpperCase) {
pdoc->BeginUndoAction();
int startCurrent = currentPos;
int startAnchor = anchor;
if (selType == selRectangle) {
int lineStart = pdoc->LineFromPosition(SelectionStart());
int lineEnd = pdoc->LineFromPosition(SelectionEnd());
for (int line=lineEnd; line >= lineStart; line--) {
pdoc->ChangeCase(
Range(SelectionStart(line), SelectionEnd(line)),
makeUpperCase);
}
// Would be nicer to keep the rectangular selection but this is complex
selType = selStream;
SetSelection(startCurrent, startCurrent);
} else {
pdoc->ChangeCase(Range(SelectionStart(), SelectionEnd()),
makeUpperCase);
SetSelection(startCurrent, startAnchor);
}
pdoc->EndUndoAction();
}
void Editor::LineTranspose() {
int line = pdoc->LineFromPosition(currentPos);
if (line > 0) {
int startPrev = pdoc->LineStart(line-1);
int endPrev = pdoc->LineEnd(line-1);
int start = pdoc->LineStart(line);
int end = pdoc->LineEnd(line);
int startNext = pdoc->LineStart(line+1);
if (end < pdoc->Length()) {
end = startNext;
char *thisLine = CopyRange(start, end);
pdoc->DeleteChars(start, end-start);
pdoc->InsertString(startPrev, thisLine, end-start);
MovePositionTo(startPrev+end-start);
delete []thisLine;
} else {
// Last line so line has no line end
char *thisLine = CopyRange(start, end);
char *prevEnd = CopyRange(endPrev, start);
pdoc->DeleteChars(endPrev, end-endPrev);
pdoc->InsertString(startPrev, thisLine, end-start);
pdoc->InsertString(startPrev + end-start, prevEnd, start-endPrev);
MovePositionTo(startPrev + end-endPrev);
delete []thisLine;
delete []prevEnd;
}
}
}
int Editor::KeyCommand(UINT iMessage) {
Point pt = LocationFromPosition(currentPos);
@@ -1724,6 +1846,10 @@ int Editor::KeyCommand(UINT iMessage) {
MovePositionTo(PositionFromLocation(
Point(lastXChosen, pt.y + vs.lineHeight)), true);
break;
case SCI_LINESCROLLDOWN:
ScrollTo(topLine + 1);
MoveCaretInsideView();
break;
case SCI_LINEUP:
MovePositionTo(PositionFromLocation(
Point(lastXChosen, pt.y - vs.lineHeight)));
@@ -1732,6 +1858,10 @@ int Editor::KeyCommand(UINT iMessage) {
MovePositionTo(PositionFromLocation(
Point(lastXChosen, pt.y - vs.lineHeight)), true);
break;
case SCI_LINESCROLLUP:
ScrollTo(topLine - 1);
MoveCaretInsideView();
break;
case SCI_CHARLEFT:
if (SelectionEmpty()) {
MovePositionTo(MovePositionSoVisible(currentPos - 1, -1));
@@ -1827,6 +1957,7 @@ int Editor::KeyCommand(UINT iMessage) {
break;
case SCI_DELETEBACK:
DelCharBack();
SetLastXChosen();
EnsureCaretVisible();
break;
case SCI_TAB:
@@ -1879,13 +2010,46 @@ int Editor::KeyCommand(UINT iMessage) {
int startWord = pdoc->NextWordStart(currentPos, -1);
pdoc->DeleteChars(startWord, currentPos - startWord);
MovePositionTo(startWord);
SetLastXChosen();
}
break;
case SCI_DELWORDRIGHT: {
int endWord = pdoc->NextWordStart(currentPos, 1);
pdoc->DeleteChars(currentPos, endWord - currentPos);
MovePositionTo(currentPos);
}
break;
case SCI_LINECUT: {
int lineStart = pdoc->LineFromPosition(currentPos);
int lineEnd = pdoc->LineFromPosition(anchor);
if (lineStart > lineEnd) {
int t = lineEnd;
lineEnd = lineStart;
lineStart = t;
}
int start = pdoc->LineStart(lineStart);
int end = pdoc->LineStart(lineEnd+1);
SetSelection(start,end);
Cut();
}
break;
case SCI_LINEDELETE: {
int line = pdoc->LineFromPosition(currentPos);
int start = pdoc->LineStart(line);
int end = pdoc->LineStart(line+1);
pdoc->DeleteChars(start, end-start);
MovePositionTo(start);
}
break;
case SCI_LINETRANSPOSE:
LineTranspose();
break;
case SCI_LOWERCASE:
ChangeCaseOfSelection(false);
break;
case SCI_UPPERCASE:
ChangeCaseOfSelection(true);
break;
}
return 0;
}
@@ -2111,7 +2275,11 @@ void Editor::DropAt(int position, const char *value, bool moving, bool rectangul
int positionWasInSelection = PositionInSelection(position);
if ((!inDragDrop) || !(0 == positionWasInSelection)) {
bool positionOnEdgeOfSelection =
(position == SelectionStart()) || (position == SelectionEnd());
if ((!inDragDrop) || !(0 == positionWasInSelection) ||
(positionOnEdgeOfSelection && !moving)) {
int selStart = SelectionStart();
int selEnd = SelectionEnd();
@@ -2510,12 +2678,13 @@ char BraceOpposite(char ch) {
// TODO: should be able to extend styled region to find matching brace
// TODO: may need to make DBCS safe
// so should be moved into Document
int Editor::BraceMatch(int position, int maxReStyle) {
int Editor::BraceMatch(int position, int /*maxReStyle*/) {
char chBrace = pdoc->CharAt(position);
char chSeek = BraceOpposite(chBrace);
if (!chSeek)
if (chSeek == '\0')
return - 1;
char styBrace = pdoc->StyleAt(position) & pdoc->stylingBitsMask;
char styBrace = static_cast<char>(
pdoc->StyleAt(position) & pdoc->stylingBitsMask);
int direction = -1;
if (chBrace == '(' || chBrace == '[' || chBrace == '{' || chBrace == '<')
direction = 1;
@@ -2523,7 +2692,7 @@ int Editor::BraceMatch(int position, int maxReStyle) {
position = position + direction;
while ((position >= 0) && (position < pdoc->Length())) {
char chAtPos = pdoc->CharAt(position);
char styAtPos = pdoc->StyleAt(position) & pdoc->stylingBitsMask;
char styAtPos = static_cast<char>(pdoc->StyleAt(position) & pdoc->stylingBitsMask);
if ((position > pdoc->GetEndStyled()) || (styAtPos == styBrace)) {
if (chAtPos == chBrace)
depth++;
@@ -2566,6 +2735,10 @@ void Editor::SetDocPointer(Document *document) {
pdoc = document;
}
pdoc->AddRef();
// Reset the contraction state to fully shown.
cs.Clear();
cs.InsertLines(0, pdoc->LinesTotal()-1);
pdoc->AddWatcher(this, 0);
Redraw();
SetScrollBars();
@@ -2628,6 +2801,11 @@ void Editor::EnsureLineVisible(int line) {
}
}
static bool ValidMargin(WPARAM wParam) {
return wParam < ViewStyle::margins;
}
LRESULT Editor::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
//Platform::DebugPrintf("S start wnd proc %d %d %d\n",iMessage, wParam, lParam);
@@ -2680,6 +2858,7 @@ LRESULT Editor::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
case WM_PASTE:
Paste();
SetLastXChosen();
EnsureCaretVisible();
break;
case WM_CLEAR:
@@ -2734,19 +2913,20 @@ LRESULT Editor::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
// EM_GETPUNCTUATION
// EM_SETPUNCTUATION
// EM_GETTHUMB
// EM_SETTARGETDEVICE
// Not supported but should be:
// EM_GETEVENTMASK
// EM_SETEVENTMASK
// For printing:
// EM_DISPLAYBAND
// EM_SETTARGETDEVICE
case EM_CANUNDO:
return pdoc->CanUndo() ? TRUE : FALSE;
case EM_UNDO:
Undo();
SetLastXChosen();
break;
case EM_EMPTYUNDOBUFFER:
@@ -2782,12 +2962,6 @@ LRESULT Editor::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
case EM_GETMODIFY:
return !pdoc->IsSavePoint();
case EM_SETMODIFY:
// Not really supported now that there is the save point stuff
//pdoc->isModified = wParam;
//return pdoc->isModified;
return false;
case EM_GETRECT:
if (lParam == 0)
return 0;
@@ -2851,22 +3025,6 @@ LRESULT Editor::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
return iChar;
}
case EM_GETWORDBREAKPROC:
return 0;
case EM_SETWORDBREAKPROC:
break;
case EM_LIMITTEXT:
// wParam holds the number of characters control should be limited to
break;
case EM_GETLIMITTEXT:
return 0xffffffff;
case EM_GETOLEINTERFACE:
return 0;
case EM_LINEFROMCHAR:
if (static_cast<int>(wParam) < 0)
wParam = SelectionStart();
@@ -2936,9 +3094,6 @@ LRESULT Editor::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
pdoc->SetReadOnly(wParam);
return TRUE;
case EM_SETRECT:
break;
case EM_CANPASTE:
return 1;
@@ -3061,7 +3216,8 @@ LRESULT Editor::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
#ifdef INCLUDE_DEPRECATED_FEATURES
case SCI_APPENDUNDOSTARTACTION:
pdoc->AppendUndoStartAction();
// Not just deprecated - now dead
//pdoc->AppendUndoStartAction();
return 0;
#endif
@@ -3189,11 +3345,11 @@ LRESULT Editor::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
break;
case SCI_STARTSTYLING:
pdoc->StartStyling(wParam, lParam);
pdoc->StartStyling(wParam, static_cast<char>(lParam));
break;
case SCI_SETSTYLING:
pdoc->SetStyleFor(wParam, lParam);
pdoc->SetStyleFor(wParam, static_cast<char>(lParam));
break;
case SCI_SETSTYLINGEX: // Specify a complete styling buffer
@@ -3221,6 +3377,44 @@ LRESULT Editor::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
InvalidateStyleRedraw();
break;
case SCI_GETTABWIDTH:
return pdoc->tabInChars;
case SCI_SETINDENT:
pdoc->indentInChars = wParam;
InvalidateStyleRedraw();
break;
case SCI_GETINDENT:
return pdoc->indentInChars;
case SCI_SETUSETABS:
pdoc->useTabs = wParam;
InvalidateStyleRedraw();
break;
case SCI_GETUSETABS:
return pdoc->useTabs;
case SCI_SETLINEINDENTATION:
pdoc->SetLineIndentation(wParam, lParam);
break;
case SCI_GETLINEINDENTATION:
return pdoc->GetLineIndentation(wParam);
case SCI_GETLINEINDENTPOSITION:
return pdoc->GetLineIndentPosition(wParam);
case SCI_SETHSCROLLBAR :
horizontalScrollBarVisible = wParam;
SetScrollBars();
ReconfigureScrollBars();
break;
case SCI_GETHSCROLLBAR:
return horizontalScrollBarVisible;
case SCI_SETCODEPAGE:
pdoc->dbcsCodePage = wParam;
break;
@@ -3260,18 +3454,15 @@ LRESULT Editor::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
break;
case SCI_MARKERADD: {
int markerID = pdoc->AddMark(wParam, lParam);
RedrawSelMargin();
return markerID;
}
case SCI_MARKERDELETE:
pdoc->DeleteMark(wParam, lParam);
RedrawSelMargin();
break;
case SCI_MARKERDELETEALL:
pdoc->DeleteAllMarks(static_cast<int>(wParam));
RedrawSelMargin();
break;
case SCI_MARKERGET:
@@ -3295,53 +3486,53 @@ LRESULT Editor::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
return -1;
case SCI_SETMARGINTYPEN:
if (wParam >= 0 && wParam < ViewStyle::margins) {
if (ValidMargin(wParam)) {
vs.ms[wParam].symbol = (lParam == SC_MARGIN_SYMBOL);
InvalidateStyleRedraw();
}
break;
case SCI_GETMARGINTYPEN:
if (wParam >= 0 && wParam < ViewStyle::margins)
if (ValidMargin(wParam))
return vs.ms[wParam].symbol ? SC_MARGIN_SYMBOL : SC_MARGIN_NUMBER;
else
return 0;
case SCI_SETMARGINWIDTHN:
if (wParam >= 0 && wParam < ViewStyle::margins) {
if (ValidMargin(wParam)) {
vs.ms[wParam].width = lParam;
InvalidateStyleRedraw();
}
break;
case SCI_GETMARGINWIDTHN:
if (wParam >= 0 && wParam < ViewStyle::margins)
if (ValidMargin(wParam))
return vs.ms[wParam].width;
else
return 0;
case SCI_SETMARGINMASKN:
if (wParam >= 0 && wParam < ViewStyle::margins) {
if (ValidMargin(wParam)) {
vs.ms[wParam].mask = lParam;
InvalidateStyleRedraw();
}
break;
case SCI_GETMARGINMASKN:
if (wParam >= 0 && wParam < ViewStyle::margins)
if (ValidMargin(wParam))
return vs.ms[wParam].mask;
else
return 0;
case SCI_SETMARGINSENSITIVEN:
if (wParam >= 0 && wParam < ViewStyle::margins) {
if (ValidMargin(wParam)) {
vs.ms[wParam].sensitive = lParam;
InvalidateStyleRedraw();
}
break;
case SCI_GETMARGINSENSITIVEN:
if (wParam >= 0 && wParam < ViewStyle::margins)
if (ValidMargin(wParam))
return vs.ms[wParam].sensitive ? 1 : 0;
else
return 0;
@@ -3391,7 +3582,19 @@ LRESULT Editor::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
if (lParam == 0)
return 0;
if (wParam <= STYLE_MAX) {
strcpy(vs.styles[wParam].fontName, reinterpret_cast<char *>(lParam));
vs.SetStyleFontName(wParam, reinterpret_cast<const char *>(lParam));
InvalidateStyleRedraw();
}
break;
case SCI_STYLESETUNDERLINE:
if (wParam <= STYLE_MAX) {
vs.styles[wParam].underline = lParam;
InvalidateStyleRedraw();
}
break;
case SCI_STYLESETCHARACTERSET:
if (wParam <= STYLE_MAX) {
vs.styles[wParam].characterSet = lParam;
InvalidateStyleRedraw();
}
break;
@@ -3400,7 +3603,6 @@ LRESULT Editor::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
vs.ResetDefaultStyle();
InvalidateStyleRedraw();
break;
case SCI_SETSTYLEBITS:
pdoc->SetStylingBits(wParam);
break;
@@ -3485,14 +3687,20 @@ LRESULT Editor::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
case SCI_SEARCHNEXT:
case SCI_SEARCHPREV:
return SearchText(iMessage, wParam, lParam);
break;
case SCI_SETCARETPOLICY:
caretPolicy = wParam;
caretSlop = lParam;
break;
#ifdef INCLUDE_DEPRECATED_FEATURES
case SCI_LINESONSCREEN:
return LinesOnScreen();
case SCI_USEPOPUP:
displayPopupMenu = wParam;
break;
#ifdef INCLUDE_DEPRECATED_FEATURES
case SCI_SETFORE:
vs.styles[STYLE_DEFAULT].fore.desired = Colour(wParam);
InvalidateStyleRedraw();
@@ -3612,6 +3820,13 @@ LRESULT Editor::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
case SCI_ZOOMOUT:
case SCI_DELWORDLEFT:
case SCI_DELWORDRIGHT:
case SCI_LINECUT:
case SCI_LINEDELETE:
case SCI_LINETRANSPOSE:
case SCI_LOWERCASE:
case SCI_UPPERCASE:
case SCI_LINESCROLLDOWN:
case SCI_LINESCROLLUP:
return KeyCommand(iMessage);
case SCI_BRACEHIGHLIGHT:
@@ -3635,6 +3850,14 @@ LRESULT Editor::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
Redraw();
break;
case SCI_SETZOOM:
vs.zoomLevel = wParam;
InvalidateStyleRedraw();
break;
case SCI_GETZOOM:
return vs.zoomLevel;
case SCI_GETEDGECOLUMN:
return theEdge;
@@ -3666,6 +3889,14 @@ LRESULT Editor::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
SetDocPointer(reinterpret_cast<Document *>(lParam));
return 0;
case SCI_ADDREFDOC:
(reinterpret_cast<Document *>(lParam))->AddRef();
break;
case SCI_RELEASEDOC:
(reinterpret_cast<Document *>(lParam))->Release();
break;
case SCI_SETMODEVENTMASK:
modEventMask = wParam;
return 0;
@@ -3675,6 +3906,9 @@ LRESULT Editor::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
SetSelection(currentPos, anchor); // Ensure selection inside document
return 0;
case SCI_SELECTIONISRECTANGLE:
return (selType == selRectangle) ? 1 : 0;
#ifdef MACRO_SUPPORT
case SCI_STARTRECORD:
recordingMacro = 1;

View File

@@ -38,6 +38,9 @@ public:
};
class Editor : public DocWatcher {
// Private so Editor objects can not be copied
Editor(const Editor &) : DocWatcher() {}
Editor &operator=(const Editor &) { return *this; }
protected: // ScintillaBase subclass needs access to much of Editor
// On GTK+, Scintilla is a container widget holding two scroll bars and a drawing area
@@ -61,13 +64,14 @@ protected: // ScintillaBase subclass needs access to much of Editor
int xOffset; // Horizontal scrolled amount in pixels
int xCaretMargin; // Ensure this many pixels visible on both sides of caret
bool horizontalScrollBarVisible;
Surface pixmapLine;
Surface pixmapSelMargin;
Surface pixmapSelPattern;
// Intellimouse support - currently only implemented for Windows
unsigned int ucWheelScrollLines;
short cWheelDelta; //wheel delta from roll
int cWheelDelta; //wheel delta from roll
KeyMap kmap;
@@ -116,6 +120,8 @@ protected: // ScintillaBase subclass needs access to much of Editor
int searchAnchor;
int displayPopupMenu;
#ifdef MACRO_SUPPORT
int recordingMacro;
#endif
@@ -169,6 +175,7 @@ protected: // ScintillaBase subclass needs access to much of Editor
void ScrollTo(int line);
virtual void ScrollText(int linesToMove);
void HorizontalScrollTo(int xPos);
void MoveCaretInsideView();
void EnsureCaretVisible(bool useMargin=true);
void ShowCaretAtCurrentPosition();
void DropCaret();
@@ -184,10 +191,12 @@ protected: // ScintillaBase subclass needs access to much of Editor
virtual void SetVerticalScrollPos() = 0;
virtual void SetHorizontalScrollPos() = 0;
virtual bool ModifyScrollBars(int nMax, int nPage) = 0;
virtual void ReconfigureScrollBars();
void SetScrollBarsTo(PRectangle rsClient);
void SetScrollBars();
virtual void AddChar(char ch);
void AddChar(char ch);
virtual void AddCharUTF(char *s, unsigned int len);
void ClearSelection();
void ClearAll();
void Cut();
@@ -205,7 +214,7 @@ protected: // ScintillaBase subclass needs access to much of Editor
virtual void NotifyChange() = 0;
virtual void NotifyFocus(bool focus);
virtual void NotifyParent(SCNotification scn) = 0;
virtual void NotifyStyleNeeded(int endStyleNeeded);
virtual void NotifyStyleToNeeded(int endStyleNeeded);
void NotifyChar(char ch);
void NotifySavePoint(bool isSavePoint);
void NotifyModifyAttempt();
@@ -218,12 +227,16 @@ protected: // ScintillaBase subclass needs access to much of Editor
void NotifySavePoint(Document *document, void *userData, bool atSavePoint);
void NotifyModified(Document *document, DocModification mh, void *userData);
void NotifyDeleted(Document *document, void *userData);
void NotifyStyleNeeded(Document *doc, void *userData, int endPos);
#ifdef MACRO_SUPPORT
void NotifyMacroRecord(UINT iMessage, WPARAM wParam, LPARAM lParam);
#endif
void PageMove(int direction, bool extend=false);
void ChangeCaseOfSelection(bool makeUpperCase);
void LineTranspose();
virtual int KeyCommand(UINT iMessage);
virtual int KeyDefault(int /* key */, int /*modifiers*/);
int KeyDown(int key, bool shift, bool ctrl, bool alt);

View File

@@ -37,6 +37,22 @@ void Indicator::Draw(Surface *surface, PRectangle &rc) {
surface->MoveTo(x-3, ymid);
surface->LineTo(x-3, ymid+2);
}
} else if (style == INDIC_DIAGONAL) {
int x = rc.left;
while (x < rc.right) {
surface->MoveTo(x, rc.top+2);
int endX = x+3;
int endY = rc.top - 1;
if (endX > rc.right) {
endY += endX - rc.right;
endX = rc.right;
}
surface->LineTo(endX, endY);
x += 4;
}
} else if (style == INDIC_STRIKE) {
surface->MoveTo(rc.left, rc.top - 4);
surface->LineTo(rc.right, rc.top - 4);
} else { // Either INDIC_PLAIN or unknown
surface->MoveTo(rc.left, ymid);
surface->LineTo(rc.right, ymid);

View File

@@ -61,51 +61,59 @@ UINT KeyMap::Find(int key, int modifiers) {
}
KeyToCommand KeyMap::MapDefault[] = {
VK_DOWN, SCI_NORM, SCI_LINEDOWN,
VK_DOWN, SCI_SHIFT, SCI_LINEDOWNEXTEND,
VK_UP, SCI_NORM, SCI_LINEUP,
VK_UP, SCI_SHIFT, SCI_LINEUPEXTEND,
VK_LEFT, SCI_NORM, SCI_CHARLEFT,
VK_LEFT, SCI_SHIFT, SCI_CHARLEFTEXTEND,
VK_LEFT, SCI_CTRL, SCI_WORDLEFT,
VK_LEFT, SCI_CSHIFT, SCI_WORDLEFTEXTEND,
VK_RIGHT, SCI_NORM, SCI_CHARRIGHT,
VK_RIGHT, SCI_SHIFT, SCI_CHARRIGHTEXTEND,
VK_RIGHT, SCI_CTRL, SCI_WORDRIGHT,
VK_RIGHT, SCI_CSHIFT, SCI_WORDRIGHTEXTEND,
VK_HOME, SCI_NORM, SCI_VCHOME,
VK_HOME, SCI_SHIFT, SCI_VCHOMEEXTEND,
VK_HOME, SCI_CTRL, SCI_DOCUMENTSTART,
VK_HOME, SCI_CSHIFT, SCI_DOCUMENTSTARTEXTEND,
VK_END, SCI_NORM, SCI_LINEEND,
VK_END, SCI_SHIFT, SCI_LINEENDEXTEND,
VK_END, SCI_CTRL, SCI_DOCUMENTEND,
VK_END, SCI_CSHIFT, SCI_DOCUMENTENDEXTEND,
VK_PRIOR, SCI_NORM, SCI_PAGEUP,
VK_PRIOR, SCI_SHIFT, SCI_PAGEUPEXTEND,
VK_NEXT, SCI_NORM, SCI_PAGEDOWN,
VK_NEXT, SCI_SHIFT, SCI_PAGEDOWNEXTEND,
VK_DELETE, SCI_NORM, WM_CLEAR,
VK_DELETE, SCI_SHIFT, WM_CUT,
VK_DELETE, SCI_CTRL, SCI_DELWORDRIGHT,
VK_INSERT, SCI_NORM, SCI_EDITTOGGLEOVERTYPE,
VK_INSERT, SCI_SHIFT, WM_PASTE,
VK_INSERT, SCI_CTRL, WM_COPY,
VK_ESCAPE, SCI_NORM, SCI_CANCEL,
VK_BACK, SCI_NORM, SCI_DELETEBACK,
VK_BACK, SCI_CTRL, SCI_DELWORDLEFT,
'Z', SCI_CTRL, WM_UNDO,
'Y', SCI_CTRL, SCI_REDO,
'X', SCI_CTRL, WM_CUT,
'C', SCI_CTRL, WM_COPY,
'V', SCI_CTRL, WM_PASTE,
'A', SCI_CTRL, SCI_SELECTALL,
VK_TAB, SCI_NORM, SCI_TAB,
VK_TAB, SCI_SHIFT, SCI_BACKTAB,
VK_RETURN, SCI_NORM, SCI_NEWLINE,
'L', SCI_CTRL, SCI_FORMFEED,
VK_ADD, SCI_CTRL, SCI_ZOOMIN,
VK_SUBTRACT, SCI_CTRL, SCI_ZOOMOUT,
0,0,0,
{VK_DOWN, SCI_NORM, SCI_LINEDOWN},
{VK_DOWN, SCI_SHIFT, SCI_LINEDOWNEXTEND},
{VK_DOWN, SCI_CTRL, SCI_LINESCROLLDOWN},
{VK_UP, SCI_NORM, SCI_LINEUP},
{VK_UP, SCI_SHIFT, SCI_LINEUPEXTEND},
{VK_UP, SCI_CTRL, SCI_LINESCROLLUP},
{VK_LEFT, SCI_NORM, SCI_CHARLEFT},
{VK_LEFT, SCI_SHIFT, SCI_CHARLEFTEXTEND},
{VK_LEFT, SCI_CTRL, SCI_WORDLEFT},
{VK_LEFT, SCI_CSHIFT, SCI_WORDLEFTEXTEND},
{VK_RIGHT, SCI_NORM, SCI_CHARRIGHT},
{VK_RIGHT, SCI_SHIFT, SCI_CHARRIGHTEXTEND},
{VK_RIGHT, SCI_CTRL, SCI_WORDRIGHT},
{VK_RIGHT, SCI_CSHIFT, SCI_WORDRIGHTEXTEND},
{VK_HOME, SCI_NORM, SCI_VCHOME},
{VK_HOME, SCI_SHIFT, SCI_VCHOMEEXTEND},
{VK_HOME, SCI_CTRL, SCI_DOCUMENTSTART},
{VK_HOME, SCI_CSHIFT, SCI_DOCUMENTSTARTEXTEND},
{VK_END, SCI_NORM, SCI_LINEEND},
{VK_END, SCI_SHIFT, SCI_LINEENDEXTEND},
{VK_END, SCI_CTRL, SCI_DOCUMENTEND},
{VK_END, SCI_CSHIFT, SCI_DOCUMENTENDEXTEND},
{VK_PRIOR, SCI_NORM, SCI_PAGEUP},
{VK_PRIOR, SCI_SHIFT, SCI_PAGEUPEXTEND},
{VK_NEXT, SCI_NORM, SCI_PAGEDOWN},
{VK_NEXT, SCI_SHIFT, SCI_PAGEDOWNEXTEND},
{VK_DELETE, SCI_NORM, WM_CLEAR},
{VK_DELETE, SCI_SHIFT, WM_CUT},
{VK_DELETE, SCI_CTRL, SCI_DELWORDRIGHT},
{VK_INSERT, SCI_NORM, SCI_EDITTOGGLEOVERTYPE},
{VK_INSERT, SCI_SHIFT, WM_PASTE},
{VK_INSERT, SCI_CTRL, WM_COPY},
{VK_ESCAPE, SCI_NORM, SCI_CANCEL},
{VK_BACK, SCI_NORM, SCI_DELETEBACK},
{VK_BACK, SCI_CTRL, SCI_DELWORDLEFT},
{'Z', SCI_CTRL, WM_UNDO},
{'Y', SCI_CTRL, SCI_REDO},
{'X', SCI_CTRL, WM_CUT},
{'C', SCI_CTRL, WM_COPY},
{'V', SCI_CTRL, WM_PASTE},
{'A', SCI_CTRL, SCI_SELECTALL},
{VK_TAB, SCI_NORM, SCI_TAB},
{VK_TAB, SCI_SHIFT, SCI_BACKTAB},
{VK_RETURN, SCI_NORM, SCI_NEWLINE},
{VK_ADD, SCI_CTRL, SCI_ZOOMIN},
{VK_SUBTRACT, SCI_CTRL, SCI_ZOOMOUT},
{VK_DIVIDE, SCI_CTRL, SCI_SETZOOM},
//'L', SCI_CTRL, SCI_FORMFEED,
{'L', SCI_CTRL, SCI_LINECUT},
{'L', SCI_CSHIFT, SCI_LINEDELETE},
{'T', SCI_CTRL, SCI_LINETRANSPOSE},
{'U', SCI_CTRL, SCI_LOWERCASE},
{'U', SCI_CSHIFT, SCI_UPPERCASE},
{0,0,0},
};

View File

@@ -11,6 +11,7 @@
#define SCI_CTRL LEFT_CTRL_PRESSED
#define SCI_ALT LEFT_ALT_PRESSED
#define SCI_CSHIFT (SCI_CTRL | SCI_SHIFT)
#define SCI_ASHIFT (SCI_ALT | SCI_SHIFT)
class KeyToCommand {
public:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,258 @@
// SciTE - Scintilla based Text Editor
// LexCPP.cxx - lexer for C++, C, Java, and Javascript
// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>
#include "Platform.h"
#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"
static bool classifyWordCpp(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
char s[100];
bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
bool wordIsUUID = false;
for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
s[i] = styler[start + i];
s[i + 1] = '\0';
}
char chAttr = SCE_C_IDENTIFIER;
if (wordIsNumber)
chAttr = SCE_C_NUMBER;
else {
if (keywords.InList(s)) {
chAttr = SCE_C_WORD;
wordIsUUID = strcmp(s, "uuid") == 0;
}
}
styler.ColourTo(end, chAttr);
return wordIsUUID;
}
static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
Accessor &styler) {
WordList &keywords = *keywordlists[0];
styler.StartAt(startPos);
bool fold = styler.GetPropertyInt("fold");
int lineCurrent = styler.GetLine(startPos);
int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
int levelCurrent = levelPrev;
int state = initStyle;
if (state == SCE_C_STRINGEOL) // Does not leak onto next line
state = SCE_C_DEFAULT;
char chPrev = ' ';
char chNext = styler[startPos];
unsigned int lengthDoc = startPos + length;
int visChars = 0;
styler.StartSegment(startPos);
bool lastWordWasUUID = false;
for (unsigned int i = startPos; i < lengthDoc; i++) {
char ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
// End of line
if (state == SCE_C_STRINGEOL) {
styler.ColourTo(i, state);
state = SCE_C_DEFAULT;
}
if (fold) {
int lev = levelPrev;
if (visChars == 0)
lev |= SC_FOLDLEVELWHITEFLAG;
if ((levelCurrent > levelPrev) && (visChars > 0))
lev |= SC_FOLDLEVELHEADERFLAG;
styler.SetLevel(lineCurrent, lev);
lineCurrent++;
visChars = 0;
levelPrev = levelCurrent;
}
}
if (!isspace(ch))
visChars++;
if (styler.IsLeadByte(ch)) {
chNext = styler.SafeGetCharAt(i + 2);
chPrev = ' ';
i += 1;
continue;
}
if (state == SCE_C_DEFAULT) {
if (iswordstart(ch)) {
styler.ColourTo(i-1, state);
if (lastWordWasUUID) {
state = SCE_C_UUID;
lastWordWasUUID = false;
} else {
state = SCE_C_WORD;
}
} else if (ch == '/' && chNext == '*') {
styler.ColourTo(i-1, state);
if (styler.SafeGetCharAt(i + 2) == '*')
state = SCE_C_COMMENTDOC;
else
state = SCE_C_COMMENT;
} else if (ch == '/' && chNext == '/') {
styler.ColourTo(i-1, state);
state = SCE_C_COMMENTLINE;
} else if (ch == '\"') {
styler.ColourTo(i-1, state);
state = SCE_C_STRING;
} else if (ch == '\'') {
styler.ColourTo(i-1, state);
state = SCE_C_CHARACTER;
} else if (ch == '#') {
styler.ColourTo(i-1, state);
state = SCE_C_PREPROCESSOR;
} else if (isoperator(ch)) {
styler.ColourTo(i-1, state);
styler.ColourTo(i, SCE_C_OPERATOR);
if ((ch == '{') || (ch == '}')) {
levelCurrent += (ch == '{') ? 1 : -1;
}
}
} else if (state == SCE_C_WORD) {
if (!iswordchar(ch)) {
lastWordWasUUID = classifyWordCpp(styler.GetStartSegment(), i - 1, keywords, styler);
state = SCE_C_DEFAULT;
if (ch == '/' && chNext == '*') {
if (styler.SafeGetCharAt(i + 2) == '*')
state = SCE_C_COMMENTDOC;
else
state = SCE_C_COMMENT;
} else if (ch == '/' && chNext == '/') {
state = SCE_C_COMMENTLINE;
} else if (ch == '\"') {
state = SCE_C_STRING;
} else if (ch == '\'') {
state = SCE_C_CHARACTER;
} else if (ch == '#') {
state = SCE_C_PREPROCESSOR;
} else if (isoperator(ch)) {
styler.ColourTo(i, SCE_C_OPERATOR);
if ((ch == '{') || (ch == '}')) {
levelCurrent += (ch == '{') ? 1 : -1;
}
}
}
} else {
if (state == SCE_C_PREPROCESSOR) {
if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) {
styler.ColourTo(i-1, state);
state = SCE_C_DEFAULT;
}
} else if (state == SCE_C_COMMENT) {
if (ch == '/' && chPrev == '*') {
if (((i > styler.GetStartSegment() + 2) || (
(initStyle == SCE_C_COMMENT) &&
(styler.GetStartSegment() == static_cast<unsigned int>(startPos))))) {
styler.ColourTo(i, state);
state = SCE_C_DEFAULT;
}
}
} else if (state == SCE_C_COMMENTDOC) {
if (ch == '/' && chPrev == '*') {
if (((i > styler.GetStartSegment() + 2) || (
(initStyle == SCE_C_COMMENTDOC) &&
(styler.GetStartSegment() == static_cast<unsigned int>(startPos))))) {
styler.ColourTo(i, state);
state = SCE_C_DEFAULT;
}
}
} else if (state == SCE_C_COMMENTLINE) {
if (ch == '\r' || ch == '\n') {
styler.ColourTo(i-1, state);
state = SCE_C_DEFAULT;
}
} else if (state == SCE_C_STRING) {
if (ch == '\\') {
if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
i++;
ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
}
} else if (ch == '\"') {
styler.ColourTo(i, state);
state = SCE_C_DEFAULT;
i++;
ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
} else if (chNext == '\r' || chNext == '\n') {
styler.ColourTo(i-1, SCE_C_STRINGEOL);
state = SCE_C_STRINGEOL;
}
} else if (state == SCE_C_CHARACTER) {
if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
styler.ColourTo(i-1, SCE_C_STRINGEOL);
state = SCE_C_STRINGEOL;
} else if (ch == '\\') {
if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
i++;
ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
}
} else if (ch == '\'') {
styler.ColourTo(i, state);
state = SCE_C_DEFAULT;
i++;
ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
}
} else if (state == SCE_C_UUID) {
if (ch == '\r' || ch == '\n' || ch == ')') {
styler.ColourTo(i-1, state);
state = SCE_C_DEFAULT;
}
}
if (state == SCE_C_DEFAULT) { // One of the above succeeded
if (ch == '/' && chNext == '*') {
if (styler.SafeGetCharAt(i + 2) == '*')
state = SCE_C_COMMENTDOC;
else
state = SCE_C_COMMENT;
} else if (ch == '/' && chNext == '/') {
state = SCE_C_COMMENTLINE;
} else if (ch == '\"') {
state = SCE_C_STRING;
} else if (ch == '\'') {
state = SCE_C_CHARACTER;
} else if (ch == '#') {
state = SCE_C_PREPROCESSOR;
} else if (iswordstart(ch)) {
state = SCE_C_WORD;
} else if (isoperator(ch)) {
styler.ColourTo(i, SCE_C_OPERATOR);
if ((ch == '{') || (ch == '}')) {
levelCurrent += (ch == '{') ? 1 : -1;
}
}
}
}
chPrev = ch;
}
styler.ColourTo(lengthDoc - 1, state);
// Fill in the real level of the next line, keeping the current flags as they will be filled in later
if (fold) {
int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
//styler.SetLevel(lineCurrent, levelCurrent | flagsNext);
styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}
}
LexerModule lmCPP(SCLEX_CPP, ColouriseCppDoc);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,304 @@
// SciTE - Scintilla based Text Editor
// LexOthers.cxx - lexers for properties files, batch files, make files and error lists
// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>
#include "Platform.h"
#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"
static void ColouriseBatchLine(char *lineBuffer, int endLine, Accessor &styler) {
if (0 == strncmp(lineBuffer, "REM", 3)) {
styler.ColourTo(endLine, 1);
} else if (0 == strncmp(lineBuffer, "rem", 3)) {
styler.ColourTo(endLine, 1);
} else if (0 == strncmp(lineBuffer, "SET", 3)) {
styler.ColourTo(endLine, 2);
} else if (0 == strncmp(lineBuffer, "set", 3)) {
styler.ColourTo(endLine, 2);
} else if (lineBuffer[0] == ':') {
styler.ColourTo(endLine, 3);
} else {
styler.ColourTo(endLine, 0);
}
}
static void ColouriseBatchDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
char lineBuffer[1024];
styler.StartAt(startPos);
styler.StartSegment(startPos);
unsigned int linePos = 0;
for (unsigned int i = startPos; i < startPos + length; i++) {
lineBuffer[linePos++] = styler[i];
if (styler[i] == '\r' || styler[i] == '\n' || (linePos >= sizeof(lineBuffer) - 1)) {
ColouriseBatchLine(lineBuffer, i, styler);
linePos = 0;
}
}
if (linePos > 0)
ColouriseBatchLine(lineBuffer, startPos + length, styler);
}
static void ColourisePropsLine(char *lineBuffer, int lengthLine, int startLine, int endPos, Accessor &styler) {
int i = 0;
while (isspace(lineBuffer[i]) && (i < lengthLine)) // Skip initial spaces
i++;
if (lineBuffer[i] == '#' || lineBuffer[i] == '!' || lineBuffer[i] == ';') {
styler.ColourTo(endPos, 1);
} else if (lineBuffer[i] == '[') {
styler.ColourTo(endPos, 2);
} else if (lineBuffer[i] == '@') {
styler.ColourTo(startLine+i, 4);
if (lineBuffer[++i] == '=')
styler.ColourTo(startLine+i, 3);
styler.ColourTo(endPos, 0);
} else {
while (lineBuffer[i] != '=' && (i < lengthLine)) // Search the '=' character
i++;
if (lineBuffer[i] == '=') {
styler.ColourTo(startLine+i-1, 0);
styler.ColourTo(startLine+i, 3);
styler.ColourTo(endPos, 0);
} else {
styler.ColourTo(endPos, 0);
}
}
}
static void ColourisePropsDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
char lineBuffer[1024];
styler.StartAt(startPos);
styler.StartSegment(startPos);
unsigned int linePos = 0;
int startLine = startPos;
for (unsigned int i = startPos; i <= startPos + length; i++) {
lineBuffer[linePos++] = styler[i];
if ((styler[i] == '\r' && styler.SafeGetCharAt(i+1) != '\n') ||
styler[i] == '\n' ||
(linePos >= sizeof(lineBuffer) - 1)) {
lineBuffer[linePos] = '\0';
ColourisePropsLine(lineBuffer, linePos, startLine, i, styler);
linePos = 0;
startLine = i+1;
}
}
if (linePos > 0)
ColourisePropsLine(lineBuffer, linePos, startLine, startPos + length, styler);
}
static void ColouriseMakeLine(char *lineBuffer, int lengthLine, int endPos, Accessor &styler) {
int i = 0;
while (isspace(lineBuffer[i]) && (i < lengthLine))
i++;
if (lineBuffer[i] == '#' || lineBuffer[i] == '!') {
styler.ColourTo(endPos, 1);
} else {
styler.ColourTo(endPos, 0);
}
}
static void ColouriseMakeDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
char lineBuffer[1024];
styler.StartAt(startPos);
styler.StartSegment(startPos);
unsigned int linePos = 0;
for (unsigned int i = startPos; i <= startPos + length; i++) {
lineBuffer[linePos++] = styler[i];
if (styler[i] == '\r' || styler[i] == '\n' || (linePos >= sizeof(lineBuffer) - 1)) {
ColouriseMakeLine(lineBuffer, linePos, i, styler);
linePos = 0;
}
}
if (linePos > 0)
ColouriseMakeLine(lineBuffer, linePos, startPos + length, styler);
}
static void ColouriseErrorListLine(char *lineBuffer, int lengthLine, int endPos, Accessor &styler) {
if (lineBuffer[0] == '>') {
// Command or return status
styler.ColourTo(endPos, 4);
} else if (strstr(lineBuffer, "File \"") && strstr(lineBuffer, ", line ")) {
styler.ColourTo(endPos, 1);
} else if (0 == strncmp(lineBuffer, "Error ", strlen("Error "))) {
// Borland error message
styler.ColourTo(endPos, 5);
} else if (0 == strncmp(lineBuffer, "Warning ", strlen("Warning "))) {
// Borland warning message
styler.ColourTo(endPos, 5);
} else {
// Look for <filename>:<line>:message
// Look for <filename>(line)message
// Look for <filename>(line,pos)message
int state = 0;
for (int i = 0; i < lengthLine; i++) {
if (state == 0 && lineBuffer[i] == ':' && isdigit(lineBuffer[i + 1])) {
state = 1;
} else if (state == 0 && lineBuffer[i] == '(') {
state = 10;
} else if (state == 1 && isdigit(lineBuffer[i])) {
state = 2;
} else if (state == 2 && lineBuffer[i] == ':') {
state = 3;
break;
} else if (state == 2 && !isdigit(lineBuffer[i])) {
state = 99;
} else if (state == 10 && isdigit(lineBuffer[i])) {
state = 11;
} else if (state == 11 && lineBuffer[i] == ',') {
state = 14;
} else if (state == 11 && lineBuffer[i] == ')') {
state = 12;
} else if (state == 12 && lineBuffer[i] == ':') {
state = 13;
} else if (state == 14 && lineBuffer[i] == ')') {
state = 15;
break;
} else if (((state == 11) || (state == 14)) && !((lineBuffer[i] == ' ') || isdigit(lineBuffer[i]))) {
state = 99;
}
}
if (state == 3) {
styler.ColourTo(endPos, 2);
} else if ((state == 13) || (state == 14) || (state == 15)) {
styler.ColourTo(endPos, 3);
} else {
styler.ColourTo(endPos, 0);
}
}
}
static void ColouriseErrorListDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
char lineBuffer[1024];
styler.StartAt(startPos);
styler.StartSegment(startPos);
unsigned int linePos = 0;
for (unsigned int i = startPos; i <= startPos + length; i++) {
lineBuffer[linePos++] = styler[i];
if (styler[i] == '\r' || styler[i] == '\n' || (linePos >= sizeof(lineBuffer) - 1)) {
ColouriseErrorListLine(lineBuffer, linePos, i, styler);
linePos = 0;
}
}
if (linePos > 0)
ColouriseErrorListLine(lineBuffer, linePos, startPos + length, styler);
}
static int isSpecial(char s) {
return (s == '\\') || (s == ',') || (s == ';') || (s == '\'') || (s == ' ') ||
(s == '\"') || (s == '`') || (s == '^') || (s == '~');
}
static int isTag(int start, Accessor &styler) {
char s[6];
unsigned int i = 0, e=1;
while (i < 5 && e) {
s[i] = styler[start + i];
i++;
e = styler[start + i] != '{';
}
s[i] = '\0';
return (strcmp(s, "begin") == 0) || (strcmp(s, "end") == 0);
}
static void ColouriseLatexDoc(unsigned int startPos, int length, int initStyle,
WordList *[], Accessor &styler) {
styler.StartAt(startPos);
int state = initStyle;
char chNext = styler[startPos];
styler.StartSegment(startPos);
int lengthDoc = startPos + length;
for (int i = startPos; i < lengthDoc; i++) {
char ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
if (styler.IsLeadByte(ch)) {
chNext = styler.SafeGetCharAt(i + 2);
i++;
continue;
}
switch(state) {
case SCE_L_DEFAULT :
switch(ch) {
case '\\' :
styler.ColourTo(i - 1, state);
if (isSpecial(styler[i + 1])) {
styler.ColourTo(i + 1, SCE_L_COMMAND);
i++;
chNext = styler.SafeGetCharAt(i + 1);
}
else {
if (isTag(i+1, styler))
state = SCE_L_TAG;
else
state = SCE_L_COMMAND;
}
break;
case '$' :
styler.ColourTo(i - 1, state);
state = SCE_L_MATH;
if (chNext == '$') {
i++;
chNext = styler.SafeGetCharAt(i + 1);
}
break;
case '%' :
styler.ColourTo(i - 1, state);
state = SCE_L_COMMENT;
break;
}
break;
case SCE_L_COMMAND :
if (chNext == '[' || chNext == '{' || chNext == '}' ||
chNext == ' ' || chNext == '\r' || chNext == '\n') {
styler.ColourTo(i, state);
state = SCE_L_DEFAULT;
i++;
chNext = styler.SafeGetCharAt(i + 1);
}
break;
case SCE_L_TAG :
if (ch == '}') {
styler.ColourTo(i, state);
state = SCE_L_DEFAULT;
}
break;
case SCE_L_MATH :
if (ch == '$') {
if (chNext == '$') {
i++;
chNext = styler.SafeGetCharAt(i + 1);
}
styler.ColourTo(i, state);
state = SCE_L_DEFAULT;
}
break;
case SCE_L_COMMENT :
if (ch == '\r' || ch == '\n') {
styler.ColourTo(i - 1, state);
state = SCE_L_DEFAULT;
}
}
}
styler.ColourTo(lengthDoc, state);
}
LexerModule lmProps(SCLEX_PROPERTIES, ColourisePropsDoc);
LexerModule lmErrorList(SCLEX_ERRORLIST, ColouriseErrorListDoc);
LexerModule lmMake(SCLEX_MAKEFILE, ColouriseMakeDoc);
LexerModule lmBatch(SCLEX_BATCH, ColouriseBatchDoc);
LexerModule lmLatex(SCLEX_LATEX, ColouriseLatexDoc);

View File

@@ -0,0 +1,480 @@
// SciTE - Scintilla based Text Editor
// LexPerl.cxx - lexer for subset of Perl
// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>
#include "Platform.h"
#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"
inline bool isPerlOperator(char ch) {
if (isalnum(ch))
return false;
// '.' left out as it is used to make up numbers
if (ch == '%' || ch == '^' || ch == '&' || ch == '*' || ch == '\\' ||
ch == '(' || ch == ')' || ch == '-' || ch == '+' ||
ch == '=' || ch == '|' || ch == '{' || ch == '}' ||
ch == '[' || ch == ']' || ch == ':' || ch == ';' ||
ch == '<' || ch == '>' || ch == ',' || ch == '/' ||
ch == '?' || ch == '!' || ch == '.' || ch == '~')
return true;
return false;
}
static int classifyWordPerl(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
char s[100];
bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
s[i] = styler[start + i];
s[i + 1] = '\0';
}
char chAttr = SCE_PL_IDENTIFIER;
if (wordIsNumber)
chAttr = SCE_PL_NUMBER;
else {
if (keywords.InList(s))
chAttr = SCE_PL_WORD;
}
styler.ColourTo(end, chAttr);
return chAttr;
}
static bool isEndVar(char ch) {
return !isalnum(ch) && ch != '#' && ch != '$' &&
ch != '_' && ch != '\'';
}
static bool isMatch(Accessor &styler, int lengthDoc, int pos, const char *val) {
if ((pos + static_cast<int>(strlen(val))) >= lengthDoc) {
return false;
}
while (*val) {
if (*val != styler[pos++]) {
return false;
}
val++;
}
return true;
}
static char opposite(char ch) {
if (ch == '(')
return ')';
if (ch == '[')
return ']';
if (ch == '{')
return '}';
if (ch == '<')
return '>';
return ch;
}
static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
WordList *keywordlists[], Accessor &styler) {
// Lexer for perl often has to backtrack to start of current style to determine
// which characters are being used as quotes, how deeply nested is the
// start position and what the termination string is for here documents
WordList &keywords = *keywordlists[0];
char sooked[100];
int quotes = 0;
char quoteDown = 'd';
char quoteUp = 'd';
int quoteRep = 1;
int sookedpos = 0;
bool preferRE = true;
sooked[sookedpos] = '\0';
int state = initStyle;
int lengthDoc = startPos + length;
// If in a long distance lexical state, seek to the beginning to find quote characters
if (state == SCE_PL_HERE || state == SCE_PL_REGEX ||
state == SCE_PL_REGSUBST || state == SCE_PL_LONGQUOTE) {
while ((startPos > 1) && (styler.StyleAt(startPos - 1) == state)) {
startPos--;
}
state = SCE_PL_DEFAULT;
}
styler.StartAt(startPos);
char chPrev = ' ';
char chNext = styler[startPos];
styler.StartSegment(startPos);
for (int i = startPos; i < lengthDoc; i++) {
char ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
char chNext2 = styler.SafeGetCharAt(i + 2);
if (styler.IsLeadByte(ch)) {
chNext = styler.SafeGetCharAt(i + 2);
chPrev = ' ';
i += 1;
continue;
}
if (state == SCE_PL_DEFAULT) {
if (iswordstart(ch)) {
styler.ColourTo(i - 1, state);
if (ch == 's' && !isalnum(chNext)) {
state = SCE_PL_REGSUBST;
quotes = 0;
quoteUp = '\0';
quoteDown = '\0';
quoteRep = 2;
} else if (ch == 'm' && !isalnum(chNext)) {
state = SCE_PL_REGEX;
quotes = 0;
quoteUp = '\0';
quoteDown = '\0';
quoteRep = 1;
} else if (ch == 't' && chNext == 'r' && !isalnum(chNext2)) {
state = SCE_PL_REGSUBST;
quotes = 0;
quoteUp = '\0';
quoteDown = '\0';
quoteRep = 2;
i++;
chNext = chNext2;
} else if (ch == 'q' && (chNext == 'q' || chNext == 'r' || chNext == 'w' || chNext == 'x') && !isalnum(chNext2)) {
state = SCE_PL_LONGQUOTE;
i++;
chNext = chNext2;
quotes = 0;
quoteUp = '\0';
quoteDown = '\0';
quoteRep = 1;
} else {
state = SCE_PL_WORD;
preferRE = false;
}
} else if (ch == '#') {
styler.ColourTo(i - 1, state);
state = SCE_PL_COMMENTLINE;
} else if (ch == '\"') {
styler.ColourTo(i - 1, state);
state = SCE_PL_STRING;
} else if (ch == '\'') {
if (chPrev == '&') {
// Archaic call
styler.ColourTo(i, state);
} else {
styler.ColourTo(i - 1, state);
state = SCE_PL_CHARACTER;
}
} else if (ch == '`') {
styler.ColourTo(i - 1, state);
state = SCE_PL_BACKTICKS;
} else if (ch == '$') {
preferRE = false;
styler.ColourTo(i - 1, state);
if (isalnum(chNext) || chNext == '#' || chNext == '$' || chNext == '_') {
state = SCE_PL_SCALAR;
} else if (chNext != '{' && chNext != '[') {
styler.ColourTo(i, SCE_PL_SCALAR);
i++;
ch = ' ';
chNext = ' ';
} else {
styler.ColourTo(i, SCE_PL_SCALAR);
}
} else if (ch == '@') {
preferRE = false;
styler.ColourTo(i - 1, state);
if (isalpha(chNext) || chNext == '#' || chNext == '$' || chNext == '_') {
state = SCE_PL_ARRAY;
} else if (chNext != '{' && chNext != '[') {
styler.ColourTo(i, SCE_PL_ARRAY);
i++;
ch = ' ';
} else {
styler.ColourTo(i, SCE_PL_ARRAY);
}
} else if (ch == '%') {
preferRE = false;
styler.ColourTo(i - 1, state);
if (isalpha(chNext) || chNext == '#' || chNext == '$' || chNext == '_') {
state = SCE_PL_HASH;
} else if (chNext != '{' && chNext != '[') {
styler.ColourTo(i, SCE_PL_HASH);
i++;
ch = ' ';
} else {
styler.ColourTo(i, SCE_PL_HASH);
}
} else if (ch == '*') {
styler.ColourTo(i - 1, state);
state = SCE_PL_SYMBOLTABLE;
} else if (ch == '/' && preferRE) {
styler.ColourTo(i - 1, state);
state = SCE_PL_REGEX;
quoteUp = '/';
quoteDown = '/';
quotes = 1;
quoteRep = 1;
} else if (ch == '<' && chNext == '<') {
styler.ColourTo(i - 1, state);
state = SCE_PL_HERE;
i++;
ch = chNext;
chNext = chNext2;
quotes = 0;
sookedpos = 0;
sooked[sookedpos] = '\0';
} else if (ch == '=' && isalpha(chNext)) {
styler.ColourTo(i - 1, state);
state = SCE_PL_POD;
quotes = 0;
sookedpos = 0;
sooked[sookedpos] = '\0';
} else if (isPerlOperator(ch)) {
if (ch == ')' || ch == ']')
preferRE = false;
else
preferRE = true;
styler.ColourTo(i - 1, state);
styler.ColourTo(i, SCE_PL_OPERATOR);
}
} else if (state == SCE_PL_WORD) {
if (!iswordchar(ch) && ch != '\'') { // Archaic Perl has quotes inside names
if (isMatch(styler, lengthDoc, styler.GetStartSegment(), "__DATA__")) {
styler.ColourTo(i, SCE_PL_DATASECTION);
state = SCE_PL_DATASECTION;
} else if (isMatch(styler, lengthDoc, styler.GetStartSegment(), "__END__")) {
styler.ColourTo(i, SCE_PL_DATASECTION);
state = SCE_PL_DATASECTION;
} else {
if (classifyWordPerl(styler.GetStartSegment(), i - 1, keywords, styler) == SCE_PL_WORD)
preferRE = true;
state = SCE_PL_DEFAULT;
if (ch == '#') {
state = SCE_PL_COMMENTLINE;
} else if (ch == '\"') {
state = SCE_PL_STRING;
} else if (ch == '\'') {
state = SCE_PL_CHARACTER;
} else if (ch == '<' && chNext == '<') {
state = SCE_PL_HERE;
quotes = 0;
sookedpos = 0;
sooked[sookedpos] = '\0';
} else if (isPerlOperator(ch)) {
if (ch == ')' || ch == ']')
preferRE = false;
else
preferRE = true;
styler.ColourTo(i, SCE_PL_OPERATOR);
state = SCE_PL_DEFAULT;
}
}
}
} else {
if (state == SCE_PL_COMMENTLINE) {
if (ch == '\r' || ch == '\n') {
styler.ColourTo(i - 1, state);
state = SCE_PL_DEFAULT;
}
} else if (state == SCE_PL_HERE) {
if (isalnum(ch) && quotes < 2) {
sooked[sookedpos++] = ch;
sooked[sookedpos] = '\0';
if (quotes == 0)
quotes = 1;
} else {
quotes++;
}
if (quotes > 1 && isMatch(styler, lengthDoc, i, sooked) && (chPrev == '\n' || chPrev == '\r') ) {
styler.ColourTo(i + sookedpos - 1, SCE_PL_HERE);
i += sookedpos;
chNext = styler.SafeGetCharAt(i);
if (chNext == '\n' || chNext == '\r') {
state = SCE_PL_DEFAULT;
}
chNext = ' ';
}
} else if (state == SCE_PL_STRING) {
if (ch == '\\') {
if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
i++;
ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
}
} else if (ch == '\"') {
styler.ColourTo(i, state);
state = SCE_PL_DEFAULT;
i++;
ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
}
} else if (state == SCE_PL_CHARACTER) {
if (ch == '\\') {
if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
i++;
ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
}
} else if (ch == '\'') {
styler.ColourTo(i, state);
state = SCE_PL_DEFAULT;
i++;
ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
}
} else if (state == SCE_PL_BACKTICKS) {
if (ch == '`') {
styler.ColourTo(i, state);
state = SCE_PL_DEFAULT;
i++;
ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
}
} else if (state == SCE_PL_POD) {
if (ch == '=') {
if (isMatch(styler, lengthDoc, i, "=cut")) {
styler.ColourTo(i - 1 + 4, state);
i += 4;
state = SCE_PL_DEFAULT;
chNext = ' ';
ch = ' ';
}
}
} else if (state == SCE_PL_SCALAR) {
if (isEndVar(ch)) {
styler.ColourTo(i - 1, state);
state = SCE_PL_DEFAULT;
}
} else if (state == SCE_PL_ARRAY) {
if (isEndVar(ch)) {
styler.ColourTo(i - 1, state);
state = SCE_PL_DEFAULT;
}
} else if (state == SCE_PL_HASH) {
if (isEndVar(ch)) {
styler.ColourTo(i - 1, state);
state = SCE_PL_DEFAULT;
}
} else if (state == SCE_PL_SYMBOLTABLE) {
if (isEndVar(ch)) {
styler.ColourTo(i - 1, state);
state = SCE_PL_DEFAULT;
}
} else if (state == SCE_PL_REF) {
if (isEndVar(ch)) {
styler.ColourTo(i - 1, state);
state = SCE_PL_DEFAULT;
}
} else if (state == SCE_PL_REGEX) {
if (!quoteUp && !isspace(ch)) {
quoteUp = ch;
quoteDown = opposite(ch);
quotes++;
} else {
if (ch == quoteDown && chPrev != '\\') {
quotes--;
if (quotes == 0) {
quoteRep--;
if (quoteUp == quoteDown) {
quotes++;
}
}
if (!isalpha(chNext)) {
if (quoteRep <= 0) {
styler.ColourTo(i, state);
state = SCE_PL_DEFAULT;
ch = ' ';
}
}
} else if (ch == quoteUp && chPrev != '\\') {
quotes++;
} else if (!isalpha(chNext)) {
if (quoteRep <= 0) {
styler.ColourTo(i, state);
state = SCE_PL_DEFAULT;
ch = ' ';
}
}
}
} else if (state == SCE_PL_REGSUBST) {
if (!quoteUp && !isspace(ch)) {
quoteUp = ch;
quoteDown = opposite(ch);
quotes++;
} else {
if (ch == quoteDown && chPrev != '\\') {
quotes--;
if (quotes == 0) {
quoteRep--;
}
if (!isalpha(chNext)) {
if (quoteRep <= 0) {
styler.ColourTo(i, state);
state = SCE_PL_DEFAULT;
ch = ' ';
}
}
if (quoteUp == quoteDown) {
quotes++;
}
} else if (ch == quoteUp && chPrev != '\\') {
quotes++;
} else if (!isalpha(chNext)) {
if (quoteRep <= 0) {
styler.ColourTo(i, state);
state = SCE_PL_DEFAULT;
ch = ' ';
}
}
}
} else if (state == SCE_PL_LONGQUOTE) {
if (!quoteDown && !isspace(ch)) {
quoteUp = ch;
quoteDown = opposite(quoteUp);
quotes++;
} else if (ch == quoteDown) {
quotes--;
if (quotes == 0) {
quoteRep--;
if (quoteRep <= 0) {
styler.ColourTo(i, state);
state = SCE_PL_DEFAULT;
ch = ' ';
}
if (quoteUp == quoteDown) {
quotes++;
}
}
} else if (ch == quoteUp) {
quotes++;
}
}
if (state == SCE_PL_DEFAULT) { // One of the above succeeded
if (ch == '#') {
state = SCE_PL_COMMENTLINE;
} else if (ch == '\"') {
state = SCE_PL_STRING;
} else if (ch == '\'') {
state = SCE_PL_CHARACTER;
} else if (iswordstart(ch)) {
state = SCE_PL_WORD;
preferRE = false;
} else if (isoperator(ch)) {
styler.ColourTo(i, SCE_PL_OPERATOR);
}
}
}
chPrev = ch;
}
styler.ColourTo(lengthDoc, state);
}
LexerModule lmPerl(SCLEX_PERL, ColourisePerlDoc);

View File

@@ -0,0 +1,274 @@
// SciTE - Scintilla based Text Editor
// LexPython.cxx - lexer for Python
// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>
#include "Platform.h"
#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"
static void ClassifyWordPy(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord) {
char s[100];
bool wordIsNumber = isdigit(styler[start]);
for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
s[i] = styler[start + i];
s[i + 1] = '\0';
}
char chAttr = SCE_P_IDENTIFIER;
if (0 == strcmp(prevWord, "class"))
chAttr = SCE_P_CLASSNAME;
else if (0 == strcmp(prevWord, "def"))
chAttr = SCE_P_DEFNAME;
else if (wordIsNumber)
chAttr = SCE_P_NUMBER;
else if (keywords.InList(s))
chAttr = SCE_P_WORD;
styler.ColourTo(end, chAttr);
strcpy(prevWord, s);
}
static bool IsPyComment(Accessor &styler, int pos, int len) {
return len>0 && styler[pos]=='#';
}
static void ColourisePyDoc(unsigned int startPos, int length, int initStyle,
WordList *keywordlists[], Accessor &styler) {
int lengthDoc = startPos + length;
// Backtrack to previous line in case need to fix its fold status or tab whinging
int lineCurrent = styler.GetLine(startPos);
if (startPos > 0) {
if (lineCurrent > 0) {
lineCurrent--;
startPos = styler.LineStart(lineCurrent);
if (startPos == 0)
initStyle = SCE_P_DEFAULT;
else
initStyle = styler.StyleAt(startPos-1);
}
}
// Python uses a different mask because bad indentation is marked by oring with 32
styler.StartAt(startPos, 127);
WordList &keywords = *keywordlists[0];
bool fold = styler.GetPropertyInt("fold");
int whingeLevel = styler.GetPropertyInt("tab.timmy.whinge.level");
char prevWord[200];
prevWord[0] = '\0';
if (length == 0)
return ;
int spaceFlags = 0;
int state = initStyle & 31;
int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsPyComment);
if ((state == SCE_P_TRIPLE) || (state == SCE_P_TRIPLEDOUBLE))
indentCurrent |= SC_FOLDLEVELWHITEFLAG;
char chPrev = ' ';
char chPrev2 = ' ';
char chNext = styler[startPos];
styler.StartSegment(startPos);
bool atStartLine = true;
for (int i = startPos; i < lengthDoc; i++) {
if (atStartLine) {
char chBad = static_cast<char>(64);
char chGood = static_cast<char>(0);
char chFlags = chGood;
if (whingeLevel == 1) {
chFlags = (spaceFlags & wsInconsistent) ? chBad : chGood;
} else if (whingeLevel == 2) {
chFlags = (spaceFlags & wsSpaceTab) ? chBad : chGood;
} else if (whingeLevel == 3) {
chFlags = (spaceFlags & wsSpace) ? chBad : chGood;
} else if (whingeLevel == 4) {
chFlags = (spaceFlags & wsTab) ? chBad : chGood;
}
styler.SetFlags(chFlags, static_cast<char>(state));
atStartLine = false;
}
char ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
char chNext2 = styler.SafeGetCharAt(i + 2);
if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) {
if ((state == SCE_P_DEFAULT) || (state == SCE_P_TRIPLE) || (state == SCE_P_TRIPLEDOUBLE)) {
// Perform colourisation of white space and triple quoted strings at end of each line to allow
// tab marking to work inside white space and triple quoted strings
styler.ColourTo(i, state);
}
int lev = indentCurrent;
int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsPyComment);
if ((state == SCE_P_TRIPLE) || (state == SCE_P_TRIPLEDOUBLE))
indentNext |= SC_FOLDLEVELWHITEFLAG;
if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
// Only non whitespace lines can be headers
if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {
lev |= SC_FOLDLEVELHEADERFLAG;
} else if (indentNext & SC_FOLDLEVELWHITEFLAG) {
// Line after is blank so check the next - maybe should continue further?
int spaceFlags2 = 0;
int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsPyComment);
if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) {
lev |= SC_FOLDLEVELHEADERFLAG;
}
}
}
indentCurrent = indentNext;
if (fold) {
styler.SetLevel(lineCurrent, lev);
}
lineCurrent++;
atStartLine = true;
}
if (styler.IsLeadByte(ch)) {
chNext = styler.SafeGetCharAt(i + 2);
chPrev = ' ';
chPrev2 = ' ';
i += 1;
continue;
}
if (state == SCE_P_STRINGEOL) {
if (ch != '\r' && ch != '\n') {
styler.ColourTo(i - 1, state);
state = SCE_P_DEFAULT;
}
}
if (state == SCE_P_DEFAULT) {
if (iswordstart(ch)) {
styler.ColourTo(i - 1, state);
state = SCE_P_WORD;
} else if (ch == '#') {
styler.ColourTo(i - 1, state);
state = chNext == '#' ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE;
} else if (ch == '\"') {
styler.ColourTo(i - 1, state);
if (chNext == '\"' && chNext2 == '\"') {
i += 2;
state = SCE_P_TRIPLEDOUBLE;
ch = ' ';
chPrev = ' ';
chNext = styler.SafeGetCharAt(i + 1);
} else {
state = SCE_P_STRING;
}
} else if (ch == '\'') {
styler.ColourTo(i - 1, state);
if (chNext == '\'' && chNext2 == '\'') {
i += 2;
state = SCE_P_TRIPLE;
ch = ' ';
chPrev = ' ';
chNext = styler.SafeGetCharAt(i + 1);
} else {
state = SCE_P_CHARACTER;
}
} else if (isoperator(ch)) {
styler.ColourTo(i - 1, state);
styler.ColourTo(i, SCE_P_OPERATOR);
}
} else if (state == SCE_P_WORD) {
if (!iswordchar(ch)) {
ClassifyWordPy(styler.GetStartSegment(), i - 1, keywords, styler, prevWord);
state = SCE_P_DEFAULT;
if (ch == '#') {
state = chNext == '#' ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE;
} else if (ch == '\"') {
if (chNext == '\"' && chNext2 == '\"') {
i += 2;
state = SCE_P_TRIPLEDOUBLE;
ch = ' ';
chPrev = ' ';
chNext = styler.SafeGetCharAt(i + 1);
} else {
state = SCE_P_STRING;
}
} else if (ch == '\'') {
if (chNext == '\'' && chNext2 == '\'') {
i += 2;
state = SCE_P_TRIPLE;
ch = ' ';
chPrev = ' ';
chNext = styler.SafeGetCharAt(i + 1);
} else {
state = SCE_P_CHARACTER;
}
} else if (isoperator(ch)) {
styler.ColourTo(i, SCE_P_OPERATOR);
}
}
} else {
if (state == SCE_P_COMMENTLINE || state == SCE_P_COMMENTBLOCK) {
if (ch == '\r' || ch == '\n') {
styler.ColourTo(i - 1, state);
state = SCE_P_DEFAULT;
}
} else if (state == SCE_P_STRING) {
if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
styler.ColourTo(i - 1, state);
state = SCE_P_STRINGEOL;
} else if (ch == '\\') {
if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
i++;
ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
}
} else if (ch == '\"') {
styler.ColourTo(i, state);
state = SCE_P_DEFAULT;
}
} else if (state == SCE_P_CHARACTER) {
if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
styler.ColourTo(i - 1, state);
state = SCE_P_STRINGEOL;
} else if (ch == '\\') {
if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
i++;
ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
}
} else if (ch == '\'') {
styler.ColourTo(i, state);
state = SCE_P_DEFAULT;
}
} else if (state == SCE_P_TRIPLE) {
if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') {
styler.ColourTo(i, state);
state = SCE_P_DEFAULT;
}
} else if (state == SCE_P_TRIPLEDOUBLE) {
if (ch == '\"' && chPrev == '\"' && chPrev2 == '\"') {
styler.ColourTo(i, state);
state = SCE_P_DEFAULT;
}
}
}
chPrev2 = chPrev;
chPrev = ch;
}
if (state == SCE_P_WORD) {
ClassifyWordPy(styler.GetStartSegment(), lengthDoc, keywords, styler, prevWord);
} else {
styler.ColourTo(lengthDoc, state);
}
}
LexerModule lmPython(SCLEX_PYTHON, ColourisePyDoc);

View File

@@ -0,0 +1,156 @@
// SciTE - Scintilla based Text Editor
// LexSQL.cxx - lexer for SQL
// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>
#include "Platform.h"
#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"
static void classifyWordSQL(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
char s[100];
bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
s[i] = static_cast<char>(toupper(styler[start + i]));
s[i + 1] = '\0';
}
char chAttr = SCE_C_IDENTIFIER;
if (wordIsNumber)
chAttr = SCE_C_NUMBER;
else {
if (keywords.InList(s))
chAttr = SCE_C_WORD;
}
styler.ColourTo(end, chAttr);
}
static void ColouriseSQLDoc(unsigned int startPos, int length,
int initStyle, WordList *keywordlists[], Accessor &styler) {
WordList &keywords = *keywordlists[0];
styler.StartAt(startPos);
bool fold = styler.GetPropertyInt("fold");
int lineCurrent = styler.GetLine(startPos);
int spaceFlags = 0;
int state = initStyle;
char chPrev = ' ';
char chNext = styler[startPos];
styler.StartSegment(startPos);
unsigned int lengthDoc = startPos + length;
for (unsigned int i = startPos; i < lengthDoc; i++) {
char ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags);
int lev = indentCurrent;
if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
// Only non whitespace lines can be headers
int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags);
if (indentCurrent < (indentNext & ~SC_FOLDLEVELWHITEFLAG)) {
lev |= SC_FOLDLEVELHEADERFLAG;
}
}
if (fold) {
styler.SetLevel(lineCurrent, lev);
}
}
if (styler.IsLeadByte(ch)) {
chNext = styler.SafeGetCharAt(i + 2);
chPrev = ' ';
i += 1;
continue;
}
if (state == SCE_C_DEFAULT) {
if (iswordstart(ch)) {
styler.ColourTo(i - 1, state);
state = SCE_C_WORD;
} else if (ch == '/' && chNext == '*') {
styler.ColourTo(i - 1, state);
state = SCE_C_COMMENT;
} else if (ch == '-' && chNext == '-') {
styler.ColourTo(i - 1, state);
state = SCE_C_COMMENTLINE;
} else if (ch == '\'') {
styler.ColourTo(i - 1, state);
state = SCE_C_STRING;
} else if (isoperator(ch)) {
styler.ColourTo(i - 1, state);
styler.ColourTo(i, SCE_C_OPERATOR);
}
} else if (state == SCE_C_WORD) {
if (!iswordchar(ch)) {
classifyWordSQL(styler.GetStartSegment(), i - 1, keywords, styler);
state = SCE_C_DEFAULT;
if (ch == '/' && chNext == '*') {
state = SCE_C_COMMENT;
} else if (ch == '-' && chNext == '-') {
state = SCE_C_COMMENTLINE;
} else if (ch == '\'') {
state = SCE_C_STRING;
} else if (isoperator(ch)) {
styler.ColourTo(i, SCE_C_OPERATOR);
}
}
} else {
if (state == SCE_C_COMMENT) {
if (ch == '/' && chPrev == '*') {
if (((i > (styler.GetStartSegment() + 2)) || ((initStyle == SCE_C_COMMENT) &&
(styler.GetStartSegment() == startPos)))) {
styler.ColourTo(i, state);
state = SCE_C_DEFAULT;
}
}
} else if (state == SCE_C_COMMENTLINE) {
if (ch == '\r' || ch == '\n') {
styler.ColourTo(i - 1, state);
state = SCE_C_DEFAULT;
}
} else if (state == SCE_C_STRING) {
if (ch == '\'') {
if ( chNext == '\'' ) {
i++;
} else {
styler.ColourTo(i, state);
state = SCE_C_DEFAULT;
i++;
}
ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
}
}
if (state == SCE_C_DEFAULT) { // One of the above succeeded
if (ch == '/' && chNext == '*') {
state = SCE_C_COMMENT;
} else if (ch == '-' && chNext == '-') {
state = SCE_C_COMMENTLINE;
} else if (ch == '\'') {
state = SCE_C_STRING;
} else if (iswordstart(ch)) {
state = SCE_C_WORD;
} else if (isoperator(ch)) {
styler.ColourTo(i, SCE_C_OPERATOR);
}
}
}
chPrev = ch;
}
styler.ColourTo(lengthDoc - 1, state);
}
LexerModule lmSQL(SCLEX_SQL, ColouriseSQLDoc);

View File

@@ -0,0 +1,118 @@
// SciTE - Scintilla based Text Editor
// LexVB.cxx - lexer for Visual Basic and VBScript
// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>
#include "Platform.h"
#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"
static int classifyWordVB(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
char s[100];
bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
s[i] = static_cast<char>(tolower(styler[start + i]));
s[i + 1] = '\0';
}
char chAttr = SCE_C_DEFAULT;
if (wordIsNumber)
chAttr = SCE_C_NUMBER;
else {
if (keywords.InList(s)) {
chAttr = SCE_C_WORD;
if (strcmp(s, "rem") == 0)
chAttr = SCE_C_COMMENTLINE;
}
}
styler.ColourTo(end, chAttr);
if (chAttr == SCE_C_COMMENTLINE)
return SCE_C_COMMENTLINE;
else
return SCE_C_DEFAULT;
}
static void ColouriseVBDoc(unsigned int startPos, int length, int initStyle,
WordList *keywordlists[], Accessor &styler) {
WordList &keywords = *keywordlists[0];
styler.StartAt(startPos);
int state = initStyle;
char chNext = styler[startPos];
styler.StartSegment(startPos);
int lengthDoc = startPos + length;
for (int i = startPos; i < lengthDoc; i++) {
char ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
if (styler.IsLeadByte(ch)) {
chNext = styler.SafeGetCharAt(i + 2);
i += 1;
continue;
}
if (state == SCE_C_DEFAULT) {
if (iswordstart(ch)) {
styler.ColourTo(i - 1, state);
state = SCE_C_WORD;
} else if (ch == '\'') {
styler.ColourTo(i - 1, state);
state = SCE_C_COMMENTLINE;
} else if (ch == '\"') {
styler.ColourTo(i - 1, state);
state = SCE_C_STRING;
}
} else if (state == SCE_C_WORD) {
if (!iswordchar(ch)) {
state = classifyWordVB(styler.GetStartSegment(), i - 1, keywords, styler);
if (state == SCE_C_DEFAULT) {
if (ch == '\'') {
state = SCE_C_COMMENTLINE;
} else if (ch == '\"') {
state = SCE_C_STRING;
}
}
}
} else {
if (state == SCE_C_COMMENTLINE) {
if (ch == '\r' || ch == '\n') {
styler.ColourTo(i - 1, state);
state = SCE_C_DEFAULT;
}
} else if (state == SCE_C_STRING) {
// VB doubles quotes to preserve them
if (ch == '\"') {
styler.ColourTo(i, state);
state = SCE_C_DEFAULT;
i++;
ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
}
}
if (state == SCE_C_DEFAULT) { // One of the above succeeded
if (ch == '\'') {
state = SCE_C_COMMENTLINE;
} else if (ch == '\"') {
state = SCE_C_STRING;
} else if (iswordstart(ch)) {
state = SCE_C_WORD;
}
}
}
}
styler.ColourTo(lengthDoc, state);
}
LexerModule lmVB(SCLEX_VB, ColouriseVBDoc);

View File

@@ -51,20 +51,6 @@ void LineMarker::Draw(Surface *surface, PRectangle &rc) {
} else if (markType == SC_MARK_PLUS) {
int armSize = dimOn2-2;
Point xpts[] = {
Point(centreX - armSize, centreY),
Point(centreX, centreY),
Point(centreX, centreY - armSize),
Point(centreX, centreY - armSize),
Point(centreX, centreY),
Point(centreX + armSize, centreY),
Point(centreX + armSize, centreY),
Point(centreX, centreY),
Point(centreX, centreY + armSize),
Point(centreX, centreY + armSize),
Point(centreX, centreY),
Point(centreX - armSize, centreY),
};
Point pts[] = {
Point(centreX - armSize, centreY - 1),
Point(centreX - 1, centreY - 1),
@@ -90,12 +76,6 @@ void LineMarker::Draw(Surface *surface, PRectangle &rc) {
Point(centreX + armSize, centreY +1),
Point(centreX - armSize, centreY + 1),
};
Point xpts[] = {
Point(centreX - armSize, centreY),
Point(centreX + armSize, centreY),
Point(centreX + armSize, centreY),
Point(centreX - armSize, centreY),
};
surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
fore.allocated, back.allocated);

View File

@@ -27,6 +27,7 @@ bool EqualCaseInsensitive(const char *a, const char *b) {
// Get a line of input. If end of line escaped with '\\' then continue reading.
static bool GetFullLine(const char *&fpc, int &lenData, char *s, int len) {
bool continuation = true;
s[0] = '\0';
while ((len > 1) && lenData > 0) {
char ch = *fpc;
fpc++;
@@ -38,7 +39,7 @@ static bool GetFullLine(const char *&fpc, int &lenData, char *s, int len) {
fpc++;
lenData--;
}
*s++ = '\0';
*s = '\0';
return true;
}
} else if ((ch == '\\') && (lenData > 0) && ((*fpc == '\r') || (*fpc == '\n'))) {
@@ -46,6 +47,7 @@ static bool GetFullLine(const char *&fpc, int &lenData, char *s, int len) {
} else {
continuation = false;
*s++ = ch;
*s = '\0';
len--;
}
}
@@ -120,7 +122,7 @@ SString PropSet::Get(const char *key) {
int PropSet::GetInt(const char *key, int defaultValue) {
SString val = Get(key);
if (val.length())
return Get(key).value();
return val.value();
else
return defaultValue;
}
@@ -253,6 +255,9 @@ void PropSet::ReadFromMemory(const char *data, int len) {
if (isalpha(linebuf[0]))
Set(linebuf);
}
// If there is a final line:
if (isalpha(linebuf[0]))
Set(linebuf);
}
}
@@ -371,7 +376,7 @@ bool WordList::InList(const char *s) {
for (int i = 0; words[i][0]; i++)
len++;
SortWordList(words, len);
for (int k = 0; k < (sizeof(starts) / sizeof(starts[0])); k++)
for (unsigned int k = 0; k < (sizeof(starts) / sizeof(starts[0])); k++)
starts[k] = -1;
for (int l = len - 1; l >= 0; l--) {
unsigned char indexChar = words[l][0];

View File

@@ -30,7 +30,7 @@ class SVector {
return;
}
size = newSize;
for (int i=0; i<len; i++) {
for (unsigned int i=0; i<len; i++) {
newv[i] = v[i];
}
delete []v;
@@ -94,13 +94,13 @@ public:
size = 0;
len = 0;
}
void SetLength(int newLen) {
if (newLen > len) {
if (newLen >= size) {
SizeTo(newLen);
void SetLength(unsigned int newLength) {
if (newLength > len) {
if (newLength >= size) {
SizeTo(newLength);
}
}
len = newLen;
len = newLength;
}
int Length() const {
return len;

View File

@@ -15,6 +15,8 @@
#include "SciLexer.h"
#include "PropSet.h"
#include "Accessor.h"
#include "WindowAccessor.h"
#include "DocumentAccessor.h"
#include "KeyWords.h"
#endif
#include "ContractionState.h"
@@ -50,11 +52,11 @@ void ScintillaBase::RefreshColourPalette(Palette &pal, bool want) {
ct.RefreshColourPalette(pal, want);
}
void ScintillaBase::AddChar(char ch) {
void ScintillaBase::AddCharUTF(char *s, unsigned int len) {
bool acActiveBeforeCharAdded = ac.Active();
Editor::AddChar(ch);
Editor::AddCharUTF(s, len);
if (acActiveBeforeCharAdded)
AutoCompleteChanged(ch);
AutoCompleteChanged(s[0]);
}
void ScintillaBase::Command(int cmdId) {
@@ -276,20 +278,20 @@ void ScintillaBase::Colourise(int start, int end) {
end = lengthDoc;
int len = end - start;
PropSet props;
StylingContext styler(wMain.GetID(), props);
//WindowAccessor styler(wMain.GetID(), props);
DocumentAccessor styler(pdoc, props);
int styleStart = 0;
if (start > 0)
styleStart = styler.StyleAt(start - 1);
ColouriseDoc(pdoc->dbcsCodePage, start, len, styleStart, lexLanguage, keyWordLists, styler);
styler.SetCodePage(pdoc->dbcsCodePage);
LexerModule::Colourise(start, len, styleStart, lexLanguage, keyWordLists, styler);
styler.Flush();
}
#endif
void ScintillaBase::NotifyStyleNeeded(int endStyleNeeded) {
void ScintillaBase::NotifyStyleToNeeded(int endStyleNeeded) {
#ifdef SCI_LEXER
if (lexLanguage != SCLEX_CONTAINER) {
int endStyled = Platform::SendScintilla(wMain.GetID(), SCI_GETENDSTYLED, 0, 0);
@@ -299,7 +301,7 @@ void ScintillaBase::NotifyStyleNeeded(int endStyleNeeded) {
return;
}
#endif
Editor::NotifyStyleNeeded(endStyleNeeded);
Editor::NotifyStyleToNeeded(endStyleNeeded);
}
LRESULT ScintillaBase::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
@@ -322,9 +324,20 @@ LRESULT ScintillaBase::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
AutoCompleteCompleted();
break;
case SCI_AUTOCSETSEPARATOR:
ac.SetSeparator(wParam);
break;
case SCI_AUTOCGETSEPARATOR:
return ac.GetSeparator();
case SCI_AUTOCSTOPS:
ac.SetStopChars(reinterpret_cast<char *>(lParam));
break;
case SCI_AUTOCSELECT:
ac.Select(reinterpret_cast<char *>(lParam));
break;
case SCI_CALLTIPSHOW: {
AutoCompleteCancel();
@@ -377,6 +390,7 @@ LRESULT ScintillaBase::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
case SCI_COLOURISE:
Colourise(wParam, lParam);
Redraw();
break;
case SCI_SETPROPERTY:
@@ -385,7 +399,7 @@ LRESULT ScintillaBase::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
break;
case SCI_SETKEYWORDS:
if ((wParam >= 0) && (wParam < numWordLists)) {
if (wParam < numWordLists) {
keyWordLists[wParam]->Clear();
keyWordLists[wParam]->Set(reinterpret_cast<const char *>(lParam));
}

View File

@@ -7,6 +7,9 @@
#define SCINTILLABASE_H
class ScintillaBase : public Editor {
// Private so ScintillaBase objects can not be copied
ScintillaBase(const ScintillaBase &) : Editor() {}
ScintillaBase &operator=(const ScintillaBase &) { return *this; }
protected:
// Enumeration of commands and child windows
enum {
@@ -42,7 +45,7 @@ protected:
virtual void RefreshColourPalette(Palette &pal, bool want);
virtual void AddChar(char ch);
virtual void AddCharUTF(char *s, unsigned int len);
void Command(int cmdId);
virtual int KeyCommand(UINT iMessage);
@@ -59,7 +62,7 @@ protected:
virtual void ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt);
virtual void NotifyStyleNeeded(int endStyleNeeded);
virtual void NotifyStyleToNeeded(int endStyleNeeded);
public:
// Public so scintilla_send_message can use it
virtual LRESULT WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam);

View File

@@ -7,49 +7,108 @@
#include "Platform.h"
#include "Scintilla.h"
#include "Style.h"
Style::Style() {
Clear();
aliasOfDefaultFont = true;
Clear(Colour(0,0,0), Colour(0xff,0xff,0xff),
Platform::DefaultFontSize(), 0, SC_CHARSET_DEFAULT,
false, false, false, false);
}
Style::Style(const Style &source) {
Clear(Colour(0,0,0), Colour(0xff,0xff,0xff),
0, 0, 0,
false, false, false, false);
fore.desired = source.fore.desired;
back.desired = source.back.desired;
characterSet = source.characterSet;
bold = source.bold;
italic = source.italic;
size = source.size;
eolFilled = source.eolFilled;
underline = source.underline;
}
Style::~Style() {
font.Release();
if (aliasOfDefaultFont)
font.SetID(0);
else
font.Release();
aliasOfDefaultFont = false;
}
Style &Style::operator=(const Style &source) {
if (this == &source)
return *this;
Clear();
Clear(Colour(0,0,0), Colour(0xff,0xff,0xff),
0, 0, SC_CHARSET_DEFAULT,
false, false, false, false);
fore.desired = source.fore.desired;
back.desired = source.back.desired;
characterSet = source.characterSet;
bold = source.bold;
italic = source.italic;
size = source.size;
strcpy(fontName, source.fontName);
eolFilled = source.eolFilled;
underline = source.underline;
return *this;
}
void Style::Clear(Colour fore_, Colour back_, int size_, const char *fontName_,
bool bold_, bool italic_, bool eolFilled_) {
void Style::Clear(Colour fore_, Colour back_, int size_,
const char *fontName_, int characterSet_,
bool bold_, bool italic_, bool eolFilled_, bool underline_) {
fore.desired = fore_;
back.desired = back_;
characterSet = characterSet_;
bold = bold_;
italic = italic_;
size = size_;
strcpy(fontName, fontName_);
fontName = fontName_;
eolFilled = eolFilled_;
font.Release();
underline = underline_;
if (aliasOfDefaultFont)
font.SetID(0);
else
font.Release();
aliasOfDefaultFont = false;
}
void Style::Realise(Surface &surface, int zoomLevel) {
bool Style::EquivalentFontTo(const Style *other) const {
if (bold != other->bold ||
italic != other->italic ||
size != other->size ||
characterSet != other->characterSet)
return false;
if (fontName == other->fontName)
return true;
if (!fontName)
return false;
if (!other->fontName)
return false;
return strcmp(fontName, other->fontName) == 0;
}
void Style::Realise(Surface &surface, int zoomLevel, Style *defaultStyle) {
int sizeZoomed = size + zoomLevel;
if (sizeZoomed <= 2) // Hangs if sizeZoomed <= 1
sizeZoomed = 2;
int deviceHeight = (sizeZoomed * surface.LogPixelsY()) / 72;
font.Create(fontName, deviceHeight, bold, italic);
if (aliasOfDefaultFont)
font.SetID(0);
else
font.Release();
int deviceHeight = surface.DeviceHeightFont(sizeZoomed);
aliasOfDefaultFont = defaultStyle &&
(EquivalentFontTo(defaultStyle) || !fontName);
if (aliasOfDefaultFont) {
font.SetID(defaultStyle->font.GetID());
} else if (fontName) {
font.Create(fontName, characterSet, deviceHeight, bold, italic);
} else {
font.SetID(0);
}
ascent = surface.Ascent(font);
descent = surface.Descent(font);

View File

@@ -10,11 +10,14 @@ class Style {
public:
ColourPair fore;
ColourPair back;
bool aliasOfDefaultFont;
bool bold;
bool italic;
int size;
char fontName[100];
const char *fontName;
int characterSet;
bool eolFilled;
bool underline;
Font font;
unsigned int lineHeight;
@@ -25,13 +28,15 @@ public:
unsigned int spaceWidth;
Style();
Style(const Style &source);
~Style();
Style &operator=(const Style &source);
void Clear(Colour fore_=Colour(0,0,0), Colour back_=Colour(0xff,0xff,0xff),
int size_=Platform::DefaultFontSize(),
const char *fontName_=Platform::DefaultFont(),
bool bold_=false, bool italic_=false, bool eolFilled_=false);
void Realise(Surface &surface, int zoomLevel);
void Clear(Colour fore_, Colour back_,
int size_,
const char *fontName_, int characterSet_,
bool bold_, bool italic_, bool eolFilled_, bool underline_);
bool EquivalentFontTo(const Style *other) const;
void Realise(Surface &surface, int zoomLevel, Style *defaultStyle=0);
};
#endif

View File

@@ -0,0 +1,77 @@
// UniConversion.h - functions to handle UFT-8 and UCS-2 strings
// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h>
#include "UniConversion.h"
unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen) {
unsigned int len = 0;
for (unsigned int i = 0; i < tlen && uptr[i]; i++) {
unsigned int uch = uptr[i];
if (uch < 0x80)
len++;
else if (uch < 0x800)
len+=2;
else
len +=3;
}
return len;
}
void UTF8FromUCS2(const wchar_t *uptr, unsigned int tlen, char *putf, unsigned int len) {
int k = 0;
for (unsigned int i = 0; i < tlen && uptr[i]; i++) {
unsigned int uch = uptr[i];
if (uch < 0x80) {
putf[k++] = static_cast<char>(uch);
} else if (uch < 0x800) {
putf[k++] = static_cast<char>(0xC0 | (uch >> 6));
putf[k++] = static_cast<char>(0x80 | (uch & 0x3f));
} else {
putf[k++] = static_cast<char>(0xE0 | (uch >> 12));
putf[k++] = static_cast<char>(0x80 | ((uch >> 6) & 0x3f));
putf[k++] = static_cast<char>(0x80 | (uch & 0x3f));
}
}
putf[len] = '\0';
}
unsigned int UCS2Length(const char *s, unsigned int len) {
unsigned int ulen = 0;
for (unsigned int i=0;i<len;i++) {
unsigned char ch = static_cast<unsigned char>(s[i]);
if ((ch < 0x80) || (ch > (0x80 + 0x40)))
ulen++;
}
return ulen;
}
unsigned int UCS2FromUTF8(const char *s, unsigned int len, wchar_t *tbuf, unsigned int tlen) {
#ifdef USE_API
return ::MultiByteToWideChar(CP_UTF8, 0, s, len, tbuf, tlen);
#else
unsigned int ui=0;
const unsigned char *us = reinterpret_cast<const unsigned char *>(s);
unsigned int i=0;
while ((i<len) && (ui<tlen)) {
unsigned char ch = us[i++];
if (ch < 0x80) {
tbuf[ui] = ch;
} else if (ch < 0x80 + 0x40 + 0x20) {
tbuf[ui] = static_cast<wchar_t>((ch & 0x1F) << 6);
ch = us[i++];
tbuf[ui] = static_cast<wchar_t>(tbuf[ui] + (ch & 0x7F));
} else {
tbuf[ui] = static_cast<wchar_t>((ch & 0xF) << 12);
ch = us[i++];
tbuf[ui] = static_cast<wchar_t>(tbuf[ui] + ((ch & 0x7F) << 6));
ch = us[i++];
tbuf[ui] = static_cast<wchar_t>(tbuf[ui] + (ch & 0x7F));
}
ui++;
}
return ui;
#endif
}

View File

@@ -0,0 +1,9 @@
// UniConversion.h - functions to handle UFT-8 and UCS-2 strings
// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen);
void UTF8FromUCS2(const wchar_t *uptr, unsigned int tlen, char *putf, unsigned int len);
unsigned int UCS2Length(const char *s, unsigned int len);
unsigned int UCS2FromUTF8(const char *s, unsigned int len, wchar_t *tbuf, unsigned int tlen);

View File

@@ -17,14 +17,46 @@ MarginStyle::MarginStyle() :
symbol(false), width(16), mask(0xffffffff), sensitive(false) {
}
// A list of the fontnames - avoids wasting space in each style
FontNames::FontNames() {
max = 0;
}
FontNames::~FontNames() {
Clear();
}
void FontNames::Clear() {
for (int i=0;i<max;i++) {
delete []names[i];
}
max = 0;
}
const char *FontNames::Save(const char *name) {
if (!name)
return 0;
for (int i=0;i<max;i++) {
if (strcmp(names[i], name) == 0) {
return names[i];
}
}
names[max] = new char[strlen(name) + 1];
strcpy(names[max], name);
max++;
return names[max-1];
}
ViewStyle::ViewStyle() {
Init();
}
ViewStyle::ViewStyle(const ViewStyle &source) {
Init();
for (int sty=0;sty<=STYLE_MAX;sty++) {
for (unsigned int sty=0;sty<(sizeof(styles)/sizeof(styles[0]));sty++) {
styles[sty] = source.styles[sty];
// Can't just copy fontname as its lifetime is relative to its owning ViewStyle
styles[sty].fontName = fontNames.Save(source.styles[sty].fontName);
}
for (int mrk=0;mrk<=MARKER_MAX;mrk++) {
markers[mrk] = source.markers[mrk];
@@ -59,6 +91,9 @@ ViewStyle::~ViewStyle() {
}
void ViewStyle::Init() {
fontNames.Clear();
ResetDefaultStyle();
indicators[0].style = INDIC_SQUIGGLE;
indicators[0].fore = Colour(0, 0x7f, 0);
indicators[1].style = INDIC_TT;
@@ -136,14 +171,17 @@ void ViewStyle::RefreshColourPalette(Palette &pal, bool want) {
void ViewStyle::Refresh(Surface &surface) {
selbar.desired = Platform::Chrome();
selbarlight.desired = Platform::ChromeHighlight();
maxAscent = 1;
maxDescent = 1;
styles[STYLE_DEFAULT].Realise(surface, zoomLevel);
maxAscent = styles[STYLE_DEFAULT].ascent;
maxDescent = styles[STYLE_DEFAULT].descent;
for (unsigned int i=0;i<(sizeof(styles)/sizeof(styles[0]));i++) {
styles[i].Realise(surface, zoomLevel);
if (maxAscent < styles[i].ascent)
maxAscent = styles[i].ascent;
if (maxDescent < styles[i].descent)
maxDescent = styles[i].descent;
if (i != STYLE_DEFAULT) {
styles[i].Realise(surface, zoomLevel, &styles[STYLE_DEFAULT]);
if (maxAscent < styles[i].ascent)
maxAscent = styles[i].ascent;
if (maxDescent < styles[i].descent)
maxDescent = styles[i].descent;
}
}
lineHeight = maxAscent + maxDescent;
@@ -162,22 +200,31 @@ void ViewStyle::Refresh(Surface &surface) {
}
void ViewStyle::ResetDefaultStyle() {
styles[STYLE_DEFAULT].Clear();
styles[STYLE_DEFAULT].Clear(Colour(0,0,0), Colour(0xff,0xff,0xff),
Platform::DefaultFontSize(), fontNames.Save(Platform::DefaultFont()),
SC_CHARSET_DEFAULT,
false, false, false, false);
}
void ViewStyle::ClearStyles() {
// Reset all styles to be like the default style
for (int i=0; i<=STYLE_MAX; i++) {
for (unsigned int i=0;i<(sizeof(styles)/sizeof(styles[0]));i++) {
if (i != STYLE_DEFAULT) {
styles[i].Clear(
styles[STYLE_DEFAULT].fore.desired,
styles[STYLE_DEFAULT].back.desired,
styles[STYLE_DEFAULT].size,
styles[STYLE_DEFAULT].fontName,
styles[STYLE_DEFAULT].characterSet,
styles[STYLE_DEFAULT].bold,
styles[STYLE_DEFAULT].italic);
styles[STYLE_DEFAULT].italic,
styles[STYLE_DEFAULT].eolFilled,
styles[STYLE_DEFAULT].underline);
}
}
styles[STYLE_LINENUMBER].back.desired = Platform::Chrome();
}
void ViewStyle::SetStyleFontName(int styleIndex, const char *name) {
styles[styleIndex].fontName = fontNames.Save(name);
}

View File

@@ -15,8 +15,20 @@ public:
MarginStyle();
};
class FontNames {
private:
char *names[STYLE_MAX + 1];
int max;
public:
FontNames();
~FontNames();
void Clear();
const char *Save(const char *name);
};
class ViewStyle {
public:
FontNames fontNames;
Style styles[STYLE_MAX + 1];
LineMarker markers[MARKER_MAX + 1];
Indicator indicators[INDIC_MAX + 1];
@@ -54,6 +66,7 @@ public:
void Refresh(Surface &surface);
void ResetDefaultStyle();
void ClearStyles();
void SetStyleFontName(int styleIndex, const char *name);
};
#endif

View File

@@ -0,0 +1,173 @@
// SciTE - Scintilla based Text Editor
// Accessor.cxx - rapid easy access to contents of a Scintilla
// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include "Platform.h"
#include "PropSet.h"
#include "Accessor.h"
#include "WindowAccessor.h"
#include "Scintilla.h"
WindowAccessor::~WindowAccessor() {
}
bool WindowAccessor::InternalIsLeadByte(char ch) {
#if PLAT_GTK
// TODO: support DBCS under GTK+
return false;
#elif PLAT_WIN
if (SC_CP_UTF8 == codePage)
// For lexing, all characters >= 0x80 are treated the
// same so none is considered a lead byte.
return false;
else
return IsDBCSLeadByteEx(codePage, ch);
#elif PLAT_WX
return false;
#endif
}
void WindowAccessor::Fill(int position) {
if (lenDoc == -1)
lenDoc = Platform::SendScintilla(id, WM_GETTEXTLENGTH, 0, 0);
startPos = position - slopSize;
if (startPos + bufferSize > lenDoc)
startPos = lenDoc - bufferSize;
if (startPos < 0)
startPos = 0;
endPos = startPos + bufferSize;
if (endPos > lenDoc)
endPos = lenDoc;
TEXTRANGE tr = {{startPos, endPos}, buf};
Platform::SendScintilla(id, EM_GETTEXTRANGE, 0, reinterpret_cast<LPARAM>(&tr));
}
char WindowAccessor::StyleAt(int position) {
return static_cast<char>(Platform::SendScintilla(
id, SCI_GETSTYLEAT, position, 0));
}
int WindowAccessor::GetLine(int position) {
return Platform::SendScintilla(id, EM_LINEFROMCHAR, position, 0);
}
int WindowAccessor::LineStart(int line) {
return Platform::SendScintilla(id, EM_LINEINDEX, line, 0);
}
int WindowAccessor::LevelAt(int line) {
return Platform::SendScintilla(id, SCI_GETFOLDLEVEL, line, 0);
}
int WindowAccessor::Length() {
if (lenDoc == -1)
lenDoc = Platform::SendScintilla(id, WM_GETTEXTLENGTH, 0, 0);
return lenDoc;
}
int WindowAccessor::GetLineState(int line) {
return Platform::SendScintilla(id, SCI_GETLINESTATE, line);
}
int WindowAccessor::SetLineState(int line, int state) {
return Platform::SendScintilla(id, SCI_SETLINESTATE, line, state);
}
void WindowAccessor::StartAt(unsigned int start, char chMask) {
Platform::SendScintilla(id, SCI_STARTSTYLING, start, chMask);
}
void WindowAccessor::StartSegment(unsigned int pos) {
startSeg = pos;
}
void WindowAccessor::ColourTo(unsigned int pos, int chAttr) {
// Only perform styling if non empty range
if (pos != startSeg - 1) {
if (pos < startSeg) {
Platform::DebugPrintf("Bad colour positions %d - %d\n", startSeg, pos);
}
if (validLen + (pos - startSeg + 1) >= bufferSize)
Flush();
if (validLen + (pos - startSeg + 1) >= bufferSize) {
// Too big for buffer so send directly
Platform::SendScintilla(id, SCI_SETSTYLING, pos - startSeg + 1, chAttr);
} else {
if (chAttr != chWhile)
chFlags = 0;
chAttr |= chFlags;
for (unsigned int i = startSeg; i <= pos; i++) {
styleBuf[validLen++] = static_cast<char>(chAttr);
}
}
}
startSeg = pos+1;
}
void WindowAccessor::SetLevel(int line, int level) {
Platform::SendScintilla(id, SCI_SETFOLDLEVEL, line, level);
}
void WindowAccessor::Flush() {
startPos = extremePosition;
lenDoc = -1;
if (validLen > 0) {
Platform::SendScintilla(id, SCI_SETSTYLINGEX, validLen,
reinterpret_cast<LPARAM>(styleBuf));
validLen = 0;
}
}
int WindowAccessor::IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader) {
int end = Length();
int spaceFlags = 0;
// Determines the indentation level of the current line and also checks for consistent
// indentation compared to the previous line.
// Indentation is judged consistent when the indentation whitespace of each line lines
// the same or the indentation of one line is a prefix of the other.
int pos = LineStart(line);
char ch = (*this)[pos];
int indent = 0;
bool inPrevPrefix = line > 0;
int posPrev = inPrevPrefix ? LineStart(line-1) : 0;
while ((ch == ' ' || ch == '\t') && (pos < end)) {
if (inPrevPrefix) {
char chPrev = (*this)[posPrev++];
if (chPrev == ' ' || chPrev == '\t') {
if (chPrev != ch)
spaceFlags |= wsInconsistent;
} else {
inPrevPrefix = false;
}
}
if (ch == ' ') {
spaceFlags |= wsSpace;
indent++;
} else { // Tab
spaceFlags |= wsTab;
if (spaceFlags & wsSpace)
spaceFlags |= wsSpaceTab;
indent = (indent / 8 + 1) * 8;
}
ch = (*this)[++pos];
}
*flags = spaceFlags;
indent += SC_FOLDLEVELBASE;
// if completely empty line or the start of a comment...
if (isspace(ch) || (pfnIsCommentLeader && (*pfnIsCommentLeader)(*this, pos, end-pos)) )
return indent | SC_FOLDLEVELWHITEFLAG;
else
return indent;
}

View File

@@ -5,7 +5,7 @@
// derive directly from the Scintilla classes, but instead
// delegates most things to the real Scintilla class.
// This allows the use of Scintilla without polluting the
// namespace with all the classes and itentifiers from Scintilla.
// namespace with all the classes and identifiers from Scintilla.
//
// Author: Robin Dunn
//
@@ -15,11 +15,53 @@
// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
#include <ctype.h>
#include "wx/stc/stc.h"
#include "ScintillaWX.h"
#include <wx/tokenzr.h>
// The following code forces a reference to all of the Scintilla lexers.
// If we don't do something like this, then the linker tends to "optimize"
// them away. (eric@sourcegear.com)
int wxForceScintillaLexers(void)
{
extern LexerModule lmCPP;
extern LexerModule lmHTML;
extern LexerModule lmXML;
extern LexerModule lmProps;
extern LexerModule lmErrorList;
extern LexerModule lmMake;
extern LexerModule lmBatch;
extern LexerModule lmPerl;
extern LexerModule lmPython;
extern LexerModule lmSQL;
extern LexerModule lmVB;
if (
&lmCPP
&& &lmHTML
&& &lmXML
&& &lmProps
&& &lmErrorList
&& &lmMake
&& &lmBatch
&& &lmPerl
&& &lmPython
&& &lmSQL
&& &lmVB
)
{
return 1;
}
else
{
return 0;
}
}
//----------------------------------------------------------------------
const wxChar* wxSTCNameStr = "stcwindow";
@@ -33,13 +75,19 @@ BEGIN_EVENT_TABLE(wxStyledTextCtrl, wxControl)
EVT_LEFT_UP (wxStyledTextCtrl::OnMouseLeftUp)
EVT_RIGHT_UP (wxStyledTextCtrl::OnMouseRightUp)
EVT_CHAR (wxStyledTextCtrl::OnChar)
EVT_KEY_DOWN (wxStyledTextCtrl::OnKeyDown)
EVT_KILL_FOCUS (wxStyledTextCtrl::OnLoseFocus)
EVT_SET_FOCUS (wxStyledTextCtrl::OnGainFocus)
EVT_SYS_COLOUR_CHANGED (wxStyledTextCtrl::OnSysColourChanged)
EVT_ERASE_BACKGROUND (wxStyledTextCtrl::OnEraseBackground)
EVT_MENU_RANGE (-1, -1, wxStyledTextCtrl::OnMenu)
EVT_LISTBOX_DCLICK (-1, wxStyledTextCtrl::OnListBox)
END_EVENT_TABLE()
IMPLEMENT_CLASS(wxStyledTextCtrl, wxControl)
IMPLEMENT_DYNAMIC_CLASS(wxStyledTextEvent, wxCommandEvent)
//----------------------------------------------------------------------
// Constructor and Destructor
@@ -69,7 +117,7 @@ wxStyledTextCtrl::~wxStyledTextCtrl() {
//----------------------------------------------------------------------
inline long wxStyledTextCtrl::SendMsg(int msg, long wp, long lp) {
long wxStyledTextCtrl::SendMsg(int msg, long wp, long lp) {
return m_swx->WndProc(msg, wp, lp);
}
@@ -81,9 +129,10 @@ inline long wxStyledTextCtrl::SendMsg(int msg, long wp, long lp) {
wxString wxStyledTextCtrl::GetText() {
wxString text;
int len = GetTextLength();
char* buff = text.GetWriteBuf(len);
char* buff = text.GetWriteBuf(len+1);
SendMsg(WM_GETTEXT, len, (long)buff);
buff[len] = 0;
text.UngetWriteBuf();
return text;
}
@@ -99,8 +148,9 @@ wxString wxStyledTextCtrl::GetLine(int line) {
int len = GetLineLength(line);
char* buff = text.GetWriteBuf(len+1);
*((WORD*)buff) = len+1;
*((WORD*)buff) = len;
SendMsg(EM_GETLINE, line, (long)buff);
buff[len] = 0;
text.UngetWriteBuf();
return text;
}
@@ -384,7 +434,7 @@ wxString wxStyledTextCtrl::GetCurrentLineText(int* linePos) {
int len = GetLineLength(GetCurrentLine());
char* buff = text.GetWriteBuf(len+1);
int pos = SendMsg(SCI_GETCURLINE, len+1, (long)buff);
int pos = SendMsg(SCI_GETCURLINE, len, (long)buff);
text.UngetWriteBuf();
if (linePos)
@@ -410,7 +460,7 @@ int wxStyledTextCtrl::LineFromPoint(wxPoint pt) {
wxPoint wxStyledTextCtrl::PointFromPosition(int pos) {
Point pt;
SendMsg(EM_POSFROMCHAR, pos, (long)&pt);
SendMsg(EM_POSFROMCHAR, (long)&pt, pos);
return wxPoint(pt.x, pt.y);
}
@@ -491,6 +541,27 @@ int wxStyledTextCtrl::GetSelectionType() {
}
int wxStyledTextCtrl::GetLinesOnScreen() {
return SendMsg(SCI_LINESONSCREEN);
}
bool wxStyledTextCtrl::IsSelectionRectangle() {
return SendMsg(SCI_SELECTIONISRECTANGLE) != 0;
}
void wxStyledTextCtrl::SetUseHorizontalScrollBar(bool use) {
SendMsg(SCI_SETHSCROLLBAR, use);
}
bool wxStyledTextCtrl::GetUseHorizontalScrollBar() {
return SendMsg(SCI_GETHSCROLLBAR) != 0;
}
//----------------------------------------------------------------------
@@ -598,6 +669,16 @@ void wxStyledTextCtrl::SetStyleBytes(int length, char* styleBytes) {
}
void wxStyledTextCtrl::SetLineState(int line, int value) {
SendMsg(SCI_SETLINESTATE, line, value);
}
int wxStyledTextCtrl::GetLineState(int line) {
return SendMsg(SCI_GETLINESTATE, line);
}
//----------------------------------------------------------------------
// Style Definition
@@ -646,6 +727,7 @@ void wxStyledTextCtrl::StyleResetDefault() {
// face:[facename] sets the font face name to use
// size:[num] sets the font size in points
// eol turns on eol filling
// underline turns on underlining
//
void wxStyledTextCtrl::StyleSetSpec(int styleNum, const wxString& spec) {
@@ -663,6 +745,9 @@ void wxStyledTextCtrl::StyleSetSpec(int styleNum, const wxString& spec) {
else if (option == "italic")
StyleSetItalic(styleNum, true);
else if (option == "underline")
StyleSetUnderline(styleNum, true);
else if (option == "eol")
StyleSetEOLFilled(styleNum, true);
@@ -699,18 +784,21 @@ void wxStyledTextCtrl::StyleSetFont(int styleNum, wxFont& font) {
wxString faceName = font.GetFaceName();
bool bold = font.GetWeight() == wxBOLD;
bool italic = font.GetStyle() != wxNORMAL;
bool under = font.GetUnderlined();
StyleSetFontAttr(styleNum, size, faceName, bold, italic);
StyleSetFontAttr(styleNum, size, faceName, bold, italic, under);
}
void wxStyledTextCtrl::StyleSetFontAttr(int styleNum, int size,
const wxString& faceName,
bool bold, bool italic) {
bool bold, bool italic,
bool underline) {
StyleSetSize(styleNum, size);
StyleSetFaceName(styleNum, faceName);
StyleSetBold(styleNum, bold);
StyleSetItalic(styleNum, italic);
StyleSetUnderline(styleNum, underline);
}
@@ -739,6 +827,11 @@ void wxStyledTextCtrl::StyleSetEOLFilled(int styleNum, bool fillEOL) {
}
void wxStyledTextCtrl::StyleSetUnderline(int styleNum, bool underline) {
SendMsg(SCI_STYLESETUNDERLINE, styleNum, underline);
}
//----------------------------------------------------------------------
// Margins in the edit area
@@ -829,7 +922,7 @@ void wxStyledTextCtrl::SetSelectionBackground(const wxColour& colour) {
void wxStyledTextCtrl::SetCaretForeground(const wxColour& colour) {
SendMsg(SCI_SETCARETFORE, 0, wxColourAsLong(colour));
SendMsg(SCI_SETCARETFORE, wxColourAsLong(colour));
}
@@ -858,11 +951,41 @@ void wxStyledTextCtrl::SetTabWidth(int numChars) {
}
void wxStyledTextCtrl::SetIndent(int numChars) {
SendMsg(SCI_SETINDENT, numChars);
}
void wxStyledTextCtrl::SetUseTabs(bool usetabs) {
SendMsg(SCI_SETUSETABS, usetabs);
}
void wxStyledTextCtrl::SetLineIndentation(int line, int indentation) {
SendMsg(SCI_SETLINEINDENTATION, line, indentation);
}
int wxStyledTextCtrl:: GetLineIndentation(int line) {
return SendMsg(SCI_GETLINEINDENTATION, line);
}
int wxStyledTextCtrl::GetLineIndentationPos(int line) {
return SendMsg(SCI_GETLINEINDENTPOSITION, line);
}
void wxStyledTextCtrl::SetWordChars(const wxString& wordChars) {
SendMsg(SCI_SETTABWIDTH, 0, (long)wordChars.c_str());
}
void wxStyledTextCtrl::SetUsePop(bool usepopup) {
SendMsg(SCI_USEPOPUP, usepopup);
}
//----------------------------------------------------------------------
// Brace highlighting
@@ -967,7 +1090,7 @@ int wxStyledTextCtrl::IndicatorGetStyle(int indicNum) {
void wxStyledTextCtrl::IndicatorSetColour(int indicNum, const wxColour& colour) {
SendMsg(SCI_INDICSETSTYLE, indicNum, wxColourAsLong(colour));
SendMsg(SCI_INDICSETFORE, indicNum, wxColourAsLong(colour));
}
@@ -1006,6 +1129,21 @@ void wxStyledTextCtrl::AutoCompStopChars(const wxString& stopChars) {
}
void wxStyledTextCtrl::AutoCompSetSeparator(char separator) {
SendMsg(SCI_AUTOCSETSEPARATOR, separator);
}
char wxStyledTextCtrl::AutoCompGetSeparator() {
return SendMsg(SCI_AUTOCGETSEPARATOR);
}
void wxStyledTextCtrl::AutoCompSelect(const wxString& stringtoselect) {
SendMsg(SCI_AUTOCSELECT, (long)stringtoselect.c_str());
}
//----------------------------------------------------------------------
// Call tips
@@ -1129,8 +1267,8 @@ int wxStyledTextCtrl::GetFoldLevel(int line) {
}
int wxStyledTextCtrl::GetLastChild(int line) {
return SendMsg(SCI_GETLASTCHILD, line);
int wxStyledTextCtrl::GetLastChild(int line, int level) {
return SendMsg(SCI_GETLASTCHILD, line, level);
}
@@ -1154,8 +1292,8 @@ bool wxStyledTextCtrl::GetLineVisible(int line) {
}
void wxStyledTextCtrl::SetFoldExpanded(int line) {
SendMsg(SCI_SETFOLDEXPANDED, line);
void wxStyledTextCtrl::SetFoldExpanded(int line, bool expanded) {
SendMsg(SCI_SETFOLDEXPANDED, line, expanded);
}
@@ -1174,6 +1312,33 @@ void wxStyledTextCtrl::EnsureVisible(int line) {
}
void wxStyledTextCtrl::SetFoldFlags(int flags) {
SendMsg(SCI_SETFOLDFLAGS, flags);
}
//----------------------------------------------------------------------
// Zooming
void wxStyledTextCtrl::ZoomIn() {
SendMsg(SCI_ZOOMIN);
}
void wxStyledTextCtrl::ZoomOut() {
SendMsg(SCI_ZOOMOUT);
}
void wxStyledTextCtrl::SetZoom(int zoom) {
SendMsg(SCI_SETZOOM, zoom);
}
int wxStyledTextCtrl::GetZoom() {
return SendMsg(SCI_GETZOOM);
}
//----------------------------------------------------------------------
// Long Lines
@@ -1232,6 +1397,18 @@ void wxStyledTextCtrl::SetKeywords(int keywordSet, const wxString& keywordLi
//----------------------------------------------------------------------
// Event mask for Modified Event
void wxStyledTextCtrl::SetModEventMask(int mask) {
SendMsg(SCI_SETMODEVENTMASK, mask);
}
//int wxStyledTextCtrl::GetModEventMask() {
// return SendMsg(SCI_GETMODEVENTMASK);
//}
//----------------------------------------------------------------------
// Event handlers
@@ -1278,20 +1455,23 @@ void wxStyledTextCtrl::OnMouseRightUp(wxMouseEvent& evt) {
}
void wxStyledTextCtrl::OnChar(wxKeyEvent& evt) {
int processed = 0;
long key = evt.KeyCode();
if ((key > WXK_ESCAPE) &&
(key != WXK_DELETE) && (key < 255) &&
!evt.ControlDown() && !evt.AltDown()) {
m_swx->DoAddChar(key);
processed = true;
}
else {
key = toupper(key);
processed = m_swx->DoKeyDown(key, evt.ShiftDown(),
evt.ControlDown(), evt.AltDown());
evt.Skip();
}
}
void wxStyledTextCtrl::OnKeyDown(wxKeyEvent& evt) {
long key = evt.KeyCode();
key = toupper(key);
int processed = m_swx->DoKeyDown(key, evt.ShiftDown(),
evt.ControlDown(), evt.AltDown());
if (! processed)
evt.Skip();
}
@@ -1319,9 +1499,15 @@ void wxStyledTextCtrl::OnMenu(wxCommandEvent& evt) {
}
void wxStyledTextCtrl::OnListBox(wxCommandEvent& evt) {
m_swx->DoOnListBox();
}
//----------------------------------------------------------------------
// Turn notifications from Scintilla into events
void wxStyledTextCtrl::NotifyChange() {
wxStyledTextEvent evt(wxEVT_STC_CHANGE, GetId());
GetEventHandler()->ProcessEvent(evt);
@@ -1375,7 +1561,8 @@ void wxStyledTextCtrl::NotifyParent(SCNotification* _scn) {
evt.SetModifiers(scn.modifiers);
if (eventType == wxEVT_STC_MODIFIED) {
evt.SetModificationType(scn.modificationType);
evt.SetText(scn.text);
if (scn.text)
evt.SetText(wxString(scn.text, scn.length));
evt.SetLength(scn.length);
evt.SetLinesAdded(scn.linesAdded);
evt.SetLine(scn.line);