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>
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 4 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 4 KiB |
BIN
color-images/istack-11.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
color-images/istack-12.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
color-images/istack-13.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
color-images/istack-14.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
color-images/istack-15.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
color-images/istack-16.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
color-images/istack-17.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
color-images/istack-18.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
color-images/istack-19.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 4 KiB |
BIN
color-images/istack-20.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
color-images/istack-21.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
color-images/istack-22.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
color-images/istack-23.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
color-images/istack-24.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 3 KiB After Width: | Height: | Size: 3.9 KiB |
BIN
color-images/istack-7b.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 4.5 KiB |
BIN
color-images/istack-9c.png
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
color-images/istack-9d.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 4 KiB |
BIN
images/istack-11.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
images/istack-12.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
images/istack-13.png
Normal file
After Width: | Height: | Size: 4 KiB |
BIN
images/istack-14.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
images/istack-15.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
images/istack-16.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
images/istack-17.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
images/istack-18.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
images/istack-19.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.9 KiB |
BIN
images/istack-20.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
images/istack-21.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
images/istack-22.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
images/istack-23.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
images/istack-24.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.8 KiB |
BIN
images/istack-7b.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 3 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 4.4 KiB |
BIN
images/istack-9c.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
images/istack-9d.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
|
@ -501,7 +501,6 @@ COMMAND_BODY(Bytes)
|
|||
if (rt.top(bin))
|
||||
if (rt.push(integer::make(size)))
|
||||
return OK;
|
||||
|
||||
}
|
||||
return ERROR;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
|
@ -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
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
|
171
src/tests.cc
|
@ -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("1 221");
|
||||
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");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|