CodeEditor, ide: ReadOnly mode now blocks all write operations (some of advanced ones were not blocked)

git-svn-id: svn://ultimatepp.org/upp/trunk@11112 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2017-05-22 09:57:05 +00:00
parent 93253148ea
commit 1e89b14fcd
8 changed files with 139 additions and 120 deletions

View file

@ -211,6 +211,7 @@ void CodeEditor::CopyWord() {
void CodeEditor::DuplicateLine()
{
if(IsReadOnly()) return;
int i = GetLine(cursor);
int pos = GetPos(i);
int len = GetLineLength(i);
@ -243,6 +244,7 @@ void CodeEditor::FinishPut()
void CodeEditor::ReformatComment()
{
if(IsReadOnly()) return;
NextUndo();
GetSyntax(GetLine(cursor))->ReformatComment(*this);
}
@ -322,6 +324,7 @@ void CodeEditor::IndentInsert(int chr, int count) {
void CodeEditor::Make(Event<String&> op)
{
if(IsReadOnly()) return;
Point cursor = GetColumnLine(GetCursor());
Point scroll = GetScrollPos();
int l, h;
@ -541,6 +544,7 @@ bool CodeEditor::GetLineSelection(int& l, int& h) {
}
void CodeEditor::TabRight() {
if(IsReadOnly()) return;
int l, h;
if(!GetLineSelection(l, h)) return;
int ll = l;
@ -551,6 +555,7 @@ void CodeEditor::TabRight() {
}
void CodeEditor::TabLeft() {
if(IsReadOnly()) return;
int l, h;
if(!GetLineSelection(l, h)) return;
int ll = l;
@ -731,6 +736,8 @@ void CodeEditor::Goto() {
bool CodeEditor::ToggleSimpleComment(int &start_line, int &end_line, bool usestars)
{
if(IsReadOnly()) return true;
int l, h;
if(!GetSelection(l, h))
return true;
@ -752,6 +759,8 @@ bool CodeEditor::ToggleSimpleComment(int &start_line, int &end_line, bool usesta
void CodeEditor::ToggleLineComments(bool usestars)
{
if(IsReadOnly()) return;
int start_line, end_line;
if(ToggleSimpleComment(start_line, end_line))
return;
@ -801,6 +810,8 @@ void CodeEditor::ToggleLineComments(bool usestars)
void CodeEditor::ToggleStarComments()
{
if(IsReadOnly()) return;
int start_line, end_line;
if(ToggleSimpleComment(start_line, end_line))
return;
@ -828,6 +839,8 @@ void CodeEditor::ToggleStarComments()
void CodeEditor::Enclose(const char *c1, const char *c2, int l, int h)
{
if(IsReadOnly()) return;
if((l < 0 || h < 0) && !GetSelection(l, h))
return;
Insert(l, WString(c1));

View file

@ -611,6 +611,9 @@ void CodeEditor::OpenNormalFindReplace(bool replace)
void CodeEditor::FindReplace(bool pick_selection, bool pick_text, bool replace)
{
if(IsReadOnly())
replace = false;
if(findreplace.IsOpen())
CloseFindReplace();

View file

@ -66,8 +66,8 @@ variable name and value:&]
[s7; DUMPHEX(h);&]
[s0; &]
[s17; x `= 0x7b&]
[s17; h `= Memory at 0x01B8F964, size 0x3 `= 3&]
[s17; `+0 0x01B8F964 66 6F 6F
[s17; h `= Memory at 0x01CAF9D8, size 0x3 `= 3&]
[s17; `+0 0x01CAF9D8 66 6F 6F
foo &]
[s0; &]
[s5; To log the value of a container (or generic Range), you can
@ -311,8 +311,8 @@ data, including zeroes:&]
[s7; &]
[s7; DUMPHEX(a);&]
[s0; &]
[s17; a `= Memory at 0x01B8F9C4, size 0x5 `= 5&]
[s17; `+0 0x01B8F9C4 31 32 33 34 00
[s17; a `= Memory at 0x01CAFA38, size 0x5 `= 5&]
[s17; `+0 0x01CAFA38 31 32 33 34 00
1234. &]
[s0; &]
[s3;H4; 1.3 StringBuffer&]
@ -415,7 +415,7 @@ concrete types.&]
[s7; &]
[s7; DUMP(date);&]
[s0; &]
[s17; date `= 05/20/2017&]
[s17; date `= 02/21/2017&]
[s0; &]
[s5; All data members of [*C@5 Date] structure are public:&]
[s0; &]
@ -426,8 +426,8 @@ would log&]
[s7; DUMP((int)date.day); // as characters&]
[s0; &]
[s17; (int)date.year `= 2017&]
[s17; (int)date.month `= 5&]
[s17; (int)date.day `= 20&]
[s17; (int)date.month `= 2&]
[s17; (int)date.day `= 21&]
[s0; &]
[s5; Dates can be compared:&]
[s0; &]
@ -442,15 +442,15 @@ ing goes to the next/previous day:&]
[s7; DUMP(`-`-date);&]
[s7; DUMP(`+`+date);&]
[s0; &]
[s17; date `+ 1 `= 05/21/2017&]
[s17; `-`-date `= 05/19/2017&]
[s17; `+`+date `= 05/20/2017&]
[s17; date `+ 1 `= 02/22/2017&]
[s17; `-`-date `= 02/20/2017&]
[s17; `+`+date `= 02/21/2017&]
[s0; &]
[s5; Subtraction of dates yields a number of days between them:&]
[s0; &]
[s7; DUMP(date `- Date(2000, 1, 1));&]
[s0; &]
[s17; date `- Date(2000, 1, 1) `= 6349&]
[s17; date `- Date(2000, 1, 1) `= 6261&]
[s0; &]
[s5; There are several [*C@5 Date] and calendar related functions:&]
[s0; &]
@ -476,7 +476,7 @@ ing goes to the next/previous day:&]
[s0; &]
[s7; DUMP(DayOfWeek(date)); // 0 is Sunday&]
[s0; &]
[s17; DayOfWeek(date) `= 6&]
[s17; DayOfWeek(date) `= 2&]
[s0; &]
[s0; &]
[s7; DUMP(LastDayOfMonth(date));&]
@ -486,11 +486,11 @@ ing goes to the next/previous day:&]
[s7; DUMP(DayOfYear(date)); // number of days since Jan`-1 `+ 1&]
[s7; DUMP(DayOfYear(Date(2016, 1, 1)));&]
[s0; &]
[s17; LastDayOfMonth(date) `= 05/31/2017&]
[s17; FirstDayOfMonth(date) `= 05/01/2017&]
[s17; LastDayOfMonth(date) `= 02/28/2017&]
[s17; FirstDayOfMonth(date) `= 02/01/2017&]
[s17; LastDayOfYear(date) `= 12/31/2017&]
[s17; FirstDayOfYear(date) `= 01/01/2017&]
[s17; DayOfYear(date) `= 140&]
[s17; DayOfYear(date) `= 52&]
[s17; DayOfYear(Date(2016, 1, 1)) `= 1&]
[s0; &]
[s0; &]
@ -501,10 +501,10 @@ between two dates&]
partial months`' between two dates&]
[s7; DUMP(AddYears(date, 2));&]
[s0; &]
[s17; AddMonths(date, 20) `= 01/20/2019&]
[s17; AddMonths(date, 20) `= 10/21/2018&]
[s17; GetMonths(date, date `+ 100) `= 3&]
[s17; GetMonthsP(date, date `+ 100) `= 4&]
[s17; AddYears(date, 2) `= 05/20/2019&]
[s17; AddYears(date, 2) `= 02/21/2019&]
[s0; &]
[s0; &]
[s7; DUMP(GetWeekDate(2015, 1));&]
@ -544,11 +544,11 @@ time:&]
[s7; DUMP((int)time.minute);&]
[s7; DUMP((int)time.second);&]
[s0; &]
[s17; time `= 05/20/2017 20:04:42&]
[s17; (Date)time `= 05/20/2017&]
[s17; (int)time.hour `= 20&]
[s17; (int)time.minute `= 4&]
[s17; (int)time.second `= 42&]
[s17; time `= 02/21/2017 11:17:59&]
[s17; (Date)time `= 02/21/2017&]
[s17; (int)time.hour `= 11&]
[s17; (int)time.minute `= 17&]
[s17; (int)time.second `= 59&]
[s0; &]
[s5; Times can be compared:&]
[s0; &]
@ -575,10 +575,10 @@ but numbers represent seconds (using [*C@5 int64] datatype):&]
is in days&]
[s7; DUMP(time `- ToTime(date)); // Time `- Time is in seconds&]
[s0; &]
[s17; time `+ 1 `= 05/20/2017 20:04:43&]
[s17; time `+ 24 `* 3600 `= 05/21/2017 20:04:42&]
[s17; time `+ 1 `= 02/21/2017 11:18:00&]
[s17; time `+ 24 `* 3600 `= 02/22/2017 11:17:59&]
[s17; time `- date `= 0&]
[s17; time `- ToTime(date) `= 72282&]
[s17; time `- ToTime(date) `= 40679&]
[s0; &]
[s5; [*C@5 Time] defines era limits too:&]
[s0; &]
@ -633,9 +633,9 @@ items predefined by U`+`+:&]
[s7; DUMP(LoadFile(ConfigFile(`"test.txt`")));&]
[s7; DUMP(sout);&]
[s0; &]
[s17; LoadFile(ConfigFile(`"test.txt`")) `= 1.23 05/20/2017 05/20/2017
20:04:42&]
[s17; sout `= 1.23 05/20/2017 05/20/2017 20:04:42&]
[s17; LoadFile(ConfigFile(`"test.txt`")) `= 1.23 02/21/2017 02/21/2017
11:17:59&]
[s17; sout `= 1.23 02/21/2017 02/21/2017 11:17:59&]
[s0; &]
[s5; Getting client types involved into this schema is not too difficult,
all you need to do is to add [*C@5 ToString] method:&]
@ -978,7 +978,7 @@ value.&]
[s7; &]
[s7; DUMP(v);&]
[s0; &]
[s17; v `= `[1018, 980, 1051, 888, 978, 1033, 1021, 1005, 999, 1027`]&]
[s17; v `= `[1025, 972, 1004, 1033, 996, 988, 992, 1022, 970, 998`]&]
[s0; &]
[s5; You can apply algorithms on containers, e.g. Sort&]
[s0; &]
@ -986,7 +986,7 @@ value.&]
[s7; &]
[s7; DUMP(v);&]
[s0; &]
[s17; v `= `[888, 978, 980, 999, 1005, 1018, 1021, 1027, 1033, 1051`]&]
[s17; v `= `[970, 972, 988, 992, 996, 998, 1004, 1022, 1025, 1033`]&]
[s0; &]
[s3;H4; 2.3 Transfer issues&]
[s5; Often you need to pass content of one container to another of
@ -1092,15 +1092,15 @@ to it:&]
[s7; DUMPC(dist);&]
[s0; &]
[s17; dist:&]
[s17; -|`[0`] `= Test 5: `[1973, 2048, 1988, 2007, 1984`]&]
[s17; -|`[1`] `= Test 6: `[1751, 1696, 1588, 1596, 1729, 1640`]&]
[s17; -|`[2`] `= Test 7: `[1402, 1450, 1457, 1425, 1421, 1395, 1450`]&]
[s17; -|`[3`] `= Test 8: `[1231, 1278, 1265, 1255, 1243, 1298, 1195,
1235`]&]
[s17; -|`[4`] `= Test 9: `[1096, 1078, 1164, 1071, 1138, 1064, 1111,
1135, 1143`]&]
[s17; -|`[5`] `= Test 10: `[1015, 1054, 959, 996, 1037, 977, 986, 981,
958, 1037`]&]
[s17; -|`[0`] `= Test 5: `[2020, 1997, 2005, 2018, 1960`]&]
[s17; -|`[1`] `= Test 6: `[1708, 1680, 1730, 1617, 1671, 1594`]&]
[s17; -|`[2`] `= Test 7: `[1380, 1489, 1479, 1424, 1415, 1345, 1468`]&]
[s17; -|`[3`] `= Test 8: `[1332, 1239, 1185, 1245, 1236, 1305, 1247,
1211`]&]
[s17; -|`[4`] `= Test 9: `[1122, 1129, 1109, 1083, 1151, 1115, 1069,
1113, 1109`]&]
[s17; -|`[5`] `= Test 10: `[1031, 1011, 1124, 1001, 980, 940, 973, 943,
1015, 982`]&]
[s0; &]
[s5; Another possibility is to use [*C@5 Vector`::Add(T`&`&)] method,
which uses pick`-constructor instead of deep`-copy constructor.
@ -1523,19 +1523,6 @@ see later):&]
[s17; e.key `= 3&]
[s17; e.value `= Peter Carpenter&]
[s0; &]
[s5; Note that the `'projection range`' obtained by [*C@5 operator`~]
is temporary value, which means that if mutating operation is
required for values, r`-value reference has to be used instead
of plain reference:&]
[s0; &]
[s7; for(const auto`& e : `~m)&]
[s7; -|if(e.key `=`= `"2`")&]
[s7; -|-|e.value.surname `= `"May`";&]
[s7; &]
[s7; DUMP(m);&]
[s0; &]
[s17; m `= `{1: John Smith, 2: Carl May, 3: Peter Carpenter`}&]
[s0; &]
[s5; You can use Find method to retrieve position of element with
required key:&]
[s0; &]
@ -1547,7 +1534,7 @@ required key:&]
[s0; &]
[s7; DUMP(m.Get(`"2`"));&]
[s0; &]
[s17; m.Get(`"2`") `= Carl May&]
[s17; m.Get(`"2`") `= Carl Engles&]
[s0; &]
[s5; Passing key not present in [*C@5 VectorMap] as [*C@5 Get] parameter
is undefined behavior (ASSERT fails in debug mode), but there
@ -1571,7 +1558,7 @@ invisible for Find operations:&]
[s7; m.SetKey(1, `"33`");&]
[s7; DUMP(m.Get(`"33`", Person(`"unknown`", `"person`")));&]
[s0; &]
[s17; m.Get(`"33`", Person(`"unknown`", `"person`")) `= Carl May&]
[s17; m.Get(`"33`", Person(`"unknown`", `"person`")) `= Carl Engles&]
[s0; &]
[s5; If there are more elements with the same key in [*C@5 VectorMap],
you can iterate them using [*C@5 FindNext] method:&]
@ -1584,7 +1571,7 @@ you can iterate them using [*C@5 FindNext] method:&]
[s7; -|q `= m.FindNext(q);&]
[s7; `}&]
[s0; &]
[s17; m`[q`] `= Carl May&]
[s17; m`[q`] `= Carl Engles&]
[s17; m`[q`] `= Peter Pan&]
[s0; &]
[s5; Unlinked positions can be `'reused`' using Put method:&]
@ -2240,11 +2227,11 @@ is for the most part seamless:&]
[s0; &]
[s17; a `= 1&]
[s17; b `= 2.34&]
[s17; c `= 05/20/2017&]
[s17; c `= 02/21/2017&]
[s17; d `= hello&]
[s17; x `= 1&]
[s17; y `= 2.34&]
[s17; z `= 05/20/2017&]
[s17; z `= 02/21/2017&]
[s17; s `= hello&]
[s0; &]
[s5; As for primitive types, Value seamlessly works with [*C@5 int],
@ -2276,7 +2263,7 @@ as it is supported by these types):&]
[s0; &]
[s17; i `= 1&]
[s17; j `= 2&]
[s17; k `= 05/20/2017 00:00:00&]
[s17; k `= 02/21/2017 00:00:00&]
[s17; t `= hello&]
[s0; &]
[s5; To determine type of value stored in [*C@5 Value], you can use
@ -2908,8 +2895,8 @@ thread to [*C@5 Wait] for its completion:&]
[s17; In the thread 2&]
[s17; In the main thread 3&]
[s17; In the thread 3&]
[s17; In the thread 4&]
[s17; In the main thread 4&]
[s17; In the thread 4&]
[s17; About to wait for thread to finish&]
[s17; In the thread 5&]
[s17; In the thread 6&]
@ -2959,7 +2946,7 @@ code demonstrates why:&]
[s7; t.Wait();&]
[s7; DUMP(sum);&]
[s0; &]
[s17; sum `= 1025121&]
[s17; sum `= 1022929&]
[s0; &]
[s5; While the expected value is 2000000, produced value is different.
The problem is that both thread read / modify / write [*C@5 sum]
@ -3084,13 +3071,13 @@ testing data&]
[s7; DUMP(w);&]
[s0; &]
[s17; w `= `[Lorem, ipsum, dolor, sit, amet, consectetur, adipiscing,
elit, sed, do, eiusmod, esse, cillum, dolore, eu, fugiat, nulla,
pariatur, Excepteur, sint, occaecat, cupidatat, quis, nostrud,
elit, sed, do, eiusmod, non, proident, sunt, in, culpa, qui,
officia, deserunt, mollit, anim, id, est, laborum, quis, nostrud,
exercitation, ullamco, laboris, nisi, ut, aliquip, ex, ea, commodo,
tempor, incididunt, labore, et, magna, aliqua, Ut, enim, ad,
minim, veniam, consequat, Duis, aute, irure, in, reprehenderit,
voluptate, velit, non, proident, sunt, culpa, qui, officia, deserunt,
mollit, anim, id, est, laborum`]&]
consequat, Duis, aute, irure, reprehenderit, voluptate, velit,
tempor, incididunt, labore, et, dolore, magna, aliqua, Ut, enim,
ad, minim, veniam, esse, cillum, eu, fugiat, nulla, pariatur,
Excepteur, sint, occaecat, cupidatat`]&]
[s0; &]
[s5; Adding words to [*C@5 w] requires [*C@5 Mutex]. Alternative to this
`'result gathering`' [*C@5 Mutex] is CoWork`::FinLock. The idea
@ -3118,13 +3105,13 @@ end of CoWork job&]
[s7; DUMP(w);&]
[s0; &]
[s17; w `= `[Lorem, ipsum, dolor, sit, amet, consectetur, adipiscing,
elit, sed, do, eiusmod, esse, cillum, dolore, eu, fugiat, nulla,
pariatur, Excepteur, sint, occaecat, cupidatat, quis, nostrud,
elit, sed, do, eiusmod, non, proident, sunt, in, culpa, qui,
officia, deserunt, mollit, anim, id, est, laborum, quis, nostrud,
exercitation, ullamco, laboris, nisi, ut, aliquip, ex, ea, commodo,
tempor, incididunt, labore, et, magna, aliqua, Ut, enim, ad,
minim, veniam, consequat, Duis, aute, irure, in, reprehenderit,
voluptate, velit, non, proident, sunt, culpa, qui, officia, deserunt,
mollit, anim, id, est, laborum`]&]
consequat, Duis, aute, irure, reprehenderit, voluptate, velit,
tempor, incididunt, labore, et, dolore, magna, aliqua, Ut, enim,
ad, minim, veniam, esse, cillum, eu, fugiat, nulla, pariatur,
Excepteur, sint, occaecat, cupidatat`]&]
[s0; &]
[s5; Of course, the code performed after FinLock should not take
long, otherwise there is negative impact on all CoWork instances.
@ -3226,5 +3213,4 @@ for `'Sort`' it is `'CoSort`':&]
[s0; &]
[s5; Caution should be exercised when using these algorithms `- for
small datasets, they are almost certainly slower than single`-threaded
versions.&]
[s5; ]]
versions.]]

View file

@ -165,25 +165,27 @@ bool Ide::SearchInFile(const String& fn, const String& pattern, bool wholeword,
if(infile && ffs != STYLE_NO_REPLACE)
{
EditFile(fn);
bool doit = true;
if(ffs == STYLE_CONFIRM_REPLACE)
{
editor.SetCursor(0);
editor.Find(false, true);
switch(PromptYesNoCancel(NFormat("Replace %d lines in [* \1%s\1]?", infile, fn)))
if(!editor.IsReadOnly()) {
bool doit = true;
if(ffs == STYLE_CONFIRM_REPLACE)
{
case 1: break;
case 0: doit = false; break;
case -1: return false;
editor.SetCursor(0);
editor.Find(false, true);
switch(PromptYesNoCancel(NFormat("Replace %d lines in [* \1%s\1]?", infile, fn)))
{
case 1: break;
case 0: doit = false; break;
case -1: return false;
}
}
if(doit)
{
editor.SelectAll();
editor.BlockReplace();
SaveFile();
ffound.Add(fn, Null, AsString(infile) + " replacements made");
ffound.Sync();
}
}
if(doit)
{
editor.SelectAll();
editor.BlockReplace();
SaveFile();
ffound.Add(fn, Null, AsString(infile) + " replacements made");
ffound.Sync();
}
}
@ -191,8 +193,6 @@ bool Ide::SearchInFile(const String& fn, const String& pattern, bool wholeword,
}
void Ide::FindInFiles(bool replace) {
if(editor.IsReadOnly())
replace = false;
CodeEditor::FindReplaceData d = editor.GetFindReplaceData();
CtrlRetriever rf;
rf(ff.find, d.find)
@ -328,6 +328,7 @@ void Ide::FindString(bool back)
void Ide::TranslateString()
{
if(editor.IsReadOnly()) return;
int l, h;
if(editor.GetSelection(l, h)) {
editor.Insert(l, "t_(");

View file

@ -116,6 +116,7 @@ WString Ide::FormatCodeString(WString const &Src, ASFormatter &Formatter)
// Formats editor's code with Ide format parameters
void Ide::FormatCode()
{
if(editor.IsReadOnly()) return;
// Gets editor contents from editor
WString Src;
int l, h;

View file

@ -59,6 +59,8 @@ bool InsertColorDlg::IsCanceled()
void Ide::InsertColor()
{
if(editor.IsReadOnly())
return;
InsertColorDlg dlg;
dlg.Execute();
if (!dlg.IsCanceled())
@ -67,6 +69,8 @@ void Ide::InsertColor()
void Ide::InsertLay(const String& fn)
{
if(editor.IsReadOnly())
return;
String s;
s << "#define LAYOUTFILE <" << fn << ">\n"
<< "#include <CtrlCore/lay.h>\n";
@ -75,6 +79,8 @@ void Ide::InsertLay(const String& fn)
void Ide::InsertIml(const String& fn, String classname)
{
if(editor.IsReadOnly())
return;
if(!EditText(classname, "Insert .iml include", "Img class"))
return;
String h;
@ -89,11 +95,15 @@ void Ide::InsertIml(const String& fn, String classname)
void Ide::InsertText(const String& text)
{
if(editor.IsReadOnly())
return;
editor.Paste(text.ToWString());
}
void Ide::InsertCString()
{
if(editor.IsReadOnly())
return;
String txt = ReadClipboardText();
if(txt.GetCount())
editor.Paste(AsCString(txt).ToWString());
@ -101,6 +111,8 @@ void Ide::InsertCString()
void Ide::InsertFilePath(bool c)
{
if(editor.IsReadOnly())
return;
String path = SelectFileOpen("All files\t*.*");
path.Replace("\\", "/");
if(path.GetCount()) {
@ -174,9 +186,10 @@ void Ide::InsertInclude(Bar& bar)
void Ide::InsertAdvanced(Bar& bar)
{
bar.Add("Insert", THISBACK(InsertMenu));
bar.Add("Insert #include", THISBACK(InsertInclude));
bar.Add("Advanced", THISBACK(EditSpecial));
bool b = !editor.IsReadOnly();
bar.Add(b, "Insert", THISBACK(InsertMenu));
bar.Add(b, "Insert #include", THISBACK(InsertInclude));
bar.Add(b, "Advanced", THISBACK(EditSpecial));
}
void Ide::EditorMenu(Bar& bar)

View file

@ -117,41 +117,42 @@ void Ide::OnlineSearchMenu(Bar& menu)
void Ide::EditSpecial(Bar& menu)
{
menu.Add(AK_SPACESTOTABS, THISBACK(EditMakeTabs))
bool b = !editor.IsReadOnly();
menu.Add(b, AK_SPACESTOTABS, THISBACK(EditMakeTabs))
.Help("Convert leading blanks on each line to tabs");
menu.Add(AK_TABSTOSPACES, THISBACK(EditMakeSpaces))
menu.Add(b, AK_TABSTOSPACES, THISBACK(EditMakeSpaces))
.Help("Convert all tabs to spaces");
menu.Add(AK_LINEENDINGS, THISBACK(EditMakeLineEnds))
menu.Add(b, AK_LINEENDINGS, THISBACK(EditMakeLineEnds))
.Help("Remove tabs and spaces at line endings");
menu.Add(AK_TRANSLATESTRING, THISBACK(TranslateString))
menu.Add(b, AK_TRANSLATESTRING, THISBACK(TranslateString))
.Help("Mark the current selection as translated string");
menu.Add(AK_SWAPCHARS, THISBACK(SwapChars))
menu.Add(b, AK_SWAPCHARS, THISBACK(SwapChars))
.Help("Transpose characters");
menu.Add(AK_COPYWORD, THISBACK(CopyWord))
.Help("Copy the current identifier to the clipboard");
menu.Add(AK_DUPLICATELINE, THISBACK(DuplicateLine))
menu.Add(b, AK_DUPLICATELINE, THISBACK(DuplicateLine))
.Help("Duplicate the current line");
menu.Add(AK_FORMATCODE, THISBACK(FormatCode))
menu.Add(b, AK_FORMATCODE, THISBACK(FormatCode))
.Help("Reformat code in editor");
menu.Add(editor.IsSelection(), AK_TOUPPER, THISBACK(TextToUpper))
menu.Add(b && editor.IsSelection(), AK_TOUPPER, THISBACK(TextToUpper))
.Help("Convert letters in selection to uppercase");
menu.Add(editor.IsSelection(), AK_TOLOWER, THISBACK(TextToLower))
menu.Add(b && editor.IsSelection(), AK_TOLOWER, THISBACK(TextToLower))
.Help("Convert letters in selection to lowercase");
menu.Add(editor.IsSelection(), AK_TOASCII, THISBACK(TextToAscii))
menu.Add(b && editor.IsSelection(), AK_TOASCII, THISBACK(TextToAscii))
.Help("Covert text to 7-bit ASCII removing all accents and special symbols");
menu.Add(editor.IsSelection(), AK_INITCAPS, THISBACK(TextInitCaps))
menu.Add(b && editor.IsSelection(), AK_INITCAPS, THISBACK(TextInitCaps))
.Help("Capitalize the first character of words in selection");
menu.Add(editor.IsSelection(), AK_SWAPCASE, THISBACK(SwapCase))
menu.Add(b && editor.IsSelection(), AK_SWAPCASE, THISBACK(SwapCase))
.Help("Swap the case of letters in selection");
menu.Add(editor.IsSelection(), AK_TOCSTRING, THISBACK(ToCString))
menu.Add(b && editor.IsSelection(), AK_TOCSTRING, THISBACK(ToCString))
.Help("Convert selection to CString");
menu.Add(editor.IsSelection(), AK_TOCOMMENT, THISBACK(ToComment))
menu.Add(b && editor.IsSelection(), AK_TOCOMMENT, THISBACK(ToComment))
.Help("Comment code");
menu.Add(editor.IsSelection(), AK_COMMENTLINES, THISBACK(CommentLines))
menu.Add(b && editor.IsSelection(), AK_COMMENTLINES, THISBACK(CommentLines))
.Help("Comment code lines");
menu.Add(editor.IsSelection(), AK_UNCOMMENT, THISBACK(UnComment))
menu.Add(b && editor.IsSelection(), AK_UNCOMMENT, THISBACK(UnComment))
.Help("Uncomment code");
menu.Add(AK_REFORMAT_COMMENT, THISBACK(ReformatComment))
menu.Add(b, AK_REFORMAT_COMMENT, THISBACK(ReformatComment))
.Help("Reformat multiline comment into paragraph");
}
@ -160,7 +161,7 @@ void Ide::SearchMenu(Bar& menu)
if(!designer) {
menu.Add(AK_FIND, THISBACK(EditFind))
.Help("Search for text or text pattern");
menu.Add(AK_REPLACE, THISBACK(EditReplace))
menu.Add(!editor.IsReadOnly(), AK_REPLACE, THISBACK(EditReplace))
.Help("Search for text or text pattern, with replace option");
// menu.Add(AK_FINDSEL, THISBACK(EditFindReplacePickText))
// .Help("Show find / replace dialog & set active text as the 'find' text");
@ -180,7 +181,7 @@ void Ide::SearchMenu(Bar& menu)
}
menu.Add(AK_FINDINFILES, THISBACK1(FindInFiles, false))
.Help("Find text or text pattern in subtree of given path");
menu.Add(editor.IsEditable(), AK_REPLACEINFILES, THISBACK1(FindInFiles, true))
menu.Add(AK_REPLACEINFILES, THISBACK1(FindInFiles, true))
.Help("Find text or text pattern in subtree of given path, with replace option(s)");
menu.Add(AK_FINDFILE, THISBACK(FindFileName))
.Help("Locate file by filename (use *, ? when you're not sure)");
@ -188,6 +189,7 @@ void Ide::SearchMenu(Bar& menu)
void Ide::Edit(Bar& menu)
{
bool b = !editor.IsReadOnly();
if(editfile.GetCount() && editashex.Find(editfile) < 0) {
menu.Add(AK_EDITASHEX, THISBACK(EditAsHex));
if(!designer)
@ -220,18 +222,18 @@ void Ide::Edit(Bar& menu)
.Help("Edit using the designer (not as text)");
menu.MenuSeparator();
}
menu.Add("Undo", CtrlImg::undo(), callback(&editor, &LineEdit::Undo))
menu.Add(b, "Undo", CtrlImg::undo(), callback(&editor, &LineEdit::Undo))
.Key(K_CTRL_Z)
.Enable(editor.IsUndo())
.Help("Undo changes to text");
menu.Add("Redo", CtrlImg::redo(), callback(&editor, &LineEdit::Redo))
menu.Add(b, "Redo", CtrlImg::redo(), callback(&editor, &LineEdit::Redo))
.Key(K_SHIFT|K_CTRL_Z)
.Enable(editor.IsRedo())
.Help("Redo undone changes");
menu.Separator();
menu.Add("Cut", CtrlImg::cut(), callback(&editor, &LineEdit::Cut))
menu.Add(b, "Cut", CtrlImg::cut(), callback(&editor, &LineEdit::Cut))
.Key(K_CTRL_X)
.Enable(selection)
.Help("Cut selection and place it on the system clipboard");
@ -239,7 +241,7 @@ void Ide::Edit(Bar& menu)
.Key(K_CTRL_C)
.Enable(selection)
.Help("Copy current selection on the system clipboard");
menu.Add("Paste", CtrlImg::paste(), THISBACK(EditPaste))
menu.Add(b, "Paste", CtrlImg::paste(), THISBACK(EditPaste))
.Key(K_CTRL_V)
.Help("Insert text from clipboard at cursor location");

View file

@ -289,7 +289,7 @@ String FormatElapsedTime(double run)
void Ide::AlterText(WString (*op)(const WString& in))
{
if(designer || !editor.IsSelection())
if(designer || !editor.IsSelection() || editor.IsReadOnly())
return;
editor.NextUndo();
WString w = editor.GetSelectionW();