ui: Add Edit feature to interactive stack

Add the `Edit` feature to the interactive stack.
When editing an object and replacing it with multiple objects, the
objects are inserted at the interactive stack location.

Add the `Info` button to show information about the stack level.

Separate the `Sort` feature into `MemSort` (sort by memory
representation) and `ValSort` (sort by value).

Add the `EchoNSp` to echo without spaces the way the HP48 does.

Fixes: #1031

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
This commit is contained in:
Christophe de Dinechin 2024-07-20 14:29:43 +02:00
parent d5c88faa4f
commit c9c770b981
69 changed files with 303 additions and 57 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 4 KiB

BIN
color-images/istack-11.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
color-images/istack-12.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
color-images/istack-13.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
color-images/istack-14.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
color-images/istack-15.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
color-images/istack-16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
color-images/istack-17.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
color-images/istack-18.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
color-images/istack-19.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 4 KiB

BIN
color-images/istack-20.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
color-images/istack-21.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
color-images/istack-22.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
color-images/istack-23.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
color-images/istack-24.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
color-images/istack-7b.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
color-images/istack-9c.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

BIN
color-images/istack-9d.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 4 KiB

BIN
images/istack-11.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
images/istack-12.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
images/istack-13.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 KiB

BIN
images/istack-14.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
images/istack-15.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
images/istack-16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
images/istack-17.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
images/istack-18.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
images/istack-19.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
images/istack-20.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
images/istack-21.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
images/istack-22.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
images/istack-23.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
images/istack-24.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
images/istack-7b.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
images/istack-9c.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
images/istack-9d.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View file

@ -501,7 +501,6 @@ COMMAND_BODY(Bytes)
if (rt.top(bin))
if (rt.push(integer::make(size)))
return OK;
}
return ERROR;
}

View file

@ -1571,7 +1571,7 @@ list_p list::map(algebraic_r x, arithmetic_fn fn) const
//
// ============================================================================
static int memory_compare(object_p *xp, object_p *yp)
int memory_compare(object_p *xp, object_p *yp)
// ----------------------------------------------------------------------------
// Compare using type IDs and memory content
// ----------------------------------------------------------------------------

View file

@ -363,8 +363,9 @@ object::result to_list(uint depth);
int value_compare(object_p *xp, object_p *yp);
int memory_compare(object_p *xp, object_p *yp);
// ----------------------------------------------------------------------------
// Value comparison for sorting
// Value and memory comparison for sorting
// ----------------------------------------------------------------------------

View file

