diff --git a/src/gd_con.erl b/src/gd_con.erl index 172f705..5cc4295 100644 --- a/src/gd_con.erl +++ b/src/gd_con.erl @@ -652,7 +652,7 @@ do_sign_mess(Request = #{"public_id" := ID, "payload" := Message}, #s{wallet = #wallet{keys = Keys}}) -> case lists:keyfind(ID, #key.id, Keys) of #key{pair = #{secret := SecKey}} -> - Sig = base64:encode(sign_message(list_to_binary(Message), SecKey)), + Sig = base64:encode(hz:sign_message(list_to_binary(Message), SecKey)), do_sign_mess2(Request#{"signature" => Sig}); false -> gd_gui:trouble({bad_key, ID}) @@ -675,37 +675,6 @@ do_sign_mess2(Request = #{"url" := URL}) -> end. -% TODO: Should probably be part of Hakuzaru -sign_message(Message, SecKey) -> - Prefix = <<"Gajumaru Signed Message:\n">>, - {ok, PSize} = vencode(byte_size(Prefix)), - {ok, MSize} = vencode(byte_size(Message)), - Smashed = iolist_to_binary([PSize, Prefix, MSize, Message]), - {ok, Hashed} = eblake2:blake2b(32, Smashed), - ecu_eddsa:sign_detached(Hashed, SecKey). - - -vencode(N) when N < 0 -> - {error, {negative_N, N}}; -vencode(N) when N < 16#FD -> - {ok, <>}; -vencode(N) when N =< 16#FFFF -> - NBytes = eu(N, 2), - {ok, <<16#FD, NBytes/binary>>}; -vencode(N) when N =< 16#FFFF_FFFF -> - NBytes = eu(N, 4), - {ok, <<16#FE, NBytes/binary>>}; -vencode(N) when N < (2 bsl 64) -> - NBytes = eu(N, 8), - {ok, <<16#FF, NBytes/binary>>}. - -eu(N, Size) -> - Bytes = binary:encode_unsigned(N, little), - NExtraZeros = Size - byte_size(Bytes), - ExtraZeros = << <<0>> || _ <- lists:seq(1, NExtraZeros) >>, - <>. - - do_sign_tx(Request = #{"public_id" := ID, "payload" := CallData, "network_id" := NID}, #s{wallet = #wallet{keys = Keys}}) -> BinNID = list_to_binary(NID), diff --git a/src/gd_sophia_editor.erl b/src/gd_sophia_editor.erl index 99f73a7..6319610 100644 --- a/src/gd_sophia_editor.erl +++ b/src/gd_sophia_editor.erl @@ -1,39 +1,103 @@ -module(gd_sophia_editor). --export([new/3, get_text/1, set_text/2]). +-export([new/1, update/2, + get_text/1, set_text/2]). +-include("$zx_include/zx_logger.hrl"). -include_lib("wx/include/wx.hrl"). -new(Parent, Id, Opts) -> - STC = wxStyledTextCtrl:new(Parent, [{id, Id} | Opts]), - - %% Set up the container lexer - wxStyledTextCtrl:setLexer(STC, ?wxSTC_LEX_CONTAINER), +%%% Formatting Constants +%% Style labels +-define(DEFAULT, 0). +-define(KEYWORD, 1). +-define(IDENTIFIER, 2). +-define(COMMENT, 3). +-define(STRING, 4). +-define(NUMBER, 5). +-define(OPERATOR, 6). + + + +%% Color palette + +% Intensities: +-define(H, 255). % High +-define(M, 192). % Medium +-define(L, 128). % Low +-define(Z, 0). % Zilch + + +% RGB values +% R G B +-define(black, {?Z, ?Z, ?Z}). +-define(light_red, {?H, ?Z, ?Z}). +-define(light_green, {?Z, ?H, ?Z}). +-define(light_blue, {?Z, ?Z, ?H}). +-define(yellow, {?H, ?H, ?Z}). +-define(light_magenta, {?H, ?Z, ?H}). +-define(light_cyan, {?Z, ?H, ?H}). +-define(high_white, {?H, ?H, ?H}). +-define(red, {?L, ?Z, ?Z}). +-define(green, {?Z, ?L, ?Z}). +-define(blue, {?Z, ?Z, ?L}). +-define(brown, {?L, ?L, ?Z}). +-define(magenta, {?L, ?Z, ?L}). +-define(cyan, {?Z, ?L, ?L}). +-define(grey, {?L, ?L, ?L}). +-define(white, {?M, ?M, ?M}). + +styles() -> + [?DEFAULT, + ?KEYWORD, + ?IDENTIFIER, + ?COMMENT, + ?STRING, + ?NUMBER, + ?OPERATOR]. + +palette(light) -> + #{?DEFAULT => ?black, + ?KEYWORD => ?blue, + ?IDENTIFIER => ?cyan, + ?COMMENT => ?grey, + ?STRING => ?red, + ?NUMBER => ?magenta, + ?OPERATOR => ?brown}; +palette(dark) -> + #{?DEFAULT => ?white, + ?KEYWORD => ?light_cyan, + ?IDENTIFIER => ?green, + ?COMMENT => ?grey, + ?STRING => ?light_red, + ?NUMBER => ?light_magenta, + ?OPERATOR => ?yellow}. + +color_mode() -> + light. + + +new(Parent) -> + STC = wxStyledTextCtrl:new(Parent), + ok = wxStyledTextCtrl:setLexer(STC, ?wxSTC_LEX_CONTAINER), FontSize = 13, - Mono = wxFont:new(FontSize, ?wxFONTFAMILY_TELETYPE, ?wxFONTSTYLE_NORMAL, - ?wxFONTWEIGHT_NORMAL, [{face, "Monospace"}]), - lists:foreach( - fun(Style) -> - wxStyledTextCtrl:styleSetFont(STC, Style, Mono) - end, - lists:seq(0, 6) - ), - %% - wxStyledTextCtrl:styleSetFont(STC, ?wxSTC_STYLE_DEFAULT, Mono), - %% Define styles - set_colors(STC), - %% Connect the styling event - wxStyledTextCtrl:connect( - STC, 'stc_styleneeded', - [{callback, fun(Event, _) -> style_needed(Event, STC) end}]), + Mono = wxFont:new(FontSize, + ?wxFONTFAMILY_TELETYPE, + ?wxFONTSTYLE_NORMAL, + ?wxFONTWEIGHT_NORMAL, + [{face, "Monospace"}]), + + SetMonospace = fun(Style) -> wxStyledTextCtrl:styleSetFont(STC, Style, Mono) end, + ok = lists:foreach(SetMonospace, styles()), + ok = wxStyledTextCtrl:styleSetFont(STC, ?wxSTC_STYLE_DEFAULT, Mono), + ok = set_colors(STC), STC. get_text(STC) -> wxStyledTextCtrl:getText(STC). set_text(STC, Text) -> - wxStyledTextCtrl:setText(STC, Text), + ok = wxStyledTextCtrl:setText(STC, Text), %% Force Scintilla to request styling for the entire text wxStyledTextCtrl:colourise(STC, 0, -1). @@ -41,15 +105,16 @@ set_text(STC, Text) -> set_colors(STC) -> wxStyledTextCtrl:styleClearAll(STC), - wxStyledTextCtrl:styleSetForeground(STC, 0, {0, 0, 0}), % Default: Black - wxStyledTextCtrl:styleSetForeground(STC, 1, {0, 0, 192}), % Keywords: Deep Blue - wxStyledTextCtrl:styleSetForeground(STC, 2, {0, 0, 0}), % Identifiers: Black - wxStyledTextCtrl:styleSetForeground(STC, 3, {128, 128, 128}), % Comments: Gray - wxStyledTextCtrl:styleSetForeground(STC, 4, {163, 21, 21}), % Strings/Chars: Reddish - wxStyledTextCtrl:styleSetForeground(STC, 5, {128, 0, 128}), % Numbers: Purple - wxStyledTextCtrl:styleSetForeground(STC, 6, {0, 0, 0}). % Operators: Black + Palette = palette(color_mode()), + Colorize = + fun(Style) -> + Color = maps:get(Style, Palette), + wxStyledTextCtrl:styleSetForeground(STC, Style, Color) + end, + lists:foreach(Colorize, styles()). -style_needed(_Event, STC) -> + +update(_Event, STC) -> try StartPos = wxStyledTextCtrl:getEndStyled(STC), EndPos = wxStyledTextCtrl:getLength(STC), @@ -91,21 +156,21 @@ classify_style(Type, Value) -> case Type of symbol -> case lists:member(Value, keywords()) of - true -> 1; - false -> 6 + true -> ?KEYWORD; + false -> ?OPERATOR end; - id -> 2; - qid -> 2; - con -> 2; - qcon -> 2; - tvar -> 2; - string -> 4; - char -> 4; - int -> 5; - hex -> 5; - bytes -> 5; - skip -> 3; - _Other -> 1 + id -> ?IDENTIFIER; + qid -> ?IDENTIFIER; + con -> ?IDENTIFIER; + qcon -> ?IDENTIFIER; + tvar -> ?IDENTIFIER; + string -> ?STRING; + char -> ?STRING; + int -> ?NUMBER; + hex -> ?NUMBER; + bytes -> ?NUMBER; + skip -> ?COMMENT; + _Other -> ?DEFAULT end. type_and_value({Type,_Line,Value}) -> {Type, Value}; diff --git a/src/gd_v_devman.erl b/src/gd_v_devman.erl index 434abcf..675eaca 100644 --- a/src/gd_v_devman.erl +++ b/src/gd_v_devman.erl @@ -258,6 +258,9 @@ handle_event(E = #wx{event = #wxCommand{type = command_button_clicked}, State end, {noreply, NewState}; +handle_event(#wx{event = Event = #wxStyledText{type = stc_styleneeded}, obj = Win}, State) -> + ok = style(State, Win, Event), + {noreply, State}; handle_event(#wx{event = #wxClose{}}, State = #s{frame = Frame, prefs = Prefs}) -> Geometry = case wxTopLevelWindow:isMaximized(Frame) of @@ -293,6 +296,15 @@ terminate(Reason, State) -> %%% Doers +style(#s{code = {Codebook, Pages}}, Win, Event) -> + case lists:keyfind(Win, #p.win, Pages) of + #p{code = STC} -> + tell("Received style event.~nWin: ~p~nEvent: ~p", [Win, Event]), + gd_sophia_editor:update(Event, STC); + false -> + tell("Received bogus style event.~nWin: ~p~nEvent: ~p", [Win, Event]) + end. + clicked(State = #s{cons = {Consbook, Contracts}}, Name) -> case wxNotebook:getSelection(Consbook) of ?wxNOT_FOUND -> @@ -506,30 +518,13 @@ add_code_page2(State, {hash, Address}) -> open_hash2(State, Address). add_code_page(State = #s{tabs = TopBook, code = {Codebook, Pages}}, Location, Code) -> -% FIXME: One of these days we need to define the text area as a wxStyledTextCtrl and will -% have to contend with system theme issues (light/dark themese, namely) -% Leaving this little thing here to remind myself how any of that works later. -% The call below returns a wx_color4() type (not that we need alpha...). -% Color = wxSystemSettings:getColour(?wxSYS_COLOUR_WINDOW), -% tell("Color: ~p", [Color]), + Color = wxSystemSettings:getColour(?wxSYS_COLOUR_WINDOW), + tell("Color: ~p", [Color]), Window = wxWindow:new(Codebook, ?wxID_ANY), PageSz = wxBoxSizer:new(?wxHORIZONTAL), - CodeTxStyle = {style, ?wxTE_MULTILINE bor ?wxTE_PROCESS_TAB bor ?wxTE_DONTWRAP}, - CodeTx = case ?editorMode of - plain -> wxTextCtrl:new(Window, ?wxID_ANY, [CodeTxStyle]); - sophia -> gd_sophia_editor:new(Window, ?wxID_ANY, [CodeTxStyle]) - end, - TextAt = wxTextAttr:new(), - Mono = wxFont:new(10, ?wxMODERN, ?wxNORMAL, ?wxNORMAL, [{face, "Monospace"}]), - ok = wxTextAttr:setFont(TextAt, Mono), - case ?editorMode of - plain -> - true = wxTextCtrl:setDefaultStyle(CodeTx, TextAt), - ok = wxTextCtrl:setValue(CodeTx, Code); - sophia -> - gd_sophia_editor:set_text(CodeTx, Code) - end, + CodeTx = gd_sophia_editor:new(Window), + ok = gd_sophia_editor:set_text(CodeTx, Code), _ = wxSizer:add(PageSz, CodeTx, zxw:flags(wide)), @@ -541,6 +536,7 @@ add_code_page(State = #s{tabs = TopBook, code = {Codebook, Pages}}, Location, Co {file, Path} -> filename:basename(Path); {hash, Addr} -> Addr end, + ok = wxStyledTextCtrl:connect(Window, stc_styleneeded), true = wxNotebook:addPage(Codebook, Window, FileName, [{bSelect, true}]), Page = #p{path = Location, win = Window, code = CodeTx}, NewPages = Pages ++ [Page],