diff options
Diffstat (limited to 'lib/debugger/src')
27 files changed, 306 insertions, 5939 deletions
| diff --git a/lib/debugger/src/Makefile b/lib/debugger/src/Makefile index 85754da219..90189dd297 100644 --- a/lib/debugger/src/Makefile +++ b/lib/debugger/src/Makefile @@ -45,20 +45,6 @@ MODULES= \  	dbg_iload \  	dbg_iserver \  	dbg_istk \ -	dbg_ui_break \ -	dbg_ui_break_win \ -	dbg_ui_edit \ -	dbg_ui_edit_win \ -	dbg_ui_filedialog_win \ -	dbg_ui_interpret \ -	dbg_ui_mon \ -	dbg_ui_mon_win \ -	dbg_ui_settings \ -	dbg_ui_trace \ -	dbg_ui_trace_win \ -	dbg_ui_view \ -	dbg_ui_win \ -	dbg_ui_winman \  	dbg_wx_break \  	dbg_wx_break_win \  	dbg_wx_code \ diff --git a/lib/debugger/src/dbg_icmd.erl b/lib/debugger/src/dbg_icmd.erl index b230efaa7a..b1bf4ebecc 100644 --- a/lib/debugger/src/dbg_icmd.erl +++ b/lib/debugger/src/dbg_icmd.erl @@ -1,7 +1,7 @@  %%  %% %CopyrightBegin%  %%  -%% Copyright Ericsson AB 1998-2011. All Rights Reserved. +%% Copyright Ericsson AB 1998-2013. All Rights Reserved.  %%   %% The contents of this file are subject to the Erlang Public License,  %% Version 1.1, (the "License"); you may not use this file except in @@ -399,7 +399,7 @@ eval_restricted({From,_Mod,Cmd,SP}, Bs) ->  eval_nonrestricted({From,Mod,Cmd,SP}, Bs, #ieval{level=Le}) when SP < Le->      %% Evaluate in stack -    eval_restricted({From, Mod, Cmd, SP}, Bs), +    _ = eval_restricted({From, Mod, Cmd, SP}, Bs),      Bs;  eval_nonrestricted({From, _Mod, Cmd, _SP}, Bs,   		   #ieval{level=Le,module=M,line=Line}=Ieval) -> @@ -465,7 +465,8 @@ tell_attached(Msg) ->      case get(attached) of  	undefined -> ignore;  	AttPid -> -	    AttPid ! {self(), Msg} +	    AttPid ! {self(), Msg}, +            ignore      end.  %%==================================================================== diff --git a/lib/debugger/src/dbg_ieval.erl b/lib/debugger/src/dbg_ieval.erl index f4b6d488a5..77297de0f3 100644 --- a/lib/debugger/src/dbg_ieval.erl +++ b/lib/debugger/src/dbg_ieval.erl @@ -204,7 +204,8 @@ meta(Int, Debugged, M, F, As) ->  		%% If it's a fun we're evaluating, show a text  		%% representation of the fun and its arguments,  		%% not dbg_ieval:eval_fun(...) -		{dbg_ieval, eval_fun} -> +		{dbg_ieval, EvalFun} when EvalFun =:= eval_fun; +					  EvalFun =:= eval_named_fun ->  		    {Mx, Fx} = lists:last(As),  		    {Mx, Fx, lists:nth(2, As)};  		_ -> @@ -432,7 +433,8 @@ eval_function(Mod, Name, As, Bs, Called, Ieval0, Lc) ->  do_eval_function(Mod, Fun, As0, Bs0, _, Ieval0) when is_function(Fun);  						    Mod =:= ?MODULE, -						    Fun =:= eval_fun -> +						    Fun =:= eval_fun orelse +						    Fun =:= eval_named_fun ->      #ieval{level=Le,line=Li,top=Top} = Ieval0,      case lambda(Fun, As0) of  	{[{clause,Fc,_,_,_}|_]=Cs,Module,Name,As,Bs} -> @@ -487,13 +489,29 @@ lambda(eval_fun, [Cs,As,Bs,{Mod,Name}=F]) ->  	true ->   	    {error,{badarity,{F,As}}}      end; +lambda(eval_named_fun, [Cs,As,Bs0,FName,RF,{Mod,Name}=F]) -> +    %% Fun defined in interpreted code, called from outside +    if +	length(element(3,hd(Cs))) =:= length(As) -> +	    db_ref(Mod),  %% Adds ref between module and process +	    Bs1 = add_binding(FName, RF, Bs0), +	    {Cs,Mod,Name,As,Bs1}; +	true -> +	    {error,{badarity,{F,As}}} +    end;  lambda(Fun, As) when is_function(Fun) ->      %% Fun called from within interpreted code...      case erlang:fun_info(Fun, module) of  	%% ... and the fun was defined in interpreted code  	{module, ?MODULE} -> -	    {env, [{Mod,Name},Bs,Cs]} = erlang:fun_info(Fun, env), +	    {Mod,Name,Bs, Cs} = +		case erlang:fun_info(Fun, env) of +		    {env,[{{M,F},Bs0,Cs0}]} -> +		        {M,F,Bs0, Cs0}; +		    {env,[{{M,F},Bs0,Cs0,FName}]} -> +		        {M,F,add_binding(FName, Fun, Bs0), Cs0} +		end,  	    {arity, Arity} = erlang:fun_info(Fun, arity),  	    if   		length(As) =:= Arity -> @@ -636,6 +654,25 @@ expr({tuple,Line,Es0}, Bs0, Ieval) ->      {Vs,Bs} = eval_list(Es0, Bs0, Ieval#ieval{line=Line}),      {value,list_to_tuple(Vs),Bs}; +%% Map +expr({map,Line,Fs0}, Bs0, Ieval) -> +    {Fs,Bs} = eval_map_fields(Fs0, Bs0, Ieval#ieval{line=Line,top=false}), +    Value = lists:foldl(fun ({map_assoc,K,V}, Mi) -> maps:put(K,V,Mi) end, +                        #{}, Fs), +    {value,Value,Bs}; +expr({map,Line,E0,Fs0}, Bs0, Ieval0) -> +    Ieval = Ieval0#ieval{line=Line,top=false}, +    {value,E,Bs1} = expr(E0, Bs0, Ieval), +    case E of +        #{} -> +            {Fs,Bs2} = eval_map_fields(Fs0, Bs0, Ieval), +            Value = lists:foldl(fun ({map_assoc,K,V}, Mi) -> maps:put(K,V,Mi); +                                    ({map_exact,K,V}, Mi) -> maps:update(K,V,Mi) +                                end, E, Fs), +            {value,Value,merge_bindings(Bs2, Bs1, Ieval)}; +        _ -> +            exception(error, {badarg,E}, Bs1, Ieval) +    end;  %% A block of statements  expr({block,Line,Es},Bs,Ieval) ->      seq(Es, Bs, Ieval#ieval{line=Line}); @@ -694,23 +731,25 @@ expr({'if',Line,Cs}, Bs, Ieval) ->      if_clauses(Cs, Bs, Ieval#ieval{line=Line});  %% Andalso/orelse -expr({'andalso',Line,E1,E2}, Bs, Ieval) -> -    case expr(E1, Bs, Ieval#ieval{line=Line, top=false}) of -	{value,false,_}=Res -> -	    Res; -	{value,true,_} ->  -	    expr(E2, Bs, Ieval#ieval{line=Line, top=false}); -	{value,Val,Bs} -> -	    exception(error, {badarg,Val}, Bs, Ieval) +expr({'andalso',Line,E1,E2}, Bs0, Ieval) -> +    case expr(E1, Bs0, Ieval#ieval{line=Line, top=false}) of +        {value,false,_}=Res -> +           Res; +        {value,true,Bs} -> +            {value,Val,_} = expr(E2, Bs, Ieval#ieval{line=Line, top=false}), +            {value,Val,Bs}; +        {value,Val,Bs} -> +            exception(error, {badarg,Val}, Bs, Ieval)      end; -expr({'orelse',Line,E1,E2}, Bs, Ieval) -> -    case expr(E1, Bs, Ieval#ieval{line=Line, top=false}) of -	{value,true,_}=Res -> -	    Res; -	{value,false,_} -> -	    expr(E2, Bs, Ieval#ieval{line=Line, top=false}); -	{value,Val,_} -> -	    exception(error, {badarg,Val}, Bs, Ieval) +expr({'orelse',Line,E1,E2}, Bs0, Ieval) -> +    case expr(E1, Bs0, Ieval#ieval{line=Line, top=false}) of +        {value,true,_}=Res -> +           Res; +        {value,false,Bs} -> +            {value,Val,_} = expr(E2, Bs, Ieval#ieval{line=Line, top=false}), +            {value,Val,Bs}; +        {value,Val,Bs} -> +            exception(error, {badarg,Val}, Bs, Ieval)      end;  %% Matching expression @@ -727,50 +766,121 @@ expr({match,Line,Lhs,Rhs0}, Bs0, Ieval0) ->  %% Construct a fun  expr({make_fun,Line,Name,Cs}, Bs, #ieval{module=Module}=Ieval) ->      Arity = length(element(3,hd(Cs))), -    Info = {Module,Name}, +    Info = {{Module,Name},Bs,Cs},      Fun =   	case Arity of -	    0 -> fun() -> eval_fun(Cs, [], Bs, Info) end; -	    1 -> fun(A) -> eval_fun(Cs, [A], Bs,Info) end; -	    2 -> fun(A,B) -> eval_fun(Cs, [A,B], Bs,Info) end; -	    3 -> fun(A,B,C) -> eval_fun(Cs, [A,B,C], Bs,Info) end; -	    4 -> fun(A,B,C,D) -> eval_fun(Cs, [A,B,C,D], Bs,Info) end; -	    5 -> fun(A,B,C,D,E) -> eval_fun(Cs, [A,B,C,D,E], Bs,Info) end; -	    6 -> fun(A,B,C,D,E,F) -> eval_fun(Cs, [A,B,C,D,E,F], Bs,Info) end; +	    0 -> fun() -> eval_fun([], Info) end; +	    1 -> fun(A) -> eval_fun([A], Info) end; +	    2 -> fun(A,B) -> eval_fun([A,B], Info) end; +	    3 -> fun(A,B,C) -> eval_fun([A,B,C], Info) end; +	    4 -> fun(A,B,C,D) -> eval_fun([A,B,C,D], Info) end; +	    5 -> fun(A,B,C,D,E) -> eval_fun([A,B,C,D,E], Info) end; +	    6 -> fun(A,B,C,D,E,F) -> eval_fun([A,B,C,D,E,F], Info) end;  	    7 -> fun(A,B,C,D,E,F,G) ->  -			 eval_fun(Cs, [A,B,C,D,E,F,G], Bs,Info) end; +			 eval_fun([A,B,C,D,E,F,G], Info) end;  	    8 -> fun(A,B,C,D,E,F,G,H) ->  -			 eval_fun(Cs, [A,B,C,D,E,F,G,H], Bs,Info) end; +			 eval_fun([A,B,C,D,E,F,G,H], Info) end;  	    9 -> fun(A,B,C,D,E,F,G,H,I) ->  -			 eval_fun(Cs, [A,B,C,D,E,F,G,H,I], Bs,Info) end; +			 eval_fun([A,B,C,D,E,F,G,H,I], Info) end;  	    10 -> fun(A,B,C,D,E,F,G,H,I,J) ->  -		     	  eval_fun(Cs, [A,B,C,D,E,F,G,H,I,J], Bs,Info) end; +			  eval_fun([A,B,C,D,E,F,G,H,I,J], Info) end;  	    11 -> fun(A,B,C,D,E,F,G,H,I,J,K) ->  -		     	  eval_fun(Cs, [A,B,C,D,E,F,G,H,I,J,K], Bs,Info) end; +			  eval_fun([A,B,C,D,E,F,G,H,I,J,K], Info) end;  	    12 -> fun(A,B,C,D,E,F,G,H,I,J,K,L) ->  -		     	  eval_fun(Cs, [A,B,C,D,E,F,G,H,I,J,K,L], Bs,Info) end; +			  eval_fun([A,B,C,D,E,F,G,H,I,J,K,L], Info) end;  	    13 -> fun(A,B,C,D,E,F,G,H,I,J,K,L,M) ->  -		     	  eval_fun(Cs, [A,B,C,D,E,F,G,H,I,J,K,L,M], Bs,Info) end; +			  eval_fun([A,B,C,D,E,F,G,H,I,J,K,L,M], Info) end;  	    14 -> fun(A,B,C,D,E,F,G,H,I,J,K,L,M,N) ->  -		     	  eval_fun(Cs, [A,B,C,D,E,F,G,H,I,J,K,L,M,N], Bs,Info) end; +			  eval_fun([A,B,C,D,E,F,G,H,I,J,K,L,M,N], Info) end;  	    15 -> fun(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O) ->  -		     	  eval_fun(Cs, [A,B,C,D,E,F,G,H,I,J,K,L,M,N,O], Bs,Info) end; +			  eval_fun([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O], Info) end;  	    16 -> fun(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P) ->  -		     	  eval_fun(Cs, [A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P], Bs,Info) end; +			  eval_fun([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P], Info) end;  	    17 -> fun(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q) ->  -		     	  eval_fun(Cs, [A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q], Bs,Info) end; +			  eval_fun([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q], Info) end;  	    18 -> fun(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R) ->  -		     	  eval_fun(Cs, [A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R], Bs,Info) end; +			  eval_fun([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R], Info) end;  	    19 -> fun(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S) ->  -		     	  eval_fun(Cs, [A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S],Bs,Info) end; +			  eval_fun([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S],Info) end;  	    20 -> fun(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T) ->  -			  eval_fun(Cs, [A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T],Bs,Info) end; +			  eval_fun([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T],Info) end;  	    _Other ->  		exception(error, {'argument_limit',{'fun',Cs}}, Bs,  			  Ieval#ieval{line=Line})  	end,      {value,Fun,Bs}; +%% Construct a fun +expr({make_named_fun,Line,Name,FName,Cs}, Bs, #ieval{module=Module}=Ieval) -> +    Arity = length(element(3,hd(Cs))), +    Info = {{Module,Name},Bs,Cs,FName}, +    Fun = +	case Arity of +	    0 -> fun RF() -> eval_named_fun([], RF, Info) end; +	    1 -> fun RF(A) -> eval_named_fun([A], RF, Info) end; +	    2 -> fun RF(A,B) -> +			 eval_named_fun([A,B], RF, Info) end; +	    3 -> fun RF(A,B,C) -> +			 eval_named_fun([A,B,C], RF, Info) end; +	    4 -> fun RF(A,B,C,D) -> +			 eval_named_fun([A,B,C,D], RF, Info) end; +	    5 -> fun RF(A,B,C,D,E) -> +			 eval_named_fun([A,B,C,D,E], +					RF, Info) end; +	    6 -> fun RF(A,B,C,D,E,F) -> +			 eval_named_fun([A,B,C,D,E,F], +					RF, Info) end; +	    7 -> fun RF(A,B,C,D,E,F,G) -> +			 eval_named_fun([A,B,C,D,E,F,G], +					RF, Info) end; +	    8 -> fun RF(A,B,C,D,E,F,G,H) -> +			 eval_named_fun([A,B,C,D,E,F,G,H], +					RF, Info) end; +	    9 -> fun RF(A,B,C,D,E,F,G,H,I) -> +			 eval_named_fun([A,B,C,D,E,F,G,H,I], +					RF, Info) end; +	    10 -> fun RF(A,B,C,D,E,F,G,H,I,J) -> +			 eval_named_fun([A,B,C,D,E,F,G,H,I,J], +					RF, Info) end; +	    11 -> fun RF(A,B,C,D,E,F,G,H,I,J,K) -> +			 eval_named_fun([A,B,C,D,E,F,G,H,I,J,K], +					RF, Info) end; +	    12 -> fun RF(A,B,C,D,E,F,G,H,I,J,K,L) -> +			 eval_named_fun([A,B,C,D,E,F,G,H,I,J,K,L], +					RF, Info) end; +	    13 -> fun RF(A,B,C,D,E,F,G,H,I,J,K,L,M) -> +			 eval_named_fun([A,B,C,D,E,F,G,H,I,J,K,L,M], +					RF, Info) end; +	    14 -> fun RF(A,B,C,D,E,F,G,H,I,J,K,L,M,N) -> +			 eval_named_fun([A,B,C,D,E,F,G,H,I,J,K,L,M,N], +					RF, Info) end; +	    15 -> fun RF(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O) -> +			 eval_named_fun([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O], +					RF, Info) end; +	    16 -> fun RF(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P) -> +			 eval_named_fun([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P], +					RF, Info) end; +	    17 -> fun RF(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q) -> +			 eval_named_fun([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q], +					RF, Info) end; +	    18 -> fun RF(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R) -> +			 eval_named_fun([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q, +					     R], +					RF, Info) end; +	    19 -> fun RF(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S) -> +			 eval_named_fun([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q, +					     R,S], +					RF, Info) end; +	    20 -> fun RF(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T) -> +			 eval_named_fun([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q, +					     R,S,T], +					RF, Info) end; +	    _Other -> +		exception(error, {'argument_limit',{named_fun,FName,Cs}}, Bs, +			  Ieval#ieval{line=Line}) +	end, +    {value,Fun,Bs}; +  %% Construct an external fun.  expr({make_ext_fun,Line,MFA0}, Bs0, Ieval0) ->      {[M,F,A],Bs} = eval_list(MFA0, Bs0, Ieval0), @@ -960,9 +1070,13 @@ expr(E, _Bs, _Ieval) ->      erlang:error({'NYI',E}).  %% Interpreted fun() called from uninterpreted module, recurse -eval_fun(Cs, As, Bs, Info) -> +eval_fun(As, {Info,Bs,Cs}) ->      dbg_debugged:eval(?MODULE, eval_fun, [Cs,As,Bs,Info]). +%% Interpreted named fun() called from uninterpreted module, recurse +eval_named_fun(As, RF, {Info,Bs,Cs,FName}) -> +    dbg_debugged:eval(?MODULE, eval_named_fun, [Cs,As,Bs,FName,RF,Info]). +  %% eval_lc(Expr,[Qualifier],Bindings,IevalState) ->  %%	{value,Value,Bindings}.  %% This is evaluating list comprehensions "straight out of the book". @@ -1032,7 +1146,7 @@ eval_generate([V|Rest], P, Bs0, CompFun, Ieval) ->      case catch match1(P, V, erl_eval:new_bindings(), Bs0) of  	{match,Bsn} ->  	    Bs2 = add_bindings(Bsn, Bs0), -            CompFun(Bs2) ++ eval_generate(Rest, P, Bs2, CompFun, Ieval); +            CompFun(Bs2) ++ eval_generate(Rest, P, Bs0, CompFun, Ieval);  	nomatch ->   	    eval_generate(Rest, P, Bs0, CompFun, Ieval)  	end; @@ -1373,6 +1487,19 @@ guard_expr({cons,_,H0,T0}, Bs) ->  guard_expr({tuple,_,Es0}, Bs) ->      {values,Es} = guard_exprs(Es0, Bs),      {value,list_to_tuple(Es)}; +guard_expr({map,_,Fs0}, Bs) -> +    Fs = eval_map_fields_guard(Fs0, Bs), +    Value = lists:foldl(fun ({map_assoc,K,V}, Mi) -> maps:put(K,V,Mi) end, +                        #{}, Fs), +    {value,Value}; +guard_expr({map,_,E0,Fs0}, Bs) -> +    {value,E} = guard_expr(E0, Bs), +    Fs = eval_map_fields_guard(Fs0, Bs), +    Value = lists:foldl(fun ({map_assoc,K,V}, Mi) -> maps:put(K,V,Mi); +                            ({map_exact,K,V}, Mi) -> maps:update(K,V,Mi) end, +                        E, Fs), +    io:format("~p~n", [{E,Value}]), +    {value,Value};  guard_expr({bin,_,Flds}, Bs) ->      {value,V,_Bs} =   	eval_bits:expr_grp(Flds, Bs, @@ -1382,6 +1509,37 @@ guard_expr({bin,_,Flds}, Bs) ->  			   end, [], false),      {value,V}. + +%% eval_map_fields([Field], Bindings, IEvalState) -> +%%  {[{map_assoc | map_exact,Key,Value}],Bindings} + +eval_map_fields(Fs, Bs, Ieval) -> +    eval_map_fields(Fs, Bs, Ieval, fun expr/3). + +eval_map_fields_guard(Fs0, Bs) -> +    {Fs,_} = eval_map_fields(Fs0, Bs, #ieval{}, +                             fun (G0, Bs0, _) -> +                            {value,G} = guard_expr(G0, Bs0), +                            {value,G,Bs0} +                    end), +    Fs. + +eval_map_fields(Fs, Bs, Ieval, F) -> +    eval_map_fields(Fs, Bs, Ieval, F, []). + +eval_map_fields([{map_field_assoc,Line,K0,V0}|Fs], Bs0, Ieval0, F, Acc) -> +    Ieval = Ieval0#ieval{line=Line}, +    {value,K,Bs1} = F(K0, Bs0, Ieval), +    {value,V,Bs2} = F(V0, Bs1, Ieval), +    eval_map_fields(Fs, Bs2, Ieval0, F, [{map_assoc,K,V}|Acc]); +eval_map_fields([{map_field_exact,Line,K0,V0}|Fs], Bs0, Ieval0, F, Acc) -> +    Ieval = Ieval0#ieval{line=Line}, +    {value,K,Bs1} = F(K0, Bs0, Ieval), +    {value,V,Bs2} = F(V0, Bs1, Ieval), +    eval_map_fields(Fs, Bs2, Ieval0, F, [{map_exact,K,V}|Acc]); +eval_map_fields([], Bs, _Ieval, _F, Acc) -> +    {lists:reverse(Acc),Bs}. +  %% match(Pattern,Term,Bs) -> {match,Bs} | nomatch  match(Pat, Term, Bs) ->      try match1(Pat, Term, Bs, Bs) @@ -1411,6 +1569,8 @@ match1({cons,_,H,T}, [H1|T1], Bs0, BBs) ->  match1({tuple,_,Elts}, Tuple, Bs, BBs)     when length(Elts) =:= tuple_size(Tuple) ->      match_tuple(Elts, Tuple, 1, Bs, BBs); +match1({map,_,Fields}, Map, Bs, BBs) when is_map(Map) -> +    match_map(Fields, Map, Bs, BBs);  match1({bin,_,Fs}, B, Bs0, BBs) when is_bitstring(B) ->      try eval_bits:match_bits(Fs, B, Bs0, BBs,  			     match_fun(BBs), @@ -1434,6 +1594,17 @@ match_tuple([E|Es], Tuple, I, Bs0, BBs) ->  match_tuple([], _, _, Bs, _BBs) ->      {match,Bs}. +match_map([{map_field_exact,_,K0,Pat}|Fs], Map, Bs0, BBs) -> +    {value,K,BBs} = expr(K0, BBs, #ieval{}), +    case maps:find(K, Map) of +        {ok,Value} -> +            {match,Bs} = match1(Pat, Value, Bs0, BBs), +            match_map(Fs, Map, Bs, BBs); +        error -> throw(nomatch) +    end; +match_map([], _, Bs, _BBs) -> +    {match,Bs}. +  head_match([Par|Pars], [Arg|Args], Bs0, BBs) ->      try match1(Par, Arg, Bs0, BBs) of  	{match,Bs} -> head_match(Pars, Args, Bs, BBs) diff --git a/lib/debugger/src/dbg_iload.erl b/lib/debugger/src/dbg_iload.erl index 3c95ef8068..ad05a7c529 100644 --- a/lib/debugger/src/dbg_iload.erl +++ b/lib/debugger/src/dbg_iload.erl @@ -1,7 +1,7 @@  %%  %% %CopyrightBegin%  %% -%% Copyright Ericsson AB 1998-2010. All Rights Reserved. +%% Copyright Ericsson AB 1998-2014. All Rights Reserved.  %%  %% The contents of this file are subject to the Erlang Public License,  %% Version 1.1, (the "License"); you may not use this file except in @@ -42,18 +42,21 @@  load_mod(Mod, File, Binary, Db) ->      Flag = process_flag(trap_exit, true), -    Pid = spawn_link(fun () -> load_mod1(Mod, File, Binary, Db) end), +    Pid = spawn_link(load_mod1(Mod, File, Binary, Db)),      receive  	{'EXIT', Pid, What} ->  	    process_flag(trap_exit, Flag),  	    What      end. --spec load_mod1(atom(), file:filename(), binary(), ets:tid()) -> no_return(). +-spec load_mod1(atom(), file:filename(), binary(), ets:tid()) -> +                       fun(() -> no_return()).  load_mod1(Mod, File, Binary, Db) -> -    store_module(Mod, File, Binary, Db), -    exit({ok, Mod}). +    fun() -> +            store_module(Mod, File, Binary, Db), +            exit({ok, Mod}) +    end.  %%====================================================================  %% Internal functions @@ -194,6 +197,11 @@ pattern({cons,Line,H0,T0}) ->  pattern({tuple,Line,Ps0}) ->      Ps1 = pattern_list(Ps0),      {tuple,Line,Ps1}; +pattern({map,Line,Fs0}) -> +    Fs1 = lists:map(fun ({map_field_exact,L,K,V}) -> +                            {map_field_exact,L,expr(K, false),pattern(V)} +                    end, Fs0), +    {map,Line,Fs1};  pattern({op,_,'-',{integer,Line,I}}) ->      {value,Line,-I};  pattern({op,_,'+',{integer,Line,I}}) -> @@ -262,6 +270,8 @@ guard_test({string,Line,_}) -> {value,Line,false};  guard_test({nil,Line}) -> {value,Line,false};  guard_test({cons,Line,_,_}) -> {value,Line,false};  guard_test({tuple,Line,_}) -> {value,Line,false}; +guard_test({map,Line,_}) -> {value,Line,false}; +guard_test({map,Line,_,_}) -> {value,Line,false};  guard_test({bin,Line,_}) ->  {value,Line,false}.  gexpr({var,Line,V}) -> {var,Line,V}; @@ -279,6 +289,13 @@ gexpr({cons,Line,H0,T0}) ->  gexpr({tuple,Line,Es0}) ->      Es1 = gexpr_list(Es0),      {tuple,Line,Es1}; +gexpr({map,Line,Fs0}) -> +    Fs1 = map_fields(Fs0, fun gexpr/1), +    {map,Line,Fs1}; +gexpr({map,Line,E0,Fs0}) -> +    E1 = gexpr(E0), +    Fs1 = map_fields(Fs0, fun gexpr/1), +    {map,Line,E1,Fs1};  gexpr({bin,Line,Flds0}) ->      Flds = gexpr_list(Flds0),      {bin,Line,Flds}; @@ -341,6 +358,13 @@ expr({cons,Line,H0,T0}, _Lc) ->  expr({tuple,Line,Es0}, _Lc) ->      Es1 = expr_list(Es0),      {tuple,Line,Es1}; +expr({map,Line,Fs0}, _Lc) -> +    Fs1 = map_fields(Fs0), +    {map,Line,Fs1}; +expr({map,Line,E0,Fs0}, _Lc) -> +    E1 = expr(E0, false), +    Fs1 = map_fields(Fs0), +    {map,Line,E1,Fs1};  expr({block,Line,Es0}, Lc) ->      %% Unfold block into a sequence.      Es1 = exprs(Es0, Lc), @@ -369,6 +393,9 @@ expr({'fun',Line,{function,F,A},{_Index,_OldUniq,Name}}, _Lc) ->      As = new_vars(A, Line),      Cs = [{clause,Line,As,[],[{local_call,Line,F,As,true}]}],      {make_fun,Line,Name,Cs}; +expr({named_fun,Line,FName,Cs0,{_,_,Name}}, _Lc) when is_atom(Name) -> +    Cs = fun_clauses(Cs0), +    {make_named_fun,Line,Name,FName,Cs};  expr({'fun',Line,{function,{atom,_,M},{atom,_,F},{integer,_,A}}}, _Lc)    when 0 =< A, A =< 255 ->      %% New format in R15 for fun M:F/A (literal values). @@ -433,7 +460,7 @@ expr({lc,Line,E0,Gs0}, _Lc) ->			%R8.  		       ({b_generate,L,P0,Qs}) -> %R12.  			   {b_generate,L,expr(P0, false),expr(Qs, false)};  		       (Expr) -> -			   case is_guard(Expr) of +			   case erl_lint:is_guard_test(Expr) of  			       true -> {guard,guard([[Expr]])};  			       false -> expr(Expr, false)  			   end @@ -445,7 +472,7 @@ expr({bc,Line,E0,Gs0}, _Lc) ->			%R12.  		       ({b_generate,L,P0,Qs}) -> %R12.  			   {b_generate,L,expr(P0, false),expr(Qs, false)};  		       (Expr) -> -			   case is_guard(Expr) of +			   case erl_lint:is_guard_test(Expr) of  			       true -> {guard,guard([[Expr]])};  			       false -> expr(Expr, false)  			   end @@ -488,42 +515,6 @@ expr({bin_element,Line,Expr,Size,Type}, _Lc) ->  expr(Other, _Lc) ->      exit({?MODULE,{unknown_expr,Other}}). -%% is_guard(Expression) -> true | false. -%%  Test if a general expression is a guard test or guard BIF. -%%  Cannot use erl_lint here as sys_pre_expand has transformed source. - -is_guard({op,_,Op,L,R}) -> -    erl_internal:comp_op(Op, 2) andalso is_gexpr_list([L,R]); -is_guard({call,_,{remote,_,{atom,_,erlang},{atom,_,Test}},As}) -> -    Arity = length(As), -    (erl_internal:guard_bif(Test, Arity) orelse -     erl_internal:old_type_test(Test, Arity)) andalso is_gexpr_list(As); -is_guard({atom,_,true}) -> true; -is_guard(_) -> false. - -is_gexpr({var,_,_}) -> true; -is_gexpr({atom,_,_}) -> true; -is_gexpr({integer,_,_}) -> true; -is_gexpr({char,_,_}) -> true; -is_gexpr({float,_,_}) -> true; -is_gexpr({string,_,_}) -> true; -is_gexpr({nil,_}) -> true; -is_gexpr({cons,_,H,T}) -> is_gexpr_list([H,T]); -is_gexpr({tuple,_,Es}) -> is_gexpr_list(Es); -is_gexpr({call,_,{remote,_,{atom,_,erlang},{atom,_,F}},As}) -> -    Ar = length(As), -    case erl_internal:guard_bif(F, Ar) of -	true -> is_gexpr_list(As); -	false -> erl_internal:arith_op(F, Ar) andalso is_gexpr_list(As) -    end; -is_gexpr({op,_,Op,A}) -> -    erl_internal:arith_op(Op, 1) andalso is_gexpr(A); -is_gexpr({op,_,Op,A1,A2}) -> -    erl_internal:arith_op(Op, 2) andalso is_gexpr_list([A1,A2]); -is_gexpr(_) -> false. - -is_gexpr_list(Es) -> lists:all(fun (E) -> is_gexpr(E) end, Es). -  consify([A|As]) ->       {cons,0,A,consify(As)};  consify([]) -> {value,0,[]}. @@ -547,6 +538,15 @@ fun_clauses([{clause,L,H,G,B}|Cs]) ->      [{clause,L,head(H),guard(G),exprs(B, true)}|fun_clauses(Cs)];  fun_clauses([]) -> []. +map_fields(Fs) -> +    map_fields(Fs, fun (E) -> expr(E, false) end). + +map_fields([{map_field_assoc,L,N,V}|Fs], F) -> +    [{map_field_assoc,L,F(N),F(V)}|map_fields(Fs)]; +map_fields([{map_field_exact,L,N,V}|Fs], F) -> +    [{map_field_exact,L,F(N),F(V)}|map_fields(Fs)]; +map_fields([], _) -> []. +  %% new_var_name() -> VarName.  new_var_name() -> diff --git a/lib/debugger/src/dbg_ui_break.erl b/lib/debugger/src/dbg_ui_break.erl deleted file mode 100644 index 8b9a236ce7..0000000000 --- a/lib/debugger/src/dbg_ui_break.erl +++ /dev/null @@ -1,98 +0,0 @@ -%% -%% %CopyrightBegin% -%%  -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. -%%  -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%%  -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%%  -%% %CopyrightEnd% -%% --module(dbg_ui_break). - -%% External exports --export([start/3, start/4, start/5]). - -%% Internal exports --export([init/5]). - -%%==================================================================== -%% External exports -%%==================================================================== - -%%-------------------------------------------------------------------- -%% start(GS, Pos, Type) -%% start(GS, Pos, Type, Module, Line) -%%   GS = graphics system identifier -%%   Pos = {X, Y} -%%     X = Y = integer() -%%   Type =  line | conditional | function -%%   Module = atom() -%%   Line = integer() -%%-------------------------------------------------------------------- -start(GS, Pos, Type) -> -    start(GS, Pos, Type, "", ""). -start(GS, Pos, Type, Mod) -> -    start(GS, Pos, Type, Mod, ""). -start(GS, Pos, Type, Mod, Line) -> -    spawn_link(?MODULE, init, [GS, Pos, Type, Mod, Line]). - - -%%==================================================================== -%% Internal exports -%%==================================================================== - -init(GS, Pos, Type, Mod, Line) -> -    Win = dbg_ui_break_win:create_win(GS, Pos, Type, Mod, Line), -    if -	Type==function, is_atom(Mod) -> -	    Win2 = gui_cmd({module, Mod}, Win), -	    loop(Win2); -	true -> -	    loop(Win) -    end. - -loop(Win) -> -    receive - -	%% From the GUI -	GuiEvent when is_tuple(GuiEvent), element(1, GuiEvent)==gs -> -	    Cmd = dbg_ui_break_win:handle_event(GuiEvent, Win), -	    Win2 = gui_cmd(Cmd, Win), -	    loop(Win2) -    end. - -gui_cmd(ignore, Win) -> -    Win; -gui_cmd(stopped, _Win) -> -    exit(normal); -gui_cmd({win, Win2}, _Win) -> -    Win2; -gui_cmd({module, Mod}, Win) -> -    Funcs = int:functions(Mod), -    dbg_ui_break_win:update_functions(Win, Funcs); -gui_cmd({break, DataL, Action}, _Win) -> -    Fun = -	fun(Data) -> -		case Data of -		    [Mod, Line] -> -			int:break(Mod, Line), -			int:action_at_break(Mod, Line, Action); -		    [Mod, Line, CMod, CFunc] -> -			int:break(Mod, Line), -			int:test_at_break(Mod, Line, {CMod, CFunc}), -			int:action_at_break(Mod, Line, Action); -		    [Mod, Func, Arity] -> -			int:break_in(Mod, Func, Arity) -		end -	end, -    lists:foreach(Fun, DataL), -    exit(normal). diff --git a/lib/debugger/src/dbg_ui_break_win.erl b/lib/debugger/src/dbg_ui_break_win.erl deleted file mode 100644 index 11d810ccab..0000000000 --- a/lib/debugger/src/dbg_ui_break_win.erl +++ /dev/null @@ -1,314 +0,0 @@ -%% -%% %CopyrightBegin% -%%  -%% Copyright Ericsson AB 2002-2012. All Rights Reserved. -%%  -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%%  -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%%  -%% %CopyrightEnd% -%% --module(dbg_ui_break_win). --compile([{nowarn_deprecated_function,{gs,button,2}}, -          {nowarn_deprecated_function,{gs,config,2}}, -          {nowarn_deprecated_function,{gs,create,3}}, -          {nowarn_deprecated_function,{gs,entry,2}}, -          {nowarn_deprecated_function,{gs,frame,2}}, -          {nowarn_deprecated_function,{gs,label,2}}, -          {nowarn_deprecated_function,{gs,listbox,2}}, -          {nowarn_deprecated_function,{gs,menu,2}}, -          {nowarn_deprecated_function,{gs,menuitem,2}}, -          {nowarn_deprecated_function,{gs,radiobutton,2}}, -          {nowarn_deprecated_function,{gs,read,2}}, -          {nowarn_deprecated_function,{gs,window,2}}]). - -%% External exports --export([create_win/5, -	 update_functions/2, -	 handle_event/2]). - --record(winInfo, {type,            % line | conditional | function -		  win,             % gsobj() -		  packer,          % gsobj() | undefined -		  entries,         % [{atom|integer, GSobj()}] -		  trigger,         % enable | disable | delete -		  ok,              % gsobj() -		  cancel,          % gsobj() -		  listbox,         % gsobj() -		  funcs=[]         % [[Name, Arity]] -		 }). - -%%==================================================================== -%% External exports -%%==================================================================== - -%%-------------------------------------------------------------------- -%% create_win(GS, Pos, Type, Mod, Line) -> #winInfo{} -%%   GS = graphics system identifier -%%   Pos = {X, Y} -%%     X = Y = integer() -%%   Type =  line | conditional | function -%%   Mod = atom() | "" -%%   Line = integer() | "" -%%-------------------------------------------------------------------- -create_win(GS, {X, Y}, function, Mod, _Line) -> -    Pad = 8, -    W = 230, - -    Font = dbg_ui_win:font(normal), - -    %% Window -    Win = gs:window(GS, [{title, "Function Break"}, {x, X}, {y, Y}, -			 {destroy, true}, {configure, true}, -			 {keypress, true}, {data, window}]), - -    %% Frame -    Frm = gs:frame(Win, [{x, 0}, {y, 0}, {width, W}, {height, 190}, -			 {packer_x, [{fixed, 70}, {stretch, 1, W-80}, -				     {fixed, 10}]}, -			 {packer_y, [{fixed, 10}, {fixed, 30}, -				     {stretch, 1, 100}, {fixed, 40}]}]), - -    %% Create input field (label+entry) -    gs:label(Frm, [{label, {text,"Module:"}}, {font, Font}, {align, e}, -		   {pack_x, 1}, {pack_y, 2}]), -    Ent = gs:entry(Frm, [{text, Mod}, -			 {pack_x, 2}, {pack_y, 2}, -			 {keypress, true}, {setfocus, true}, -			 {buttonpress, true}]), -    Entries = [{Ent, atom}], - -    %% Create a listbox containing the functions of the module -    gs:label(Frm, [{label, {text,"Function:"}}, {font, Font}, {align, ne}, -		   {pack_x, 1}, {pack_y, 3}]), -    Lb = gs:listbox(Frm, [{bw, 2}, {relief, ridge}, {vscroll, right}, -			  {pack_x, 2}, {pack_y, 3}, -			  {selectmode, multiple}]), - -    %% Add OK and Cancel buttons -    {Wbtn, Hbtn} = dbg_ui_win:min_size(["OK","Cancel"], 70, 30), -    Bot = gs:frame(Frm, [{pack_x, {1, 3}}, {pack_y, 4}]), -    OK = gs:button(Bot, [{x, Pad}, {y, Pad}, -			 {width, Wbtn}, {height, Hbtn}, -			 {label, {text,"OK"}}, {font, Font}]), -    Cancel = gs:button(Bot, [{x, W-Pad-Wbtn}, {y, Pad}, -			     {width, Wbtn}, {height, Hbtn}, -			     {label, {text,"Cancel"}}, {font, Font}]), - -    Wfrm = gs:read(Frm, width), Hfrm = gs:read(Frm, height), -    gs:config(Win, [{width, Wfrm}, {height, Hfrm}, {map, true}]), -    #winInfo{type=function, win=Win, -	     packer=Frm, entries=Entries, trigger=enable, -	     ok=OK, cancel=Cancel, listbox=Lb, funcs=[]}; -create_win(GS, {X, Y}, Type, Mod, Line) -> -    Pad = 8, -    W = 230, - -    Font = dbg_ui_win:font(normal), - -    %% Window -    Title = case Type of -		line -> "Line Break"; -		conditional -> "Conditional Break" -	    end, -    Win = gs:window(GS, [{title, Title}, {x, X}, {y, Y}, -			 {destroy, true}]), - -    %% Create input fields (label+entry) -    {Wlbl, Hlbl} = dbg_ui_win:min_size(["C-Function:"], 10, 30), -    Went = W-Wlbl-2*Pad, -    Labels = case Type of -		 line -> -		     [{atom,"Module:",Mod}, {integer,"Line:",Line}]; -		 conditional -> -		     [{atom,"Module:",Mod}, {integer,"Line:",Line}, -		      {atom,"C-Module:",""}, {atom,"C-Function:",""}] -	     end, -    Fun = fun({DataType, Label, Default}, Yin) -> -		  gs:create(label, Win, [{x, Pad}, {y, Yin}, -					 {width,Wlbl}, {height,Hlbl}, -					 {label, {text,Label}}, -					 {font, Font}, {align, e}]), -		  Ent = gs:create(entry, Win, [{x, Pad+Wlbl}, {y, Yin}, -					       {width, Went}, -					       {height, Hlbl}, -					       {text, Default}, -					       {keypress, true}]), -		  {{Ent, DataType}, Yin+Hlbl} -	  end, -    {Entries, Yacc} = lists:mapfoldl(Fun, Pad, Labels), -    {First, _DataType} = hd(Entries), -    gs:config(First, [{buttonpress, true}, {setfocus, true}]), - -    %% Add 'trigger action' buttons -    {Wlbl2, Hlbl2} = dbg_ui_win:min_size(["Trigger Action"], 100, 20), -    Wfrm = Wlbl2+8, Hfrm = Hlbl2*4+4, -    Grp = erlang:now(), -    Frm = gs:frame(Win, [{x, W/2-Wfrm/2-2}, {y, Yacc+Pad-2}, -			 {width, Wfrm}, {height, Hfrm}, {bw, 2}]), -    gs:label(Frm, [{label, {text, "Trigger Action"}}, {font, Font}, -		   {x, 2}, {y, 0}, {width, Wlbl2}, {height, Hlbl2}]), -    gs:radiobutton(Frm, [{label, {text, "Enable"}}, {font, Font}, -			 {x, 10}, {y, Hlbl2}, -			 {width, Wlbl2-10}, {height, Hlbl2}, -			 {align, w}, {group, Grp}, -			 {data, {trigger, enable}}, -			 {select, true}]), -    gs:radiobutton(Frm, [{label, {text, "Disable"}}, {font, Font}, -			 {x, 10}, {y, Hlbl2*2}, -			 {width, Wlbl2-10}, {height, Hlbl2}, -			 {align, w}, {group, Grp}, -			 {data, {trigger, disable}}]), -    gs:radiobutton(Frm, [{label, {text, "Delete"}}, {font, Font}, -			 {x, 10}, {y, Hlbl2*3}, -			 {width, Wlbl2-10}, {height, Hlbl2}, -			 {align, w}, {group, Grp}, -			 {data, {trigger, delete}}]), - -    %% Add OK and Cancel buttons -    {Wbtn, Hbtn} = dbg_ui_win:min_size(["OK","Cancel"], 70, 30), -    Ybtn = Yacc + Pad + Hfrm + Pad, -    OK = gs:button(Win, [{x, Pad}, {y, Ybtn}, -			 {width, Wbtn}, {height, Hbtn}, -			 {label, {text,"OK"}}, {font, Font}]), -    gs:button(Win, [{x, W-Pad-Wbtn}, {y, Ybtn}, -		    {width, Wbtn}, {height, Hbtn}, -		    {label, {text,"Cancel"}}, {font, Font}]), - -    Hwin = Ybtn + Hbtn + Pad, -    gs:config(Win, [{width, W}, {height, Hwin}, {map, true}]), - -    #winInfo{type=Type, win=Win, -	     entries=Entries, trigger=enable, ok=OK}. - -%%-------------------------------------------------------------------- -%% update_functions(WinInfo, Funcs) -> WinInfo -%%   WinInfo = #winInfo{} -%%   Funcs = [{Name, Arity}] -%%     Name = atom() -%%     Arity = integer() -%%-------------------------------------------------------------------- -update_functions(WinInfo, Funcs) -> -    Items = lists:map(fun([N, A]) -> io_lib:format("~p/~p", [N, A]) end, -		      Funcs), -    gs:config(WinInfo#winInfo.listbox, [{items, Items}, -					{setfocus, true}]), -    WinInfo#winInfo{funcs=Funcs}. - -%%-------------------------------------------------------------------- -%% handle_event(GSEvent, WinInfo) -> Command -%% GSEvent = {gs, Id, Event, Data, Arg} -%% WinInfo = #winInfo{} -%% Command = ignore -%%         | stopped -%%         | {win, WinInfo} -%%         | {module, Mod} -%%         | {break, [[Mod, Line]], Action} -%%         | {break, [[Mod, Line, CMod, CFunc]], Action} -%%         | {break, [[Mod, Func, Arity]], Action} -%%-------------------------------------------------------------------- -handle_event({gs, _Id, destroy, _Data, _Arg}, _WinInfo) -> -    stopped; -handle_event({gs, _Id, configure, _Data, [W, H|_]}, WinInfo) -> -    gs:config(WinInfo#winInfo.packer, [{width, W-10}, {height, H-10}]), -    gs:config(WinInfo#winInfo.cancel, [{x, W-80}]), -    ignore; -handle_event({gs, Ent, buttonpress, _,[N,X0,Y0|_]}, WinInfo) when N>1 -> -    %% Right (middle) mouse button click in module entry, display a -    %% menu containing all interpreted modules -    Mods = int:interpreted(), -    X = gs:read(Ent, x) + X0, -    Y = gs:read(Ent, y) + Y0, -    Menu = gs:menu(WinInfo#winInfo.win, [{post_at,{X,Y}}]), -    lists:foreach(fun(Mod) -> -			  gs:menuitem(Menu, [{label,{text,Mod}}, -					     {data,{module,Mod}}]) -		  end, -		  Mods), -    ignore; -handle_event({gs, LB, keypress, window, [Key|_]}, WinInfo) -> -    %% Used for functional break window, since listboxes for some -    %% reason doesn't generate keypress events -    if -	Key/='Tab', Key/='Return' -> -	    ignore; -	true -> -	    handle_event({gs, LB, click, listbox, ["OK"]}, WinInfo) -    end; -handle_event({gs, Ent, keypress, Data, [Key|_]}, WinInfo) -> -    case WinInfo#winInfo.type of -	function when Key/='Tab', Key/='Return' -> -	    case gs:read(WinInfo#winInfo.listbox, items) of -		[] -> ignore; -		_Items -> -		    gs:config(WinInfo#winInfo.listbox, clear), -		    {win, WinInfo#winInfo{funcs=[]}} -	    end; -	function -> % 'Return' | 'Tab' pressed in Module entry -	    case check_input(WinInfo#winInfo.entries) of -		error -> ignore; -		[Mod] -> {module, Mod} -	    end; -	_Type when Key=='Tab'; Key=='Return' -> -	    case next_entry(Ent, WinInfo#winInfo.entries) of -		last -> -		    gs:config(WinInfo#winInfo.ok, flash), -		    handle_event({gs, Ent, click, Data, ["OK"]}, WinInfo); -		Next -> -		    gs:config(Next, {setfocus, true}), -		    ignore -	    end; -	_Type -> ignore -    end; -handle_event({gs, _Id, click, _Data, ["OK"|_]}, WinInfo) -> -    case check_input(WinInfo#winInfo.entries) of -	error -> ignore; -	Data when WinInfo#winInfo.type/=function -> -	    {break, [Data], WinInfo#winInfo.trigger}; -	[Mod] -> % Function break window -	    case gs:read(WinInfo#winInfo.listbox, selection) of -		[] -> -		    {module, Mod}; -		IndexL -> -		    Funcs = WinInfo#winInfo.funcs, -		    Breaks = -			[[Mod|lists:nth(Index+1, Funcs)] || Index <- IndexL], -		    {break, Breaks, enable} -	    end -    end; -handle_event({gs, _Id, click, _Data, ["Cancel"|_]}, _WinInfo) -> -    stopped; -handle_event({gs, _Id, click, {trigger,Trigger}, _Arg}, WinInfo) -> -    {win, WinInfo#winInfo{trigger=Trigger}}; -handle_event({gs, _Id, click, {module, Mod}, _Arg}, WinInfo) -> -    {Ent, _DataType} = hd(WinInfo#winInfo.entries), -    gs:config(Ent, {insert,{0,Mod}}), -    ignore; -handle_event(_GSEvent, _WinInfo) -> -    ignore. - -check_input(Entries) -> -    check_input(Entries, []). -check_input([{Entry, Type} | Entries], Data) -> -    Str = gs:read(Entry, text), -    case erl_scan:string(Str) of -	{ok, [{Type, _Line, Val}], _EndLine} -> -	    check_input(Entries, [Val|Data]); -	_Error -> error -    end; -check_input([], Data) -> lists:reverse(Data). - -next_entry(Entry, [{Entry, _Type}]) -> -    last; -next_entry(Entry, [{Entry, _Type1}, {Next, _Type2}|_]) -> -    Next; -next_entry(Entry, [_|Entries]) -> -    next_entry(Entry, Entries). diff --git a/lib/debugger/src/dbg_ui_edit.erl b/lib/debugger/src/dbg_ui_edit.erl deleted file mode 100644 index 390e6acdb4..0000000000 --- a/lib/debugger/src/dbg_ui_edit.erl +++ /dev/null @@ -1,91 +0,0 @@ -%% -%% %CopyrightBegin% -%%  -%% Copyright Ericsson AB 2002-2009. All Rights Reserved. -%%  -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%%  -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%%  -%% %CopyrightEnd% -%% --module(dbg_ui_edit). - -%% External exports --export([start/5]). - -%% Internal exports --export([init/6]). - --record(state, {win,    % term() Edit dialog window data -		pid,    % pid() Parent -		prompt  % atom() -	       }). - -%%==================================================================== -%% External exports -%%==================================================================== - -%%-------------------------------------------------------------------- -%% start(GS, Pos, Title, Prompt, {Type, Value}) -%%   GS = graphics system identifier -%%   Pos = {X, Y} -%%     X = Y = integer() -%%   Title = string() -%%   Prompt = atom() -%%   Type = term | atom | float | integer | string -%%   Value = term() -%%-------------------------------------------------------------------- -start(GS, Pos, Title, Prompt, Edit) -> -    case dbg_ui_winman:is_started(Title) of -	true -> ignore; -	false -> -	    spawn(?MODULE, init, [self(), GS, Pos, Title, Prompt, Edit]) -    end. - - -%%==================================================================== -%% Internal exports -%%==================================================================== - -init(Pid, GS, Pos, Title, Prompt, Edit) -> - -    %% Create edit dialog window -    Win = dbg_ui_edit_win:create_win(GS, Pos, Title, Prompt, Edit), -    Window = dbg_ui_edit_win:get_window(Win), -    dbg_ui_winman:insert(Title, Window), -    State = #state{win=Win, pid=Pid, prompt=Prompt}, - -    loop(State). - -loop(State) -> -    receive - -	%% From the GUI -	GuiEvent when is_tuple(GuiEvent), element(1, GuiEvent)==gs -> -	    Cmd = dbg_ui_edit_win:handle_event(GuiEvent, -						    State#state.win), -	    State2 = gui_cmd(Cmd, State), -	    loop(State2); - -	%% From the dbg_ui_winman process (Debugger window manager) -	{dbg_ui_winman, update_windows_menu, _Data} -> -	    loop(State); -	{dbg_ui_winman, destroy} -> -	    exit(normal) -    end. - -gui_cmd(ignore, State) -> -    State; -gui_cmd(stopped, _State) -> -    exit(normal); -gui_cmd({edit, Value}, State) -> -    State#state.pid ! {dbg_ui_edit, State#state.prompt, Value}, -    exit(normal). diff --git a/lib/debugger/src/dbg_ui_edit_win.erl b/lib/debugger/src/dbg_ui_edit_win.erl deleted file mode 100644 index 2e9a685b57..0000000000 --- a/lib/debugger/src/dbg_ui_edit_win.erl +++ /dev/null @@ -1,128 +0,0 @@ -%% -%% %CopyrightBegin% -%%  -%% Copyright Ericsson AB 2002-2012. All Rights Reserved. -%%  -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%%  -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%%  -%% %CopyrightEnd% -%% --module(dbg_ui_edit_win). --compile([{nowarn_deprecated_function,{gs,button,2}}, -          {nowarn_deprecated_function,{gs,config,2}}, -          {nowarn_deprecated_function,{gs,entry,2}}, -          {nowarn_deprecated_function,{gs,label,2}}, -          {nowarn_deprecated_function,{gs,read,2}}, -          {nowarn_deprecated_function,{gs,window,2}}]). - -%% External exports --export([create_win/5, get_window/1, -	 handle_event/2]). - --record(winInfo, {window,   % gsobj() -		  entry,    % gsobj() -		  button,   % gsobj() -		  type      % atom() -		 }). - -%%==================================================================== -%% External exports -%%==================================================================== - -%%-------------------------------------------------------------------- -%% create_win(GS, Pos, Title, Prompt, {Type, Value}) -> #winInfo{} -%%   GS = graphics system identifier -%%   Pos = {X, Y} -%%     X = Y = integer() -%%   Title = string() -%%   Prompt = atom() -%%   Type = term | atom | float | integer | string -%%   Value = term() -%%-------------------------------------------------------------------- -create_win(GS, {X, Y}, Title, Prompt, {Type, Value}) -> -    Pad=8, - -    Font = dbg_ui_win:font(normal), - -    %% Window -    Win = gs:window(GS, [{title, Title}, {x, X}, {y, Y}, -			 {destroy, true}]), - -    %% Label -    {Wlbl, Hlbl} = dbg_ui_win:min_size([Prompt], 50, 30), -    gs:label(Win, [{x, Pad}, {y, Pad}, {width, Wlbl}, {height, Hlbl}, -		   {align, e}, {label, {text, Prompt}}, {font, Font}]), - - -    %% Entry -    {Went, _Hent} = dbg_ui_win:min_size([Value], 100, 20), -    Ent = gs:entry(Win, [{x, Pad+Wlbl}, {y, Pad}, -			 {width, Went}, {height, Hlbl}, -			 {text, Value}, -			 {keypress, true}]), - -    %% OK and Cancel buttons -    W = Pad + Wlbl + Went + Pad, -    {Wbtn, Hbtn} = dbg_ui_win:min_size(["Cancel"], 70, 30), -    Ybtn = Pad + Hlbl + Pad, -    Btn = gs:button(Win, [{x, Pad}, {y, Ybtn}, -			  {width, Wbtn}, {height, Hbtn}, -			  {label, {text,"OK"}}, {font, Font}]), -    gs:button(Win, [{x, W-Pad-Wbtn}, {y, Ybtn}, -		    {width, Wbtn}, {height, Hbtn}, -		    {label, {text,"Cancel"}}, {font, Font}]), - -    H = Ybtn + Hbtn + Pad, -    gs:config(Win, [{width, W}, {height, H}, {map, true}]), - -    #winInfo{window=Win, entry=Ent, button=Btn, type=Type}. - -%%-------------------------------------------------------------------- -%% get_window(WinInfo) -> Window -%%   WinInfo = #winInfo{} -%%   Window = gsobj() -%%-------------------------------------------------------------------- -get_window(WinInfo) -> -    WinInfo#winInfo.window. - -%%-------------------------------------------------------------------- -%% handle_event(GSEvent, WinInfo) -> Command -%% GSEvent = {gs, Id, Event, Data, Arg} -%% WinInfo = #winInfo{} -%% Command = ignore -%%         | stopped -%%         | {edit, Value} -%%-------------------------------------------------------------------- -handle_event({gs, _Id, destroy, _Data, _Arg}, _WinInfo) -> -    stopped; -handle_event({gs, Id, keypress, Data, ['Return'|_]}, WinInfo) -> -    gs:config(WinInfo#winInfo.button, flash), -    handle_event({gs, Id, click, Data, ["OK"]}, WinInfo); -handle_event({gs, _Id, click, _Data, ["OK"|_]}, WinInfo) -> -    Ent = WinInfo#winInfo.entry, -    Str = gs:read(Ent, text), -    Type = WinInfo#winInfo.type, -    case erl_scan:string(Str) of -	{ok, Tokens, _EndLine} when Type==term -> -	    case erl_parse:parse_term(Tokens++[{dot, 1}]) of -		{ok, Value} -> {edit, Value}; -		_Error -> ignore -	    end; -	{ok, [{Type, _Line, Value}], _EndLine} when Type/=term -> -	    {edit, Value}; -	_ -> -	    ignore -    end; -handle_event({gs, _Id, click, _Data, ["Cancel"|_]}, _WinInfo) -> -    stopped; -handle_event(_GSEvent, _WinInfo) -> -    ignore. diff --git a/lib/debugger/src/dbg_ui_filedialog_win.erl b/lib/debugger/src/dbg_ui_filedialog_win.erl deleted file mode 100644 index 52dc2012f3..0000000000 --- a/lib/debugger/src/dbg_ui_filedialog_win.erl +++ /dev/null @@ -1,340 +0,0 @@ -%% -%% %CopyrightBegin% -%%  -%% Copyright Ericsson AB 2002-2012. All Rights Reserved. -%%  -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%%  -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%%  -%% %CopyrightEnd% -%% - --module(dbg_ui_filedialog_win). --compile([{nowarn_deprecated_function,{gs,button,2}}, -          {nowarn_deprecated_function,{gs,config,2}}, -          {nowarn_deprecated_function,{gs,entry,3}}, -          {nowarn_deprecated_function,{gs,label,2}}, -          {nowarn_deprecated_function,{gs,listbox,3}}, -          {nowarn_deprecated_function,{gs,read,2}}, -          {nowarn_deprecated_function,{gs,window,2}}]). - -%% External exports --export([create_win/6, create_win/7, get_window/1, -	 tag/2, -	 handle_event/2]). - --record(winInfo, {window,        % gsobj() -		  extra,         % fun() -		  cwd,           % string() -		  pattern        % string() -		 }). - -%%==================================================================== -%% External exports -%%==================================================================== - -%%-------------------------------------------------------------------- -%% create_win(GS, Title, Pos, Mode, Filter, Extra) -%% create_win(GS, Title, Pos, Mode, Filter, Extra, FileName) -> #winInfo{} -%%   GS  = term() -%%   Title = string() -%%   Pos = {X,Y} -%%   Mode = normal | multiselect -%%   Filter = string() File name that may include * symbols. -%%   Extra = fun(File) -> {true, tag} | true | {error, term()} -%%   FileName = string() Suggested file name when saving -%%-------------------------------------------------------------------- -create_win(GS, Title, {X,Y}, Mode, Filter, Extra) -> -    create_win(GS, Title, {X,Y}, Mode, Filter, Extra, null). -create_win(GS, Title, {X,Y}, Mode, Filter, Extra, FileName) -> -    Pad = 8, -    Wlb = 480, Hlb = 130, - -    Font = dbg_ui_win:font(normal), - -    {Wlbl, Hlbl} = dbg_ui_win:min_size(["Directories"], 80, 20), -    {Wbtn, Hbtn} = dbg_ui_win:min_size(["Filter","Cancel"], 70, 30), - -    %% Window -    Win = gs:window(GS, [{title,Title}, {x, X}, {y,Y}, {destroy,true}]), - -    %% 'Filter' label and entry (for selecting directory) -    gs:label(Win, [{label, {text,"Filter"}}, {font, Font}, {align, sw}, -		   {x, Pad+2}, {y, Pad}, {width,Wlbl}, {height,Hlbl}]), -    gs:entry('Filter', Win, [{x, Pad}, {y, Pad+Hlbl}, -			     {width, Wlb}, {height, Hbtn}, -			     {keypress, true}]), - -    %% Listboxes (showing directories and files) -    Xmid = Pad + Wlb/2, -    Y2 = Pad + Hlbl + Hbtn + Pad, -    gs:label(Win, [{label, {text,"Directories"}}, -		   {font, Font}, {align, sw}, -		   {x, Pad+2}, {y, Y2}, -		   {width, Wlbl}, {height, Hlbl}]), -    gs:label(Win, [{label, {text,"Files"}}, -		   {font, Font}, {align, sw}, -		   {x, Xmid+Pad/2+2}, {y, Y2}, -		   {width, Wlbl}, {height, Hlbl}]), -    gs:listbox('Dirs', Win, [{x, Pad}, {y, Y2+Hlbl}, -			     {width, Wlb/2-Pad/2}, {height, Hlb}, -			     {vscroll, right}, -			     {click, true}, {doubleclick, true}]), -    gs:listbox('Files', Win, [{x, Xmid+Pad/2}, {y, Y2+Hlbl}, -			      {width, Wlb/2-Pad/2}, {height, Hlb}, -			      {vscroll, right}, -			      {click, true}, {doubleclick, true}]), - -    %% 'Selection' label and entry (for selecting file) -    Y3 = Y2 + Hlbl + Hlb, -    gs:label(Win, [{label, {text,"Selection"}}, {font,Font}, {align,sw}, -		   {x, Pad+2}, {y, Y3}, {width, Wlbl}, {height, Hlbl}]), -    gs:entry('Selection', Win, [{x, Pad}, {y, Y3+Hlbl}, -				{width, Wlb}, {height, Hbtn}, -				{keypress, true}]), - -    %% Buttons -    Y4 = Y3 + Hlbl + Hbtn + Pad, -    Wb = Wlb - Wbtn, -    Opts = [{y, Y4}, {width, Wbtn}, {height, Hbtn}, {font, Font}], -    case Mode of -	normal -> -	    gs:button(Win, [{label, {text,"OK"}}, {x, Pad}, -			    {data, select} | Opts]), -	    gs:button(Win, [{label, {text,"Filter"}}, {x, Wlb/2-Wbtn/2}, -			    {data, filter} | Opts]), -	    gs:button(Win, [{label, {text,"Cancel"}}, {x, Pad+Wb}, -			    {data, done} | Opts]); -	multiselect -> -	    gs:button(Win, [{label, {text,"Choose"}}, {x, Pad}, -			    {data, select} | Opts]), -	    gs:button(Win, [{label, {text,"All"}}, {x, Pad+Wb/3}, -			    {data, multiselect} | Opts]), -	    gs:button(Win, [{label, {text,"Filter"}}, {x, Pad+2*Wb/3}, -			    {data, filter} | Opts]), -	    gs:button(Win, [{label, {text,"Done"}}, {x, Pad+Wb}, -			    {data, done} | Opts]) -    end, - -    %% Insert contents -    {ok, Home} = file:get_cwd(), -    {Cwd, Pattern} = update_win(Filter, Extra, Home), -    if -	is_list(FileName) -> -	    gs:config('Selection', {text, filename:join(Cwd,FileName)}); -	true -> ignore -    end, - -    Wwin = Pad + Wlb + Pad, -    Hwin = Y4 + Hbtn + Pad, -    gs:config(Win, [{width, Wwin}, {height, Hwin}, {map, true}]), - -    #winInfo{window=Win, extra=Extra, cwd=Cwd, pattern=Pattern}. - -%%-------------------------------------------------------------------- -%% get_window(WinInfo) -> Window -%%   WinInfo = #winInfo{} -%%   Window = gsobj() -%%-------------------------------------------------------------------- -get_window(WinInfo) -> -    WinInfo#winInfo.window. - -%%-------------------------------------------------------------------- -%% tag(WinInfo, File) -%%   WinInfo = #winInfo{} -%%   File = string() -%%-------------------------------------------------------------------- -tag(WinInfo, File0) -> -    File = relfile(WinInfo#winInfo.cwd, File0), -    case member(File, gs:read('Files', items)) of -	{true, Index} -> gs:config('Files', {change, {Index, tag(File)}}); -	false -> ignore -    end. - -tag(Str) -> [$*|Str]. -untag([$*|Str]) -> Str; -untag([$(|Str]) -> [$)|Rts] = lists:reverse(Str),lists:reverse(Rts); -untag(Str) -> Str. - -member(E, L) ->        member(E, L, 0). -member(E, [E|_], I) -> {true, I}; -member(E, [_|T], I) -> member(E, T, I+1); -member(_E, [], _I) ->  false. - -%%-------------------------------------------------------------------- -%% handle_event(GSEvent, WinInfo) -> Command -%%   GSEvent = {gs, Id, Event, Data, Arg} -%%   WinInfo = #winInfo{} -%%   Command = ignore -%%           | {stopped, Dir} -%%           | {win, WinInfo} -%%           | {select, File} | {multiselect, Dir, FileNames} -%%-------------------------------------------------------------------- -handle_event({gs, _Id, destroy, _Data, _Args}, WinInfo) -> -    {stopped, WinInfo#winInfo.cwd}; - -handle_event({gs, 'Filter', keypress, _Data, ['Return'|_]}, WinInfo) -> -    handle_event({gs, null, click, filter, null}, WinInfo); -handle_event({gs, 'Selection', keypress, _Data, ['Return'|_]}, WinInfo) -> -    handle_event({gs, null, click, select, null}, WinInfo); - -handle_event({gs, 'Dirs', click, _Data, [0,"..",true|_]}, WinInfo) -> -    Filter = filename:join(filename:dirname(WinInfo#winInfo.cwd), -			   WinInfo#winInfo.pattern), -    gs:config('Filter', {text, Filter}), -    ignore; -handle_event({gs, 'Dirs', click, _Data, [_Index,Str,true|_]}, WinInfo) -> -    Filter = filename:join([WinInfo#winInfo.cwd, Str, -			    WinInfo#winInfo.pattern]), -    gs:config('Filter', {text, Filter}), -    ignore; -handle_event({gs, 'Dirs', doubleclick, _Data, _Arg}, WinInfo) -> -    handle_event({gs, null, click, filter, null}, WinInfo); - -handle_event({gs, 'Files', click, _Data, [_Index,Str,true|_]}, WinInfo) -> -    Selection = filename:join(WinInfo#winInfo.cwd, untag(Str)), -    gs:config('Selection', {text, Selection}), -    ignore; -handle_event({gs, 'Files', doubleclick, _Data, _Arg}, WinInfo) -> -    handle_event({gs, null, click, select, null}, WinInfo); -   -handle_event({gs, _Id, click, select, _Arg}, _WinInfo) -> -    {select, gs:read('Selection', text)}; -handle_event({gs, _Id, click, multiselect, _Arg}, WinInfo) -> -    Files = [untag(File) || File <- gs:read('Files', items)], -    {multiselect, WinInfo#winInfo.cwd, Files}; -handle_event({gs, _Id, click, filter, _Arg}, WinInfo) -> -    {Cwd, Pattern} = update_win(gs:read('Filter', text), -				WinInfo#winInfo.extra, -				WinInfo#winInfo.cwd), -    {win, WinInfo#winInfo{cwd=Cwd, pattern=Pattern}}; -handle_event({gs, _Id, click, done, _Arg}, WinInfo) -> -    {stopped, WinInfo#winInfo.cwd}; -     -handle_event(_GSEvent, _WinInfo) -> -    ignore. - -%%==================================================================== -%% Internal functions -%%==================================================================== - -update_win(Filter, ExtraFilter, Prev) -> -    {Res, {Filter2, Cwd, FilePattern}} = check_filter(Filter, Prev), - -    Dirs = [".." | get_subdirs(Cwd)], - -    gs:config('Filter', {text, Filter2}), -    gs:config('Dirs', {items, Dirs}), -    gs:config('Selection', {text, Cwd}), - -    case Res of -	ok -> -	    Matching = lists:sort(filelib:wildcard(Filter2, erl_prim_loader)), -	    Files = extra_filter(Matching, Cwd, ExtraFilter), -	    gs:config('Files', {items, Files}); -	error -> -	    gs:config('Files', beep) -    end, - -    {Cwd, FilePattern}. - -%% check_filter(Filter, Prev) -> {ok, Res} | {error, Res} -%%   Res = {Filter, Cwd, FilePattern} -%%   Filter = Prev = Cwd = FilePattern = string() -check_filter(Filter0, Prev) -> -    Filter = case filename:pathtype(Filter0) of -		 absolute -> Filter0; -		 _Relative -> filename:absname(Filter0, Prev) -	     end, -    Comps = filename:split(Filter), -    Last = lists:last(Comps), -    FilePattern = case is_pattern(Last) of -		      true -> Last; -		      false -> "*" -		  end, -    {Cwd, Rest} = max_existing(Comps), -    case Rest of -	[] -> -	    %% Filter = existing file or directory -	    Res = case filelib:is_dir(Filter, erl_prim_loader) of -		      true -> {filename:join(Filter, "*"), Filter, "*"}; -		      false -> {Filter, filename:dirname(Filter), -				filename:basename(Filter)} -		  end, -	    {ok, Res}; -	[FilePattern] -> -	    %% Filter = existing dir and valid pattern -	    {ok, {Filter, Cwd, FilePattern}};  -	Comps -> -	    %% Filter = garbage -	    {error, {Prev, Prev, "*"}}; -	[Name|_Names] -> -	    %% Filter = existing dir ++ pattern or non-existing file/dir -	    case is_pattern(Name) of -		true -> {ok, {Filter, Cwd, FilePattern}}; -		false -> {error, {Cwd, Cwd, ""}} -	    end -    end. - -max_existing([Name | Names]) -> -    case filelib:is_file(Name, erl_prim_loader) of -	true -> max_existing(Name, Names); -	false -> {[], [Name | Names]} -    end. -max_existing(Dir, [Name | Names]) -> -    Dir2 = filename:join(Dir, Name), -    case filelib:is_file(Dir2, erl_prim_loader) of -	true when Names =:= [] -> {Dir2, []}; -	true -> max_existing(Dir2, Names); -	false -> {Dir, [Name | Names]} -    end. - -is_pattern(Str) -> -    lists:member($*, Str). - -extra_filter([File|Files], Dir, Fun) -> -    case Fun(File) of -	true -> -	    [relfile(Dir, File) | extra_filter(Files, Dir, Fun)]; -	{true,tag} -> -	    [[$*|relfile(Dir,File)] | extra_filter(Files, Dir, Fun)]; -	{true,disable} -> -	    [[$(|relfile(Dir,File)]++[$)] | extra_filter(Files, Dir, Fun)]; -	{error, _Reason} -> extra_filter(Files, Dir, Fun) -    end; -extra_filter([], _Dir, _Fun) -> []. - -get_subdirs(Dir) -> -    case erl_prim_loader:list_dir(Dir) of -	{ok, FileNames} -> -	    X = [FN || FN <- FileNames, -		       filelib:is_dir(filename:join(Dir, FN), erl_prim_loader)], -	    lists:sort(X); -	_Error -> -	    [] -    end. - -%% Return the "remainder" of a file name relative a dir name, examples: -%%   relfile("/home/gunilla", "/home/gunilla/m.erl") -> "m.erl" -%%   relfile("/home/gunilla/dir", "/home/gunilla/dir/m.erl") -> "dir/m.erl" -%%   relfile("/home/gunilla", "/home/arne/m.erl") -> "/home/arne/m.erl" -relfile(Dir, File) -> -    case compare(Dir, File) of -	error -> File; -	RelFile -> RelFile -    end. - -compare([_|Dir], [_|File]) -> -    compare(Dir, File); -compare([], [$/|File]) -> -    File; -compare(_, _) -> -    error. diff --git a/lib/debugger/src/dbg_ui_interpret.erl b/lib/debugger/src/dbg_ui_interpret.erl deleted file mode 100644 index 73392d40cb..0000000000 --- a/lib/debugger/src/dbg_ui_interpret.erl +++ /dev/null @@ -1,161 +0,0 @@ -%% -%% %CopyrightBegin% -%%  -%% Copyright Ericsson AB 1997-2011. All Rights Reserved. -%%  -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%%  -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%%  -%% %CopyrightEnd% -%% --module(dbg_ui_interpret). - --include_lib("kernel/include/file.hrl"). - -%% External exports --export([start/4]). - -%% Internal exports --export([init/6]). - --record(state, {gs,      % term() Graphics system id -		win,     % term() Interpret dialog window data -		monitor, % pid() Monitor pid -		mode     % local | global -	       }). - -%%==================================================================== -%% External exports -%%==================================================================== - -%%-------------------------------------------------------------------- -%% start(GS, Pos, Dir, Mode) -%%   GS  = Graphics system id -%%   Dir = string() -%%   Pos = {X,Y} -%%   Mode = local | global -%%-------------------------------------------------------------------- -start(GS, Pos, Dir, Mode) -> -    Title = "Interpret Dialog", -    case dbg_ui_winman:is_started(Title) of -	true -> ignore; -	false -> -	    spawn(?MODULE, init, [self(), GS, Pos, Title, Dir, Mode]) -    end. - -%%==================================================================== -%% Internal exports -%%==================================================================== - -init(Monitor, GS, Pos, Title, Dir, Mode) -> -    Filter = filename:join(Dir, "*.erl"), -    Extra = fun(File) -> -		    case int:interpretable(File) of -			true -> -			    ModS = filename:basename(File, ".erl"), -			    Mod = list_to_atom(ModS), -			    case int:file(Mod) of -				File -> {true, tag}; -				_ -> true % {error,not_loaded} | File2 -			    end; -			_Error -> {true,disable} -		    end -	    end, -			 -    %% Create interpret dialog window -    Win = dbg_ui_filedialog_win:create_win(GS, Title, Pos, multiselect, -					   Filter, Extra), -    Window = dbg_ui_filedialog_win:get_window(Win), -    dbg_ui_winman:insert(Title, Window), - -    State = #state{gs=GS, win=Win, monitor=Monitor, mode=Mode}, -    loop(State). - - -%%==================================================================== -%% Main loop and message handling -%%==================================================================== - -loop(State) -> -    receive - -	%% From the GUI -	GuiEvent when is_tuple(GuiEvent), element(1, GuiEvent)==gs -> -	    Cmd = dbg_ui_filedialog_win:handle_event(GuiEvent, -						    State#state.win), -	    State2 = gui_cmd(Cmd, State), -	    loop(State2); - -	%% From the dbg_ui_winman process (Debugger window manager) -	{dbg_ui_winman, update_windows_menu, _Data} -> -	    loop(State); -	{dbg_ui_winman, destroy} -> -	    exit(normal) -    end. - -gui_cmd(ignore, State) -> -    State; -gui_cmd({stopped, Dir}, State) ->	 -    State#state.monitor ! {dbg_ui_interpret, Dir}, -    exit(normal); -gui_cmd({win, Win}, State) -> -    State#state{win=Win}; -gui_cmd({select, File}, State) -> -    Res = case State#state.mode of -	      local -> int:i(File); -	      global -> int:ni(File) -	  end, - -    case Res of -	%% Interpretation succeeded, tag the file name -	{module, _Mod} -> -	    dbg_ui_filedialog_win:tag(State#state.win, File); - -	%% Interpretation failed -	error -> -	    Error = format_error(int:interpretable(File)), -	    Msg = ["Error when interpreting:", File, Error], -	    Window = dbg_ui_filedialog_win:get_window(State#state.win), -	    tool_utils:notify(Window, Msg) -    end, -    State; -gui_cmd({multiselect, Dir, FileNames}, State) -> -    interpret_all(State, Dir, FileNames), -    State. - -interpret_all(State, Dir, [File0|Files]) -> -    File = filename:join(Dir, File0), -    Res = case State#state.mode of -	      local -> int:i(File); -	      global -> int:ni(File) -	  end, -    case Res of -	{module, _Mod} -> -	    dbg_ui_filedialog_win:tag(State#state.win, File), -	    interpret_all(State, Dir, Files); -	error -> -	    Window = dbg_ui_filedialog_win:get_window(State#state.win), -	    Error = format_error(int:interpretable(File)), -	    Msg = ["Error when interpreting:", File, Error, -		   "OK to continue?"], -	    case tool_utils:confirm(Window, Msg) of -		ok -> interpret_all(State, Dir, Files); -		cancel -> true -	    end -    end; -interpret_all(_State, _Dir, []) -> -    true. - -format_error({error,no_beam}) -> "No BEAM file"; -format_error({error,no_debug_info}) -> "No debug_info in BEAM file"; -format_error({error,badarg}) -> "File does not exist"; -format_error({error,{app,App}}) -> -    "Cannot interpret "++atom_to_list(App)++" modules". diff --git a/lib/debugger/src/dbg_ui_mon.erl b/lib/debugger/src/dbg_ui_mon.erl deleted file mode 100644 index 82fe210968..0000000000 --- a/lib/debugger/src/dbg_ui_mon.erl +++ /dev/null @@ -1,738 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% -%% --module(dbg_ui_mon). - --include_lib("kernel/include/file.hrl"). - -%% External exports --export([start/2, stop/0]). - --define(TRACEWIN, ['Button Area', 'Evaluator Area', 'Bindings Area']). --define(BACKTRACE, 100). - --record(pinfo, {pid,       % pid() -		status     % break | exit | idle | running | waiting -	       }). - --record(state, {mode,      % local | global -		starter,   % bool() 'true' if int was started by me - -		gs,        % term() Graphics system id -		win,       % term() Monitor window data -		focus,     % undefined | #pinfo{} Process in focus -		coords,    % {X,Y} Mouse pointer position - -		intdir,    % string() Default dir -		pinfos,    % [#pinfo{}] Debugged processes - -		tracewin,  % [Area] Areas shown in trace window -		backtrace, % integer() Number of call frames to fetch - -		attach,    % false | {Flags, Function} - -		sfile,     % default | string() Settings file -		changed    % boolean() Settings have been changed -	       }).  - -%%==================================================================== -%% External exports -%%==================================================================== - -%%-------------------------------------------------------------------- -%% start(Mode, SFile) -> {ok, Pid} | {error, Reason} -%%   Mode = local | global -%%   SFile = string() | default  Settings file -%%   Pid = pid() -%%   Reason = {already_started,Pid} | term() -%%-------------------------------------------------------------------- -start(Mode, SFile) -> -    case whereis(?MODULE) of -	undefined -> -	    CallingPid = self(), -	    Pid = spawn(fun () -> init(CallingPid, Mode, SFile) end), -	    receive -		{initialization_complete, Pid} -> -		    {ok, Pid}; -		Error -> -		    Error -	    end; - -	Pid -> -            {error, {already_started,Pid}} -    end. - -%%-------------------------------------------------------------------- -%% stop() -> ok -%%-------------------------------------------------------------------- -stop() -> -    case whereis(?MODULE) of -	undefined -> -	    ok; -	Pid -> -	    Flag = process_flag(trap_exit, true), -	    link(Pid), -	    Pid ! stop, -	    receive -		{'EXIT', Pid, stop} -> -		    process_flag(trap_exit, Flag), -		    ok -	    end -    end. - - -%%==================================================================== -%% Initialization -%%==================================================================== - -init(CallingPid, Mode, SFile) -> -    register(?MODULE, self()), - -    %% Graphics system -    case catch dbg_ui_mon_win:init() of -	{'EXIT', Reason} -> -	    CallingPid ! {error, Reason}; -	GS -> -	    init2(CallingPid, Mode, SFile, GS) -    end. - -init2(CallingPid, Mode, SFile, GS) -> - -    %% Start Int if necessary and subscribe to information from it -    Bool = case int:start() of -	       {ok, _Int} -> true; -	       {error, {already_started, _Int}} -> false -	   end, -    int:subscribe(), - -    %% Start other necessary stuff -    dbg_ui_winman:start(), % Debugger window manager - -    %% Create monitor window -    Title = "Monitor", -    Win = dbg_ui_mon_win:create_win(GS, Title, menus()), -    Window = dbg_ui_mon_win:get_window(Win), -    dbg_ui_winman:insert(Title, Window), - -    %% Initial process state -    State1 = #state{mode    = Mode, -		    starter = Bool, - -		    gs      = GS, -		    win     = Win, -		    focus   = undefined, -		    coords  = {0,0}, - -		    intdir  = element(2, file:get_cwd()), -		    pinfos  = [], - -		    sfile   = SFile, -		    changed = false -		   }, - -    State2 = init_options(?TRACEWIN,            % Trace Window -			  int:auto_attach(),    % Auto Attach -			  int:stack_trace(),    % Stack Trace -			  ?BACKTRACE,           % Back Trace Size -			  State1), - -    State3 = init_contents(int:interpreted(),   % Modules -			   int:all_breaks(),    % Breakpoints -			   int:snapshot(),      % Processes -			   State2), - -    %% Disable/enable functionality according to process in focus (none) -    gui_enable_functions(State3#state.focus), - -    CallingPid ! {initialization_complete, self()}, - -    if -	SFile =:= default -> -	    loop(State3); -	true -> -	    loop(load_settings(SFile, State3)) -    end. - -init_options(TraceWin, AutoAttach, StackTrace, BackTrace, State) -> -    lists:foreach(fun(Area) -> -			  dbg_ui_mon_win:select(Area, true) -		  end, -		  TraceWin), - -    case AutoAttach of -	false -> ignore; -	{Flags, _Function} -> -	    dbg_ui_mon_win:show_option(State#state.win, -				       auto_attach, Flags), -	    lists:foreach(fun(Flag) -> -				  dbg_ui_mon_win:select(map(Flag), true) -			  end, -			  Flags) -    end, - -    dbg_ui_mon_win:show_option(State#state.win, -			       stack_trace, StackTrace), -    dbg_ui_mon_win:select(map(StackTrace), true), - -    dbg_ui_mon_win:show_option(State#state.win, back_trace, BackTrace), - -    State#state{tracewin=TraceWin, backtrace=BackTrace}. - -init_contents(Mods, Breaks, Processes, State) -> -    Win2 = -        lists:foldl(fun(Mod, Win) -> -			    dbg_ui_mon_win:add_module(Win,'Module',Mod) -		    end, -		    State#state.win, -		    Mods), - -    Win3 =  -        lists:foldl(fun(Break, Win) -> -			    dbg_ui_mon_win:add_break(Win,'Break',Break) -		    end, -		    Win2, -		    Breaks), - -    lists:foldl(fun(PidTuple, State0) -> -			int_cmd({new_process, PidTuple}, State0) -		end, -		State#state{win=Win3}, -		Processes). - - -%%==================================================================== -%% Main loop and message handling -%%==================================================================== - -loop(State) -> -    receive - -	stop -> -	    gui_cmd(stopped, State); - -	%% From the GUI -	GuiEvent when is_tuple(GuiEvent), element(1, GuiEvent) =:= gs -> -	    Cmd = dbg_ui_mon_win:handle_event(GuiEvent,State#state.win), -	    State2 = gui_cmd(Cmd, State), -	    loop(State2); - -	%% From the interpreter process -	{int, Cmd} -> -	    State2 = int_cmd(Cmd, State), -	    loop(State2); - -	%% From the dbg_ui_interpret process -	{dbg_ui_interpret, Dir} -> -	    loop(State#state{intdir=Dir}); - -	%% From the dbg_ui_edit process -	{dbg_ui_edit, 'Backtrace:', BackTrace}  -> -	    dbg_ui_mon_win:show_option(State#state.win, -				       back_trace, BackTrace), -	    loop(State#state{backtrace=BackTrace}); - -	%% From the dbg_ui_settings process -	{dbg_ui_settings, SFile, Action} -> -	    State2 = case Action of -			 load -> load_settings(SFile, State); -			 save -> save_settings(SFile, State) -		     end, -	    loop(State2); - -	%% From the dbg_ui_winman process (Debugger window manager) -	{dbg_ui_winman, update_windows_menu, Data} -> -	    dbg_ui_winman:update_windows_menu(Data), -	    loop(State) -    end. - -%%--Commands from the GUI--------------------------------------------- -%% Act upon a command from the GUI. In most cases, it is only necessary -%% to call a relevant int-function. int will then report when the action -%% has been taken. - -gui_cmd(ignore, State) -> -    State; -gui_cmd(stopped, State) -> -    if -	State#state.starter =:= true -> int:stop(); -	true -> int:auto_attach(false) -    end, -    exit(stop); -gui_cmd({coords, Coords}, State) -> -    State#state{coords=Coords}; - -gui_cmd({shortcut, Key}, State) -> -    case shortcut(Key) of -	{always, Cmd} -> gui_cmd(Cmd, State); -	{if_enabled, Cmd} -> -	    case dbg_ui_mon_win:is_enabled(Cmd) of -		true -> gui_cmd(Cmd, State); -		false -> State -	    end; -	false -> State -    end; - -%% File Menu -gui_cmd('Load Settings...', State) -> -    Window = dbg_ui_mon_win:get_window(State#state.win), -    dbg_ui_settings:start(Window, State#state.coords, -			  load, State#state.sfile), -    State; -gui_cmd('Save Settings...', State) -> -    Window = dbg_ui_mon_win:get_window(State#state.win), -    dbg_ui_settings:start(Window, State#state.coords, -			  save, State#state.sfile), -    State; -gui_cmd('Exit', State) -> -    gui_cmd(stopped, State); - -%% Edit Menu -gui_cmd('Refresh', State) -> -    int:clear(), -    Win = dbg_ui_mon_win:clear_processes(State#state.win), -    gui_enable_functions(undefined), -    State2 = State#state{win=Win, focus=undefined, pinfos=[]}, -    lists:foldl(fun(PidTuple, S) -> -			int_cmd({new_process,PidTuple}, S) -		end, -		State2, -		int:snapshot()); -gui_cmd('Kill All', State) -> -    lists:foreach(fun(PInfo) -> -			  case PInfo#pinfo.status of -			      exit -> ignore; -			      _Status -> exit(PInfo#pinfo.pid, kill) -			  end -		  end, -		  State#state.pinfos), -    State; - -%% Module Menu -gui_cmd('Interpret...', State) -> -    dbg_ui_interpret:start(State#state.gs, State#state.coords, -			   State#state.intdir, State#state.mode), -    State; -gui_cmd('Delete All Modules', State) -> -    lists:foreach(fun(Mod) -> int:nn(Mod) end, int:interpreted()), -    State; -gui_cmd({module, Mod, What}, State) -> -    case What of -	delete -> int:nn(Mod); -	view -> dbg_ui_view:start(State#state.gs, Mod) -    end, -    State; - -%% Process Menu -gui_cmd('Step', State) -> -    int:step((State#state.focus)#pinfo.pid), -    State; -gui_cmd('Next', State) -> -    int:next((State#state.focus)#pinfo.pid), -    State; -gui_cmd('Continue', State) -> -    int:continue((State#state.focus)#pinfo.pid), -    State; -gui_cmd('Finish ', State) -> -    int:finish((State#state.focus)#pinfo.pid), -    State; -gui_cmd('Attach', State) -> -    Pid = (State#state.focus)#pinfo.pid, -    case dbg_ui_winman:is_started(dbg_ui_trace:title(Pid)) of -	true -> ignore; -	false -> int:attach(Pid, trace_function(State)) -    end, -    State; -gui_cmd('Kill', State) -> -    exit((State#state.focus)#pinfo.pid, kill), -    State; - -%% Break Menu -gui_cmd('Line Break...', State) -> -    dbg_ui_break:start(State#state.gs, State#state.coords, line), -    State; -gui_cmd('Conditional Break...', State) -> -    dbg_ui_break:start(State#state.gs, State#state.coords, conditional), -    State; -gui_cmd('Function Break...', State) -> -    dbg_ui_break:start(State#state.gs, State#state.coords, function), -    State; -gui_cmd('Enable All', State) -> -    Breaks = int:all_breaks(), -    lists:foreach(fun ({{Mod, Line}, _Options}) -> -			  int:enable_break(Mod, Line) -		  end, -		  Breaks), -    State; -gui_cmd('Disable All', State) -> -    Breaks = int:all_breaks(), -    lists:foreach(fun ({{Mod, Line}, _Options}) -> -			  int:disable_break(Mod, Line) -		  end, -		  Breaks), -    State; -gui_cmd('Delete All', State) -> -    int:no_break(), -    State; -gui_cmd({break, {Mod, Line}, What}, State) -> -    case What of -	delete -> int:delete_break(Mod, Line); -	{status, inactive} -> int:disable_break(Mod, Line); -	{status, active} -> int:enable_break(Mod, Line); -	{trigger, Action} -> int:action_at_break(Mod, Line, Action) -    end, -    State; - -%% Options Commands -gui_cmd({'Trace Window', TraceWin}, State) -> -    State2 = State#state{tracewin=TraceWin}, -    case State#state.attach of -	false -> ignore; -	{Flags, {dbg_ui_trace, start, StartFlags}} -> -	    case trace_function(State2) of -		{_, _, StartFlags} -> ignore; -		NewFunction -> % {_, _, NewStartFlags} -		    int:auto_attach(Flags, NewFunction) -	    end; -	_AutoAttach -> ignore -    end, -    State2; -gui_cmd({'Auto Attach', When}, State) -> -    if -	When =:= [] -> int:auto_attach(false); -	true -> -	    Flags = [map(Name) || Name <- When], -	    int:auto_attach(Flags, trace_function(State)) -    end, -    State; -gui_cmd({'Stack Trace', [Name]}, State) -> -    int:stack_trace(map(Name)), -    State; -gui_cmd('Back Trace Size...', State) -> -    dbg_ui_edit:start(State#state.gs, State#state.coords, "Backtrace", -		      'Backtrace:', {integer, State#state.backtrace}), -    State; - -%% Help Menu -gui_cmd('Debugger', State) -> -    HelpFile = filename:join([code:lib_dir(debugger), "doc", "html", "index.html"]), -    Window = dbg_ui_mon_win:get_window(State#state.win), -    tool_utils:open_help(Window, HelpFile), -    State; - -gui_cmd({focus, Pid, Win}, State) -> -    {value, PInfo} = -	lists:keysearch(Pid, #pinfo.pid, State#state.pinfos), -    gui_enable_functions(PInfo), -    State#state{win=Win, focus=PInfo}; -gui_cmd(default, State) -> -    case lists:member('Attach', menus(enabled, State#state.focus)) of -	true -> gui_cmd('Attach', State); -	false -> State -    end. - -%%--Commands from the interpreter------------------------------------- - -int_cmd({interpret, Mod}, State) -> -    Win = dbg_ui_mon_win:add_module(State#state.win, 'Module', Mod), -    State#state{win=Win}; -int_cmd({no_interpret, Mod}, State) -> -    Win = dbg_ui_mon_win:delete_module(State#state.win, Mod), -    State#state{win=Win}; - -int_cmd({new_process, {Pid, Function, Status, Info}}, State) -> - -    %% Create record with information about the process -    Name = registered_name(Pid), -    PInfo = #pinfo{pid=Pid, status=Status}, - -    %% Update window -    Win = dbg_ui_mon_win:add_process(State#state.win, -				     Pid, Name, Function, Status, Info), - -    %% Store process information -    PInfos = State#state.pinfos ++ [PInfo], -    State#state{win=Win, pinfos=PInfos}; -int_cmd({new_status, Pid, Status, Info}, State) -> - -    %% Find stored information about the process -    PInfos = State#state.pinfos, -    {value, PInfo} = lists:keysearch(Pid, #pinfo.pid, PInfos), - -    %% Update process information -    PInfo2 = PInfo#pinfo{status=Status}, -    PInfos2 = lists:keyreplace(Pid, #pinfo.pid, PInfos, PInfo2), -    State2 = State#state{pinfos=PInfos2}, - -    %% Update window -    dbg_ui_mon_win:update_process(State2#state.win, Pid, Status, Info), -    case State2#state.focus of -	#pinfo{pid=Pid} -> -	    gui_enable_functions(PInfo2), -	    State2#state{focus=PInfo2}; -	_ -> -	    State2 -    end; - -int_cmd({new_break, Break}, State) -> -    Win = dbg_ui_mon_win:add_break(State#state.win, 'Break', Break), -    State#state{win=Win}; -int_cmd({delete_break, Point}, State) -> -    Win = dbg_ui_mon_win:delete_break(State#state.win, Point), -    State#state{win=Win}; -int_cmd({break_options, Break}, State) -> -    dbg_ui_mon_win:update_break(State#state.win, Break), -    State; -int_cmd(no_break, State) -> -    Win = dbg_ui_mon_win:clear_breaks(State#state.win), -    State#state{win=Win}; -int_cmd({no_break, Mod}, State) -> -    Win = dbg_ui_mon_win:clear_breaks(State#state.win, Mod), -    State#state{win=Win}; - -int_cmd({auto_attach, AutoAttach}, State) -> -    OnFlags = case AutoAttach of -		  false -> []; -		  {Flags, _Function} -> Flags -	      end, -    OffFlags = [init, exit, break] -- OnFlags, -    dbg_ui_mon_win:show_option(State#state.win, auto_attach, OnFlags), -    lists:foreach(fun(Flag) -> -			  dbg_ui_mon_win:select(map(Flag), true) -		  end, -		  OnFlags), -    lists:foreach(fun(Flag) -> -			  dbg_ui_mon_win:select(map(Flag), false) -		  end, -		  OffFlags), -    State#state{attach=AutoAttach}; -int_cmd({stack_trace, Flag}, State) -> -    dbg_ui_mon_win:show_option(State#state.win, stack_trace, Flag), -    dbg_ui_mon_win:select(map(Flag), true), -    State. - - -%%==================================================================== -%% GUI auxiliary functions -%%==================================================================== - -menus() -> -    [{'File', [{'Load Settings...', 0}, -	       {'Save Settings...', 2}, -	       separator, -	       {'Exit', 0}]}, -     {'Edit', [{'Refresh', no}, -	       {'Kill All', no}]}, -     {'Module', [{'Interpret...', 0}, -		 {'Delete All Modules', no}, -		 separator]}, -     {'Process', [{'Step', 0}, -		  {'Next', 0}, -		  {'Continue', 0}, -		  {'Finish ', 0}, -		  separator, -		  {'Attach', 0}, -		  {'Kill', no}]}, -     {'Break', [{'Line Break...', 5}, -		{'Conditional Break...', no}, -		{'Function Break...', no}, -		separator, -		{'Enable All', no}, -		{'Disable All', no}, -		{'Delete All', 0}, -		separator]}, -     {'Options', [{'Trace Window', no, cascade, -		   [{'Button Area', no, check}, -		    {'Evaluator Area', no, check}, -		    {'Bindings Area', no, check}, -		    {'Trace Area', no, check}]}, -		  {'Auto Attach', no, cascade, -		   [{'First Call', no, check}, -		    {'On Break', no, check}, -		    {'On Exit', no, check}]}, -		  {'Stack Trace', no, cascade, -		   [{'Stack On, Tail', no, radio}, -		    {'Stack On, No Tail', no, radio}, -		    {'Stack Off', no, radio}]}, -		  {'Back Trace Size...', no}]}, -     {'Help', [{'Debugger', no}]}]. - -menus(enabled,  undefined) -> -    []; -menus(disabled, undefined) -> -    ['Step','Next','Continue','Finish ','Attach','Kill']; -menus(enabled,  #pinfo{status=exit}) -> -    ['Attach']; -menus(disabled, #pinfo{status=exit}) -> -    ['Step','Next','Continue','Finish ','Kill']; -menus(enabled,  #pinfo{status=break}) -> -    ['Step','Next','Continue','Finish ','Attach','Kill']; -menus(disabled, #pinfo{status=break}) -> -    []; -menus(enabled,  _PInfo) -> -    ['Attach','Kill']; -menus(disabled, _PInfo) -> -    ['Step','Next','Continue','Finish ']. - -shortcut(l) -> {always, 'Load Settings...'}; -shortcut(v) -> {always, 'Save Settings...'}; -shortcut(e) -> {always, 'Exit'}; - -shortcut(i) -> {always, 'Interpret...'}; - -shortcut(s) -> {if_enabled, 'Step'}; -shortcut(n) -> {if_enabled, 'Next'}; -shortcut(c) -> {if_enabled, 'Continue'}; -shortcut(f) -> {if_enabled, 'Finish '}; -shortcut(a) -> {if_enabled, 'Attach'}; - -shortcut(b) -> {always, 'Line Break...'}; -shortcut(d) -> {always, 'Delete All'}; - -shortcut(_) -> false. - -%% Enable/disable functionality depending on the state of the process -%% currently in Focus -gui_enable_functions(PInfo) -> -    Enabled = menus(enabled, PInfo), -    Disabled = menus(disabled, PInfo), -    dbg_ui_mon_win:enable(Enabled, true), -    dbg_ui_mon_win:enable(Disabled, false). - -%% Map values used by int to/from GUI names -map('First Call')        -> init;               % Auto attach -map('On Exit')           -> exit; -map('On Break')          -> break; -map(init)                -> 'First Call'; -map(exit)                -> 'On Exit'; -map(break)               -> 'On Break'; - -map('Stack On, Tail')    -> all;               % Stack trace -map('Stack On, No Tail') -> no_tail; -map('Stack Off')         -> false; -map(all)                 -> 'Stack On, Tail'; -map(true)                -> 'Stack On, Tail'; -map(no_tail)             -> 'Stack On, No Tail'; -map(false)               -> 'Stack Off'. - - -%%==================================================================== -%% Debugger settings -%%==================================================================== - -load_settings(SFile, State) -> -    case file:read_file(SFile) of -	{ok, Binary} -> -	    case catch binary_to_term(Binary) of -		{debugger_settings, Settings} -> -		    load_settings2(Settings, -				   State#state{sfile=SFile, -					       changed=false}); -		_Error -> State -	    end; -	{error, _Reason} -> State -    end. - -load_settings2(Settings, State) -> -    {TraceWin, AutoAttach, StackTrace, BackTrace, Files, Breaks} = -	Settings, - -    TraceWinAll = ['Button Area', 'Evaluator Area', 'Bindings Area', -		   'Trace Area'], -    lists:foreach(fun(Area) -> dbg_ui_mon_win:select(Area, true) end, -		  TraceWin), -    lists:foreach(fun(Area) -> dbg_ui_mon_win:select(Area, false) end, -		  TraceWinAll--TraceWin), - -    case AutoAttach of -	false -> int:auto_attach(false); -	{Flags, Function} -> int:auto_attach(Flags, Function) -    end, - -    int:stack_trace(StackTrace), - -    dbg_ui_mon_win:show_option(State#state.win, back_trace, BackTrace), - -    case State#state.mode of -	local -> lists:foreach(fun(File) -> int:i(File) end, Files); -	global -> lists:foreach(fun(File) -> int:ni(File) end, Files) -    end, -    lists:foreach(fun(Break) -> -			  {{Mod, Line}, [Status, Action, _, Cond]} = -			      Break, -			  int:break(Mod, Line), -			  if -			      Status =:= inactive -> -				  int:disable_break(Mod, Line); -			      true -> ignore -			  end, -			  if -			      Action/=enable -> -				  int:action_at_break(Mod,Line,Action); -			      true -> ignore -			  end, -			  case Cond of -			      CFunction when is_tuple(CFunction) -> -				  int:test_at_break(Mod,Line,CFunction); -			      null -> ignore -			  end -		  end, -		  Breaks), - -    State#state{tracewin=TraceWin, backtrace=BackTrace}. - -save_settings(SFile, State) -> -    Settings = {State#state.tracewin, -		int:auto_attach(), -		int:stack_trace(), -		State#state.backtrace, -		[int:file(Mod) || Mod <- int:interpreted()], -		int:all_breaks()}, -    Binary = term_to_binary({debugger_settings, Settings}), -    case file:write_file(SFile, Binary) of -	ok -> -	    State#state{sfile=SFile, changed=false}; -	{error, _Reason} -> -	    State -    end. - - -%%==================================================================== -%% Other internal functions -%%==================================================================== - -registered_name(Pid) -> -    %% Yield in order to give Pid more time to register its name -    timer:sleep(200), - -    Node = node(Pid), -    if -	Node =:= node() -> -	    case erlang:process_info(Pid, registered_name) of -		{registered_name, Name} -> Name; -		_ -> undefined -	    end; -	true -> -	    case rpc:call(Node,erlang,process_info, -			  [Pid,registered_name]) of -		{registered_name, Name} -> Name; -		_ -> undefined -	    end -    end. - -trace_function(State) -> -    {dbg_ui_trace, start, [State#state.tracewin,State#state.backtrace]}. diff --git a/lib/debugger/src/dbg_ui_mon_win.erl b/lib/debugger/src/dbg_ui_mon_win.erl deleted file mode 100644 index 8655c7697a..0000000000 --- a/lib/debugger/src/dbg_ui_mon_win.erl +++ /dev/null @@ -1,573 +0,0 @@ -%% -%% %CopyrightBegin% -%%  -%% Copyright Ericsson AB 1997-2012. All Rights Reserved. -%%  -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%%  -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%%  -%% %CopyrightEnd% -%% --module(dbg_ui_mon_win). --compile([{nowarn_deprecated_function,{gs,checkbutton,2}}, -          {nowarn_deprecated_function,{gs,config,2}}, -          {nowarn_deprecated_function,{gs,destroy,1}}, -          {nowarn_deprecated_function,{gs,frame,2}}, -          {nowarn_deprecated_function,{gs,grid,2}}, -          {nowarn_deprecated_function,{gs,gridline,2}}, -          {nowarn_deprecated_function,{gs,label,2}}, -          {nowarn_deprecated_function,{gs,listbox,2}}, -          {nowarn_deprecated_function,{gs,menu,2}}, -          {nowarn_deprecated_function,{gs,menubar,2}}, -          {nowarn_deprecated_function,{gs,menuitem,2}}, -          {nowarn_deprecated_function,{gs,read,2}}, -          {nowarn_deprecated_function,{gs,window,2}}]). - -%% External exports --export([init/0]). --export([create_win/3, get_window/1, -	 show_option/3, -	 enable/2, is_enabled/1, select/2, -	 add_module/3, delete_module/2, -	 add_process/6, update_process/4, clear_processes/1, -	 add_break/3, update_break/2, delete_break/2, -	 clear_breaks/1, clear_breaks/2, -	 handle_event/2 -	]). - --define(default_rows,50). - --record(moduleInfo, {module, menubtn}). --record(procInfo, {pid, row}). --record(breakInfo, {point, status, break}). --record(winInfo, {window,       % gsobj() -		  grid,         % gsobj() -		  row,          % int() Last row in grid - -		  focus,        % int() Selected row in grid - -		  modules=[],   % [#moduleInfo{}] Known modules -		  processes=[], % [#procInfo{}] Known processes -		  breaks=[],    % [#breakInfo{}] Known breakpoints - -		  listbox,      % gsobj() Listinng known modules - -		  %% Auto attach buttons -		  fbutton,      % gsobj() -		  bbutton,      % gsobj() -		  ebutton,      % gsobj() -		  selected=[],  % ['First Call'|'On Break'|'On Exit'] - -		  slabel,       % showing Stack Trace option -		  blabel        % showing Back Trace Size -		 }). - -%%==================================================================== -%% External exports -%%==================================================================== - -init() -> -    dbg_ui_win:init(). - -%%-------------------------------------------------------------------- -%% create_win(GS, Title, Menus) -> #winInfo{} -%%   GS = gsobj() -%%   Title = string() -%%   Menus = [menu()]  See dbg_ui_win.erl -%%-------------------------------------------------------------------- - --define(PAD, 5). --define(Wf, 150). --define(Wg, 770). --define(W, 800). --define(H, 390). - -create_win(GS, Title, Menus) -> -    Win = gs:window(GS, [{title, Title}, -			 {width, ?W}, {height, ?H}, -			 {configure,true}, {destroy,true}, -			 {keypress,true}, {motion,true}]), - -    MenuBar = gs:menubar(Win, []), -    dbg_ui_win:create_menus(MenuBar, Menus), -    dbg_ui_winman:windows_menu(MenuBar), - -    Font = dbg_ui_win:font(normal), - -    Frame = gs:frame(Win, [{x, ?PAD}, {y, 30}, -			   {width, ?Wf}, {height, ?H}]), -    Hlb = 200, -    Listbox = gs:listbox(Frame, [{x, 0}, {y, 0}, -				 {width, ?Wf}, {height, Hlb}, -				 {data, listbox}, -				 {doubleclick, true}, -				 {items, []}]), -    gs:label(Frame, [{x, 0}, {y, Hlb}, {width, ?Wf}, {height, 20}, -		     {align, w}, -		     {label, {text, "Auto Attach:"}}, {font, Font}]), -    Fbtn = gs:checkbutton(Frame, [{x, 0}, {y, Hlb+20}, -				  {width, ?Wf}, {height, 20}, -				  {label, {text, 'First Call'}}, -				  {align, w}, {font, Font}, -				  {data, autoattach}]), -    Bbtn = gs:checkbutton(Frame, [{x, 0}, {y, Hlb+40}, -				  {width, ?Wf}, {height, 20}, -				  {label, {text, 'On Break'}}, -				  {align, w}, {font, Font}, -				  {data, autoattach}]), -    Ebtn = gs:checkbutton(Frame, [{x, 0}, {y, Hlb+60}, -				  {width, ?Wf}, {height, 20}, -				  {label, {text, 'On Exit'}}, -				  {align, w}, {font, Font}, -				  {data, autoattach}]), -    SLabel = gs:label(Frame, [{x, 0}, {y, Hlb+80}, -			      {width, ?Wf}, {height, 40}, -			      {font, Font}, {align, w}]), -    BLabel = gs:label(Frame, [{x, 0}, {y, Hlb+120}, -			      {width, ?Wf}, {height, 40}, -			      {font, Font}, {align, w}]), - -    Grid = gs:grid(Win, [{x, 2*?PAD+?Wf}, {y, 30}, -			 {width, ?W-(2*?PAD+?Wf)}, {height, ?H-30}, -			 {bg, grey}, {fg, black}, -			 {vscroll, right}, {hscroll, bottom}, -			 calc_columnwidths(?Wg), -			 {rows, {1,?default_rows}}]), -    gs:gridline(Grid, [{row, 1}, {bw, 5}, {fg, blue}, -		       {font, Font}, -		       {text, {1,"Pid"}}, {text, {2,"Initial Call"}}, -		       {text, {3,"Name"}}, {text, {4,"Status"}}, -		       {text, {5,"Information"}}]), - -    gs:config(Win, {map, true}), -    #winInfo{window=Win, grid=Grid, row=1, focus=0, -	     listbox=Listbox, -	     fbutton=Fbtn, bbutton=Bbtn, ebutton=Ebtn, -	     slabel=SLabel, blabel=BLabel}. - -%%-------------------------------------------------------------------- -%% get_window(WinInfo) -> Window -%%   WinInfo = #winInfo{} -%%   Window = gsobj() -%%-------------------------------------------------------------------- -get_window(WinInfo) -> -    WinInfo#winInfo.window. - -%%-------------------------------------------------------------------- -%% show_option(WinInfo, Option, Value) -> void() -%%   WinInfo = #winInfo{} -%%   Option = auto_attach | stack_trace | back_trace -%%   Value = [Flag]                          % Option==auto_attach -%%             Flag = init | break | exit -%%         | true | all | no_tail | false    % Option==stack_trace -%%         | int()                           % Option==back_trace -%%-------------------------------------------------------------------- -show_option(WinInfo, Option, Value) -> -    case Option of - -	auto_attach -> -	    lists:foreach(fun (Button) -> -				  gs:config(Button, {select, false}) -			  end, -			  option_buttons(WinInfo, [init, break, exit])), -	    lists:foreach(fun (Button) -> -				  gs:config(Button, {select, true}) -			  end, -			  option_buttons(WinInfo, Value)); - -	stack_trace -> -	    Text = case Value of -		       all ->     "Stack Trace:\n On (with tail)"; -		       true ->    "Stack Trace:\n On (with tail)"; -		       no_tail -> "Stack Trace:\n On (no tail)"; -		       false ->   "Stack Trace:\n Off" -		   end, -	    gs:config(WinInfo#winInfo.slabel, {label, {text, Text}}); - -	back_trace -> -	    Text = "Back Trace Size:\n " ++ integer_to_list(Value), -	    gs:config(WinInfo#winInfo.blabel, {label, {text, Text}}) -    end. - -option_buttons(WinInfo, [init|Flags]) -> -    [WinInfo#winInfo.fbutton|option_buttons(WinInfo, Flags)]; -option_buttons(WinInfo, [break|Flags]) -> -    [WinInfo#winInfo.bbutton|option_buttons(WinInfo, Flags)]; -option_buttons(WinInfo, [exit|Flags]) -> -    [WinInfo#winInfo.ebutton|option_buttons(WinInfo, Flags)]; -option_buttons(_WinInfo, []) -> -    []. - -%%-------------------------------------------------------------------- -%% enable([MenuItem], Bool) -%% is_enabled(MenuItem) -> Bool -%%   MenuItem = atom() -%%   Bool = boolean() -%%-------------------------------------------------------------------- -enable(MenuItems, Bool) -> -    lists:foreach(fun(MenuItem) -> -			  gs:config(MenuItem, {enable, Bool}) -		  end, -		  MenuItems). - -is_enabled(MenuItem) -> -    gs:read(MenuItem, enable). - -%%-------------------------------------------------------------------- -%% select(MenuItem, Bool) -%%   MenuItem = atom() -%%   Bool = boolean() -%%-------------------------------------------------------------------- -select(MenuItem, Bool) -> -    dbg_ui_win:select(MenuItem, Bool). - -%%-------------------------------------------------------------------- -%% add_module(WinInfo, Name, Mod) -> WinInfo -%%   WinInfo = #winInfo{} -%%   Name = atom() -%%   Mod = atom() -%%-------------------------------------------------------------------- -add_module(WinInfo, Menu, Mod) -> -    Modules = WinInfo#winInfo.modules, -    case lists:keymember(Mod, #moduleInfo.module, Modules) of -	false -> -	    %% Create a menu for the module -	    Font = dbg_ui_win:font(normal), -	    MenuBtn = gs:menuitem(Menu, [{label, {text,Mod}}, -					 {font, Font}, -					 {itemtype, cascade}]), -	    SubMenu = gs:menu(MenuBtn, []), -	    gs:menuitem(SubMenu, [{label, {text,"View"}}, -				  {font, Font}, -				  {data, {module,Mod,view}}]), -	    gs:menuitem(SubMenu, [{label, {text,"Delete"}}, -				  {font, Font}, -				  {data, {module,Mod,delete}}]), - -	    %% Add the module to the listbox -	    gs:config(WinInfo#winInfo.listbox, {add, Mod}), - -	    ModInfo = #moduleInfo{module=Mod, menubtn=MenuBtn}, -	    WinInfo#winInfo{modules=[ModInfo | Modules]}; -	true -> WinInfo -    end. -     -%%-------------------------------------------------------------------- -%% delete_module(WinInfo, Mod) -> WinInfo -%%   WinInfo = #winInfo{} -%%   Mod = atom() -%%-------------------------------------------------------------------- -delete_module(WinInfo, Mod) -> -    {value, ModInfo} = lists:keysearch(Mod, #moduleInfo.module, -				       WinInfo#winInfo.modules), -    gs:destroy(ModInfo#moduleInfo.menubtn), -    delete_module(WinInfo#winInfo.listbox, atom_to_list(Mod), 0), -    WinInfo#winInfo{modules=lists:keydelete(Mod, #moduleInfo.module, -					    WinInfo#winInfo.modules)}. - -delete_module(Listbox, ModS, Index) -> -    case gs:read(Listbox, {get, Index}) of -	ModS -> -	    gs:config(Listbox, {del, Index}); -	_OtherModS -> -	    delete_module(Listbox, ModS, Index+1) -    end. - -%%-------------------------------------------------------------------- -%% add_process(WinInfo, Pid, Name, Function, Status, Info) -> WinInfo -%%   WinInfo = #winInfo{} -%%   Pid = pid() -%%   Name = undefined | atom() -%%   Function = {Mod, Func, Args} -%%   Status = idle | running | break | exit -%%   Info = {} | term() -%%-------------------------------------------------------------------- -add_process(WinInfo, Pid, Name, {Mod,Func,Args}, Status, Info) -> -    Grid = WinInfo#winInfo.grid, -    Row = (WinInfo#winInfo.row)+1, -    GridLine = case gs:read(Grid, {obj_at_row, Row}) of -		   undefined -> -		       if Row>?default_rows -> -			       gs:config(Grid,[{rows,{1,Row}}]); -			  true -> ok -		       end, -		       gs:gridline(Grid,[{row,Row}, {bw,5}, {fg,black}, -					 {font,dbg_ui_win:font(normal)}, -					 {click, true}, -					 {doubleclick, true}]); -		   GSObj -> -		       GSObj -	       end, -    Name2 = case Name of undefined -> ""; _ -> Name end, -    FuncS = io_lib:format("~w:~w/~w", [Mod, Func, length(Args)]), -    Info2 = case Info of {} -> ""; _ -> Info end, -    Options = [{text, {1,Pid}}, {text, {2,FuncS}}, {text, {3,Name2}}, -	       {text, {4,Status}}, {text, {5,Info2}}, -	       {data, {gridline, Pid}}], -    gs:config(GridLine, Options), - -    ProcInfo = #procInfo{pid=Pid, row=Row}, -    WinInfo#winInfo{processes=[ProcInfo|WinInfo#winInfo.processes], -		    row=Row}. - -%%-------------------------------------------------------------------- -%% update_process(WinInfo, Pid, Status, Info) -%%   WinInfo = #winInfo{} -%%   Pid = pid() -%%   Status = idle | running | break | exit -%%   Info = {} | term() -%%-------------------------------------------------------------------- -update_process(WinInfo, Pid, Status, Info) -> -    {value, ProcInfo} = lists:keysearch(Pid, #procInfo.pid, -					WinInfo#winInfo.processes), - -    Grid = WinInfo#winInfo.grid, -    GridLine = gs:read(Grid, {obj_at_row, ProcInfo#procInfo.row}), -     -    Info2 = case Info of {} -> ""; _ -> Info end, -    gs:config(GridLine, [{text, {4,Status}}, {text, {5,Info2}}]). - -%%-------------------------------------------------------------------- -%% clear_processes(WinInfo) -> WinInfo -%%   WinInfo = #winInfo{} -%%-------------------------------------------------------------------- -clear_processes(WinInfo) -> -    Grid = WinInfo#winInfo.grid, -    Max = WinInfo#winInfo.row, -    clear_processes(Grid, 2, Max), -    gs:config(Grid,[{rows,{1,?default_rows}}]), -    WinInfo#winInfo{row=1, focus=0, processes=[]}. - -clear_processes(Grid, Row, Max) when Row=<Max -> -    GridLine = gs:read(Grid, {obj_at_row, Row}), -    case gs:read(GridLine,{text,4}) of -	"exit" ->  -	    Pid = list_to_pid(gs:read(GridLine,{text,1})), -	    dbg_ui_winman:clear_process(dbg_ui_trace:title(Pid)); -	_ ->  -	    ok -    end, -	     -    Options = [{fg, black}, -	       {{text,1}, ""}, {{text,2},""}, {{text,3},""}, -	       {{text,4}, ""}, {{text,5},""}, -	       {data, []}], -    gs:config(GridLine, Options), -    clear_processes(Grid, Row+1, Max); -clear_processes(_Grid, Row, Max) when Row>Max -> -    done. - -%%-------------------------------------------------------------------- -%% add_break(WinInfo, Name, {Point, Options}) -> WinInfo -%%   WinInfo = #winInfo{} -%%   Name = atom() -%%   Point = {Mod, Line} -%%   Options = [Status, Action, Mods, Cond] -%%     Status = active | inactive -%%     Action = enable | disable | delete -%%     Mods = null (not used) -%%     Cond = null | {Mod, Func} -%%-------------------------------------------------------------------- -add_break(WinInfo, Menu, {Point, Options}) -> -    Break = dbg_ui_win:add_break(Menu, Point), -    dbg_ui_win:update_break(Break, Options), -    BreakInfo = #breakInfo{point=Point, break=Break}, -    WinInfo#winInfo{breaks=[BreakInfo|WinInfo#winInfo.breaks]}. - -%%-------------------------------------------------------------------- -%% update_break(WinInfo, {Point, Options}) -%%   WinInfo = #winInfo{} -%%   Point = {Mod, Line} -%%   Options = [Status, Action, Mods, Cond] -%%     Status = active | inactive -%%     Action = enable | disable | delete -%%     Mods = null (not used) -%%     Cond = null | {Mod, Func} -%%-------------------------------------------------------------------- -update_break(WinInfo, {Point, Options}) -> -    {value, BreakInfo} = lists:keysearch(Point, #breakInfo.point, -					 WinInfo#winInfo.breaks), -    dbg_ui_win:update_break(BreakInfo#breakInfo.break, Options). - -%%-------------------------------------------------------------------- -%% delete_break(WinInfo, Point) -> WinInfo -%%   WinInfo = #winInfo{} -%%   Point = {Mod, Line} -%%-------------------------------------------------------------------- -delete_break(WinInfo, Point) -> -    {value, BreakInfo} = lists:keysearch(Point, #breakInfo.point, -					 WinInfo#winInfo.breaks), -    dbg_ui_win:delete_break(BreakInfo#breakInfo.break), -    WinInfo#winInfo{breaks=lists:keydelete(Point, #breakInfo.point, -					   WinInfo#winInfo.breaks)}. - -%%-------------------------------------------------------------------- -%% clear_breaks(WinInfo) -> WinInfo -%% clear_breaks(WinInfo, Mod) -> WinInfo -%%   WinInfo = #winInfo{} -%%-------------------------------------------------------------------- -clear_breaks(WinInfo) -> -    lists:foreach(fun(BreakInfo) -> -			  dbg_ui_win:delete_break(BreakInfo#breakInfo.break) -		  end, -		  WinInfo#winInfo.breaks), -    WinInfo#winInfo{breaks=[]}. -clear_breaks(WinInfo, Mod) -> -    Fun = -	fun(BreakInfo) -> -		case BreakInfo#breakInfo.point of -		    {Mod, _Line} -> -			dbg_ui_win:delete_break(BreakInfo#breakInfo.break), -			false; -		    _ -> true -		end -	end, -    Breaks = lists:filter(Fun, WinInfo#winInfo.breaks), -    WinInfo#winInfo{breaks=Breaks}. -     -%%-------------------------------------------------------------------- -%% handle_event(GSEvent, WinInfo) -> Command -%%   GSEvent = {gs, Id, Event, Data, Arg} -%%   WinInfo = #winInfo{} -%%   Command = ignore -%%           | stopped -%%           | {coords, {X,Y}} -%% -%%           | {shortcut, Key} -%%           | MenuItem | {Menu, [MenuItem]} -%%               MenuItem = Menu = atom() -%%           | {break, Point, What} -%%               What = delete | {status, Status} | {trigger, Trigger} -%%           | {module, Mod, What} -%%               What = view | delete -%% -%%           | {focus, Pid, WinInfo} -%%           | default -%%-------------------------------------------------------------------- -%% Window events -handle_event({gs, _Id, configure, _Data, [W, H |_]}, WinInfo) -> -    configure(WinInfo, {W, H}), -    ignore; -handle_event({gs, _Id, destroy, _Data, _Arg}, _WinInfo) -> -    stopped; -handle_event({gs, _Id, motion, _Data, [X,Y]}, WinInfo) -> -    {LastX, LastY} = dbg_ui_win:motion(X, Y), -    Win = WinInfo#winInfo.window, -    {coords, {gs:read(Win, x)+LastX-5, gs:read(Win, y)+LastY-5}}; - -%% Menus and keyboard shortcuts -handle_event({gs, _Id, keypress, _Data, [Key,_,_,1]}, _WinInfo) when -  Key/='Up', Key/='Down', Key/=p, Key/=n -> -    {shortcut, Key}; -handle_event({gs, _Id, click, {dbg_ui_winman, Win}, _Arg}, _WinInfo) -> -    dbg_ui_winman:raise(Win), -    ignore; -handle_event({gs, _Id, click, {menuitem, Name}, _Arg}, _WinInfo) -> -    Name; -handle_event({gs, _Id, click, {menu, Menu}, _Arg}, _WinInfo) -> -    Names = dbg_ui_win:selected(Menu), -    {Menu, Names}; -handle_event({gs, _Id, click, {break, Point, What}, _Arg}, _WinInfo) -> -    {break, Point, What}; -handle_event({gs, _Id, click, {module, Mod, What}, _Arg}, _WinInfo) -> -    {module, Mod, What}; - -%% Listbox -handle_event({gs, _Id, doubleclick, listbox, [_Index, ModS|_]}, _WI) -> -    {module, list_to_atom(ModS), view}; - -%% Auto attach buttons -handle_event({gs, _Id, click, autoattach, _Arg}, WinInfo) -> -    Names = lists:foldl(fun (Button, NamesAcc) -> -				case gs:read(Button, select) of -				    true -> -					{text, Name} = -					    gs:read(Button, label), -					[list_to_atom(Name)|NamesAcc]; -				    false -> -					NamesAcc -				end -			end, -			[], -			[WinInfo#winInfo.ebutton, -			 WinInfo#winInfo.bbutton, -			 WinInfo#winInfo.fbutton]), -    {'Auto Attach', Names}; - -%% Process grid -handle_event({gs, _Id, keypress, _Data, [Key|_]}, WinInfo) when -  Key =:= 'Up'; Key =:= 'Down' -> -    Dir = if Key =:= 'Up' -> up; Key =:= 'Down' -> down end, -    Row = move(WinInfo, Dir), -    if Row>1 -> -	    WinInfo2 = highlight(WinInfo, Row), -	    #procInfo{pid=Pid} = -		lists:keyfind(Row, #procInfo.row, WinInfo#winInfo.processes), -	    {focus, Pid, WinInfo2}; -       true -> -	    ignore -    end; -handle_event({gs, _Id, click, {gridline, Pid}, [_Col,Row|_]}, WinInfo) -> -    WinInfo2 = highlight(WinInfo, Row), -    {focus, Pid, WinInfo2}; -handle_event({gs, _Id, doubleclick, _Data, _Arg}, _WinInfo) -> -    default; - -handle_event(_GSEvent, _WinInfo) -> -    ignore. - -move(WinInfo, Dir) -> -    Row = WinInfo#winInfo.focus, -    Last = WinInfo#winInfo.row, -    if -	Dir =:= up, Row > 1 -> Row-1; -	Dir =:= down, Row < Last -> Row+1; -	true -> Row -    end. - -highlight(WinInfo, Row) -> -    Grid = WinInfo#winInfo.grid, -    case WinInfo#winInfo.focus of -	0 -> ignore; -	Focus -> -	    GridLine1 = gs:read(Grid, {obj_at_row, Focus}), -	    gs:config(GridLine1, {fg, black}) -    end, -    GridLine2 = gs:read(Grid, {obj_at_row, Row}), -    gs:config(GridLine2, {fg, white}), -    WinInfo#winInfo{focus=Row}. - -%%==================================================================== -%% Internal functions -%%==================================================================== - -configure(WinInfo, {W, H}) -> -    Grid = WinInfo#winInfo.grid, -    NewW = W - (2*?PAD+?Wf), -    Dx = NewW - gs:read(Grid, width), -    Dy = H-42 - gs:read(Grid, height), -    if -	(Dx+Dy) =/= 0 -> -	    gs:config(Grid, [{width, NewW}, {height, H-30}]), -	    Cols = calc_columnwidths(NewW), -	    gs:config(Grid, Cols); -	true -> -	    ok -    end. - -calc_columnwidths(Width) -> -    W = if -	    Width =< ?Wg -> ?Wg; -	    true -> Width -	end, -    First = [round(X) || X <- [0.13*W, 0.27*W, 0.18*W, 0.18*W]], -    Last = W - lists:sum(First) - 30, -    {columnwidths, First++[Last]}. diff --git a/lib/debugger/src/dbg_ui_settings.erl b/lib/debugger/src/dbg_ui_settings.erl deleted file mode 100644 index fcfd67966f..0000000000 --- a/lib/debugger/src/dbg_ui_settings.erl +++ /dev/null @@ -1,162 +0,0 @@ -%% -%% %CopyrightBegin% -%%  -%% Copyright Ericsson AB 2002-2011. All Rights Reserved. -%%  -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%%  -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%%  -%% %CopyrightEnd% -%% --module(dbg_ui_settings). - --include_lib("kernel/include/file.hrl"). - -%% External exports --export([start/4]). - -%% Internal exports --export([init/6]). - -%% OTP-6011 What's denoted gs="Graphics system id" is now in fact -%% the object id of the monitor window. --record(state, {gs,      % term() Graphics system id -		win,     % term() Settings dialog window data -		monitor, % pid()  Monitor pid -		action   % load | save -	       }). - -%%==================================================================== -%% External exports -%%==================================================================== - -%%-------------------------------------------------------------------- -%% start(GS, Pos, Action, SFile) -%%   GS  = Graphics system id -%%   Pos = {X,Y} -%%   Action = load | save -%%   SFile = default | string() -%%-------------------------------------------------------------------- -start(GS, Pos, Action, SFile) -> -    Title = case Action of -		load -> "Load Settings Dialog"; -		save -> "Save Settings Dialog" -	    end, -    case dbg_ui_winman:is_started(Title) of -	true -> ignore; -	false -> -	    spawn(?MODULE, init, [self(), GS, Pos, Title, Action, SFile]) -    end. - -%%==================================================================== -%% Internal exports -%%==================================================================== - -init(Monitor, GS, Pos, Title, Action, SFile) -> -    {SDir, SFileName} = -	if -	    %% If settings are saved for the first time, and to -	    %% the default directory HOME/erlang.tools/debugger, -	    %% make sure the directory exists, or create it if -	    %% desired and possible -	    SFile==default -> {default_settings_dir(GS), "NoName.state"}; -	    true -> {filename:dirname(SFile), filename:basename(SFile)} -	end, -		     -    Filter = filename:join(SDir, "*.state"), -    Extra = fun(_File) -> true end, -			 -    %% Create window -    Win = case Action of -	      load -> -		  dbg_ui_filedialog_win:create_win(GS, Title, Pos, normal, -						   Filter, Extra); -	      save -> -		  dbg_ui_filedialog_win:create_win(GS, Title, Pos, normal, -						   Filter, Extra, SFileName) -	  end, -    Window = dbg_ui_filedialog_win:get_window(Win), -    dbg_ui_winman:insert(Title, Window), - -    State = #state{gs=GS, win=Win, monitor=Monitor, action=Action}, -    loop(State). - - -%%==================================================================== -%% Main loop and message handling -%%==================================================================== - -loop(State) -> -    receive - -	%% From the GUI -	GuiEvent when is_tuple(GuiEvent), element(1, GuiEvent)==gs -> -	    Cmd = dbg_ui_filedialog_win:handle_event(GuiEvent, -						     State#state.win), -	    State2 = gui_cmd(Cmd, State), -	    loop(State2); - -	%% From the dbg_ui_winman process (Debugger window manager) -	{dbg_ui_winman, update_windows_menu, _Data} -> -	    loop(State); -	{dbg_ui_winman, destroy} -> -	    exit(normal) -    end. - -gui_cmd(ignore, State) -> -    State; -gui_cmd({stopped, _Dir}, _State) ->	 -    exit(normal); -gui_cmd({win, Win}, State) -> -    State#state{win=Win}; -gui_cmd({select, File}, State) -> -    State#state.monitor ! {dbg_ui_settings, File, State#state.action}, -    exit(normal). - - -%%==================================================================== -%% Internal functions -%%==================================================================== - -default_settings_dir(GS) -> -    {ok, [[Home]]} = init:get_argument(home), -    DefDir = filename:join([Home, ".erlang_tools", "debugger"]), - -    case filelib:is_dir(DefDir) of -	true -> DefDir; -	false -> -	    {ok, CWD} = file:get_cwd(), -	     -	    Msg = ["Default directory", DefDir, "does not exist.", -		   "Click OK to create it or", -		   "Cancel to use other directory."], -	    case tool_utils:confirm(GS, Msg) of -		ok -> -		    ToolsDir = filename:dirname(DefDir), -		    case filelib:is_dir(ToolsDir) of -			true -> -			    case file:make_dir(DefDir) of -				ok -> DefDir; -				_Error -> CWD -			    end; -			false -> -			    case file:make_dir(ToolsDir) of -				ok -> -				    case file:make_dir(DefDir) of -					ok -> DefDir; -					_Error -> CWD -				    end; -				_Error -> CWD -			    end -		    end; -		cancel -> CWD -	    end -    end. diff --git a/lib/debugger/src/dbg_ui_trace.erl b/lib/debugger/src/dbg_ui_trace.erl deleted file mode 100644 index 3e1fb2dcae..0000000000 --- a/lib/debugger/src/dbg_ui_trace.erl +++ /dev/null @@ -1,814 +0,0 @@ -%% -%% %CopyrightBegin% -%%  -%% Copyright Ericsson AB 1998-2013. All Rights Reserved. -%%  -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%%  -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%%  -%% %CopyrightEnd% -%% --module(dbg_ui_trace). - -%% External exports --export([start/1, start/3]). --export([title/1]). - --define(TRACEWIN, ['Button Area', 'Evaluator Area', 'Bindings Area']). --define(BACKTRACE, 100). - --record(state, {gs,            % term() Graphics system id -		win,           % term() Attach process window data -		coords,        % {X,Y} Mouse point position - -		pid,           % pid() Debugged process -		meta,          % pid() Meta process -		status,        % {Status,Mod,Line} | {exit,Where,Reason} -		               %   Status = init | idle | break -		               %      | wait_break | wait_running -		               %      | running -                               % Where={Mod,Line} | null - -		cm,            % atom() | undefined Current module -		cm_obsolete=false, % boolean() Curr mod needs reloading - -		stack,         % {Cur,Max} - -		trace,         % boolean() -		stack_trace,   % all | no_tail | false -		backtrace      % integer() #call frames to fetch -	       }). - -%%==================================================================== -%% External exports -%%==================================================================== - -%%-------------------------------------------------------------------- -%% start(Pid) -%% start(Pid, TraceWin, BackTrace) -%%   Pid = pid() -%%   TraceWin = [WinArea] -%%     WinArea = 'Button|Evaluator|Bindings|Trace Area' -%%   Backtrace = integer() -%%-------------------------------------------------------------------- -start(Pid) -> % Used by debugger:quick/3 (no monitor) -    start(Pid, ?TRACEWIN, ?BACKTRACE). -start(Pid, TraceWin, BackTrace) -> -    case {whereis(dbg_wx_mon), whereis(dbg_ui_mon)} of -	{undefined, undefined} -> -	    case which_gui() of -		gs -> -		    start2(Pid, TraceWin, BackTrace); -		wx -> -		    dbg_wx_trace:start(Pid, TraceWin, BackTrace) -	    end; -	{undefined, Monitor} when is_pid(Monitor) -> -	    start2(Pid, TraceWin, BackTrace); -	{Monitor, _} when is_pid(Monitor) -> -	    dbg_wx_trace:start(Pid, TraceWin, BackTrace) -    end. - -start2(Pid, TraceWin, BackTrace) -> -    %% Inform int about my existence and get the meta pid back -    case int:attached(Pid) of -	{ok, Meta} -> -	    init(Pid, Meta, TraceWin, BackTrace); -	error -> -	    ignore -    end. - -which_gui() -> -    try -	wx:new(), -	wx:destroy(), -	wx -    catch _:_ -> -	    gs -    end. - -%%-------------------------------------------------------------------- -%% title(Pid) -> string() -%% By exporting this function, dbg_ui_mon may check with dbg_ui_winman -%% if there already is an attach window for a given pid and thus avoid -%% spawning processes unnecessarily. -%%-------------------------------------------------------------------- -title(Pid) -> -    "Attach Process " ++ pid_to_list(Pid). - - -%%==================================================================== -%% Main loop and message handling -%%==================================================================== - -init(Pid, Meta, TraceWin, BackTrace) -> - -    %% Start necessary stuff -    GS = dbg_ui_trace_win:init(),               % Graphics system - -    %% Create attach process window -    Title = title(Pid), -    Win = dbg_ui_trace_win:create_win(GS, Title, TraceWin, menus()), -    Window = dbg_ui_trace_win:get_window(Win), -    dbg_ui_winman:insert(Title, Window), - -    %% Initial process state -    State1 = #state{gs=GS, win=Win, coords={0,0}, pid=Pid, meta=Meta, -		    status={idle,null,null}, -		    stack={1,1}}, - -    State2 = init_options(TraceWin, -			  int:stack_trace(),    % Stack Trace -			  BackTrace,            % Back trace size -			  State1), - -    State3 = init_contents(int:all_breaks(),    % Breakpoints -			   State2), - -    int:meta(Meta, trace, State3#state.trace), - -    gui_enable_updown(stack_trace, {1,1}), -    gui_enable_btrace(false, false), -    dbg_ui_trace_win:display(idle), - -    loop(State3). - -init_options(TraceWin, StackTrace, BackTrace, State) -> -    lists:foreach(fun(Area) -> dbg_ui_trace_win:select(Area, true) end, -		  TraceWin), - -    Trace = lists:member('Trace Area', TraceWin), - -    dbg_ui_trace_win:select(map(StackTrace), true), - -    %% Backtrace size is (currently) not shown in window - -    State#state{trace=Trace,stack_trace=StackTrace,backtrace=BackTrace}. - -init_contents(Breaks, State) -> -    Win = -	lists:foldl(fun(Break, Win) -> -			    dbg_ui_trace_win:add_break(Win, -						       'Break',Break) -		    end, -		    State#state.win, -		    Breaks), - -    State#state{win=Win}. - -loop(#state{meta=Meta} = State) -> -    receive - -	%% From the GUI main window -	GuiEvent when is_tuple(GuiEvent), element(1, GuiEvent)==gs -> -	    Cmd = -		dbg_ui_trace_win:handle_event(GuiEvent,State#state.win), -	    State2 = gui_cmd(Cmd, State), -	    loop(State2); - -	%% From the GUI help windows -	{gui, Cmd} -> -	    State2 = gui_cmd(Cmd, State), -	    loop(State2); - -	%% From the interpreter -	{int, Cmd} -> -	    State2 = int_cmd(Cmd, State), -	    loop(State2); - -	%% From the meta process -	{Meta, Cmd} -> -	    State2 = meta_cmd(Cmd, State), -	    loop(State2); -	{NewMeta, {exit_at, Where, Reason, Cur}} -> -	    State2 = meta_cmd({exit_at, Where, Reason, Cur}, -			      State#state{meta=NewMeta}), -	    loop(State2); - -	%% From the dbg_ui_edit process -	{dbg_ui_edit, 'Backtrace:', BackTrace}  -> -	    loop(State#state{backtrace=BackTrace}); -	{dbg_ui_edit, Var, Val} -> -	    Cmd = atom_to_list(Var)++"="++io_lib:format("~p", [Val]), -	    State2 = gui_cmd({user_command, lists:flatten(Cmd)}, State), -	    loop(State2); - -	%% From the dbg_ui_winman process (Debugger window manager) -	{dbg_ui_winman, update_windows_menu, Data} -> -	    dbg_ui_winman:update_windows_menu(Data), -	    loop(State); -	{dbg_ui_winman, destroy} -> -	    exit(stop) -    end. - -%%--Commands from the GUI--------------------------------------------- - -gui_cmd(ignore, State) -> -    State; -gui_cmd({win, Win}, State) -> -    State#state{win=Win}; -gui_cmd(stopped, _State) -> -    exit(stop); -gui_cmd({coords, Coords}, State) -> -    State#state{coords=Coords}; - -gui_cmd({shortcut, Key}, State) -> -    case shortcut(Key) of -	{always, Cmd} -> gui_cmd(Cmd, State); -	{if_enabled, Cmd} -> -	    case dbg_ui_trace_win:is_enabled(Cmd) of -		true -> gui_cmd(Cmd, State); -		false -> State -	    end; -	false -> State -    end; - -%% File menu -gui_cmd('Close', State) -> -    gui_cmd(stopped, State); - -%% Edit menu -gui_cmd('Go To Line...', State) -> -    %% Will result in message handled below: {gui, {gotoline, Line}} -    dbg_ui_trace_win:helpwin(gotoline, State#state.win, -			      State#state.gs, State#state.coords), -    State; -gui_cmd({gotoline, Line}, State) -> -    Win = dbg_ui_trace_win:select_line(State#state.win, Line), -    State#state{win=Win}; -gui_cmd('Search...', State) -> -    dbg_ui_trace_win:helpwin(search, State#state.win, -			     State#state.gs, State#state.coords), -    State; - -%% Process menu -gui_cmd('Step', State) -> -    int:meta(State#state.meta, step), -    State; -gui_cmd('Next', State) -> -    int:meta(State#state.meta, next), -    State; -gui_cmd('Continue', State) -> -    int:meta(State#state.meta, continue), -    {Status, Mod, Line} = State#state.status, -    if -	Status==wait_break -> -	    Win = dbg_ui_trace_win:unmark_line(State#state.win), -	    gui_enable_functions(wait_running), -	    State#state{win=Win, status={wait_running,Mod,Line}}; -	true -> -	    dbg_ui_trace_win:enable(['Stop'], true), -	    dbg_ui_trace_win:enable(['Continue'], false), -	    State -    end; -gui_cmd('Finish', State) -> -    int:meta(State#state.meta, finish), -    State; -gui_cmd('Skip', State) -> -    int:meta(State#state.meta, skip), -    State; -gui_cmd('Time Out', State) -> -    int:meta(State#state.meta, timeout), -    State; -gui_cmd('Stop', State) -> -    int:meta(State#state.meta, stop), -    {Status, Mod, Line} = State#state.status, -    if -	Status==wait_running -> -	    Win = dbg_ui_trace_win:mark_line(State#state.win, Line, -					     break), -	    gui_enable_functions(wait_break), -	    gui_enable_updown(State#state.stack_trace, -			      State#state.stack), -	    gui_enable_btrace(State#state.trace, -			      State#state.stack_trace), -	    dbg_ui_trace_win:display({wait, Mod, Line}), -	    State#state{win=Win, status={wait_break,Mod,Line}}; -	true -> -	    dbg_ui_trace_win:enable(['Stop'], false), -	    dbg_ui_trace_win:enable(['Continue'], true), -	    State -    end; -gui_cmd('Where', State) -> -    {_Cur, Max} = State#state.stack, -    Stack = {Max, Max}, -    {_Status, Mod, Line} = State#state.status, -    Win = gui_show_module(State#state.win, Mod, Line, -			  State#state.cm, State#state.pid, break), -    gui_update_bindings(State#state.meta), -    gui_enable_updown(State#state.stack_trace, Stack), -    dbg_ui_trace_win:display(State#state.status), -    State#state{win=Win, cm=Mod, stack=Stack}; - -gui_cmd('Kill', State) -> -    exit(State#state.pid, kill), -    State; -gui_cmd('Messages', State) -> -    case int:meta(State#state.meta, messages) of -	[] -> -	    dbg_ui_trace_win:eval_output("< No Messages!\n", bold); -	Messages -> -	    dbg_ui_trace_win:eval_output("< --- Current Messages ---\n", -					 bold), -	    lists:foldl( -	      fun(Msg, N) -> -		      Str1 = io_lib:format(" ~w:", [N]), -		      dbg_ui_trace_win:eval_output(Str1, bold), -		      Str2 = io_lib:format(" ~ts~n",[io_lib:print(Msg)]), -		      dbg_ui_trace_win:eval_output(Str2, normal), -		      N+1 -	      end, -	      1, -	      Messages) -    end, -    State; -gui_cmd('Back Trace', State) -> -    dbg_ui_trace_win:trace_output("\nBACK TRACE\n----------\n"), -    lists:foreach( -      fun({Le, {Mod,Func,Args}}) -> -	      Str = io_lib:format("~p > ~p:~p~p~n", -				  [Le, Mod, Func, Args]), -	      dbg_ui_trace_win:trace_output(Str); -	 ({Le, {Fun,Args}}) -> -	      Str = io_lib:format("~p > ~p~p~n", [Le, Fun, Args]), -	      dbg_ui_trace_win:trace_output(Str); -	 (_) -> ignore -      end, -      int:meta(State#state.meta, backtrace, State#state.backtrace)), -    dbg_ui_trace_win:trace_output("\n"), -    State; -gui_cmd('Up', State) -> -    {Cur, Max} = State#state.stack, -    case int:meta(State#state.meta, stack_frame, {up, Cur}) of -	{New, {undefined,-1}, _Bs} -> % call from non-interpreted code -	    Stack = {New, Max}, -	    Win = dbg_ui_trace_win:show_no_code(State#state.win), -	    dbg_ui_trace_win:update_bindings([]), -	    gui_enable_updown(State#state.stack_trace, Stack), -	    dbg_ui_trace_win:display({New,null,null}), -	    State#state{win=Win, cm=null, stack=Stack}; - -	{New, {Mod,Line}, Bs} -> -	    Stack = {New, Max}, -	    Win = gui_show_module(State#state.win, Mod, Line, -				  State#state.cm, State#state.pid, -				  where), -	    dbg_ui_trace_win:update_bindings(Bs), -	    gui_enable_updown(State#state.stack_trace, Stack), -	    dbg_ui_trace_win:display({New,Mod,Line}), -	    State#state{win=Win, cm=Mod, stack=Stack}; -	top -> -	    dbg_ui_trace_win:enable(['Up'], false), -	    State -    end; -gui_cmd('Down', State) -> -    {Cur, Max} = State#state.stack, -    case int:meta(State#state.meta, stack_frame, {down, Cur}) of -	{New, {undefined,-1}, _Bs} -> % call from non-interpreted code -	    Stack = {New, Max}, -	    Win = dbg_ui_trace_win:show_no_code(State#state.win), -	    dbg_ui_trace_win:update_bindings([]), -	    gui_enable_updown(State#state.stack_trace, Stack), -	    dbg_ui_trace_win:display({New,null,null}), -	    State#state{win=Win, cm=null, stack=Stack}; - -	{New, {Mod,Line}, Bs} -> -	    Stack = {New, Max}, -	    Win = gui_show_module(State#state.win, Mod, Line, -				  State#state.cm, State#state.pid, -				  where), -	    dbg_ui_trace_win:update_bindings(Bs), -	    gui_enable_updown(State#state.stack_trace, Stack), -	    dbg_ui_trace_win:display({New,Mod,Line}), -	    State#state{win=Win, cm=Mod, stack=Stack}; - -	bottom -> -	    gui_cmd('Where', State) -    end; - -%% Break menu -gui_cmd('Line Break...', State) -> -    add_break(State#state.gs, State#state.coords, line, -	      State#state.cm, -	      dbg_ui_trace_win:selected_line(State#state.win)), -    State; -gui_cmd('Conditional Break...', State) -> -    add_break(State#state.gs, State#state.coords, conditional, -	      State#state.cm, -	      dbg_ui_trace_win:selected_line(State#state.win)), -    State; -gui_cmd('Function Break...', State) -> -    add_break(State#state.gs, State#state.coords, function, -	      State#state.cm, undefined), -    State; -gui_cmd('Enable All', State) -> -    Breaks = int:all_breaks(), -    ThisMod = State#state.cm, -    lists:foreach(fun ({{Mod, Line}, _Options}) when Mod==ThisMod -> -			  int:enable_break(Mod, Line); -		      (_Break) -> -			  ignore -		  end, -		  Breaks), -    State; -gui_cmd('Disable All', State) -> -    Breaks = int:all_breaks(), -    ThisMod = State#state.cm, -    lists:foreach(fun ({{Mod, Line}, _Options}) when Mod==ThisMod -> -			  int:disable_break(Mod, Line); -		      (_Break) -> -			  ignore -		  end, -		  Breaks), -    State; -gui_cmd('Delete All', State) -> -    int:no_break(State#state.cm), -    State; -gui_cmd({break, {Mod, Line}, What}, State) -> -    case What of -	add -> int:break(Mod, Line); -	delete -> int:delete_break(Mod, Line); -	{status, inactive} -> int:disable_break(Mod, Line); -	{status, active} -> int:enable_break(Mod, Line); -	{trigger, Action} -> int:action_at_break(Mod, Line, Action) -    end, -    State; - -%% Options menu -gui_cmd({'Trace Window', TraceWin}, State) -> -    Trace = lists:member('Trace Area', TraceWin), -    int:meta(State#state.meta, trace, Trace), -    Win = dbg_ui_trace_win:configure(State#state.win, TraceWin), -    {Status,_,_} = State#state.status, -    if -	Status==break; Status==wait_break -> -	    gui_enable_btrace(Trace, State#state.stack_trace); -	true -> ignore -    end, -    State#state{win=Win, trace=Trace}; -gui_cmd({'Stack Trace', [Name]}, State) -> -    int:meta(State#state.meta, stack_trace, map(Name)), -    {Status,_,_} = State#state.status, -    if -	Status==break; Status==wait_break -> -	    gui_enable_btrace(State#state.trace, map(Name)); -	true -> ignore -    end, -    State; -gui_cmd('Back Trace Size...', State) -> -    dbg_ui_edit:start(State#state.gs, State#state.coords, "Backtrace", -		      'Backtrace:', {integer, State#state.backtrace}), -    State; - -%% Help menu -gui_cmd('Debugger', State) -> -    Window = dbg_ui_trace_win:get_window(State#state.win), -    HelpFile = filename:join([code:lib_dir(debugger), -			      "doc", "html", "part_frame.html"]), -    tool_utils:open_help(Window, HelpFile), -    State; - -gui_cmd({user_command, Cmd}, State) -> -    {Status, _Mod, _Line} = State#state.status, -    if -	Status==break; -	Status==wait_break; -	Status==wait_running -> -	    Cm = State#state.cm, -	    Arg = case State#state.stack of -		      {Cur, Max} when Cur<Max -> {Cm, Cmd, Cur}; -		      _Stack -> {Cm, Cmd} -		  end, - -	    %% Reply will be received as {Meta, {eval_rsp, Res}} -	    int:meta(State#state.meta, eval, Arg); -	true -> -	    Str = "Commands not allowed", -	    dbg_ui_trace_win:eval_output([$<,Str,10], normal) -    end, -    State; - -gui_cmd({edit, {Var, Val}}, State) -> -    dbg_ui_edit:start(State#state.gs, State#state.coords, -		      "Edit variable", Var, {term, Val}), -    State. - -add_break(GS, Coords, Type, undefined, _Line) -> -    dbg_ui_break:start(GS, Coords, Type); -add_break(GS, Coords, Type, Mod, undefined) -> -    dbg_ui_break:start(GS, Coords, Type, Mod); -add_break(GS, Coords, Type, Mod, Line) -> -    dbg_ui_break:start(GS, Coords, Type, Mod, Line). - -%%--Commands from the interpreter------------------------------------- - -int_cmd({interpret, Mod}, State) -> -    if -	Mod==State#state.cm -> -	    State#state{cm_obsolete=true}; -	true -> -	    State -    end; -int_cmd({no_interpret, Mod}, State) -> -    if -	Mod==State#state.cm -> -	    State#state{cm_obsolete=true}; -	true -> -	    Win = dbg_ui_trace_win:remove_code(State#state.win, Mod), -	    State#state{win=Win} -    end; - -int_cmd({new_break, Break}, State) -> -    Win = dbg_ui_trace_win:add_break(State#state.win, 'Break', Break), -    State#state{win=Win}; -int_cmd({delete_break, Point}, State) -> -    Win = dbg_ui_trace_win:delete_break(State#state.win, Point), -    State#state{win=Win}; -int_cmd({break_options, Break}, State) -> -    Win = dbg_ui_trace_win:update_break(State#state.win, Break), -    State#state{win=Win}; -int_cmd(no_break, State) -> -    Win = dbg_ui_trace_win:clear_breaks(State#state.win), -    State#state{win=Win}; -int_cmd({no_break, Mod}, State) -> -    Win = dbg_ui_trace_win:clear_breaks(State#state.win, Mod), -    State#state{win=Win}. - -%%--Commands from the meta process------------------------------------ - -%% Message received when first attached to a living process -%% '_Trace' is a boolean indicating if the process is traced or not -- -%% ignore this as we already have ordered tracing or not depending on if -%% the Trace Area is shown or not. -meta_cmd({attached, Mod, Line, _Trace}, State) -> -    Win = if -	      Mod/=undefined -> -		  gui_enable_functions(init), -		  gui_show_module(State#state.win, Mod, Line, -				  State#state.cm, State#state.pid, -				  break); -	      true -> State#state.win -	  end, -    State#state{win=Win, status={init,Mod,Line}, cm=Mod}; - -%% Message received when returning to interpreted code -meta_cmd({re_entry, dbg_ieval, eval_fun}, State) -> -    State; -meta_cmd({re_entry, Mod, _Func}, State) -> -    Obs = State#state.cm_obsolete, -    case State#state.cm of -	Mod when Obs==true -> -	    Win = gui_load_module(State#state.win, Mod,State#state.pid), -	    State#state{win=Win, cm_obsolete=false}; -	Mod -> State; -	Cm -> -	    Win = gui_show_module(State#state.win, Mod, 0, -				  Cm, State#state.pid, break), -	    State#state{win=Win, cm=Mod} -    end; - -%% Message received when attached to a terminated process -meta_cmd({exit_at, null, Reason, Cur}, State) -> -    Stack = {Cur, Cur}, -    gui_enable_functions(exit), -    gui_enable_updown(false, Stack), -    dbg_ui_trace_win:display({exit, null, Reason}), -    State#state{status={exit,null,Reason}, stack=Stack}; -meta_cmd({exit_at, {Mod,Line}, Reason, Cur}, State) -> -    Stack = {Cur+1, Cur+1}, -    Win = gui_show_module(State#state.win, Mod, Line, -			  State#state.cm, State#state.pid, break), -    gui_enable_functions(exit), -    gui_enable_updown(State#state.stack_trace, Stack), -    gui_enable_btrace(State#state.trace, State#state.stack_trace), -    gui_update_bindings(State#state.meta), -    dbg_ui_trace_win:display({exit, {Mod,Line}, Reason}), -    State#state{win=Win, cm=Mod,status={exit,{Mod,Line},Reason}, -		stack=Stack}; - -meta_cmd({break_at, Mod, Line, Cur}, State) -> -    Stack = {Cur,Cur}, -    Win = gui_show_module(State#state.win, Mod, Line, -			  State#state.cm, State#state.pid, break), -    gui_enable_functions(break), -    gui_enable_updown(State#state.stack_trace, Stack), -    gui_enable_btrace(State#state.trace, State#state.stack_trace), -    gui_update_bindings(State#state.meta), -    dbg_ui_trace_win:display({break, Mod, Line}), -    State#state{win=Win, cm=Mod, status={break,Mod,Line}, stack=Stack}; -meta_cmd({func_at, Mod, Line, Cur}, State) -> -    Stack = {Cur,Cur}, -    Win = gui_show_module(State#state.win, Mod, Line, -			  State#state.cm, State#state.pid, where), -    gui_enable_functions(idle), -    dbg_ui_trace_win:display(idle), -    State#state{win=Win, cm=Mod, status={idle,Mod,Line}, stack=Stack}; -meta_cmd({wait_at, Mod, Line, Cur}, #state{status={Status,_,_}}=State) -  when Status/=init, Status/=break -> -    Stack = {Cur,Cur}, -    gui_enable_functions(wait_running), -    dbg_ui_trace_win:display({wait,Mod,Line}), -    State#state{status={wait_running,Mod,Line}, stack=Stack}; -meta_cmd({wait_at, Mod, Line, Cur}, State) -> -    Stack = {Cur,Cur}, -    Win = gui_show_module(State#state.win, Mod, Line, -			  State#state.cm, State#state.pid, break), -    gui_enable_functions(wait_break), -    gui_enable_updown(State#state.stack_trace, Stack), -    gui_enable_btrace(State#state.trace, State#state.stack_trace), -    gui_update_bindings(State#state.meta), -    dbg_ui_trace_win:display({wait, Mod, Line}), -    State#state{win=Win, cm=Mod, status={wait_break,Mod,Line}, -		stack=Stack}; -meta_cmd({wait_after_at, Mod, Line, Sp}, State) -> -    meta_cmd({wait_at, Mod, Line, Sp}, State); -meta_cmd(running, State) -> -    Win = dbg_ui_trace_win:unmark_line(State#state.win), -    gui_enable_functions(running), -    dbg_ui_trace_win:update_bindings([]), -    dbg_ui_trace_win:display({running, State#state.cm}), -    State#state{win=Win, status={running,null,null}}; - -meta_cmd(idle, State) -> -    Win = dbg_ui_trace_win:show_no_code(State#state.win), -    gui_enable_functions(idle), -    dbg_ui_trace_win:update_bindings([]), -    dbg_ui_trace_win:display(idle), -    State#state{win=Win, status={idle,null,null}, cm=undefined}; - -%% Message about changed trace option can be ignored, the change must -%% have been ordered by this process. (In theory, the change could have -%% been ordered by another attached process. The Debugger, though, -%% allows max one attached process per debugged process). -meta_cmd({trace, _Bool}, State) -> -    State; - -meta_cmd({stack_trace, Flag}, State) -> -    dbg_ui_trace_win:select(map(Flag), true), -    gui_enable_updown(Flag, State#state.stack), -    {Status,_,_} = State#state.status, -    if -	Status==break; Status==wait_break -> -	    gui_enable_btrace(State#state.trace, Flag); -	true -> ignore -    end, -    State#state{stack_trace=Flag}; - -meta_cmd({trace_output, Str}, State) -> -    dbg_ui_trace_win:trace_output(Str), -    State; - -%% Reply on a user command -meta_cmd({eval_rsp, Res}, State) -> -    Str = io_lib:print(Res), -    dbg_ui_trace_win:eval_output([$<,Str,10], normal), -    State. - - -%%==================================================================== -%% GUI auxiliary functions -%%==================================================================== - -menus() -> -    [{'File', [{'Close', no}]}, -     {'Edit', [{'Go To Line...', no}, -	       {'Search...', no}]}, -     {'Process', [{'Step', 0}, -		  {'Next', 0}, -		  {'Continue', 0}, -		  {'Finish', 0}, -		  {'Skip', no}, -		  {'Time Out', no}, -		  {'Stop', no}, -		  separator, -		  {'Kill', no}, -		  separator, -		  {'Messages', 0}, -		  {'Back Trace', no}, -		  separator, -		  {'Where', 0}, -		  {'Up', no}, -		  {'Down', no}]}, -     {'Break', [{'Line Break...', 5}, -		{'Conditional Break...', no}, -		{'Function Break...', no}, -		separator, -		{'Enable All', no}, -		{'Disable All', no}, -		{'Delete All', 0}, -		separator]}, -     {'Options', [{'Trace Window', no, cascade, -		   [{'Button Area', no, check}, -		    {'Evaluator Area', no, check}, -		    {'Bindings Area', no, check}, -		    {'Trace Area', no, check}]}, -		  {'Stack Trace', no, cascade, -		   [{'Stack On, Tail', no, radio}, -		    {'Stack On, No Tail', no, radio}, -		    {'Stack Off', no, radio}]}, -		  {'Back Trace Size...', no}]}, -     {'Help', [{'Debugger', no}]}]. - -%% enable(Status) -> [MenuItem] -%%   Status = init  % when first message from Meta has arrived -%%          | idle | break | exit | wait_break | wait_running | running -enable(init) -> []; -enable(idle) -> ['Stop','Kill']; -enable(break) -> ['Step','Next','Continue','Finish','Skip', -		  'Kill','Messages']; -enable(exit) -> []; -enable(wait_break) -> ['Continue','Time Out','Kill']; -enable(wait_running) -> ['Stop','Kill']; -enable(running) -> ['Stop','Kill']. - -all_buttons() -> -    ['Step','Next','Continue','Finish','Skip','Time Out','Stop', -     'Kill','Messages','Back Trace','Where','Up','Down']. - -shortcut(s) -> {if_enabled, 'Step'}; -shortcut(n) -> {if_enabled, 'Next'}; -shortcut(c) -> {if_enabled, 'Continue'}; -shortcut(f) -> {if_enabled, 'Finish'}; -shortcut(m) -> {if_enabled, 'Messages'}; -shortcut(w) -> {if_enabled, 'Where'}; - -shortcut(b) -> {always, 'Line Break...'}; -shortcut(d) -> {always, 'Delete All'}; - -shortcut(_) -> false. - -map('Stack On, Tail')    -> all;               % Stack trace -map('Stack On, No Tail') -> no_tail; -map('Stack Off')         -> false; -map(all)                 -> 'Stack On, Tail'; -map(true)                -> 'Stack On, Tail'; -map(no_tail)             -> 'Stack On, No Tail'; -map(false)               -> 'Stack Off'. - - -%% gui_show_module(Win, Mod, Line, Cm, Pid, How) -> Win -%% gui_show_module(Win, {Mod,Line}, _Reason, Cm, Pid, How) -> Win -%%   How = where | break -%% Show contents of a module in code area -gui_show_module(Win, {Mod,Line}, _Reason, Cm, Pid, How) -> -    gui_show_module(Win, Mod, Line, Cm, Pid, How); -gui_show_module(Win, Mod, Line, Mod, _Pid, How) -> -    dbg_ui_trace_win:mark_line(Win, Line, How); -gui_show_module(Win, Mod, Line, _Cm, Pid, How) -> -    Win2 = case dbg_ui_trace_win:is_shown(Win, Mod) of -	       {true, Win3} -> Win3; -	       false -> gui_load_module(Win, Mod, Pid) -	   end, -    dbg_ui_trace_win:mark_line(Win2, Line, How). - -gui_load_module(Win, Mod, Pid) -> -    dbg_ui_trace_win:display({text, "Loading module..."}), -    Contents = int:contents(Mod, Pid), -    Win2 = dbg_ui_trace_win:show_code(Win, Mod, Contents), -    dbg_ui_trace_win:display({text, ""}), -    Win2. - -gui_update_bindings(Meta) -> -    Bs = int:meta(Meta, bindings, nostack), -    dbg_ui_trace_win:update_bindings(Bs). - -gui_enable_functions(Status) -> -    Enable = enable(Status), -    Disable = all_buttons() -- Enable, -    dbg_ui_trace_win:enable(Disable, false), -    dbg_ui_trace_win:enable(Enable, true). - -gui_enable_updown(Flag, Stack) -> -    {Enable, Disable} = -	if -	    Flag==false -> {[], ['Up', 'Down']}; -	    true -> -		case Stack of -		    {1,1} -> {[], ['Up', 'Down']}; -		    {2,2} -> {[], ['Up', 'Down']}; -		    {Max,Max} -> {['Up'], ['Down']}; -		    {2,_Max} -> {['Down'], ['Up']}; -		    {_Cur,_Max} -> {['Up', 'Down'], []} -		end -	end, -    dbg_ui_trace_win:enable(Enable, true), -    dbg_ui_trace_win:enable(Disable, false), -    if -	Enable==[] -> dbg_ui_trace_win:enable(['Where'], false); -	true -> dbg_ui_trace_win:enable(['Where'], true) -    end. - -gui_enable_btrace(Trace, StackTrace) -> -    Bool = if -	       Trace==false -> false; -	       StackTrace==false -> false; -	       true -> true -	   end, -    dbg_ui_trace_win:enable(['Back Trace'], Bool). diff --git a/lib/debugger/src/dbg_ui_trace_win.erl b/lib/debugger/src/dbg_ui_trace_win.erl deleted file mode 100644 index beb3fbd71e..0000000000 --- a/lib/debugger/src/dbg_ui_trace_win.erl +++ /dev/null @@ -1,1595 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1997-2012. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% -%% --module(dbg_ui_trace_win). --compile([{nowarn_deprecated_function,{gs,button,2}}, -          {nowarn_deprecated_function,{gs,button,3}}, -          {nowarn_deprecated_function,{gs,checkbutton,2}}, -          {nowarn_deprecated_function,{gs,config,2}}, -          {nowarn_deprecated_function,{gs,create,4}}, -          {nowarn_deprecated_function,{gs,destroy,1}}, -          {nowarn_deprecated_function,{gs,editor,2}}, -          {nowarn_deprecated_function,{gs,editor,3}}, -          {nowarn_deprecated_function,{gs,entry,2}}, -          {nowarn_deprecated_function,{gs,entry,3}}, -          {nowarn_deprecated_function,{gs,frame,3}}, -          {nowarn_deprecated_function,{gs,grid,3}}, -          {nowarn_deprecated_function,{gs,gridline,2}}, -          {nowarn_deprecated_function,{gs,label,2}}, -          {nowarn_deprecated_function,{gs,label,3}}, -          {nowarn_deprecated_function,{gs,menubar,2}}, -          {nowarn_deprecated_function,{gs,read,2}}, -          {nowarn_deprecated_function,{gs,window,2}}, -          {nowarn_deprecated_function,{gs,window,3}}]). - -%% External exports --export([init/0]). --export([create_win/4, get_window/1, -	 configure/2, -	 enable/2, is_enabled/1, select/2, -	 add_break/3, update_break/2, delete_break/2, -	 clear_breaks/1, clear_breaks/2, -	 display/1,                                   % Help messages -	 is_shown/2,                                  % Code area -	 show_code/3, show_no_code/1, remove_code/2,       -	 mark_line/3, unmark_line/1, -	 select_line/2, selected_line/1, -	 eval_output/2,                               % Evaluator area -	 update_bindings/1,                           % Bindings area -	 trace_output/1,                              % Trace area -	 handle_event/2 -	]). --export([helpwin/4,                                   % Help windows -	 helpwin/5]). - --record(breakInfo, {point, status, break}). --record(winInfo, {window,          % gsobj() -		  size,            % {W, H} -		  flags,           % {F,F,F,F} F = open|close - -		  marked_line=0,   % integer() Current line -		  selected_line=0, % integer() Selected line - -		  breaks=[],       % [#breakInfo{}] Known breakpoints - -		  editor,          % {Mod, Editor}  Visible code editor -		  editors=[]       % [{Mod,Editor}] Code editors -		 }). - - -%%==================================================================== -%% External exports -%%==================================================================== - -%%-------------------------------------------------------------------- -%% init() -> GS -%%   GS = term() -%%-------------------------------------------------------------------- -init() -> -    dbg_ui_win:init(). - -%%-------------------------------------------------------------------- -%% create_win(GS, Title, TraceWin, Menus) -> #winInfo{} -%%  GS = gsobj() -%%  Title = string() -%%  TraceWin = [WinArea] -%%    WinArea = 'Button|Evaluator|Bindings|Trace Area' -%%  Menus = [menu()]  See dbg_ui_win.erl -%%-------------------------------------------------------------------- -create_win(GS, Title, TraceWin, Menus) -> -    Bu = flip(lists:member('Button Area', TraceWin)), -    Ev = flip(lists:member('Evaluator Area', TraceWin)), -    Bi = flip(lists:member('Bindings Area', TraceWin)), -    Tr = flip(lists:member('Trace Area', TraceWin)), -     -    Win = gs:window(trace_window, GS, [{title, Title}, -				       {width, 550}, -				       {configure,true}, {destroy,true}, -				       {keypress,true}, {motion,true}]), - -    MenuBar = gs:menubar(Win, []), -    dbg_ui_win:create_menus(MenuBar, Menus), -    dbg_ui_winman:windows_menu(MenuBar), - -    FrameOpts = [{anchor,nw}, {relief,raised}, {bw,2}, {keypress,true}], -    Editor = code_area(2, 25, FrameOpts, Win), -    button_area(Bu, 2, 235, FrameOpts, Win), -    eval_area({Ev,Bi}, 2, 265, FrameOpts, Win), -    bind_area({Ev,Bi}, 300, 265, FrameOpts, Win), -    trace_area(Tr, 2, 475, FrameOpts, Win), - -    Flags = {Bu, Ev, Bi, Tr}, -    resizebar(rb1(Flags), 'RB1',   2, 225, 710,  10, Win), -    resizebar(rb2(Flags), 'RB2',   2, 465, 710,  10, Win), -    resizebar(rb3(Flags), 'RB3', 290, 265,  10, 200, Win), -    config_v(), -    config_h(), -     -    gs:config(Win,{height, -		   25 + -		   gs:read('CodeArea', height) + -		   gs:read('RB1', height) + -		   gs:read('ButtonArea', height) + -		   erlang:max(gs:read('EvalArea', height), -		       gs:read('BindArea', height)) + -		   gs:read('RB2', height) + -		   gs:read('TraceArea', height)}), -     -    gs:config(Win, {map, true}), -    #winInfo{window=Win, size={gs:read(Win,width), gs:read(Win,height)}, -	     flags=Flags, -	     editor={'$top', Editor}, editors=[{'$top', Editor}]}. - -flip(true) -> open; -flip(false) -> close. -     -%%-------------------------------------------------------------------- -%% get_window(WinInfo) -> Window -%%   WinInfo = #winInfo{} -%%   Window = gsobj() -%%-------------------------------------------------------------------- -get_window(WinInfo) -> -    WinInfo#winInfo.window. - -%%-------------------------------------------------------------------- -%% configure(WinInfo, TraceWin) -> WinInfo -%%   WinInfo = #winInfo{} -%%  TraceWin = [WinArea] -%%    WinArea = 'Button|Evaluator|Bindings|Trace Area' -%% Window areas should be opened or closed. -%%-------------------------------------------------------------------- -configure(WinInfo, TraceWin) -> -    {Bu1, Ev1, Bi1, Tr1} = OldFlags = WinInfo#winInfo.flags, -    Bu2 = flip(lists:member('Button Area', TraceWin)), -    Ev2 = flip(lists:member('Evaluator Area', TraceWin)), -    Bi2 = flip(lists:member('Bindings Area', TraceWin)), -    Tr2 = flip(lists:member('Trace Area', TraceWin)), -    NewFlags = {Bu2, Ev2, Bi2, Tr2}, - -    Win = WinInfo#winInfo.window, -    W = gs:read(Win, width), -    H = gs:read(Win, height), - -    H2 = if -	     Bu1 =:= close, Bu2 =:= open -> -		 resize_button_area(open, width, W-4), -		 gs:config('ButtonArea', {height, 30}), -		 H+30; -	     Bu1 =:= open, Bu2 =:= close -> -		 gs:config('ButtonArea', [{width, 0}, {height, 0}]), -		 H-30; -	     true -> H -	 end, -    H3 = if -	     Ev1 =:= close, Ev2 =:= open, Bi1 =:= open -> -		 Wnew1 = round((W-10-4)/2), % W = window/2 - rb - pads -		 Hbi1 = gs:read('BindArea', height), % H = bind area h -		 resize_eval_area(open, width, Wnew1), -		 resize_eval_area(open, height, Hbi1), -		 gs:config('RB3', {width, 10}), -		 gs:config('RB3', {height, Hbi1}), -		 resize_bind_area(open, width, -				  Wnew1-gs:read('BindArea', width)), -		 H2; -	     Ev1 =:= close, Ev2 =:= open, Bi1 =:= close -> -		 resize_eval_area(open, width, W-4), -		 resize_eval_area(open, height, 200), -		 H2+200; -	     Ev1 =:= open, Ev2 =:= close, Bi1 =:= open -> -		 gs:config('EvalArea', [{width,0}, {height,0}]), -		 gs:config('RB3', [{width, 0}, {height, 0}]), -		 Wnew2 = W-4, -		 resize_bind_area(open, width, -				  Wnew2-gs:read('BindArea', width)), -		 H2; -	     Ev1 =:= open, Ev2 =:= close, Bi1 =:= close -> -		 Hs1 = gs:read('EvalArea', height), -		 gs:config('EvalArea', [{width, 0}, {height, 0}]), -		 H2-Hs1; -	     true -> H2 -	 end, -    H4 = if -	     Bi1 =:= close, Bi2 =:= open, Ev2 =:= open -> -		 Wnew3 = round((W-10-4)/2), % W = window/2 - rb - pads -		 Hs2 = gs:read('EvalArea', height), % H = eval area h -		 resize_bind_area(open, width, Wnew3), -		 resize_bind_area(open, height, Hs2), -		 gs:config('RB3', [{width,10},{height,Hs2}]), -		 resize_eval_area(open, width, -				  Wnew3-gs:read('EvalArea', width)), -		 H3; -	     Bi1 =:= close, Bi2 =:= open, Ev2 =:= close -> -		 resize_bind_area(open, width, W-4), -		 resize_bind_area(open, height, 200), -		 H3+200; -	     Bi1 =:= open, Bi2 =:= close, Ev2 =:= open -> -		 gs:config('BindArea', [{width, 0}, {height, 0}]), -		 gs:config('RB3', [{width, 0}, {height, 0}]), -		 Wnew4 = W-4, -		 resize_eval_area(open, width, -				  Wnew4-gs:read('EvalArea', width)), -		 H3; -	     Bi1 =:= open, Bi2 =:= close, Ev2 =:= close -> -		 Hbi2 = gs:read('BindArea', height), -		 gs:config('BindArea', [{width, 0}, {height, 0}]), -		 H3-Hbi2; -	     true -> H3 -	 end, -    H5 = if -	     Tr1 =:= close, Tr2 =:= open -> -		 resize_trace_area(open, width, W-4), -		 resize_trace_area(open, height, 200), -		 H4+200; -	     Tr1 =:= open, Tr2 =:= close -> -		 Hf = gs:read('TraceArea', height), -		 gs:config('TraceArea', [{width, 0}, {height, 0}]), -		 H4-Hf; -	     true -> H4 -	 end, -    gs:config(Win, {height, H5}), - -    RB1old = rb1(OldFlags), RB1new = rb1(NewFlags), -    if -	RB1old =:= close, RB1new =:= open -> -	    gs:config('RB1', [{width, W-4}, {height, 10}]), -	    gs:config(Win, {height, gs:read(Win, height)+10}); -	RB1old =:= open, RB1new =:= close -> -	    gs:config('RB1', [{width, 0}, {height, 0}, lower]), -	    gs:config(Win, {height, gs:read(Win, height)-10}); -	true -> ignore -    end, - -    RB2old = rb2(OldFlags), RB2new = rb2(NewFlags), -    if -	RB2old =:= close, RB2new =:= open -> -	    gs:config('RB2', [{width, W-4}, {height, 10}]), -	    gs:config(Win, {height,gs:read(Win, height)+10}); -	RB2old =:= open, RB2new =:= close -> -	    gs:config('RB2', [{width, 0}, {height, 0}, lower]), -	    gs:config(Win, {height, gs:read(Win, height)-10}); -	true -> ignore -    end, -    config_v(), -    config_h(), - -    flush_configure(), -     -    WinInfo#winInfo{size={gs:read(Win, width), gs:read(Win, height)}, -		    flags=NewFlags}. - -flush_configure() -> -    receive -	{gs, _Id, configure, _Data, _Arg} -> -	    flush_configure() -    after 100 -> -	    true -    end. - -%%-------------------------------------------------------------------- -%% enable([MenuItem], Bool) -%% is_enabled(MenuItem) -> Bool -%%   MenuItem = atom() -%%   Bool = boolean() -%%-------------------------------------------------------------------- -enable(MenuItems, Bool) -> -    lists:foreach(fun(MenuItem) -> -			  gs:config(MenuItem, {enable, Bool}), -			  case is_button(MenuItem) of -			      {true, Button} -> -				  gs:config(Button, {enable, Bool}); -			      false -> ignore -			  end -		  end, -		  MenuItems). - -is_enabled(MenuItem) -> -    gs:read(MenuItem, enable). - -%%-------------------------------------------------------------------- -%% select(MenuItem, Bool) -%%   MenuItem = atom() -%%   Bool = boolean() -%%-------------------------------------------------------------------- -select(MenuItem, Bool) -> -    dbg_ui_win:select(MenuItem, Bool). - -%%-------------------------------------------------------------------- -%% add_break(WinInfo, Name, {Point, Options}) -> WinInfo -%%   WinInfo = #winInfo{} -%%   Name = atom() Menu name -%%   Point = {Mod, Line} -%%   Options = [Status, Action, Mods, Cond] -%%     Status = active | inactive -%%     Action = enable | disable | delete -%%     Mods = null (not used) -%%     Cond = null | {Mod, Func} -%%-------------------------------------------------------------------- -add_break(WinInfo, Menu, {{Mod,Line},[Status|_Options]}=Break) -> -    case lists:keyfind(Mod, 1, WinInfo#winInfo.editors) of -	{Mod, Editor} -> -	    add_break_to_code(Editor, Line, Status); -	false -> ignore -    end, -    add_break_to_menu(WinInfo, Menu, Break). - -add_break_to_code(Editor, Line, Status) -> -    Color = if Status =:= active -> red; Status =:= inactive -> blue end, -    config_editor(Editor, [{overwrite,{{Line,0},"-@-  "}}, -			   {fg,{{{Line,0},{Line,lineend}}, Color}}]). - -add_break_to_menu(WinInfo, Menu, {Point, [Status|_Options]=Options}) -> -    Break = dbg_ui_win:add_break(Menu, Point), -    dbg_ui_win:update_break(Break, Options), -    BreakInfo = #breakInfo{point=Point, status=Status, break=Break}, -    WinInfo#winInfo{breaks=[BreakInfo|WinInfo#winInfo.breaks]}. - -%%-------------------------------------------------------------------- -%% update_break(WinInfo, {Point, Options}) -> WinInfo -%%   WinInfo = #winInfo{} -%%   Point = {Mod, Line} -%%   Options = [Status, Action, Mods, Cond] -%%     Status = active | inactive -%%     Action = enable | disable | delete -%%     Mods = null (not used) -%%     Cond = null | {Mod, Func} -%%-------------------------------------------------------------------- -update_break(WinInfo, {{Mod,Line},[Status|_Options]}=Break) -> -    case lists:keyfind(Mod, 1, WinInfo#winInfo.editors) of -	{Mod, Editor} -> -	    add_break_to_code(Editor, Line, Status); -	false -> ignore -    end, -    update_break_in_menu(WinInfo, Break). - -update_break_in_menu(WinInfo, {Point, [Status|_Options]=Options}) -> -    {value, BreakInfo} = lists:keysearch(Point, #breakInfo.point, -					 WinInfo#winInfo.breaks), -    dbg_ui_win:update_break(BreakInfo#breakInfo.break, Options), -    BreakInfo2 = BreakInfo#breakInfo{status=Status}, -    WinInfo#winInfo{breaks=lists:keyreplace(Point, #breakInfo.point, -					    WinInfo#winInfo.breaks, -					    BreakInfo2)}. - -%%-------------------------------------------------------------------- -%% delete_break(WinInfo, Point) -> WinInfo -%%   WinInfo = #winInfo{} -%%   Point = {Mod, Line} -%%-------------------------------------------------------------------- -delete_break(WinInfo, {Mod,Line}=Point) -> -    case lists:keyfind(Mod, 1, WinInfo#winInfo.editors) of -	{Mod, Editor} -> delete_break_from_code(Editor, Line); -	false -> ignore -    end, -    delete_break_from_menu(WinInfo, Point). - -delete_break_from_code(Editor, Line) -> -    Prefix = string:substr(integer_to_list(Line)++":   ", 1, 5), -    config_editor(Editor, [{overwrite,{{Line,0},Prefix}}, -			   {fg,{{{Line,0},{Line,lineend}}, black}}]). - -delete_break_from_menu(WinInfo, Point) -> -    {value, BreakInfo} = lists:keysearch(Point, #breakInfo.point, -					 WinInfo#winInfo.breaks), -    dbg_ui_win:delete_break(BreakInfo#breakInfo.break), -    WinInfo#winInfo{breaks=lists:keydelete(Point, #breakInfo.point, -					   WinInfo#winInfo.breaks)}. - -%%-------------------------------------------------------------------- -%% clear_breaks(WinInfo) -> WinInfo -%% clear_breaks(WinInfo, Mod) -> WinInfo -%%   WinInfo = #winInfo{} -%%-------------------------------------------------------------------- -clear_breaks(WinInfo) -> -    clear_breaks(WinInfo, all). -clear_breaks(WinInfo, Mod) -> -    Remove = if -		 Mod =:= all -> WinInfo#winInfo.breaks; -		 true -> -		     lists:filter(fun(#breakInfo{point={Mod2,_L}}) -> -					  if -					      Mod2 =:= Mod -> true; -					      true -> false -					  end -				  end, -				  WinInfo#winInfo.breaks) -	     end, -    lists:foreach(fun(#breakInfo{point=Point}) -> -			  delete_break(WinInfo, Point) -		  end, -		  Remove), -    Remain = WinInfo#winInfo.breaks -- Remove, -    WinInfo#winInfo{breaks=Remain}. - -%%-------------------------------------------------------------------- -%% display(Arg) -%%   Arg = idle | {Status,Mod,Line} | {running,Mod} -%%       | {exit,Where,Reason} | {text,Text} -%%     Status = break | wait | Level -%%       Level = int() -%%     Mod = atom() -%%     Line = integer() -%%     Where = {Mod,Line} | null -%%     Reason = term() -%%     Text = string() -%%-------------------------------------------------------------------- -display(Arg) -> -    Str = case Arg of -	      idle -> "State: uninterpreted"; -	      {exit, {Mod,Line}, Reason} -> -		  gs:config(trace_window, raise), -		  io_lib:format("State: EXITED [~w.erl/~w], Reason:~w", -				[Mod, Line, Reason]); -	      {exit, null, Reason} -> -		  gs:config(trace_window, raise), -		  io_lib:format("State: EXITED [uninterpreted], " -				"Reason:~w", [Reason]); -	      {Level, null, _Line} when is_integer(Level) -> -		  io_lib:format("*** Call level #~w " -				"(in non-interpreted code)", -				[Level]); -	      {Level, Mod, Line} when is_integer(Level) -> -		  io_lib:format("*** Call level #~w [~w.erl/~w]", -				[Level, Mod, Line]); -	      {Status, Mod, Line} -> -		  What = case Status of -			     wait -> 'receive'; -			     _ -> Status -			 end, -		  io_lib:format("State: ~w [~w.erl/~w]", -				[What, Mod, Line]); -	      {running, Mod} -> -		  io_lib:format("State: running [~w.erl]", [Mod]); -	      {text, Text}  -> Text -	  end, -    gs:config(info_window, {label,{text,lists:flatten(Str)}}). - -%%-------------------------------------------------------------------- -%% is_shown(WinInfo, Mod) -> {true, WinInfo} | false -%% show_code(WinInfo, Mod, Contents) -> WinInfo -%% show_no_code(WinInfo) -> WinInfo -%% remove_code(WinInfo, Mod) -> WinInfo -%%   WinInfo = #winInfo{} -%%   Mod = atom() -%%   Contents = string() -%% Note: remove_code/2 should not be used for currently shown module. -%%-------------------------------------------------------------------- -is_shown(WinInfo, Mod) -> -    case lists:keyfind(Mod, 1, WinInfo#winInfo.editors) of -	{Mod, Editor} -> -	    gs:config(Editor, raise), -	    {true, WinInfo#winInfo{editor={Mod, Editor}}}; -	false -> false -    end. - -show_code(WinInfo, Mod, Contents) -> -    Editors = WinInfo#winInfo.editors, -    {Flag, Editor} = case lists:keyfind(Mod, 1, Editors) of -			 {Mod, Ed} -> {existing, Ed}; -			 false -> {new, code_editor()} -		     end, -    %% Insert code and update breakpoints, if any -    config_editor(Editor, [raise, clear]), -    show_code(Editor, Contents), -    lists:foreach(fun(BreakInfo) -> -			  case BreakInfo#breakInfo.point of -			      {Mod2, Line} when Mod2 =:= Mod -> -				  Status = BreakInfo#breakInfo.status, -				  add_break_to_code(Editor, Line,Status); -			      _Point -> ignore -			  end -		  end, -		  WinInfo#winInfo.breaks), -    case Flag of -	existing -> -	    WinInfo#winInfo{editor={Mod, Editor}}; -	new -> -	    WinInfo#winInfo{editor={Mod, Editor}, -			    editors=[{Mod, Editor} | Editors]} -    end. -	 -show_code(Editor, Text) when length(Text) > 1500 -> -    %% Add some text at a time so that other processes may get scheduled -    Str = string:sub_string(Text, 1, 1500), -    config_editor(Editor, {insert,{'end', Str}}), -    show_code(Editor, string:sub_string(Text, 1501)); -show_code(Editor, Text) -> -    config_editor(Editor, {insert,{'end',Text}}). - -show_no_code(WinInfo) -> -    {'$top', Editor} = lists:keyfind('$top', 1, WinInfo#winInfo.editors), -    gs:config(Editor, raise), -    WinInfo#winInfo{editor={'$top', Editor}}. - -remove_code(WinInfo, Mod) -> -    Editors = WinInfo#winInfo.editors, -    case lists:keyfind(Mod, 1, Editors) of -	{Mod, Editor} -> -	    gs:destroy(Editor), -	    WinInfo#winInfo{editors=lists:keydelete(Mod, 1, Editors)}; -	false -> -	    WinInfo -    end. - -%%-------------------------------------------------------------------- -%% mark_line(WinInfo, Line, How) -> WinInfo -%%   WinInfo = #winInfo{} -%%   Line = integer() -%%   How = break | where -%% Mark the code line where the process is executing. -%%-------------------------------------------------------------------- -mark_line(WinInfo, Line, How) -> -    {_Mod, Editor} = WinInfo#winInfo.editor, -    mark_line2(Editor, WinInfo#winInfo.marked_line, false), -    mark_line2(Editor, Line, How), -    if -	Line =/= 0 -> config_editor(Editor, {vscrollpos, Line-5}); -	true -> ignore -    end, -    WinInfo#winInfo{marked_line=Line}. - -unmark_line(WinInfo) -> -    mark_line(WinInfo, 0, false). - -mark_line2(Editor, Line, How) -> -    Prefix = case How of -		 break -> "-->"; -		 where -> ">>>"; -		 false -> "   " -	     end, -    Font = if -	       How =:= false -> dbg_ui_win:font(normal); -	       true -> dbg_ui_win:font(bold) -	   end, -    config_editor(Editor, [{overwrite, {{Line,5}, Prefix}}, -			   {font_style, -			    {{{Line,0},{Line,lineend}}, Font}}]). - -%%-------------------------------------------------------------------- -%% select_line(WinInfo, Line) -> WinInfo -%% selected_line(WinInfo) -> undefined | Line -%%   WinInfo = #winInfo{} -%%   Line = integer() -%% Select/unselect a line (unselect if Line=0). -%%-------------------------------------------------------------------- -select_line(WinInfo, Line) -> -    {_Mod, Editor} = WinInfo#winInfo.editor, - -    %% Since 'Line' may be specified by the user in the 'Go To Line' -    %% help window, it must be checked that it is correct -    Size = gs:read(Editor, size), -    if -	Line =:= 0 -> -	    select_line(Editor, WinInfo#winInfo.selected_line, false), -	    WinInfo#winInfo{selected_line=0}; -	Line < Size -> -	    select_line(Editor, Line, true), -	    config_editor(Editor, {vscrollpos, Line-5}), -	    WinInfo#winInfo{selected_line=Line}; -	true -> -	    WinInfo -    end. - -select_line(Editor, Line, true) -> -    config_editor(Editor, {selection, {{Line,0}, {Line,lineend}}}); -select_line(Editor, _Line, false) -> -    config_editor(Editor, {selection, {{1,0}, {1,0}}}). - -selected_line(WinInfo) -> -    case WinInfo#winInfo.selected_line of -	0 -> undefined; -	Line -> Line -    end. - -%%-------------------------------------------------------------------- -%% eval_output(Str, Face) -%%   Str = string() -%%   Face = normal | bold -%%-------------------------------------------------------------------- -eval_output(Text, Face) -> -    Y1 = gs:read('EvalEditor', size), -    config_editor('EvalEditor', {insert,{'end',Text}}), -    Y2 = gs:read('EvalEditor', size), - -    Font = dbg_ui_win:font(Face), -    config_editor('EvalEditor', -		  [{font_style, {{{Y1,0},{Y2,lineend}}, Font}}, -		   {vscrollpos,Y2}]). - -%%-------------------------------------------------------------------- -%% update_bindings(Bs) -%%   Bs = [{Var,Val}] -%%-------------------------------------------------------------------- -update_bindings(Bs) -> -    gs:config('BindGrid', {rows, {1,length(Bs)+1}}), -    Font = dbg_ui_win:font(normal), -    Last = -	lists:foldl(fun({Var, Val}, Row) -> -			    Opts = [{text, {1,atom_to_list(Var)}}, -				    {text, {2,io_lib:format("~P", -							    [Val, 4])}}, -				    {doubleclick, true}, -				    {data, {binding,{Var,Val}}}], -			    case gs:read('BindGrid',{obj_at_row,Row}) of -				undefined -> -				    gs:gridline('BindGrid', -						[{row, Row}, -						 {height, 14}, -						 {font, Font} | Opts]); -				GridLine -> -				    gs:config(GridLine, Opts) -			    end, -			    Row+1 -		    end, -		    2, -		    Bs), -    delete_gridlines(Last). - -delete_gridlines(Row) ->  -    case gs:read('BindGrid', {obj_at_row, Row}) of -	undefined -> true; -	GridLine -> -	    gs:destroy(GridLine), -	    delete_gridlines(Row+1) -    end. - -%%-------------------------------------------------------------------- -%% trace_output(Str) -%%   Str = string() -%%-------------------------------------------------------------------- -trace_output(Str) -> -    Font = dbg_ui_win:font(normal), -    config_editor('TraceEditor', -		  [{insert, {'end',Str}}, -		   {fg, {{{1,0},'end'},black}}, -		   {font_style, {{{1,0},'end'},Font}}]), -    Max = gs:read('TraceEditor', size), -    config_editor('TraceEditor', {vscrollpos, Max}). -     -%%-------------------------------------------------------------------- -%% handle_event(GSEvent, WinInfo) -> Command -%%   GSEvent = {gs, Id, Event, Data, Arg} -%%   WinInfo = #winInfo{} -%%   Command = ignore -%%           | {win, WinInfo} -%%           | stopped -%%           | {coords, {X,Y}} -%% -%%           | {shortcut, Key} -%%           | MenuItem | {Menu, [MenuItem]} -%%               MenuItem = Menu = atom() -%%           | {break, Point, What} -%%               What = add | delete | {status,Status} |{trigger,Trigger} -%%           | {module, Mod, view} -%% -%%           | {user_command, Cmd} -%% -%%           | {edit, {Var, Val}} -%%-------------------------------------------------------------------- -%% Window events -handle_event({gs, _Id, configure, _Data, [W, H|_]}, WinInfo) -> -    case WinInfo#winInfo.size of -	{W, H} -> ignore; -	_Size -> -	    configure(WinInfo, W, H), -	    {win, WinInfo#winInfo{size={W, H}}} -    end; -handle_event({gs, _Id, destroy, _Data, _Arg}, _WinInfo) -> -    stopped; -handle_event({gs, _Id, motion, _Data, [X,Y]}, WinInfo) -> -    {LastX, LastY} = dbg_ui_win:motion(X, Y), -    Win = WinInfo#winInfo.window, -    {coords, {gs:read(Win, x)+LastX-5, gs:read(Win, y)+LastY-5}}; -handle_event({gs, RB, buttonpress, resizebar, _Arg}, WinInfo) -> -    resize(WinInfo, RB), % Resize window contents -    ignore; - -%% Menus, buttons and keyboard shortcuts -handle_event({gs, _Id, keypress, _Data, [Key,_,_,1]}, _WinInfo) -> -    {shortcut, Key}; -handle_event({gs, _Id, click, {dbg_ui_winman, Win}, _Arg}, _WinInfo) -> -    dbg_ui_winman:raise(Win), -    ignore; -handle_event({gs, _Id, click, {menuitem, Name}, _Arg}, _WinInfo) -> -    Name; -handle_event({gs, _Id, click, {menu, Menu}, _Arg}, _WinInfo) -> -    Names = dbg_ui_win:selected(Menu), -    {Menu, Names}; -handle_event({gs, _Id, click, {break, Point, What}, _Arg}, _WinInfo) -> -    {break, Point, What}; -handle_event({gs, _Id, click, {module, Mod, view}, _Arg}, _WinInfo) -> -    {module, Mod, view}; - -%% Code area -handle_event({gs, Editor, buttonpress, code_editor, _Arg}, WinInfo) -> -    {Row, _Col} = gs:read(Editor, insertpos), -    Again = receive -		{gs, Editor, buttonpress, code_editor, _} -> -		    gs:read(Editor, insertpos) -	    after 500 -> -		    false -	    end, -    case Again of -	{Row, _} -> -	    {Mod, _Editor} = WinInfo#winInfo.editor, -	    Point = {Mod, Row}, -	    case lists:keymember(Point, #breakInfo.point, -				 WinInfo#winInfo.breaks) of -		false -> {break, Point, add}; -		true  -> {break, Point, delete} -	    end; -	{Row2, _} -> -	    select_line(Editor, Row2, true), -	    {win, WinInfo#winInfo{selected_line=Row2}}; -	false -> -	    select_line(Editor, Row, true), -	    {win, WinInfo#winInfo{selected_line=Row}} -    end; - -%% Button area -handle_event({gs, _Id, click, {button, Name}, _Arg}, _WinInfo) -> -    Name; - -%% Evaluator area -handle_event({gs, 'EvalEntry', keypress, _Data, ['Return'|_]}, _WI) -> -    Command = case gs:read('EvalEntry', text) of -		  [10] -> -		      eval_output("\n", normal), -		      ignore; -		  Cmd -> -		      eval_output([$>, Cmd, 10], normal), -		      {user_command, Cmd} -	      end, -    gs:config('EvalEntry', [{text,""}, {focus,false}]), -    Command; - -%% Bindings area -handle_event({gs, _Id, click, {binding, {Var, Val}}, _Arg}, _WinInfo) -> -    Str = io_lib:format("< ~p = ~p~n", [Var, Val]), -    eval_output(Str, bold), -    ignore; -handle_event({gs, _Id, doubleclick, {binding, B}, _Arg}, _WinInfo) -> -    {edit, B}; - -handle_event(_GSEvent, _WinInfo) -> -    ignore. - - -%%==================================================================== -%% Internal functions -%%==================================================================== - -%%--Code Area--------------------------------------------------------- - -code_area(X, Y, FrameOpts, Win) -> -    gs:frame('CodeArea', Win, -	     [{x,X}, {y,Y}, {width,546}, {height,400} | FrameOpts]), -    gs:label(info_window, 'CodeArea', -	     [{label,{text,""}}, {font,dbg_ui_win:font(normal)}, -	      {x,5}, {y,10}, {width,406}, {height,15}, -	      {anchor,nw}, {align,w}]), -    code_editor('CodeEditor', 536, 365). - -code_editor() -> -    W = gs:read('CodeEditor', width), -    H = gs:read('CodeEditor', height), -    code_editor(null, W, H). - -code_editor(Name, W, H) -> -    Editor = if -		 Name =:= null -> gs:editor('CodeArea', []); -		 true -> gs:editor(Name, 'CodeArea', []) -	     end, -    gs:config(Editor, [{x,5}, {y,30}, {width,W}, {height,H}, -		       {keypress,false}, {buttonpress,true},  -		       {data,code_editor}]), -    config_editor(Editor, [{vscroll,right}, {hscroll,bottom}]), -    Font = dbg_ui_win:font(normal), -    config_editor(Editor, [{wrap,none}, {fg,{{{1,0},'end'},black}}, -			   {font, Font}, -			   {font_style, {{{1,0},'end'},Font}}]), -    Editor. - -resize_code_area(WinInfo, Key, Diff) -> -    gs:config('CodeArea', {Key,gs:read('CodeArea', Key)+Diff}), -    case Key of -	width -> -	    gs:config(info_window, {Key,gs:read(info_window,Key)+Diff}); -	height -> ignore -    end, - -    %% Resize all code editors -    Value = gs:read('CodeEditor', Key)+Diff, -    gs:config('CodeEditor', {Key,Value}), -    Editors = WinInfo#winInfo.editors, -    lists:foreach(fun({_Mod, Editor}) -> -			  gs:config(Editor, {Key,Value}) -		  end, -		  Editors). - -%%--Button Area------------------------------------------------------- - -buttons() -> -    [{'Step','StepButton'}, {'Next','NextButton'}, -     {'Continue','ContinueButton'}, {'Finish','FinishButton'}, -     {'Where','WhereButton'}, {'Up','UpButton'}, {'Down','DownButton'}]. - -is_button(Name) -> -    case lists:keyfind(Name, 1, buttons()) of -	{Name, Button} -> {true, Button}; -	false -> false -    end. - -button_area(Bu, X, Y, FrameOpts, Win) -> -    {W,H} = case Bu of -		open -> {546,30}; -		close -> {0,0} -	    end, -    gs:frame('ButtonArea', Win, -	     [{x,X}, {y,Y}, {width,W}, {height,H} | FrameOpts]), -    Font = dbg_ui_win:font(normal), -    lists:foldl(fun({Name, Button}, Xb) -> -			gs:button(Button, 'ButtonArea', -				  [{label, {text,Name}}, {font,Font}, -				   {x, Xb}, {y, 1}, -				   {width, 77}, {height, 24}, -				   {data, {button,Name}}]), -			Xb+78 -		end, -		1, -		buttons()). - -resize_button_area(close, width, _Diff) -> -    ignore; -resize_button_area(open, width, Diff) -> -    gs:config('ButtonArea', {width, gs:read('ButtonArea', width)+Diff}). - -%%--Evaluator Area---------------------------------------------------- - -eval_area({Ev,Bi}, X, Y, FrameOpts, Win) -> -    {W,H} = if -		Ev =:= open -> {289,200}; -		true -> {0,0} -	    end, -    Font = dbg_ui_win:font(normal), -    gs:frame('EvalArea', Win, -	     [{x,X}, {y,Y}, {width,W}, {height,H} | FrameOpts]), -    gs:label('EvalArea', -	     [{label,{text,"Evaluator:"}}, {font, Font}, -	      {x,5}, {y,35}, {width,80}, {height,25}, -	      {anchor,sw}, {align,center}]), -    gs:entry('EvalEntry', 'EvalArea', -	     [{font, Font}, -	      {x,80}, {y,35}, {width,185}, {height,25}, -	      {anchor,sw}, {keypress,true}]), -    gs:editor('EvalEditor', 'EvalArea', -	      [{x,5}, {y,35}, {width, 280}, {height, 160}, -	       {keypress,false}, -	       {vscroll,right}, {hscroll,bottom}, -	       {wrap,none}, {fg,{{{1,0},'end'},black}}, -	       {font, Font}, -	       {font_style,{{{1,0},'end'},Font}}]), -    gs:config('EvalEditor', {enable, false}), -    if -	Ev =:= open, Bi =:= close -> resize_eval_area(Ev, width, 257); -	true -> ignore -    end. - -resize_eval_area(close, _Key, _Diff) -> -    ignore; -resize_eval_area(open, Key, Diff) -> -    New = gs:read('EvalArea', Key)+Diff, -    gs:config('EvalArea', {Key,New}), -    case Key of -	width -> -	    gs:config('EvalEntry', {width,New-104}), -	    gs:config('EvalEditor', {width,New-9}); -	height -> -	    gs:config('EvalEditor', {height,New-40}) -    end. - -%%--Bindings Area----------------------------------------------------- - -bind_area({Ev,Bi}, X, Y, FrameOpts, Win) -> -    {W,H} = if -		Bi =:= open -> {249,200}; -		true -> {0,0} -	    end, -    gs:frame('BindArea', Win, -	     [{x,X}, {y,Y}, {width,W}, {height,H} | FrameOpts]), - -    Font = dbg_ui_win:font(bold), -    gs:grid('BindGrid', 'BindArea', -	    [{x,2}, {y,2}, {height,193}, {width,241}, -	     {fg,black}, {vscroll,right}, {hscroll,bottom}, -	     {font,Font}, -	     calc_columnwidths(241), {rows, {1,50}}]),  -    gs:gridline('BindGrid', -		[{row,1}, {height,14}, {fg,blue}, -		 {text,{1,"Name"}}, {text,{2,"Value"}}, {font,Font}]), -    gs:config('BindGrid', {rows,{1,1}}), -    if -	Bi =:= open, Ev =:= close -> resize_bind_area(Bi, width, 297); -	true -> ignore -    end. - -resize_bind_area(close, _Key, _Diff) -> -    ignore; -resize_bind_area(open, Key, Diff) -> -    New = gs:read('BindArea', Key)+Diff, -    gs:config('BindArea', {Key,New}), -    case Key of -	width -> -	    gs:config('BindGrid', {width,New-8}), -	    Cols = calc_columnwidths(New-8), -	    gs:config('BindGrid', Cols); -	height -> -	    gs:config('BindGrid', {height,New-7}) -    end. - -calc_columnwidths(Width) ->     -    if Width =< 291 ->  -	    {columnwidths,[90,198]}; -       true ->  -	    S = (Width)/(90+198), -	    {columnwidths,[round(90*S),round(198*S)]} -    end. - -%%--Trace Area-------------------------------------------------------- - -trace_area(Tr, X, Y, FrameOpts, Win) -> -    {W,H} = case Tr of -		open -> {546,200}; -		close -> {0,0} -	    end, -    gs:frame('TraceArea', Win, -	     [{x,X}, {y,Y}, {width,W}, {height,H} | FrameOpts]), -    Editor = gs:editor('TraceEditor', 'TraceArea', -		       [{x,5}, {y,5}, {width,536}, {height,190}, -			{keypress,false}]), -    Font = dbg_ui_win:font(normal), -    config_editor(Editor, -		  [{vscroll,right}, {hscroll,bottom}, -		   {wrap,none},{fg,{{{1,0},'end'},black}}, -		   {font, Font}, -		   {font_style,{{{1,0},'end'},Font}}]). - -resize_trace_area(close, _Key, _Diff) -> -    ignore; -resize_trace_area(open, Key, Diff) -> -    New = gs:read('TraceArea', Key)+Diff, -    gs:config('TraceArea', {Key,New}), -    gs:config('TraceEditor', {Key,New-10}). - -%%--Editors----------------------------------------------------------- - -config_editor(Editor, Opts) -> -    gs:config(Editor, {enable,true}), -    gs:config(Editor, Opts), -    gs:config(Editor, {enable,false}). - -%%--Resize Bars------------------------------------------------------- -%% The resize bars are used to resize the areas within the window. - -%%-------------------------------------------------------------------- -%% resizebar(Flag, Name, X, Y, W, H, Obj) -> resizebar() -%%   Flag = open | close -%%   Name = atom() -%%   X = Y = integer()  Coordinates relative to Obj -%%   W = H = integer()  Width and height -%%   Obj = gsobj() -%% Creates a 'resize bar', a frame object over which the cursor will -%% be of the 'resize' type. -%%-------------------------------------------------------------------- -resizebar(Flag, Name, X, Y, W, H, Obj) -> -    {W2,H2} = case Flag of -		  open  -> {W,H}; -		  close -> {0,0} -	      end, -    gs:create(frame, Name, Obj, [{x,X}, {y,Y}, {width,W2}, {height,H2}, -				 {bw,2}, -				 {cursor,resize}, -				 {buttonpress,true}, {buttonrelease,true}, -				 {data,resizebar}]). - -rb1({_Bu,Ev,Bi,Tr}) -> -    if -	Ev =:= close, Bi =:= close, Tr =:= close -> close; -	true -> open -    end. -     -rb2({_Bu,Ev,Bi,Tr}) -> -    if -	Tr =:= open -> -	    if -		Ev =:= close, Bi =:= close -> close; -		true -> open -	    end; -	true -> close -    end. -     -rb3({_Bu,Ev,Bi,_Tr}) -> -    if -	Ev =:= open, Bi =:= open -> open; -	true -> close -    end. - -%%--Configuration----------------------------------------------------- -%% Resize the window as well as its contents - -%%-------------------------------------------------------------------- -%% config_v() -%% Reconfigure the window vertically. -%%-------------------------------------------------------------------- -config_v() -> -    Y1 = 25+gs:read('CodeArea', height), -    gs:config('RB1', {y,Y1}), -     -    Y2 = Y1+gs:read('RB1', height), -    gs:config('ButtonArea', {y,Y2}), -     -    Y3 = Y2+gs:read('ButtonArea', height), -    gs:config('EvalArea', {y,Y3}), -    gs:config('RB3', {y,Y3}), -    gs:config('BindArea', {y,Y3}), -     -    Y4 = Y3 + erlang:max(gs:read('EvalArea', height), -		  gs:read('BindArea', height)), -    gs:config('RB2', {y,Y4}), -     -    Y5 = Y4 + gs:read('RB2', height), -    gs:config('TraceArea', {y,Y5}). - -%%-------------------------------------------------------------------- -%% config_h() -%% Reconfigure the window horizontally. -%%-------------------------------------------------------------------- -config_h() -> -    X1 = 2+gs:read('EvalArea', width), -    gs:config('RB3', {x,X1}), -     -    X2 = X1+gs:read('RB3', width), -    gs:config('BindArea', {x,X2}). - -%%-------------------------------------------------------------------- -%% configure(WinInfo, W, H) -%% The window has been resized, now its contents must be resized too. -%%-------------------------------------------------------------------- -configure(WinInfo, NewW, NewH) -> -    {Bu,Ev,Bi,Tr} = Flags = WinInfo#winInfo.flags, -     -    OldW = gs:read('CodeArea', width)+4, -    OldH = 25+gs:read('CodeArea', height)+ -	gs:read('RB1', height)+ -	gs:read('ButtonArea', height)+ -	erlang:max(gs:read('EvalArea', height), gs:read('BindArea', height))+ -	gs:read('RB2', height)+ -	gs:read('TraceArea', height), - -    %% Adjust width unless it is unchanged or less than minimum width -    if -	OldW =/= NewW -> -	    {Dcode,Deval,Dbind} = configure_widths(OldW,NewW,Flags), -	    resize_code_area(WinInfo, width, Dcode), -	    case rb1(Flags) of -		open -> -		    gs:config('RB1', {width,gs:read('RB1',width)+Dcode}); -		close -> ignore -	    end, -	    resize_button_area(Bu, width, Dcode), -	    resize_eval_area(Ev, width, Deval), -	    resize_bind_area(Bi, width, Dbind), -	    case rb2(Flags) of -		open -> -		    gs:config('RB2', {width,gs:read('RB2',width)+Dcode}); -		close -> ignore -	    end, -	    resize_trace_area(Tr, width, Dcode), -	    config_h(); -	true -> ignore -    end, -     -    %% Adjust height unless it is unchanged or less than minimum height -    if -	OldH =/= NewH -> -	    {Dcode2,Deval2,Dtrace} = configure_heights(OldH,NewH,Flags), -	    resize_code_area(WinInfo, height, Dcode2), -	    resize_eval_area(Ev, height, Deval2), -	    case rb3(Flags) of -		open -> -		    gs:config('RB3', -			      {height,gs:read('RB3',height)+Deval2}); -		close -> ignore -	    end, -	    resize_bind_area(Bi, height, Deval2), -	    resize_trace_area(Tr, height, Dtrace), -	    config_v(); -	true -> ignore -    end. - -%% Compute how much the width of each frame must be increased or -%% decreased in order to adjust to the new window width. -configure_widths(OldW, NewW, Flags) -> -    {_Bu,Ev,Bi,_Tr} = Flags, - -    %% Difference between old and new width, considering min window width -    Diff = abs(erlang:max(OldW,330)-erlang:max(NewW,330)), -     -    %% Check how much the frames can be resized in reality -    Limits = if -		 %% Window larger -		 NewW > OldW -> -		     if -			 Ev =:= open, Bi =:= open -> {0,Diff,Diff}; -			 Ev =:= open -> {0,Diff,0}; -			 Bi =:= open -> {0,0,Diff}; -			 true -> {Diff,0,0} -		     end; -		  -		 %% Window smaller; get difference between min size -		 %% and current size -		 OldW>NewW -> -		     if -			 Ev =:= open, Bi =:= open -> -			     {0, -			      gs:read('EvalArea',width)-204, -			      gs:read('BindArea',width)-112}; -			 Ev =:= open -> {0,Diff,0}; -			 Bi =:= open -> {0,0,Diff}; -			 true -> {Diff,0,0} -		     end -	     end, -     -    case Limits of - -	%% No Shell or Bind frame, larger window -	{T,0,0} when NewW > OldW -> {T,0,0}; -	 -	%% No Shell or Bind frame, smaller window -	{T,0,0} when OldW > NewW -> {-T,0,0}; - -	%% Window larger; divide Diff among the frames and return result -	{_,Sf,B} when NewW > OldW -> -	    {_,Sf2,B2} = divide([{0,0},{0,Sf},{0,B}],Diff), -	    {Sf2+B2,Sf2,B2}; - -	%% Window smaller; divide Diff among the frames and return -	%% the inverted result (the frames should shrink) -	{_,Sf,B} when OldW>NewW -> -	    {_,Sf2,B2} = divide([{0,0},{0,Sf},{0,B}],Diff), -	    {-(Sf2+B2),-Sf2,-B2} -    end. - -%% Compute how much the height of each frame must be increased or -%% decreased in order to adjust to the new window height. -configure_heights(OldH, NewH, Flags) -> -    {_Bu,Ev,Bi,Tr} = Flags, - -    %% Difference between old and new height, considering min win height -    MinH = min_height(Flags), -    Diff = abs(erlang:max(OldH,MinH)-erlang:max(NewH,MinH)), -     -    %% Check how much the frames can be resized in reality -    {T,Sf,Ff} = if -		  %% Window larger -		  NewH > OldH -> -		      {Diff, -		       if -			   Ev =:= close, Bi =:= close -> 0; -			   true -> Diff -		       end, -		       if -			   Tr =:= open -> Diff; -			   true -> 0 -		       end}; - -		  %% Window smaller; get difference between min size -		  %% and current size -		  OldH > NewH -> -		      {gs:read('CodeArea',height)-100, -		       if -			   Ev =:= close, Bi =:= close -> 0; -			   true -> -			       if -				   Ev =:= open -> -				       gs:read('EvalArea',height)-100; -				   Bi =:= open -> -				       gs:read('BindArea',height)-100 -			       end -		       end, -		       if -			   Tr =:= open -> gs:read('TraceArea',height)-100; -			   true -> 0 -		       end} -	      end, -     -    if -	%% Window larger; divide Diff among the frames and return result -	NewH>OldH -> divide([{0,T},{0,Sf},{0,Ff}],Diff); - -	%% Window smaller; divide Diff among the frames and return -	%% the inverted result (the frames should shrink) -	OldH>NewH -> -	    {T2,Sf2,Ff2} = divide([{0,T},{0,Sf},{0,Ff}],Diff), -	    {-T2,-Sf2,-Ff2} -    end. - -%% Compute minimum window height -min_height(Flags) -> -    {Bu,S,Bi,F} = Flags, -    H1 = 25 + 100 + 2, % Upper pad + Trace frame + lower pad -    H2 = H1 + bu(Bu) + s_bi(S,Bi) + f(F), -    H3 = case rb1(Flags) of -	     open -> H2+10; -	     close -> H2 -	 end, -    H4 = case rb2(Flags) of -	     open -> H3+10; -	     close -> H3 -	 end, -    H4. - -bu(close) -> 0; -bu(open)  -> 30. - -s_bi(close,close) -> 0; -s_bi(_,_) -> 100. - -f(close) -> 0; -f(open)  -> 100. - -%% Try to distribute Diff as evenly as possible between E1, E2 and E3. -divide([{T,T},{S,S},{F,F}], _Diff) -> -    {T,S,F}; -divide(L, Diff) -> -    [{T,Tmax},{S,Smax},{F,Fmax}] = L, - -    %% Count how many elements in L can still be filled -    Rem = remaining(L), -     -    %% Divide Diff by Rem -    D = Diff div Rem, - -    if -	%% All of Diff has been distributed -	D =:= 0 -> {T,S,F}; -	true -> -	    %% For each element, try to add as much as possible of D -	    {NewT,Dt} = divide2(D,T,Tmax), -	    {NewS,Ds} = divide2(D,S,Smax), -	    {NewF,Df} = divide2(D,F,Fmax), -     -	    %% Recur with a list of elements with new current values -	    %% and decreased Diff -	    divide([{NewT,Tmax},{NewS,Smax},{NewF,Fmax}], -		   (Diff rem Rem)+Dt+Ds+Df) -    end. - -%% Count the number of 'non-filled' elements in L, ie where Curr<Max. -remaining([]) -> 0; -remaining([{Max,Max}|T]) -> remaining(T); -remaining([_H|T]) -> 1 + remaining(T). - -divide2(_Diff, Max, Max) -> {Max,0}; -divide2(Diff, Curr, Max) -> -    New = Curr+Diff, -    if -	New>Max -> {Max,New-Max}; -	true -> {New,0} -    end. - -%%--Resizing using resize bars---------------------------------------- -%% Motions event will move the ResizeBar accordingly in Win, when -%% the mouse button is released, the window is reconfigured. - -resize(WinInfo, ResizeBar) ->		 -     -    %% Get window dimensions -    W = gs:read(WinInfo#winInfo.window, width), -    H = gs:read(WinInfo#winInfo.window, height), -     -    %% Call resize loop with min and max for the resize bars derived -    %% from the window dimensions -    resizeloop(WinInfo, ResizeBar, null, -	       rblimits('RB1',W,H), -	       rblimits('RB2',W,H), -	       rblimits('RB3',W,H)). - -resizeloop(WI, RB, Prev, {Min1,Max1}, {Min2,Max2}, {Min3,Max3}) -> -    receive -	{gs,_,motion,_,[_,Y]} when RB =:= 'RB1', Y > Min1, Y < Max1 -> -	    gs:config('RB1', {y,Y}), -	    resizeloop(WI, RB, Y, {Min1,Max1}, {Min2,Max2}, {Min3,Max3}); -	{gs,_,motion,_,_} when RB =:= 'RB1' -> -	    resizeloop(WI, RB, Prev, {Min1,Max1}, {Min2,Max2}, {Min3,Max3}); -	 -	{gs,_,motion,_,[_,Y]} when RB =:= 'RB2', Y > Min2, Y < Max2 -> -	    gs:config('RB2', {y,Y}), -	    resizeloop(WI, RB, Y, {Min1,Max1}, {Min2,Max2}, {Min3,Max3}); -	{gs,_,motion,_,_} when RB =:= 'RB2' -> -	    resizeloop(WI, RB, Prev, {Min1,Max1}, {Min2,Max2}, {Min3,Max3}); -	  -	{gs,_,motion,_,[X,_]} when RB =:= 'RB3', X > Min3, X < Max3 -> -	    gs:config('RB3', {x,X}), -	    resizeloop(WI, RB, X, {Min1,Max1}, {Min2,Max2}, {Min3,Max3}); -	{gs,_,motion,_,_} when RB =:= 'RB3' -> -	    resizeloop(WI, RB, Prev, {Min1,Max1}, {Min2,Max2}, {Min3,Max3}); -	 -	{gs,_,buttonrelease,_,_} -> -	    resize_win(WI, RB, Prev) -    end. - -resize_win(_WinInfo, _RB, null) -> ignore; -resize_win(WinInfo, 'RB1', Y) -> -    {_Bu,S,Bi,F} = Flags = WinInfo#winInfo.flags, -    H = gs:read('CodeArea', height), -    Diff = H-(Y-25), - -    %% Resize Code, Evaluator and Binding areas -    resize_code_area(WinInfo, height, -Diff), -    if -	S =:= close, Bi =:= close, F =:= open -> -	    resize_trace_area(open, height, Diff); -	true -> -	    resize_eval_area(S, height, Diff), -	    resize_bind_area(Bi, height, Diff) -    end, - -    %% Resize vertical resize bar -    case rb3(Flags) of -	open -> gs:config('RB3', {height,gs:read('RB3',height)+Diff}); -	close -> ignore -    end, -     -    %% Adjust the frames y coordinates -    config_v(); -resize_win(WinInfo, 'RB2', Y) -> -    {_Bu,S,Bi,F} = Flags = WinInfo#winInfo.flags, -    Prev = gs:read('TraceArea',y), -    Diff = Prev-(Y+10), -     -    %% Resize Trace, Evaluator and Binding areas -    resize_trace_area(F, height, Diff), -    resize_eval_area(S, height, -Diff), -    resize_bind_area(Bi, height, -Diff), - -    %% Resize vertical resize bar -    case rb3(Flags) of -	open -> gs:config('RB3', {height,gs:read('RB3',height)-Diff}); -	close -> ignore -    end, - -    %% Adjust the frames y coordinates -    config_v(); - -resize_win(WinInfo, 'RB3', X) -> -    {_Bu,S,Bi,_F} = WinInfo#winInfo.flags, -    Prev = gs:read('BindArea', x), -    Diff = Prev-(X+10), -     -    %% Resize Binding and Trace areas -    resize_bind_area(Bi, width, Diff), -    resize_eval_area(S, width, -Diff), - -    %% Adjust the frames x coordinates -    config_h(). - -%% Given the window dimensions, return the limits for a  resize bar. -rblimits('RB1',_W,H) -> -     -    %% Code frame should not have height <100 -    Min = 126, -     -    %% Max is decided by a minimum distance to 'RB2' -    %% unless 'RB2' is invisible and 'CodeArea' is visible -    %% (=> EvalFrame and BindFrame invisible) in which case -    %% TraceFrame should not have height <100 -    RB2 = gs:read('RB2',height), -    FF = gs:read('TraceArea',height), -    Max = case RB2 of -	      0 when FF =/= 0 -> -		  H-112; -	      _ -> -		  Y = gs:read('RB2',y), -		  erlang:max(Min,Y-140) -	  end, -     -    {Min,Max}; -rblimits('RB2',_W,H) -> -    %% TraceFrame should not have height < 100 -    Max = H-112, -    %% Min is decided by a minimum distance to 'RB1' -    Y = gs:read('RB1',y), -    Min = erlang:min(Max,Y+140), -    {Min,Max}; - -rblimits('RB3',W,_H) -> -    %% Neither CodeArea nor BindArea should occupy  -    %% less than 1/3 of the total window width and EvalFrame should -    %% be at least 289 pixels wide -    {erlang:max(round(W/3),289),round(2*W/3)}. - - -%%==================================================================== -%% 'Go To Line' and 'Search' help windows -%%==================================================================== - -helpwin(gotoline, WinInfo, GS, Coords) -> -    spawn_link(?MODULE, helpwin, [gotoline, WinInfo, GS, Coords,self()]); -helpwin(search, WinInfo, GS, Coords) -> -    spawn_link(?MODULE, helpwin, [search, WinInfo, GS, Coords, self()]). - -helpwin(Type, WinInfo, GS, Coords, AttPid) -> -    {_Mod, Editor} =  WinInfo#winInfo.editor, -    Data = case Type of -	       gotoline -> null; -	       search -> -		   {{1, 0}, false} -	   end, -    Win = helpwin(Type, GS, Coords), -    helpwin_loop(Type, AttPid, Editor, Data, Win). - -helpwin_loop(Type, AttPid, Editor, Data, Win) -> -    receive -	{gs, _Id, destroy, _Data, _Arg} -> -	    helpwin_stop(Type, AttPid, Editor, Data), -	    true; - -	{gs, _Id, keypress, _Data, ['Return'|_]} -> -	    gs:config(btn(Win), flash), -	    Data2 = helpwin_action(Type, default, -				   AttPid, Editor, Data, Win), -	    helpwin_loop(Type, AttPid, Editor, Data2, Win); -	{gs, _Id, keypress, _Data, _Arg} -> -	    helpwin_loop(Type, AttPid, Editor, Data, Win); -	 -	{gs, _Id, click, _Data, ["Clear"]} -> -	    gs:config(ent(Win), {delete, {0,last}}), -	    Data2 = helpwin_clear(Type, AttPid, Editor, Data, Win), -	    helpwin_loop(Type, AttPid, Editor, Data2, Win); -	{gs, _Id, click, _Data, ["Close"]} -> -	    helpwin_stop(Type, AttPid, Editor, Data), -	    true; -	{gs, _Id, click, Action, _Arg} -> -	    Data2 = -		helpwin_action(Type, Action, AttPid, Editor, Data, Win), -	    helpwin_loop(Type, AttPid, Editor, Data2, Win) -    end. - -helpwin_stop(gotoline, _AttPid, _Editor, _Data) -> -    ignore; -helpwin_stop(search, _AttPid, Editor, {Pos, _CS}) -> -    unmark_string(Editor, Pos). - -helpwin_clear(gotoline, _AttPid, _Editor, Data, _Win) -> -    Data; -helpwin_clear(search, _AttPid, Editor, {Pos, CS}, Win) -> -    unmark_string(Editor, Pos), -    gs:config(lbl(Win), {label, {text,""}}), -    {{1, 0}, CS}. - -helpwin_action(gotoline, default, AttPid, _Editor, Data, Win) -> -    case string:strip(gs:read(ent(Win), text)) of -	"" -> ignore; -	Str -> -	    case catch list_to_integer(Str) of -		{'EXIT', _Reason} -> ignore; -		Line -> AttPid ! {gui, {gotoline, Line}} -	    end -    end, -    Data; -helpwin_action(search, case_sensitive, _AttPid, _Ed, {Pos, CS}, _Win) -> -    Bool = if CS =:= true -> false; CS =:= false -> true end, -    {Pos, Bool}; -helpwin_action(search, default, _AttPid, Editor, {Pos, CS}, Win) -> -    gs:config(lbl(Win), {label, {text, ""}}), -    unmark_string(Editor, Pos), -    case gs:read(ent(Win), text) of -	"" -> {Pos, CS}; -	Str -> -	    gs:config(lbl(Win), {label, {text,"Searching..."}}), -	    Str2 = lowercase(CS, Str), -	    case search(Str2, Editor, gs:read(Editor, size), Pos, CS) of -		{Row, Col} -> -		    gs:config(lbl(Win), {label, {text,""}}), -		    mark_string(Editor, {Row, Col}, Str), -		    {{Row, Col}, CS}; -		not_found -> -		    gs:config(lbl(Win), {label, {text,"Not found"}}), -		    {Pos, CS} -	    end -    end. - -search(_Str, _Editor, Max, {Row, _Col}, _CS) when Row>Max -> -    not_found; -search(Str, Editor, Max, {Row, Col}, CS) -> -    SearchIn = lowercase(CS, gs:read(Editor, -				     {get,{{Row,Col+1},{Row,lineend}}})), -    case string:str(SearchIn, Str) of -	0 -> search(Str, Editor, Max, {Row+1, 0}, CS); -	N -> {Row, Col+N} -    end. - -lowercase(true, Str) -> Str; -lowercase(false, Str) -> -    [if Char >= $A, Char =< $Z -> Char+32; -	true -> Char -     end || Char <- Str]. - -mark_string(Editor, {Row, Col}, Str) -> -    Between = {{Row,Col}, {Row,Col+length(Str)}}, -    Font = dbg_ui_win:font(bold), -    gs:config(Editor, [{vscrollpos, Row-5}, -		       {font_style, {Between, Font}}, -		       {fg, {Between, red}}]). - -unmark_string(Editor, {Row, Col}) -> -    Between = {{Row,Col}, {Row,lineend}}, -    Font = dbg_ui_win:font(normal), -    gs:config(Editor, [{vscrollpos, Row-5}, -		       {font_style, {Between, Font}}, -		       {fg, {Between, black}}]). - -helpwin(Type, GS, {X, Y}) -> -    W = 200, Pad = 10, Wbtn = 50, - -    Title = case Type of search -> "Search"; gotoline -> "Go To Line" end, -    Win = gs:window(GS, [{title, Title}, {x, X}, {y, Y}, {width, W}, -			 {destroy, true}]), -     -    Ent = gs:entry(Win, [{x, Pad}, {y, Pad}, {width, W-2*Pad}, -			 {keypress, true}]), -    Hent = gs:read(Ent, height), - -    Font = dbg_ui_win:font(normal), - -    {Ybtn, Lbl} = -	case Type of -	    search -> -		Ycb = Pad+Hent, -		gs:checkbutton(Win, [{label, {text, "Case Sensitive"}}, -				     {font, Font}, -				     {align, w}, -				     {x, Pad}, {y, Ycb}, -				     {width, W-2*Pad}, {height, 15}, -				     {data, case_sensitive}]), -		Ylbl = Ycb+15, -		{Ylbl+Hent+Pad, -		 gs:label(Win, [{x, Pad}, {y, Ylbl}, -				{width, W-2*Pad}, {height, Hent}])}; -	    gotoline -> {Pad+Hent+Pad, null} -	end, - -    BtnLbl = case Type of search -> "Search"; gotoline -> "Go" end, -    Btn = gs:button(Win, [{label, {text, BtnLbl}}, {font, Font}, -			  {x, W/2-3/2*Wbtn-Pad}, {y, Ybtn}, -			  {width, Wbtn}, {height, Hent}, -			  {data, default}]), -    gs:button(Win, [{label, {text, "Clear"}}, {font, Font}, -		    {x, W/2-1/2*Wbtn}, {y, Ybtn}, -		    {width, Wbtn}, {height, Hent}]), -    gs:button(Win, [{label, {text, "Close"}}, {font, Font}, -		    {x, W/2+1/2*Wbtn+Pad}, {y, Ybtn}, -		    {width, Wbtn}, {height, Hent}]), - -    H = Ybtn+Hent+Pad, -    gs:config(Win, [{height, H}, {map, true}]), -    {Ent, Lbl, Btn}. - -ent(Win) -> element(1, Win). -lbl(Win) -> element(2, Win). -btn(Win) -> element(3, Win). diff --git a/lib/debugger/src/dbg_ui_view.erl b/lib/debugger/src/dbg_ui_view.erl deleted file mode 100644 index be998f22ff..0000000000 --- a/lib/debugger/src/dbg_ui_view.erl +++ /dev/null @@ -1,255 +0,0 @@ -%% -%% %CopyrightBegin% -%%  -%% Copyright Ericsson AB 1998-2011. All Rights Reserved. -%%  -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%%  -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%%  -%% %CopyrightEnd% -%% --module(dbg_ui_view). - -%% External exports --export([start/2]). - --record(state, {gs,                % term() Graphics system id -		win,               % term() Attach process window data -		coords,            % {X,Y} Mouse point position -		mod                % atom() Module -	       }). - -%%==================================================================== -%% External exports -%%==================================================================== - -%%-------------------------------------------------------------------- -%% start(GS, Mod) -%%   Mod = atom() -%%-------------------------------------------------------------------- -start(GS, Mod) -> -    Title = "View Module " ++ atom_to_list(Mod), -    case dbg_ui_winman:is_started(Title) of -	true -> ignore; -	false -> spawn(fun () -> init(GS, Mod, Title) end) -    end. - --spec stop() -> no_return(). -stop() -> -    exit(stop). - -%%==================================================================== -%% Main loop and message handling -%%==================================================================== - -init(GS, Mod, Title) -> -    %% Subscribe to messages from the interpreter -    int:subscribe(), - -    %% Create attach process window -    Win1 = dbg_ui_trace_win:create_win(GS, Title, ['Code Area'], menus()), -    Window = dbg_ui_trace_win:get_window(Win1), -    dbg_ui_winman:insert(Title, Window), - -    Win2 = gui_load_module(Win1, Mod), -    Win3 = -	lists:foldl(fun(Break, Win) -> -			    dbg_ui_trace_win:add_break(Win, 'Break', Break) -		    end, -		    Win2, -		    int:all_breaks(Mod)), -     -    loop(#state{gs=GS, win=Win3, coords={0,0}, mod=Mod}). - -loop(State) -> -    receive - -	%% From the GUI main window -	GuiEvent when is_tuple(GuiEvent), element(1, GuiEvent)==gs -> -	    Cmd = dbg_ui_trace_win:handle_event(GuiEvent, State#state.win), -	    State2 = gui_cmd(Cmd, State), -	    loop(State2); - -	%% From the GUI help windows -	{gui, Cmd} -> -	    State2 = gui_cmd(Cmd, State), -	    loop(State2); - -	%% From the interpreter -	{int, Cmd} -> -	    State2 = int_cmd(Cmd, State), -	    loop(State2); - -	%% From the dbg_ui_winman process (Debugger window manager) -	{dbg_ui_winman, update_windows_menu, Data} -> -	    dbg_ui_winman:update_windows_menu(Data), -	    loop(State); -	{dbg_ui_winman, destroy} -> -	    stop(); - -	%% Help window termination -- ignore -	{'EXIT', _Pid, _Reason} -> -	    loop(State) -    end. - -%%--Commands from the GUI--------------------------------------------- - -gui_cmd(ignore, State) -> -    State; -gui_cmd({win, Win}, State) -> -    State#state{win=Win}; -gui_cmd(stopped, _State) -> -    stop(); -gui_cmd({coords, Coords}, State) -> -    State#state{coords=Coords}; - -gui_cmd({shortcut, Key}, State) -> -    case shortcut(Key) of -	false -> State; -	Cmd -> gui_cmd(Cmd, State) -    end; - -%% File menu -gui_cmd('Close', _State) -> -    stop(); - -%% Edit menu -gui_cmd('Go To Line...', State) -> -    %% Will result in message handled below: {gui, {gotoline, Line}} -    dbg_ui_trace_win:helpwin(gotoline, State#state.win, -			      State#state.gs, State#state.coords), -    State; -gui_cmd({gotoline, Line}, State) -> -    Win = dbg_ui_trace_win:select_line(State#state.win, Line), -    State#state{win=Win}; -gui_cmd('Search...', State) -> -    dbg_ui_trace_win:helpwin(search, State#state.win, -			     State#state.gs, State#state.coords), -    State; - -%% Break menu -gui_cmd('Line Break...', State) -> -    add_break(State#state.gs, State#state.coords, line, -	      State#state.mod, -	      dbg_ui_trace_win:selected_line(State#state.win)), -    State; -gui_cmd('Conditional Break...', State) -> -    add_break(State#state.gs, State#state.coords, conditional, -	      State#state.mod, -	      dbg_ui_trace_win:selected_line(State#state.win)), -    State; -gui_cmd('Function Break...', State) -> -    add_break(State#state.gs, State#state.coords, function, -	      State#state.mod, undefined), -    State; -gui_cmd('Enable All', State) -> -    Breaks = int:all_breaks(), -    ThisMod = State#state.mod, -    lists:foreach(fun ({{Mod, Line}, _Options}) when Mod==ThisMod -> -			  int:enable_break(Mod, Line); -		      (_Break) -> -			  ignore -		  end, -		  Breaks), -    State; -gui_cmd('Disable All', State) -> -    Breaks = int:all_breaks(), -    ThisMod = State#state.mod, -    lists:foreach(fun ({{Mod, Line}, _Options}) when Mod==ThisMod -> -			  int:disable_break(Mod, Line); -		      (_Break) -> -			  ignore -		  end, -		  Breaks), -    State; -gui_cmd('Delete All', State) -> -    int:no_break(State#state.mod), -    State; -gui_cmd({break, {Mod, Line}, What}, State) -> -    case What of -	add -> int:break(Mod, Line); -	delete -> int:delete_break(Mod, Line); -	{status, inactive} -> int:disable_break(Mod, Line); -	{status, active} -> int:enable_break(Mod, Line); -	{trigger, Action} -> int:action_at_break(Mod, Line, Action) -    end, -    State; - -%% Help menu -gui_cmd('Debugger', State) -> -    Window = dbg_ui_trace_win:get_window(State#state.win), -    HelpFile = filename:join([code:lib_dir(debugger), -			      "doc", "html", "part_frame.html"]), -    tool_utils:open_help(Window, HelpFile), -    State. - -add_break(GS, Coords, Type, undefined, _Line) -> -    dbg_ui_break:start(GS, Coords, Type); -add_break(GS, Coords, Type, Mod, undefined) -> -    dbg_ui_break:start(GS, Coords, Type, Mod); -add_break(GS, Coords, Type, Mod, Line) -> -    dbg_ui_break:start(GS, Coords, Type, Mod, Line). - -%%--Commands from the interpreter------------------------------------- - -int_cmd({new_break, {{Mod,_Line},_Options}=Break}, #state{mod=Mod}=State) -> -    Win = dbg_ui_trace_win:add_break(State#state.win, 'Break', Break), -    State#state{win=Win}; -int_cmd({delete_break, {Mod,_Line}=Point}, #state{mod=Mod}=State) -> -    Win = dbg_ui_trace_win:delete_break(State#state.win, Point), -    State#state{win=Win}; -int_cmd({break_options, {{Mod,_Line},_Options}=Break}, #state{mod=Mod}=State) -> -    Win = dbg_ui_trace_win:update_break(State#state.win, Break), -    State#state{win=Win}; -int_cmd(no_break, State) -> -    Win = dbg_ui_trace_win:clear_breaks(State#state.win), -    State#state{win=Win}; -int_cmd({no_break, _Mod}, State) -> -    Win = dbg_ui_trace_win:clear_breaks(State#state.win), -    State#state{win=Win}; -int_cmd(_, State) -> -    State. - - -%%==================================================================== -%% GUI auxiliary functions -%%==================================================================== - -menus() -> -    [{'File', [{'Close', 0}]}, -     {'Edit', [{'Go To Line...', 0}, -	       {'Search...', 0}]}, -     {'Break', [{'Line Break...', 5}, -		{'Conditional Break...', 13}, -		{'Function Break...', 0}, -		separator, -		{'Enable All', no}, -		{'Disable All', no}, -		{'Delete All', 0}, -		separator]}, -     {'Help', [{'Debugger', no}]}]. - -shortcut(c) -> 'Close'; -shortcut(g) -> 'Go To Line...'; -shortcut(s) -> 'Search...'; -shortcut(b) -> 'Line Break...'; -shortcut(r) -> 'Conditional Break...'; -shortcut(f) -> 'Function Break...'; -shortcut(d) -> 'Delete All'; - -shortcut(_) -> false. - -gui_load_module(Win, Mod) -> -    dbg_ui_trace_win:display({text, "Loading module..."}), -    Contents = int:contents(Mod, any), -    Win2 = dbg_ui_trace_win:show_code(Win, Mod, Contents), -    dbg_ui_trace_win:display({text, ""}), -    Win2. diff --git a/lib/debugger/src/dbg_ui_win.erl b/lib/debugger/src/dbg_ui_win.erl deleted file mode 100644 index 1c7a80a1c4..0000000000 --- a/lib/debugger/src/dbg_ui_win.erl +++ /dev/null @@ -1,281 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2002-2012. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% -%% --module(dbg_ui_win). --compile([{nowarn_deprecated_function,{gs,config,2}}, -          {nowarn_deprecated_function,{gs,destroy,1}}, -          {nowarn_deprecated_function,{gs,menu,2}}, -          {nowarn_deprecated_function,{gs,menu,3}}, -          {nowarn_deprecated_function,{gs,menubutton,2}}, -          {nowarn_deprecated_function,{gs,menuitem,2}}, -          {nowarn_deprecated_function,{gs,menuitem,3}}, -          {nowarn_deprecated_function,{gs,read,2}}, -          {nowarn_deprecated_function,{gs,start,1}}]). - -%% External exports --export([init/0, -	 font/1, min_size/3, min_size/4, -	 create_menus/2, select/2, selected/1, -	 add_break/2, update_break/2, delete_break/1, -	 motion/2 -	]). - --record(break, {mb, smi, emi, dimi, demi}). - -%%==================================================================== -%% External exports -%%==================================================================== - -%%-------------------------------------------------------------------- -%% init() -> GS -%%   GS = term() -%%-------------------------------------------------------------------- -init() -> -    gs:start([{kernel, true}]). - -%%-------------------------------------------------------------------- -%% font(Style) -> Font -%%   Style = normal | bold -%% Select a suitable font. Defaults to {screen,12} and, if it does not -%% exist, {courier,12}. -%%-------------------------------------------------------------------- -font(Style) -> -    GS = init(), -    Style2 = if -		 Style =:= normal -> []; -		 true -> [Style] -	     end, -    case gs:read(GS, {choose_font, {screen,Style2,12}}) of -	Font when element(1, Font) =:= screen -> -	    Font; -	_ -> -	    gs:read(GS, {choose_font, {courier,Style2,12}}) -    end. - -%%-------------------------------------------------------------------- -%% min_size(Strings, MinW, MinH) -> {W, H} -%% min_size(Font, Strings, MinW, MinH) -> {W, H} -%%   Font = GS font - defaults to dbg_ui_win:font(normal) -%%   Strings = [string()] -%%   MinW = MinH = int() -%%   W = H = int() -%%-------------------------------------------------------------------- -min_size(Strings, MinW, MinH) -> -    min_size(font(normal), Strings, MinW, MinH). - -min_size(Font, Strings, MinW, MinH) -> -    GS = init(), -    min_size(GS, Font, Strings, MinW, MinH). - -min_size(GS, Font, [String|Strings], MinW, MinH) -> -    {W, H} = gs:read(GS, {font_wh, {Font, String}}), -    min_size(GS, Font, Strings, erlang:max(MinW, W), erlang:max(MinH, H)); -min_size(_GS, _Font, [], W, H) -> -    {W, H}. - -%%-------------------------------------------------------------------- -%% create_menus(MenuBar, [Menu]) -%%   MenuBar = gsobj() -%%   Menu = {Name, [Item]} -%%     Name = atom() -%%     Item = {Name, N} | {Name, N, Type} | {Name, N, cascade, [Item]} -%%          | separator -%%       N = no | integer() -%%       Type = check | radio -%% Create the specified menus and menuitems. -%% -%% Normal menuitems are specified as {Name, N}. Generates the event: -%%   {gs, _Id, click, {menuitem, Name}, _Arg} -%% -%% Check and radio menuitems are specified as {Name, N, check|radio}. -%% They are assumed to be children to a cascade menuitem! (And all children -%% to one cascade menuitem are assumed to be either check OR radio -%% menuitems)! -%% Selecting a check/radio menuitem generates the event: -%%   {gs, _Id, click, {menu, Menu}, _Arg} -%% where Menu is the name of the parent, the cascade menuitem. -%% Use selected(Menu) to retrieve which check/radio menuitems are -%% selected. -%%-------------------------------------------------------------------- -create_menus(MenuBar, [{Title, Items}|Menus]) -> -    Title2 = " "++(atom_to_list(Title))++" ", -    MenuBtn = gs:menubutton(MenuBar, [{label, {text,Title2}}, -				      {font, font(normal)}]), -    case Title of -	'Help' -> gs:config(MenuBtn, {side, right}); -	_ -> ignore -    end, -    Menu = gs:menu(Title, MenuBtn, []), -    create_items(Menu, Items, Title), -    create_menus(MenuBar, Menus); -create_menus(_MenuBar, []) -> -    done. - -create_items(Menu, [Item|Items], Group) -> -    create_item(Menu, Item, Group), -    create_items(Menu, Items, Group); -create_items(_Menu, [], _Group) -> -    done. - -create_item(Menu, {Name, _N, cascade, Items}, _Group) -> -    MenuBtn = gs:menuitem(Menu, [{label, {text,Name}}, -				 {font, font(normal)}, -				 {itemtype, cascade}]), -    SubMenu = gs:menu(Name, MenuBtn, []), -    create_items(SubMenu, Items, Name); -create_item(Menu, separator, _Group) -> -    gs:menuitem(Menu, [{itemtype, separator}]); -create_item(Menu, MenuItem, Group) -> -    Options = case MenuItem of -		  {Name, N} -> -		      [{data, {menuitem,Name}}]; -		  {Name, N, check} -> -		      [{itemtype, check}, {data, {menu, Group}}]; -		  {Name, N, radio} -> -		      [{itemtype, radio}, {data, {menu, Group}}, -		       {group, group(Group)}] -	      end, -    gs:menuitem(Name, Menu, [{label, {text,Name}}, -			     {font, font(normal)} | Options]), -    if -	is_integer(N) -> gs:config(Name, {underline, N}); -	true -> ignore -    end. - -%% When grouping radio buttons, the group id must be an atom unique for -%% each window. -group(Group) -> -    list_to_atom(atom_to_list(Group)++pid_to_list(self())). - -%%-------------------------------------------------------------------- -%% select(MenuItem, Bool) -%%   MenuItem = atom() -%%   Bool = boolean() -%%-------------------------------------------------------------------- -select(MenuItem, Bool) -> -    gs:config(MenuItem, {select, Bool}). - -%%-------------------------------------------------------------------- -%% selected(Menu) -> [Name] -%%   Menu = Name = atom() -%%-------------------------------------------------------------------- -selected(Menu) -> -    Children = gs:read(Menu, children), -    Selected = [gs:read(Child, select) || Child <- Children], -    lists:map(fun(Child) -> -		      {text, Name} = gs:read(Child, label), -		      list_to_atom(Name) -	      end, -	      Selected). - -%%-------------------------------------------------------------------- -%% add_break(Name, Point) -> #break{} -%%   Name = atom() -%%   Point = {Mod, Line} -%% The break will generate the following events: -%%   {gs, _Id, click, {break, Point, Event}, _Arg} -%%     Event = delete | {trigger, Action} | {status, Status} -%%       Action = enable | disable | delete -%%       Status = active | inactive -%%-------------------------------------------------------------------- -add_break(Menu, Point) -> -    Font = font(normal), - -    %% Create a name for the breakpoint -    {Mod, Line} = Point, -    Label = io_lib:format("~w ~5w", [Mod, Line]), - -    %% Create a menu for the breakpoint -    MenuBtn = gs:menuitem(Menu, [{label, {text,Label}}, {font, Font}, -				 {itemtype, cascade}]), -    SubMenu = gs:menu(MenuBtn, []), -    SMI = gs:menuitem(SubMenu, [{data, {break,Point,null}}]), -    gs:menuitem(SubMenu, [{label, {text,"Delete"}}, {font, Font}, -			  {data, {break,Point,delete}}]), -    TriggerMenuBtn = gs:menuitem(SubMenu, -				 [{label,{text,"Trigger Action"}}, -				  {font, Font}, -				  {itemtype, cascade}]), -    TriggerMenu = gs:menu(TriggerMenuBtn, []), -    Group = element(3, erlang:now()), -    EMI = gs:menuitem(TriggerMenu, [{label, {text,"Enable"}}, -				    {font, Font}, -				    {itemtype, radio}, {group, Group}, -				    {data, -				     {break,Point,{trigger,enable}}}]), -    DiMI = gs:menuitem(TriggerMenu, [{label, {text,"Disable"}}, -				     {font, Font}, -				     {itemtype, radio}, {group, Group}, -				     {data, -				      {break,Point,{trigger,disable}}}]), -    DeMI = gs:menuitem(TriggerMenu, [{label, {text,"Delete"}}, -				     {font, Font}, -				     {itemtype, radio}, {group, Group}, -				     {data, -				      {break,Point,{trigger,delete}}}]), - -    #break{mb=MenuBtn, smi=SMI, emi=EMI, dimi=DiMI, demi=DeMI}. - -%%-------------------------------------------------------------------- -%% update_break(Break, Options) -%%   Break = #break{} -%%   Options = [Status, Action, Mods, Cond] -%%     Status = active | inactive -%%     Action = enable | disable | delete -%%     Mods = null (not used) -%%     Cond = null | {Mod, Func} -%%-------------------------------------------------------------------- -update_break(Break, Options) -> -    [Status, Trigger|_] = Options, -    {break, Point, _Status} = gs:read(Break#break.smi, data), -     -    {Label, Data} = case Status of -			active -> -			    {"Disable", {break,Point,{status,inactive}}}; -			inactive -> -			    {"Enable", {break,Point,{status,active}}} -		    end, -    gs:config(Break#break.smi, [{label, {text,Label}}, -				{font, font(normal)}, -				{data, Data}]), - -    TriggerMI = case Trigger of -		    enable -> Break#break.emi; -		    disable -> Break#break.dimi; -		    delete -> Break#break.demi -		end, -    gs:config(TriggerMI, {select, true}). - -%%-------------------------------------------------------------------- -%% delete_break(Break) -%%   Break = #break{} -%%-------------------------------------------------------------------- -delete_break(Break) -> -    gs:destroy(Break#break.mb). - -%%-------------------------------------------------------------------- -%% motion(X, Y) -> {X, Y} -%%   X = Y = integer() -%%-------------------------------------------------------------------- -motion(X, Y) -> -    receive -	{gs, _Id, motion, _Data, [NX,NY]} -> -	    motion(NX, NY) -    after 0 -> -	    {X, Y} -    end. diff --git a/lib/debugger/src/dbg_ui_winman.erl b/lib/debugger/src/dbg_ui_winman.erl deleted file mode 100644 index b5433a202b..0000000000 --- a/lib/debugger/src/dbg_ui_winman.erl +++ /dev/null @@ -1,182 +0,0 @@ -%% -%% %CopyrightBegin% -%%  -%% Copyright Ericsson AB 1998-2012. All Rights Reserved. -%%  -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%%  -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%%  -%% %CopyrightEnd% -%% --module(dbg_ui_winman). --behaviour(gen_server). --compile([{nowarn_deprecated_function,{gs,config,2}}, -          {nowarn_deprecated_function,{gs,destroy,1}}, -          {nowarn_deprecated_function,{gs,menu,3}}, -          {nowarn_deprecated_function,{gs,menubutton,3}}, -          {nowarn_deprecated_function,{gs,menuitem,3}}]). - -%% External exports --export([start/0]). --export([insert/2, is_started/1, -	 clear_process/1, -	 raise/1, -	 windows_menu/1, update_windows_menu/1]). - -%% gen_server callbacks --export([init/1, handle_call/3, handle_cast/2, handle_info/2, -	 terminate/2, code_change/3]). - --record(win, {owner,     % pid() -	      title,     % string() -	      win        % gsobj() -	     }). - --record(state, {wins=[]  % [#win{}] -	       }). - -%%==================================================================== -%% External exports -%%==================================================================== - -%%-------------------------------------------------------------------- -%% start() -%%-------------------------------------------------------------------- -start() -> -    gen_server:start({local,?MODULE}, ?MODULE, [], []). - -%%-------------------------------------------------------------------- -%% insert(Title, Win) -%%   Title = string() -%%   Win = gsobj() -%%-------------------------------------------------------------------- -insert(Title, Win) -> -    gen_server:cast(?MODULE, {insert, self(), Title, Win}). - -%%-------------------------------------------------------------------- -%% is_started(Title) -> true | false -%%   Title = string() -%%-------------------------------------------------------------------- -is_started(Title) -> -    case gen_server:call(?MODULE, {is_started, Title}, infinity) of -	{true, Win} -> -	    raise(Win), -	    true; -	false -> -	    false -    end. - -%%-------------------------------------------------------------------- -%% clear_process(Title) -%%   Title = string() -%%-------------------------------------------------------------------- -clear_process(Title) -> -    gen_server:cast(?MODULE, {clear_process, Title}). - -%%-------------------------------------------------------------------- -%% raise(Win) -%%   Win = gsobj() -%%-------------------------------------------------------------------- -raise(Win) -> -    gs:config(Win, [raise, {iconify, false}, {setfocus, true}]). - -%%-------------------------------------------------------------------- -%% windows_menu(MenuBar) -%%   MenuBar = gsobj() -%%-------------------------------------------------------------------- -windows_menu(MenuBar) -> -    gs:menubutton('WindowsMenuBtn', MenuBar, -		  [{label,{text," Windows "}}, -		   {font, dbg_ui_win:font(normal)}]), -    gs:menu('WindowsMenu', 'WindowsMenuBtn', []). - -%%-------------------------------------------------------------------- -%% update_windows_menu(Data) -%%   Data = {New, Old} -%%     New = Old = list() -%%-------------------------------------------------------------------- -update_windows_menu([MonInfo|Infos]) -> -    gs:destroy('WindowsMenu'), -    gs:menu('WindowsMenu', 'WindowsMenuBtn', []), -    menuitem(MonInfo), -    gs:menuitem(separator, 'WindowsMenu', [{itemtype, separator}]), -    lists:foreach(fun(Info) -> menuitem(Info) end, Infos). - -menuitem({Title, Win}) -> -    gs:menuitem(Title, 'WindowsMenu', [{label, {text,Title}}, -				       {font, dbg_ui_win:font(normal)}, -				       {data, {dbg_ui_winman,Win}}]). - - -%%==================================================================== -%% gen_server callbacks -%%==================================================================== - -init(_Arg) -> -    process_flag(trap_exit, true), -    {ok, #state{}}. - -handle_call({is_started, Title}, _From, State) -> -    Reply = case lists:keyfind(Title, #win.title, State#state.wins) of -		false -> false; -		Win -> {true, Win#win.win} -	    end, -    {reply, Reply, State}. - -handle_cast({insert, Pid, Title, Win}, State) -> -    link(Pid), -    Wins = State#state.wins ++ [#win{owner=Pid, title=Title, win=Win}], -    inform_all(Wins), -    {noreply, State#state{wins=Wins}}; - -handle_cast({clear_process, Title}, State) -> -    OldWins = State#state.wins, -    Wins = case lists:keyfind(Title, #win.title, OldWins) of -		 #win{owner=Pid} -> -		   Msg = {dbg_ui_winman, destroy}, -		   Pid ! Msg, -		   lists:keydelete(Title, #win.title, OldWins); -	       false ->  -		   OldWins -    end, -    {noreply, State#state{wins=Wins}}. - -handle_info({'EXIT', Pid, _Reason}, State) -> -    [Mon | _Wins] = State#state.wins, -    if -	Pid =:= Mon#win.owner -> {stop, normal, State}; -	true -> -	    Wins2 = lists:keydelete(Pid, #win.owner, State#state.wins), -	    inform_all(Wins2), -	    {noreply, State#state{wins=Wins2}} -    end. - -terminate(_Reason, State) -> -    delete_all(State#state.wins), -    ok. - -code_change(_OldVsn, State, _Extra) -> -    {ok, State}. - - -%%==================================================================== -%% Internal functions -%%==================================================================== - -inform_all(Wins) -> -    Infos = lists:map(fun(#win{title=Title, win=Win}) -> {Title, Win} end, -			  Wins), -    Msg = {dbg_ui_winman, update_windows_menu, Infos}, -    lists:foreach(fun(#win{owner=Pid}) -> Pid ! Msg end, Wins). - -delete_all(Wins) -> -    Msg = {dbg_ui_winman, destroy}, -    lists:foreach(fun(#win{owner=Pid}) -> Pid ! Msg end, Wins). diff --git a/lib/debugger/src/dbg_wx_filedialog_win.erl b/lib/debugger/src/dbg_wx_filedialog_win.erl index c8ecb7b5d4..ea34295067 100644 --- a/lib/debugger/src/dbg_wx_filedialog_win.erl +++ b/lib/debugger/src/dbg_wx_filedialog_win.erl @@ -1,7 +1,7 @@  %%  %% %CopyrightBegin%  %% -%% Copyright Ericsson AB 2009-2012. All Rights Reserved. +%% Copyright Ericsson AB 2009-2014. All Rights Reserved.  %%  %% The contents of this file are subject to the Erlang Public License,  %% Version 1.1, (the "License"); you may not use this file except in @@ -242,16 +242,13 @@ handle_event(#wx{event=#wxList{itemIndex=Index}},  	    {noreply, State0}      end; -handle_event(#wx{event=#wxCommand{type=command_text_updated, cmdString=Wanted}},  +handle_event(#wx{event=#wxCommand{type=command_text_updated, cmdString=Wanted}},  	     State = #state{ptext=Previous, completion=Comp}) ->      case Previous =:= undefined orelse lists:prefix(Wanted, Previous) of -	true ->  -	    case Comp of -		{Temp,_} -> wxWindow:destroy(Temp); -		undefined -> ok -	    end, +	true -> +	    destroy_completion(Comp),  	    {noreply, State#state{ptext=Wanted,completion=undefined}}; -	false ->  +	false ->  	    {noreply, show_completion(Wanted, State)}      end; @@ -310,8 +307,7 @@ handle_event(#wx{event=#wxSize{size={Width,_}}}, State = #state{list=LC}) ->  	     end),      {noreply, State}; -handle_event(Event,State) -> -    io:format("~p Got ~p ~n",[self(), Event]), +handle_event(_Event,State) ->      {noreply, State}.  handle_info(_Msg, State) -> @@ -419,8 +415,9 @@ show_completion(Wanted, State = #state{text=TC, win=Win, list=LC, completion=Com      end.  destroy_completion(undefined) -> ok; -destroy_completion({Window, _}) -> +destroy_completion({Window, _LB}) ->      Parent = wxWindow:getParent(Window), +    wxWindow:hide(Window),      wxWindow:destroy(Window),      wxWindow:refresh(Parent). diff --git a/lib/debugger/src/dbg_wx_mon.erl b/lib/debugger/src/dbg_wx_mon.erl index 4a01492cf5..4ab03985d3 100644 --- a/lib/debugger/src/dbg_wx_mon.erl +++ b/lib/debugger/src/dbg_wx_mon.erl @@ -1,7 +1,7 @@  %%  %% %CopyrightBegin%  %% -%% Copyright Ericsson AB 2008-2013. All Rights Reserved. +%% Copyright Ericsson AB 2008-2014. All Rights Reserved.  %%  %% The contents of this file are subject to the Erlang Public License,  %% Version 1.1, (the "License"); you may not use this file except in @@ -148,7 +148,7 @@ init2(CallingPid, Mode, SFile, GS) ->  		    win     = Win,  		    focus   = undefined, -		    coords  = {20,20}, +		    coords  = {-1,-1},  		    intdir  = element(2, file:get_cwd()),  		    pinfos  = [], diff --git a/lib/debugger/src/dbg_wx_mon_win.erl b/lib/debugger/src/dbg_wx_mon_win.erl index a617f3e1e7..d94eb14937 100644 --- a/lib/debugger/src/dbg_wx_mon_win.erl +++ b/lib/debugger/src/dbg_wx_mon_win.erl @@ -1,7 +1,7 @@  %%  %% %CopyrightBegin%  %% -%% Copyright Ericsson AB 2008-2013. All Rights Reserved. +%% Copyright Ericsson AB 2008-2014. All Rights Reserved.  %%  %% The contents of this file are subject to the Erlang Public License,  %% Version 1.1, (the "License"); you may not use this file except in @@ -43,7 +43,7 @@  -record(moduleInfo, {module, menubtn}).  -record(procInfo, {pid, row}).  -record(breakInfo, {point, status, break}). --record(break, {mb, smi, emi, dimi, demi}).  %% BUGBUG defined in dbg_ui_win +-record(break, {mb, smi, emi, dimi, demi}).  -record(winInfo, {window,       % gsobj()  		  grid,         % gsobj()  		  row,          % int() Last row in grid @@ -76,13 +76,6 @@  init() ->      dbg_wx_win:init(). -%%-------------------------------------------------------------------- -%% create_win(GS, Title, Menus) -> #winInfo{} -%%   GS = gsobj() -%%   Title = string() -%%   Menus = [menu()]  See dbg_ui_win.erl -%%-------------------------------------------------------------------- -  -define(GRID,1000).  -define(PAD, 5). @@ -624,8 +617,6 @@ handle_event(#wx{userData=Data,  	     _WinInfo) ->      Data;  handle_event(_Event, _WinInfo) -> -%% FIXME -    io:format("Ev: ~p~n",[_Event]),      ignore.  %%==================================================================== diff --git a/lib/debugger/src/dbg_wx_trace.erl b/lib/debugger/src/dbg_wx_trace.erl index 7108b5a79a..4438466bb0 100644 --- a/lib/debugger/src/dbg_wx_trace.erl +++ b/lib/debugger/src/dbg_wx_trace.erl @@ -1,7 +1,7 @@  %%  %% %CopyrightBegin%  %%  -%% Copyright Ericsson AB 2008-2013. All Rights Reserved. +%% Copyright Ericsson AB 2008-2014. All Rights Reserved.  %%   %% The contents of this file are subject to the Erlang Public License,  %% Version 1.1, (the "License"); you may not use this file except in @@ -71,21 +71,10 @@ start(Pid, TraceWin, BackTrace) ->      start(Pid, TraceWin, BackTrace, ?STRINGS).  start(Pid, TraceWin, BackTrace, Strings) -> -    case {whereis(dbg_wx_mon), whereis(dbg_ui_mon)} of -	{undefined, undefined} -> -	    case which_gui() of -		gs -> -		    dbg_ui_trace:start(Pid, TraceWin, BackTrace); -		wx -> -		    Parent = wx:new(), -		    Env = wx:get_env(), -		    start(Pid, Env, Parent, TraceWin, BackTrace, Strings) -	    end; -	{undefined, Monitor} when is_pid(Monitor) -> -	    dbg_ui_trace:start(Pid, TraceWin, BackTrace); -	{Monitor, _} when is_pid(Monitor) -> +    case whereis(dbg_wx_mon) of +	Monitor when is_pid(Monitor) ->  	    Monitor ! {?MODULE, self(), get_env}, -	    receive  +	    receive  		{env, Monitor, Env, Parent} ->  		    start(Pid, Env, Parent, TraceWin, BackTrace, Strings)  	    end @@ -110,15 +99,6 @@ start(Pid, Env, Parent, TraceWin, BackTrace, Strings) ->  	    ignore      end. -which_gui() -> -    try -	wx:new(), -	wx:destroy(), -	wx -    catch _:_ -> -	    gs -    end. -  %%--------------------------------------------------------------------  %% title(Pid) -> string()  %% By exporting this function, dbg_wx_mon may check with dbg_wx_winman @@ -145,7 +125,7 @@ init(Pid, Parent, Meta, TraceWin, BackTrace, Strings) ->      dbg_wx_winman:insert(Title, Window),      %% Initial process state -    State1 = #state{win=Win, coords={0,0}, pid=Pid, meta=Meta, +    State1 = #state{win=Win, coords={-1,-1}, pid=Pid, meta=Meta,  		    status={idle,null,null},  		    stack={1,1}, strings=[str_on]}, diff --git a/lib/debugger/src/dbg_wx_view.erl b/lib/debugger/src/dbg_wx_view.erl index 6242b9d0e0..fc7ffc0d56 100644 --- a/lib/debugger/src/dbg_wx_view.erl +++ b/lib/debugger/src/dbg_wx_view.erl @@ -1,7 +1,7 @@  %%  %% %CopyrightBegin%  %%  -%% Copyright Ericsson AB 2008-2011. All Rights Reserved. +%% Copyright Ericsson AB 2008-2014. All Rights Reserved.  %%   %% The contents of this file are subject to the Erlang Public License,  %% Version 1.1, (the "License"); you may not use this file except in @@ -72,7 +72,7 @@ init(GS, Env, Mod, Title) ->  		    Win2,  		    int:all_breaks(Mod)), -    try loop(#state{gs=GS, win=Win3, coords={0,0}, mod=Mod})  +    try loop(#state{gs=GS, win=Win3, coords={-1,-1}, mod=Mod})      catch _E:normal ->  	    exit(normal);  	  _E:_R -> diff --git a/lib/debugger/src/debugger.app.src b/lib/debugger/src/debugger.app.src index 807054c983..f102385d39 100644 --- a/lib/debugger/src/debugger.app.src +++ b/lib/debugger/src/debugger.app.src @@ -1,7 +1,7 @@  %%  %% %CopyrightBegin%  %%  -%% Copyright Ericsson AB 1997-2011. All Rights Reserved. +%% Copyright Ericsson AB 1997-2013. All Rights Reserved.  %%   %% The contents of this file are subject to the Erlang Public License,  %% Version 1.1, (the "License"); you may not use this file except in @@ -27,20 +27,6 @@  	     dbg_iload,  	     dbg_iserver,  	     dbg_istk, -	     dbg_ui_break, -	     dbg_ui_break_win, -	     dbg_ui_edit, -	     dbg_ui_edit_win, -	     dbg_ui_filedialog_win, -	     dbg_ui_interpret, -	     dbg_ui_mon, -	     dbg_ui_mon_win, -	     dbg_ui_settings, -	     dbg_ui_trace, -	     dbg_ui_trace_win, -	     dbg_ui_view, -	     dbg_ui_win, -	     dbg_ui_winman,  	     dbg_wx_break,  	     dbg_wx_break_win,  	     dbg_wx_code, @@ -59,5 +45,7 @@  	     i,  	     int  	    ]}, -  {registered, [dbg_iserver, dbg_ui_mon, dbg_ui_winman]}, -  {applications, [kernel, stdlib, gs]}]}. +  {registered, [dbg_iserver, dbg_wx_mon, dbg_wx_winman]}, +  {applications, [kernel, stdlib]}, +  {runtime_dependencies, ["wx-1.2","stdlib-2.0","kernel-3.0","erts-6.0", +			  "compiler-5.0"]}]}. diff --git a/lib/debugger/src/debugger.appup.src b/lib/debugger/src/debugger.appup.src index 7a435e9b22..81d2fab05a 100644 --- a/lib/debugger/src/debugger.appup.src +++ b/lib/debugger/src/debugger.appup.src @@ -1,7 +1,7 @@ -%% +%% -*- erlang -*-  %% %CopyrightBegin%  %%  -%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% Copyright Ericsson AB 2001-2014. All Rights Reserved.  %%   %% The contents of this file are subject to the Erlang Public License,  %% Version 1.1, (the "License"); you may not use this file except in @@ -15,5 +15,7 @@  %% under the License.  %%   %% %CopyrightEnd% -%% -{"%VSN%",[],[]}. +{"%VSN%", + [{<<".*">>,[{restart_application, debugger}]}], + [{<<".*">>,[{restart_application, debugger}]}] +}. diff --git a/lib/debugger/src/debugger.erl b/lib/debugger/src/debugger.erl index b97091ee6b..77fd0acb70 100644 --- a/lib/debugger/src/debugger.erl +++ b/lib/debugger/src/debugger.erl @@ -1,7 +1,7 @@  %%  %% %CopyrightBegin%  %%  -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% Copyright Ericsson AB 1997-2013. All Rights Reserved.  %%   %% The contents of this file are subject to the Erlang Public License,  %% Version 1.1, (the "License"); you may not use this file except in @@ -32,44 +32,38 @@  %% --------  %% Interface module.  %% -%% dbg_ui_winman +%% dbg_wx_winman  %% -------------  %% Window manager, keeping track of open windows and Debugger  %% processes.  %% -%% dbg_ui_mon, dbg_ui_mon_win +%% dbg_wx_mon, dbg_wx_mon_win  %% --------------------------  %% Monitor window, main window of Debugger, displaying information  %% about interpreted modules and debugged processes.  %% -%% dbg_ui_trace, dbg_ui_trace_win +%% dbg_wx_trace, dbg_wx_trace_win  %% ------------------------------  %% Attach process window, showing the code executed by a debugged  %% process and providing a GUI for stepping, inspecting variables etc.  %% -%% dbg_ui_break, dbg_ui_break_win +%% dbg_wx_break, dbg_wx_break_win  %% ------------------------------  %% Help window for creating new breakpoints.  %% -%% dbg_ui_edit, dbg_ui_edit_win -%% -------------------------------------- -%% Help window for editing terms, used for setting backtrace size -%% (i.e. how many stack frames to display in the attach process window) -%% and changing variable values. -%% -%% dbg_ui_interpret, dbg_ui_filedialog_win +%% dbg_wx_interpret, dbg_wx_filedialog_win  %% --------------------------------------  %% Help window for selecting modules to interpret.  %% -%% dbg_ui_settings, dbg_ui_filedialog_win +%% dbg_wx_settings, dbg_wx_filedialog_win  %% --------------------------------------  %% Help window for saving and loading Debugger settings.  %% -%% dbg_ui_view +%% dbg_wx_view  %% ----------- -%% Help window for viewing interpreted modules (uses dbg_ui_trace_win). +%% Help window for viewing interpreted modules (uses dbg_wx_trace_win).  %% -%% dbg_ui_win +%% dbg_wx_win  %% ----------  %% GUI specific functionality used by more than one window type.  %% @@ -78,7 +72,7 @@ start() ->      start(global, default, default).  start(Mode) when Mode==local; Mode==global ->      start(Mode, default, default); -start(Gui) when Gui==gs; Gui==wx -> +start(Gui) when Gui==wx ->      start(global, default, Gui);  start(SFile) when is_list(SFile), is_integer(hd(SFile)) ->      start(global, SFile, default). @@ -86,8 +80,6 @@ start(SFile) when is_list(SFile), is_integer(hd(SFile)) ->  start(Mode, SFile) ->      start(Mode, SFile, default). -start(Mode, SFile, gs) -> -    dbg_ui_mon:start(Mode, SFile);  start(Mode, SFile, wx) ->      dbg_wx_mon:start(Mode, SFile);  start(Mode, SFile, default) -> @@ -95,7 +87,7 @@ start(Mode, SFile, default) ->      start(Mode, SFile, Gui).  stop() -> -    dbg_ui_mon:stop(). +    dbg_wx_mon:stop().  quick(M, F, A) ->      int:i(M), @@ -104,15 +96,7 @@ quick(M, F, A) ->  auto_attach(Flags) ->          case which_gui() of -	gs -> int:auto_attach(Flags, {dbg_ui_trace, start, []});  	wx -> int:auto_attach(Flags, {dbg_wx_trace, start, []})      end. -which_gui() -> -    try -	wx:new(), -	wx:destroy(), -	wx -    catch _:_ -> -	    gs -    end. +which_gui() -> wx. diff --git a/lib/debugger/src/int.erl b/lib/debugger/src/int.erl index bdd671cff1..2755db64b8 100644 --- a/lib/debugger/src/int.erl +++ b/lib/debugger/src/int.erl @@ -630,14 +630,13 @@ find_beam(Mod, Src) ->      File = filename:join(SrcDir, BeamFile),      case is_file(File) of  	true -> File; -	false -> find_beam_1(Mod, BeamFile, SrcDir) +	false -> find_beam_1(BeamFile, SrcDir)      end. -find_beam_1(Mod, BeamFile, SrcDir) -> +find_beam_1(BeamFile, SrcDir) ->      RootDir = filename:dirname(SrcDir),      EbinDir = filename:join(RootDir, "ebin"),      CodePath = [EbinDir | code:get_path()], -    BeamFile = atom_to_list(Mod) ++ code:objfile_extension(),      lists:foldl(fun(_, Beam) when is_list(Beam) -> Beam;  		   (Dir, error) ->  			File = filename:join(Dir, BeamFile), | 
