import "GoToDialog"
import "Array"
+char * strchrmax(const char * s, int c, int max)
+{
+ int i;
+ char ch;
+ for(i = 0; i < max && (ch = s[i]); i++)
+ if(ch == c)
+ return (char *)s + i;
+ return null;
+}
+
public class SyntaxColorScheme
{
public:
{
public:
subclass(UndoAction) type;
+ bool continued;
+
virtual void Undo(void * data) { type.Undo(this, data); }
virtual void Redo(void * data) { type.Redo(this, data); }
#ifdef _DEBUG
void * data;
int dontRecord;
bool insideRedo;
+ bool recordAsOne;
+ bool firstEvent;
dontRecord = 0;
void Undo()
{
- dontRecord++;
- if(curAction > 0)
+ bool continued = true;
+ while(curAction > 0 && continued)
{
UndoAction action = actions[--curAction];
+ dontRecord++;
+
#ifdef _DEBUG
/*Print("Undoing: ");
action.Print(data);*/
#endif
action.Undo(data);
+ dontRecord--;
+
+ continued = curAction > 0 && actions[curAction-1].continued;
}
- dontRecord--;
}
void Redo()
{
- dontRecord++;
- insideRedo = true;
- if(curAction < count)
+ bool continued = true;
+ while(curAction < count && continued)
{
UndoAction action = actions[curAction];
+ continued = action.continued;
+ dontRecord++;
+ insideRedo = true;
+
curAction++;
#ifdef _DEBUG
/*Print("Redoing: ");
action.Print(data);*/
#endif
action.Redo(data);
+
+ insideRedo = false;
+ dontRecord--;
}
- insideRedo = false;
- dontRecord--;
}
void Record(UndoAction action)
/*Print("Recording: ");
action.Print(data);*/
#endif
+ if(recordAsOne)
+ {
+ if(!firstEvent && count > 0)
+ actions[count-1].continued = true;
+ firstEvent = false;
+ }
actions[count++] = action;
curAction = count;
int length;
EditBox editBox;
public:
- property char * text
+ property const char * text
{
set
{
public enum EditBoxFindResult { notFound, found, wrapped };
-static char * keyWords1[] =
+static const char * keyWords1[] =
{
// C
"return","break","continue","default","switch","case","if","else","for","while", "do","long","short",
"__declspec", "goto",
"inline", "__inline__", "_inline", "__inline", "__typeof","__extension__",
"asm", "__asm", "_asm", "volatile", "#cpu", "__stdcall__",
+ "__restrict__", "__restrict", "restrict",
// eC
"class", "private", "public",
null
};
-static char * keyWords2[] =
+static const char * keyWords2[] =
{
- "defined", "warning", null
+ "defined", "warning",
+ "include", "pragma", "elif", "ifdef", "ifndef", "endif", "undef", "line",
+ null
};
-static char ** keyWords[] = { keyWords1, keyWords2 };
+static const char ** keyWords[] = { keyWords1, keyWords2 };
#define NUM_KEYWORD_GROUPS (sizeof(keyWords) / sizeof(char **))
//static int * keyLen[NUM_KEYWORD_GROUPS];
static int keyLen[NUM_KEYWORD_GROUPS][sizeof(keyWords1)];
property EditLine firstLine { get { return lines.first; } }; // Change these to a List<EditLine>... (this.lines[10].text)
property EditLine lastLine { get { return lines.last; } };
property EditLine line { get { return this.line; } }; // TODO: Add Set this.line = this.lines[10]
- property char * contents
+ property const char * contents
{
property_category $"Data"
set
return null;
}
- void SetLineText(char * text)
+ void SetLineText(const char * text)
{
if(this)
{
property Color selectionColor { set { selectionColor = value; } get { return selectionColor; } isset { return selectionColor ? true : false; } };
property Color selectionText { set { selectionText = value; } get { return selectionText; } isset { return selectionText ? true : false; } };
property SyntaxColorScheme syntaxColorScheme { set { delete colorScheme; colorScheme = value; incref colorScheme; } }
+ property bool recordUndoEvent { set { undoBuffer.recordAsOne = value; undoBuffer.firstEvent = true; } get { return undoBuffer.recordAsOne; } };
// selectionStart.line, selectionStart.column (With Set)
// selection.line1, selection.line2, selection.column1, selection.column2 (Read only)
bool modified;
- void (* FontExtent)(Display display, Font font, char * text, int len, int * width, int * height);
+ void (* FontExtent)(Display display, Font font, const char * text, int len, int * width, int * height);
Color backColor;
bool rightButtonDown;
void NotifyDestroyed(Window window, DialogResult result)
{
ReplaceDialog dialog = (ReplaceDialog)window;
- char * replace = dialog.replaceString;
+ const char * replace = dialog.replaceString;
if(replace)
strcpy(replaceString, replace);
strcpy(searchString, dialog.searchString);
FontExtent = Display::FontExtent;
font = fontObject;
- lines.offset = (uint)&((EditLine)0).prev;
+ lines.offset = (uint)(uintptr)&((EditLine)0).prev;
style = EditBoxBits { hScroll = true };
}
}
- int CheckColors(EditLine line, int wc, bool selection, int selX, int editX, bool *selected,
- Color selectionForeground, Color selectionBackground, Color textColor, Color *foreground, Color *background, bool *opacity, bool *overwrite)
+ bool CheckColors(EditLine line, int wc, bool selection, int selX, int editX, bool *selected,
+ Color selectionForeground, Color selectionBackground, Color textColor, Color *foreground, Color *background, bool *opacity, int *overwrite)
{
bool flush = false;
if((style.stuckCaret && wc == line.count && !line.next) ||
(!mouseMove && line == this.line && wc == editX))
{
- *overwrite = true;
+ *overwrite = 1;
flush = true;
}
}
bool opacity;
// Overwrite Caret Stuff
- bool overWrite = false;
- int overWriteX, overWriteY;
- byte overWriteCh;
+ int overWrite = 0;
+ int overWriteX = 0, overWriteY = 0;
+ char overWriteCh;
// ****** SYNTAX STATES ******
bool inMultiLineComment = style.inMultiLineComment;
if(!wasEscaped)
escaped = true;
}
- else if(!inQuotes && !inString && !inMultiLineComment && !inSingleLineComment && (isdigit(word[0]) || (word[0] == '.' && isdigit(word[1]))))
+ else if(x < box.right && !inQuotes && !inString && !inMultiLineComment && !inSingleLineComment && (isdigit(word[0]) || (word[0] == '.' && isdigit(word[1]))))
{
- char * dot = strchr(word, '.');
- bool isHex = (word[0] == '0' && (word[1] == 'x' || word[1] == 'X'));
- char * exponent;
- bool isReal;
+ char * dot = word[wordLen] == '.' ? word + wordLen : (word[0] == '.' && (word == line.buffer || word[-1] == '-' || isspace(word[-1])) ? word : null);
+ bool isReal = dot != null;
char * s = null;
- if(isHex)
- {
- exponent = strchr(word, 'p');
- if(!exponent) exponent = strchr(word, 'P');
- }
+ if(dot)
+ isReal = true;
else
{
- exponent = strchr(word, 'e');
- if(!exponent) exponent = strchr(word, 'E');
+ char * exponent;
+ bool isHex = (word[0] == '0' && (word[1] == 'x' || word[1] == 'X'));
+ if(isHex)
+ {
+ exponent = strchrmax(word, 'p', wordLen);
+ if(!exponent) exponent = strchrmax(word, 'P', wordLen);
+ }
+ else
+ {
+ exponent = strchrmax(word, 'e', wordLen);
+ if(!exponent) exponent = strchrmax(word, 'E', wordLen);
+ }
+ isReal = exponent != null;
}
- if(dot && dot > word + wordLen) dot = null;
- isReal = dot || exponent;
if(isReal)
strtod(word, &s); // strtod() seems to break on hex floats (e.g. 0x23e3p12, 0x1.fp3)
else
if(firstWord)
{
inPrep = true;
- newTextColor = colorScheme.preprocessorColor;
+ newTextColor = wordLen == 1 ? colorScheme.keywordColors[1] : colorScheme.preprocessorColor;
}
}
- if(!inQuotes && !inString && !inMultiLineComment && !inSingleLineComment)
+ if(x < box.right && !inQuotes && !inString && !inMultiLineComment && !inSingleLineComment)
{
for(g = 0; g < ((inPrep && word[0] != '#') ? 2 : 1); g++)
{
- char ** keys = keyWords[g];
+ const char ** keys = keyWords[g];
int * len = keyLen[g];
for(ccc = 0; keys[ccc]; ccc++)
{
{
flush = CheckColors(line, wc, selection, selX, editX, &selected, selectionForeground,
selectionBackground, textColor, &foreground, &background, &opacity, &overWrite);
- if(overWrite == true)
+ if(overWrite == 1)
{
overWriteCh = (wc < line.count) ? line.buffer[wc] : ' ';
if(overWriteCh == '\t') overWriteCh = ' ';
flagTrailingSpace = numSpaces && trailingSpace && style.syntax && start + bufferLen == line.count && line != this.line;
if(flagTrailingSpace) surface.SetBackground(red);
FlushBuffer(surface, line, wc, &renderStart, &x, y, numSpaces, flagTrailingSpace, box);
- if(overWrite == true)
+ if(overWrite == 1)
{
overWriteX = x;
overWriteY = y;
if(CheckColors(line, c, selection, selX, editX, &selected, selectionForeground,
selectionBackground, textColor, &foreground, &background, &opacity, &overWrite))
{
- if(overWrite == true)
+ if(overWrite == 1)
{
overWriteX = x;
overWriteY = y;
void ComputeLength(EditLine line)
{
int c;
- int tabOccur = 0;
- int tabWidth;
int x = 0;
for(c = 0; c < line.count; )
this.col = position;
}
- int DelCh(EditLine l1, int y1, int c1, EditLine l2, int y2, int c2, bool placeAfter)
+ void DelCh(EditLine l1, int y1, int c1, EditLine l2, int y2, int c2, bool placeAfter)
{
- return _DelCh(l1, y1, c1, l2, y2, c2, placeAfter, true, null);
+ _DelCh(l1, y1, c1, l2, y2, c2, placeAfter, true, null);
}
bool HasCommentOrEscape(EditLine line)
buffer = new char[line.size ? line.size : 1];
*/
buffer = new char[line.size];
- if(!buffer) return;
+ // TODO: Better handling of these allocation failures
+ if(!buffer) return extras;
CopyBytes(buffer,l2.buffer,oldCount1 + 1/*line.count + 1*//*line.size*/);
}
else
buffer = l2.buffer;
+ // TODO: Better handling of these allocation failures
if(!line.AdjustBuffer(newLineCount))
- return;
+ return extras;
#ifdef _DEBUG
/*if(newLineCount > 4000 || newLineCount < 0)
return false;
}
- bool AddToLine(char * stringLine, int count, bool LFComing, int * addedSpacesPtr, int * addedTabsPtr)
+ bool AddToLine(const char * stringLine, int count, bool LFComing, int * addedSpacesPtr, int * addedTabsPtr)
{
bool hadComment = false;
// Add the line here
{
int w;
int numBytes = 1;
- char * string;
+ const char * string;
if(c < Min(this.x, line.count))
string = line.buffer + c;
else if(c < endX)
// Returns true if it needs scrolling
bool FindMouse(int px, int py, int * tx, int * ty, EditLine * tline, bool half)
{
- int w;
int c;
- int x, y;
+ int y;
EditLine line;
bool needHScroll = false;
{
if(line)
{
- if(mouseMove || (!overwrite && !style.noCaret))
+ if(mouseMove || !style.noCaret)
{
int max = this.mouseMove ? this.dropX : this.x;
int y = this.mouseMove ? this.dropY : this.y;
if(setCaret)
caretX = x;
caretY = y * this.space.h;
- SetCaret(x + XOFFSET-2, y * space.h + YOFFSET, space.h);
+ if(!overwrite)
+ SetCaret(x + XOFFSET-2, y * space.h + YOFFSET, space.h);
+ else
+ SetCaret(0, 0, 0);
}
else
SetCaret(0, 0, 0);
while(true)
{
int start = c;
- int numBytes = 1;
int len = 1;
int w;
if(c < Min(max, line.count))
}
/*
- bool SaveFile(char * fileName)
+ bool SaveFile(const char * fileName)
{
File f = eFile_Open(fileName, FO_WRITE);
if(f)
moveX = this.selX - this.x;
}
}
+
+ recordUndoEvent = true;
DelSel(null);
this.dropX -= moveX;
this.selX = this.x = this.dropX;
this.selY = this.y = this.dropY;
this.selLine = this.line = this.dropLine;
AddS(text);
+ recordUndoEvent = false;
+
SetViewToCursor(true);
delete text;
Modified();
int y;
bool done = false;
EditLine line = this.line;
- int c;
+ int c = 0;
for(y = this.y; y>= 0; y--)
{
c = (y == this.y) ? (Min(this.x-1, line.count-1)) : line.count-1;
if(key.ctrl)
{
int i;
- int length;
char * buffer = line1.buffer;
for(i = x1; i < line1.count; i++)
{
bool stuffAfter = false;
char * addString;
int len = 0;
- bool resetX = false;
- int backX;
+ /*bool resetX = false;
+ int backX;*/
if(style.stuckCaret) GoToEnd(true);
if(style.readOnly) break;
}
// Prevent adding trailing spaces if at the head of a line
- if(c && c == this.x && c < this.line.count && this.x == this.selX && this.y == this.selY)
+ /*if(c && c == this.x && c < this.line.count && this.x == this.selX && this.y == this.selY)
{
position = 0;
backX = this.x;
this.x = 0;
this.selX = 0;
resetX = true;
- }
+ }*/
if(!line.count)
position = x;
stuffAfter = true;
//If last character is a { indent one tab
- if(this.line.buffer[this.x - 1] == '{')
+ c = Min(x, line.count);
+ if(c > 0 && line.buffer[c - 1] == '{')
{
//Except if the next non space character is a }
bool indent = false;
int i;
- for(i = this.x; i < this.line.size; i++)
+ for(i = c; i <= this.line.count; i++) // indent will be set to true on nul terminating char
if(this.line.buffer[i] != ' ' && this.line.buffer[i] != '\t')
{
if(this.line.buffer[i] != '}')
}
addString[len] = '\0';
}
+ recordUndoEvent = true;
if(AddS(addString))
{
- /*EditLine prevLine = this.line.prev;
+ EditLine prevLine = this.line.prev;
if(prevLine)
{
// Nuke spaces if that is all that is left on previous line
break;
if(i == prevLine.count)
DelCh(prevLine, this.y - 1, 0, prevLine, this.y - 1, prevLine.count, false);
- }*/
- if(resetX)
+ }
+ /*if(resetX)
{
this.x = this.selX = backX;
ComputeColumn();
}
- else if(!stuffAfter && style.freeCaret)
+ else */if(!stuffAfter && style.freeCaret)
{
this.x = this.selX = position;
ComputeColumn();
SetViewToCursor(true);
Modified();
}
+ recordUndoEvent = false;
delete addString;
return false;
}
bool foundAlpha = false;
bool found = false;
int y = this.y;
- EditLine line, lastLine;
- int lastC, lastY;
+ EditLine line, lastLine = null;
+ int lastC = 0, lastY = 0;
for(line = this.line; (line && !found); line = line.prev, y--)
{
break;
}
}
- while(--c)
+ while(--c >= 0)
{
byte ch = line.buffer[c];
if(UTF8_IS_FIRST(ch)) break;
{
if(x <= line.count)
{
- byte * buffer = line.buffer;
+ byte * buffer = (byte *)line.buffer;
while(--x)
{
byte ch = buffer[x];
{
bool foundAlpha = false;
bool found = false;
- EditLine line, lastLine;
+ EditLine line = null, lastLine = null;
int y = this.y;
- int lastC, lastY, lastNumBytes;
+ int lastC = 0, lastY = 0, lastNumBytes = 0;
for(line = this.line; (line && !found); line = line.next, y++)
{
{
if(x < line.count)
{
- byte * buffer = line.buffer;
+ byte * buffer = (byte *)line.buffer;
while(++x)
{
byte ch = buffer[x];
{
if(style.stuckCaret) break;
{
+ /*
int th = space.h;
int textPos = 0;
int sx = 0, sy = this.y * this.space.h;
int maxW = clientSize.w - sx;
char * text = line.buffer;
+ */
if(!shift) SelDirty();
DirtyLine(this.y);
for(c=0; line.buffer[c]; c++)
if(line.buffer[c] != ' ' && line.buffer[c] != '\t')
break;
- if(shift && (c != 0 || this.x))
+ if(overwrite || (shift && (c != 0 || this.x)))
DirtyLine(this.y);
if(this.x != c)
this.x = c;
}
else
{
- if(shift && this.x != 0)
+ if(overwrite || (shift && this.x != 0))
DirtyLine(this.y);
this.x = 0;
}
else if(this.x != this.line.count)
{
this.x = this.line.count;
- if(shift)
+ if(overwrite || shift)
DirtyLine(this.y);
ComputeColumn();
}
Copy();
return false;
}
- else if(key.shift)
+ else if(!style.readOnly)
{
- if(!(style.readOnly))
- Paste();
- return false;
- }
- else
- {
- this.overwrite ^= 1;
- UpdateCaretPosition(true);
- if(this.overwrite)
- SetCaret(0,0,0);
- DirtyLine(this.y);
- UpdateDirty();
- NotifyOvrToggle(master, this, this.overwrite);
+ if(key.shift)
+ {
+ if(!(style.readOnly))
+ Paste();
+ return false;
+ }
+ else
+ {
+ this.overwrite ^= 1;
+ UpdateCaretPosition(true);
+ if(this.overwrite)
+ SetCaret(0,0,0);
+ DirtyLine(this.y);
+ UpdateDirty();
+ NotifyOvrToggle(master, this, this.overwrite);
+ }
}
break;
case hotKey:
{
//Only indent back if you are exactly at one tab.
{
- bool whitespace = true;
+ //bool whitespace = true;
int i;
char * newline;
int putsize;
- int indentwidth;
+ int indentwidth = 0;
EditLine line = this.line;
//Only remove one tab if there is nothing else on the line.
bool _AddCh(unichar ch, int * addedSpacesPtr, int * addedTabsPtr)
{
EditLine line;
- int length, endX;
+ int length, endX = 0;
bool result;
ReplaceTextAction replaceAction = null;
AddCharAction addCharAction = null;
void Delete(EditLine line1, int y1, int x1, EditLine line2, int y2, int x2)
{
Deselect();
- DelCh(line1, y1, x1, line2, y2, x2, false);
+ _DelCh(line1, y1, x1, line2, y2, x2, false, false, null);
SetViewToCursor(true);
UpdateDirty();
Modified();
undoBuffer.Undo();
itemEditUndo.disabled = undoBuffer.curAction == 0;
itemEditRedo.disabled = undoBuffer.curAction == undoBuffer.count;
+
+ UpdateDirty();
+ SetSelectCursor();
+ SelectionEnables();
+
if(savedAction == undoBuffer.curAction)
{
modifiedDocument = false;
undoBuffer.Redo();
itemEditUndo.disabled = undoBuffer.curAction == 0;
itemEditRedo.disabled = undoBuffer.curAction == undoBuffer.count;
+
+ UpdateDirty();
+ SetSelectCursor();
+ SelectionEnables();
+
if(savedAction == undoBuffer.curAction)
{
modifiedDocument = false;
}
// BASIC OUTPUT
- bool AddS(char * string)
+ bool AddS(const char * string)
{
if(this)
{
bool ret = true;
- char * line;
+ const char * line;
int c, count;
int addedSpaces = 0, addedTabs = 0;
AddTextAction action = null;
{
if(string[c] == '\n' || string[c] == '\r')
{
- if(!AddToLine(line,count, true, addedSpaces ? null : &addedSpaces, addedTabs ? null : &addedTabs))
+ if(!AddToLine(line, count, true, addedSpaces ? null : &addedSpaces, addedTabs ? null : &addedTabs))
{
ret = false;
break;
}
}
- void PutS(char * string)
+ void PutS(const char * string)
{
if(this)
{
}
}
- void Printf(char * format, ...)
+ void Printf(const char * format, ...)
{
if(this)
{
}
}
- void SetContents(char * format, ...)
+ void SetContents(const char * format, ...)
{
if(this)
{
{
if(created)
{
- int w;
- int c, numLines;
+ int numLines;
EditLine line;
int x;
int checkX, checkY;
}
else
{
- EditLine oldLine = this.line;
+ //EditLine oldLine = this.line;
bool lastOne = false;
EditLine oldViewLine = this.viewLine;
bool figureSyntax = false;
}
else
{
- EditLine oldLine = this.line;
-
for(c=0, line = this.line.prev; line && c<numLines; line = line.prev, c++)
{
this.line = line;
itemEditRedo.disabled = undoBuffer.curAction == undoBuffer.count;
}
- EditBoxFindResult Find(char * text, bool matchWord, bool matchCase, bool isSearchDown)
+ EditBoxFindResult Find(const char * text, bool matchWord, bool matchCase, bool isSearchDown)
{
EditLine line;
int num;
return notFound;
}
- EditBoxFindResult FindInSelection(char * text, bool matchWord, bool matchCase, EditLine l2, int y2, int x2)
+ EditBoxFindResult FindInSelection(const char * text, bool matchWord, bool matchCase, EditLine l2, int y2, int x2)
{
EditLine line;
int y;
return result;
}
- bool Puts(char * string)
+ bool Puts(const char * string)
{
EditBox editBox = this.editBox;
BufferLocation start { editBox.line, editBox.y, editBox.x };
{
utf8Bytes[numBytes++] = ch;
utf8Bytes[numBytes] = 0;
- if(UTF8Validate(utf8Bytes))
+ if(UTF8Validate((char *)utf8Bytes))
{
editBox.AddCh(UTF8_GET_CHAR(utf8Bytes, numBytes));
numBytes = 0;
start.AdjustDelete(pos, end);
sel.AdjustDelete(pos, end);
- editBox.DelCh(pos.line, pos.y, pos.x, end.line, end.y, end.x, true);
+ editBox._DelCh(pos.line, pos.y, pos.x, end.line, end.y, end.x, true, false, null);
}
}
};