You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3032 lines
72 KiB
3032 lines
72 KiB
// This module implements the "official" high-level API of the TQt port of
|
|
// Scintilla. It is modelled on TQTextEdit - a method of the same name should
|
|
// behave in the same way.
|
|
//
|
|
// Copyright (c) 2006
|
|
// Riverbank Computing Limited <info@riverbankcomputing.co.uk>
|
|
//
|
|
// This file is part of TQScintilla.
|
|
//
|
|
// This copy of TQScintilla is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation; either version 2, or (at your option) any
|
|
// later version.
|
|
//
|
|
// TQScintilla is supplied in the hope that it will be useful, but WITHOUT ANY
|
|
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
// details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License along with
|
|
// TQScintilla; see the file LICENSE. If not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
|
|
#include <string.h>
|
|
#include <tqapplication.h>
|
|
#include <tqcolor.h>
|
|
|
|
#include "qextscintilla.h"
|
|
#include "qextscintillalexer.h"
|
|
#include "qextscintillaapis.h"
|
|
#include "qextscintillacommandset.h"
|
|
|
|
|
|
// Make sure these match the values in Scintilla.h. We don't #include that
|
|
// file because it just causes more clashes.
|
|
#define KEYWORDSET_MAX 8
|
|
#define MARKER_MAX 31
|
|
|
|
|
|
// The default fold margin width.
|
|
static const int defaultFoldMarginWidth = 14;
|
|
|
|
// The default set of characters that make up a word.
|
|
static const char *defaultWordChars = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
|
|
|
|
|
// The ctor.
|
|
QextScintilla::QextScintilla(TQWidget *parent,const char *name,WFlags f)
|
|
: QextScintillaBase(parent,name,f), allocatedMarkers(0), oldPos(-1),
|
|
selText(FALSE), fold(NoFoldStyle), autoInd(FALSE),
|
|
braceMode(NoBraceMatch), acSource(AcsDocument), acThresh(-1),
|
|
acStart(""), acAPIs(0), ctAPIs(0), maxCallTips(-1),
|
|
showSingle(FALSE), modified(FALSE), explicit_fillups(FALSE),
|
|
fillups_enabled(FALSE), saved_fillups("")
|
|
{
|
|
connect(this,TQT_SIGNAL(SCN_MODIFYATTEMPTRO()),
|
|
TQT_SIGNAL(modificationAttempted()));
|
|
|
|
connect(this,TQT_SIGNAL(SCN_MODIFIED(int,int,const char *,int,int,int,int,int)),
|
|
TQT_SLOT(handleModified(int,int,const char *,int,int,int,int,int)));
|
|
connect(this,TQT_SIGNAL(SCN_CALLTIPCLICK(int)),
|
|
TQT_SLOT(handleCallTipClick(int)));
|
|
connect(this,TQT_SIGNAL(SCN_CHARADDED(int)),
|
|
TQT_SLOT(handleCharAdded(int)));
|
|
connect(this,TQT_SIGNAL(SCN_MARGINCLICK(int,int,int)),
|
|
TQT_SLOT(handleMarginClick(int,int,int)));
|
|
connect(this,TQT_SIGNAL(SCN_SAVEPOINTREACHED()),
|
|
TQT_SLOT(handleSavePointReached()));
|
|
connect(this,TQT_SIGNAL(SCN_SAVEPOINTLEFT()),
|
|
TQT_SLOT(handleSavePointLeft()));
|
|
connect(this,TQT_SIGNAL(SCN_UPDATEUI()),
|
|
TQT_SLOT(handleUpdateUI()));
|
|
connect(this,TQT_SIGNAL(TQSCN_SELCHANGED(bool)),
|
|
TQT_SLOT(handleSelectionChanged(bool)));
|
|
connect(this,TQT_SIGNAL(SCN_USERLISTSELECTION(const char *,int)),
|
|
TQT_SLOT(handleUserListSelection(const char *,int)));
|
|
|
|
// Set the default font.
|
|
setFont(TQApplication::font());
|
|
|
|
// Set the default fore and background colours.
|
|
TQColorGroup cg = TQApplication::palette().active();
|
|
setColor(cg.text());
|
|
setPaper(cg.base());
|
|
|
|
#if defined(Q_OS_WIN)
|
|
setEolMode(EolWindows);
|
|
#elif defined(Q_OS_MAC)
|
|
setEolMode(EolMac);
|
|
#else
|
|
setEolMode(EolUnix);
|
|
#endif
|
|
|
|
// Capturing the mouse seems to cause problems on multi-head systems.
|
|
// TQt should do the right thing anyway.
|
|
SendScintilla(SCI_SETMOUSEDOWNCAPTURES,0UL);
|
|
|
|
SendScintilla(SCI_SETPROPERTY,"fold","1");
|
|
|
|
setMatchedBraceForegroundColor(blue);
|
|
setUnmatchedBraceForegroundColor(red);
|
|
|
|
setLexer();
|
|
|
|
// Set the visible policy. These are the same as SciTE's defaults
|
|
// which, presumably, are sensible.
|
|
SendScintilla(SCI_SETVISIBLEPOLICY,VISIBLE_STRICT|VISIBLE_SLOP,4);
|
|
|
|
// Create the standard command set.
|
|
stdCmds = new QextScintillaCommandSet(this);
|
|
|
|
doc.display(this,0);
|
|
}
|
|
|
|
|
|
// The dtor.
|
|
QextScintilla::~QextScintilla()
|
|
{
|
|
doc.undisplay(this);
|
|
delete stdCmds;
|
|
}
|
|
|
|
|
|
// Return the current text colour.
|
|
TQColor QextScintilla::color() const
|
|
{
|
|
return nl_text_colour;
|
|
}
|
|
|
|
|
|
// Set the text colour.
|
|
void QextScintilla::setColor(const TQColor &c)
|
|
{
|
|
if (lex.isNull())
|
|
{
|
|
// Assume style 0 applies to everything so that we don't need to use
|
|
// SCI_STYLECLEARALL which clears everything.
|
|
SendScintilla(SCI_STYLESETFORE, 0, c);
|
|
nl_text_colour = c;
|
|
}
|
|
}
|
|
|
|
|
|
// Return the current paper colour.
|
|
TQColor QextScintilla::paper() const
|
|
{
|
|
return nl_paper_colour;
|
|
}
|
|
|
|
|
|
// Set the paper colour.
|
|
void QextScintilla::setPaper(const TQColor &c)
|
|
{
|
|
if (lex.isNull())
|
|
{
|
|
// Assume style 0 applies to everything so that we don't need to use
|
|
// SCI_STYLECLEARALL which clears everything. We still have to set the
|
|
// default style as well for the background without any text.
|
|
SendScintilla(SCI_STYLESETBACK, 0, c);
|
|
SendScintilla(SCI_STYLESETBACK, STYLE_DEFAULT, c);
|
|
nl_paper_colour = c;
|
|
}
|
|
}
|
|
|
|
|
|
// Set the default font.
|
|
void QextScintilla::setFont(const TQFont &f)
|
|
{
|
|
if (lex.isNull())
|
|
{
|
|
// Assume style 0 applies to everything so that we don't need to use
|
|
// SCI_STYLECLEARALL which clears everything.
|
|
setStylesFont(f, 0);
|
|
nl_font = f;
|
|
}
|
|
}
|
|
|
|
|
|
// Enable/disable auto-indent.
|
|
void QextScintilla::setAutoIndent(bool autoindent)
|
|
{
|
|
autoInd = autoindent;
|
|
}
|
|
|
|
|
|
// Set the brace matching mode.
|
|
void QextScintilla::setBraceMatching(BraceMatch bm)
|
|
{
|
|
braceMode = bm;
|
|
}
|
|
|
|
|
|
// Handle the addition of a character.
|
|
void QextScintilla::handleCharAdded(int ch)
|
|
{
|
|
// Ignore if there is a selection.
|
|
long pos = SendScintilla(SCI_GETSELECTIONSTART);
|
|
|
|
if (pos != SendScintilla(SCI_GETSELECTIONEND) || pos == 0)
|
|
return;
|
|
|
|
// If auto-completion is already active then see if this character is a
|
|
// start character. If it is then create a new list which will be a
|
|
// subset of the current one. The case where it isn't a start
|
|
// character seem to be handled correctly elsewhere.
|
|
if (isListActive())
|
|
{
|
|
if (isAutoCStartChar(ch))
|
|
{
|
|
cancelList();
|
|
startAutoCompletion(acSource, FALSE, FALSE);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// Handle call tips.
|
|
if (strchr("(),", ch) != NULL)
|
|
callTip();
|
|
|
|
// Handle auto-indentation.
|
|
if (autoInd)
|
|
if (lex.isNull() || (lex -> autoIndentStyle() & AiMaintain))
|
|
maintainIndentation(ch,pos);
|
|
else
|
|
autoIndentation(ch,pos);
|
|
|
|
// See if we might want to start auto-completion.
|
|
if (!isCallTipActive())
|
|
if (isAutoCStartChar(ch))
|
|
startAutoCompletion(acSource, FALSE, FALSE);
|
|
else if (acThresh >= 1 && isWordChar(ch))
|
|
startAutoCompletion(acSource, TRUE, FALSE);
|
|
}
|
|
|
|
|
|
// See if a call tip is active.
|
|
bool QextScintilla::isCallTipActive()
|
|
{
|
|
return SendScintilla(SCI_CALLTIPACTIVE);
|
|
}
|
|
|
|
|
|
// Handle a possible change to any current call tip.
|
|
void QextScintilla::callTip()
|
|
{
|
|
if (!ctAPIs)
|
|
return;
|
|
|
|
long pos = SendScintilla(SCI_GETCURRENTPOS);
|
|
long linenr = SendScintilla(SCI_LINEFROMPOSITION,pos);
|
|
long linelen = SendScintilla(SCI_LINELENGTH,linenr);
|
|
|
|
char *lbuf = new char[linelen + 1];
|
|
|
|
int loff = SendScintilla(SCI_GETCURLINE,linelen + 1,lbuf);
|
|
|
|
int commas = 0, start = -1;
|
|
|
|
// Move backwards through the line looking for the start of the current
|
|
// call tip and working out which argument it is.
|
|
while (loff > 0)
|
|
{
|
|
char ch = lbuf[--loff];
|
|
|
|
if (ch == ',')
|
|
++commas;
|
|
else if (ch == ')')
|
|
{
|
|
int depth = 1;
|
|
|
|
// Ignore everything back to the start of the
|
|
// corresponding parenthesis.
|
|
while (loff > 0)
|
|
{
|
|
ch = lbuf[--loff];
|
|
|
|
if (ch == ')')
|
|
++depth;
|
|
else if (ch == '(' && --depth == 0)
|
|
break;
|
|
}
|
|
}
|
|
else if (ch == '(' && loff > 0)
|
|
{
|
|
if (isWordChar(lbuf[loff - 1]))
|
|
{
|
|
// The parenthesis is preceded by a word so
|
|
// find the start of that word.
|
|
lbuf[loff--] = '\0';
|
|
|
|
while (loff >= 0)
|
|
{
|
|
if (!isWordChar(lbuf[loff]) && !isAutoCStartChar(lbuf[loff]))
|
|
break;
|
|
|
|
--loff;
|
|
}
|
|
|
|
start = loff + 1;
|
|
break;
|
|
}
|
|
|
|
// We are between parentheses that do not correspond to
|
|
// a call tip, so reset the argument count.
|
|
commas = 0;
|
|
}
|
|
}
|
|
|
|
// Cancel any existing call tip.
|
|
SendScintilla(SCI_CALLTIPCANCEL);
|
|
|
|
// Done if there is no new call tip to set.
|
|
if (start < 0)
|
|
{
|
|
delete []lbuf;
|
|
return;
|
|
}
|
|
|
|
TQString ct = ctAPIs -> callTips(&lbuf[start],maxCallTips,commas);
|
|
|
|
delete []lbuf;
|
|
|
|
if (ct.isEmpty())
|
|
return;
|
|
|
|
ctpos = SendScintilla(SCI_POSITIONFROMLINE,linenr) + start;
|
|
|
|
SendScintilla(SCI_CALLTIPSHOW,ctpos,ct.latin1());
|
|
|
|
// Done if there is more than one line in the call tip or there isn't a
|
|
// down arrow at the start.
|
|
if (ct[0] == '\002' || ct.find('\n') >= 0)
|
|
return;
|
|
|
|
// Highlight the current argument.
|
|
int astart;
|
|
|
|
if (commas == 0)
|
|
astart = ct.find('(');
|
|
else
|
|
{
|
|
astart = -1;
|
|
|
|
do
|
|
astart = ct.find(',',astart + 1);
|
|
while (astart >= 0 && --commas > 0);
|
|
}
|
|
|
|
int len = ct.length();
|
|
|
|
if (astart < 0 || ++astart == len)
|
|
return;
|
|
|
|
// The end is at the next comma or unmatched closing parenthesis.
|
|
int aend, depth = 0;
|
|
|
|
for (aend = astart; aend < len; ++aend)
|
|
{
|
|
TQChar ch = ct.at(aend);
|
|
|
|
if (ch == ',' && depth == 0)
|
|
break;
|
|
else if (ch == '(')
|
|
++depth;
|
|
else if (ch == ')')
|
|
{
|
|
if (depth == 0)
|
|
break;
|
|
|
|
--depth;
|
|
}
|
|
}
|
|
|
|
if (astart != aend)
|
|
SendScintilla(SCI_CALLTIPSETHLT,astart,aend);
|
|
}
|
|
|
|
|
|
// Handle a call tip click.
|
|
void QextScintilla::handleCallTipClick(int dir)
|
|
{
|
|
if (!ctAPIs)
|
|
return;
|
|
|
|
TQString ct = ctAPIs -> callTipsNextPrev(dir);
|
|
|
|
if (ct.isNull())
|
|
return;
|
|
|
|
SendScintilla(SCI_CALLTIPSHOW,ctpos,ct.latin1());
|
|
}
|
|
|
|
|
|
// Possibly start auto-completion.
|
|
void QextScintilla::startAutoCompletion(AutoCompletionSource acs,
|
|
bool checkThresh, bool single)
|
|
{
|
|
// Get the current line.
|
|
long len = SendScintilla(SCI_GETCURLINE) + 1;
|
|
|
|
char *line = new char[len];
|
|
|
|
int wend = SendScintilla(SCI_GETCURLINE, len, line);
|
|
|
|
// Find the start of the auto-completion text.
|
|
int wstart = wend;
|
|
bool numeric = true;
|
|
|
|
while (wstart > 0)
|
|
{
|
|
char ch = line[wstart - 1];
|
|
|
|
// Don't auto-complete numbers.
|
|
if (ch < '0' || ch > '9')
|
|
numeric = false;
|
|
|
|
if (!isWordChar(ch) && !isAutoCStartChar(ch))
|
|
break;
|
|
|
|
--wstart;
|
|
}
|
|
|
|
int wlen = wend - wstart;
|
|
|
|
if (numeric || wlen == 0 || (checkThresh && wlen < acThresh))
|
|
return;
|
|
|
|
// Isolate the auto-completion text.
|
|
char *word = &line[wstart];
|
|
line[wend] = '\0';
|
|
|
|
// Generate the string representing the valid words to select from.
|
|
TQStringList wlist;
|
|
bool cs = !SendScintilla(SCI_AUTOCGETIGNORECASE);
|
|
|
|
if (acs == AcsAll || acs == AcsDocument)
|
|
{
|
|
SendScintilla(SCI_SETSEARCHFLAGS,SCFIND_WORDSTART | (cs ? SCFIND_MATCHCASE : 0));
|
|
|
|
long pos = 0;
|
|
long dlen = SendScintilla(SCI_GETLENGTH);
|
|
long caret = SendScintilla(SCI_GETCURRENTPOS);
|
|
TQString root(word);
|
|
|
|
for (;;)
|
|
{
|
|
long fstart;
|
|
|
|
SendScintilla(SCI_SETTARGETSTART,pos);
|
|
SendScintilla(SCI_SETTARGETEND,dlen);
|
|
|
|
if ((fstart = SendScintilla(SCI_SEARCHINTARGET,wlen,word)) < 0)
|
|
break;
|
|
|
|
// Move past the root part.
|
|
pos = fstart + wlen;
|
|
|
|
// Skip if this is the word we are auto-completing.
|
|
if (pos == caret)
|
|
continue;
|
|
|
|
// Get the rest of this word.
|
|
TQString w(root);
|
|
|
|
while (pos < dlen)
|
|
{
|
|
char ch = SendScintilla(SCI_GETCHARAT,pos);
|
|
|
|
if (!isWordChar(ch))
|
|
break;
|
|
|
|
w += ch;
|
|
|
|
++pos;
|
|
}
|
|
|
|
// Add the word if it isn't already there.
|
|
if (wlist.findIndex(w) < 0)
|
|
wlist.append(w);
|
|
}
|
|
}
|
|
|
|
if ((acs == AcsAll || acs == AcsAPIs) && acAPIs)
|
|
acAPIs->autoCompletionList(word, cs, wlist);
|
|
|
|
delete []line;
|
|
|
|
if (wlist.isEmpty())
|
|
return;
|
|
|
|
wlist.sort();
|
|
|
|
const char sep = '\x03';
|
|
|
|
SendScintilla(SCI_AUTOCSETCHOOSESINGLE,single);
|
|
SendScintilla(SCI_AUTOCSETSEPARATOR, sep);
|
|
SendScintilla(SCI_AUTOCSHOW, wlen, wlist.join(TQChar(sep)).latin1());
|
|
}
|
|
|
|
|
|
// Check if a character is an auto-completion start character.
|
|
bool QextScintilla::isAutoCStartChar(char ch) const
|
|
{
|
|
const char *start_chars = 0;
|
|
|
|
if (!lex.isNull())
|
|
start_chars = lex->autoCompletionStartCharacters();
|
|
|
|
if (!start_chars)
|
|
start_chars = acStart;
|
|
|
|
return (strchr(start_chars, ch) != NULL);
|
|
}
|
|
|
|
|
|
// Maintain the indentation of the previous line.
|
|
void QextScintilla::maintainIndentation(char ch,long pos)
|
|
{
|
|
if (ch != '\r' && ch != '\n')
|
|
return;
|
|
|
|
int curr_line = SendScintilla(SCI_LINEFROMPOSITION,pos);
|
|
|
|
// Get the indentation of the preceding non-zero length line.
|
|
int ind = 0;
|
|
|
|
for (int line = curr_line - 1; line >= 0; --line)
|
|
{
|
|
if (SendScintilla(SCI_GETLINEENDPOSITION,line) >
|
|
SendScintilla(SCI_POSITIONFROMLINE,line))
|
|
{
|
|
ind = indentation(line);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (ind > 0)
|
|
autoIndentLine(pos,curr_line,ind);
|
|
}
|
|
|
|
|
|
// Implement auto-indentation.
|
|
void QextScintilla::autoIndentation(char ch,long pos)
|
|
{
|
|
int curr_line = SendScintilla(SCI_LINEFROMPOSITION,pos);
|
|
int ind_width = indentationWidth();
|
|
long curr_line_start = SendScintilla(SCI_POSITIONFROMLINE,curr_line);
|
|
|
|
const char *block_start = lex -> blockStart();
|
|
bool start_single = (block_start && strlen(block_start) == 1);
|
|
|
|
const char *block_end = lex -> blockEnd();
|
|
bool end_single = (block_end && strlen(block_end) == 1);
|
|
|
|
if (end_single && block_end[0] == ch)
|
|
{
|
|
if ((lex -> autoIndentStyle() & AiClosing) && rangeIsWhitespace(curr_line_start,pos - 1))
|
|
autoIndentLine(pos,curr_line,blockIndent(curr_line - 1) - indentationWidth());
|
|
}
|
|
else if (start_single && block_start[0] == ch)
|
|
{
|
|
// De-indent if we have already indented because the previous
|
|
// line was a start of block keyword.
|
|
if ((lex->autoIndentStyle() & AiOpening) && curr_line > 0 && getIndentState(curr_line - 1) == isKeywordStart && rangeIsWhitespace(curr_line_start, pos - 1))
|
|
autoIndentLine(pos,curr_line,blockIndent(curr_line - 1) - indentationWidth());
|
|
}
|
|
else if (ch == '\r' || ch == '\n')
|
|
autoIndentLine(pos,curr_line,blockIndent(curr_line - 1));
|
|
}
|
|
|
|
|
|
// Set the indentation for a line.
|
|
void QextScintilla::autoIndentLine(long pos,int line,int indent)
|
|
{
|
|
if (indent < 0)
|
|
return;
|
|
|
|
long pos_before = SendScintilla(SCI_GETLINEINDENTPOSITION,line);
|
|
SendScintilla(SCI_SETLINEINDENTATION,line,indent);
|
|
long pos_after = SendScintilla(SCI_GETLINEINDENTPOSITION,line);
|
|
long new_pos = -1;
|
|
|
|
if (pos_after > pos_before)
|
|
new_pos = pos + (pos_after - pos_before);
|
|
else if (pos_after < pos_before && pos >= pos_after)
|
|
if (pos >= pos_before)
|
|
new_pos = pos + (pos_after - pos_before);
|
|
else
|
|
new_pos = pos_after;
|
|
|
|
if (new_pos >= 0)
|
|
SendScintilla(SCI_SETSEL,new_pos,new_pos);
|
|
}
|
|
|
|
|
|
// Return the indentation of the block defined by the given line (or something
|
|
// significant before).
|
|
int QextScintilla::blockIndent(int line)
|
|
{
|
|
if (line < 0)
|
|
return 0;
|
|
|
|
// Handle the trvial case.
|
|
if (!lex -> blockStartKeyword() && !lex -> blockStart() && !lex -> blockEnd())
|
|
return indentation(line);
|
|
|
|
int line_limit = line - lex -> blockLookback();
|
|
|
|
if (line_limit < 0)
|
|
line_limit = 0;
|
|
|
|
for (int l = line; l >= line_limit; --l)
|
|
{
|
|
IndentState istate = getIndentState(l);
|
|
|
|
if (istate != isNone)
|
|
{
|
|
int ind_width = indentationWidth();
|
|
int ind = indentation(l);
|
|
|
|
if (istate == isBlockStart)
|
|
{
|
|
if (lex -> autoIndentStyle() & AiOpening)
|
|
ind += ind_width;
|
|
}
|
|
else if (istate == isBlockEnd)
|
|
{
|
|
if (!(lex -> autoIndentStyle() & AiClosing))
|
|
ind -= ind_width;
|
|
|
|
if (ind < 0)
|
|
ind = 0;
|
|
}
|
|
else if (line == l)
|
|
ind += ind_width;
|
|
|
|
return ind;
|
|
}
|
|
}
|
|
|
|
return indentation(line);
|
|
}
|
|
|
|
|
|
// Return TRUE if all characters starting at spos up to, but not including
|
|
// epos, are spaces or tabs.
|
|
bool QextScintilla::rangeIsWhitespace(long spos,long epos)
|
|
{
|
|
while (spos < epos)
|
|
{
|
|
char ch = SendScintilla(SCI_GETCHARAT,spos);
|
|
|
|
if (ch != ' ' && ch != '\t')
|
|
return FALSE;
|
|
|
|
++spos;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// Returns the indentation state of a line.
|
|
QextScintilla::IndentState QextScintilla::getIndentState(int line)
|
|
{
|
|
IndentState istate;
|
|
|
|
// Get the styled text.
|
|
long spos = SendScintilla(SCI_POSITIONFROMLINE,line);
|
|
long epos = SendScintilla(SCI_POSITIONFROMLINE,line + 1);
|
|
|
|
char *text = new char[(epos - spos + 1) * 2];
|
|
|
|
SendScintilla(SCI_GETSTYLEDTEXT,spos,epos,text);
|
|
|
|
int style, bstart_off, bend_off;
|
|
|
|
// Block start/end takes precedence over keywords.
|
|
const char *bstart_words = lex->blockStart(&style);
|
|
bstart_off = findStyledWord(text, style, bstart_words);
|
|
|
|
const char *bend_words = lex->blockEnd(&style);
|
|
bend_off = findStyledWord(text, style, bend_words);
|
|
|
|
// If there is a block start but no block end characters then ignore it
|
|
// unless the block start is the last significant thing on the line,
|
|
// ie. assume Python-like blocking.
|
|
if (bstart_off >= 0 && !bend_words)
|
|
for (int i = bstart_off * 2; text[i] != '\0'; i += 2)
|
|
if (!TQChar(text[i]).isSpace())
|
|
return isNone;
|
|
|
|
if (bstart_off > bend_off)
|
|
istate = isBlockStart;
|
|
else if (bend_off > bstart_off)
|
|
istate = isBlockEnd;
|
|
else
|
|
{
|
|
const char *words = lex->blockStartKeyword(&style);
|
|
|
|
istate = (findStyledWord(text,style,words) >= 0) ? isKeywordStart : isNone;
|
|
}
|
|
|
|
delete[] text;
|
|
|
|
return istate;
|
|
}
|
|
|
|
|
|
// text is a pointer to some styled text (ie. a character byte followed by a
|
|
// style byte). style is a style number. words is a space separated list of
|
|
// words. Returns the position in the text immediately after the last one of
|
|
// the words with the style. The reason we are after the last, and not the
|
|
// first, occurance is that we are looking for words that start and end a block
|
|
// where the latest one is the most significant.
|
|
int QextScintilla::findStyledWord(const char *text,int style,const char *words)
|
|
{
|
|
if (!words)
|
|
return -1;
|
|
|
|
// Find the range of text with the style we are looking for.
|
|
const char *stext;
|
|
|
|
for (stext = text; stext[1] != style; stext += 2)
|
|
if (stext[0] == '\0')
|
|
return -1;
|
|
|
|
// Move to the last character.
|
|
const char *etext = stext;
|
|
|
|
while (etext[2] != '\0')
|
|
etext += 2;
|
|
|
|
// Backtrack until we find the style. There will be one.
|
|
while (etext[1] != style)
|
|
etext -= 2;
|
|
|
|
// Look for each word in turn.
|
|
while (words[0] != '\0')
|
|
{
|
|
// Find the end of the word.
|
|
const char *eword = words;
|
|
|
|
while (eword[1] != ' ' && eword[1] != '\0')
|
|
++eword;
|
|
|
|
// Now search the text backwards.
|
|
const char *wp = eword;
|
|
|
|
for (const char *tp = etext; tp >= stext; tp -= 2)
|
|
{
|
|
if (tp[0] != wp[0] || tp[1] != style)
|
|
{
|
|
// Reset the search.
|
|
wp = eword;
|
|
continue;
|
|
}
|
|
|
|
// See if all the word has matched.
|
|
if (wp-- == words)
|
|
return ((tp - text) / 2) + (eword - words) + 1;
|
|
}
|
|
|
|
// Move to the start of the next word if there is one.
|
|
words = eword + 1;
|
|
|
|
if (words[0] == ' ')
|
|
++words;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
// Return TRUE if the code page is UTF8.
|
|
bool QextScintilla::isUtf8()
|
|
{
|
|
return (SendScintilla(SCI_GETCODEPAGE) == SC_CP_UTF8);
|
|
}
|
|
|
|
|
|
// Set the code page.
|
|
void QextScintilla::setUtf8(bool cp)
|
|
{
|
|
SendScintilla(SCI_SETCODEPAGE,(cp ? SC_CP_UTF8 : 0));
|
|
}
|
|
|
|
|
|
// Return the end-of-line mode.
|
|
QextScintilla::EolMode QextScintilla::eolMode()
|
|
{
|
|
return (EolMode)SendScintilla(SCI_GETEOLMODE);
|
|
}
|
|
|
|
|
|
// Set the end-of-line mode.
|
|
void QextScintilla::setEolMode(EolMode mode)
|
|
{
|
|
SendScintilla(SCI_SETEOLMODE,mode);
|
|
}
|
|
|
|
|
|
// Convert the end-of-lines to a particular mode.
|
|
void QextScintilla::convertEols(EolMode mode)
|
|
{
|
|
SendScintilla(SCI_CONVERTEOLS,mode);
|
|
}
|
|
|
|
|
|
// Return the edge colour.
|
|
TQColor QextScintilla::edgeColor()
|
|
{
|
|
long res = SendScintilla(SCI_GETEDGECOLOUR);
|
|
|
|
return TQColor((int)res, ((int)(res >> 8)) & 0x00ff, ((int)(res >> 16)) & 0x00ff);
|
|
}
|
|
|
|
|
|
// Set the edge colour.
|
|
void QextScintilla::setEdgeColor(const TQColor &col)
|
|
{
|
|
SendScintilla(SCI_SETEDGECOLOUR,col);
|
|
}
|
|
|
|
|
|
// Return the edge column.
|
|
int QextScintilla::edgeColumn()
|
|
{
|
|
return SendScintilla(SCI_GETEDGECOLUMN);
|
|
}
|
|
|
|
|
|
// Set the edge column.
|
|
void QextScintilla::setEdgeColumn(int colnr)
|
|
{
|
|
SendScintilla(SCI_SETEDGECOLUMN,colnr);
|
|
}
|
|
|
|
|
|
// Return the edge mode.
|
|
QextScintilla::EdgeMode QextScintilla::edgeMode()
|
|
{
|
|
return (EdgeMode)SendScintilla(SCI_GETEDGEMODE);
|
|
}
|
|
|
|
|
|
// Set the edge mode.
|
|
void QextScintilla::setEdgeMode(EdgeMode mode)
|
|
{
|
|
SendScintilla(SCI_SETEDGEMODE,mode);
|
|
}
|
|
|
|
|
|
// Return the end-of-line visibility.
|
|
bool QextScintilla::eolVisibility()
|
|
{
|
|
return SendScintilla(SCI_GETVIEWEOL);
|
|
}
|
|
|
|
|
|
// Set the end-of-line visibility.
|
|
void QextScintilla::setEolVisibility(bool visible)
|
|
{
|
|
SendScintilla(SCI_SETVIEWEOL,visible);
|
|
}
|
|
|
|
|
|
// Return the whitespace visibility.
|
|
QextScintilla::WhitespaceVisibility QextScintilla::whitespaceVisibility()
|
|
{
|
|
return (WhitespaceVisibility)SendScintilla(SCI_GETVIEWWS);
|
|
}
|
|
|
|
|
|
// Set the whitespace visibility.
|
|
void QextScintilla::setWhitespaceVisibility(WhitespaceVisibility mode)
|
|
{
|
|
SendScintilla(SCI_SETVIEWWS,mode);
|
|
}
|
|
|
|
|
|
// Return the line wrap mode.
|
|
QextScintilla::WrapMode QextScintilla::wrapMode()
|
|
{
|
|
return (WrapMode)SendScintilla(SCI_GETWRAPMODE);
|
|
}
|
|
|
|
|
|
// Set the line wrap mode.
|
|
void QextScintilla::setWrapMode(WrapMode mode)
|
|
{
|
|
SendScintilla(SCI_SETLAYOUTCACHE, (mode == WrapNone ? SC_CACHE_CARET : SC_CACHE_DOCUMENT));
|
|
SendScintilla(SCI_SETWRAPMODE, mode);
|
|
}
|
|
|
|
|
|
// Set the line wrap visual flags.
|
|
void QextScintilla::setWrapVisualFlags(WrapVisualFlag eflag,
|
|
WrapVisualFlag sflag, int sindent)
|
|
{
|
|
int flags = SC_WRAPVISUALFLAG_NONE;
|
|
int loc = SC_WRAPVISUALFLAGLOC_DEFAULT;
|
|
|
|
if (eflag == WrapFlagByText)
|
|
{
|
|
flags |= SC_WRAPVISUALFLAG_END;
|
|
loc |= SC_WRAPVISUALFLAGLOC_END_BY_TEXT;
|
|
}
|
|
else if (eflag == WrapFlagByBorder)
|
|
flags |= SC_WRAPVISUALFLAG_END;
|
|
|
|
if (sflag == WrapFlagByText)
|
|
{
|
|
flags |= SC_WRAPVISUALFLAG_START;
|
|
loc |= SC_WRAPVISUALFLAGLOC_START_BY_TEXT;
|
|
}
|
|
else if (sflag == WrapFlagByBorder)
|
|
flags |= SC_WRAPVISUALFLAG_START;
|
|
|
|
SendScintilla(SCI_SETWRAPVISUALFLAGS, flags);
|
|
SendScintilla(SCI_SETWRAPVISUALFLAGSLOCATION, loc);
|
|
SendScintilla(SCI_SETWRAPSTARTINDENT, sindent);
|
|
}
|
|
|
|
|
|
// Set the folding style.
|
|
void QextScintilla::setFolding(FoldStyle folding)
|
|
{
|
|
fold = folding;
|
|
|
|
if (folding == NoFoldStyle)
|
|
{
|
|
SendScintilla(SCI_SETMARGINWIDTHN,2,0L);
|
|
return;
|
|
}
|
|
|
|
int mask = SendScintilla(SCI_GETMODEVENTMASK);
|
|
SendScintilla(SCI_SETMODEVENTMASK,mask | SC_MOD_CHANGEFOLD);
|
|
|
|
SendScintilla(SCI_SETFOLDFLAGS,SC_FOLDFLAG_LINEAFTER_CONTRACTED);
|
|
|
|
SendScintilla(SCI_SETMARGINTYPEN,2,(long)SC_MARGIN_SYMBOL);
|
|
SendScintilla(SCI_SETMARGINMASKN,2,SC_MASK_FOLDERS);
|
|
SendScintilla(SCI_SETMARGINSENSITIVEN,2,1);
|
|
|
|
// Set the marker symbols to use.
|
|
switch (folding)
|
|
{
|
|
case PlainFoldStyle:
|
|
setFoldMarker(SC_MARKNUM_FOLDEROPEN,SC_MARK_MINUS);
|
|
setFoldMarker(SC_MARKNUM_FOLDER,SC_MARK_PLUS);
|
|
setFoldMarker(SC_MARKNUM_FOLDERSUB);
|
|
setFoldMarker(SC_MARKNUM_FOLDERTAIL);
|
|
setFoldMarker(SC_MARKNUM_FOLDEREND);
|
|
setFoldMarker(SC_MARKNUM_FOLDEROPENMID);
|
|
setFoldMarker(SC_MARKNUM_FOLDERMIDTAIL);
|
|
|
|
break;
|
|
|
|
case CircledFoldStyle:
|
|
setFoldMarker(SC_MARKNUM_FOLDEROPEN,SC_MARK_CIRCLEMINUS);
|
|
setFoldMarker(SC_MARKNUM_FOLDER,SC_MARK_CIRCLEPLUS);
|
|
setFoldMarker(SC_MARKNUM_FOLDERSUB);
|
|
setFoldMarker(SC_MARKNUM_FOLDERTAIL);
|
|
setFoldMarker(SC_MARKNUM_FOLDEREND);
|
|
setFoldMarker(SC_MARKNUM_FOLDEROPENMID);
|
|
setFoldMarker(SC_MARKNUM_FOLDERMIDTAIL);
|
|
|
|
break;
|
|
|
|
case BoxedFoldStyle:
|
|
setFoldMarker(SC_MARKNUM_FOLDEROPEN,SC_MARK_BOXMINUS);
|
|
setFoldMarker(SC_MARKNUM_FOLDER,SC_MARK_BOXPLUS);
|
|
setFoldMarker(SC_MARKNUM_FOLDERSUB);
|
|
setFoldMarker(SC_MARKNUM_FOLDERTAIL);
|
|
setFoldMarker(SC_MARKNUM_FOLDEREND);
|
|
setFoldMarker(SC_MARKNUM_FOLDEROPENMID);
|
|
setFoldMarker(SC_MARKNUM_FOLDERMIDTAIL);
|
|
|
|
break;
|
|
|
|
case CircledTreeFoldStyle:
|
|
setFoldMarker(SC_MARKNUM_FOLDEROPEN,SC_MARK_CIRCLEMINUS);
|
|
setFoldMarker(SC_MARKNUM_FOLDER,SC_MARK_CIRCLEPLUS);
|
|
setFoldMarker(SC_MARKNUM_FOLDERSUB,SC_MARK_VLINE);
|
|
setFoldMarker(SC_MARKNUM_FOLDERTAIL,SC_MARK_LCORNERCURVE);
|
|
setFoldMarker(SC_MARKNUM_FOLDEREND,SC_MARK_CIRCLEPLUSCONNECTED);
|
|
setFoldMarker(SC_MARKNUM_FOLDEROPENMID,SC_MARK_CIRCLEMINUSCONNECTED);
|
|
setFoldMarker(SC_MARKNUM_FOLDERMIDTAIL,SC_MARK_TCORNERCURVE);
|
|
|
|
break;
|
|
|
|
case BoxedTreeFoldStyle:
|
|
setFoldMarker(SC_MARKNUM_FOLDEROPEN,SC_MARK_BOXMINUS);
|
|
setFoldMarker(SC_MARKNUM_FOLDER,SC_MARK_BOXPLUS);
|
|
setFoldMarker(SC_MARKNUM_FOLDERSUB,SC_MARK_VLINE);
|
|
setFoldMarker(SC_MARKNUM_FOLDERTAIL,SC_MARK_LCORNER);
|
|
setFoldMarker(SC_MARKNUM_FOLDEREND,SC_MARK_BOXPLUSCONNECTED);
|
|
setFoldMarker(SC_MARKNUM_FOLDEROPENMID,SC_MARK_BOXMINUSCONNECTED);
|
|
setFoldMarker(SC_MARKNUM_FOLDERMIDTAIL,SC_MARK_TCORNER);
|
|
|
|
break;
|
|
}
|
|
|
|
SendScintilla(SCI_SETMARGINWIDTHN,2,defaultFoldMarginWidth);
|
|
}
|
|
|
|
|
|
// Set up a folder marker.
|
|
void QextScintilla::setFoldMarker(int marknr,int mark)
|
|
{
|
|
SendScintilla(SCI_MARKERDEFINE,marknr,mark);
|
|
|
|
if (mark != SC_MARK_EMPTY)
|
|
{
|
|
SendScintilla(SCI_MARKERSETFORE,marknr,white);
|
|
SendScintilla(SCI_MARKERSETBACK,marknr,black);
|
|
}
|
|
}
|
|
|
|
|
|
// Handle a click in the fold margin. This is mostly taken from SciTE.
|
|
void QextScintilla::foldClick(int lineClick,int bstate)
|
|
{
|
|
if ((bstate & ShiftButton) && (bstate & ControlButton))
|
|
{
|
|
foldAll();
|
|
return;
|
|
}
|
|
|
|
int levelClick = SendScintilla(SCI_GETFOLDLEVEL,lineClick);
|
|
|
|
if (levelClick & SC_FOLDLEVELHEADERFLAG)
|
|
{
|
|
if (bstate & ShiftButton)
|
|
{
|
|
// Ensure all children are visible.
|
|
SendScintilla(SCI_SETFOLDEXPANDED,lineClick,1);
|
|
foldExpand(lineClick,TRUE,TRUE,100,levelClick);
|
|
}
|
|
else if (bstate & ControlButton)
|
|
{
|
|
if (SendScintilla(SCI_GETFOLDEXPANDED,lineClick))
|
|
{
|
|
// Contract this line and all its children.
|
|
SendScintilla(SCI_SETFOLDEXPANDED,lineClick,0L);
|
|
foldExpand(lineClick,FALSE,TRUE,0,levelClick);
|
|
}
|
|
else
|
|
{
|
|
// Expand this line and all its children.
|
|
SendScintilla(SCI_SETFOLDEXPANDED,lineClick,1);
|
|
foldExpand(lineClick,TRUE,TRUE,100,levelClick);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Toggle this line.
|
|
SendScintilla(SCI_TOGGLEFOLD,lineClick);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Do the hard work of hiding and showing lines. This is mostly taken from
|
|
// SciTE.
|
|
void QextScintilla::foldExpand(int &line,bool doExpand,bool force,
|
|
int visLevels,int level)
|
|
{
|
|
int lineMaxSubord = SendScintilla(SCI_GETLASTCHILD,line,level & SC_FOLDLEVELNUMBERMASK);
|
|
|
|
line++;
|
|
|
|
while (line <= lineMaxSubord)
|
|
{
|
|
if (force)
|
|
{
|
|
if (visLevels > 0)
|
|
SendScintilla(SCI_SHOWLINES,line,line);
|
|
else
|
|
SendScintilla(SCI_HIDELINES,line,line);
|
|
}
|
|
else if (doExpand)
|
|
SendScintilla(SCI_SHOWLINES,line,line);
|
|
|
|
int levelLine = level;
|
|
|
|
if (levelLine == -1)
|
|
levelLine = SendScintilla(SCI_GETFOLDLEVEL,line);
|
|
|
|
if (levelLine & SC_FOLDLEVELHEADERFLAG)
|
|
{
|
|
if (force)
|
|
{
|
|
if (visLevels > 1)
|
|
SendScintilla(SCI_SETFOLDEXPANDED,line,1);
|
|
else
|
|
SendScintilla(SCI_SETFOLDEXPANDED,line,0L);
|
|
|
|
foldExpand(line,doExpand,force,visLevels - 1);
|
|
}
|
|
else if (doExpand)
|
|
{
|
|
if (!SendScintilla(SCI_GETFOLDEXPANDED,line))
|
|
SendScintilla(SCI_SETFOLDEXPANDED,line,1);
|
|
|
|
foldExpand(line,TRUE,force,visLevels - 1);
|
|
}
|
|
else
|
|
foldExpand(line,FALSE,force,visLevels - 1);
|
|
}
|
|
else
|
|
line++;
|
|
}
|
|
}
|
|
|
|
|
|
// Fully expand (if there is any line currently folded) all text. Otherwise,
|
|
// fold all text. This is mostly taken from SciTE.
|
|
void QextScintilla::foldAll(bool children)
|
|
{
|
|
recolor();
|
|
|
|
int maxLine = SendScintilla(SCI_GETLINECOUNT);
|
|
bool expanding = TRUE;
|
|
|
|
for (int lineSeek = 0; lineSeek < maxLine; lineSeek++)
|
|
{
|
|
if (SendScintilla(SCI_GETFOLDLEVEL,lineSeek) & SC_FOLDLEVELHEADERFLAG)
|
|
{
|
|
expanding = !SendScintilla(SCI_GETFOLDEXPANDED,lineSeek);
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (int line = 0; line < maxLine; line++)
|
|
{
|
|
int level = SendScintilla(SCI_GETFOLDLEVEL,line);
|
|
|
|
if (!(level & SC_FOLDLEVELHEADERFLAG))
|
|
continue;
|
|
|
|
if (children ||
|
|
(SC_FOLDLEVELBASE == (level & SC_FOLDLEVELNUMBERMASK)))
|
|
{
|
|
if (expanding)
|
|
{
|
|
SendScintilla(SCI_SETFOLDEXPANDED,line,1);
|
|
foldExpand(line,TRUE,FALSE,0,level);
|
|
line--;
|
|
}
|
|
else
|
|
{
|
|
int lineMaxSubord = SendScintilla(SCI_GETLASTCHILD,line,-1);
|
|
|
|
SendScintilla(SCI_SETFOLDEXPANDED,line,0L);
|
|
|
|
if (lineMaxSubord > line)
|
|
SendScintilla(SCI_HIDELINES,line + 1,lineMaxSubord);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Handle a fold change. This is mostly taken from SciTE.
|
|
void QextScintilla::foldChanged(int line,int levelNow,int levelPrev)
|
|
{
|
|
if (levelNow & SC_FOLDLEVELHEADERFLAG)
|
|
{
|
|
if (!(levelPrev & SC_FOLDLEVELHEADERFLAG))
|
|
SendScintilla(SCI_SETFOLDEXPANDED,line,1);
|
|
}
|
|
else if (levelPrev & SC_FOLDLEVELHEADERFLAG)
|
|
{
|
|
if (!SendScintilla(SCI_GETFOLDEXPANDED,line))
|
|
{
|
|
// Removing the fold from one that has been contracted
|
|
// so should expand. Otherwise lines are left
|
|
// invisible with no way to make them visible.
|
|
foldExpand(line,TRUE,FALSE,0,levelPrev);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Toggle the fold for a line if it contains a fold marker.
|
|
void QextScintilla::foldLine(int line)
|
|
{
|
|
SendScintilla(SCI_TOGGLEFOLD,line);
|
|
}
|
|
|
|
|
|
// Handle the SCN_MODIFIED notification.
|
|
void QextScintilla::handleModified(int pos,int mtype,const char *text,int len,
|
|
int added,int line,int foldNow,int foldPrev)
|
|
{
|
|
if (mtype & SC_MOD_CHANGEFOLD)
|
|
{
|
|
if (fold)
|
|
foldChanged(line,foldNow,foldPrev);
|
|
}
|
|
else if (mtype & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT))
|
|
emit textChanged();
|
|
}
|
|
|
|
|
|
// Zoom in a number of points.
|
|
void QextScintilla::zoomIn(int range)
|
|
{
|
|
zoomTo(SendScintilla(SCI_GETZOOM) + range);
|
|
}
|
|
|
|
|
|
// Zoom in a single point.
|
|
void QextScintilla::zoomIn()
|
|
{
|
|
SendScintilla(SCI_ZOOMIN);
|
|
}
|
|
|
|
|
|
// Zoom out a number of points.
|
|
void QextScintilla::zoomOut(int range)
|
|
{
|
|
zoomTo(SendScintilla(SCI_GETZOOM) - range);
|
|
}
|
|
|
|
|
|
// Zoom out a single point.
|
|
void QextScintilla::zoomOut()
|
|
{
|
|
SendScintilla(SCI_ZOOMOUT);
|
|
}
|
|
|
|
|
|
// Set the zoom to a number of points.
|
|
void QextScintilla::zoomTo(int size)
|
|
{
|
|
if (size < -10)
|
|
size = -10;
|
|
else if (size > 20)
|
|
size = 20;
|
|
|
|
SendScintilla(SCI_SETZOOM,size);
|
|
}
|
|
|
|
|
|
// Find the first occurrence of a string.
|
|
bool QextScintilla::findFirst(const TQString &expr,bool re,bool cs,bool wo,
|
|
bool wrap,bool forward,int line,int index,
|
|
bool show)
|
|
{
|
|
findState.inProgress = FALSE;
|
|
|
|
if (expr.isEmpty())
|
|
return FALSE;
|
|
|
|
findState.expr = expr;
|
|
findState.wrap = wrap;
|
|
findState.forward = forward;
|
|
|
|
findState.flags = (cs ? SCFIND_MATCHCASE : 0) |
|
|
(wo ? SCFIND_WHOLEWORD : 0) |
|
|
(re ? SCFIND_REGEXP : 0);
|
|
|
|
if (line < 0 || index < 0)
|
|
findState.startpos = SendScintilla(SCI_GETCURRENTPOS);
|
|
else
|
|
findState.startpos = posFromLineIndex(line,index);
|
|
|
|
if (forward)
|
|
findState.endpos = SendScintilla(SCI_GETLENGTH);
|
|
else
|
|
findState.endpos = 0;
|
|
|
|
findState.show = show;
|
|
|
|
return doFind();
|
|
}
|
|
|
|
|
|
// Find the next occurrence of a string.
|
|
bool QextScintilla::findNext()
|
|
{
|
|
if (!findState.inProgress)
|
|
return FALSE;
|
|
|
|
return doFind();
|
|
}
|
|
|
|
|
|
// Do the hard work of findFirst() and findNext().
|
|
bool QextScintilla::doFind()
|
|
{
|
|
SendScintilla(SCI_SETSEARCHFLAGS,findState.flags);
|
|
|
|
long pos = simpleFind();
|
|
|
|
// See if it was found. If not and wraparound is wanted, try again.
|
|
if (pos == -1 && findState.wrap)
|
|
{
|
|
if (findState.forward)
|
|
{
|
|
findState.startpos = 0;
|
|
findState.endpos = SendScintilla(SCI_GETLENGTH);
|
|
}
|
|
else
|
|
{
|
|
findState.startpos = SendScintilla(SCI_GETLENGTH);
|
|
findState.endpos = 0;
|
|
}
|
|
|
|
pos = simpleFind();
|
|
}
|
|
|
|
if (pos == -1)
|
|
{
|
|
findState.inProgress = FALSE;
|
|
return FALSE;
|
|
}
|
|
|
|
// It was found.
|
|
long targstart = SendScintilla(SCI_GETTARGETSTART);
|
|
long targend = SendScintilla(SCI_GETTARGETEND);
|
|
|
|
// Ensure the text found is visible if required.
|
|
if (findState.show)
|
|
{
|
|
int startLine = SendScintilla(SCI_LINEFROMPOSITION,targstart);
|
|
int endLine = SendScintilla(SCI_LINEFROMPOSITION,targend);
|
|
|
|
for (int i = startLine; i <= endLine; ++i)
|
|
SendScintilla(SCI_ENSUREVISIBLEENFORCEPOLICY,i);
|
|
}
|
|
|
|
// Now set the selection.
|
|
SendScintilla(SCI_SETSEL,targstart,targend);
|
|
|
|
// Finally adjust the start position so that we don't find the same one
|
|
// again.
|
|
if (findState.forward)
|
|
findState.startpos = targend;
|
|
else if ((findState.startpos = targstart - 1) < 0)
|
|
findState.startpos = 0;
|
|
|
|
findState.inProgress = TRUE;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// Do a simple find between the start and end positions.
|
|
long QextScintilla::simpleFind()
|
|
{
|
|
if (findState.startpos == findState.endpos)
|
|
return -1;
|
|
|
|
SendScintilla(SCI_SETTARGETSTART,findState.startpos);
|
|
SendScintilla(SCI_SETTARGETEND,findState.endpos);
|
|
|
|
long pos;
|
|
|
|
if (isUtf8())
|
|
{
|
|
TQCString s = findState.expr.utf8();
|
|
|
|
pos = SendScintilla(SCI_SEARCHINTARGET,s.length(),s.data());
|
|
}
|
|
else
|
|
{
|
|
const char *s = findState.expr.latin1();
|
|
|
|
pos = SendScintilla(SCI_SEARCHINTARGET,strlen(s),s);
|
|
}
|
|
|
|
return pos;
|
|
}
|
|
|
|
|
|
// Replace the text found with the previous findFirst() or findNext().
|
|
void QextScintilla::replace(const TQString &replaceStr)
|
|
{
|
|
if (!findState.inProgress)
|
|
return;
|
|
|
|
long start = SendScintilla(SCI_GETSELECTIONSTART);
|
|
|
|
SendScintilla(SCI_TARGETFROMSELECTION);
|
|
|
|
long len;
|
|
int cmd = (findState.flags & SCFIND_REGEXP) ? SCI_REPLACETARGETRE : SCI_REPLACETARGET;
|
|
|
|
if (isUtf8())
|
|
len = SendScintilla(cmd,-1,replaceStr.utf8().data());
|
|
else
|
|
len = SendScintilla(cmd,-1,replaceStr.latin1());
|
|
|
|
// Reset the selection.
|
|
SendScintilla(SCI_SETSELECTIONSTART,start);
|
|
SendScintilla(SCI_SETSELECTIONEND,start + len);
|
|
|
|
if (findState.forward)
|
|
findState.startpos = start + len;
|
|
}
|
|
|
|
|
|
// Query the modified state.
|
|
bool QextScintilla::isModified()
|
|
{
|
|
// We don't use SCI_GETMODIFY as it seems to be buggy in Scintilla
|
|
// v1.61.
|
|
return modified;
|
|
}
|
|
|
|
|
|
// Set the modified state.
|
|
void QextScintilla::setModified(bool m)
|
|
{
|
|
if (!m)
|
|
SendScintilla(SCI_SETSAVEPOINT);
|
|
}
|
|
|
|
|
|
// Handle the SCN_MARGINCLICK notification.
|
|
void QextScintilla::handleMarginClick(int pos,int modifiers,int margin)
|
|
{
|
|
int state = 0;
|
|
|
|
if (modifiers & SCMOD_SHIFT)
|
|
state |= ShiftButton;
|
|
|
|
if (modifiers & SCMOD_CTRL)
|
|
state |= ControlButton;
|
|
|
|
if (modifiers & SCMOD_ALT)
|
|
state |= AltButton;
|
|
|
|
int line = SendScintilla(SCI_LINEFROMPOSITION,pos);
|
|
|
|
if (fold && margin == 2)
|
|
foldClick(line,state);
|
|
else
|
|
emit marginClicked(margin,line,(ButtonState)state);
|
|
}
|
|
|
|
|
|
// Handle the SCN_SAVEPOINTREACHED notification.
|
|
void QextScintilla::handleSavePointReached()
|
|
{
|
|
if (modified)
|
|
{
|
|
modified = FALSE;
|
|
emit modificationChanged(FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
// Handle the SCN_SAVEPOINTLEFT notification.
|
|
void QextScintilla::handleSavePointLeft()
|
|
{
|
|
if (!modified)
|
|
{
|
|
modified = TRUE;
|
|
emit modificationChanged(TRUE);
|
|
}
|
|
}
|
|
|
|
|
|
// Handle the TQSCN_SELCHANGED signal.
|
|
void QextScintilla::handleSelectionChanged(bool yes)
|
|
{
|
|
selText = yes;
|
|
|
|
emit copyAvailable(yes);
|
|
emit selectionChanged();
|
|
}
|
|
|
|
|
|
// Get the current selection.
|
|
void QextScintilla::getSelection(int *lineFrom,int *indexFrom,
|
|
int *lineTo,int *indexTo)
|
|
{
|
|
if (selText)
|
|
{
|
|
lineIndexFromPos(SendScintilla(SCI_GETSELECTIONSTART),
|
|
lineFrom,indexFrom);
|
|
lineIndexFromPos(SendScintilla(SCI_GETSELECTIONEND),
|
|
lineTo,indexTo);
|
|
}
|
|
else
|
|
*lineFrom = *indexFrom = *lineTo = *indexTo = -1;
|
|
}
|
|
|
|
|
|
// Sets the current selection.
|
|
void QextScintilla::setSelection(int lineFrom,int indexFrom,
|
|
int lineTo,int indexTo)
|
|
{
|
|
SendScintilla(SCI_SETSELECTIONSTART,posFromLineIndex(lineFrom,indexFrom));
|
|
SendScintilla(SCI_SETSELECTIONEND,posFromLineIndex(lineTo,indexTo));
|
|
}
|
|
|
|
|
|
// Set the background colour of selected text.
|
|
void QextScintilla::setSelectionBackgroundColor(const TQColor &col)
|
|
{
|
|
SendScintilla(SCI_SETSELBACK,1,col);
|
|
|
|
int alpha = tqAlpha(col.rgb());
|
|
|
|
if (alpha < 255)
|
|
SendScintilla(SCI_SETSELALPHA, alpha);
|
|
}
|
|
|
|
|
|
// Set the foreground colour of selected text.
|
|
void QextScintilla::setSelectionForegroundColor(const TQColor &col)
|
|
{
|
|
SendScintilla(SCI_SETSELFORE,1,col);
|
|
}
|
|
|
|
|
|
// Reset the background colour of selected text to the default.
|
|
void QextScintilla::resetSelectionBackgroundColor()
|
|
{
|
|
SendScintilla(SCI_SETSELALPHA, SC_ALPHA_NOALPHA);
|
|
SendScintilla(SCI_SETSELBACK,0UL);
|
|
}
|
|
|
|
|
|
// Reset the foreground colour of selected text to the default.
|
|
void QextScintilla::resetSelectionForegroundColor()
|
|
{
|
|
SendScintilla(SCI_SETSELFORE,0UL);
|
|
}
|
|
|
|
|
|
// Set the width of the caret.
|
|
void QextScintilla::setCaretWidth(int width)
|
|
{
|
|
SendScintilla(SCI_SETCARETWIDTH,width);
|
|
}
|
|
|
|
|
|
// Set the foreground colour of the caret.
|
|
void QextScintilla::setCaretForegroundColor(const TQColor &col)
|
|
{
|
|
SendScintilla(SCI_SETCARETFORE,col);
|
|
}
|
|
|
|
|
|
// Set the background colour of the line containing the caret.
|
|
void QextScintilla::setCaretLineBackgroundColor(const TQColor &col)
|
|
{
|
|
SendScintilla(SCI_SETCARETLINEBACK,col);
|
|
|
|
int alpha = tqAlpha(col.rgb());
|
|
|
|
if (alpha < 255)
|
|
SendScintilla(SCI_SETCARETLINEBACKALPHA, alpha);
|
|
}
|
|
|
|
|
|
// Set the state of the background colour of the line containing the caret.
|
|
void QextScintilla::setCaretLineVisible(bool enable)
|
|
{
|
|
SendScintilla(SCI_SETCARETLINEVISIBLE,enable);
|
|
}
|
|
|
|
|
|
// Query the read-only state.
|
|
bool QextScintilla::isReadOnly()
|
|
{
|
|
return SendScintilla(SCI_GETREADONLY);
|
|
}
|
|
|
|
|
|
// Set the read-only state.
|
|
void QextScintilla::setReadOnly(bool ro)
|
|
{
|
|
SendScintilla(SCI_SETREADONLY,ro);
|
|
}
|
|
|
|
|
|
// Append the given text.
|
|
void QextScintilla::append(const TQString &text)
|
|
{
|
|
bool ro = ensureRW();
|
|
|
|
if (isUtf8())
|
|
{
|
|
TQCString s = text.utf8();
|
|
|
|
SendScintilla(SCI_APPENDTEXT,s.length(),s.data());
|
|
}
|
|
else
|
|
{
|
|
const char *s = text.latin1();
|
|
|
|
SendScintilla(SCI_APPENDTEXT,strlen(s),s);
|
|
}
|
|
|
|
SendScintilla(SCI_EMPTYUNDOBUFFER);
|
|
|
|
setReadOnly(ro);
|
|
}
|
|
|
|
|
|
// Insert the given text at the current position.
|
|
void QextScintilla::insert(const TQString &text)
|
|
{
|
|
bool ro = ensureRW();
|
|
|
|
SendScintilla(SCI_BEGINUNDOACTION);
|
|
|
|
if (isUtf8())
|
|
SendScintilla(SCI_INSERTTEXT,-1,text.utf8().data());
|
|
else
|
|
SendScintilla(SCI_INSERTTEXT,-1,text.latin1());
|
|
|
|
SendScintilla(SCI_ENDUNDOACTION);
|
|
|
|
setReadOnly(ro);
|
|
}
|
|
|
|
|
|
// Insert the given text at the given position.
|
|
void QextScintilla::insertAt(const TQString &text,int line,int index)
|
|
{
|
|
bool ro = ensureRW();
|
|
long position = posFromLineIndex(line,index);
|
|
|
|
SendScintilla(SCI_BEGINUNDOACTION);
|
|
|
|
if (isUtf8())
|
|
SendScintilla(SCI_INSERTTEXT,position,text.utf8().data());
|
|
else
|
|
SendScintilla(SCI_INSERTTEXT,position,text.latin1());
|
|
|
|
SendScintilla(SCI_ENDUNDOACTION);
|
|
|
|
setReadOnly(ro);
|
|
}
|
|
|
|
|
|
// Begin a sequence of undoable actions.
|
|
void QextScintilla::beginUndoAction()
|
|
{
|
|
SendScintilla(SCI_BEGINUNDOACTION);
|
|
}
|
|
|
|
|
|
// End a sequence of undoable actions.
|
|
void QextScintilla::endUndoAction()
|
|
{
|
|
SendScintilla(SCI_ENDUNDOACTION);
|
|
}
|
|
|
|
|
|
// Redo a sequence of actions.
|
|
void QextScintilla::redo()
|
|
{
|
|
SendScintilla(SCI_REDO);
|
|
}
|
|
|
|
|
|
// Undo a sequence of actions.
|
|
void QextScintilla::undo()
|
|
{
|
|
SendScintilla(SCI_UNDO);
|
|
}
|
|
|
|
|
|
// See if there is something to redo.
|
|
bool QextScintilla::isRedoAvailable()
|
|
{
|
|
return SendScintilla(SCI_CANREDO);
|
|
}
|
|
|
|
|
|
// See if there is something to undo.
|
|
bool QextScintilla::isUndoAvailable()
|
|
{
|
|
return SendScintilla(SCI_CANUNDO);
|
|
}
|
|
|
|
|
|
// Return the number of lines.
|
|
int QextScintilla::lines()
|
|
{
|
|
return SendScintilla(SCI_GETLINECOUNT);
|
|
}
|
|
|
|
|
|
// Return the line at a position.
|
|
int QextScintilla::lineAt(const TQPoint &pos)
|
|
{
|
|
long chpos = SendScintilla(SCI_POSITIONFROMPOINTCLOSE,pos.x(),pos.y());
|
|
|
|
if (chpos < 0)
|
|
return -1;
|
|
|
|
return SendScintilla(SCI_LINEFROMPOSITION,chpos);
|
|
}
|
|
|
|
|
|
// Return the length of a line.
|
|
int QextScintilla::lineLength(int line)
|
|
{
|
|
if (line < 0 || line >= SendScintilla(SCI_GETLINECOUNT))
|
|
return -1;
|
|
|
|
return SendScintilla(SCI_LINELENGTH,line);
|
|
}
|
|
|
|
|
|
// Return the length of the current text.
|
|
int QextScintilla::length()
|
|
{
|
|
return SendScintilla(SCI_GETTEXTLENGTH);
|
|
}
|
|
|
|
|
|
// Remove any selected text.
|
|
void QextScintilla::removeSelectedText()
|
|
{
|
|
SendScintilla(SCI_REPLACESEL,"");
|
|
}
|
|
|
|
|
|
// Return the current selected text.
|
|
TQString QextScintilla::selectedText()
|
|
{
|
|
if (!selText)
|
|
return TQString();
|
|
|
|
// Scintilla doesn't tell us the length of the selected text so we use
|
|
// the length of the whole document.
|
|
char *buf = new char[length() + 1];
|
|
|
|
SendScintilla(SCI_GETSELTEXT,buf);
|
|
|
|
TQString qs = convertText(buf);
|
|
delete[] buf;
|
|
|
|
return qs;
|
|
}
|
|
|
|
|
|
// Return the current text.
|
|
TQString QextScintilla::text()
|
|
{
|
|
int buflen = length() + 1;
|
|
char *buf = new char[buflen];
|
|
|
|
SendScintilla(SCI_GETTEXT,buflen,buf);
|
|
|
|
TQString qs = convertText(buf);
|
|
delete[] buf;
|
|
|
|
return qs;
|
|
}
|
|
|
|
|
|
// Return the text of a line.
|
|
TQString QextScintilla::text(int line)
|
|
{
|
|
int line_len = lineLength(line);
|
|
|
|
if (line_len < 1)
|
|
return TQString();
|
|
|
|
char *buf = new char[line_len + 1];
|
|
|
|
SendScintilla(SCI_GETLINE,line,buf);
|
|
buf[line_len] = '\0';
|
|
|
|
TQString qs = convertText(buf);
|
|
delete[] buf;
|
|
|
|
return qs;
|
|
}
|
|
|
|
|
|
// Set the given text.
|
|
void QextScintilla::setText(const TQString &text)
|
|
{
|
|
bool ro = ensureRW();
|
|
|
|
if (isUtf8())
|
|
SendScintilla(SCI_SETTEXT,text.utf8().data());
|
|
else
|
|
SendScintilla(SCI_SETTEXT,text.latin1());
|
|
|
|
SendScintilla(SCI_EMPTYUNDOBUFFER);
|
|
|
|
setReadOnly(ro);
|
|
}
|
|
|
|
|
|
// Get the cursor position
|
|
void QextScintilla::getCursorPosition(int *line,int *index)
|
|
{
|
|
long pos = SendScintilla(SCI_GETCURRENTPOS);
|
|
long lin = SendScintilla(SCI_LINEFROMPOSITION,pos);
|
|
long linpos = SendScintilla(SCI_POSITIONFROMLINE,lin);
|
|
|
|
*line = lin;
|
|
*index = pos - linpos;
|
|
}
|
|
|
|
|
|
// Set the cursor position
|
|
void QextScintilla::setCursorPosition(int line,int index)
|
|
{
|
|
SendScintilla(SCI_GOTOPOS,posFromLineIndex(line,index));
|
|
}
|
|
|
|
|
|
// Ensure the cursor is visible.
|
|
void QextScintilla::ensureCursorVisible()
|
|
{
|
|
SendScintilla(SCI_SCROLLCARET);
|
|
}
|
|
|
|
|
|
// Ensure a line is visible.
|
|
void QextScintilla::ensureLineVisible(int line)
|
|
{
|
|
SendScintilla(SCI_ENSUREVISIBLEENFORCEPOLICY,line);
|
|
}
|
|
|
|
|
|
// Copy text to the clipboard.
|
|
void QextScintilla::copy()
|
|
{
|
|
SendScintilla(SCI_COPY);
|
|
}
|
|
|
|
|
|
// Cut text to the clipboard.
|
|
void QextScintilla::cut()
|
|
{
|
|
SendScintilla(SCI_CUT);
|
|
}
|
|
|
|
|
|
// Paste text from the clipboard.
|
|
void QextScintilla::paste()
|
|
{
|
|
SendScintilla(SCI_PASTE);
|
|
}
|
|
|
|
|
|
// Select all text, or deselect any selected text.
|
|
void QextScintilla::selectAll(bool select)
|
|
{
|
|
if (selText)
|
|
SendScintilla(SCI_SETANCHOR,SendScintilla(SCI_GETCURRENTPOS));
|
|
else
|
|
SendScintilla(SCI_SELECTALL);
|
|
}
|
|
|
|
|
|
// Delete all text.
|
|
void QextScintilla::clear()
|
|
{
|
|
bool ro = ensureRW();
|
|
|
|
SendScintilla(SCI_BEGINUNDOACTION);
|
|
SendScintilla(SCI_CLEARALL);
|
|
SendScintilla(SCI_ENDUNDOACTION);
|
|
|
|
setReadOnly(ro);
|
|
}
|
|
|
|
|
|
// Return the indentation of a line.
|
|
int QextScintilla::indentation(int line)
|
|
{
|
|
return SendScintilla(SCI_GETLINEINDENTATION,line);
|
|
}
|
|
|
|
|
|
// Set the indentation of a line.
|
|
void QextScintilla::setIndentation(int line,int indentation)
|
|
{
|
|
SendScintilla(SCI_BEGINUNDOACTION);
|
|
SendScintilla(SCI_SETLINEINDENTATION,line,indentation);
|
|
SendScintilla(SCI_ENDUNDOACTION);
|
|
}
|
|
|
|
|
|
// Indent a line.
|
|
void QextScintilla::indent(int line)
|
|
{
|
|
setIndentation(line,indentation(line) + indentWidth());
|
|
}
|
|
|
|
|
|
// Unindent a line.
|
|
void QextScintilla::unindent(int line)
|
|
{
|
|
int newIndent = indentation(line) - indentWidth();
|
|
|
|
if (newIndent < 0)
|
|
newIndent = 0;
|
|
|
|
setIndentation(line,newIndent);
|
|
}
|
|
|
|
|
|
// Return the indentation of the current line.
|
|
int QextScintilla::currentIndent()
|
|
{
|
|
return indentation(SendScintilla(SCI_LINEFROMPOSITION,SendScintilla(SCI_GETCURRENTPOS)));
|
|
}
|
|
|
|
|
|
// Return the current indentation width.
|
|
int QextScintilla::indentWidth()
|
|
{
|
|
int w = indentationWidth();
|
|
|
|
if (w == 0)
|
|
w = tabWidth();
|
|
|
|
return w;
|
|
}
|
|
|
|
|
|
// Return the state of indentation guides.
|
|
bool QextScintilla::indentationGuides()
|
|
{
|
|
return SendScintilla(SCI_GETINDENTATIONGUIDES);
|
|
}
|
|
|
|
|
|
// Enable and disable indentation guides.
|
|
void QextScintilla::setIndentationGuides(bool enable)
|
|
{
|
|
SendScintilla(SCI_SETINDENTATIONGUIDES,enable);
|
|
}
|
|
|
|
|
|
// Set the background colour of indentation guides.
|
|
void QextScintilla::setIndentationGuidesBackgroundColor(const TQColor &col)
|
|
{
|
|
SendScintilla(SCI_STYLESETBACK,STYLE_INDENTGUIDE,col);
|
|
}
|
|
|
|
|
|
// Set the foreground colour of indentation guides.
|
|
void QextScintilla::setIndentationGuidesForegroundColor(const TQColor &col)
|
|
{
|
|
SendScintilla(SCI_STYLESETFORE,STYLE_INDENTGUIDE,col);
|
|
}
|
|
|
|
|
|
// Return the indentation width.
|
|
int QextScintilla::indentationWidth()
|
|
{
|
|
return SendScintilla(SCI_GETINDENT);
|
|
}
|
|
|
|
|
|
// Set the indentation width.
|
|
void QextScintilla::setIndentationWidth(int width)
|
|
{
|
|
SendScintilla(SCI_SETINDENT,width);
|
|
}
|
|
|
|
|
|
// Return the tab width.
|
|
int QextScintilla::tabWidth()
|
|
{
|
|
return SendScintilla(SCI_GETTABWIDTH);
|
|
}
|
|
|
|
|
|
// Set the tab width.
|
|
void QextScintilla::setTabWidth(int width)
|
|
{
|
|
SendScintilla(SCI_SETTABWIDTH,width);
|
|
}
|
|
|
|
|
|
// Return the effect of the backspace key.
|
|
bool QextScintilla::backspaceUnindents()
|
|
{
|
|
return SendScintilla(SCI_GETBACKSPACEUNINDENTS);
|
|
}
|
|
|
|
|
|
// Set the effect of the backspace key.
|
|
void QextScintilla::setBackspaceUnindents(bool unindents)
|
|
{
|
|
SendScintilla(SCI_SETBACKSPACEUNINDENTS,unindents);
|
|
}
|
|
|
|
|
|
// Return the effect of the tab key.
|
|
bool QextScintilla::tabIndents()
|
|
{
|
|
return SendScintilla(SCI_GETTABINDENTS);
|
|
}
|
|
|
|
|
|
// Set the effect of the tab key.
|
|
void QextScintilla::setTabIndents(bool indents)
|
|
{
|
|
SendScintilla(SCI_SETTABINDENTS,indents);
|
|
}
|
|
|
|
|
|
// Return the indentation use of tabs.
|
|
bool QextScintilla::indentationsUseTabs()
|
|
{
|
|
return SendScintilla(SCI_GETUSETABS);
|
|
}
|
|
|
|
|
|
// Set the indentation use of tabs.
|
|
void QextScintilla::setIndentationsUseTabs(bool tabs)
|
|
{
|
|
SendScintilla(SCI_SETUSETABS,tabs);
|
|
}
|
|
|
|
|
|
// Return the state of line numbers in a margin.
|
|
bool QextScintilla::marginLineNumbers(int margin)
|
|
{
|
|
return SendScintilla(SCI_GETMARGINTYPEN,margin);
|
|
}
|
|
|
|
|
|
// Enable and disable line numbers in a margin.
|
|
void QextScintilla::setMarginLineNumbers(int margin,bool lnrs)
|
|
{
|
|
SendScintilla(SCI_SETMARGINTYPEN,margin,lnrs ? SC_MARGIN_NUMBER : 0);
|
|
}
|
|
|
|
|
|
// Return the marker mask of a margin.
|
|
int QextScintilla::marginMarkerMask(int margin)
|
|
{
|
|
return SendScintilla(SCI_GETMARGINMASKN,margin);
|
|
}
|
|
|
|
|
|
// Set the marker mask of a margin.
|
|
void QextScintilla::setMarginMarkerMask(int margin,int mask)
|
|
{
|
|
SendScintilla(SCI_SETMARGINMASKN,margin,mask);
|
|
}
|
|
|
|
|
|
// Return the state of a margin's sensitivity.
|
|
bool QextScintilla::marginSensitivity(int margin)
|
|
{
|
|
return SendScintilla(SCI_GETMARGINSENSITIVEN,margin);
|
|
}
|
|
|
|
|
|
// Enable and disable a margin's sensitivity.
|
|
void QextScintilla::setMarginSensitivity(int margin,bool sens)
|
|
{
|
|
SendScintilla(SCI_SETMARGINSENSITIVEN,margin,sens);
|
|
}
|
|
|
|
|
|
// Return the width of a margin.
|
|
int QextScintilla::marginWidth(int margin)
|
|
{
|
|
return SendScintilla(SCI_GETMARGINWIDTHN,margin);
|
|
}
|
|
|
|
|
|
// Set the width of a margin.
|
|
void QextScintilla::setMarginWidth(int margin,int width)
|
|
{
|
|
SendScintilla(SCI_SETMARGINWIDTHN,margin,width);
|
|
}
|
|
|
|
|
|
// Set the width of a margin to the width of some text.
|
|
void QextScintilla::setMarginWidth(int margin,const TQString &s)
|
|
{
|
|
int width;
|
|
|
|
if (isUtf8())
|
|
width = SendScintilla(SCI_TEXTWIDTH,STYLE_LINENUMBER,s.utf8().data());
|
|
else
|
|
width = SendScintilla(SCI_TEXTWIDTH,STYLE_LINENUMBER,s.latin1());
|
|
|
|
setMarginWidth(margin,width);
|
|
}
|
|
|
|
|
|
// Set the background colour of all margins.
|
|
void QextScintilla::setMarginsBackgroundColor(const TQColor &col)
|
|
{
|
|
handleStylePaperChange(col,STYLE_LINENUMBER);
|
|
}
|
|
|
|
|
|
// Set the foreground colour of all margins.
|
|
void QextScintilla::setMarginsForegroundColor(const TQColor &col)
|
|
{
|
|
handleStyleColorChange(col,STYLE_LINENUMBER);
|
|
}
|
|
|
|
|
|
// Set the font of all margins.
|
|
void QextScintilla::setMarginsFont(const TQFont &f)
|
|
{
|
|
setStylesFont(f,STYLE_LINENUMBER);
|
|
}
|
|
|
|
|
|
// Define a marker based on a symbol.
|
|
int QextScintilla::markerDefine(MarkerSymbol sym,int mnr)
|
|
{
|
|
checkMarker(mnr);
|
|
|
|
if (mnr >= 0)
|
|
SendScintilla(SCI_MARKERDEFINE,mnr,static_cast<long>(sym));
|
|
|
|
return mnr;
|
|
}
|
|
|
|
|
|
// Define a marker based on a character.
|
|
int QextScintilla::markerDefine(char ch,int mnr)
|
|
{
|
|
checkMarker(mnr);
|
|
|
|
if (mnr >= 0)
|
|
SendScintilla(SCI_MARKERDEFINE,mnr,static_cast<long>(SC_MARK_CHARACTER) + ch);
|
|
|
|
return mnr;
|
|
}
|
|
|
|
|
|
// Define a marker based on a TQPixmap.
|
|
int QextScintilla::markerDefine(const TQPixmap *pm,int mnr)
|
|
{
|
|
checkMarker(mnr);
|
|
|
|
if (mnr >= 0)
|
|
SendScintilla(SCI_MARKERDEFINEPIXMAP,mnr,pm);
|
|
|
|
return mnr;
|
|
}
|
|
|
|
|
|
// Add a marker to a line.
|
|
int QextScintilla::markerAdd(int linenr,int mnr)
|
|
{
|
|
if (mnr < 0 || mnr > MARKER_MAX || (allocatedMarkers & (1 << mnr)) == 0)
|
|
return -1;
|
|
|
|
return SendScintilla(SCI_MARKERADD,linenr,mnr);
|
|
}
|
|
|
|
|
|
// Get the marker mask for a line.
|
|
unsigned QextScintilla::markersAtLine(int linenr)
|
|
{
|
|
return SendScintilla(SCI_MARKERGET,linenr);
|
|
}
|
|
|
|
|
|
// Delete a marker from a line.
|
|
void QextScintilla::markerDelete(int linenr,int mnr)
|
|
{
|
|
if (mnr <= MARKER_MAX)
|
|
{
|
|
if (mnr < 0)
|
|
{
|
|
unsigned am = allocatedMarkers;
|
|
|
|
for (int m = 0; m <= MARKER_MAX; ++m)
|
|
{
|
|
if (am & 1)
|
|
SendScintilla(SCI_MARKERDELETE,linenr,m);
|
|
|
|
am >>= 1;
|
|
}
|
|
}
|
|
else if (allocatedMarkers & (1 << mnr))
|
|
SendScintilla(SCI_MARKERDELETE,linenr,mnr);
|
|
}
|
|
}
|
|
|
|
|
|
// Delete a marker from the text.
|
|
void QextScintilla::markerDeleteAll(int mnr)
|
|
{
|
|
if (mnr <= MARKER_MAX)
|
|
{
|
|
if (mnr < 0)
|
|
SendScintilla(SCI_MARKERDELETEALL,-1);
|
|
else if (allocatedMarkers & (1 << mnr))
|
|
SendScintilla(SCI_MARKERDELETEALL,mnr);
|
|
}
|
|
}
|
|
|
|
|
|
// Delete a marker handle from the text.
|
|
void QextScintilla::markerDeleteHandle(int mhandle)
|
|
{
|
|
SendScintilla(SCI_MARKERDELETEHANDLE,mhandle);
|
|
}
|
|
|
|
|
|
// Return the line containing a marker instance.
|
|
int QextScintilla::markerLine(int mhandle)
|
|
{
|
|
return SendScintilla(SCI_MARKERLINEFROMHANDLE,mhandle);
|
|
}
|
|
|
|
|
|
// Search forwards for a marker.
|
|
int QextScintilla::markerFindNext(int linenr,unsigned mask)
|
|
{
|
|
return SendScintilla(SCI_MARKERNEXT,linenr,mask);
|
|
}
|
|
|
|
|
|
// Search backwards for a marker.
|
|
int QextScintilla::markerFindPrevious(int linenr,unsigned mask)
|
|
{
|
|
return SendScintilla(SCI_MARKERPREVIOUS,linenr,mask);
|
|
}
|
|
|
|
|
|
// Set the marker background colour.
|
|
void QextScintilla::setMarkerBackgroundColor(const TQColor &col,int mnr)
|
|
{
|
|
if (mnr <= MARKER_MAX)
|
|
{
|
|
int alpha = tqAlpha(col.rgb());
|
|
|
|
if (mnr < 0)
|
|
{
|
|
unsigned am = allocatedMarkers;
|
|
|
|
for (int m = 0; m <= MARKER_MAX; ++m)
|
|
{
|
|
if (am & 1)
|
|
{
|
|
SendScintilla(SCI_MARKERSETBACK,m,col);
|
|
|
|
if (alpha < 255)
|
|
SendScintilla(SCI_MARKERSETALPHA, m, alpha);
|
|
}
|
|
|
|
am >>= 1;
|
|
}
|
|
}
|
|
else if (allocatedMarkers & (1 << mnr))
|
|
{
|
|
SendScintilla(SCI_MARKERSETBACK,mnr,col);
|
|
|
|
if (alpha < 255)
|
|
SendScintilla(SCI_MARKERSETALPHA, mnr, alpha);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Set the marker foreground colour.
|
|
void QextScintilla::setMarkerForegroundColor(const TQColor &col,int mnr)
|
|
{
|
|
if (mnr <= MARKER_MAX)
|
|
{
|
|
if (mnr < 0)
|
|
{
|
|
unsigned am = allocatedMarkers;
|
|
|
|
for (int m = 0; m <= MARKER_MAX; ++m)
|
|
{
|
|
if (am & 1)
|
|
SendScintilla(SCI_MARKERSETFORE,m,col);
|
|
|
|
am >>= 1;
|
|
}
|
|
}
|
|
else if (allocatedMarkers & (1 << mnr))
|
|
SendScintilla(SCI_MARKERSETFORE,mnr,col);
|
|
}
|
|
}
|
|
|
|
|
|
// Check a marker, allocating a marker number if necessary.
|
|
void QextScintilla::checkMarker(int &mnr)
|
|
{
|
|
if (mnr >= 0)
|
|
{
|
|
// Check the explicit marker number isn't already allocated.
|
|
if (mnr > MARKER_MAX || allocatedMarkers & (1 << mnr))
|
|
mnr = -1;
|
|
}
|
|
else
|
|
{
|
|
unsigned am = allocatedMarkers;
|
|
|
|
// Find the smallest unallocated marker number.
|
|
for (mnr = 0; mnr <= MARKER_MAX; ++mnr)
|
|
{
|
|
if ((am & 1) == 0)
|
|
break;
|
|
|
|
am >>= 1;
|
|
}
|
|
}
|
|
|
|
// Define the marker if it is valid.
|
|
if (mnr >= 0)
|
|
allocatedMarkers |= (1 << mnr);
|
|
}
|
|
|
|
|
|
// Reset the fold margin colours.
|
|
void QextScintilla::resetFoldMarginColors()
|
|
{
|
|
SendScintilla(SCI_SETFOLDMARGINHICOLOUR,0,0L);
|
|
SendScintilla(SCI_SETFOLDMARGINCOLOUR,0,0L);
|
|
}
|
|
|
|
|
|
// Set the fold margin colours.
|
|
void QextScintilla::setFoldMarginColors(const TQColor &fore,const TQColor &back)
|
|
{
|
|
SendScintilla(SCI_SETFOLDMARGINHICOLOUR,1,fore);
|
|
SendScintilla(SCI_SETFOLDMARGINCOLOUR,1,back);
|
|
}
|
|
|
|
|
|
// Set the call tips background colour.
|
|
void QextScintilla::setCallTipsBackgroundColor(const TQColor &col)
|
|
{
|
|
SendScintilla(SCI_CALLTIPSETBACK,col);
|
|
}
|
|
|
|
|
|
// Set the call tips foreground colour.
|
|
void QextScintilla::setCallTipsForegroundColor(const TQColor &col)
|
|
{
|
|
SendScintilla(SCI_CALLTIPSETFORE,col);
|
|
}
|
|
|
|
|
|
// Set the call tips highlight colour.
|
|
void QextScintilla::setCallTipsHighlightColor(const TQColor &col)
|
|
{
|
|
SendScintilla(SCI_CALLTIPSETFOREHLT,col);
|
|
}
|
|
|
|
|
|
// Set the matched brace background colour.
|
|
void QextScintilla::setMatchedBraceBackgroundColor(const TQColor &col)
|
|
{
|
|
SendScintilla(SCI_STYLESETBACK,STYLE_BRACELIGHT,col);
|
|
}
|
|
|
|
|
|
// Set the matched brace foreground colour.
|
|
void QextScintilla::setMatchedBraceForegroundColor(const TQColor &col)
|
|
{
|
|
SendScintilla(SCI_STYLESETFORE,STYLE_BRACELIGHT,col);
|
|
}
|
|
|
|
|
|
// Set the unmatched brace background colour.
|
|
void QextScintilla::setUnmatchedBraceBackgroundColor(const TQColor &col)
|
|
{
|
|
SendScintilla(SCI_STYLESETBACK,STYLE_BRACEBAD,col);
|
|
}
|
|
|
|
|
|
// Set the unmatched brace foreground colour.
|
|
void QextScintilla::setUnmatchedBraceForegroundColor(const TQColor &col)
|
|
{
|
|
SendScintilla(SCI_STYLESETFORE,STYLE_BRACEBAD,col);
|
|
}
|
|
|
|
|
|
// Set the lexer.
|
|
void QextScintilla::setLexer(QextScintillaLexer *lexer)
|
|
{
|
|
// Disconnect any previous lexer.
|
|
if (!lex.isNull())
|
|
{
|
|
lex -> disconnect(this);
|
|
|
|
SendScintilla(SCI_STYLERESETDEFAULT);
|
|
}
|
|
|
|
// Connect up the new lexer.
|
|
lex = lexer;
|
|
|
|
if (lex)
|
|
{
|
|
int bits = SendScintilla(SCI_GETSTYLEBITSNEEDED);
|
|
int nrStyles = 1 << bits;
|
|
|
|
SendScintilla(SCI_SETSTYLEBITS,bits);
|
|
|
|
connect(lex,TQT_SIGNAL(colorChanged(const TQColor &,int)),
|
|
TQT_SLOT(handleStyleColorChange(const TQColor &,int)));
|
|
connect(lex,TQT_SIGNAL(eolFillChanged(bool,int)),
|
|
TQT_SLOT(handleStyleEolFillChange(bool,int)));
|
|
connect(lex,TQT_SIGNAL(fontChanged(const TQFont &,int)),
|
|
TQT_SLOT(handleStyleFontChange(const TQFont &,int)));
|
|
connect(lex,TQT_SIGNAL(paperChanged(const TQColor &,int)),
|
|
TQT_SLOT(handleStylePaperChange(const TQColor &,int)));
|
|
connect(lex,TQT_SIGNAL(propertyChanged(const char *,const char *)),
|
|
TQT_SLOT(handlePropertyChange(const char *,const char *)));
|
|
|
|
SendScintilla(SCI_SETLEXERLANGUAGE,lex -> lexer());
|
|
|
|
// Set the keywords. Scintilla allows for sets numbered 0 to
|
|
// KEYWORDSET_MAX (although the lexers only seem to exploit 0
|
|
// to KEYWORDSET_MAX - 1). We number from 1 in line with
|
|
// SciTE's property files.
|
|
for (int k = 0; k <= KEYWORDSET_MAX; ++k)
|
|
{
|
|
const char *kw = lex -> keywords(k + 1);
|
|
|
|
if (kw)
|
|
SendScintilla(SCI_SETKEYWORDS,k,kw);
|
|
}
|
|
|
|
// Initialise each style.
|
|
for (int s = 0; s < nrStyles; ++s)
|
|
{
|
|
if (lex -> description(s).isNull())
|
|
continue;
|
|
|
|
handleStyleColorChange(lex -> color(s),s);
|
|
handleStyleEolFillChange(lex -> eolFill(s),s);
|
|
handleStyleFontChange(lex -> font(s),s);
|
|
handleStylePaperChange(lex -> paper(s),s);
|
|
}
|
|
|
|
// Initialise the properties.
|
|
lex -> refreshProperties();
|
|
|
|
// Set the auto-completion fillups if they haven't been
|
|
// explcitly set.
|
|
if (fillups_enabled && !explicit_fillups)
|
|
SendScintilla(SCI_AUTOCSETFILLUPS, lex->autoCompletionFillups());
|
|
}
|
|
else
|
|
{
|
|
SendScintilla(SCI_SETLEXER,SCLEX_NULL);
|
|
|
|
setColor(nl_text_colour);
|
|
setPaper(nl_paper_colour);
|
|
setFont(nl_font);
|
|
}
|
|
}
|
|
|
|
|
|
// Get the current lexer.
|
|
QextScintillaLexer *QextScintilla::lexer() const
|
|
{
|
|
return lex;
|
|
}
|
|
|
|
|
|
// Handle a change in lexer style foreground colour.
|
|
void QextScintilla::handleStyleColorChange(const TQColor &c,int style)
|
|
{
|
|
SendScintilla(SCI_STYLESETFORE,style,c);
|
|
}
|
|
|
|
|
|
// Handle a change in lexer style end-of-line fill.
|
|
void QextScintilla::handleStyleEolFillChange(bool eolfill,int style)
|
|
{
|
|
SendScintilla(SCI_STYLESETEOLFILLED,style,eolfill);
|
|
}
|
|
|
|
|
|
// Handle a change in lexer style font.
|
|
void QextScintilla::handleStyleFontChange(const TQFont &f,int style)
|
|
{
|
|
setStylesFont(f,style);
|
|
|
|
if (style == lex->defaultStyle())
|
|
setStylesFont(f, STYLE_DEFAULT);
|
|
|
|
if (style == lex -> braceStyle())
|
|
{
|
|
setStylesFont(f,STYLE_BRACELIGHT);
|
|
setStylesFont(f,STYLE_BRACEBAD);
|
|
}
|
|
}
|
|
|
|
|
|
// Set the font for a style.
|
|
void QextScintilla::setStylesFont(const TQFont &f,int style)
|
|
{
|
|
SendScintilla(SCI_STYLESETFONT,style,f.family().latin1());
|
|
SendScintilla(SCI_STYLESETSIZE,style,f.pointSize());
|
|
SendScintilla(SCI_STYLESETBOLD,style,f.bold());
|
|
SendScintilla(SCI_STYLESETITALIC,style,f.italic());
|
|
SendScintilla(SCI_STYLESETUNDERLINE,style,f.underline());
|
|
}
|
|
|
|
|
|
// Handle a change in lexer style background colour.
|
|
void QextScintilla::handleStylePaperChange(const TQColor &c,int style)
|
|
{
|
|
SendScintilla(SCI_STYLESETBACK,style,c);
|
|
}
|
|
|
|
|
|
// Handle a change in lexer property.
|
|
void QextScintilla::handlePropertyChange(const char *prop,const char *val)
|
|
{
|
|
SendScintilla(SCI_SETPROPERTY,prop,val);
|
|
}
|
|
|
|
|
|
// Handle a change to the user visible user interface.
|
|
void QextScintilla::handleUpdateUI()
|
|
{
|
|
long newPos = SendScintilla(SCI_GETCURRENTPOS);
|
|
|
|
if (newPos != oldPos)
|
|
{
|
|
oldPos = newPos;
|
|
|
|
int line = SendScintilla(SCI_LINEFROMPOSITION,newPos);
|
|
int col = SendScintilla(SCI_GETCOLUMN,newPos);
|
|
|
|
emit cursorPositionChanged(line,col);
|
|
}
|
|
|
|
if (braceMode != NoBraceMatch)
|
|
braceMatch();
|
|
}
|
|
|
|
|
|
// Handle brace matching.
|
|
void QextScintilla::braceMatch()
|
|
{
|
|
long braceAtCaret, braceOpposite;
|
|
|
|
findMatchingBrace(braceAtCaret,braceOpposite,braceMode);
|
|
|
|
if (braceAtCaret >= 0 && braceOpposite < 0)
|
|
{
|
|
SendScintilla(SCI_BRACEBADLIGHT,braceAtCaret);
|
|
SendScintilla(SCI_SETHIGHLIGHTGUIDE,0UL);
|
|
}
|
|
else
|
|
{
|
|
char chBrace = SendScintilla(SCI_GETCHARAT,braceAtCaret);
|
|
|
|
SendScintilla(SCI_BRACEHIGHLIGHT,braceAtCaret,braceOpposite);
|
|
|
|
long columnAtCaret = SendScintilla(SCI_GETCOLUMN,braceAtCaret);
|
|
long columnOpposite = SendScintilla(SCI_GETCOLUMN,braceOpposite);
|
|
|
|
if (chBrace == ':')
|
|
{
|
|
long lineStart = SendScintilla(SCI_LINEFROMPOSITION,braceAtCaret);
|
|
long indentPos = SendScintilla(SCI_GETLINEINDENTPOSITION,lineStart);
|
|
long indentPosNext = SendScintilla(SCI_GETLINEINDENTPOSITION,lineStart + 1);
|
|
|
|
columnAtCaret = SendScintilla(SCI_GETCOLUMN,indentPos);
|
|
|
|
long columnAtCaretNext = SendScintilla(SCI_GETCOLUMN,indentPosNext);
|
|
long indentSize = SendScintilla(SCI_GETINDENT);
|
|
|
|
if (columnAtCaretNext - indentSize > 1)
|
|
columnAtCaret = columnAtCaretNext - indentSize;
|
|
|
|
if (columnOpposite == 0)
|
|
columnOpposite = columnAtCaret;
|
|
}
|
|
|
|
long column = columnAtCaret;
|
|
|
|
if (column > columnOpposite)
|
|
column = columnOpposite;
|
|
|
|
SendScintilla(SCI_SETHIGHLIGHTGUIDE,column);
|
|
}
|
|
}
|
|
|
|
|
|
// Check if the character at a position is a brace.
|
|
long QextScintilla::checkBrace(long pos,int brace_style,bool &colonMode)
|
|
{
|
|
long brace_pos = -1;
|
|
char ch = SendScintilla(SCI_GETCHARAT,pos);
|
|
|
|
if (ch == ':')
|
|
{
|
|
// A bit of a hack.
|
|
if (!lex.isNull() && strcmp(lex -> lexer(),"python") == 0)
|
|
{
|
|
brace_pos = pos;
|
|
colonMode = TRUE;
|
|
}
|
|
}
|
|
else if (ch && strchr("[](){}<>",ch))
|
|
{
|
|
if (brace_style < 0)
|
|
brace_pos = pos;
|
|
else
|
|
{
|
|
int style = SendScintilla(SCI_GETSTYLEAT,pos) & 0x1f;
|
|
|
|
if (style == brace_style)
|
|
brace_pos = pos;
|
|
}
|
|
}
|
|
|
|
return brace_pos;
|
|
}
|
|
|
|
|
|
// Find a brace and it's match. Return TRUE if the current position is inside
|
|
// a pair of braces.
|
|
bool QextScintilla::findMatchingBrace(long &brace,long &other,BraceMatch mode)
|
|
{
|
|
bool colonMode = FALSE;
|
|
int brace_style = (lex.isNull() ? -1 : lex -> braceStyle());
|
|
|
|
brace = -1;
|
|
other = -1;
|
|
|
|
long caretPos = SendScintilla(SCI_GETCURRENTPOS);
|
|
|
|
if (caretPos > 0)
|
|
brace = checkBrace(caretPos - 1,brace_style,colonMode);
|
|
|
|
bool isInside = FALSE;
|
|
|
|
if (brace < 0 && mode == SloppyBraceMatch)
|
|
{
|
|
brace = checkBrace(caretPos,brace_style,colonMode);
|
|
|
|
if (brace >= 0 && !colonMode)
|
|
isInside = TRUE;
|
|
}
|
|
|
|
if (brace >= 0)
|
|
{
|
|
if (colonMode)
|
|
{
|
|
// Find the end of the Python indented block.
|
|
long lineStart = SendScintilla(SCI_LINEFROMPOSITION,brace);
|
|
long lineMaxSubord = SendScintilla(SCI_GETLASTCHILD,lineStart,-1);
|
|
|
|
other = SendScintilla(SCI_GETLINEENDPOSITION,lineMaxSubord);
|
|
}
|
|
else
|
|
other = SendScintilla(SCI_BRACEMATCH,brace);
|
|
|
|
if (other > brace)
|
|
isInside = !isInside;
|
|
}
|
|
|
|
return isInside;
|
|
}
|
|
|
|
|
|
// Move to the matching brace.
|
|
void QextScintilla::moveToMatchingBrace()
|
|
{
|
|
gotoMatchingBrace(FALSE);
|
|
}
|
|
|
|
|
|
// Select to the matching brace.
|
|
void QextScintilla::selectToMatchingBrace()
|
|
{
|
|
gotoMatchingBrace(TRUE);
|
|
}
|
|
|
|
|
|
// Move to the matching brace and optionally select the text.
|
|
void QextScintilla::gotoMatchingBrace(bool select)
|
|
{
|
|
long braceAtCaret;
|
|
long braceOpposite;
|
|
|
|
bool isInside = findMatchingBrace(braceAtCaret,braceOpposite,SloppyBraceMatch);
|
|
|
|
if (braceOpposite >= 0)
|
|
{
|
|
// Convert the character positions into caret positions based
|
|
// on whether the caret position was inside or outside the
|
|
// braces.
|
|
if (isInside)
|
|
{
|
|
if (braceOpposite > braceAtCaret)
|
|
braceAtCaret++;
|
|
else
|
|
braceOpposite++;
|
|
}
|
|
else
|
|
{
|
|
if (braceOpposite > braceAtCaret)
|
|
braceOpposite++;
|
|
else
|
|
braceAtCaret++;
|
|
}
|
|
|
|
ensureLineVisible(SendScintilla(SCI_LINEFROMPOSITION,braceOpposite));
|
|
|
|
if (select)
|
|
SendScintilla(SCI_SETSEL,braceAtCaret,braceOpposite);
|
|
else
|
|
SendScintilla(SCI_SETSEL,braceOpposite,braceOpposite);
|
|
}
|
|
}
|
|
|
|
|
|
// Return a position from a line number and an index within the line.
|
|
long QextScintilla::posFromLineIndex(int line,int index)
|
|
{
|
|
long pos = SendScintilla(SCI_POSITIONFROMLINE,line);
|
|
|
|
// Allow for multi-byte characters.
|
|
for(int i = 0; i < index; i++)
|
|
pos = SendScintilla(SCI_POSITIONAFTER,pos);
|
|
|
|
return pos;
|
|
}
|
|
|
|
|
|
// Return a line number and an index within the line from a position.
|
|
void QextScintilla::lineIndexFromPos(long pos,int *line,int *index)
|
|
{
|
|
long lin = SendScintilla(SCI_LINEFROMPOSITION,pos);
|
|
long linpos = SendScintilla(SCI_POSITIONFROMLINE,lin);
|
|
|
|
*line = lin;
|
|
*index = pos - linpos;
|
|
}
|
|
|
|
|
|
// Convert a Scintilla string to a TQt Unicode string.
|
|
TQString QextScintilla::convertText(const char *s)
|
|
{
|
|
if (isUtf8())
|
|
return TQString::fromUtf8(s);
|
|
|
|
TQString qs;
|
|
|
|
qs.setLatin1(s);
|
|
|
|
return qs;
|
|
}
|
|
|
|
|
|
// Set the source of the auto-completion list.
|
|
void QextScintilla::setAutoCompletionSource(AutoCompletionSource source)
|
|
{
|
|
acSource = source;
|
|
}
|
|
|
|
|
|
// Set the threshold for automatic auto-completion.
|
|
void QextScintilla::setAutoCompletionThreshold(int thresh)
|
|
{
|
|
acThresh = thresh;
|
|
}
|
|
|
|
|
|
// Set the auto-completion start characters.
|
|
void QextScintilla::setAutoCompletionStartCharacters(const char *start)
|
|
{
|
|
acStart = start;
|
|
}
|
|
|
|
|
|
// Set the APIs for auto-completion.
|
|
void QextScintilla::setAutoCompletionAPIs(QextScintillaAPIs *apis)
|
|
{
|
|
acAPIs = apis;
|
|
}
|
|
|
|
|
|
// Explicitly auto-complete from all sources.
|
|
void QextScintilla::autoCompleteFromAll()
|
|
{
|
|
startAutoCompletion(AcsAll, FALSE, showSingle);
|
|
}
|
|
|
|
|
|
// Explicitly auto-complete from the APIs.
|
|
void QextScintilla::autoCompleteFromAPIs()
|
|
{
|
|
startAutoCompletion(AcsAPIs, FALSE, showSingle);
|
|
}
|
|
|
|
|
|
// Explicitly auto-complete from the document.
|
|
void QextScintilla::autoCompleteFromDocument()
|
|
{
|
|
// If we are not in a word then ignore.
|
|
if (currentCharInWord())
|
|
startAutoCompletion(AcsDocument, FALSE, showSingle);
|
|
}
|
|
|
|
|
|
// Return TRUE if the current character (ie. the one before the carat) is part
|
|
// of a word.
|
|
bool QextScintilla::currentCharInWord()
|
|
{
|
|
long pos = SendScintilla(SCI_GETCURRENTPOS);
|
|
|
|
if (pos <= 0)
|
|
return FALSE;
|
|
|
|
return isWordChar(SendScintilla(SCI_GETCHARAT,pos - 1));
|
|
}
|
|
|
|
|
|
// Check if a character can be in a word.
|
|
bool QextScintilla::isWordChar(char ch) const
|
|
{
|
|
const char *word_chars = 0;
|
|
|
|
if (!lex.isNull())
|
|
word_chars = lex->wordCharacters();
|
|
|
|
if (!word_chars)
|
|
word_chars = defaultWordChars;
|
|
|
|
return (strchr(word_chars, ch) != NULL);
|
|
}
|
|
|
|
|
|
// Recolour the document.
|
|
void QextScintilla::recolor(int start,int end)
|
|
{
|
|
SendScintilla(SCI_COLOURISE,start,end);
|
|
}
|
|
|
|
|
|
// Registered an image.
|
|
void QextScintilla::registerImage(int id,const TQPixmap *pm)
|
|
{
|
|
SendScintilla(SCI_REGISTERIMAGE,id,pm);
|
|
}
|
|
|
|
|
|
// Clear all registered images.
|
|
void QextScintilla::clearRegisteredImages()
|
|
{
|
|
SendScintilla(SCI_CLEARREGISTEREDIMAGES);
|
|
}
|
|
|
|
|
|
// Set the fill-up characters for auto-completion.
|
|
void QextScintilla::setAutoCompletionFillups(const char *fillups)
|
|
{
|
|
if (!fillups)
|
|
fillups = "";
|
|
|
|
SendScintilla(SCI_AUTOCSETFILLUPS, fillups);
|
|
fillups_enabled = explicit_fillups = TRUE;
|
|
|
|
// Save them in case we need to reenable them at some point.
|
|
saved_fillups = fillups;
|
|
}
|
|
|
|
|
|
// Enable/disable fill-ups for auto-completion.
|
|
void QextScintilla::setAutoCompletionFillupsEnabled(bool enabled)
|
|
{
|
|
const char *fillups;
|
|
|
|
if (!enabled)
|
|
fillups = "";
|
|
else if (!explicit_fillups && !lex.isNull())
|
|
fillups = lex->autoCompletionFillups();
|
|
else
|
|
fillups = saved_fillups.data();
|
|
|
|
SendScintilla(SCI_AUTOCSETFILLUPS, fillups);
|
|
fillups_enabled = enabled;
|
|
}
|
|
|
|
|
|
// Return the state of fill-ups for auto-completion.
|
|
bool QextScintilla::autoCompletionFillupsEnabled()
|
|
{
|
|
return fillups_enabled;
|
|
}
|
|
|
|
|
|
// Set the case sensitivity for auto-completion.
|
|
void QextScintilla::setAutoCompletionCaseSensitivity(bool cs)
|
|
{
|
|
SendScintilla(SCI_AUTOCSETIGNORECASE,!cs);
|
|
}
|
|
|
|
|
|
// Return the case sensitivity for auto-completion.
|
|
bool QextScintilla::autoCompletionCaseSensitivity()
|
|
{
|
|
return !SendScintilla(SCI_AUTOCGETIGNORECASE);
|
|
}
|
|
|
|
|
|
// Set the replace word mode for auto-completion.
|
|
void QextScintilla::setAutoCompletionReplaceWord(bool replace)
|
|
{
|
|
SendScintilla(SCI_AUTOCSETDROPRESTOFWORD,replace);
|
|
}
|
|
|
|
|
|
// Return the replace word mode for auto-completion.
|
|
bool QextScintilla::autoCompletionReplaceWord()
|
|
{
|
|
return SendScintilla(SCI_AUTOCGETDROPRESTOFWORD);
|
|
}
|
|
|
|
|
|
// Set the single item mode for auto-completion.
|
|
void QextScintilla::setAutoCompletionShowSingle(bool single)
|
|
{
|
|
showSingle = single;
|
|
}
|
|
|
|
|
|
// Return the single item mode for auto-completion.
|
|
bool QextScintilla::autoCompletionShowSingle()
|
|
{
|
|
return showSingle;
|
|
}
|
|
|
|
|
|
// Set the APIs for call tips.
|
|
void QextScintilla::setCallTipsAPIs(QextScintillaAPIs *apis)
|
|
{
|
|
ctAPIs = apis;
|
|
}
|
|
|
|
|
|
// Set maximum number of call tips displayed.
|
|
void QextScintilla::setCallTipsVisible(int nr)
|
|
{
|
|
maxCallTips = nr;
|
|
}
|
|
|
|
|
|
// Set the document to display.
|
|
void QextScintilla::setDocument(const QextScintillaDocument &document)
|
|
{
|
|
if (doc.pdoc != document.pdoc)
|
|
{
|
|
doc.undisplay(this);
|
|
doc.attach(document);
|
|
doc.display(this,&document);
|
|
}
|
|
}
|
|
|
|
|
|
// Ensure the document is read-write and return True if was was read-only.
|
|
bool QextScintilla::ensureRW()
|
|
{
|
|
bool ro = isReadOnly();
|
|
|
|
if (ro)
|
|
setReadOnly(FALSE);
|
|
|
|
return ro;
|
|
}
|
|
|
|
|
|
// Return the number of the first visible line.
|
|
int QextScintilla::firstVisibleLine()
|
|
{
|
|
return SendScintilla(SCI_GETFIRSTVISIBLELINE);
|
|
}
|
|
|
|
|
|
// Return the height in pixels of the text in a particular line.
|
|
int QextScintilla::textHeight(int linenr)
|
|
{
|
|
return SendScintilla(SCI_TEXTHEIGHT, linenr);
|
|
}
|
|
|
|
|
|
// See if auto-completion or user list is active.
|
|
bool QextScintilla::isListActive()
|
|
{
|
|
return SendScintilla(SCI_AUTOCACTIVE);
|
|
}
|
|
|
|
|
|
// Cancel any current auto-completion or user list.
|
|
void QextScintilla::cancelList()
|
|
{
|
|
SendScintilla(SCI_AUTOCCANCEL);
|
|
}
|
|
|
|
|
|
// Display a user list.
|
|
void QextScintilla::showUserList(int id, const TQStringList &list)
|
|
{
|
|
// Sanity check to make sure auto-completion doesn't get confused.
|
|
if (id <= 0)
|
|
return;
|
|
|
|
const char sep = '\x03';
|
|
|
|
SendScintilla(SCI_AUTOCSETSEPARATOR, sep);
|
|
SendScintilla(SCI_USERLISTSHOW, id, list.join(TQChar(sep)).latin1());
|
|
}
|
|
|
|
|
|
// Translate the SCN_USERLISTSELECTION notification into something more useful.
|
|
void QextScintilla::handleUserListSelection(const char *text, int id)
|
|
{
|
|
emit userListActivated(id, TQString(text));
|
|
}
|