add copy, start on paste and text selections
This commit is contained in:
parent
70f51642cd
commit
342e342a50
2
src/dlib
2
src/dlib
@ -1 +1 @@
|
|||||||
Subproject commit 2af4a293148aadac84d9fec3505d2adcdb747298
|
Subproject commit 92c4f8eb665e9fc7a58dc9631bb6f26a0828a638
|
||||||
@ -15,12 +15,26 @@ struct FlatBuffer
|
|||||||
LineStart[] line_starts;
|
LineStart[] line_starts;
|
||||||
u64 length;
|
u64 length;
|
||||||
u64 lf_count;
|
u64 lf_count;
|
||||||
|
|
||||||
i64 buf_pos;
|
i64 buf_pos;
|
||||||
i64 offset;
|
i64 offset;
|
||||||
i64 rows;
|
i64 rows;
|
||||||
|
|
||||||
|
I64Vec2 sel;
|
||||||
|
SelectMode sel_mode;
|
||||||
|
|
||||||
bool dirty;
|
bool dirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum SelectMode
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Normal,
|
||||||
|
Line,
|
||||||
|
}
|
||||||
|
|
||||||
|
alias SM = SelectMode;
|
||||||
|
|
||||||
struct LineStart
|
struct LineStart
|
||||||
{
|
{
|
||||||
u64 pos;
|
u64 pos;
|
||||||
@ -98,6 +112,7 @@ CreateFlatBuffer(u8[] data)
|
|||||||
data: buf,
|
data: buf,
|
||||||
length: cast(u64)data.length,
|
length: cast(u64)data.length,
|
||||||
lf_count: CountLF(data),
|
lf_count: CountLF(data),
|
||||||
|
sel: -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
fb.tk = CreateTokenizer(&fb);
|
fb.tk = CreateTokenizer(&fb);
|
||||||
@ -277,7 +292,42 @@ Insert(FlatBuffer* fb, u8[] insert, u64 length, u64 pos)
|
|||||||
|
|
||||||
Reset(&fb.arena);
|
Reset(&fb.arena);
|
||||||
|
|
||||||
AdjustOffset(fb);
|
UpdateOffset(fb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ToggleSelection(FlatBuffer* fb, SelectMode mode)
|
||||||
|
{
|
||||||
|
if(fb.sel_mode == SM.None)
|
||||||
|
{
|
||||||
|
StartSelection(fb, mode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EndSelection(fb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
StartSelection(FlatBuffer* fb, SelectMode mode)
|
||||||
|
{
|
||||||
|
fb.sel_mode = mode;
|
||||||
|
|
||||||
|
if(mode == SM.Normal)
|
||||||
|
{
|
||||||
|
fb.sel = fb.buf_pos;
|
||||||
|
}
|
||||||
|
else if(mode == SM.Line)
|
||||||
|
{
|
||||||
|
fb.sel = CurrentLine(fb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EndSelection(FlatBuffer* fb)
|
||||||
|
{
|
||||||
|
fb.sel = -1;
|
||||||
|
fb.sel_mode = SM.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -790,14 +840,30 @@ Move(FlatBuffer* fb, Input key, Modifier md)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AdjustOffset(fb);
|
UpdateOffset(fb);
|
||||||
U64Vec2 p = VecPos(fb);
|
UpdateSelection(fb);
|
||||||
|
|
||||||
|
Logf("selection %s", fb.sel.v);
|
||||||
|
|
||||||
return taken;
|
return taken;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AdjustOffset(FlatBuffer* fb)
|
UpdateSelection(FlatBuffer* fb)
|
||||||
|
{
|
||||||
|
if(fb.sel_mode == SM.Normal)
|
||||||
|
{
|
||||||
|
fb.sel.y = fb.buf_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fb.sel_mode == SM.Line)
|
||||||
|
{
|
||||||
|
fb.sel.y = CurrentLine(fb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
UpdateOffset(FlatBuffer* fb)
|
||||||
{
|
{
|
||||||
if(fb.rows > 0) with(fb)
|
if(fb.rows > 0) with(fb)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -22,6 +22,7 @@ debug bool g_frame_continue = false;
|
|||||||
struct EditorCtx
|
struct EditorCtx
|
||||||
{
|
{
|
||||||
Arena arena;
|
Arena arena;
|
||||||
|
PlatformWindow* window;
|
||||||
UIPanel* base_panel;
|
UIPanel* base_panel;
|
||||||
u64 panel_id;
|
u64 panel_id;
|
||||||
EditState state;
|
EditState state;
|
||||||
@ -61,6 +62,23 @@ struct Editor
|
|||||||
u64 line_offset;
|
u64 line_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ChangeStacks
|
||||||
|
{
|
||||||
|
Arena arena;
|
||||||
|
u64 current_pos;
|
||||||
|
u8[] current_str;
|
||||||
|
u64 current_len;
|
||||||
|
EditorChange* undos;
|
||||||
|
EditorChange* redos;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct EditorChange
|
||||||
|
{
|
||||||
|
u8[] str;
|
||||||
|
u64 pos;
|
||||||
|
EditorChange* next;
|
||||||
|
}
|
||||||
|
|
||||||
struct Command
|
struct Command
|
||||||
{
|
{
|
||||||
u8[] name;
|
u8[] name;
|
||||||
@ -79,6 +97,8 @@ enum CmdType
|
|||||||
OpenFile,
|
OpenFile,
|
||||||
SaveFile,
|
SaveFile,
|
||||||
CreateFile,
|
CreateFile,
|
||||||
|
VSplit,
|
||||||
|
HSplit,
|
||||||
}
|
}
|
||||||
|
|
||||||
alias CT = CmdType;
|
alias CT = CmdType;
|
||||||
@ -148,6 +168,7 @@ InitEditorCtx(PlatformWindow* window)
|
|||||||
InitUICtx(window);
|
InitUICtx(window);
|
||||||
|
|
||||||
EditorCtx ctx = {
|
EditorCtx ctx = {
|
||||||
|
window: window,
|
||||||
arena: CreateArena(MB(2)),
|
arena: CreateArena(MB(2)),
|
||||||
cmd: {
|
cmd: {
|
||||||
arena: CreateArena(MB(1)),
|
arena: CreateArena(MB(1)),
|
||||||
@ -473,6 +494,9 @@ Shift(Modifier md)
|
|||||||
void
|
void
|
||||||
HandleInputs(EditorCtx* ctx, Inputs* inputs)
|
HandleInputs(EditorCtx* ctx, Inputs* inputs)
|
||||||
{
|
{
|
||||||
|
u8[] cb_text;
|
||||||
|
FlatBuffer* fb = !Nil(GetFocusedPanel()) ? &(GetFocusedPanel()).ed.buf : null;
|
||||||
|
|
||||||
for(auto node = inputs.list.first; node != null; node = node.next)
|
for(auto node = inputs.list.first; node != null; node = node.next)
|
||||||
{
|
{
|
||||||
bool taken = false;
|
bool taken = false;
|
||||||
@ -480,7 +504,6 @@ HandleInputs(EditorCtx* ctx, Inputs* inputs)
|
|||||||
Input key = node.value.key;
|
Input key = node.value.key;
|
||||||
Modifier md = node.value.md;
|
Modifier md = node.value.md;
|
||||||
bool pressed = node.value.pressed;
|
bool pressed = node.value.pressed;
|
||||||
FlatBuffer* fb = !Nil(GetFocusedPanel()) ? &(GetFocusedPanel()).ed.buf : null;
|
|
||||||
|
|
||||||
if (pressed)
|
if (pressed)
|
||||||
{
|
{
|
||||||
@ -529,8 +552,18 @@ HandleInputs(EditorCtx* ctx, Inputs* inputs)
|
|||||||
} break;
|
} break;
|
||||||
case v:
|
case v:
|
||||||
{
|
{
|
||||||
AddEditor(ctx, GetFocusedPanel(), A2D.X);
|
if(Ctrl(md))
|
||||||
taken = true;
|
{
|
||||||
|
cb_text = ClipboardText(ctx.window);
|
||||||
|
}
|
||||||
|
if(Shift(md))
|
||||||
|
{
|
||||||
|
ToggleSelection(fb, SM.Line);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ToggleSelection(fb, SM.Normal);
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
case c:
|
case c:
|
||||||
{
|
{
|
||||||
@ -566,6 +599,11 @@ HandleInputs(EditorCtx* ctx, Inputs* inputs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
InsertInputToBuf(ctx);
|
InsertInputToBuf(ctx);
|
||||||
|
|
||||||
|
if(cb_text.length > 0)
|
||||||
|
{
|
||||||
|
Insert(fb, cb_text, cb_text.length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -721,6 +759,14 @@ GetCommands(CmdPalette* cmd)
|
|||||||
name: CastStr!(u8)("create"),
|
name: CastStr!(u8)("create"),
|
||||||
type: CT.CreateFile,
|
type: CT.CreateFile,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: CastStr!(u8)("vsplit"),
|
||||||
|
type: CT.VSplit,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: CastStr!(u8)("hsplit"),
|
||||||
|
type: CT.HSplit,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
Reset(&cmd.arena);
|
Reset(&cmd.arena);
|
||||||
@ -770,16 +816,24 @@ HandleCmdMode(EditorCtx* ctx, InputEvent ev)
|
|||||||
{
|
{
|
||||||
case Enter:
|
case Enter:
|
||||||
{
|
{
|
||||||
if(cmd.current.type == CT.None)
|
if(cmd.current.type == CT.None && cmd.commands.length > 0)
|
||||||
|
{
|
||||||
|
if(cmd.commands[cmd.selected].type == CT.OpenFile)
|
||||||
{
|
{
|
||||||
goto case Tab;
|
goto case Tab;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cmd.current = cmd.commands[cmd.selected];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UIPanel* p = GetFocusedPanel();
|
||||||
|
|
||||||
switch(cmd.current.type)
|
switch(cmd.current.type)
|
||||||
{
|
{
|
||||||
case CT.OpenFile:
|
case CT.OpenFile:
|
||||||
{
|
{
|
||||||
UIPanel* p = GetFocusedPanel();
|
|
||||||
if(!Nil(p) && cmd.selected >= 0 && cmd.selected < cmd.opt_strs.length)
|
if(!Nil(p) && cmd.selected >= 0 && cmd.selected < cmd.opt_strs.length)
|
||||||
{
|
{
|
||||||
OpenFile(p.ed, cmd.opt_strs[cmd.selected]);
|
OpenFile(p.ed, cmd.opt_strs[cmd.selected]);
|
||||||
@ -787,12 +841,15 @@ HandleCmdMode(EditorCtx* ctx, InputEvent ev)
|
|||||||
} break;
|
} break;
|
||||||
case CT.SaveFile:
|
case CT.SaveFile:
|
||||||
{
|
{
|
||||||
UIPanel* p = GetFocusedPanel();
|
|
||||||
if(!Nil(p))
|
if(!Nil(p))
|
||||||
{
|
{
|
||||||
SaveFile(p.ed, GetParam(cmd));
|
SaveFile(p.ed, GetParam(cmd));
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
case CT.VSplit, CT.HSplit:
|
||||||
|
{
|
||||||
|
AddEditor(ctx, p, cmd.current.type == CT.VSplit ? A2D.X : A2D.Y);
|
||||||
|
} break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -800,15 +857,10 @@ HandleCmdMode(EditorCtx* ctx, InputEvent ev)
|
|||||||
} goto CmdInputEnd;
|
} goto CmdInputEnd;
|
||||||
case Backspace:
|
case Backspace:
|
||||||
{
|
{
|
||||||
if(cmd.icount > 0)
|
if(CondIncr!(-1)(cmd.icount > 0, &cmd.icount) && cmd.buffer[cmd.icount] == ' ')
|
||||||
{
|
|
||||||
cmd.icount -= 1;
|
|
||||||
|
|
||||||
if(cmd.buffer[cmd.icount] == ' ')
|
|
||||||
{
|
{
|
||||||
cmd.current = cast(Command)NO_CMD;
|
cmd.current = cast(Command)NO_CMD;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} break;
|
} break;
|
||||||
case Space:
|
case Space:
|
||||||
{
|
{
|
||||||
@ -827,17 +879,11 @@ HandleCmdMode(EditorCtx* ctx, InputEvent ev)
|
|||||||
} break;
|
} break;
|
||||||
case Up:
|
case Up:
|
||||||
{
|
{
|
||||||
if(cmd.selected > 0)
|
CondIncr!(-1)(cmd.selected > 0, &cmd.selected);
|
||||||
{
|
|
||||||
cmd.selected -= 1;
|
|
||||||
}
|
|
||||||
} break;
|
} break;
|
||||||
case Down:
|
case Down:
|
||||||
{
|
{
|
||||||
if(cmd.selected < cmd.opt_strs.length-1)
|
CondIncr!(+1)(cmd.selected < cmd.opt_strs.length-1, &cmd.selected);
|
||||||
{
|
|
||||||
cmd.selected += 1;
|
|
||||||
}
|
|
||||||
} break;
|
} break;
|
||||||
mixin(TextLineCharCases());
|
mixin(TextLineCharCases());
|
||||||
default: break;
|
default: break;
|
||||||
|
|||||||
@ -129,6 +129,7 @@ struct UICtx
|
|||||||
UIStack!(f32)* edge_softness;
|
UIStack!(f32)* edge_softness;
|
||||||
|
|
||||||
i64 highlighted_char;
|
i64 highlighted_char;
|
||||||
|
I64Vec2 selected;
|
||||||
u32 tab_width;
|
u32 tab_width;
|
||||||
f32 text_size;
|
f32 text_size;
|
||||||
|
|
||||||
@ -176,6 +177,7 @@ struct UIItem
|
|||||||
UISize[2] size_info;
|
UISize[2] size_info;
|
||||||
Vec2 adjustment;
|
Vec2 adjustment;
|
||||||
i64 highlighted_char;
|
i64 highlighted_char;
|
||||||
|
I64Vec2 selected;
|
||||||
|
|
||||||
// Calculated Parameters
|
// Calculated Parameters
|
||||||
Vec4[4] color;
|
Vec4[4] color;
|
||||||
|
|||||||
@ -378,7 +378,16 @@ EditorView(UIPanel* panel)
|
|||||||
|
|
||||||
Container(ScratchName(panel.id, "lines"), UISize(ST.Percentage, 1.0), UISize(ST.Percentage, 1.0), A2D.Y);
|
Container(ScratchName(panel.id, "lines"), UISize(ST.Percentage, 1.0), UISize(ST.Percentage, 1.0), A2D.Y);
|
||||||
{
|
{
|
||||||
|
I64Vec2 sel = ed.buf.sel;
|
||||||
|
if(sel.x > sel.y)
|
||||||
|
{
|
||||||
|
i64 t = sel.y;
|
||||||
|
sel.y = sel.x;
|
||||||
|
sel.x = t;
|
||||||
|
}
|
||||||
|
|
||||||
U64Vec2 pos = VecPos(&ed.buf);
|
U64Vec2 pos = VecPos(&ed.buf);
|
||||||
|
SelectMode sm = ed.buf.sel_mode;
|
||||||
u64 i = 0;
|
u64 i = 0;
|
||||||
for(LineBuffer* buf = ed.linebufs.first; buf != null; buf = buf.next, i += 1)
|
for(LineBuffer* buf = ed.linebufs.first; buf != null; buf = buf.next, i += 1)
|
||||||
{
|
{
|
||||||
@ -395,6 +404,10 @@ EditorView(UIPanel* panel)
|
|||||||
Push!("highlighted_char")(pos.x);
|
Push!("highlighted_char")(pos.x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(sm == SM.Line && line_no >= sel.x && line_no <= sel.y)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
TextPart* tp = WrappedTextLine(buf.text, panel.id, text_size, line_no, buf.style);
|
TextPart* tp = WrappedTextLine(buf.text, panel.id, text_size, line_no, buf.style);
|
||||||
height += (text_size * tp.count);
|
height += (text_size * tp.count);
|
||||||
if(TextClicked(tp))
|
if(TextClicked(tp))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user