@ -81,6 +81,7 @@ TESTS(shifts, "Shift logic");
TESTS(keyboard, "Keyboard entry");
TESTS(types, "Data types");
TESTS(editor, "Editor operations");
TESTS(istack, "Interactive stack operations");
TESTS(stack, "Stack operations");
TESTS(arithmetic, "Arithmetic operations");
TESTS(globals, "Global variables");
@ -163,7 +164,7 @@ void tests::run(bool onlyCurrent)
if (onlyCurrent)
{
here().begin("Current");
editor_operations();
interactive_stack_operations();
}
else
{
@ -173,6 +174,7 @@ void tests::run(bool onlyCurrent)
data_types();
editor_operations();
stack_operations();
interactive_stack_operations();
arithmetic();
global_variables();
local_variables();
@ -819,9 +821,20 @@ void tests::editor_operations()
step("Insert iferr-then-else from menu")
.test(CLEAR, LSHIFT, KEY3, LSHIFT, F2, LSHIFT, F4)
.editor("iferr then else end ");
}
void tests::interactive_stack_operations()
// ----------------------------------------------------------------------------
// Check interactive stack operations
// ----------------------------------------------------------------------------
{
BEGIN(istack);
step("Interactive stack")
.test(CLEAR, "111 222 333 444 555 666 'inv(sqrt(2*X))' 888 999", ENTER,
.test(CLEAR, EXIT, EXIT, EXIT,
"111 222 333 444 555 666 'inv(sqrt((2+3*6)*X))' 888 999",
ENTER,
"X 2", NOSHIFT, MUL, C, B, ENTER, UP)
.image_noheader("istack-1");
step("Interactive stack level 2")
@ -840,31 +853,161 @@ void tests::editor_operations()
.test(DOWN, DOWN, DOWN, DOWN, DOWN)
.image_noheader("istack-3d");
step("Interactive stack ->List")
.test(F6)
.image_noheader("istack-4");
.test(LSHIFT, F5)
.image_noheader("istack-4")
.expect("{ 888 999 '(√(2·X))⁻¹' '(√(2·X))⁻¹' }");
step("Interactive stack Pick")
.test(F5)
.test(UP, F5)
.image_noheader("istack-5");
step("Interactive stack Roll Down")
.test(F4)
.test(UP, UP, UP, UP, F4)
.image_noheader("istack-6");
step("Interactive stack Level")
.test(F3)
.image_noheader("istack-7");
step("Interactive stack going down")
.test(DOWN)
.image_noheader("istack-8");
.test(RSHIFT, F6)
.image_noheader("istack-7")
.test(ENTER)
.expect("6");
step("Interactive stack jump to level 2")
.test(UP, NOSHIFT, KEY2)
.image_noheader("istack-7b");
step("Interactive stack going up")
.test(UP)
.image_noheader("istack-8", 0, 1000);
step("Interactive stack Show")
.test(F2)
.image_noheader("istack-9", 0, 1000);
step("Interactive stack Show after EXIT")
.test(EXIT)
.image_noheader("istack-9b", 0, 1000);
step("Interactive stack Edit")
.test(UP, F1, UP, F1, DOWN, F1)
step("Interactive stack show with dot key")
.test(NOSHIFT, UP, UP, NOSHIFT, DOT)
.image_noheader("istack-9c", 0, 1000)
.test(ENTER)
.image_noheader("istack-9d", 0, 1000);
step("Interactive stack Echo")
.test(DOWN, F1, UP, F1, DOWN, F1)
.image_noheader("istack-10", 0, 1000)
.editor("666 555 666 ")
.test(CLEAR, EXIT);
.test(ENTER)
.editor("666 555 666 ")
.test(ENTER)
.expect("666")
.test(BSP)
.expect("555");
step("Interactive stack Echo without spaces")
.test(UP, RSHIFT, F1, UP, RSHIFT, F1, DOWN, RSHIFT, F1)
.image_noheader("istack-11", 0, 1000)
.editor("555666555")
.test(EXIT, EXIT);
step("Interactive stack jump to level 5")
.test(UP, NOSHIFT, KEY5)
.image_noheader("istack-12", 0, 1000);
step("Interactive stack jump to level 1")
.test(NOSHIFT, KEY1)
.image_noheader("istack-13", 0, 1000);
step("Interactive stack jump to level 11")
.test(NOSHIFT, KEY1)
.image_noheader("istack-14", 0, 1000);
step("Interactive stack jump to level 5")
.test(NOSHIFT, KEY5)
.image_noheader("istack-15", 0, 1000);
step("Interactive stack evaluate level 5")
.test(F3)
.image_noheader("istack-16", 0, 1000);
step("Interactive stack show level 5")
.test(NOSHIFT, DOT)
.image_noheader("istack-17", 0, 1000)
.test(ENTER);
step("Interactive stack info about 5")
.test(LSHIFT, F6)
.image_noheader("istack-18", 0, 1000)
.test(ENTER);
step("Interactive stack edit level 5")
.test(F6)
.image_noheader("istack-19", 0, 1000)
.editor("'(√(20·X))⁻¹'");
step("Interactive stack edit object that was at level 5")
.test(UP, MUL, KEY3, ADD, KEY2)
.editor("'(√(20·X))⁻¹·3+2'");
step("Interactive stack end editing object level 5")
.test(ENTER)
.image_noheader("istack-20", 0, 1000)
.test(ENTER, ADD)
.expect("1221");
step("Interactive stack memory sort")
.test(NOSHIFT, UP, NOSHIFT, KEY7, RSHIFT, F3)
.image_noheader("istack-21", 0, 1000);
step("Interactive stack revert")
.test(RSHIFT, F4)
.image_noheader("istack-22", 0, 1000);
step("Interactive stack value sort")
.test(NOSHIFT, KEY3, RSHIFT, F2)
.image_noheader("istack-23", 0, 1000);
step("Interactive stack revert")
.test(RSHIFT, F4)
.image_noheader("istack-24", 0, 1000);
step("Interactive stack DupN and sort")
.test(ENTER, CLEAR, "111 222 333 444", ENTER,
UP, KEY3, LSHIFT, F1, KEY6, RSHIFT, F2, ENTER)
.expect("222")
.test(BSP).expect("222")
.test(BSP).expect("333")
.test(BSP).expect("333")
.test(BSP).expect("444")
.test(BSP).expect("444")
.test(BSP).expect("111")
.test(BSP).noerror()
.test(BSP).error("Too few arguments");
step("Interactive stack DupN and non-reverted sort")
.test(ENTER, CLEAR, "123 456 789 ABC", ENTER,
UP, KEY3, LSHIFT, F1, KEY6, RSHIFT, F3, ENTER)
.expect("'ABC'")
.test(BSP).expect("'ABC'")
.test(BSP).expect("789")
.test(BSP).expect("789")
.test(BSP).expect("456")
.test(BSP).expect("456")
.test(BSP).expect("123")
.test(BSP).noerror()
.test(BSP).error("Too few arguments");
step("Interactive stack DupN and reverted sort")
.test(ENTER, CLEAR, "123 456 789 ABC", ENTER,
UP, KEY3, LSHIFT, F1, KEY6, RSHIFT, F3, RSHIFT, F4, ENTER)
.expect("456")
.test(BSP).expect("456")
.test(BSP).expect("789")
.test(BSP).expect("789")
.test(BSP).expect("'ABC'")
.test(BSP).expect("'ABC'")
.test(BSP).expect("123")
.test(BSP).noerror()
.test(BSP).error("Too few arguments");
step("Interactive stack Keep")
.test(ENTER, CLEAR, "123 456 789 ABC DEF GHI", ENTER,
UP, UP, UP, LSHIFT, F3, ENTER)
.expect("'GHI'")
.test(BSP).expect("'DEF'")
.test(BSP).expect("'ABC'")
.test(BSP).noerror()
.test(BSP).error("Too few arguments");
step("Interactive stack Swap and Level")
.test(ENTER, CLEAR, "123 456 789 ABC DEF GHI", ENTER,
UP, UP, UP, RSHIFT, F5, RSHIFT, F6, ENTER)
.expect("3")
.test(BSP).expect("'GHI'")
.test(BSP).expect("'DEF'")
.test(BSP).expect("789")
.test(BSP).expect("'ABC'")
.test(BSP).expect("456")
.test(BSP).expect("123")
.test(BSP).noerror()
.test(BSP).error("Too few arguments");
}

View file

@ -61,6 +61,7 @@ struct tests
void keyboard_entry();
void data_types();
void editor_operations();
void interactive_stack_operations();
void stack_operations();
void arithmetic();
void global_variables();

View file

@ -107,6 +107,7 @@ user_interface::user_interface()
nextRefresh(~0U),
dirty(),
editing(),
editingLevel(0),
cmdIndex(0),
clipboard(),
shift(false),
@ -350,11 +351,36 @@ bool user_interface::end_edit()
// We successfully parsed the line
editor_save(saved, false);
clear_editor();
this->editing = nullptr;
if (Settings.SaveStack())
rt.save();
save<bool> no_halt(program::halted, false);
cmds->run(Settings.SaveLastArguments());
if (editingLevel)
{
bool first = true;
for (auto obj : *cmds)
{
if (first)
{
rt.stack(editingLevel - 1, obj);
first = false;
}
else
{
rt.push(obj);
rt.rolld(editingLevel);
}
}
Stack.interactive = editingLevel;
editing = nullptr;
editingLevel = 0;
dirtyStack = true;
}
else
{
editing = nullptr;
editingLevel = 0;
if (Settings.SaveStack())
rt.save();
save<bool> no_halt(program::halted, false);
cmds->run(Settings.SaveLastArguments());
}
}
else
{
@ -1213,7 +1239,7 @@ uint user_interface::menu_planes()
}
else if (Stack.interactive)
{
planes = 2;
planes = 3;
}
else
{
@ -1387,8 +1413,9 @@ bool user_interface::draw_menus()
{
static cstring stackMenu[] =
{
"Echo", "Show", "Level", "Roll↓", "Pick", "→List",
"DupN", "DropN", "Keep", "Roll↑", "Sort", "Revert"
"Echo", "Show", "Eval", "Roll↓", "Pick", "Edit",
"DupN", "DropN", "Keep", "Roll↑", "→List", "Info",
"EchoNSp", "ValSort", "MemSort", "Revert", "Swap", "Level"
};
labels = stackMenu + 6 * plane;
}
@ -3655,7 +3682,7 @@ bool user_interface::handle_editing(int key)
// ----------------------------------------------------------------------------
{
bool consumed = false;
size_t editing = rt.editing();
size_t isEditing = rt.editing();
if (uint interactive = Stack.interactive)
{
@ -3696,10 +3723,7 @@ bool user_interface::handle_editing(int key)
dirtyStack = true;
break;
case KEY_F1:
if (xshift)
{
}
else if (shift)
if (shift)
{
// DupN
for (uint i = 0; i < interactive; i++)
@ -3714,7 +3738,8 @@ bool user_interface::handle_editing(int key)
{
size_t sz = obj->edit();
cursor += sz;
edit(unicode(' '), PROGRAM, false);
if (!shift && !xshift)
edit(unicode(' '), PROGRAM, false);
edRows = 0;
dirtyEditor = true;
}
@ -3724,6 +3749,10 @@ bool user_interface::handle_editing(int key)
case KEY_F2: // DropN
if (xshift)
{
// Sort by value
typedef int (*qsort_fn)(const void *, const void*);
qsort(rt.stack_base(), interactive,
sizeof(object_p), qsort_fn(value_compare));
}
else if (shift)
{
@ -3741,6 +3770,10 @@ bool user_interface::handle_editing(int key)
case KEY_F3:
if (xshift)
{
// Sort by memory representation
typedef int (*qsort_fn)(const void *, const void*);
qsort(rt.stack_base(), interactive,
sizeof(object_p), qsort_fn(memory_compare));
}
else if (shift)
{
@ -3755,14 +3788,34 @@ bool user_interface::handle_editing(int key)
}
else
{
if (integer_p depth = integer::make(interactive))
rt.push(depth);
// Evaluate the given item and insert results in stack
rt.roll(interactive);
if (object_g obj = rt.pop())
{
size_t odepth = rt.depth();
obj->evaluate();
size_t ndepth = rt.depth();
size_t diff = ndepth - odepth - 1;
while (ndepth > odepth)
{
rt.rolld(interactive + diff);
odepth++;
}
}
}
dirtyStack = true;
break;
case KEY_F4:
if (xshift)
{
// Revert
for (uint i = 0; i < interactive / 2; i++)
{
object_p a = rt.stack(i);
object_p b = rt.stack(interactive + ~i);
rt.stack(i, b);
rt.stack(interactive + ~i, a);
}
}
else if (shift)
{
@ -3779,13 +3832,14 @@ bool user_interface::handle_editing(int key)
case KEY_F5:
if (xshift)
{
// Swap
goto swap;
}
else if (shift)
{
// Sort
typedef int (*qsort_fn)(const void *, const void*);
qsort(rt.stack_base(), interactive,
sizeof(object_p), qsort_fn(value_compare));
// To List
to_list(interactive);
Stack.interactive = 1;
}
else
{
@ -3798,22 +3852,51 @@ bool user_interface::handle_editing(int key)
case KEY_F6:
if (xshift)
{
// Put level on the stack
if (integer_p depth = integer::make(interactive))
rt.push(depth);
}
else if (shift)
{
// Revert
for (uint i = 0; i < interactive / 2; i++)
// Info
if (object_g obj = rt.stack(interactive - 1))
{
object_p a = rt.stack(i);
object_p b = rt.stack(interactive + ~i);
rt.stack(i, b);
rt.stack(interactive + ~i, a);
size_t size = obj->size();
size_t maxsize = (Settings.WordSize() + 7) / 8;
size_t hashsize = size > maxsize ? maxsize : size;
gcbytes bytes = byte_p(obj);
#if CONFIG_FIXED_BASED_OBJECTS
// Force base 16 if we have that option
const object::id type = object::ID_hex_bignum;
#else // !CONFIG_FIXED_BASED_OBJECTS
const object::id type = object::ID_based_bignum;
#endif // CONFIG_FIXED_BASED_OBJECTS
if (bignum_g bin = rt.make<bignum>(type, bytes, hashsize))
{
char sizebuf[20];
char valbuf[40];
snprintf(sizebuf, sizeof(sizebuf), "%zu bytes", size);
bin->render(valbuf, sizeof(valbuf));
draw_message("Object info", sizebuf, valbuf);
wait_for_key_press();
}
}
}
else
{
// To List
to_list(interactive);
// Edit
if (object_p obj = rt.stack(interactive - 1))
{
editingLevel = interactive;
editing = obj;
size_t sz = obj->edit();
cursor += sz;
edRows = 0;
dirtyEditor = true;
dirtyStack = true;
Stack.interactive = 0;
last = 0;
}
}
dirtyStack = true;
break;
@ -3825,6 +3908,22 @@ bool user_interface::handle_editing(int key)
Stack.interactive = 0;
return false;
}
else if (shift)
{
}
else
{
swap:
// Swap
if (interactive + 1 < rt.depth())
{
object_p x = rt.stack(interactive - 1);
object_p y = rt.stack(interactive);
rt.stack(interactive, x);
rt.stack(interactive - 1, y);
dirtyStack = true;
}
}
break;
case KEY_0: digit = 0; break;
@ -3864,9 +3963,9 @@ bool user_interface::handle_editing(int key)
{
case KEY_XEQ:
// XEQ is used to enter algebraic / equation objects
if ((!editing || mode != BASED) && !shift && !xshift)
if ((!isEditing || mode != BASED) && !shift && !xshift)
{
bool is_eqn = editing && is_algebraic(mode);
bool is_eqn = isEditing && is_algebraic(mode);
edit(is_eqn ? '(' : '\'', ALGEBRAIC);
last = 0;
return true;
@ -3886,7 +3985,7 @@ bool user_interface::handle_editing(int key)
last = 0;
return true;
}
else if (editing)
else if (isEditing)
{
// Stick to space role while editing, do not EVAL, repeat
if (mode == PARENTHESES)
@ -3912,7 +4011,7 @@ bool user_interface::handle_editing(int key)
}
}
if (editing)
if (isEditing)
{
record(user_interface, "Editing key %d", key);
switch (key)
@ -3936,10 +4035,10 @@ bool user_interface::handle_editing(int key)
else
{
utf8 ed = rt.editor();
if (shift && cursor < editing)
if (shift && cursor < isEditing)
{
// Shift + Backspace = Delete to right of cursor
uint after = utf8_next(ed, cursor, editing);
uint after = utf8_next(ed, cursor, isEditing);
if (utf8_codepoint(ed + cursor) == '\n')
edRows = 0;
remove(cursor, after - cursor);
@ -4005,10 +4104,11 @@ bool user_interface::handle_editing(int key)
{
editor_save(false);
clear_editor();
if (this->editing)
if (editing)
{
rt.push(this->editing);
this->editing = nullptr;
if (!editingLevel)
rt.push(editing);
editing = nullptr;
dirtyEditor = true;
dirtyStack = true;
}
@ -4068,12 +4168,12 @@ bool user_interface::handle_editing(int key)
{
return false;
}
else if (cursor < editing)
else if (cursor < isEditing)
{
font_p edFont = Settings.editor_font(edRows > 2);
utf8 ed = rt.editor();
unicode cp = utf8_codepoint(ed + cursor);
uint ncursor = utf8_next(ed, cursor, editing);
uint ncursor = utf8_next(ed, cursor, isEditing);
if (cp != '\n')
{
draw_cursor(-1, ncursor);
@ -4128,7 +4228,8 @@ bool user_interface::handle_editing(int key)
{
if (object_p obj = rt.pop())
{
this->editing = obj;
editing = obj;
editingLevel = 0;
obj->edit();
dirtyEditor = true;
return true;

View file

@ -239,6 +239,7 @@ protected:
uint nextRefresh; // Time for next refresh
rect dirty; // Dirty rectangles
object_g editing; // Object being edited if any
uint editingLevel; // Stack level being edited
uint cmdIndex; // Command index for next command to save
uint cmdHistoryIndex; // Command index for next command history
text_g history[HISTORY]; // Command-line history