anchor.diff:  %%--------------------------------------------------------------------
   %%% Internal functions
   %%--------------------------------------------------------------------
  +
  +send(Msg, {To, _Nick}) when is_pid(To); is_atom(To) ->
  +    To ! Msg;
  +send(Msg, To) when is_pid(To); is_atom(To) ->
  +    To ! Msg.
  +
  +srv_msg(Msg, Ref, C = #state{}) when is_reference(Ref) ->
  +    gen_irc:msg(server, Ref, C#state.name, Msg).
  
positive.code: -export([init/1, handle_call/3, handle_cast/2, handle_info/2,
           terminate/2, code_change/3]).
  
  -record(state, {net, name}).
  -define(SERVER, ?MODULE).
  
  %%====================================================================
  
negative.code: %% @doc Non gen-server message handler callbacks
  %% @end
  %%--------------------------------------------------------------------
  handle_info({irc, user, Ref, From = {Pid,Nick}, {nick, N}}, S = #state{users=U}) ->
      case lists:keysearch(N, #user.nick, U) of
          {value, #user{}} ->
              send(srv_msg({error, nicknameinuse}, Ref, S), From),
              {noreply, S};
          false ->
              case lists:keysearch(Nick, #user.nick, U) of
                  {value, User = #user{}} ->
                      NewUser = User#user{nick=N},
                      NewUsers = [NewUser|lists:delete(User, U)],
                      send(srv_msg(ok, Ref, S), From),
                      {noreply, S#state{users=NewUsers}};
                  false ->
                      URef = erlang:monitor(process, Pid),
                      NewUser = #user{nick=N, pid=Pid, ref=URef},
                      NewUsers = [NewUser|U],
                      send(srv_msg(ok, Ref, S), From),
                      {noreply, S#state{users=NewUsers}}
              end
      end;
  handle_info({irc, channel, Ref, From, {join, Chan}},
              S = #state{channels=C}) ->
      case lists:keysearch(Chan, #chan.name, C) of
          {value, #chan{pid=P}} ->
              P ! gen_irc:msg(channel, Ref, From, join),
              {noreply, S};
          false ->
              case irc_channel:start_monitor(S#state.net, Chan) of
                  {ok, CPid, CRef} ->
                      NewChan = #chan{pid=CPid,name=Chan,ref=CRef},
                      NewChans = [NewChan|C],
                      CPid ! gen_irc:msg(channel, Ref, From, join),
                      {noreply, S#state{channels=NewChans}};
                  Error ->
                      ?WARN("Couldn't start channel ~p: ~p", [Chan, Error]),
                      send(gen_irc:msg(channel, Ref, S#state.name, {error, toomanychannels}), From),
                      {noreply, S}
              end
      end;
  handle_info(M = {'DOWN', Ref, process, _Pid, _}, S = #state{channels=C,users=U}) ->
      case lists:keysearch(Ref, #user.ref, U) of
          {value, User} ->
              {noreply, S#state{users=lists:delete(User,U)}};
          false ->
              case lists:keysearch(Ref, #chan.ref, C) of
                  {value, Chan} ->
                      {noreply, S#state{channels=lists:delete(Chan,c)}};
                  false ->
                      ?WARN("Unexpected monitor message ~p",[M]),
                      {noreply, S}
              end
      end;
  handle_info(Info, State) ->
      ?WARN("Unexpected info ~p", [Info]),
      {noreply, State}.
  