diff --git a/uppsrc/CodeEditor/CodeEditor.cpp b/uppsrc/CodeEditor/CodeEditor.cpp index bbf3c979c..9fc508b20 100644 --- a/uppsrc/CodeEditor/CodeEditor.cpp +++ b/uppsrc/CodeEditor/CodeEditor.cpp @@ -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 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)); diff --git a/uppsrc/CodeEditor/FindReplace.cpp b/uppsrc/CodeEditor/FindReplace.cpp index a8f5aed70..1da6769f3 100644 --- a/uppsrc/CodeEditor/FindReplace.cpp +++ b/uppsrc/CodeEditor/FindReplace.cpp @@ -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(); diff --git a/uppsrc/Core/srcdoc.tpp/Tutorial$en-us.tpp b/uppsrc/Core/srcdoc.tpp/Tutorial$en-us.tpp index 410af7834..40ca21cb5 100644 --- a/uppsrc/Core/srcdoc.tpp/Tutorial$en-us.tpp +++ b/uppsrc/Core/srcdoc.tpp/Tutorial$en-us.tpp @@ -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; ]] \ No newline at end of file +versions.]] \ No newline at end of file diff --git a/uppsrc/ide/FindInFiles.cpp b/uppsrc/ide/FindInFiles.cpp index 263b6ddf0..a5ac8f826 100644 --- a/uppsrc/ide/FindInFiles.cpp +++ b/uppsrc/ide/FindInFiles.cpp @@ -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_("); diff --git a/uppsrc/ide/FormatCode.cpp b/uppsrc/ide/FormatCode.cpp index 69966d8cc..abd8ee05e 100644 --- a/uppsrc/ide/FormatCode.cpp +++ b/uppsrc/ide/FormatCode.cpp @@ -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; diff --git a/uppsrc/ide/Insert.cpp b/uppsrc/ide/Insert.cpp index b82ff19a0..43bb878a3 100644 --- a/uppsrc/ide/Insert.cpp +++ b/uppsrc/ide/Insert.cpp @@ -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 \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) diff --git a/uppsrc/ide/idebar.cpp b/uppsrc/ide/idebar.cpp index cef708a00..3da55758b 100644 --- a/uppsrc/ide/idebar.cpp +++ b/uppsrc/ide/idebar.cpp @@ -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"); diff --git a/uppsrc/ide/idetool.cpp b/uppsrc/ide/idetool.cpp index f4d80f900..d5c86acf9 100644 --- a/uppsrc/ide/idetool.cpp +++ b/uppsrc/ide/idetool.cpp @@ -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();