changeset 202:1bb19c7b3298

Replace irssi with weechat
author zegervdv <zegervdv@me.com>
date Wed, 19 Nov 2014 19:24:17 +0100
parents 6de3103d47f4
children 2c77dbb93f11
files irssi/config irssi/pbrisbin.theme irssi/scripts/adv_windowlist.pl irssi/scripts/autorun/adv_windowlist.pl irssi/scripts/autorun/cap_sasl.pl irssi/scripts/autorun/hilightwin.pl irssi/scripts/autorun/nicklist.pl irssi/scripts/autorun/nm.pl irssi/scripts/autorun/queryresume.pl irssi/scripts/autorun/trackbar.pl irssi/scripts/bitlbee_typing_notice.pl irssi/scripts/cap_sasl.pl irssi/scripts/hilightwin.pl irssi/scripts/nicklist.pl irssi/scripts/nm.pl irssi/scripts/queryresume.pl irssi/scripts/trackbar.pl weechat/buffers.conf weechat/perl/autoload/buffers.pl weechat/perl/autoload/iset.pl weechat/perl/buffers.pl weechat/perl/iset.pl weechat/weechat.conf
diffstat 23 files changed, 7458 insertions(+), 5083 deletions(-) [+]
line wrap: on
line diff
--- a/irssi/config	Wed Nov 19 19:08:21 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,219 +0,0 @@
-# vim:ft=config
-
-servers = (
-  {
-    address = "irc.freenode.net";
-    chatnet = "freenode";
-    port = "6697";
-    use_ssl = "yes";
-    ssl_verify = "yes";
-    ssl_capath = "/etc/ssl/certs/";
-    autoconnect = "yes";
-  },
-
-  { address = "localhost"; chatnet = "bitlbee"; autoconnect = "yes"; }
-);
-
-chatnets = {
-  freenode = { type = "IRC"; nick = "zegervdv"; };
-  bitlbee = { type = "IRC"; };
-};
-
-channels = (
-  { name = "#vim"; chatnet = "freenode"; autojoin = "yes"; },
-  { name = "#raspberrypi"; chatnet = "freenode"; autojoin = "yes"; },
-  { name = "#archlinux-arm"; chatnet = "freenode"; autojoin = "yes"; }
-);
-
-aliases = {
-  J = "join";
-  LEAVE = "part";
-  E = "exec - runz";
-  EO = "exec - -o runz";
-  EXIT = "quit";
-  LL = "lastlog";
-  W = "window";
-  M = "mark";
-  WC = "window close";
-  WK = "window kill";
-  WN = "window new hide";
-  WA = "window goto active";
-  RUN = "SCRIPT LOAD";
-  Q = "QUERY";
-};
-
-statusbar = {
-  items = {
-    time = "{sb $Z}       ";
-    window = ":: {sb [$winref] $tag $itemname} ";
-    window_empty = ":: {sb [$winref] $tag $itemname} ";
-
-    prompt = "{prompt}";
-    prompt_empty = "{prompt}";
-  };
-
-  default = {
-    window = {
-      type = "window";
-      placement = "top";
-      visible = "active";
-      items = { window = { }; window_empty = { }; typing_notice = { }; };
-    };
-
-    window_inact = {
-      type = "window";
-      placement = "top";
-      visible = "inactive";
-      items = { window = { }; window_empty = { }; };
-    };
-
-    prompt = {
-      type = "root";
-      placement = "bottom";
-      position = "100";
-      visible = "always";
-
-      items = {
-        time = { };
-        user = { };
-        prompt = { priority = "-1"; };
-        prompt_empty = { priority = "-1"; };
-
-        input = { priority = "10"; };
-      };
-    };
-
-    topic = {
-      type = "root";
-      placement = "bottom";
-      position = "1";
-      visible = "always";
-      items = { topic = { }; topic_empty = { }; };
-    };
-
-    awl_0 = {
-      items = {
-        barstart = { priority = "100"; };
-        awl_0 = { };
-        barend = { priority = "100"; alignment = "right"; };
-      };
-    };
-  };
-};
-
-settings = {
-  core = {
-    real_name = "Zeger Van de Vannet";
-    user_name = "zegervdv";
-    nick = "zegervdv";
-    awaylog_file = "/dev/null";
-    recode_autodetect_utf8 = "yes";
-    recode_fallback = "CP1252";
-  };
-
-  "fe-text" = { actlist_sort = "refnum"; };
-
-  "fe-common/core" = {
-    emphasis = "OFF";
-    theme = "pbrisbin";
-    beep_msg_level = "NOTICE MSGS HILIGHT";
-    bell_beeps = "no";
-    hilight_nick_matches = "no";
-    autolog_path = "~/.irssi/logs/$tag/$0.log";
-    autolog = "yes";
-  };
-
-  "perl/core/scripts" = {
-    neat_maxlength = "13";
-    awl_display_key = "%w$N.$H$C$S ";
-    awl_position = "0";
-    awl_sbar_maxlength = "no";
-    awl_maxlines = "3";
-    screen_away_message = "away";
-    hilightwin_showprivmsg = "no";
-    bitlbee_send_typing = "yes";
-    lt_in_queries = "yes";
-    neat_left_actions = "no";
-    awl_shared_sbar = "OFF";
-  };
-};
-
-ignores = (
-  { level = "JOINS PARTS QUITS NICKS"; },
-  { level = "MODES"; channels = ( "&bitlbee", "&facebook" ); }
-);
-
-hilights = (
-  { text = "zegervdv"; nick = "no"; word = "yes"; fullword = "yes"; },
-  { text = "@zegervdv"; nick = "no"; word = "yes"; fullword = "yes"; }
-);
-
-logs = { };
-windows = {
-  1 = { immortal = "yes"; name = "(status)"; level = "ALL"; };
-  2 = { name = "hilight"; sticky = "yes"; };
-  3 = {
-    items = (
-      {
-        type = "CHANNEL";
-        chat_type = "IRC";
-        name = "&bitlbee";
-        tag = "bitlbee";
-      }
-    );
-  };
-  4 = {
-    items = (
-      {
-        type = "CHANNEL";
-        chat_type = "IRC";
-        name = "#twitter_zegervdv";
-        tag = "bitlbee";
-      }
-    );
-  };
-  5 = {
-    items = (
-      {
-        type = "CHANNEL";
-        chat_type = "IRC";
-        name = "&facebook";
-        tag = "bitlbee";
-      }
-    );
-  };
-  6 = {
-    items = (
-      {
-        type = "CHANNEL";
-        chat_type = "IRC";
-        name = "#vim";
-        tag = "freenode";
-      }
-    );
-  };
-  7 = {
-    items = (
-      {
-        type = "CHANNEL";
-        chat_type = "IRC";
-        name = "#raspberrypi";
-        tag = "freenode";
-      }
-    );
-  };
-  8 = {
-    items = (
-      {
-        type = "CHANNEL";
-        chat_type = "IRC";
-        name = "#archlinux-arm";
-        tag = "freenode";
-      }
-    );
-  };
-};
-mainwindows = {
-  1 = { first_line = "11"; lines = "44"; };
-  2 = { first_line = "1"; lines = "10"; };
-};
--- a/irssi/pbrisbin.theme	Wed Nov 19 19:08:21 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,174 +0,0 @@
-##
-## pbrisbin's irssi theme.
-##
-
-default_color = "-1";
-info_eol = "false";
-replaces = { "[]=" = "%K$*%n"; };
-
-# Only overrides are shown, defaults are commented.
-abstracts = {
-  ##
-  ## Generic
-  ##
-  line_start = "%c::%n ";
-  timestamp = "%K$0-%n";
-  hilight = "%W$*%W";
-
-  #error = "%R$*%n";
-  #channel = "%_$*%_";
-  #nick = "%_$*%_";
-  #nickhost = "[$*]";
-  #server = "%_$*%_";
-  #comment = "[$*]";
-  #reason = "{comment $*}";
-  #mode = "{comment $*}";
-
-  # channel specific messages
-  #channick_hilight = "%C$*%n";
-  #chanhost_hilight = "{nickhost %c$*%n}";
-  #channick = "%c$*%n";
-  #chanhost = "{nickhost $*}";
-  #channelhilight = "%c$*%n";
-  #ban = "%c$*%n";
-
-  ##
-  ## Messages
-  ##
-  msgnick = "$0$1-%c:%n %|";
-
-  #ownmsgnick = "{msgnick $0 $1-}";
-  #ownnick = "%W$*%n";
-  #pubmsgnick = "{msgnick $0 $1-}";
-  #pubnick = "%N$*%n";
-  #pubmsgmenick = "{msgnick $0 $1-}";
-  #menick = "%Y$*%n";
-  #pubmsghinick = "{msgnick $1 $0$2-%n}";
-  #msgchannel = "%K:%c$*%n";
-  #privmsg = "[%R$0%K(%r$1-%K)%n] ";
-  #ownprivmsg = "[%r$0%K(%R$1-%K)%n] ";
-  #ownprivmsgnick = "{msgnick  $*}";
-  #ownprivnick = "%W$*%n";
-  #privmsgnick = "{msgnick  %R$*%n}";
-
-  ##
-  ## Action
-  ##
-  action_core = "%M$*";
-  action = "{action_core $*}";
-  pvtaction = "{action_core $*}";
-  ownaction_target = "{action_core $*}";
-
-  #ownaction = "{action $*}";
-  pubaction = "{action $*} ";
-  # fix neatlength inconsistency, sigh
-  #pvtaction_query = "{action $*}";
-
-  ##
-  ## whois
-  ##
-  #whois = "%# $[8]0 : $1-";
-
-  ##
-  ## Notices
-  ##
-  #ownnotice = "[%r$0%K(%R$1-%K)]%n ";
-  #notice = "%K-%M$*%K-%n ";
-  #pubnotice_channel = "%K:%m$*";
-  #pvtnotice_host = "%K(%m$*%K)";
-  #servernotice = "%g!$*%n ";
-
-  ##
-  ## CTCP
-  ##
-  #ownctcp = "[%r$0%K(%R$1-%K)] ";
-  #ctcp = "%g$*%n";
-
-  ##
-  ## Wallops
-  ##
-  #wallop = "%W$*%n: ";
-  #wallop_nick = "%n$*";
-  #wallop_action = "%W * $*%n ";
-
-  ##
-  ## Netsplits
-  ##
-  #netsplit = "%R$*%n";
-  #netjoin = "%C$*%n";
-
-  ##
-  ## Names
-  ##
-  #names_prefix = "";
-  #names_nick = "[%_$0%_$1-] ";
-  #names_nick_op = "{names_nick $*}";
-  #names_nick_halfop = "{names_nick $*}";
-  #names_nick_voice = "{names_nick $*}";
-  #names_users = "[%g$*%n]";
-  #names_channel = "%G$*%n";
-
-  ##
-  ## DCC
-  ##
-  #dcc = "%g$*%n";
-  #dccfile = "%_$*%_";
-  #dccownmsg = "[%r$0%K($1-%K)%n] ";
-  #dccownnick = "%R$*%n";
-  #dccownquerynick = "%W$*%n";
-  #dccownaction = "{action $*}";
-  #dccownaction_target = "{action_core $0}%K:%c$1%n ";
-  #dccmsg = "[%G$1-%K(%g$0%K)%n] ";
-  #dccquerynick = "%G$*%n";
-  #dccaction = "%W (*dcc*) $*%n %|";
-
-  ##
-  ## Statusbar
-  ##
-  sb_background = "%n%0";
-  sbstart = " ";
-  sbend = " ";
-  prompt = "   %c:%n ";
-  sb = "%W$*";
-  sbmode = "";
-  sbaway = " (%Gaway%n)";
-
-  #sb_prompt_bg = "%n";
-  #sb_info_bg = "%8";
-  #sbstart = "";
-  #sbend = " ";
-  #topicsbstart = "{sbstart $*}";
-  #topicsbend = "{sbend $*}";
-  #prompt = "[$*] ";
-  #sb = " %c[%n$*%c]%n";
-  #sbmode = "(%c+%n$*)";
-  #sbaway = " (%GzZzZ%n)";
-  #sbservertag = ":$0 (change with ^X)";
-  #sbnickmode = "$0";
-  #sb_act_sep = "%c$*";
-  #sb_act_text = "%c$*";
-  #sb_act_msg = "%W$*";
-  #sb_act_hilight = "%M$*";
-  #sb_act_hilight_color = "$0$1-%n";
-};
-
-formats = {
-  "fe-common/core" = {
-    own_msg = "{ownmsgnick {ownnick $[-13]0$2}}$1";
-    own_msg_channel = "{ownmsgnick {ownnick $[-13]0$3}{msgchannel $1}}$2";
-    own_msg_private_query = "{ownprivmsgnick {ownprivnick $[-13]2}}$1";
-    pubmsg_me = "{pubmsgmenick {menick $[-13]0}$2}$1";
-    pubmsg_me_channel = "{pubmsgmenick {menick $[-13]0$3}{msgchannel $1}}$2";
-    pubmsg_hilight = "{pubmsghinick $0 $0 $[-13]1$3%n}$2";
-    pubmsg_hilight_channel = "{pubmsghinick $0 $[-13]1$4{msgchannel $2}}$3";
-    pubmsg = "{pubmsgnick {pubnick $[-13]0$2}}$1";
-    pubmsg_channel = "{pubmsgnick {pubnick $[-13]0$2}}$1";
-    msg_private_query = "{privmsgnick $[-13]0}$2";
-  };
-  "fe-common/irc" = {
-    own_action = "{ownaction $[-11]0} $1";
-    action_private = "{pvtaction $[-11]0}$1";
-    action_private_query = "{pvtaction_query $[-11]0} $2";
-    action_public = "{pubaction $[-11]0}$1";
-  };
-};
--- a/irssi/scripts/adv_windowlist.pl	Wed Nov 19 19:08:21 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2478 +0,0 @@
-use strict; # use warnings;
-
-# {{{ debug
-
-#BEGIN {
-#	open STDERR, '>', '/home/ailin/wlstatwarnings';
-#};
-
-# FIXME COULD SOMEONE PLEASE TELL ME HOW TO SHUT UP
-#
-# ...
-# Variable "*" will not stay shared at (eval *) line *.
-# Variable "*" will not stay shared at (eval *) line *.
-# ...
-# Can't locate package Irssi::Nick for @Irssi::Irc::Nick::ISA at (eval *) line *.
-# ...
-#
-# THANKS
-
-# }}}
-
-# if you don't know how to operate folds, type zn
-
-# {{{ header
-
-use Irssi (); # which is the minimum required version of Irssi ?
-use Irssi::TextUI;
-
-use vars qw($VERSION %IRSSI);
-
-$VERSION = '0.6ca';
-%IRSSI = (
-	original_authors => q(BC-bd,        Veli,          Timo Sirainen, ).
-	                    q(Wouter Coekaerts,    Jean-Yves Lefort), # (decadix)
-	original_contact => q([email protected], [email protected], [email protected], ).
-	                    q([email protected], [email protected]),
-	authors          => q(Nei),
-	contact          => q(Nei @ [email protected]),
-	url              =>  "http://anti.teamidiot.de/",
-	name             => q(awl),
-	description      => q(Adds a permanent advanced window list on the right or ).
-	                    q(in a statusbar.),
-	description2     => q(Based on chanact.pl which was apparently based on ).
-	                    q(lightbar.c and nicklist.pl with various other ideas ).
-	                    q(from random scripts.),
-	license          => q(GNU GPLv2 or later),
-);
-
-# }}}
-
-# {{{ *** D O C U M E N T A T I O N ***
-
-# adapted by Nei
-
-###############
-# {{{ original comment
-# ###########
-# # Adds new powerful and customizable [Act: ...] item (chanelnames,modes,alias).
-# # Lets you give alias characters to windows so that you can select those with
-# # meta-<char>.
-# #
-# # for irssi 0.8.2 by [email protected]
-# #
-# # inspired by chanlist.pl by '[email protected]'
-# #
-# #########
-# # {{{ Contributors
-# #########
-# #
-# # [email protected]   /window_alias code
-# # [email protected]  chanact_abbreviate_names
-# # [email protected]      Extra chanact_show_mode and chanact_chop_status
-# # }}}
-# }}}
-# 
-# {{{ FURTHER THANKS TO
-# ############
-# # buu, fxn, Somni, Khisanth, integral, tybalt89   for much support in any aspect perl
-# # and the channel in general ( #perl @ freenode ) and especially the ir_* functions
-# #
-# # Valentin 'senneth' Batz ( [email protected] ) for the pointer to grep.pl, continuous support
-# #                                         and help in digging up ir_strip_codes
-# #
-# # OnetrixNET technology networks for the debian environment
-# #
-# # Monkey-Pirate.com / Spaceman Spiff for the webspace
-# #
-# }}}
-
-######
-# {{{ M A I N    P R O B L E M
-#####
-#
-# It is impossible to place the awl on a statusbar together with other items,
-# because I do not know how to calculate the size that it is going to get
-# granted, and therefore I cannot do the linebreaks properly.
-# This is what is missing to make a nice script out of awl.
-# If you have any ideas, please contact me ASAP :).
-# }}}
-######
-
-######
-# {{{ UTF-8 PROBLEM
-#####
-#
-# Please help me find a solution to this:
-# this be your statusbar, it is using up the maximum term size
-# [[1=1]#abc [2=2]#defghi]
-# 
-# now consider this example:i
-# "ascii" characters are marked with ., utf-8 characters with *
-# [[1=1]#... [2=2]#...***]
-#
-# you should think that this is how it would be displayed? WRONG!
-# [[1=1]#... [2=2]#...***   ]
-#
-# this is what Irssi does.. I believe my length calculating code to be correct,
-# however, I'd love to be proven wrong (or receive any other fix, too, of
-# course!)
-# }}}
-######
-
-#########
-# {{{ USAGE
-###
-#
-# copy the script to ~/.irssi/scripts/
-#
-# In irssi:
-#
-#		/script load awl
-#
-#
-# Hint: to get rid of the old [Act:] display
-#     /statusbar window remove act
-#
-# to get it back:
-#     /statusbar window add -after lag -priority 10 act
-# }}}
-##########
-# {{{ OPTIONS
-########
-#
-# {{{ /set awl_display_nokey <string>
-#     /set awl_display_key <string>
-#     /set awl_display_nokey_active <string>
-#     /set awl_display_key_active <string>
-#     * string : Format String for one window. The following $'s are expanded:
-#         $C : Name
-#         $N : Number of the Window
-#         $Q : meta-Keymap
-#         $H : Start highlighting
-#         $S : Stop highlighting
-#             /+++++++++++++++++++++++++++++++++,
-#            | ****  I M P O R T A N T :  ****  |
-#            |                                  |
-#            | don't forget  to use  $S  if you |
-#            | used $H before!                  |
-#            |                                  |
-#            '+++++++++++++++++++++++++++++++++/
-#       XXX NOTE ON *_active: there is a BUG somewhere in the length
-#       XXX calculation. currently it's best to NOT remove $H/$S from those
-#       XXX settings if you use it in the non-active settings.
-# }}}
-# {{{ /set awl_separator <string>
-#     * string : Charater to use between the channel entries
-#     you'll need to escape " " space and "$" like this:
-#     "/set awl_separator \ "
-#     "/set awl_separator \$"
-#     and {}% like this:
-#     "/set awl_separator %{"
-#     "/set awl_separator %}"
-#     "/set awl_separator %%"
-#     (reason being, that the separator is used inside a {format })
-# }}}
-# {{{ /set awl_prefer_name <ON|OFF>
-#     * this setting decides whether awl will use the active_name (OFF) or the
-#       window name as the name/caption in awl_display_*.
-#       That way you can rename windows using /window name myownname.
-# }}}
-# {{{ /set awl_hide_data <num>
-#     * num : hide the window if its data_level is below num
-#     set it to 0 to basically disable this feature,
-#               1 if you don't want windows without activity to be shown
-#               2 to show only those windows with channel text or hilight
-#               3 to show only windows with hilight
-# }}}
-# {{{ /set awl_maxlines <num>
-#     * num : number of lines to use for the window list (0 to disable, negative
-#       lock)
-# }}}
-# {{{ /set awl_columns <num>
-#     * num : number of columns to use in screen mode (0 for unlimited)
-# }}}
-# {{{ /set awl_block <num>
-#     * num : width of a column in screen mode (negative values = block display)
-#             /+++++++++++++++++++++++++++++++++,
-#            | ******  W A R N I N G !  ******  |
-#            |                                  |
-#            | If  your  block  display  looks  |
-#            | DISTORTED,  you need to add the  |
-#            | following  line to your  .theme  |
-#            | file under                       |
-#            |     abstracts = {             :  |
-#            |                                  |
-#            |       sb_act_none = "%n$*";      |
-#            |                                  |
-#            '+++++++++++++++++++++++++++++++++/
-#.02:08:26. < shi>  Irssi::current_theme()->get_format <.. can this be used?
-# }}}
-# {{{ /set awl_sbar_maxlength <ON|OFF>
-#     * if you enable the maxlength setting, the block width will be used as a
-#       maximum length for the non-block statusbar mode too.
-# }}}
-# {{{ /set awl_height_adjust <num>
-#     * num : how many lines to leave empty in screen mode
-# }}}
-# {{{ /set awl_sort <-data_level|-last_line|refnum>
-#     * you can change the window sort order with this variable
-#         -data_level : sort windows with hilight first
-#         -last_line  : sort windows in order of activity
-#         refnum      : sort windows by window number
-# }}}
-# {{{ /set awl_placement <top|bottom>
-#     /set awl_position <num>
-#     * these settings correspond to /statusbar because awl will create
-#       statusbars for you
-#     (see /help statusbar to learn more)
-# }}}
-# {{{ /set awl_all_disable <ON|OFF>
-#     * if you set awl_all_disable to ON, awl will also remove the
-#       last statusbar it created if it is empty.
-#       As you might guess, this only makes sense with awl_hide_data > 0 ;)
-# }}}
-# {{{ /set awl_automode <sbar|screen|emulate_lightbar>
-#     * this setting defines whether the window list is shown in statusbars or
-#       whether the screen hack is used (from nicklist.pl)
-# }}}
-# }}}
-##########
-# {{{ COMMANDS
-########
-# {{{ /awl paste <ON|OFF|TOGGLE>
-#     * enables or disables the screen hack windowlist. This is useful when you
-#       want to mark & copy text that you want to paste somewhere (hence the
-#       name). (ON means AWL disabled!)
-#       This is nicely bound to a function key for example.
-# }}}
-# {{{ /awl redraw
-#     * redraws the screen hack windowlist. There are many occasions where the
-#       screen hack windowlist can get destroyed so you can use this command to
-#       fix it.
-# }}}
-# }}}
-###
-# {{{ WISHES
-####
-#
-# if you fiddle with my mess, provide me with your fixes so I can benefit as well
-#
-# Nei =^.^= ( [email protected] )
-# }}}
-
-# }}}
-
-# {{{ modules
-
-#use Class::Classless;
-#use Term::Info;
-
-# }}}
-
-# {{{ global variables
-
-my $replaces = '[=]'; # AARGH!!! (chars that are always surrounded by weird
-                      # colour codes by Irssi)
-
-my $actString = [];   # statusbar texts
-my $currentLines = 0;
-my $resetNeeded;      # layout/screen has changed, redo everything
-my $needRemake;       # "normal" changes
-#my $callcount = 0;
-sub GLOB_QUEUE_TIMER () { 100 }
-my $globTime = undef; # timer to limit remake() calls
-
-
-my $SCREEN_MODE;
-my $DISABLE_SCREEN_TEMP;
-my $currentColumns = 0;
-my $screenResizing;
-my ($screenHeight, $screenWidth);
-my $screenansi = bless {
-	NAME => 'Screen::ANSI',
-	PARENTS => [],
-	METHODS => {
-		dcs   => sub { "\033P" },
-		st    => sub { "\033\\"},
-	}
-}, 'Class::Classless::X';
-#my $terminfo = new Term::Info 'xterm'; # xterm here, make this modular
-# {{{{{{{{{{{{{{{
-my $terminfo = bless { # xterm here, make this modular
-	NAME => 'Term::Info::xterm',
-	PARENTS => [],
-	METHODS => {
- # 	civis=\E[?25l,
-		civis => sub { "\033[?25l" },
- # 	sc=\E7,
-		sc    => sub { "\0337" },
- # 	cup=\E[%i%p1%d;%p2%dH,
-		cup   => sub { shift;shift; "\033[" . ($_[0] + 1) . ';' . ($_[1] + 1) . 'H' },
- # 	el=\E[K,
-		el    => sub { "\033[K" },
- # 	rc=\E8,
-		rc    => sub { "\0338" },
- # 	cnorm=\E[?25h,
-		cnorm => sub { "\033[?25h" },
- # 	setab=\E[4%p1%dm,
-		setab => sub { shift;shift; "\033[4" . $_[0] . 'm' },
- # 	setaf=\E[3%p1%dm,
-		setaf => sub { shift;shift; "\033[3" . $_[0] . 'm' },
- # 	bold=\E[1m,
-		bold  => sub { "\033[1m" },
- # 	blink=\E[5m,
-		blink => sub { "\033[5m" },
- # 	rev=\E[7m,
-		rev   => sub { "\033[7m" },
- # 	op=\E[39;49m,
-		op    => sub { "\033[39;49m" },
-	}
-}, 'Class::Classless::X';
-# }}}}}}}}}}}}}}}
-
-
-sub setc () {
-	$IRSSI{'name'}
-}
-sub set ($) {
-	setc . '_' . shift
-}
-
-# }}}
-
-
-# {{{ sbar mode
-
-my %statusbars;       # currently active statusbars
-
-# maybe I should just tie the array ?
-sub add_statusbar {
-	for (@_) {
-		# add subs
-		for my $l ($_) { {
-			no strict 'refs'; # :P
-			*{set$l} = sub { awl($l, @_) };
-		}; }
-		Irssi::command('statusbar ' . (set$_) . ' reset');
-		Irssi::command('statusbar ' . (set$_) . ' enable');
-		if (lc Irssi::settings_get_str(set 'placement') eq 'top') {
-			Irssi::command('statusbar ' . (set$_) . ' placement top');
-		}
-		if ((my $x = int Irssi::settings_get_int(set 'position')) != 0) {
-			Irssi::command('statusbar ' . (set$_) . ' position ' . $x);
-		}
-		Irssi::command('statusbar ' . (set$_) . ' add -priority 100 -alignment left barstart');
-		Irssi::command('statusbar ' . (set$_) . ' add ' . (set$_));
-		Irssi::command('statusbar ' . (set$_) . ' add -priority 100 -alignment right barend');
-		Irssi::command('statusbar ' . (set$_) . ' disable');
-		Irssi::statusbar_item_register(set$_, '$0', set$_);
-		$statusbars{$_} = {};
-	}
-}
-
-sub remove_statusbar {
-	for (@_) {
-		Irssi::command('statusbar ' . (set$_) . ' reset');
-		Irssi::statusbar_item_unregister(set$_); # XXX does this actually work ?
-		# DO NOT REMOVE the sub before you have unregistered it :))
-		for my $l ($_) { {
-			no strict 'refs';
-			undef &{set$l};
-		}; }
-		delete $statusbars{$_};
-	}
-}
-
-sub syncLines {
-	my $temp = $currentLines;
-	$currentLines = @$actString;
-	#Irssi::print("current lines: $temp new lines: $currentLines");
-	my $currMaxLines = Irssi::settings_get_int(set 'maxlines');
-	if ($currMaxLines > 0 and @$actString > $currMaxLines) {
-		$currentLines = $currMaxLines;
-	}
-	elsif ($currMaxLines < 0) {
-		$currentLines = abs($currMaxLines);
-	}
-	return if ($temp == $currentLines);
-	if ($currentLines > $temp) {
-		for ($temp .. ($currentLines - 1)) {
-			add_statusbar($_);
-			Irssi::command('statusbar ' . (set$_) . ' enable');
-		}
-	}
-	else {
-		for ($_ = ($temp - 1); $_ >= $currentLines; $_--) {
-			Irssi::command('statusbar ' . (set$_) . ' disable');
-			remove_statusbar($_);
-		}
-	}
-}
-
-# FIXME implement $get_size_only check, and user $item->{min|max-size} ??
-sub awl {
-	my ($line, $item, $get_size_only) = @_;
-
-	if ($needRemake) {
-		$needRemake = undef;
-		remake();
-	}
-
-	my $text = $actString->[$line];  # DO NOT set the actual $actString->[$line] to '' here or
-	$text = '' unless defined $text; # you'll screw up the statusbar counter ($currentLines)
-	$item->default_handler($get_size_only, $text, '', 1);
-}
-
-# remove old statusbars
-my %killBar;
-sub get_old_status {
-	my ($textDest, $cont, $cont_stripped) = @_;
-	if ($textDest->{'level'} == 524288 and $textDest->{'target'} eq ''
-			and !defined($textDest->{'server'})
-	) {
-		my $name = quotemeta(set '');
-		if ($cont_stripped =~ m/^$name(\d+)\s/) { $killBar{$1} = {}; }
-		Irssi::signal_stop();
-	}
-}
-sub killOldStatus {
-	%killBar = ();
-	Irssi::signal_add_first('print text' => 'get_old_status');
-	Irssi::command('statusbar');
-	Irssi::signal_remove('print text' => 'get_old_status');
-	remove_statusbar(keys %killBar);
-}
-#killOldStatus();
-
-# end sbar mode }}}
-
-
-# {{{ keymaps
-
-my %keymap;
-
-sub get_keymap {
-	my ($textDest, undef, $cont_stripped) = @_;
-	if ($textDest->{'level'} == 524288 and $textDest->{'target'} eq ''
-			and !defined($textDest->{'server'})
-	) {
-		if ($cont_stripped =~ m/((?:meta-)+)(.)\s+change_window (\d+)/) {
-			my ($level, $key, $window) = ($1, $2, $3);
-			my $numlevel = ($level =~ y/-//) - 1;
-			$keymap{$window} = ('-' x $numlevel) . "$key";
-		}
-		Irssi::signal_stop();
-	}
-}
-
-sub update_keymap {
-	%keymap = ();
-	Irssi::signal_remove('command bind' => 'watch_keymap');
-	Irssi::signal_add_first('print text' => 'get_keymap');
-	Irssi::command('bind'); # stolen from grep
-	Irssi::signal_remove('print text' => 'get_keymap');
-	Irssi::signal_add('command bind' => 'watch_keymap');
-	Irssi::timeout_add_once(100, 'eventChanged', undef);
-}
-
-# watch keymap changes
-sub watch_keymap {
-	Irssi::timeout_add_once(1000, 'update_keymap', undef);
-}
-
-update_keymap();
-
-# end keymaps }}}
-
-# {{{ format handling
-
-# a bad way do do expansions but who cares
-sub expand {
-	my ($string, %format) = @_;
-	my ($exp, $repl);
-	$string =~ s/\$$exp/$repl/g while (($exp, $repl) = each(%format));
-	return $string;
-}
-
-my %strip_table = (
-	# fe-common::core::formats.c:format_expand_styles
-	#      delete                format_backs  format_fores bold_fores   other stuff
-	(map { $_ => '' } (split //, '04261537' .  'kbgcrmyw' . 'KBGCRMYW' . 'U9_8:|FnN>#[')),
-	#      escape
-	(map { $_ => $_ } (split //, '{}%')),
-);
-sub ir_strip_codes { # strip %codes
-	my $o = shift;
-	$o =~ s/(%(.))/exists $strip_table{$2} ? $strip_table{$2} : $1/gex;
-	$o
-}
-
-sub ir_parse_special {
-	my $o; my $i = shift;
-	#if ($_[0]) { # for the future?!?
-	#	eval {
-	#		$o = $_[0]->parse_special($i);
-	#	};
-	#	unless ($@) {
-	#		return $o;
-	#	}
-	#}
-	my $win = shift || Irssi::active_win();
-	my $server = Irssi::active_server();
-	if (ref $win and ref $win->{'active'}) {
-		$o = $win->{'active'}->parse_special($i);
-	}
-	elsif (ref $win and ref $win->{'active_server'}) {
-		$o = $win->{'active_server'}->parse_special($i);
-	}
-	elsif (ref $server) {
-		$o =  $server->parse_special($i);
-	}
-	else {
-		$o = Irssi::parse_special($i);
-	}
-	$o
-}
-sub ir_parse_special_protected {
-	my $o; my $i = shift;
-	$i =~ s/
-		( \\. ) | # skip over escapes (maybe)
-		( \$[^% $\]+ ) # catch special variables
-	/
-		if ($1) { $1 }
-		elsif ($2) { my $i2 = $2; ir_fe(ir_parse_special($i2, @_)) }
-		else { $& }
-	/gex;
-	$i
-}
-
-
-sub sb_ctfe { # Irssi::current_theme->format_expand wrapper
-	Irssi::current_theme->format_expand(
-		shift,
-		(
-			Irssi::EXPAND_FLAG_IGNORE_REPLACES
-				|
-			($_[0]?0:Irssi::EXPAND_FLAG_IGNORE_EMPTY)
-		)
-	)
-}
-sub sb_expand { # expand {format }s (and apply parse_special for $vars)
-	ir_parse_special(
-		sb_ctfe(shift)
-	)
-}
-sub sb_strip {
-	ir_strip_codes(
-		sb_expand(shift)
-	); # does this get us the actual length of that s*ty bar :P ?
-}
-sub sb_length {
-	# unicode cludge, d*mn broken Irssi
-	# screw it, this will fail from broken joining anyway (and cause warnings)
-	my $term_type = 'term_type';
-	if (Irssi::version > 20040819) { # this is probably wrong, but I don't know
-		                              # when the setting name got changed
-		$term_type = 'term_charset';
-	}
-	#if (lc Irssi::settings_get_str($term_type) eq '8bit'
-	#		or Irssi::settings_get_str($term_type) =~ /^iso/i
-	#) {
-	#	length(sb_strip(shift))
-	#}
-	#else {
-	my $temp = sb_strip(shift);
-	# try to get the displayed width
-	my $length;
-	eval {
-		require Text::CharWidth;
-		$length = Text::CharWidth::mbswidth($temp);
-	};
-	unless ($@) {
-		return $length;
-	}
-	else {
-		if (lc Irssi::settings_get_str($term_type) eq 'utf-8') {
-			# try to switch on utf8
-			eval {
-				no warnings;
-				require Encode;
-				#$temp = Encode::decode_utf8($temp); # thanks for the hint, but I have my
-				#                                    # reasons for _utf8_on
-				Encode::_utf8_on($temp);
-			};
-		}
-		# there is nothing more I can do
-		length($temp)
-	}
-	#}
-}
-
-# !!! G*DD*MN Irssi is adding an additional layer of backslashitis per { } layer
-# !!! AND I still don't know what I need to escape.
-# !!! and NOONE else seems to know or care either.
-# !!! f*ck open source. I mean it.
-# XXX any Irssi::print debug statement leads to SEGFAULT - why ?
-
-# major parts of the idea by buu (#perl @ freenode)
-# thanks to fxn and Somni for debugging
-#	while ($_[0] =~ /(.)/g) {
-#		my $c = $1; # XXX sooo... goto kills $1
-#		if ($q eq '%') { goto ESC; }
-
-## <freenode:#perl:tybalt89> s/%(.)|(\{)|(\})|(\\|\$)/$1?$1:$2?($level++,$2):$3?($level>$min_level&&$level--,$3):'\\'x(2**$level-1).$4/ge;  # untested...
-sub ir_escape {
-	my $min_level = $_[1] || 0; my $level = $min_level;
-	my $o = shift;
-	$o =~ s/
-		(	%.	)	| # $1
-		(	\{	)	| # $2
-		(	\}	)	| # $3
-		(	\\	)	| # $4
-		(	\$(?=[^\\])	)	| # $5
-		(	\$	) # $6
-	/
-		if ($1) { $1 } # %. escape
-		elsif ($2) { $level++; $2 } # { nesting start
-		elsif ($3) { if ($level > $min_level) { $level--; } $3 } # } nesting end
-		elsif ($4) { '\\'x(2**$level) } # \ needs \\escaping
-		elsif ($5) { '\\'x(2**$level-1) . '$' . '\\'x(2**$level-1) } # and $ needs even more because of "parse_special"
-		else { '\\'x(2**$level-1) . '$' } # $ needs \$ escaping
-	/gex;
-	$o
-}
-#sub ir_escape {
-#	my $min_level = $_[1] || 0; my $level = $min_level;
-#	my $o = shift;
-#	$o =~ s/
-#		(	%.	)	| # $1
-#		(	\{	)	| # $2
-#		(	\}	)	| # $3
-#		(	\\	|	\$	)	# $4
-#	/
-#		if ($1) { $1 } # %. escape
-#		elsif ($2) { $level++; $2 } # { nesting start
-#		elsif ($3) { if ($level > $min_level) { $level--; } $3 } # } nesting end
-#		else { '\\'x(2**($level-1)-1) . $4 } # \ or $ needs \\escaping
-#	/gex;
-#	$o
-#}
-
-sub ir_fe { # try to fix format stuff
-	my $x = shift;
-	# XXX why do I have to use two/four % here instead of one/two ??
-	# answer: you screwed up in ir_escape
-	$x =~ s/([%{}])/%$1/g;
-	#$x =~ s/(\\|\$|[ ])/\\$1/g; # XXX HOW CAN I HANDLE THE SPACES CORRECTLY XXX
-	$x =~ s/(\\|\$)/\\$1/g;
-	#$x =~ s/(\$(?=.))|(\$)/$1?"\\\$\\":"\\\$"/ge; # I think this should be here
-	#                                              # (logic), but it doesn't work
-	#                                              # that way :P
-	#$x =~ s/\\/\\\\/g; # that's right, escape escapes
-	$x
-}
-sub ir_ve { # escapes special vars but leave colours alone
-	my $x = shift;
-	#$x =~ s/([%{}])/%$1/g;
-	$x =~ s/(\\|\$|[ ])/\\$1/g;
-	$x
-}
-
-my %ansi_table;
-{
-	my ($i, $j, $k) = (0, 0, 0);
-	%ansi_table = (
-		# fe-common::core::formats.c:format_expand_styles
-		#      do                                              format_backs
-		(map { $_ => $terminfo->setab($i++) } (split //, '01234567' )),
-		#      do                                              format_fores
-		(map { $_ => $terminfo->setaf($j++) } (split //, 'krgybmcw' )),
-		#      do                                              bold_fores
-		(map { $_ => $terminfo->bold() .
-		             $terminfo->setaf($k++) } (split //, 'KRGYBMCW')),
-		# reset
-		#(map { $_ => $terminfo->op() } (split //, 'nN')),
-		(map { $_ => $terminfo->op() } (split //, 'n')),
-		(map { $_ => "\033[0m" } (split //, 'N')), # XXX quick and DIRTY
-		# flash/bright
-		F => $terminfo->blink(),
-		# reverse
-		8 => $terminfo->rev(),
-		# bold
-		(map { $_ => $terminfo->bold() } (split //, '9_')),
-		#      delete                other stuff
-		(map { $_ => '' } (split //, ':|>#[')),
-		#      escape
-		(map { $_ => $_ } (split //, '{}%')),
-	)
-}
-sub formats_to_ansi_basic {
-	my $o = shift;
-	$o =~ s/(%(.))/exists $ansi_table{$2} ? $ansi_table{$2} : $1/gex;
-	$o
-}
-
-sub lc1459 ($) { my $x = shift; $x =~ y/A-Z][\^/a-z}{|~/; $x }
-Irssi::settings_add_str(setc, 'banned_channels', '');
-Irssi::settings_add_bool(setc, 'banned_channels_on', 0);
-my %banned_channels = map { lc1459($_) => undef }
-split ' ', Irssi::settings_get_str('banned_channels');
-Irssi::settings_add_str(setc, 'fancy_abbrev', 'fancy');
-
-# }}}
-
-# {{{ main
-
-sub remake () {
-	#$callcount++;
-	#my $xx = $callcount; Irssi::print("starting remake [ $xx ]");
-	my ($hilight, $number, $display);
-	my $separator = '{sb_act_sep ' . Irssi::settings_get_str(set 'separator') .
-		'}';
-	my $custSort = Irssi::settings_get_str(set 'sort');
-	my $custSortDir = 1;
-	if ($custSort =~ /^[-!](.*)/) {
-		$custSortDir = -1;
-		$custSort = $1;
-	}
-
-	my @wins = 
-		sort {
-			(
-				( (int($a->{$custSort}) <=> int($b->{$custSort})) * $custSortDir )
-					||
-				($a->{'refnum'} <=> $b->{'refnum'})
-			)
-		} Irssi::windows;
-	my $block = Irssi::settings_get_int(set 'block');
-	my $columns = $currentColumns;
-	my $oldActString = $actString if $SCREEN_MODE;
-	$actString = $SCREEN_MODE ? ['   A W L'] : [];
-	my $line = $SCREEN_MODE ? 1 : 0;
-	my $width = $SCREEN_MODE
-			?
-		$screenWidth - abs($block)*$columns + 1
-			:
-		([Irssi::windows]->[0]{'width'} - sb_length('{sb x}'));
-	my $height = $screenHeight - abs(Irssi::settings_get_int(set
-			'height_adjust'));
-	my ($numPad, $keyPad) = (0, 0);
-	my %abbrevList;
-	if ($SCREEN_MODE or Irssi::settings_get_bool(set 'sbar_maxlength')
-			or ($block < 0)
-	) {
-		%abbrevList = ();
-		if (Irssi::settings_get_str('fancy_abbrev') !~ /^(no|off|head)/i) {
-			my @nameList = map { ref $_ ? $_->get_active_name : '' } @wins;
-			for (my $i = 0; $i < @nameList - 1; ++$i) {
-				my ($x, $y) = ($nameList[$i], $nameList[$i + 1]);
-				for ($x, $y) { s/^[+#!=]// }
-				my $res = Algorithm::LCSS::LCSS($x, $y);
-				if (defined $res) {
-					#Irssi::print("common pattern $x $y : $res");
-					#Irssi::print("found at $nameList[$i] ".index($nameList[$i],
-					#		$res));
-					$abbrevList{$nameList[$i]} = int (index($nameList[$i], $res) +
-						(length($res) / 2));
-					#Irssi::print("found at ".$nameList[$i+1]." ".index($nameList[$i+1],
-					#		$res));
-					$abbrevList{$nameList[$i+1]} = int (index($nameList[$i+1], $res) +
-						(length($res) / 2));
-				}
-			}
-		}
-		if ($SCREEN_MODE or ($block < 0)) {
-			$numPad = length((sort { length($b) <=> length($a) } keys %keymap)[0]);
-			$keyPad = length((sort { length($b) <=> length($a) } values %keymap)[0]);
-		}
-	}
-	if ($SCREEN_MODE) {
-		print STDERR $screenansi->dcs().
-		             $terminfo->civis().
-						 $terminfo->sc().
-						 $screenansi->st();
-		if (@$oldActString < 1) {
-			print STDERR $screenansi->dcs().
-							 $terminfo->cup(0, $width).
-			             $actString->[0].
-							 $terminfo->el().
-			             $screenansi->st();
-		}
-	}
-	foreach my $win (@wins) {
-		unless ($SCREEN_MODE) {
-			$actString->[$line] = '' unless defined $actString->[$line]
-					or Irssi::settings_get_bool(set 'all_disable');
-		}
-
-		# all stolen from chanact, what does this code do and why do we need it ?
-		!ref($win) && next;
-
-		my $name = $win->get_active_name;
-		$name = '*' if (Irssi::settings_get_bool('banned_channels_on') and exists
-			$banned_channels{lc1459($name)});
-		$name = $win->{'name'} if $name ne '*' and $win->{'name'} ne ''
-			and Irssi::settings_get_bool(set 'prefer_name');
-		my $active = $win->{'active'};
-		my $colour = $win->{'hilight_color'};
-		if (!defined $colour) { $colour = ''; }
-
-		if ($win->{'data_level'} < Irssi::settings_get_int(set 'hide_data')) {
-			next; } # for Geert
-		if    ($win->{'data_level'} == 0) { $hilight = '{sb_act_none '; }
-		elsif ($win->{'data_level'} == 1) { $hilight = '{sb_act_text '; }
-		elsif ($win->{'data_level'} == 2) { $hilight = '{sb_act_msg '; }
-		elsif ($colour             ne '') { $hilight = "{sb_act_hilight_color $colour "; }
-		elsif ($win->{'data_level'} == 3) { $hilight = '{sb_act_hilight '; }
-		else                              { $hilight = '{sb_act_special '; }
-
-		$number = $win->{'refnum'};
-		my @display = ('display_nokey');
-		if (defined $keymap{$number} and $keymap{$number} ne '') {
-			unshift @display, map { (my $cpy = $_) =~ s/_no/_/; $cpy } @display;
-		}
-		if (Irssi::active_win->{'refnum'} == $number) {
-			unshift @display, map { my $cpy = $_; $cpy .= '_active'; $cpy } @display;
-		}
-		#Irssi::print("win $number [@display]: " . join '.', split //, join '<<', map {
-			#		Irssi::settings_get_str(set $_) } @display);
-		$display = (grep { $_ }
-			map { Irssi::settings_get_str(set $_) }
-			@display)[0];
-			#Irssi::print("win $number : " . join '.', split //, $display);
-
-		if ($SCREEN_MODE or Irssi::settings_get_bool(set 'sbar_maxlength')
-				or ($block < 0)
-		) {
-			my $baseLength = sb_length(ir_escape(ir_ve(ir_parse_special_protected(sb_ctfe(
-				'{sb_background}' . expand($display,
-				C => ir_fe('x'),
-				N => $number . (' 'x($numPad - length($number))),
-				Q => ir_fe((' 'x($keyPad - length($keymap{$number}))) . $keymap{$number}),
-				H => $hilight,
-				S => '}{sb_background}'
-			), 1), $win)))) - 1;
-			my $diff = abs($block) - (length($name) + $baseLength);
-			if ($diff < 0) { # too long
-				if (abs($diff) >= length($name)) { $name = '' } # forget it
-				elsif (abs($diff) + 1 >= length($name)) { $name = substr($name,
-						0, 1); }
-				else {
-					my $middle = exists $abbrevList{$name} ?
-					(($abbrevList{$name} + (2*(length($name) / 2)))/3) :
-						((Irssi::settings_get_str('fancy_abbrev') =~ /^head/i) ?
-								length($name) :
-						(length($name) / 2));
-					my $cut = int($middle - (abs($diff) / 2) + .55); 
-					$cut = 1 if $cut < 1;
-					$cut = length($name) - abs($diff) - 1 if $cut > (length($name) -
-						abs($diff) - 1);
-					$name = substr($name, 0, $cut) . '~' . substr($name, $cut +
-						abs($diff) + 1);
-				}
-			}
-			elsif ($SCREEN_MODE or ($block < 0)) {
-				$name .= (' ' x $diff);
-			}
-		}
-
-		my $add = ir_ve(ir_parse_special_protected(sb_ctfe('{sb_background}' . expand($display,
-			C => ir_fe($name),
-			N => $number . (' 'x($numPad - length($number))),
-			Q => ir_fe((' 'x($keyPad - length($keymap{$number}))) . $keymap{$number}),
-			H => $hilight,
-			S => '}{sb_background}'
-		), 1), $win));
-		if ($SCREEN_MODE) {
-			$actString->[$line] = $add;
-			if ((!defined $oldActString->[$line]
-					or $oldActString->[$line] ne $actString->[$line])
-					and
-				$line <= ($columns * $height)
-			) {
-				print STDERR $screenansi->dcs().
-								 $terminfo->cup(($line-1) % $height+1, $width + (
-									 abs($block) * int(($line-1) / $height))).
-				formats_to_ansi_basic(sb_expand(ir_escape($actString->[$line]))).
-								#$terminfo->el().
-								 $screenansi->st();
-			}
-			$line++;
-		}
-		else {
-			#$temp =~ s/\{\S+?(?:\s(.*?))?\}/$1/g;
-			#$temp =~ s/\\\\\\\\/\\/g; # XXX I'm actually guessing here, someone point me
-			#                          # XXX to docs please
-			$actString->[$line] = '' unless defined $actString->[$line];
-
-			# XXX how can I check whether the content still fits in the bar? this would
-			# XXX allow awlstatus to reside on a statusbar together with other items...
-			if (sb_length(ir_escape($actString->[$line] . $add)) >= $width) {
-				# XXX doesn't correctly handle utf-8 multibyte ... help !!?
-				$actString->[$line] .= ' ' x ($width - sb_length(ir_escape(
-					$actString->[$line])));
-				$line++;
-			}
-			$actString->[$line] .= $add . $separator;
-			# XXX if I use these prints, output layout gets screwed up... why ?
-			#Irssi::print("line $line: ".$actString->[$line]);
-			#Irssi::print("temp $line: ".$temp);
-		}
-	}
-
-	if ($SCREEN_MODE) {
-		while ($line <= ($columns * $height)) {
-			print STDERR $screenansi->dcs().
-							 $terminfo->cup(($line-1) % $height+1, $width + (
-								 abs($block) * int(($line-1) / $height))).
-							 $terminfo->el().
-							 $screenansi->st();
-			$line++;
-		}
-		print STDERR $screenansi->dcs().
-						 $terminfo->rc().
-		             $terminfo->cnorm().
-						 $screenansi->st();
-	}
-	else {
-		# XXX the Irssi::print statements lead to the MOST WEIRD results
-		# e.g.: the loop gets executed TWICE for p > 0 ?!?
-		for (my $p = 0; $p < @$actString; $p++) { # wrap each line in {sb }, escape it
-			my $x = $actString->[$p];              # properly, etc.
-			$x =~ s/\Q$separator\E([ ]*)$/$1/;
-			#Irssi::print("[$p]".'current:'.join'.',split//,sb_strip(ir_escape($x,0)));
-			#Irssi::print("assumed length before:".sb_length(ir_escape($x,0)));
-			$x = "{sb $x}";
-			#Irssi::print("[$p]".'new:'.join'.',split//,sb_expand(ir_escape($x,0)));
-			#Irssi::print("[$p]".'new:'.join'.',split//,ir_escape($x,0));
-			#Irssi::print("assumed length after:".sb_length(ir_escape($x,0)));
-			$x = ir_escape($x);
-			#Irssi::print("[$p]".'REALnew:'.join'.',split//,sb_strip($x));
-			$actString->[$p] = $x;
-			# XXX any Irssi::print debug statement leads to SEGFAULT (sometimes) - why ?
-		}
-	}
-	#Irssi::print("remake [ $xx ] finished");
-}
-
-sub awlHasChanged () {
-	$globTime = undef;
-	my $temp = ($SCREEN_MODE ?
-		"\\\n" . Irssi::settings_get_int(set 'block').
-		Irssi::settings_get_int(set 'height_adjust')
-		: "!\n" . Irssi::settings_get_str(set 'placement').
-		Irssi::settings_get_int(set 'position')).
-		Irssi::settings_get_str(set 'automode');
-	if ($temp ne $resetNeeded) { wlreset(); return; }
-	#Irssi::print("awl has changed, calls to remake so far: $callcount");
-	$needRemake = 1;
-
-	#remake();
-	if (
-		($SCREEN_MODE and !$DISABLE_SCREEN_TEMP)
-			or
-		($needRemake and Irssi::settings_get_bool(set 'all_disable'))
-			or
-		(!Irssi::settings_get_bool(set 'all_disable') and $currentLines < 1)
-	) {
-		$needRemake = undef;
-		remake();
-	}
-
-	unless ($SCREEN_MODE) {
-		# XXX Irssi crashes if I try to do this without timer, why ? What's the minimum
-		# XXX delay I need to use in the timer ?
-		Irssi::timeout_add_once(100, 'syncLines', undef);
-
-		for (keys %statusbars) {
-			Irssi::statusbar_items_redraw(set$_);
-		}
-	}
-	else {
-		Irssi::timeout_add_once(100, 'syncColumns', undef);
-	}
-}
-
-sub eventChanged () { # Implement a change queue/blocker -.-)
-	if (defined $globTime) {
-		Irssi::timeout_remove($globTime);
-	} # delay the update further
-	$globTime = Irssi::timeout_add_once(GLOB_QUEUE_TIMER, 'awlHasChanged', undef);
-}
-
-# }}}
-
-
-# {{{ screen mode
-
-sub screenFullRedraw {
-	my ($window) = @_;
-	if (!ref $window or $window->{'refnum'} == Irssi::active_win->{'refnum'}) {
-		$actString = [];
-		eventChanged();
-	}
-}
-
-sub screenSize { # from nicklist.pl
-	$screenResizing = 1;
-	# fit screen
-	system 'screen -x '.$ENV{'STY'}.' -X fit';
-	# get size
-	my ($row, $col) = split ' ', `stty size`;
-	# set screen width
-	$screenWidth = $col-1;
-	$screenHeight = $row-1;
-	
-	# on some recent systems, "screen -X fit; screen -X width -w 50" doesn't work, needs a sleep in between the 2 commands
-	# so we wait a second before setting the width
-	Irssi::timeout_add_once(100, sub {
-		my ($new_irssi_width) = @_;
-		$new_irssi_width -= abs(Irssi::settings_get_int(set
-				'block'))*$currentColumns - 1;
-		system 'screen -x '.$ENV{'STY'}.' -X width -w ' . $new_irssi_width;
-		# and then we wait another second for the resizing, and then redraw.
-		Irssi::timeout_add_once(10,sub {$screenResizing = 0; screenFullRedraw()}, []);
-	}, $screenWidth);
-}
-
-sub screenOff {
-	my ($unloadMode) = @_;
-	Irssi::signal_remove('gui print text finished' => 'screenFullRedraw');
-	Irssi::signal_remove('gui page scrolled' => 'screenFullRedraw');
-	Irssi::signal_remove('window changed' => 'screenFullRedraw');
-	Irssi::signal_remove('window changed automatic' => 'screenFullRedraw');
-	if ($unloadMode) {
-		Irssi::signal_remove('terminal resized' => 'resizeTerm');
-	}
-	system 'screen -x '.$ENV{'STY'}.' -X fit';
-}
-
-sub syncColumns {
-	return if (@$actString == 0);
-	my $temp = $currentColumns;
-	#Irssi::print("current columns $temp");
-	my $height = $screenHeight - abs(Irssi::settings_get_int(set
-			'height_adjust'));
-	$currentColumns = int(($#$actString-1) / $height) + 1;
-	#Irssi::print("objects in actstring:".scalar(@$actString).", screen height:".
-	#	$height);
-	my $currMaxColumns = Irssi::settings_get_int(set 'columns');
-	if ($currMaxColumns > 0 and $currentColumns > $currMaxColumns) {
-		$currentColumns = $currMaxColumns;
-	}
-	elsif ($currMaxColumns < 0) {
-		$currentColumns = abs($currMaxColumns);
-	}
-	return if ($temp == $currentColumns);
-	screenSize();
-}
-
-#$needRemake = 1;
-sub resizeTerm () {
-	if ($SCREEN_MODE and !$screenResizing) {
-		$screenResizing = 1;
-		Irssi::timeout_add_once(10, 'screenSize', undef);
-	}
-	Irssi::timeout_add_once(100, 'eventChanged', undef);
-}
-
-# }}}
-
-
-# {{{ settings add
-
-Irssi::settings_add_str(setc, set 'display_nokey', '[$N]$H$C$S');
-Irssi::settings_add_str(setc, set 'display_key', '[$Q=$N]$H$C$S');
-Irssi::settings_add_str(setc, set 'display_nokey_active', '');
-Irssi::settings_add_str(setc, set 'display_key_active', '');
-Irssi::settings_add_str(setc, set 'separator', "\\ ");
-Irssi::settings_add_bool(setc, set 'prefer_name', 0);
-Irssi::settings_add_int(setc, set 'hide_data', 0);
-Irssi::settings_add_int(setc, set 'maxlines', 9);
-Irssi::settings_add_int(setc, set 'columns', 1);
-Irssi::settings_add_int(setc, set 'block', 20);
-Irssi::settings_add_bool(setc, set 'sbar_maxlength', 0);
-Irssi::settings_add_int(setc, set 'height_adjust', 2);
-Irssi::settings_add_str(setc, set 'sort', 'refnum');
-Irssi::settings_add_str(setc, set 'placement', 'bottom');
-Irssi::settings_add_int(setc, set 'position', 0);
-Irssi::settings_add_bool(setc, set 'all_disable', 0);
-Irssi::settings_add_str(setc, set 'automode', 'sbar');
-
-# }}}
-
-
-# {{{ init
-
-sub wlreset {
-	$actString = [];
-	$currentLines = 0; # 1; # mhmmmm .. we actually enable one line down there so
-	                        # let's try this.
-	#update_keymap();
-	killOldStatus();
-	# Register statusbar
-	#add_statusbar(0);
-	#Irssi::command('statusbar wl0 enable');
-	my $was_screen_mode = $SCREEN_MODE;
-	if ($SCREEN_MODE = (Irssi::settings_get_str(set 'automode') =~ /screen/i)
-			and
-		!$was_screen_mode
-	) {
-		if (!defined $ENV{'STY'}) {
-			Irssi::print('Screen mode can only be used in GNU screen but no '.
-				'screen was found.', MSGLEVEL_CLIENTERROR);
-			$SCREEN_MODE = undef;
-		}
-		else {
-			Irssi::signal_add_last('gui print text finished' => 'screenFullRedraw');
-			Irssi::signal_add_last('gui page scrolled' => 'screenFullRedraw');
-			Irssi::signal_add('window changed' => 'screenFullRedraw');
-			Irssi::signal_add('window changed automatic' => 'screenFullRedraw');
-		}
-	}
-	elsif ($was_screen_mode and !$SCREEN_MODE) {
-		screenOff();
-	}
-	$resetNeeded = ($SCREEN_MODE ?
-		"\\\n" . Irssi::settings_get_int(set 'block').
-		Irssi::settings_get_int(set 'height_adjust')
-		: "!\n" . Irssi::settings_get_str(set 'placement').
-		Irssi::settings_get_int(set 'position')).
-		Irssi::settings_get_str(set 'automode');
-	resizeTerm();
-}
-
-wlreset();
-
-# }}}
-
-
-# {{{ unload/deinit
-
-my $Unload;
-sub unload ($$$) {
-	$Unload = 1;
-	# pretend we didn't do anything ASAP
-	Irssi::timeout_add_once(10, sub { $Unload = undef; }, undef);
-}
-# last try to catch a sigsegv
-Irssi::signal_add_first('gui exit' => sub { $Unload = undef; });
-sub UNLOAD {
-	# this might well crash Irssi... try /eval /script unload someotherscript ;
-	# /quit (= SEGFAULT !)
-	if ($Unload) {
-		$actString = ['']; # syncLines(); # XXX Irssi crashes when trying to disable
-		killOldStatus();                  # XXX all statusbars ?
-		if ($SCREEN_MODE) {
-			screenOff('unload mode');
-		}
-	}
-}
-
-# }}}
-
-
-# {{{ signals
-
-sub addPrintTextHook { # update on print text
-	return if $_[0]->{'level'} == 262144 and $_[0]->{'target'} eq ''
-			and !defined($_[0]->{'server'});
-	if (Irssi::settings_get_str(set 'sort') =~ /^[-!]?last_line$/) {
-		Irssi::timeout_add_once(100, 'eventChanged', undef);
-	}
-}
-
-#sub _x { my ($x, $y) = @_; ($x, sub { Irssi::print('-->signal '.$x); eval "$y();"; }) }
-#sub _x { @_ }
-Irssi::signal_add_first(
-	'command script unload' => 'unload'
-);
-Irssi::signal_add_last({
-	'setup changed' => 'eventChanged',
-	'print text' => 'addPrintTextHook',
-	'terminal resized' => 'resizeTerm',
-	'setup reread' => 'wlreset',
-	'window hilight' => 'eventChanged',
-});
-Irssi::signal_add({
-	'window created' => 'eventChanged',
-	'window destroyed' => 'eventChanged',
-	'window name changed' => 'eventChanged',
-	'window refnum changed' => 'eventChanged',
-	'window changed' => 'eventChanged',
-	'window changed automatic' => 'eventChanged',
-});
-
-#Irssi::signal_add('nick mode changed', 'chanactHasChanged'); # relicts
-
-# }}}
-
-# {{{ commands
-
-
-sub runsub {
-	my ($cmd) = @_;
-	sub {
-		my ($data, $server, $item) = @_;
-		Irssi::command_runsub($cmd, $data, $server, $item);
-	};
-}
-Irssi::command_bind( setc() => runsub(setc()) );
-Irssi::command_bind( setc() . ' paste' => runsub(setc() . ' paste') );
-Irssi::command_bind(
-	setc() . ' paste on' => sub {
-		return unless $SCREEN_MODE;
-		my $was_disabled = $DISABLE_SCREEN_TEMP;
-		$DISABLE_SCREEN_TEMP = 1;
-		Irssi::print('Paste mode is now ON, '.uc(setc()).' is temporarily '.
-		             'disabled.');
-		if (!$was_disabled) {
-			$screenResizing = 1;
-			screenOff();
-		}
-	}
-);
-Irssi::command_bind(
-	setc() . ' paste off' => sub {
-		return unless $SCREEN_MODE;
-		my $was_disabled = $DISABLE_SCREEN_TEMP;
-		$DISABLE_SCREEN_TEMP = undef;
-		Irssi::print('Paste mode is now OFF, '.uc(setc()).' is enabled.');
-		if ($was_disabled) {
-			$SCREEN_MODE = undef;
-			$screenResizing = 0;
-			wlreset();
-		}
-	}
-);
-Irssi::command_bind(
-	setc() . ' paste toggle' => sub {
-		if ($DISABLE_SCREEN_TEMP) {
-			Irssi::command(setc() . ' paste off');
-		}
-		else {
-			Irssi::command(setc() . ' paste on');
-		}
-	}
-);
-Irssi::command_bind(
-	setc() . ' redraw' => sub {
-		return unless $SCREEN_MODE;
-		screenFullRedraw();
-	}
-);
-		
-
-# }}}
-
-# {{{ Algorithm::LCSS module
-{
-	package Algorithm::Diff;
-	# Skip to first "=head" line for documentation.
-	use strict;
-
-	use integer;    # see below in _replaceNextLargerWith() for mod to make
-						 # if you don't use this
-
-	# McIlroy-Hunt diff algorithm
-	# Adapted from the Smalltalk code of Mario I. Wolczko, <[email protected]>
-	# by Ned Konz, [email protected]
-	# Updates by Tye McQueen, http://perlmonks.org/?node=tye
-
-	# Create a hash that maps each element of $aCollection to the set of
-	# positions it occupies in $aCollection, restricted to the elements
-	# within the range of indexes specified by $start and $end.
-	# The fourth parameter is a subroutine reference that will be called to
-	# generate a string to use as a key.
-	# Additional parameters, if any, will be passed to this subroutine.
-	#
-	# my $hashRef = _withPositionsOfInInterval( \@array, $start, $end, $keyGen );
-
-	sub _withPositionsOfInInterval
-	{
-		 my $aCollection = shift;    # array ref
-		 my $start       = shift;
-		 my $end         = shift;
-		 my $keyGen      = shift;
-		 my %d;
-		 my $index;
-		 for ( $index = $start ; $index <= $end ; $index++ )
-		 {
-			  my $element = $aCollection->[$index];
-			  my $key = &$keyGen( $element, @_ );
-			  if ( exists( $d{$key} ) )
-			  {
-					unshift ( @{ $d{$key} }, $index );
-			  }
-			  else
-			  {
-					$d{$key} = [$index];
-			  }
-		 }
-		 return wantarray ? %d : \%d;
-	}
-
-	# Find the place at which aValue would normally be inserted into the
-	# array. If that place is already occupied by aValue, do nothing, and
-	# return undef. If the place does not exist (i.e., it is off the end of
-	# the array), add it to the end, otherwise replace the element at that
-	# point with aValue.  It is assumed that the array's values are numeric.
-	# This is where the bulk (75%) of the time is spent in this module, so
-	# try to make it fast!
-
-	sub _replaceNextLargerWith
-	{
-		 my ( $array, $aValue, $high ) = @_;
-		 $high ||= $#$array;
-
-		 # off the end?
-		 if ( $high == -1 || $aValue > $array->[-1] )
-		 {
-			  push ( @$array, $aValue );
-			  return $high + 1;
-		 }
-
-		 # binary search for insertion point...
-		 my $low = 0;
-		 my $index;
-		 my $found;
-		 while ( $low <= $high )
-		 {
-			  $index = ( $high + $low ) / 2;
-
-			  # $index = int(( $high + $low ) / 2);  # without 'use integer'
-			  $found = $array->[$index];
-
-			  if ( $aValue == $found )
-			  {
-					return undef;
-			  }
-			  elsif ( $aValue > $found )
-			  {
-					$low = $index + 1;
-			  }
-			  else
-			  {
-					$high = $index - 1;
-			  }
-		 }
-
-		 # now insertion point is in $low.
-		 $array->[$low] = $aValue;    # overwrite next larger
-		 return $low;
-	}
-
-	# This method computes the longest common subsequence in $a and $b.
-
-	# Result is array or ref, whose contents is such that
-	#   $a->[ $i ] == $b->[ $result[ $i ] ]
-	# foreach $i in ( 0 .. $#result ) if $result[ $i ] is defined.
-
-	# An additional argument may be passed; this is a hash or key generating
-	# function that should return a string that uniquely identifies the given
-	# element.  It should be the case that if the key is the same, the elements
-	# will compare the same. If this parameter is undef or missing, the key
-	# will be the element as a string.
-
-	# By default, comparisons will use "eq" and elements will be turned into keys
-	# using the default stringizing operator '""'.
-
-	# Additional parameters, if any, will be passed to the key generation
-	# routine.
-
-	sub _longestCommonSubsequence
-	{
-		 my $a        = shift;    # array ref or hash ref
-		 my $b        = shift;    # array ref or hash ref
-		 my $counting = shift;    # scalar
-		 my $keyGen   = shift;    # code ref
-		 my $compare;             # code ref
-
-		 if ( ref($a) eq 'HASH' )
-		 {                        # prepared hash must be in $b
-			  my $tmp = $b;
-			  $b = $a;
-			  $a = $tmp;
-		 }
-
-		 # Check for bogus (non-ref) argument values
-		 if ( !ref($a) || !ref($b) )
-		 {
-			  my @callerInfo = caller(1);
-			  die 'error: must pass array or hash references to ' . $callerInfo[3];
-		 }
-
-		 # set up code refs
-		 # Note that these are optimized.
-		 if ( !defined($keyGen) )    # optimize for strings
-		 {
-			  $keyGen = sub { $_[0] };
-			  $compare = sub { my ( $a, $b ) = @_; $a eq $b };
-		 }
-		 else
-		 {
-			  $compare = sub {
-					my $a = shift;
-					my $b = shift;
-					&$keyGen( $a, @_ ) eq &$keyGen( $b, @_ );
-			  };
-		 }
-
-		 my ( $aStart, $aFinish, $matchVector ) = ( 0, $#$a, [] );
-		 my ( $prunedCount, $bMatches ) = ( 0, {} );
-
-		 if ( ref($b) eq 'HASH' )    # was $bMatches prepared for us?
-		 {
-			  $bMatches = $b;
-		 }
-		 else
-		 {
-			  my ( $bStart, $bFinish ) = ( 0, $#$b );
-
-			  # First we prune off any common elements at the beginning
-			  while ( $aStart <= $aFinish
-					and $bStart <= $bFinish
-					and &$compare( $a->[$aStart], $b->[$bStart], @_ ) )
-			  {
-					$matchVector->[ $aStart++ ] = $bStart++;
-					$prunedCount++;
-			  }
-
-			  # now the end
-			  while ( $aStart <= $aFinish
-					and $bStart <= $bFinish
-					and &$compare( $a->[$aFinish], $b->[$bFinish], @_ ) )
-			  {
-					$matchVector->[ $aFinish-- ] = $bFinish--;
-					$prunedCount++;
-			  }
-
-			  # Now compute the equivalence classes of positions of elements
-			  $bMatches =
-				 _withPositionsOfInInterval( $b, $bStart, $bFinish, $keyGen, @_ );
-		 }
-		 my $thresh = [];
-		 my $links  = [];
-
-		 my ( $i, $ai, $j, $k );
-		 for ( $i = $aStart ; $i <= $aFinish ; $i++ )
-		 {
-			  $ai = &$keyGen( $a->[$i], @_ );
-			  if ( exists( $bMatches->{$ai} ) )
-			  {
-					$k = 0;
-					for $j ( @{ $bMatches->{$ai} } )
-					{
-
-						 # optimization: most of the time this will be true
-						 if ( $k and $thresh->[$k] > $j and $thresh->[ $k - 1 ] < $j )
-						 {
-							  $thresh->[$k] = $j;
-						 }
-						 else
-						 {
-							  $k = _replaceNextLargerWith( $thresh, $j, $k );
-						 }
-
-						 # oddly, it's faster to always test this (CPU cache?).
-						 if ( defined($k) )
-						 {
-							  $links->[$k] =
-								 [ ( $k ? $links->[ $k - 1 ] : undef ), $i, $j ];
-						 }
-					}
-			  }
-		 }
-
-		 if (@$thresh)
-		 {
-			  return $prunedCount + @$thresh if $counting;
-			  for ( my $link = $links->[$#$thresh] ; $link ; $link = $link->[0] )
-			  {
-					$matchVector->[ $link->[1] ] = $link->[2];
-			  }
-		 }
-		 elsif ($counting)
-		 {
-			  return $prunedCount;
-		 }
-
-		 return wantarray ? @$matchVector : $matchVector;
-	}
-
-	sub traverse_sequences
-	{
-		 my $a                 = shift;          # array ref
-		 my $b                 = shift;          # array ref
-		 my $callbacks         = shift || {};
-		 my $keyGen            = shift;
-		 my $matchCallback     = $callbacks->{'MATCH'} || sub { };
-		 my $discardACallback  = $callbacks->{'DISCARD_A'} || sub { };
-		 my $finishedACallback = $callbacks->{'A_FINISHED'};
-		 my $discardBCallback  = $callbacks->{'DISCARD_B'} || sub { };
-		 my $finishedBCallback = $callbacks->{'B_FINISHED'};
-		 my $matchVector = _longestCommonSubsequence( $a, $b, 0, $keyGen, @_ );
-
-		 # Process all the lines in @$matchVector
-		 my $lastA = $#$a;
-		 my $lastB = $#$b;
-		 my $bi    = 0;
-		 my $ai;
-
-		 for ( $ai = 0 ; $ai <= $#$matchVector ; $ai++ )
-		 {
-			  my $bLine = $matchVector->[$ai];
-			  if ( defined($bLine) )    # matched
-			  {
-					&$discardBCallback( $ai, $bi++, @_ ) while $bi < $bLine;
-					&$matchCallback( $ai,    $bi++, @_ );
-			  }
-			  else
-			  {
-					&$discardACallback( $ai, $bi, @_ );
-			  }
-		 }
-
-		 # The last entry (if any) processed was a match.
-		 # $ai and $bi point just past the last matching lines in their sequences.
-
-		 while ( $ai <= $lastA or $bi <= $lastB )
-		 {
-
-			  # last A?
-			  if ( $ai == $lastA + 1 and $bi <= $lastB )
-			  {
-					if ( defined($finishedACallback) )
-					{
-						 &$finishedACallback( $lastA, @_ );
-						 $finishedACallback = undef;
-					}
-					else
-					{
-						 &$discardBCallback( $ai, $bi++, @_ ) while $bi <= $lastB;
-					}
-			  }
-
-			  # last B?
-			  if ( $bi == $lastB + 1 and $ai <= $lastA )
-			  {
-					if ( defined($finishedBCallback) )
-					{
-						 &$finishedBCallback( $lastB, @_ );
-						 $finishedBCallback = undef;
-					}
-					else
-					{
-						 &$discardACallback( $ai++, $bi, @_ ) while $ai <= $lastA;
-					}
-			  }
-
-			  &$discardACallback( $ai++, $bi, @_ ) if $ai <= $lastA;
-			  &$discardBCallback( $ai, $bi++, @_ ) if $bi <= $lastB;
-		 }
-
-		 return 1;
-	}
-
-	sub traverse_balanced
-	{
-		 my $a                 = shift;              # array ref
-		 my $b                 = shift;              # array ref
-		 my $callbacks         = shift || {};
-		 my $keyGen            = shift;
-		 my $matchCallback     = $callbacks->{'MATCH'} || sub { };
-		 my $discardACallback  = $callbacks->{'DISCARD_A'} || sub { };
-		 my $discardBCallback  = $callbacks->{'DISCARD_B'} || sub { };
-		 my $changeCallback    = $callbacks->{'CHANGE'};
-		 my $matchVector = _longestCommonSubsequence( $a, $b, 0, $keyGen, @_ );
-
-		 # Process all the lines in match vector
-		 my $lastA = $#$a;
-		 my $lastB = $#$b;
-		 my $bi    = 0;
-		 my $ai    = 0;
-		 my $ma    = -1;
-		 my $mb;
-
-		 while (1)
-		 {
-
-			  # Find next match indices $ma and $mb
-			  do {
-					$ma++;
-			  } while(
-						 $ma <= $#$matchVector
-					&&  !defined $matchVector->[$ma]
-			  );
-
-			  last if $ma > $#$matchVector;    # end of matchVector?
-			  $mb = $matchVector->[$ma];
-
-			  # Proceed with discard a/b or change events until
-			  # next match
-			  while ( $ai < $ma || $bi < $mb )
-			  {
-
-					if ( $ai < $ma && $bi < $mb )
-					{
-
-						 # Change
-						 if ( defined $changeCallback )
-						 {
-							  &$changeCallback( $ai++, $bi++, @_ );
-						 }
-						 else
-						 {
-							  &$discardACallback( $ai++, $bi, @_ );
-							  &$discardBCallback( $ai, $bi++, @_ );
-						 }
-					}
-					elsif ( $ai < $ma )
-					{
-						 &$discardACallback( $ai++, $bi, @_ );
-					}
-					else
-					{
-
-						 # $bi < $mb
-						 &$discardBCallback( $ai, $bi++, @_ );
-					}
-			  }
-
-			  # Match
-			  &$matchCallback( $ai++, $bi++, @_ );
-		 }
-
-		 while ( $ai <= $lastA || $bi <= $lastB )
-		 {
-			  if ( $ai <= $lastA && $bi <= $lastB )
-			  {
-
-					# Change
-					if ( defined $changeCallback )
-					{
-						 &$changeCallback( $ai++, $bi++, @_ );
-					}
-					else
-					{
-						 &$discardACallback( $ai++, $bi, @_ );
-						 &$discardBCallback( $ai, $bi++, @_ );
-					}
-			  }
-			  elsif ( $ai <= $lastA )
-			  {
-					&$discardACallback( $ai++, $bi, @_ );
-			  }
-			  else
-			  {
-
-					# $bi <= $lastB
-					&$discardBCallback( $ai, $bi++, @_ );
-			  }
-		 }
-
-		 return 1;
-	}
-
-	sub prepare
-	{
-		 my $a       = shift;    # array ref
-		 my $keyGen  = shift;    # code ref
-
-		 # set up code ref
-		 $keyGen = sub { $_[0] } unless defined($keyGen);
-
-		 return scalar _withPositionsOfInInterval( $a, 0, $#$a, $keyGen, @_ );
-	}
-
-	sub LCS
-	{
-		 my $a = shift;                  # array ref
-		 my $b = shift;                  # array ref or hash ref
-		 my $matchVector = _longestCommonSubsequence( $a, $b, 0, @_ );
-		 my @retval;
-		 my $i;
-		 for ( $i = 0 ; $i <= $#$matchVector ; $i++ )
-		 {
-			  if ( defined( $matchVector->[$i] ) )
-			  {
-					push ( @retval, $a->[$i] );
-			  }
-		 }
-		 return wantarray ? @retval : \@retval;
-	}
-
-	sub LCS_length
-	{
-		 my $a = shift;                          # array ref
-		 my $b = shift;                          # array ref or hash ref
-		 return _longestCommonSubsequence( $a, $b, 1, @_ );
-	}
-
-	sub LCSidx
-	{
-		 my $a= shift @_;
-		 my $b= shift @_;
-		 my $match= _longestCommonSubsequence( $a, $b, 0, @_ );
-		 my @am= grep defined $match->[$_], 0..$#$match;
-		 my @bm= @{$match}[@am];
-		 return \@am, \@bm;
-	}
-
-	sub compact_diff
-	{
-		 my $a= shift @_;
-		 my $b= shift @_;
-		 my( $am, $bm )= LCSidx( $a, $b, @_ );
-		 my @cdiff;
-		 my( $ai, $bi )= ( 0, 0 );
-		 push @cdiff, $ai, $bi;
-		 while( 1 ) {
-			  while(  @$am  &&  $ai == $am->[0]  &&  $bi == $bm->[0]  ) {
-					shift @$am;
-					shift @$bm;
-					++$ai, ++$bi;
-			  }
-			  push @cdiff, $ai, $bi;
-			  last   if  ! @$am;
-			  $ai = $am->[0];
-			  $bi = $bm->[0];
-			  push @cdiff, $ai, $bi;
-		 }
-		 push @cdiff, 0+@$a, 0+@$b
-			  if  $ai < @$a || $bi < @$b;
-		 return wantarray ? @cdiff : \@cdiff;
-	}
-
-	sub diff
-	{
-		 my $a      = shift;    # array ref
-		 my $b      = shift;    # array ref
-		 my $retval = [];
-		 my $hunk   = [];
-		 my $discard = sub {
-			  push @$hunk, [ '-', $_[0], $a->[ $_[0] ] ];
-		 };
-		 my $add = sub {
-			  push @$hunk, [ '+', $_[1], $b->[ $_[1] ] ];
-		 };
-		 my $match = sub {
-			  push @$retval, $hunk
-					if 0 < @$hunk;
-			  $hunk = []
-		 };
-		 traverse_sequences( $a, $b,
-			  { MATCH => $match, DISCARD_A => $discard, DISCARD_B => $add }, @_ );
-		 &$match();
-		 return wantarray ? @$retval : $retval;
-	}
-
-	sub sdiff
-	{
-		 my $a      = shift;    # array ref
-		 my $b      = shift;    # array ref
-		 my $retval = [];
-		 my $discard = sub { push ( @$retval, [ '-', $a->[ $_[0] ], "" ] ) };
-		 my $add = sub { push ( @$retval, [ '+', "", $b->[ $_[1] ] ] ) };
-		 my $change = sub {
-			  push ( @$retval, [ 'c', $a->[ $_[0] ], $b->[ $_[1] ] ] );
-		 };
-		 my $match = sub {
-			  push ( @$retval, [ 'u', $a->[ $_[0] ], $b->[ $_[1] ] ] );
-		 };
-		 traverse_balanced(
-			  $a,
-			  $b,
-			  {
-					MATCH     => $match,
-					DISCARD_A => $discard,
-					DISCARD_B => $add,
-					CHANGE    => $change,
-			  },
-			  @_
-		 );
-		 return wantarray ? @$retval : $retval;
-	}
-
-	########################################
-	my $Root= __PACKAGE__;
-	package Algorithm::Diff::_impl;
-	use strict;
-
-	sub _Idx()  { 0 } # $me->[_Idx]: Ref to array of hunk indices
-					# 1   # $me->[1]: Ref to first sequence
-					# 2   # $me->[2]: Ref to second sequence
-	sub _End()  { 3 } # $me->[_End]: Diff between forward and reverse pos
-	sub _Same() { 4 } # $me->[_Same]: 1 if pos 1 contains unchanged items
-	sub _Base() { 5 } # $me->[_Base]: Added to range's min and max
-	sub _Pos()  { 6 } # $me->[_Pos]: Which hunk is currently selected
-	sub _Off()  { 7 } # $me->[_Off]: Offset into _Idx for current position
-	sub _Min() { -2 } # Added to _Off to get min instead of max+1
-
-	sub Die
-	{
-		 require Carp;
-		 Carp::confess( @_ );
-	}
-
-	sub _ChkPos
-	{
-		 my( $me )= @_;
-		 return   if  $me->[_Pos];
-		 my $meth= ( caller(1) )[3];
-		 Die( "Called $meth on 'reset' object" );
-	}
-
-	sub _ChkSeq
-	{
-		 my( $me, $seq )= @_;
-		 return $seq + $me->[_Off]
-			  if  1 == $seq  ||  2 == $seq;
-		 my $meth= ( caller(1) )[3];
-		 Die( "$meth: Invalid sequence number ($seq); must be 1 or 2" );
-	}
-
-	sub getObjPkg
-	{
-		 my( $us )= @_;
-		 return ref $us   if  ref $us;
-		 return $us . "::_obj";
-	}
-
-	sub new
-	{
-		 my( $us, $seq1, $seq2, $opts ) = @_;
-		 my @args;
-		 for( $opts->{keyGen} ) {
-			  push @args, $_   if  $_;
-		 }
-		 for( $opts->{keyGenArgs} ) {
-			  push @args, @$_   if  $_;
-		 }
-		 my $cdif= Algorithm::Diff::compact_diff( $seq1, $seq2, @args );
-		 my $same= 1;
-		 if(  0 == $cdif->[2]  &&  0 == $cdif->[3]  ) {
-			  $same= 0;
-			  splice @$cdif, 0, 2;
-		 }
-		 my @obj= ( $cdif, $seq1, $seq2 );
-		 $obj[_End] = (1+@$cdif)/2;
-		 $obj[_Same] = $same;
-		 $obj[_Base] = 0;
-		 my $me = bless \@obj, $us->getObjPkg();
-		 $me->Reset( 0 );
-		 return $me;
-	}
-
-	sub Reset
-	{
-		 my( $me, $pos )= @_;
-		 $pos= int( $pos || 0 );
-		 $pos += $me->[_End]
-			  if  $pos < 0;
-		 $pos= 0
-			  if  $pos < 0  ||  $me->[_End] <= $pos;
-		 $me->[_Pos]= $pos || !1;
-		 $me->[_Off]= 2*$pos - 1;
-		 return $me;
-	}
-
-	sub Base
-	{
-		 my( $me, $base )= @_;
-		 my $oldBase= $me->[_Base];
-		 $me->[_Base]= 0+$base   if  defined $base;
-		 return $oldBase;
-	}
-
-	sub Copy
-	{
-		 my( $me, $pos, $base )= @_;
-		 my @obj= @$me;
-		 my $you= bless \@obj, ref($me);
-		 $you->Reset( $pos )   if  defined $pos;
-		 $you->Base( $base );
-		 return $you;
-	}
-
-	sub Next {
-		 my( $me, $steps )= @_;
-		 $steps= 1   if  ! defined $steps;
-		 if( $steps ) {
-			  my $pos= $me->[_Pos];
-			  my $new= $pos + $steps;
-			  $new= 0   if  $pos  &&  $new < 0;
-			  $me->Reset( $new )
-		 }
-		 return $me->[_Pos];
-	}
-
-	sub Prev {
-		 my( $me, $steps )= @_;
-		 $steps= 1   if  ! defined $steps;
-		 my $pos= $me->Next(-$steps);
-		 $pos -= $me->[_End]   if  $pos;
-		 return $pos;
-	}
-
-	sub Diff {
-		 my( $me )= @_;
-		 $me->_ChkPos();
-		 return 0   if  $me->[_Same] == ( 1 & $me->[_Pos] );
-		 my $ret= 0;
-		 my $off= $me->[_Off];
-		 for my $seq ( 1, 2 ) {
-			  $ret |= $seq
-					if  $me->[_Idx][ $off + $seq + _Min ]
-					<   $me->[_Idx][ $off + $seq ];
-		 }
-		 return $ret;
-	}
-
-	sub Min {
-		 my( $me, $seq, $base )= @_;
-		 $me->_ChkPos();
-		 my $off= $me->_ChkSeq($seq);
-		 $base= $me->[_Base] if !defined $base;
-		 return $base + $me->[_Idx][ $off + _Min ];
-	}
-
-	sub Max {
-		 my( $me, $seq, $base )= @_;
-		 $me->_ChkPos();
-		 my $off= $me->_ChkSeq($seq);
-		 $base= $me->[_Base] if !defined $base;
-		 return $base + $me->[_Idx][ $off ] -1;
-	}
-
-	sub Range {
-		 my( $me, $seq, $base )= @_;
-		 $me->_ChkPos();
-		 my $off = $me->_ChkSeq($seq);
-		 if( !wantarray ) {
-			  return  $me->[_Idx][ $off ]
-					-   $me->[_Idx][ $off + _Min ];
-		 }
-		 $base= $me->[_Base] if !defined $base;
-		 return  ( $base + $me->[_Idx][ $off + _Min ] )
-			  ..  ( $base + $me->[_Idx][ $off ] - 1 );
-	}
-
-	sub Items {
-		 my( $me, $seq )= @_;
-		 $me->_ChkPos();
-		 my $off = $me->_ChkSeq($seq);
-		 if( !wantarray ) {
-			  return  $me->[_Idx][ $off ]
-					-   $me->[_Idx][ $off + _Min ];
-		 }
-		 return
-			  @{$me->[$seq]}[
-						 $me->[_Idx][ $off + _Min ]
-					..  ( $me->[_Idx][ $off ] - 1 )
-			  ];
-	}
-
-	sub Same {
-		 my( $me )= @_;
-		 $me->_ChkPos();
-		 return wantarray ? () : 0
-			  if  $me->[_Same] != ( 1 & $me->[_Pos] );
-		 return $me->Items(1);
-	}
-
-	my %getName;
-		 %getName= (
-			  same => \&Same,
-			  diff => \&Diff,
-			  base => \&Base,
-			  min  => \&Min,
-			  max  => \&Max,
-			  range=> \&Range,
-			  items=> \&Items, # same thing
-		 );
-
-	sub Get
-	{
-		 my $me= shift @_;
-		 $me->_ChkPos();
-		 my @value;
-		 for my $arg (  @_  ) {
-			  for my $word (  split ' ', $arg  ) {
-					my $meth;
-					if(     $word !~ /^(-?\d+)?([a-zA-Z]+)([12])?$/
-						 ||  not  $meth= $getName{ lc $2 }
-					) {
-						 Die( $Root, ", Get: Invalid request ($word)" );
-					}
-					my( $base, $name, $seq )= ( $1, $2, $3 );
-					push @value, scalar(
-						 4 == length($name)
-							  ? $meth->( $me )
-							  : $meth->( $me, $seq, $base )
-					);
-			  }
-		 }
-		 if(  wantarray  ) {
-			  return @value;
-		 } elsif(  1 == @value  ) {
-			  return $value[0];
-		 }
-		 Die( 0+@value, " values requested from ",
-			  $Root, "'s Get in scalar context" );
-	}
-
-
-	my $Obj= getObjPkg($Root);
-	no strict 'refs';
-
-	for my $meth (  qw( new getObjPkg )  ) {
-		 *{$Root."::".$meth} = \&{$meth};
-		 *{$Obj ."::".$meth} = \&{$meth};
-	}
-	for my $meth (  qw(
-		 Next Prev Reset Copy Base Diff
-		 Same Items Range Min Max Get
-		 _ChkPos _ChkSeq
-	)  ) {
-		 *{$Obj."::".$meth} = \&{$meth};
-	}
-
-};
-{
-	package Algorithm::LCSS;
-
-	use strict;
-	{
-		no strict 'refs';
-		*traverse_sequences = \&Algorithm::Diff::traverse_sequences;
-	}
-
-	sub _tokenize { [split //, $_[0]] }
-
-	sub CSS {
-		 my $is_array = ref $_[0] eq 'ARRAY' ? 1 : 0;
-		 my ( $seq1, $seq2, @match, $from_match );
-		 my $i = 0;
-		 if ( $is_array ) {
-			  $seq1 = $_[0];
-			  $seq2 = $_[1];
-			  traverse_sequences( $seq1, $seq2, {
-					MATCH => sub { push @{$match[$i]}, $seq1->[$_[0]]; $from_match = 1 },
-					DISCARD_A => sub { do{$i++; $from_match = 0} if $from_match },
-					DISCARD_B => sub { do{$i++; $from_match = 0} if $from_match },
-			  });
-		 }
-		 else {
-			  $seq1 = _tokenize($_[0]);
-			  $seq2 = _tokenize($_[1]);
-			  traverse_sequences( $seq1, $seq2, {
-					MATCH => sub { $match[$i] .= $seq1->[$_[0]]; $from_match = 1 },
-					DISCARD_A => sub { do{$i++; $from_match = 0} if $from_match },
-					DISCARD_B => sub { do{$i++; $from_match = 0} if $from_match },
-			  });
-		 }
-	  return \@match;
-	}
-
-	sub CSS_Sorted {
-		 my $match = CSS(@_);
-		 if ( ref $_[0] eq 'ARRAY' ) {
-			 @$match = map{$_->[0]}sort{$b->[1]<=>$a->[1]}map{[$_,scalar(@$_)]}@$match
-		 }
-		 else {
-			 @$match = map{$_->[0]}sort{$b->[1]<=>$a->[1]}map{[$_,length($_)]}@$match
-		 }
-	  return $match;
-	}
-
-	sub LCSS {
-		 my $is_array = ref $_[0] eq 'ARRAY' ? 1 : 0;
-		 my $css = CSS(@_);
-		 my $index;
-		 my $length = 0;
-		 if ( $is_array ) {
-			  for( my $i = 0; $i < @$css; $i++ ) {
-					next unless @{$css->[$i]}>$length;
-					$index = $i;
-					$length = @{$css->[$i]};
-			  }
-		 }
-		 else {
-			  for( my $i = 0; $i < @$css; $i++ ) {
-					next unless length($css->[$i])>$length;
-					$index = $i;
-					$length = length($css->[$i]);
-			  }
-		 }
-	  return $css->[$index];
-	}
-
-};
-# }}}
-#{{{ Class::Classless module
-{
-	package Class::Classless;
-	use strict;
-	use vars qw(@ISA);
-	use Carp;
-
-	@ISA = ();
-
-	###########################################################################
-
-	@Class::Classless::X::ISA = ();
-
-	###########################################################################
-	###########################################################################
-
-	sub Class::Classless::X::AUTOLOAD {
-	  # This's the big dispatcher.
-	  
-	  my $it = shift @_;
-	  my $m =  ($Class::Classless::X::AUTOLOAD =~ m/([^:]+)$/s ) 
-					 ? $1 : $Class::Classless::X::AUTOLOAD;
-
-	  croak "Can't call Class::Classless methods (like $m) without an object"
-		 unless ref $it;  # sanity, basically.
-
-	  my $prevstate;
-	  $prevstate = ${shift @_}
-		if scalar(@_) && defined($_[0]) &&
-			ref($_[0]) eq 'Class::Classless::CALLSTATE::SHIMMY'
-	  ;   # A shim!  we were called via $callstate->NEXT
-
-	  my $no_fail = $prevstate ? $prevstate->[3] : undef;
-	  my $i       = $prevstate ? ($prevstate->[1] + 1) : 0;
-		# where to start scanning
-	  my $lineage;
-
-	  # Get the linearization of the ISA tree
-	  if($prevstate) {
-		 $lineage = $prevstate->[2];
-	  } elsif(defined $it->{'ISA_CACHE'} and ref $it->{'ISA_CACHE'} ){
-		 $lineage = $it->{'ISA_CACHE'};
-	  } else {
-		 $lineage = [ &Class::Classless::X::ISA_TREE($it) ];
-	  }
-
-	  # Was:
-	  #my @lineage =
-	  #  $prevstate ? @{$prevstate->[2]}
-	  #             : &Class::Classless::X::ISA_TREE($it);
-	  # # Get the linearization of the ISA tree
-	  # # ISA-memoization happens in the ISA_TREE function.
-	  
-	  for(; $i < @$lineage; ++$i) {
-
-		 if( !defined($no_fail) and exists($lineage->[$i]{'NO_FAIL'}) ) {
-			$no_fail = ($lineage->[$i]{'NO_FAIL'} || 0);
-			# so the first NO_FAIL sets it
-		 }
-
-		 if(     ref($lineage->[$i]{'METHODS'}     || 0)  # sanity
-			&& exists($lineage->[$i]{'METHODS'}{$m})
-		 ){
-			# We found what we were after.  Now see what to do with it.
-			my $v = $lineage->[$i]{'METHODS'}{$m};
-			return $v unless defined $v and ref $v;
-
-			if(ref($v) eq 'CODE') { # normal case, I expect!
-			  # Used to have copying of the arglist here.
-			  #  But it was apparently useless, so I deleted it
-			  unshift @_, 
-				 $it,                   # $_[0]    -- target object
-				 # a NEW callstate
-				 bless([$m, $i, $lineage, $no_fail, $prevstate ? 1 : 0],
-						 'Class::Classless::CALLSTATE'
-						),                # $_[1]    -- the callstate
-			  ;
-			  goto &{ $v }; # yes, magic goto!  bimskalabim!
-			}
-			return @$v if ref($v) eq '_deref_array';
-			return $$v if ref($v) eq '_deref_scalar';
-			return $v; # fallthru
-		 }
-	  }
-
-	  if($m eq 'DESTROY') { # mitigate DESTROY-lookup failure at global destruction
-		 # should be impossible
-	  } else {
-		 if($no_fail || 0) {
-			return;
-		 }
-		 croak "Can't find ", $prevstate ? 'NEXT method' : 'method',
-				 " $m in ", $it->{'NAME'} || $it,
-				 " or any ancestors\n";
-	  }
-	}
-
-	###########################################################################
-	###########################################################################
-
-	sub Class::Classless::X::DESTROY {
-	  # noop
-	}
-
-	###########################################################################
-	sub Class::Classless::X::ISA_TREE {
-	  # The linearizer!
-	  # Returns the search path for $_[0], starting with $_[0]
-	  # Possibly memoized.
-
-	  # I stopped being able to understand this algorithm about five
-	  #  minutes after I wrote it.
-	  use strict;
-	  
-	  my $set_cache = 0; # flag to set the cache on the way out
-	  
-	  if(exists($_[0]{'ISA_CACHE'})) {
-		 return    @{$_[0]{'ISA_CACHE'}}
-		  if defined $_[0]{'ISA_CACHE'}
-			  and ref $_[0]{'ISA_CACHE'};
-		  
-		 # Otherwise, if exists but is not a ref, it's a signal that it should
-		 #  be replaced at the earliest, with a listref
-		 $set_cache = 1;
-	  }
-	  
-	  my $has_mi = 0; # set to 0 on the first node we see with 2 parents!
-	  # First, just figure out what's in the tree.
-	  my %last_child = ($_[0] => 1); # as if already seen
-
-	  # if $last_child{$x} == $y, that means:
-	  #  1) incidentally, we've passed the node $x before.
-	  #  2) $x is the last child of $y,
-	  #     so that means that $y can be pushed to the stack only after
-	  #      we've pushed $x to the stack.
-	  
-	  my @tree_nodes;
-	  {
-		 my $current;
-		 my @in_stack = ($_[0]);
-		 while(@in_stack) {
-			next unless
-			 defined($current = shift @in_stack)
-			 && ref($current) # sanity
-			 && ref($current->{'PARENTS'} || 0) # sanity
-			;
-
-			push @tree_nodes, $current;
-
-			$has_mi = 1 if @{$current->{'PARENTS'}} > 1;
-			unshift
-			  @in_stack,
-			  map {
-				 if(exists $last_child{$_}) { # seen before!
-					$last_child{$_} = $current;
-					(); # seen -- don't re-explore
-				 } else { # first time seen
-					$last_child{$_} = $current;
-					$_; # first time seen -- explore now
-				 }
-			  }
-			  @{$current->{'PARENTS'}}
-			;
-		 }
-
-		 # If there was no MI, then that first scan was sufficient.
-		 unless($has_mi) {
-			$_[0]{'ISA_CACHE'} = \@tree_nodes if $set_cache;
-			return @tree_nodes;
-		 }
-
-		 # Otherwise, toss this list and rescan, consulting %last_child
-	  }
-
-	  # $last_child{$parent} holds the last (or only) child of $parent
-	  # in this tree.  When walking the tree this time, only that
-	  # child is authorized to put its parent on the @in_stack.
-	  # And that's the only way a node can get added to @in_stack,
-	  # except for $_[0] (the start node) being there at the beginning.
-
-	  # Now, walk again, but this time exploring parents the LAST
-	  # time seen in the tree, not the first.
-
-	  my @out;
-	  {
-		 my $current;
-		 my @in_stack = ($_[0]);
-		 while(@in_stack) {
-			next unless defined($current = shift @in_stack) && ref($current);
-			push @out, $current; # finally.
-			unshift
-			  @in_stack,
-			  grep(
-				 (
-					defined($_) # sanity
-					&& ref($_)  # sanity
-					&& $last_child{$_} eq $current,
-				 ),
-				 # I'm lastborn (or onlyborn) of this parent
-				 # so it's OK to explore now
-				 @{$current->{'PARENTS'}}
-			  )
-			 if ref($current->{'PARENTS'} || 0) # sanity
-			;
-		 }
-
-		 unless(scalar(@out) == scalar(keys(%last_child))) {
-			# the counts should be equal
-			my %good_ones;
-			@good_ones{@out} = ();
-			croak
-			  "ISA tree for " .
-			  ($_[0]{'NAME'} || $_[0]) .
-			  " is apparently cyclic, probably involving the nodes " .
-			  nodelist( grep { ref($_) && !exists $good_ones{$_} }
-				 values(%last_child) )
-			  . "\n";
-		 }
-	  }
-	  #print "Contents of out: ", nodelist(@out), "\n";
-	  
-	  $_[0]{'ISA_CACHE'} = \@out if $set_cache;
-	  return @out;
-	}
-
-	###########################################################################
-
-	sub Class::Classless::X::can { # NOT like UNIVERSAL::can ...
-	  # return 1 if $it is capable of the method given -- otherwise 0
-	  my($it, $m) = @_[0,1];
-	  return undef unless ref $it;
-
-	  croak "undef is not a valid method name"       unless defined($m);
-	  croak "null-string is not a valid method name" unless length($m);
-
-	  foreach my $o (&Class::Classless::X::ISA_TREE($it)) {
-		 return 1
-		  if  ref($o->{'METHODS'} || 0)   # sanity
-			&& exists $o->{'METHODS'}{$m};
-	  }
-
-	  return 0;
-	}
-
-
-	###########################################################################
-
-	sub Class::Classless::X::isa { # Like UNIVERSAL::isa
-	  # Returns true for $X->isa($Y) iff $Y is $X or is an ancestor of $X.
-
-	  return unless ref($_[0]) && ref($_[1]);
-	  return scalar(grep {$_ eq $_[1]} &Class::Classless::X::ISA_TREE($_[0])); 
-	}
-
-	###########################################################################
-
-	sub nodelist { join ', ', map { "" . ($_->{'NAME'} || $_) . ""} @_ }
-
-	###########################################################################
-	###########################################################################
-	###########################################################################
-	# Methods for the CALLSTATE class.
-	#  Basically, CALLSTATE objects represent the state of the dispatcher,
-	#   frozen at the moment when the method call was dispatched to the
-	#   appropriate sub.
-	#  In the grand scheme of things, this needn't be a class -- I could
-	#   have just made the callstate data-object be a hash with documented
-	#   keys, or a closure that responded to only certain parameters,
-	#   etc.  But I like it this way.  And I like being able to say simply
-	#   $cs->NEXT
-	#  Yes, these are a bit cryptically written, but it's behoovy for
-	#   them to be very very efficient.
-
-	@Class::Classless::ISA = ();
-	sub Class::Classless::CALLSTATE::found_name { $_[0][0] }
-		#  the method name called and found
-	sub Class::Classless::CALLSTATE::found_depth { $_[0][1] }
-		#  my depth in the lineage
-	sub Class::Classless::CALLSTATE::lineage { @{$_[0][2]} }
-		#  my lineage
-	sub Class::Classless::CALLSTATE::target { $_[0][2][  0          ] }
-		#  the object that's the target -- same as $_[0] for the method called
-	sub Class::Classless::CALLSTATE::home   { $_[0][2][  $_[0][1]   ] }
-		#  the object I was found in
-	sub Class::Classless::CALLSTATE::sub_found {
-	  $_[0][2][  $_[0][1]   ]{'METHODS'}{ $_[0][0] }
-	}  #  the routine called
-
-	sub Class::Classless::CALLSTATE::no_fail          {  $_[0][3]         }
-	sub Class::Classless::CALLSTATE::set_no_fail_true {  $_[0][3] = 1     }
-	sub Class::Classless::CALLSTATE::set_fail_false   {  $_[0][3] = 0     }
-	sub Class::Classless::CALLSTATE::set_fail_undef   {  $_[0][3] = undef }
-
-	sub Class::Classless::CALLSTATE::via_next         {  $_[0][4] }
-
-	sub Class::Classless::CALLSTATE::NEXT {
-	  #croak "NEXT needs at least one argument: \$cs->NEXT('method'...)"
-	  # unless @_ > 1;
-		# no longer true.
-	  my $cs = shift @_;
-	  my $m  = shift @_; # which may be (or come out) undef...
-	  $m = $cs->[0] unless defined $m; #  the method name called and found
-
-	  ($cs->[2][0])->$m(
-		 bless( \$cs, 'Class::Classless::CALLSTATE::SHIMMY' ),
-		 @_
-	  );
-	}
-
-	###########################################################################
-};
-#}}}
-
-###############
-###
-#
-# {{{ *** C h a n g e l o g ***
-#
-# 0.6ca
-# - add screen support (from nicklist.pl)
-# - rename to adv_windowlist.pl (advanced window list) since it isn't just a
-#   window list status bar (wlstat) anymore
-# - names can now have a max length and window names can be used
-# - fixed a bug with block display in screen mode and statusbar mode
-# - added space handling to ir_fe and removed it again
-# - now handling formats on my own
-# - added warning about missing sb_act_none abstract leading to
-# - display*active settings
-# - added warning about the bug in awl_display_(no)key_active settings
-#
-# 0.5d
-# - add setting to also hide the last statusbar if empty (awl_all_disable)
-# - reverted to old utf8 code to also calculate broken utf8 length correctly
-# - simplified dealing with statusbars in wlreset
-# - added a little tweak for the renamed term_type somewhere after Irssi 0.8.9
-# - fixed bug in handling channel #$$
-# - typo on line 200 spotted by f0rked
-# - reset background colour at the beginning of an entry
-# 
-# 0.4d
-# - fixed order of disabling statusbars
-# - several attempts at special chars, without any real success
-#   and much more weird new bugs caused by this
-# - setting to specify sort order
-# - reduced timeout values
-# - added awl_hide_data for Geert Hauwaerts ( [email protected] ) :)
-# - make it so the dynamic sub is actually deleted
-# - fix a bug with removing of the last separator
-# - take into consideration parse_special
-# 
-# 0.3b
-# - automatically kill old statusbars
-# - reset on /reload
-# - position/placement settings
-#
-# 0.2
-# - automated retrieval of key bindings (thanks grep.pl authors)
-# - improved removing of statusbars
-# - got rid of status chop
-#
-# 0.1
-# - rewritten to suit my needs
-# - based on chanact 0.5.5
-# }}}
-# vim: se fdm=marker tw=80 :
--- a/irssi/scripts/autorun/adv_windowlist.pl	Wed Nov 19 19:08:21 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-../adv_windowlist.pl
\ No newline at end of file
--- a/irssi/scripts/autorun/cap_sasl.pl	Wed Nov 19 19:08:21 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-../cap_sasl.pl
\ No newline at end of file
--- a/irssi/scripts/autorun/hilightwin.pl	Wed Nov 19 19:08:21 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-../hilightwin.pl
\ No newline at end of file
--- a/irssi/scripts/autorun/nicklist.pl	Wed Nov 19 19:08:21 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-../nicklist.pl
\ No newline at end of file
--- a/irssi/scripts/autorun/nm.pl	Wed Nov 19 19:08:21 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-../nm.pl
\ No newline at end of file
--- a/irssi/scripts/autorun/queryresume.pl	Wed Nov 19 19:08:21 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-../queryresume.pl
\ No newline at end of file
--- a/irssi/scripts/autorun/trackbar.pl	Wed Nov 19 19:08:21 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-../trackbar.pl
\ No newline at end of file
--- a/irssi/scripts/bitlbee_typing_notice.pl	Wed Nov 19 19:08:21 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,319 +0,0 @@
-# INSTALLATION
-# [&bitlbee] set typing_notice true
-# <@root> typing_notice = `true'
-# AND
-# /statusbar window add typing_notice
-#
-# SETTINGS
-# [bitlbee]
-# bitlbee_send_typing = ON
-#   -> send typing messages to buddies
-# bitlbee_typing_allwin = OFF
-#   -> show typing notifications in all windows
-#
-# 
-# Changelog:
-#
-# 2010-08-09 (version 1.7.1)
-# * Multiple control channels supported by checking chanmodes
-#
-# 2010-07-27 (version 1.7)
-# * Using new server detection for latest BitlBee support
-#
-# 2010-07-26 (version 1.6.3)
-# * Removed checking if nicks exists in &bitlbee channel, this because BitlBee 
-#   can be used without control channel from this date
-#
-# 2007-03-03 (version 1.6.2)
-# * Fix: timers weren't deleted correctly. This resulted in huge mem usage.
-#
-# 2006-11-02 (version 1.6.1)
-# * Sending typing works again.
-#
-# 2006-10-27 (version 1.6)
-# * 'channel sync' re-implemented.
-# * bitlbee_send_typing was a string setting, It's a boolean now, like it should.
-#
-# 2006-10-24 (version 1.5)
-# * Sending notices to online users only. ( removed this again at 2010-07-26, see above )
-# * Using the new get_channel function;
-#
-# 2005-12-15 (version 1.42):
-# * Fixed small bug with typing notices disappearing under certain circumstances
-#   in channels
-# * Fixed bug that caused outgoing notifications not to work 
-# * root cares not about our typing status.
-#
-# 2005-12-04 (version 1.41):
-# * Implemented stale states in statusbar (shows "(stale)" for OSCAR connections) 
-# * Introduced bitlbee_typing_allwin (default OFF). Set this to ON to make
-#   typing notifications visible in all windows.
-#
-# 2005-12-03 (version 1.4):
-# * Major code cleanups and rewrites for bitlbee 1.0 with the updated typing
-#   scheme. TYPING 0, TYPING 1, and TYPING 2 are now supported from the server.
-# * Stale states (where user has typed in text but has stopped typing) are now
-#   recognized.
-# * Bug where user thinks you are still typing if you close the window after
-#   typing something and then erasing it quickly.. fixed.
-# * If a user signs off while they are still typing, the notification is removed
-# This update by Matt "f0rked" Sparks
-#
-# 2005-08-26:
-# Some fixes for AIM, Thanks to Dracula.
-#
-# 2005-08-16:
-# AIM supported, for sending notices, using CTCP TYPING 0. (Use the AIM patch from Hanji http://get.bitlbee.org/patches/)
-# 
-# 2004-10-31:
-# Sends typing notice to the bitlbee server when typing a message in irssi. bitlbee > 0.92
-#
-# 2004-06-11:
-# shows [typing: ] in &bitlbee with multiple users.
-#
-use strict;
-use Irssi::TextUI;
-use Data::Dumper;
-
-use vars qw($VERSION %IRSSI);
-
-$VERSION = '1.7.1';
-%IRSSI = (
-	authors	 	=> 'Tijmen "timing" Ruizendaal, Matt "f0rked" Sparks',
-	contact		=> '[email protected], [email protected]',
-	name		=> 'BitlBee_typing_notice',
-	description	=> '1. Adds an item to the status bar wich shows [typing] when someone is typing a message on the supported IM-networks	2. Sends typing notices to the supported IM networks (the other way arround). (For bitlbee 3.0+)',
-	license	 	=> 'GPLv2',
-	url		=> 'http://the-timing.nl/stuff/irssi-bitlbee, http://f0rked.com',
-	changed	 	=> '2010-08-09',
-);
-
-my $bitlbee_server; # server object
-my @control_channels; # mostly: &bitlbee, &facebook etc.
-init();
-
-sub init { # if script is loaded after connect
-	my @servers = Irssi::servers();
-	foreach my $server(@servers) {
-		if( $server->isupport('NETWORK') eq 'BitlBee' ){
-			$bitlbee_server = $server;
-			my @channels = $server->channels();
-			foreach my $channel(@channels) {
-				if( $channel->{mode} =~ /C/ ){
-					push @control_channels, $channel->{name} unless (grep $_ eq $channel->{name}, @control_channels);
-				}
-			}
-		}
-	}
-}
-# if connect after script is loaded
-Irssi::signal_add_last('event 005' => sub {
-	my( $server ) = @_;
-	if( $server->isupport('NETWORK') eq 'BitlBee' ){
-		$bitlbee_server = $server;
-	}
-});
-# if new control channel is synced after script is loaded
-Irssi::signal_add_last('channel sync' => sub {
-	my( $channel ) = @_;
-	if( $channel->{mode} =~ /C/ && $channel->{server}->{tag} eq $bitlbee_server->{tag} ){
-		push @control_channels, $channel->{name} unless (grep $_ eq $channel->{name}, @control_channels);
-	}
-});
-
-# How often to check if we are typing, or on msn,
-# how long to keep the typing notice up, or check
-# if the other user is still typing...
-my $KEEP_TYPING_TIMEOUT = 1;
-my $STOP_TYPING_TIMEOUT = 7;
-
-my %timer_tag;
-
-my %typing;
-my %tag;
-my $line;
-my %out_typing;
-my $lastkey;
-my $keylog_active = 1;
-my $command_char = Irssi::settings_get_str('cmdchars'); # mostly: /
-my $to_char = Irssi::settings_get_str("completion_char"); # mostly: :
-
-sub event_ctcp_msg {
-	my ($server, $msg, $from, $address) = @_;
-	return if $server->{tag} ne $bitlbee_server->{tag};
-	if ( my($type) = $msg =~ "TYPING ([0-9])" ){
-		Irssi::signal_stop();
-		if( $type == 0 ){
-			unset_typing($from);
-		} elsif( $type == 1 ){
-			$typing{$from}=1;
-			if( $address !~ /\@login\.oscar\.aol\.com/ and $address !~ /\@YAHOO/ and $address !~ /\@login\.icq\.com/ ){
-				Irssi::timeout_remove($tag{$from});
-				delete($tag{$from});
-				$tag{$from}=Irssi::timeout_add_once($STOP_TYPING_TIMEOUT*1000,"unset_typing",$from);
-			}
-			redraw($from);
-		} elsif( $type == 2 ){
-			stale_typing($from);
-		}
-	}
-}
-
-sub unset_typing {
-	my($from,$no_redraw)=@_;
-	delete $typing{$from} if $typing{$from};
-	Irssi::timeout_remove($tag{$from});
-	delete($tag{$from});
-	redraw($from) if !$no_redraw;
-}
-
-sub stale_typing {
-	my($from)=@_;
-	$typing{$from}=2;
-	redraw($from);
-}
-
-sub redraw {
-	my($from)=@_;
-	my $window = Irssi::active_win();
-	my $name = $window->get_active_name();
-	
-	# only redraw if current window equals to the typing person, is a control channel or if allwin is set
-	if( $from eq $name || (grep $_ eq $name, @control_channels) || Irssi::settings_get_bool("bitlbee_typing_allwin") ){
-		Irssi::statusbar_items_redraw('typing_notice');
-	}
-}	
-
-sub event_msg {
-	my ($server,$data,$from,$address,$target) = @_;
-	return if $server->{tag} ne $bitlbee_server->{tag};
-	my $channel=Irssi::active_win()->get_active_name();
-	unset_typing $from, "no redraw";
-	unset_typing $channel;
-}
-
-sub event_quit {
-	my $server = shift;
-	return if $server->{tag} ne $bitlbee_server->{tag};
-	my $nick = shift;
-	unset_typing $nick;
-}
-
-sub typing_notice {
-	my ($item, $get_size_only) = @_;
-	my $window = Irssi::active_win();
-	my $channel = $window->get_active_name();
-	
-	if (exists($typing{$channel})) {
-		my $append=$typing{$channel}==2 ? " (stale)" : "";
-		$item->default_handler($get_size_only, "{sb typing$append}", 0, 1);
-	} else {
-		$item->default_handler($get_size_only, "", 0, 1);
-		Irssi::timeout_remove($tag{$channel});
-		delete($tag{$channel});
-	}
-	# we check for correct windows again, because the statusbar item is redrawn after window change too.
-	if( (grep $_ eq $channel, @control_channels) || Irssi::settings_get_bool("bitlbee_typing_allwin")) {
-		foreach my $key (keys(%typing)) {
-			$line .= " ".$key;
-			if ($typing{$key}==2) { $line .= " (stale)"; }
-		}
-		if ($line ne "") {
-			$item->default_handler($get_size_only, "{sb typing:$line}", 0, 1);
-			$line = "";
-		}
-	} 
-}
-
-sub window_change {
-	Irssi::statusbar_items_redraw('typing_notice');
-	my $win = !Irssi::active_win() ? undef : Irssi::active_win()->{active};
-	if (ref $win && ($win->{server}->{tag} eq $bitlbee_server->{tag})) {
-		if (!$keylog_active) {
-			$keylog_active = 1;
-			Irssi::signal_add_last('gui key pressed', 'key_pressed');
-		}
-	} else {
-		if ($keylog_active) {
-			$keylog_active = 0;
-			Irssi::signal_remove('gui key pressed', 'key_pressed');
-		}
-	}
-}
-
-sub key_pressed {
-	return if !Irssi::settings_get_bool("bitlbee_send_typing");
-	my $key = shift;
-	if ($key != 9 && $key != 10 && $lastkey != 27 && $key != 27 
-	   && $lastkey != 91 && $key != 126 && $key != 127) 
-	{
-		my $server = Irssi::active_server();
-		my $window = Irssi::active_win();
-		my $nick = $window->get_active_name();
-
-		if ($server->{tag} eq $bitlbee_server->{tag} && $nick ne "(status)" && $nick ne "root") {
-			if( grep $_ eq $nick, @control_channels ){ # send typing if in control channel
-				my $input = Irssi::parse_special("\$L");
-				my ($first_word) = split(/ /,$input);
-				if ($input !~ /^$command_char.*/ && $first_word =~ s/$to_char$//){
-					send_typing($first_word);
-				}
-			} else { # or any other channels / query
-				my $input = Irssi::parse_special("\$L");
-				if ($input !~ /^$command_char.*/ && length($input) > 0){
-					send_typing($nick);
-				}
-			}
-		}
-	}
-	$lastkey = $key;
-}
-
-sub out_empty {
-	my ($a) = @_;
-	my($nick,$tag)=@{$a};
-	delete($out_typing{$nick});
-	Irssi::timeout_remove($timer_tag{$nick});
-	delete($timer_tag{$nick});
-	$bitlbee_server->command("^CTCP $nick TYPING 0");
-}
-
-sub send_typing {
-	my $nick = shift;
-	if (!exists($out_typing{$nick}) || time - $out_typing{$nick} > $KEEP_TYPING_TIMEOUT) {
-		$bitlbee_server->command("^CTCP $nick TYPING 1");
-		$out_typing{$nick} = time;
-		### Reset 'stop-typing' timer
-		Irssi::timeout_remove($timer_tag{$nick});
-		delete($timer_tag{$nick});
-
-		### create new timer
-		$timer_tag{$nick} = Irssi::timeout_add_once($STOP_TYPING_TIMEOUT*1000, 'out_empty', ["$nick", $bitlbee_server->{tag}]);
-	}
-}
-
-#README: Delete the old bitlbee_send_typing string from ~/.irssi/config. A boolean is better.
-
-sub db_typing { 
-	print "Detected channels: ";
-	print Dumper(@control_channels);
-	print "Detected server tag: ".$bitlbee_server->{tag};
-	print "Tag: ".Dumper(%tag);	
-	print "Timer Tag: ".Dumper(%timer_tag);	
-	print "Typing: ".Dumper(%typing);	
-	print "Out Typing: ".Dumper(%out_typing);	
-}
-
-Irssi::command_bind('db_typing','db_typing');
-
-Irssi::settings_add_bool("bitlbee","bitlbee_send_typing",1);
-Irssi::settings_add_bool("bitlbee","bitlbee_typing_allwin",0);
-
-Irssi::signal_add("ctcp msg", "event_ctcp_msg");
-Irssi::signal_add("message private", "event_msg");
-Irssi::signal_add("message public", "event_msg");
-Irssi::signal_add("message quit", "event_quit");
-Irssi::signal_add_last('window changed', 'window_change');
-Irssi::signal_add_last('gui key pressed', 'key_pressed');
-Irssi::statusbar_item_register('typing_notice', undef, 'typing_notice');
-Irssi::statusbars_recreate_items();
--- a/irssi/scripts/cap_sasl.pl	Wed Nov 19 19:08:21 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,272 +0,0 @@
-use strict;
-use Irssi;
-use vars qw($VERSION %IRSSI);
-# $Id$
-
-use MIME::Base64;
-
-$VERSION = "1.1";
-
-%IRSSI = (
-    authors     => 'Michael Tharp and Jilles Tjoelker',
-    contact     => '[email protected]',
-    name        => 'cap_sasl.pl',
-    description => 'Implements PLAIN SASL authentication mechanism for use with charybdis ircds, and enables CAP MULTI-PREFIX',
-    license     => 'GNU General Public License',
-    url         => 'http://sasl.charybdis.be/',
-);
-
-my %sasl_auth = ();
-my %mech = ();
-
-sub timeout;
-
-sub server_connected {
-	my $server = shift;
-	$server->send_raw_now("CAP LS");
-}
-
-sub event_cap {
-	my ($server, $args, $nick, $address) = @_;
-	my ($subcmd, $caps, $tosend);
-
-	$tosend = '';
-	if ($args =~ /^\S+ (\S+) :(.*)$/) {
-		$subcmd = uc $1;
-		$caps = ' '.$2.' ';
-		if ($subcmd eq 'LS') {
-			$tosend .= ' multi-prefix' if $caps =~ / multi-prefix /i;
-			$tosend .= ' sasl' if $caps =~ / sasl /i && defined($sasl_auth{$server->{tag}});
-			$tosend =~ s/^ //;
-			$server->print('', "CLICAP: supported by server:$caps");
-			if (!$server->{connected}) {
-				if ($tosend eq '') {
-					$server->send_raw_now("CAP END");
-				} else {
-					$server->print('', "CLICAP: requesting: $tosend");
-					$server->send_raw_now("CAP REQ :$tosend");
-				}
-			}
-			Irssi::signal_stop();
-		} elsif ($subcmd eq 'ACK') {
-			$server->print('', "CLICAP: now enabled:$caps");
-			if ($caps =~ / sasl /i) {
-				$sasl_auth{$server->{tag}}{buffer} = '';
-				if($mech{$sasl_auth{$server->{tag}}{mech}}) {
-					$server->send_raw_now("AUTHENTICATE " . $sasl_auth{$server->{tag}}{mech});
-					Irssi::timeout_add_once(5000, \&timeout, $server->{tag});
-				}else{
-					$server->print('', 'SASL: attempted to start unknown mechanism "' . $sasl_auth{$server->{tag}}{mech} . '"');
-				}
-			}
-			elsif (!$server->{connected}) {
-				$server->send_raw_now("CAP END");
-			}
-			Irssi::signal_stop();
-		} elsif ($subcmd eq 'NAK') {
-			$server->print('', "CLICAP: refused:$caps");
-			if (!$server->{connected}) {
-				$server->send_raw_now("CAP END");
-			}
-			Irssi::signal_stop();
-		} elsif ($subcmd eq 'LIST') {
-			$server->print('', "CLICAP: currently enabled:$caps");
-			Irssi::signal_stop();
-		}
-	}
-}
-
-sub event_authenticate {
-	my ($server, $args, $nick, $address) = @_;
-	my $sasl = $sasl_auth{$server->{tag}};
-	return unless $sasl && $mech{$sasl->{mech}};
-
-	$sasl->{buffer} .= $args;
-	return if length($args) == 400;
-
-	my $data = $sasl->{buffer} eq '+' ? '' : decode_base64($sasl->{buffer});
-	my $out = $mech{$sasl->{mech}}($sasl, $data);
-	$out = '' unless defined $out;
-	$out = $out eq '' ? '+' : encode_base64($out, '');
-
-	while(length $out >= 400) {
-		my $subout = substr($out, 0, 400, '');
-		$server->send_raw_now("AUTHENTICATE $subout");
-	}
-	if(length $out) {
-		$server->send_raw_now("AUTHENTICATE $out");
-	}else{ # Last piece was exactly 400 bytes, we have to send some padding to indicate we're done
-		$server->send_raw_now("AUTHENTICATE +");
-	}
-
-	$sasl->{buffer} = '';
-	Irssi::signal_stop();
-}
-
-sub event_saslend {
-	my ($server, $args, $nick, $address) = @_;
-
-	my $data = $args;
-	$data =~ s/^\S+ :?//;
-	# need this to see it, ?? -- jilles
-	$server->print('', $data);
-	if (!$server->{connected}) {
-		$server->send_raw_now("CAP END");
-	}
-}
-
-sub timeout {
-	my $tag = shift;
-	my $server = Irssi::server_find_tag($tag);
-	if(!$server->{connected}) {
-		$server->print('', "SASL: authentication timed out");
-		$server->send_raw_now("CAP END");
-	}
-}
-
-sub cmd_sasl {
-	my ($data, $server, $item) = @_;
-
-	if ($data ne '') {
-		Irssi::command_runsub ('sasl', $data, $server, $item);
-	} else {
-		cmd_sasl_show(@_);
-	}
-}
-
-sub cmd_sasl_set {
-	my ($data, $server, $item) = @_;
-
-	if (my($net, $u, $p, $m) = $data =~ /^(\S+) (\S+) (\S+) (\S+)$/) {
-		if($mech{uc $m}) {
-			$sasl_auth{$net}{user} = $u;
-			$sasl_auth{$net}{password} = $p;
-			$sasl_auth{$net}{mech} = uc $m;
-			Irssi::print("SASL: added $net: [$m] $sasl_auth{$net}{user} *");
-		}else{
-			Irssi::print("SASL: unknown mechanism $m");
-		}
-	} elsif ($data =~ /^(\S+)$/) {
-		$net = $1;
-		if (defined($sasl_auth{$net})) {
-			delete $sasl_auth{$net};
-			Irssi::print("SASL: deleted $net");
-		} else {
-			Irssi::print("SASL: no entry for $net");
-		}
-	} else {
-		Irssi::print("SASL: usage: /sasl set <net> <user> <password or keyfile> <mechanism>");
-	}
-}
-
-sub cmd_sasl_show {
-	#my ($data, $server, $item) = @_;
-	my $net;
-	my $count = 0;
-
-	foreach $net (keys %sasl_auth) {
-		Irssi::print("SASL: $net: [$sasl_auth{$net}{mech}] $sasl_auth{$net}{user} *");
-		$count++;
-	}
-	Irssi::print("SASL: no networks defined") if !$count;
-}
-
-sub cmd_sasl_save {
-	#my ($data, $server, $item) = @_;
-	my $file = Irssi::get_irssi_dir()."/sasl.auth";
-	open FILE, "> $file" or return;
-	foreach my $net (keys %sasl_auth) {
-		printf FILE ("%s\t%s\t%s\t%s\n", $net, $sasl_auth{$net}{user}, $sasl_auth{$net}{password}, $sasl_auth{$net}{mech});
-	}
-	close FILE;
-	Irssi::print("SASL: auth saved to $file");
-}
-
-sub cmd_sasl_load {
-	#my ($data, $server, $item) = @_;
-	my $file = Irssi::get_irssi_dir()."/sasl.auth";
-
-	open FILE, "< $file" or return;
-	%sasl_auth = ();
-	while (<FILE>) {
-		chomp;
-		my ($net, $u, $p, $m) = split (/\t/, $_, 4);
-		$m ||= "PLAIN";
-		if($mech{uc $m}) {
-			$sasl_auth{$net}{user} = $u;
-			$sasl_auth{$net}{password} = $p;
-			$sasl_auth{$net}{mech} = uc $m;
-		}else{
-			Irssi::print("SASL: unknown mechanism $m");
-		}
-	}
-	close FILE;
-	Irssi::print("SASL: auth loaded from $file");
-}
-
-sub cmd_sasl_mechanisms {
-	Irssi::print("SASL: mechanisms supported: " . join(" ", keys %mech));
-}
-
-Irssi::signal_add_first('server connected', \&server_connected);
-Irssi::signal_add('event cap', \&event_cap);
-Irssi::signal_add('event authenticate', \&event_authenticate);
-Irssi::signal_add('event 903', 'event_saslend');
-Irssi::signal_add('event 904', 'event_saslend');
-Irssi::signal_add('event 905', 'event_saslend');
-Irssi::signal_add('event 906', 'event_saslend');
-Irssi::signal_add('event 907', 'event_saslend');
-
-Irssi::command_bind('sasl', \&cmd_sasl);
-Irssi::command_bind('sasl load', \&cmd_sasl_load);
-Irssi::command_bind('sasl save', \&cmd_sasl_save);
-Irssi::command_bind('sasl set', \&cmd_sasl_set);
-Irssi::command_bind('sasl show', \&cmd_sasl_show);
-Irssi::command_bind('sasl mechanisms', \&cmd_sasl_mechanisms);
-
-$mech{PLAIN} = sub {
-	my($sasl, $data) = @_;
-	my $u = $sasl->{user};
-	my $p = $sasl->{password};
-
-	join("\0", $u, $u, $p);
-};
-
-eval {
-	use Crypt::OpenSSL::Bignum;
-	use Crypt::DH;
-	use Crypt::Blowfish;
-	use Math::BigInt;
-	sub bin2bi { return Crypt::OpenSSL::Bignum->new_from_bin(shift)->to_decimal } # binary to BigInt
-	sub bi2bin { return Crypt::OpenSSL::Bignum->new_from_decimal((shift)->bstr)->to_bin } # BigInt to binary
-	$mech{'DH-BLOWFISH'} = sub {
-		my($sasl, $data) = @_;
-		my $u = $sasl->{user};
-		my $pass = $sasl->{password};
-
-		# Generate private key and compute secret key
-		my($p, $g, $y) = unpack("(n/a*)3", $data);
-		my $dh = Crypt::DH->new(p => bin2bi($p), g => bin2bi($g));
-		$dh->generate_keys;
-
-		my $secret = bi2bin($dh->compute_secret(bin2bi($y)));
-		my $pubkey = bi2bin($dh->pub_key);
-
-		# Pad the password to the nearest multiple of blocksize and encrypt
-		$pass .= "\0";
-		$pass .= chr(rand(256)) while length($pass) % 8;
-
-		my $cipher = Crypt::Blowfish->new($secret);
-		my $crypted = '';
-		while(length $pass) {
-			my $clear = substr($pass, 0, 8, '');
-			$crypted .= $cipher->encrypt($clear);
-		}
-
-		pack("n/a*Z*a*", $pubkey, $u, $crypted);
-	};
-};
-
-cmd_sasl_load();
-
-# vim: ts=4
--- a/irssi/scripts/hilightwin.pl	Wed Nov 19 19:08:21 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-#
-# Print hilighted messages & private messages to window named "hilight" for
-# irssi 0.7.99 by Timo Sirainen
-#
-# Modded a tiny bit by znx to stop private messages entering the hilighted
-# window (can be toggled) and to put up a timestamp.
-#
-
-use Irssi;
-use POSIX;
-use vars qw($VERSION %IRSSI); 
-
-$VERSION = "0.02";
-%IRSSI = (
-    authors     => "Timo \'cras\' Sirainen, Mark \'znx\' Sangster",
-    contact     => "tss\@iki.fi, znxster\@gmail.com", 
-    name        => "hilightwin",
-    description => "Print hilighted messages to window named \"hilight\"",
-    license     => "Public Domain",
-    url         => "http://irssi.org/",
-    changed     => "Sun May 25 18:59:57 BST 2008"
-);
-
-sub sig_printtext {
-    my ($dest, $text, $stripped) = @_;
-
-    my $opt = MSGLEVEL_HILIGHT;
-
-    if(Irssi::settings_get_bool('hilightwin_showprivmsg')) {
-        $opt = MSGLEVEL_HILIGHT|MSGLEVEL_MSGS;
-    }
-    
-    if(
-        ($dest->{level} & ($opt)) &&
-        ($dest->{level} & MSGLEVEL_NOHILIGHT) == 0
-    ) {
-        $window = Irssi::window_find_name('hilight');
-        
-        if ($dest->{level} & MSGLEVEL_PUBLIC) {
-            $text = $dest->{target}.": ".$text;
-        }
-        $text = strftime(
-            Irssi::settings_get_str('timestamp_format')." ",
-            localtime
-        ).$text;
-        $window->print($text, MSGLEVEL_NEVER) if ($window);
-    }
-}
-
-$window = Irssi::window_find_name('hilight');
-Irssi::print("Create a window named 'hilight'") if (!$window);
-
-Irssi::settings_add_bool('hilightwin','hilightwin_showprivmsg',1);
-
-Irssi::signal_add('print text', 'sig_printtext');
-
-# vim:set ts=4 sw=4 et:
--- a/irssi/scripts/nicklist.pl	Wed Nov 19 19:08:21 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,611 +0,0 @@
-# for documentation: see http://wouter.coekaerts.be/site/irssi/nicklist
-
-use Irssi;
-use strict;
-use IO::Handle; # for (auto)flush
-use Fcntl; # for sysopen
-use vars qw($VERSION %IRSSI);
-$VERSION = '0.4.6';
-%IRSSI = (
-	authors     => 'Wouter Coekaerts',
-	contact     => '[email protected]',
-	name        => 'nicklist',
-	description => 'draws a nicklist to another terminal, or at the right of your irssi in the same terminal',
-	license     => 'GPLv2',
-	url         => 'http://wouter.coekaerts.be/irssi',
-	changed     => '29/06/2004'
-);
-
-sub cmd_help {
-	print ( <<EOF
-Commands:
-NICKLIST HELP
-NICKLIST SCROLL <nr of lines>
-NICKLIST SCREEN
-NICKLIST FIFO
-NICKLIST OFF
-NICKLIST UPDATE
-
-For help see: http://wouter.coekaerts.be/site/irssi/nicklist
-
-in short:
-
-1. FIFO MODE
-- in irssi: /NICKLIST FIFO (only the first time, to create the fifo)
-- in a shell, in a window where you want the nicklist: cat ~/.irssi/nicklistfifo
-- back in irssi:
-    /SET nicklist_heigth <height of nicklist>
-    /SET nicklist_width <width of nicklist>
-    /NICKLIST FIFO
-
-2. SCREEN MODE
-- start irssi inside screen ("screen irssi")
-- /NICKLIST SCREEN
-EOF
-    );
-}
-
-my $prev_lines = 0;                  # number of lines in previous written nicklist
-my $scroll_pos = 0;                  # scrolling position
-my $cursor_line;                     # line the cursor is currently on
-my ($OFF, $SCREEN, $FIFO) = (0,1,2); # modes
-my $mode = $OFF;                     # current mode
-my $need_redraw = 0;                 # nicklist needs redrawing
-my $screen_resizing = 0;             # terminal is being resized
-my $active_channel;                  # (REC)
-
-my @nicklist=();                     # array of hashes, containing the internal nicklist of the active channel
-	# nick => realnick
-	# mode =>
-	my ($MODE_OP, $MODE_HALFOP, $MODE_VOICE, $MODE_NORMAL) = (0,1,2,3);
-	# status =>
-	my ($STATUS_NORMAL, $STATUS_JOINING, $STATUS_PARTING, $STATUS_QUITING, $STATUS_KICKED, $STATUS_SPLIT) = (0,1,2,3,4,5);
-	# text => text to be printed
-	# cmp => text used to compare (sort) nicks
-
-
-# 'cached' settings
-my ($screen_prefix, $irssi_width, @prefix_mode, @prefix_status, $height, $nicklist_width);
-
-sub read_settings {
-	($screen_prefix = Irssi::settings_get_str('nicklist_screen_prefix')) =~ s/\\e/\033/g;
-
-	($prefix_mode[$MODE_OP] = Irssi::settings_get_str('nicklist_prefix_mode_op')) =~ s/\\e/\033/g;
-	($prefix_mode[$MODE_HALFOP] = Irssi::settings_get_str('nicklist_prefix_mode_halfop')) =~ s/\\e/\033/g;
-	($prefix_mode[$MODE_VOICE] = Irssi::settings_get_str('nicklist_prefix_mode_voice')) =~ s/\\e/\033/g;
-	($prefix_mode[$MODE_NORMAL] = Irssi::settings_get_str('nicklist_prefix_mode_normal')) =~ s/\\e/\033/g;
-	
-	if ($mode != $SCREEN) {
-		$height = Irssi::settings_get_int('nicklist_height');
-	}
-	my $new_nicklist_width = Irssi::settings_get_int('nicklist_width');
-	if ($new_nicklist_width != $nicklist_width && $mode == $SCREEN) {
-		sig_terminal_resized();
-	}
-	$nicklist_width = $new_nicklist_width;
-}
-
-sub update {
-	read_settings();
-	make_nicklist();
-}
-
-##################
-##### OUTPUT #####
-##################
-
-### off ###
-
-sub cmd_off {
-	if ($mode == $SCREEN) {
-		screen_stop();
-	} elsif ($mode == $FIFO) {
-		fifo_stop();
-	}
-}
-
-### fifo ###
-
-sub cmd_fifo_start {
-	read_settings();
-	my $path = Irssi::settings_get_str('nicklist_fifo_path');
-	unless (-p $path) { # not a pipe
-	    if (-e _) { # but a something else
-	        die "$0: $path exists and is not a pipe, please remove it\n";
-	    } else {
-	        require POSIX;
-	        POSIX::mkfifo($path, 0666) or die "can\'t mkfifo $path: $!";
-		Irssi::print("Fifo created. Start reading it (\"cat $path\") and try again.");
-		return;
-	    }
-	}
-	if (!sysopen(FIFO, $path, O_WRONLY | O_NONBLOCK)) { # or die "can't write $path: $!";
-		Irssi::print("Couldn\'t write to the fifo ($!). Please start reading the fifo (\"cat $path\") and try again.");
-		return;
-	}
-	FIFO->autoflush(1);
-	print FIFO "\033[2J\033[1;1H"; # erase screen & jump to 0,0
-	$cursor_line = 0;
-	if ($mode == $SCREEN) {
-		screen_stop();
-	}
-	$mode = $FIFO;
-	make_nicklist();
-}
-
-sub fifo_stop {
-	close FIFO;
-	$mode = $OFF;
-	Irssi::print("Fifo closed.");
-}
-
-### screen ###
-
-sub cmd_screen_start {
-	if (!defined($ENV{'STY'})) {
-		Irssi::print 'screen not detected, screen mode only works inside screen';
-		return;
-	}
-	read_settings();
-	if ($mode == $SCREEN) {return;}
-	if ($mode == $FIFO) {
-		fifo_stop();
-	}
-	$mode = $SCREEN;
-	Irssi::signal_add_last('gui print text finished', \&sig_gui_print_text_finished);
-	Irssi::signal_add_last('gui page scrolled', \&sig_page_scrolled);
-	Irssi::signal_add('terminal resized', \&sig_terminal_resized);
-	screen_size();
-	make_nicklist();
-}
-
-sub screen_stop {
-	$mode = $OFF;
-	Irssi::signal_remove('gui print text finished', \&sig_gui_print_text_finished);
-	Irssi::signal_remove('gui page scrolled', \&sig_page_scrolled);
-	Irssi::signal_remove('terminal resized', \&sig_terminal_resized);
-	system 'screen -x '.$ENV{'STY'}.' -X fit';
-}
-
-sub screen_size {
-	if ($mode != $SCREEN) {
-		return;
-	}
-	$screen_resizing = 1;
-	# fit screen
-	system 'screen -x '.$ENV{'STY'}.' -X fit';
-	# get size (from perldoc -q size)
-	my ($winsize, $row, $col, $xpixel, $ypixel);
-	eval 'use Term::ReadKey; ($col, $row, $xpixel, $ypixel) = GetTerminalSize';
-	#	require Term::ReadKey 'GetTerminalSize';
-	#	($col, $row, $xpixel, $ypixel) = Term::ReadKey::GetTerminalSize;
-	#};
-	if ($@) { # no Term::ReadKey, try the ugly way
-		eval {
-			require 'sys/ioctl.ph';
-			# without this reloading doesn't work. workaround for some unknown bug
-			do 'asm/ioctls.ph';
-		};
-		
-		# ugly way not working, let's try something uglier, the dg-hack(tm) (constant for linux only?)
-		if($@) { no strict 'refs'; *TIOCGWINSZ = sub { return 0x5413 } }
-		
-		unless (defined &TIOCGWINSZ) {
-			die "Term::ReadKey not found, and ioctl 'workaround' failed. Install the Term::ReadKey perl module to use screen mode.\n";
-		}
-		open(TTY, "+</dev/tty") or die "No tty: $!";
-		unless (ioctl(TTY, &TIOCGWINSZ, $winsize='')) {
-			die "Term::ReadKey not found, and ioctl 'workaround' failed ($!). Install the Term::ReadKey perl module to use screen mode.\n";
-		}
-		close(TTY);
-		($row, $col, $xpixel, $ypixel) = unpack('S4', $winsize);
-	}
-	
-	# set screen width
-	$irssi_width = $col-$nicklist_width-1;
-	$height = $row-1;
-	
-	# on some recent systems, "screen -X fit; screen -X width -w 50" doesn't work, needs a sleep in between the 2 commands
-	# so we wait a second before setting the width
-	Irssi::timeout_add_once(1000, sub {
-		my ($new_irssi_width) = @_;
-		system 'screen -x '.$ENV{'STY'}.' -X width -w ' . $new_irssi_width;
-		# and then we wait another second for the resizing, and then redraw.
-		Irssi::timeout_add_once(1000,sub {$screen_resizing = 0; redraw()}, []);
-	}, $irssi_width);
-}
-
-sub sig_terminal_resized {
-	if ($screen_resizing) {
-		return;
-	}
-	$screen_resizing = 1;
-	Irssi::timeout_add_once(1000,\&screen_size,[]);
-}
-
-
-### both ###
-
-sub nicklist_write_start {
-	if ($mode == $SCREEN) {
-		print STDERR "\033P\033[s\033\\"; # save cursor
-	}
-}
-
-sub nicklist_write_end {
-	if ($mode == $SCREEN) {
-		print STDERR "\033P\033[u\033\\"; # restore cursor
-	}
-}
-
-sub nicklist_write_line {
-	my ($line, $data) = @_;
-	if ($mode == $SCREEN) {
-		print STDERR "\033P\033[" . ($line+1) . ';'. ($irssi_width+1) .'H'. $screen_prefix . $data . "\033\\";
-	} elsif ($mode == $FIFO) {
-		$data = "\033[m$data"; # reset color
-		if ($line == $cursor_line+1) {
-			$data = "\n$data"; # next line
-		} elsif ($line == $cursor_line) {
-			$data = "\033[1G".$data; # back to beginning of line
-		} else {
-			$data = "\033[".($line+1).";0H".$data; # jump
-		}
-		$cursor_line=$line;
-		print(FIFO $data) or fifo_stop();
-	}
-}
-
-# recalc the text of the nicklist item
-sub calc_text {
-	my ($nick) = @_;
-	my $tmp = $nicklist_width-3;
-	(my $text = $nick->{'nick'}) =~ s/^(.{$tmp})..+$/$1\033[34m~\033[m/;
-	$nick->{'text'} = $prefix_mode[$nick->{'mode'}] . $text . (' ' x ($nicklist_width-length($nick->{'nick'})-1));
-	$nick->{'cmp'} = $nick->{'mode'}.lc($nick->{'nick'});
-}
-
-# redraw the given nick (nr) if it is visible
-sub redraw_nick_nr {
-	my ($nr) = @_;
-	my $line = $nr - $scroll_pos;
-	if ($line >= 0 && $line < $height) {
-		nicklist_write_line($line, $nicklist[$nr]->{'text'});
-	}
-}
-
-# nick was inserted, redraw area if necessary
-sub draw_insert_nick_nr {
-	my ($nr) = @_;
-	my $line = $nr - $scroll_pos;
-	if ($line < 0) { # nick is inserted above visible area
-		$scroll_pos++; # 'scroll' down :)
-	} elsif ($line < $height) { # line is visible
-		if ($mode == $SCREEN) {
-			need_redraw();
-		} elsif ($mode == $FIFO) {
-			my $data = "\033[m\033[L". $nicklist[$nr]->{'text'}; # reset color & insert line & write nick
-			if ($line == $cursor_line) {
-				$data = "\033[1G".$data; # back to beginning of line
-			} else {
-				$data = "\033[".($line+1).";1H".$data; # jump
-			}
-			$cursor_line=$line;
-			print(FIFO $data) or fifo_stop();
-			if ($prev_lines < $height) {
-				$prev_lines++; # the nicklist has one line more
-			}
-		}
-	}
-}
-
-sub draw_remove_nick_nr {
-	my ($nr) = @_;
-	my $line = $nr - $scroll_pos;
-	if ($line < 0) { # nick removed above visible area
-		$scroll_pos--; # 'scroll' up :)
-	} elsif ($line < $height) { # line is visible
-		if ($mode == $SCREEN) {
-			need_redraw();
-		} elsif ($mode == $FIFO) {
-			#my $data = "\033[m\033[L[i$line]". $nicklist[$nr]->{'text'}; # reset color & insert line & write nick
-			my $data = "\033[M"; # delete line
-			if ($line != $cursor_line) {
-				$data = "\033[".($line+1)."d".$data; # jump
-			}
-			$cursor_line=$line;
-			print(FIFO $data) or fifo_stop();
-			if (@nicklist-$scroll_pos >= $height) {
-				redraw_nick_nr($scroll_pos+$height-1);
-			}
-		}
-	}
-}
-
-# redraw the whole nicklist
-sub redraw {
-	$need_redraw = 0;
-	#make_nicklist();
-	nicklist_write_start();
-	my $line = 0;
-	### draw nicklist ###
-	for (my $i=$scroll_pos;$line < $height && $i < @nicklist; $i++) {
-		nicklist_write_line($line++, $nicklist[$i]->{'text'});
-	}
-
-	### clean up other lines ###
-	my $real_lines = $line;
-	while($line < $prev_lines) {
-		nicklist_write_line($line++,' ' x $nicklist_width);
-	}
-	$prev_lines = $real_lines;
-	nicklist_write_end();
-}
-
-# redraw (with little delay to avoid redrawing to much)
-sub need_redraw {
-	if(!$need_redraw) {
-		$need_redraw = 1;
-		Irssi::timeout_add_once(10,\&redraw,[]);
-	}
-}
-
-sub sig_page_scrolled {
-	$prev_lines = $height; # we'll need to redraw everything if he scrolled up
-	need_redraw;
-}
-
-# redraw (with delay) if the window is visible (only in screen mode)
-sub sig_gui_print_text_finished {
-	if ($need_redraw) { # there's already a redraw 'queued'
-		return;
-	}
-	my $window = @_[0];
-	if ($window->{'refnum'} == Irssi::active_win->{'refnum'} || Irssi::settings_get_str('nicklist_screen_split_windows') eq '*') {
-		need_redraw;
-		return;
-	}
-	foreach my $win (split(/[ ,]/, Irssi::settings_get_str('nicklist_screen_split_windows'))) {
-		if ($window->{'refnum'} == $win || $window->{'name'} eq $win) {
-			need_redraw;
-			return;
-		}
-	}
-}
-
-####################
-##### NICKLIST #####
-####################
-
-# returns the position of the given nick(as string) in the (internal) nicklist
-sub find_nick {
-	my ($nick) = @_;
-	for (my $i=0;$i < @nicklist; $i++) {
-		if ($nicklist[$i]->{'nick'} eq $nick) {
-			return $i;
-		}
-	}
-	return -1;
-}
-
-# find position where nick should be inserted into the list
-sub find_insert_pos {
-	my ($cmp)= @_;
-	for (my $i=0;$i < @nicklist; $i++) {
-		if ($nicklist[$i]->{'cmp'} gt $cmp) {
-			return $i;
-		}
-	}
-	return scalar(@nicklist); #last
-}
-
-# make the (internal) nicklist (@nicklist)
-sub make_nicklist {
-	@nicklist = ();
-	$scroll_pos = 0;
-
-	### get & check channel ###
-	my $channel = Irssi::active_win->{active};
-
-	if (!$channel || (ref($channel) ne 'Irssi::Irc::Channel' && ref($channel) ne 'Irssi::Silc::Channel' && ref($channel) ne 'Irssi::Xmpp::Channel') || $channel->{'type'} ne 'CHANNEL' || ($channel->{chat_type} ne 'SILC' && !$channel->{'names_got'}) ) {
-		$active_channel = undef;
-		# no nicklist
-	} else {
-		$active_channel = $channel;
-		### make nicklist ###
-		my $thisnick;
-		foreach my $nick (sort {(($a->{'op'}?'1':$a->{'halfop'}?'2':$a->{'voice'}?'3':'4').lc($a->{'nick'}))
-		                    cmp (($b->{'op'}?'1':$b->{'halfop'}?'2':$b->{'voice'}?'3':'4').lc($b->{'nick'}))} $channel->nicks()) {
-			$thisnick = {'nick' => $nick->{'nick'}, 'mode' => ($nick->{'op'}?$MODE_OP:$nick->{'halfop'}?$MODE_HALFOP:$nick->{'voice'}?$MODE_VOICE:$MODE_NORMAL)};
-			calc_text($thisnick);
-			push @nicklist, $thisnick;
-		}
-	}
-	need_redraw();
-}
-
-# insert nick(as hash) into nicklist
-# pre: cmp has to be calculated
-sub insert_nick {
-	my ($nick) = @_;
-	my $nr = find_insert_pos($nick->{'cmp'});
-	splice @nicklist, $nr, 0, $nick;
-	draw_insert_nick_nr($nr);
-}
-
-# remove nick(as nr) from nicklist
-sub remove_nick {
-	my ($nr) = @_;
-	splice @nicklist, $nr, 1;
-	draw_remove_nick_nr($nr);
-}
-
-###################
-##### ACTIONS #####
-###################
-
-# scroll the nicklist, arg = number of lines to scroll, positive = down, negative = up
-sub cmd_scroll {
-	if (!$active_channel) { # not a channel active
-		return;
-	}
-	my @nicks=Irssi::active_win->{active}->nicks;
-	my $nick_count = scalar(@nicks)+0;
-	my $channel = Irssi::active_win->{active};
-	if (!$channel || $channel->{type} ne 'CHANNEL' || !$channel->{names_got} || $nick_count <= Irssi::settings_get_int('nicklist_height')) {
-		return;
-	}
-	$scroll_pos += @_[0];
-
-	if ($scroll_pos > $nick_count - $height) {
-		$scroll_pos = $nick_count - $height;
-	}
-	if ($scroll_pos <= 0) {
-		$scroll_pos = 0;
-	}
-	need_redraw();
-}
-
-sub is_active_channel {
-	my ($server,$channel) = @_; # (channel as string)
-	return ($server && $server->{'tag'} eq $active_channel->{'server'}->{'tag'} && $server->channel_find($channel) && $active_channel && $server->channel_find($channel)->{'name'} eq $active_channel->{'name'});
-}
-
-sub sig_channel_wholist { # this is actualy a little late, when the names are received would be better
-	my ($channel) = @_;
-	if (Irssi::active_win->{'active'} && Irssi::active_win->{'active'}->{'name'} eq $channel->{'name'}) { # the channel joined is active
-		make_nicklist
-	}
-}
-
-sub sig_join {
-	my ($server,$channel,$nick,$address) = @_;
-	if (!is_active_channel($server,$channel)) {
-		return;
-	}
-	my $newnick = {'nick' => $nick, 'mode' => $MODE_NORMAL};
-	calc_text($newnick);
-	insert_nick($newnick);
-}
-
-sub sig_kick {
-	my ($server, $channel, $nick, $kicker, $address, $reason) = @_;
-	if (!is_active_channel($server,$channel)) {
-		return;
-	}
-	my $nr = find_nick($nick);
-	if ($nr == -1) {
-		Irssi::print("nicklist warning: $nick was kicked from $channel, but not found in nicklist");
-	} else {
-		remove_nick($nr);
-	}
-}
-
-sub sig_part {
-	my ($server,$channel,$nick,$address, $reason) = @_;
-	if (!is_active_channel($server,$channel)) {
-		return;
-	}
-	my $nr = find_nick($nick);
-	if ($nr == -1) {
-		Irssi::print("nicklist warning: $nick has parted $channel, but was not found in nicklist");
-	} else {
-		remove_nick($nr);
-	}
-
-}
-
-sub sig_quit {
-	my ($server,$nick,$address, $reason) = @_;
-	if ($server->{'tag'} ne $active_channel->{'server'}->{'tag'}) {
-		return;
-	}
-	my $nr = find_nick($nick);
-	if ($nr != -1) {
-		remove_nick($nr);
-	}
-}
-
-sub sig_nick {
-	my ($server, $newnick, $oldnick, $address) = @_;
-	if ($server->{'tag'} ne $active_channel->{'server'}->{'tag'}) {
-		return;
-	}
-	my $nr = find_nick($oldnick);
-	if ($nr != -1) { # if nick was found (nickchange is in current channel)
-		my $nick = $nicklist[$nr];
-		remove_nick($nr);
-		$nick->{'nick'} = $newnick;
-		calc_text($nick);
-		insert_nick($nick);
-	}
-}
-
-sub sig_mode {
-	my ($channel, $nick, $setby, $mode, $type) = @_; # (nick and channel as rec)
-	if ($channel->{'server'}->{'tag'} ne $active_channel->{'server'}->{'tag'} || $channel->{'name'} ne $active_channel->{'name'}) {
-		return;
-	}
-	my $nr = find_nick($nick->{'nick'});
-	if ($nr == -1) {
-		Irssi::print("nicklist warning: $nick->{'nick'} had mode set on $channel->{'name'}, but was not found in nicklist");
-	} else {
-		my $nicklist_item = $nicklist[$nr];
-		remove_nick($nr);
-		$nicklist_item->{'mode'} = ($nick->{'op'}?$MODE_OP:$nick->{'halfop'}?$MODE_HALFOP:$nick->{'voice'}?$MODE_VOICE:$MODE_NORMAL);
-		calc_text($nicklist_item);
-		insert_nick($nicklist_item);
-	}
-}
-
-##### command binds #####
-Irssi::command_bind 'nicklist' => sub {
-    my ( $data, $server, $item ) = @_;
-    $data =~ s/\s+$//g;
-    Irssi::command_runsub ('nicklist', $data, $server, $item ) ;
-};
-Irssi::signal_add_first 'default command nicklist' => sub {
-	# gets triggered if called with unknown subcommand
-	cmd_help();
-};
-Irssi::command_bind('nicklist update',\&update);
-Irssi::command_bind('nicklist help',\&cmd_help);
-Irssi::command_bind('nicklist scroll',\&cmd_scroll);
-Irssi::command_bind('nicklist fifo',\&cmd_fifo_start);
-Irssi::command_bind('nicklist screen',\&cmd_screen_start);
-Irssi::command_bind('nicklist screensize',\&screen_size);
-Irssi::command_bind('nicklist off',\&cmd_off);
-
-##### signals #####
-Irssi::signal_add_last('window item changed', \&make_nicklist);
-Irssi::signal_add_last('window changed', \&make_nicklist);
-Irssi::signal_add_last('channel wholist', \&sig_channel_wholist);
-Irssi::signal_add_first('message join', \&sig_join); # first, to be before ignores
-Irssi::signal_add_first('message part', \&sig_part);
-Irssi::signal_add_first('message kick', \&sig_kick);
-Irssi::signal_add_first('message quit', \&sig_quit);
-Irssi::signal_add_first('message nick', \&sig_nick);
-Irssi::signal_add_first('message own_nick', \&sig_nick);
-Irssi::signal_add_first('nick mode changed', \&sig_mode);
-
-Irssi::signal_add('setup changed', \&read_settings);
-
-##### settings #####
-Irssi::settings_add_str('nicklist', 'nicklist_screen_prefix', '\e[m ');
-Irssi::settings_add_str('nicklist', 'nicklist_prefix_mode_op', '\e[32m@\e[39m');
-Irssi::settings_add_str('nicklist', 'nicklist_prefix_mode_halfop', '\e[34m%\e[39m');
-Irssi::settings_add_str('nicklist', 'nicklist_prefix_mode_voice', '\e[33m+\e[39m');
-Irssi::settings_add_str('nicklist', 'nicklist_prefix_mode_normal', ' ');
-
-Irssi::settings_add_int('nicklist', 'nicklist_width',11);
-Irssi::settings_add_int('nicklist', 'nicklist_height',24);
-Irssi::settings_add_str('nicklist', 'nicklist_fifo_path', Irssi::get_irssi_dir . '/nicklistfifo');
-Irssi::settings_add_str('nicklist', 'nicklist_screen_split_windows', '');
-Irssi::settings_add_str('nicklist', 'nicklist_automode', '');
-
-read_settings();
-if (uc(Irssi::settings_get_str('nicklist_automode')) eq 'SCREEN') {
-	cmd_screen_start();
-} elsif (uc(Irssi::settings_get_str('nicklist_automode')) eq 'FIFO') {
-	cmd_fifo_start();
-}
--- a/irssi/scripts/nm.pl	Wed Nov 19 19:08:21 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,693 +0,0 @@
-use Irssi;
-use strict;
-
-use vars qw($VERSION %IRSSI);
-
-$VERSION="0.3.10";
-%IRSSI = (
-	authors=> 'BC-bd',
-	contact=> '[email protected]',
-	name=> 'nm',
-	description=> 'right aligned nicks depending on longest nick',
-	license=> 'GPL v2',
-	url=> 'http://bc-bd.org/blog/irssi/',
-);
-
-# $Id: 9cb009e8b7e6f5ce60294334faf88715ef01413e $
-# nm.pl
-# for irssi 0.8.4 by [email protected]
-#
-# right aligned nicks depending on longest nick
-#
-# inspired by neatmsg.pl from kodgehopper <[email protected]
-# formats taken from www.irssi.de
-# thanks to adrianel <[email protected]> for some hints
-# thanks to Eric Wald <[email protected]> for the left alignment patch
-# inspired by nickcolor.pl by Timo Sirainen and Ian Peters
-# thanks to And1 <[email protected]> for a small patch
-# thanks to [email protected] for the save/load patch
-# thanks to Dennis Heimbert <[email protected]> for a bug report/patch
-# thanks to Roy Sigurd Karlsbakk <[email protected]> for an autosave patch
-#
-#########
-# USAGE
-###
-# 
-# use
-# 
-# 	/neatcolor help
-#
-# for help on available commands
-#
-#########
-# OPTIONS
-#########
-
-my $help = "
-/set neat_colorize <ON|OFF>
-    * ON  : colorize nicks
-    * OFF : do not colorize nicks
-
-/set neat_colors <string>
-    Use these colors when colorizing nicks, eg:
-
-        /set neat_colors yYrR
-
-    See the file formats.txt on an explanation of what colors are
-    available.
-
-/set neat_left_actions <ON|OFF>
-    * ON  : print nicks left-aligned on actions
-    * OFF : print nicks right-aligned on actions
-
-/set neat_left_messages <ON|OFF>
-    * ON  : print nicks left-aligned on messages
-    * OFF : print nicks right-aligned on messages
-
-/set neat_right_mode <ON|OFF>
-    * ON  : print the mode of the nick e.g @%+ after the nick
-    * OFF : print it left of the nick 
-
-/set neat_maxlength <number>
-    * number : Maximum length of Nicks to display. Longer nicks are truncated.
-    * 0      : Do not truncate nicks.
-
-/set neat_melength <number>
-    * number : number of spaces to substract from /me padding
-
-/set neat_ignorechars <str>
-    * str : regular expression used to filter out unwanted characters in
-            nicks. this can be used to assign the same color for similar
-            nicks, e.g. foo and foo_:
-
-                /set neat_ignorechars [_]
-
-/set neat_allow_shrinking <ON|OFF>
-    * ON  : shrink padding when longest nick disappears
-    * OFF : do not shrink, only allow growing
-
-/set neat_autosave <number>
-    * number : autosave after <number> seconds, defaults to 60. Set to 0 to
-               disable.
-";
-
-#
-###
-################
-###
-#
-# Changelog
-#
-# Version 0.3.11
-#  - added autosave, idea from Roy Sigurd Karlsbakk
-#
-# Version 0.3.10
-#  - fix losing of saved color when changing nick shares more than one channel
-#    with you
-#
-# Version 0.3.9
-#  - fix longest nick calculation for nicks shorter than the current longest
-#    nick
-#  - updated url
-#
-# Version 0.3.8
-#  - fixed error in the nickchange tracking code, reported by Kevin Ballard
-#  - added --all switch to reset command
-#  - skip broken lines in saved_colors
-#
-# Version 0.3.7
-#  - fixed crash when calling /neatcolor without parameters
-#  - fixed url
-#
-# Version 0.3.6
-#  - added option to ignore certain characters from color hash building, see
-#    https://bc-bd.org/trac/irssi/ticket/22
-#  - added option to save and specify colors for nicks, see
-#    https://bc-bd.org/trac/irssi/ticket/23
-#  - added option to disallow shrinking, see
-#    https://bc-bd.org/trac/irssi/ticket/12
-#
-# Version 0.3.5
-#  - now also aligning own messages in queries
-#
-# Version 0.3.4
-#  - fxed off by one error in nick_to_color, patch by jrib, see
-#  https://bc-bd.org/trac/irssi/ticket/24
-#
-# Version 0.3.3
-#  - added support for alignment in queries, see
-#    https://bc-bd.org/trac/irssi/ticket/21
-#
-# Version 0.3.2
-#  - integrated left alignment patch from Eric Wald <[email protected]>, see
-#    https://bc-bd.org/trac/irssi/ticket/18
-#
-# Version 0.3.1
-#  - /me padding, see https://bc-bd.org/trac/irssi/ticket/17
-#
-# Version 0.3.0
-#  - integrate nick coloring support
-#
-# Version 0.2.1
-#  - moved neat_maxlength check to reformat() (thx to Jerome De Greef <[email protected]>)
-#
-# Version 0.2.0
-#  - by adrianel <[email protected]>
-#     * reformat after setup reload
-#     * maximum length of nicks
-#
-# Version 0.1.0
-#  - got lost somewhere
-#
-# Version 0.0.2
-#  - ugly typo fixed
-#  
-# Version 0.0.1
-#  - initial release
-#
-###
-################
-###
-#
-# BUGS
-#
-# Empty nicks, eg "<> message"
-# 	This seems to be triggered by some themes. As of now there is no known
-# 	fix other than changing themes, see
-# 	https://bc-bd.org/trac/irssi/ticket/19
-#
-# Well, it's a feature: due to the lacking support of extendable themes
-# from irssi it is not possible to just change some formats per window.
-# This means that right now all windows are aligned with the same nick
-# length, which can be somewhat annoying.
-# If irssi supports extendable themes, I will include per-server indenting
-# and a setting where you can specify servers you don't want to be indented
-#
-###
-################
-
-my ($longestNick, %saved_colors, @colors, $alignment, $sign, %commands,);
-my ($pending_save);
-
-my $colorize = -1;
-
-sub reformat() {
-	my $max = Irssi::settings_get_int('neat_maxlength');
-	my $actsign = Irssi::settings_get_bool('neat_left_actions')? '': '-';
-	$sign = Irssi::settings_get_bool('neat_left_messages')? '': '-';
-
-	if ($max && $max < $longestNick) {
-		$longestNick = $max;
-	}
-
-	my $me = $longestNick - Irssi::settings_get_int('neat_melength');
-	$me = 0 if ($me < 0);
-
-	Irssi::command('^format own_action {ownaction $['.$actsign.$me.']0} $1');
-	Irssi::command('^format action_public {pubaction $['.$actsign.$me.']0}$1');
-	Irssi::command('^format action_private {pvtaction $['.$actsign.$me.']0}$1');
-	Irssi::command('^format action_private_query {pvtaction_query $['.$actsign.$me.']0} $2');
-
-	my $length = $sign . $longestNick;
-	if (Irssi::settings_get_bool('neat_right_mode') == 0) {
-		Irssi::command('^format own_msg {ownmsgnick $2 {ownnick $['.$length.']0}}$1');
-		Irssi::command('^format own_msg_channel {ownmsgnick $3 {ownnick $['.$length.']0}{msgchannel $1}}$2');
-		Irssi::command('^format pubmsg_me {pubmsgmenick $2 {menick $['.$length.']0}}$1');
-		Irssi::command('^format pubmsg_me_channel {pubmsgmenick $3 {menick $['.$length.']0}{msgchannel $1}}$2');
-		Irssi::command('^format pubmsg_hilight {pubmsghinick $0 $3 $['.$length.']1%n}$2');
-		Irssi::command('^format pubmsg_hilight_channel {pubmsghinick $0 $4 $['.$length.']1{msgchannel $2}}$3');
-		Irssi::command('^format pubmsg {pubmsgnick $2 {pubnick $['.$length.']0}}$1');
-		Irssi::command('^format pubmsg_channel {pubmsgnick $2 {pubnick $['.$length.']0}}$1');
-	} else {
-		Irssi::command('^format own_msg {ownmsgnick {ownnick $['.$length.']0$2}}$1');
-		Irssi::command('^format own_msg_channel {ownmsgnick {ownnick $['.$length.']0$3}{msgchannel $1}}$2');
-		Irssi::command('^format pubmsg_me {pubmsgmenick {menick $['.$length.']0}$2}$1');
-		Irssi::command('^format pubmsg_me_channel {pubmsgmenick {menick $['.$length.']0$3}{msgchannel $1}}$2');
-		Irssi::command('^format pubmsg_hilight {pubmsghinick $0 $0 $['.$length.']1$3%n}$2');
-		Irssi::command('^format pubmsg_hilight_channel {pubmsghinick $0 $['.$length.']1$4{msgchannel $2}}$3');
-		Irssi::command('^format pubmsg {pubmsgnick {pubnick $['.$length.']0$2}}$1');
-		Irssi::command('^format pubmsg_channel {pubmsgnick {pubnick $['.$length.']0$2}}$1');
-	}
-
-	# format queries
-	Irssi::command('^format own_msg_private_query {ownprivmsgnick {ownprivnick $['.$length.']2}}$1');
-	Irssi::command('^format msg_private_query {privmsgnick $['.$length.']0}$2');
-};
-
-sub findLongestNick {
-	$longestNick = 0;
-
-	# get own nick length
-	map {
-		my $len = length($_->{nick});
-
-		$longestNick = $len if ($len > $longestNick);
-	} Irssi::servers();
-
-	# find longest other nick
-	foreach (Irssi::channels()) {
-		foreach ($_->nicks()) {
-			my $len = length($_->{nick});
-
-			$longestNick = $len if ($len > $longestNick);
-		}
-	}
-
-	reformat();
-}
-
-sub delayed_save
-{
-	# skip if we have already a save pending. we don't reset the timeout
-	# here, else you could end up with changes never being automatically
-	# saved if they happen more often than <neat_autosave> seconds
-	return if $pending_save;
-
-	return unless Irssi::settings_get_int('neat_autosave');
-
-	Irssi::timeout_add_once(Irssi::settings_get_int('neat_autosave') * 1000,
-		\&save_colors, undef);
-}
-
-# a new nick was created
-sub sig_newNick
-{
-	my ($channel, $nick) = @_;
-
-	my $len = length($nick->{nick});
-
-	if ($len > $longestNick) {
-		$longestNick = $len;
-		reformat();
-	}
-
-	return if (exists($saved_colors{$nick->{nick}}));
-
-	$saved_colors{$nick->{nick}} = "%".nick_to_color($nick->{nick});
-	delayed_save();
-}
-
-# something changed
-sub sig_changeNick
-{
-	my ($channel, $nick, $old_nick) = @_;
-
-	# if no saved color exists, we already handled this nickchange. irssi
-	# generates one signal per channel the nick is in, so if you share more
-	# than one channel with this nick, you'd lose the coloring.
-	return unless exists($saved_colors{$old_nick});
-
-	# we need to update the saved colorors hash independent of nick lenght
-	$saved_colors{$nick->{nick}} = $saved_colors{$old_nick};
-	delete $saved_colors{$old_nick};
-	delayed_save();
-
-	my $new = length($nick->{nick});
-
-	# in case the new nick is longer than the old one, simply remember this
-	# as the new longest nick and reformat.
-	#
-	# if the new nick is as long as the known longest nick nothing has to be
-	# done
-	#
-	# if the new nick is shorter than the current longest one and if the
-	# user allows us to shrink, find new longest nick and reformat.
-	if ($new > $longestNick) {
-		$longestNick = $new;
-	} elsif ($new == $longestNick) {
-		return;
-	} else {
-		return unless Irssi::settings_get_bool('neat_allow_shrinking');
-		findLongestNick();
-	}
-
-	reformat();
-}
-
-sub sig_removeNick
-{
-	my ($channel, $nick) = @_;
-
-	my $thisLen = length($nick->{nick});
-
-	# we only need to recalculate if this was the longest nick and we are
-	# allowed to shrink
-	if ($thisLen == $longestNick && Irssi::settings_get_bool('neat_allow_shrinking')) {
-		findLongestNick();
-		reformat();
-	}
-
-	# we do not remove a known color for a gone nick, as they may return
-}
-
-# based on simple_hash from nickcolor.pl
-sub nick_to_color($) {
-	my ($string) = @_;
-	chomp $string;
-
-	my $ignore = Irssi::settings_get_str("neat_ignorechars");
-	$string =~ s/$ignore//g;
-
-	my $counter;
-	foreach my $char (split(//, $string)) {
-		$counter += ord $char;
-	}
-
-	return $colors[$counter % ($#colors + 1)];
-}
-
-sub color_left($) {
-	Irssi::command('^format pubmsg {pubmsgnick $2 {pubnick '.$_[0].'$['.$sign.$longestNick.']0}}$1');
-	Irssi::command('^format pubmsg_channel {pubmsgnick $2 {pubnick '.$_[0].'$['.$sign.$longestNick.']0}}$1');
-}
-
-sub color_right($) {
-	Irssi::command('^format pubmsg {pubmsgnick {pubnick '.$_[0].'$['.$sign.$longestNick.']0}$2}$1');
-	Irssi::command('^format pubmsg_channel {pubmsgnick {pubnick '.$_[0].'$['.$sign.$longestNick.']0}$2}$1');
-}
-
-sub sig_public {
-	my ($server, $msg, $nick, $address, $target) = @_;
-
-	&$alignment($saved_colors{$nick});
-}
-
-sub sig_setup {
-	@colors = split(//, Irssi::settings_get_str('neat_colors'));
-
-	# check left or right alignment
-	if (Irssi::settings_get_bool('neat_right_mode') == 0) {
-		$alignment = \&color_left;
-	} else {
-		$alignment = \&color_right;
-	}
-	
-	# check if we switched coloring on or off
-	my $new = Irssi::settings_get_bool('neat_colorize');
-	if ($new != $colorize) {
-		if ($new) {
-			Irssi::signal_add('message public', 'sig_public');
-		} else {
-			if ($colorize >= 0) {
-				Irssi::signal_remove('message public', 'sig_public');
-			}
-		}
-	}
-	$colorize = $new;
-
-	reformat();
-	&$alignment('%w');
-}
-
-# make sure that every nick has an assigned color
-sub assert_colors() {
-	foreach (Irssi::channels()) {
-		foreach ($_->nicks()) {
-			next if (exists($saved_colors{$_->{nick}}));
-
-			$saved_colors{$_->{nick}} = "%".nick_to_color($_->{nick});
-			delayed_save();
-		}
-	}
-}
-
-# load colors from file
-sub load_colors() {
-	open(FID, "<".$ENV{HOME}."/.irssi/saved_colors") || return;
-
-	while (<FID>) {
-		chomp;
-		my ($k, $v) = split(/:/);
-
-		# skip broken lines, those may have been introduced by nm.pl
-		# version 0.3.7 and earlier
-		if ($k eq '' || $v eq '') {
-			neat_log(Irssi::active_win(), "Warning, broken line in saved_colors file, skipping '$k:$v'");
-			next;
-		}
-
-		$saved_colors{$k} = $v;
-	}
-
-	close(FID);
-}
-
-# save colors to file
-sub save_colors() {
-	open(FID, ">".$ENV{HOME}."/.irssi/saved_colors");
-
-	print FID $_.":".$saved_colors{$_}."\n" foreach (keys(%saved_colors));
-
-	close(FID);
-
-	# clear possible pending save.
-	Irssi::timeout_remove($pending_save) if $pending_save;
-	$pending_save = undef;
-}
-
-# log a line to a window item
-sub neat_log($@) {
-	my ($witem, @text) = @_;
-
-	$witem->print("nm.pl: ".$_) foreach(@text);
-}
-
-# show available colors
-sub cmd_neatcolor_colors($) {
-	my ($witem, undef, undef) = @_;
-
-	neat_log($witem, "Available colors: ".join("", map { "%".$_.$_ } @colors));
-}
-
-# display the configured color for a nick
-sub cmd_neatcolor_get() {
-	my ($witem, $nick, undef) = @_;
-
-	if (!exists($saved_colors{$nick})) {
-		neat_log($witem, "Error: no such nick '$nick'");
-		return;
-	}
-
-	neat_log($witem, "Color for ".$saved_colors{$nick}.$nick);
-}
-
-# display help
-sub cmd_neatcolor_help() {
-	my ($witem, $cmd, undef) = @_;
-
-	if ($cmd) {
-		if (!exists($commands{$cmd})) {
-			neat_log($witem, "Error: no such command '$cmd'");
-			return;
-		}
-
-		if (!exists($commands{$cmd}{verbose})) {
-			neat_log($witem, "No additional help for '$cmd' available");
-			return;
-		}
-
-		neat_log($witem, ( "", "Help for ".uc($cmd), "" ) );
-		neat_log($witem, @{$commands{$cmd}{verbose}});
-		return;
-	}
-
-	neat_log($witem, split(/\n/, $help));
-	neat_log($witem, "Available options for /neatcolor");
-	neat_log($witem, "    ".$_.": ".$commands{$_}{text}) foreach(sort(keys(%commands)));
-
-	my @verbose;
-	foreach (sort(keys(%commands))) {
-		push(@verbose, $_) if exists($commands{$_}{verbose});
-	}
-
-	neat_log($witem, "Verbose help available for: '".join(", ", @verbose)."'");
-}
-
-# list configured nicks
-sub cmd_neatcolor_list() {
-	my ($witem, undef, undef) = @_;
-
-	neat_log($witem, "Configured nicks: ".join(", ", map { $saved_colors{$_}.$_ } sort(keys(%saved_colors))));
-}
-
-# reset a nick to its default color
-sub cmd_neatcolor_reset() {
-	my ($witem, $nick, undef) = @_;
-
-	if ($nick eq '--all') {
-		%saved_colors = ();
-		assert_colors();
-		neat_log($witem, "Reset all colors");
-		return;
-	}
-
-	if (!exists($saved_colors{$nick})) {
-		neat_log($witem, "Error: no such nick '$nick'");
-		return;
-	}
-
-	$saved_colors{$nick} = "%".nick_to_color($nick);
-	delayed_save();
-	neat_log($witem, "Reset color for ".$saved_colors{$nick}.$nick);
-}
-
-# save configured colors to disk
-sub cmd_neatcolor_save() {
-	my ($witem, undef, undef) = @_;
-
-	save_colors();
-
-	neat_log($witem, "color information saved");
-}
-
-# set a color for a nick
-sub cmd_neatcolor_set() {
-	my ($witem, $nick, $color) = @_;
-
-	my @found = grep(/$color/, @colors);
-	if ($#found) {
-		neat_log($witem, "Error: trying to set unknown color '%$color$color%n'");
-		cmd_neatcolor_colors($witem);
-		return;
-	}
-
-	if ($witem->{type} ne "CHANNEL" && $witem->{type} ne "QUERY") {
-		neat_log($witem, "Warning: not a Channel/Query, can not check nick!");
-		neat_log($witem, "Remember, nicks are case sensitive to nm.pl");
-	} else {
-		my @nicks = grep(/^$nick$/i, map { $_->{nick} } ($witem->nicks()));
-
-		if ($#nicks < 0) {
-			neat_log($witem, "Warning: could not find nick '$nick' here");
-		} else {
-			if ($nicks[0] ne $nick) {
-				neat_log($witem, "Warning: using '$nicks[0]' instead of '$nick'");
-				$nick = $nicks[0];
-			}
-		}
-	}
-
-	$saved_colors{$nick} = "%".$color;
-	delayed_save();
-	neat_log($witem, "Set color for $saved_colors{$nick}$nick");
-}
-
-%commands = (
-	colors => {
-		text => "show available colors",
-		verbose => [
-			"COLORS",
-			"",
-			"displays all available colors",
-			"",
-			"You can restrict/define the list of available colors ".
-			"with the help of the neat_colors setting"
-		],
-		func => \&cmd_neatcolor_colors,
-	},
-	get => {
-		text => "retrieve color for a nick",
-		verbose => [
-			"GET <nick>",
-			"",
-			"displays color used for <nick>"
-		],
-		func => \&cmd_neatcolor_get,
-	},
-	help => {
-		text => "print this help message",
-		func => \&cmd_neatcolor_help,
-	},
-	list => {
-		text => "list configured nick/color pairs",
-		func => \&cmd_neatcolor_list,
-	},
-	reset => {
-		text => "reset color to default",
-		verbose => [
-			"RESET --all|<nick>",
-			"",
-			"resets the color used for all nicks or for <nick> to ",
-			"its internal default",
-		],
-		func => \&cmd_neatcolor_reset,
-	},
-	save => {
-		text => "save color information to disk",
-		verbose => [
-			"SAVE",
-			"",
-			"saves color information to disk, so that it survives ".
-			"an irssi restart.",
-			"",
-			"Color information will be automatically saved on /quit",
-		],
-		func => \&cmd_neatcolor_save,
-	},
-	set => {
-		text => "set a specific color for a nick",
-		verbose => [
-			"SET <nick> <color>",
-			"",
-			"use <color> for <nick>",
-			"",
-			"This command will perform a couple of sanity checks, ".
-			"when called from a CHANNEL/QUERY window",
-			"",
-			"EXAMPLE:",
-			"  /neatcolor set bc-bd r",
-			"",
-			"use /neatcolor COLORS to see available colors"
-		],
-		func => \&cmd_neatcolor_set,
-	},
-);
-
-# the main command callback that gets called for all neatcolor commands
-sub cmd_neatcolor() {
-	my ($data, $server, $witem) = @_;
-	my ($cmd, $nick, $color) = split (/ /, $data);
-
-	$cmd = lc($cmd);
-
-	# make sure we have a valid witem to print text to
-	$witem = Irssi::active_win() unless ($witem);
-
-	if (!exists($commands{$cmd})) {
-		neat_log($witem, "Error: unknown command '$cmd'");
-		&{$commands{"help"}{"func"}}($witem) if (exists($commands{"help"}));
-		return;
-	}
-
-	&{$commands{$cmd}{"func"}}($witem, $nick, $color);
-}
-
-Irssi::settings_add_bool('misc', 'neat_left_messages', 0);
-Irssi::settings_add_bool('misc', 'neat_left_actions', 0);
-Irssi::settings_add_bool('misc', 'neat_right_mode', 1);
-Irssi::settings_add_int('misc', 'neat_maxlength', 0);
-Irssi::settings_add_int('misc', 'neat_melength', 2);
-Irssi::settings_add_bool('misc', 'neat_colorize', 1);
-Irssi::settings_add_str('misc', 'neat_colors', 'rRgGyYbBmMcC');
-Irssi::settings_add_str('misc', 'neat_ignorechars', '');
-Irssi::settings_add_bool('misc', 'neat_allow_shrinking', 1);
-Irssi::settings_add_int('misc', 'neat_autosave', 60);
-
-Irssi::command_bind('neatcolor', 'cmd_neatcolor');
-
-Irssi::signal_add('nicklist new', 'sig_newNick');
-Irssi::signal_add('nicklist changed', 'sig_changeNick');
-Irssi::signal_add('nicklist remove', 'sig_removeNick');
-
-Irssi::signal_add('setup changed', 'sig_setup');
-Irssi::signal_add_last('setup reread', 'sig_setup');
-
-findLongestNick();
-sig_setup;
-
-load_colors();
-assert_colors();
-
-# we need to add this signal _after_ the colors have been loaded, to make sure
-# no race condition exists wrt color saving
-Irssi::signal_add('gui exit', 'save_colors');
--- a/irssi/scripts/queryresume.pl	Wed Nov 19 19:08:21 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-# QueryResume by Stefan Tomanek <[email protected]>
-#
-use strict;
-
-use vars qw($VERSION %IRSSI);
-$VERSION = '2003021201';
-%IRSSI = (
-    authors     => 'Stefan \'tommie\' Tomanek',
-    contact     => '[email protected]',
-    name        => 'QueryResume',
-    description => 'restores the last lines of a query on re-creation',
-    license     => 'GPLv2',
-    modules     => 'Date::Format File::Glob',
-    changed     => $VERSION,
-);  
-
-use Irssi 20020324;
-use Date::Format;
-use File::Glob ':glob';
-
-sub draw_box ($$$$) {
-    my ($title, $text, $footer, $colour) = @_;
-    my $box = '';
-    $box .= '%R,--[%n%9%U'.$title.'%U%9%R]%n'."\n";
-    foreach (split(/\n/, $text)) {
-        $box .= '%R|%n '.$_."\n";
-    }
-    $box .= '%R`--<%n'.$footer.'%R>->%n';
-    $box =~ s/%.//g unless $colour;
-    return $box;
-}
-
-sub sig_window_item_new ($$) {
-    my ($win, $witem) = @_;
-    return unless (ref $witem && $witem->{type} eq 'QUERY');
-    my @data;
-    my $filename = Irssi::settings_get_str('autolog_path');
-    my $servertag = $witem->{server}->{tag};
-    my $name = lc $witem->{name};
-    $filename =~ s/(\$tag|\$1)/$servertag/g;
-    $filename =~ s/\$0/$name/g;
-    my @lt = localtime(time);
-    my $zone;
-    $filename = strftime($filename, @lt, $zone);
-    $filename =~ s/(\[|\])/\\$1/g;
-    local *F;
-    open(F, "<".bsd_glob($filename));
-    my $lines = Irssi::settings_get_int('queryresume_lines');
-    foreach (<F>) {
-	unless (/^--- Log/) {
-	    push(@data, $_);
-	    shift(@data) if (@data > $lines);
-	}
-    }
-    my $text;
-    $text .= $_ foreach @data;
-    $text =~ s/%/%%/g;
-    $witem->print(draw_box('QueryResume', $text, $filename, 1), MSGLEVEL_CLIENTCRAP) if $text;
-}
-
-Irssi::settings_add_int($IRSSI{name}, 'queryresume_lines', 10);
-
-Irssi::signal_add('window item new', 'sig_window_item_new');
-
--- a/irssi/scripts/trackbar.pl	Wed Nov 19 19:08:21 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,189 +0,0 @@
-# trackbar.pl
-# 
-# This little script will do just one thing: it will draw a line each time you
-# switch away from a window. This way, you always know just upto where you've
-# been reading that window :) It also removes the previous drawn line, so you
-# don't see double lines.
-#
-# Usage: 
-#
-#     The script works right out of the box, but if you want you can change
-#     the working by /set'ing the following variables:
-#
-#     trackbar_string       The characters to repeat to draw the bar
-#     trackbar_style        The style for the bar, %r is red for example
-#                           See formats.txt that came with irssi
-#
-#     /mark is a command that will redraw the line at the bottom.  However!  This
-#     requires irssi version after 20021228.  otherwise you'll get the error
-#     redraw: unknown command, and your screen is all goofed up :)
-#
-#     /upgrade & buf.pl notice: This version tries to remove the trackbars before 
-#     the upgrade is done, so buf.pl does not restore them, as they are not removeable
-#     afterwards by trackbar.  Unfortiounatly, to make this work, trackbar and buf.pl
-#     need to be loaded in a specific order.  Please experiment to see which order works
-#     for you (strangely, it differs from configuration to configuration, something I will
-#     try to fix in a next version) 
-#
-# Authors:
-#   - Main maintainer & author: Peter 'kinlo' Leurs
-#   - Many thanks to Timo 'cras' Sirainen for placing me on my way
-#   - on-upgrade-remove-line patch by Uwe Dudenhoeffer
-#
-# Version history:
-#  1.4: - Changed our's by my's so the irssi script header is valid
-#       - Removed utf-8 support.  In theory, the script should work w/o any
-#         problems for utf-8, just set trackbar_string to a valid utf-8 character
-#         and everything *should* work.  However, this script is being plagued by
-#         irssi internal bugs.  The function Irssi::settings_get_str does NOT handle
-#         unicode strings properly, hence you will notice problems when setting the bar
-#         to a unicode char.  For changing your bar to utf-8 symbols, read the line sub.
-#  1.3: - Upgrade now removes the trackbars. 
-#       - Some code cleanups, other defaults
-#       - /mark sets the line to the bottom
-#  1.2: - Support for utf-8
-#       - How the bar looks can now be configured with trackbar_string 
-#         and trackbar_style
-#  1.1: - Fixed bug when closing window
-#  1.0: - Initial release
-#
-#
-#  Call for help!
-#
-#  There is a trackbar version 2.0 that properly handles resizes and immediate config change
-#  activation.  However, there is/are some bug(s) in irssi's main buffer/window code that causes
-#  irssi to 'forget' lines, which is ofcourse completly unaccepteable.  I haven't found the time
-#  nor do I know the irssi's internals enough to find and fix this bug, if you want to help, please
-#  contact me, I'll give you a copy of the 2.0 version that will immediatly show you the problems.
-#
-# Known bugs:
-#  - if you /clear a window, it will be uncleared when returning to the window
-#  - UTF-8 characters in the trackbar_string doesnt work.  This is an irssi bug.
-#  - if you resize your irssi (in xterm or so) the bar is not resized 
-#  - changing the trackbar style is only visible after returning to a window
-#  however, changing style/resize takes in effect after you left the window.
-#
-# Whishlist/todo:
-#  - instead of drawing a line, just invert timestamp or something, 
-#    to save a line (but I don't think this is possible with current irssi)
-#  - some pageup keybinding possibility, to scroll up upto the trackbar
-#  - <@coekie> kinlo: if i switch to another window, in another split window, i 
-#              want the trackbar to go down in the previouswindow in  that splitwindow :)
-#  - < bob_2> anyway to clear the line once the window is read?
-#  - < elho> kinlo: wishlist item: a string that gets prepended to the repeating pattern
-#  - < elho> an option to still have the timestamp in front of the bar
-#  - < elho> oh and an option to not draw it in the status window :P
-#
-# BTW: when you have feature requests, mailing a patch that works is the fastest way
-# to get it added :p
-
-use strict;
-use 5.6.1;
-use Irssi;
-use Irssi::TextUI;
-
-my $VERSION = "1.4";
-
-my %IRSSI = (
-    authors     => "Peter 'kinlo' Leurs",
-    contact     => "peter\@pfoe.be",
-    name        => "trackbar",
-    description => "Shows a bar where you've last read a window",
-    license     => "GPLv2",
-    url         => "http://www.pfoe.be/~peter/trackbar/",
-    changed     => "Thu Feb 20 16:18:08 2003",
-);
-
-my %config;
-
-Irssi::settings_add_str('trackbar', 'trackbar_string' => '-');
-$config{'trackbar_string'} = Irssi::settings_get_str('trackbar_string');
-
-Irssi::settings_add_str('trackbar', 'trackbar_style' => '%K');
-$config{'trackbar_style'} = Irssi::settings_get_str('trackbar_style');
-
-Irssi::signal_add(
-    'setup changed' => sub {
-        $config{'trackbar_string'} = Irssi::settings_get_str('trackbar_string');
-        $config{'trackbar_style'}  = Irssi::settings_get_str('trackbar_style');
-        if ($config{'trackbar_style'} =~ /(?<!%)[^%]|%%|%$/) {
-            Irssi::print(
-                "trackbar: %RWarning!%n 'trackbar_style' seems to contain "
-                . "printable characters. Only use format codes (read "
-                . "formats.txt).", MSGLEVEL_CLIENTERROR);
-        }
-    }
-);
-
-Irssi::signal_add(
-    'window changed' => sub {
-        my (undef, $oldwindow) = @_;
-
-        if ($oldwindow) {
-            my $line = $oldwindow->view()->get_bookmark('trackbar');
-            $oldwindow->view()->remove_line($line) if defined $line;
-            $oldwindow->print(line($oldwindow->{'width'}), MSGLEVEL_NEVER);
-            $oldwindow->view()->set_bookmark_bottom('trackbar');
-        }
-    }
-);
-
-sub line {
-    my $width  = shift;
-    my $string = $config{'trackbar_string'};
-    $string = '-' unless defined $string;
-
-    # There is a bug in irssi's utf-8 handling on config file settings, as you 
-    # can reproduce/see yourself by the following code sniplet:
-    #
-    #   my $quake = pack 'U*', 8364;    # EUR symbol
-    #   Irssi::settings_add_str 'temp', 'temp_foo' => $quake;
-    #   Irssi::print length $quake;
-    #       # prints 1
-    #   Irssi::print length Irssi::settings_get_str 'temp_foo';
-    #       # prints 3
-    #
-    #
-    # Trackbar used to have a workaround, but on recent versions of perl/irssi
-    # it does no longer work.  Therefore, if you want your trackbar to contain
-    # unicode characters, uncomment the line below for a nice full line, or set
-    # the string to whatever char you want.
-
-    # $string = pack('U*', 0x2500);
-
-
-    my $length = length $string;
-
-    if ($length == 0) {
-        $string = '-';
-        $length = 1;
-    }
-
-    my $times = $width / $length;
-    $times = int(1 + $times) if $times != int($times);
-    $string =~ s/%/%%/g;
-    return $config{'trackbar_style'} . substr($string x $times, 0, $width);
-}
-
-# Remove trackbars on upgrade - but this doesn't really work if the scripts are not loaded in the correct order... watch out!
-
-Irssi::signal_add_first( 'session save' => sub {
-	    for my $window (Irssi::windows) {	
-		next unless defined $window;
-		my $line = $window->view()->get_bookmark('trackbar');
-		$window->view()->remove_line($line) if defined $line;
-	    }
-	}
-);
-
-sub cmd_mark {
-    my $window = Irssi::active_win();
-#    return unless defined $window;
-    my $line = $window->view()->get_bookmark('trackbar');
-    $window->view()->remove_line($line) if defined $line;
-    $window->print(line($window->{'width'}), MSGLEVEL_NEVER);
-    $window->view()->set_bookmark_bottom('trackbar');
-    Irssi::command("redraw");    
-}
-
-Irssi::command_bind('mark',   'cmd_mark');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/weechat/buffers.conf	Wed Nov 19 19:24:17 2014 +0100
@@ -0,0 +1,71 @@
+#
+# buffers.conf -- weechat v1.0.1
+#
+
+[color]
+current_bg = default
+current_fg = cyan
+default_bg = default
+default_fg = gray
+hotlist_highlight_bg = default
+hotlist_highlight_fg = magenta
+hotlist_low_bg = default
+hotlist_low_fg = white
+hotlist_message_bg = default
+hotlist_message_fg = green
+hotlist_private_bg = default
+hotlist_private_fg = red
+none_channel_bg = default
+none_channel_fg = darkgray
+number = default
+number_char = lightgreen
+prefix_bufname = default
+queries_default_bg = default
+queries_default_fg = default
+queries_highlight_bg = default
+queries_highlight_fg = default
+queries_message_bg = default
+queries_message_fg = default
+suffix_bufname = default
+whitelist_default_bg = default
+whitelist_default_fg = default
+whitelist_highlight_bg = default
+whitelist_highlight_fg = default
+whitelist_low_bg = default
+whitelist_low_fg = default
+whitelist_message_bg = default
+whitelist_message_fg = default
+whitelist_private_bg = default
+whitelist_private_fg = default
+
+[look]
+core_to_front = off
+detach = 0
+detach_buffer_immediately = ""
+detach_display_window_number = off
+detach_displayed_buffers = on
+detach_free_content = off
+detach_query = off
+hide_merged_buffers = all
+hotlist_counter = off
+immune_detach_buffers = ""
+indenting = on
+indenting_number = on
+jump_prev_next_visited_buffer = off
+mark_inactive = off
+mouse_move_buffer = on
+mouse_wheel = on
+name_crop_suffix = "+"
+name_size_max = 0
+number_char = "  "
+prefix = off
+prefix_bufname = "  "
+prefix_empty = on
+prefix_for_query = ""
+short_names = on
+show_lag = off
+show_number = off
+sort = number
+suffix_bufname = "  "
+toggle_bar = on
+whitelist_buffers = ""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/weechat/perl/autoload/buffers.pl	Wed Nov 19 19:24:17 2014 +0100
@@ -0,0 +1,1785 @@
+#
+# Copyright (C) 2008-2014 Sebastien Helleu <[email protected]>
+# Copyright (C) 2011-2013 Nils G <[email protected]>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+#
+# Display sidebar with list of buffers.
+#
+# History:
+#
+# 2014-08-29, Patrick Steinhardt <[email protected]>:
+#     v4.9: add support for specifying custom buffer names
+# 2014-07-19, Sebastien Helleu <[email protected]>:
+#     v4.8: add support of ctrl + mouse wheel to jump to previous/next buffer,
+#           new option "mouse_wheel"
+# 2014-06-22, Sebastien Helleu <[email protected]>:
+#     v4.7: fix typos in options
+# 2014-04-05, Sebastien Helleu <[email protected]>:
+#     v4.6: add support of hidden buffers (WeeChat >= 0.4.4)
+# 2014-01-01, Sebastien Helleu <[email protected]>:
+#     v4.5: add option "mouse_move_buffer"
+# 2013-12-11, Sebastien Helleu <[email protected]>:
+#     v4.4: fix buffer number on drag to the end of list when option
+#           weechat.look.buffer_auto_renumber is off
+# 2013-12-10, nils_2@freenode.#weechat:
+#     v4.3: add options "prefix_bufname" and "suffix_bufname (idea by silverd)
+#         : fix hook_timer() for show_lag wasn't disabled
+#         : improved signal handling (less updating of buffers list)
+# 2013-11-07, Sebastien Helleu <[email protected]>:
+#     v4.2: use default filling "columns_vertical" when bar position is top/bottom
+# 2013-10-31, nils_2@freenode.#weechat:
+#     v4.1: add option "detach_buffer_immediately" (idea by farn)
+# 2013-10-20, nils_2@freenode.#weechat:
+#     v4.0: add options "detach_displayed_buffers", "detach_display_window_number"
+# 2013-09-27, nils_2@freenode.#weechat:
+#     v3.9: add option "toggle_bar" and option "show_prefix_query" (idea by IvarB)
+#         : fix problem with linefeed at end of list of buffers (reported by grawity)
+# 2012-10-18, nils_2@freenode.#weechat:
+#     v3.8: add option "mark_inactive", to mark buffers you are not in (idea by xrdodrx)
+#         : add wildcard "*" for immune_detach_buffers (idea by StarWeaver)
+#         : add new options "detach_query" and "detach_free_content" (idea by StarWeaver)
+# 2012-10-06, Nei <anti.teamidiot.de>:
+#     v3.7: call menu on right mouse if menu script is loaded.
+# 2012-10-06, nils_2 <[email protected]>:
+#     v3.6: add new option "hotlist_counter" (idea by torque).
+# 2012-06-02, nils_2 <[email protected]>:
+#     v3.5: add values "server|channel|private|all|keepserver|none" to option "hide_merged_buffers" (suggested by dominikh).
+# 2012-05-25, nils_2 <[email protected]>:
+#     v3.4: add new option "show_lag".
+# 2012-04-07, Sebastien Helleu <[email protected]>:
+#     v3.3: fix truncation of wide chars in buffer name (option name_size_max) (bug #36034)
+# 2012-03-15, nils_2 <[email protected]>:
+#     v3.2: add new option "detach"(weechat >= 0.3.8)
+#           add new option "immune_detach_buffers" (requested by Mkaysi)
+#           add new function buffers_whitelist add|del|reset (suggested by FiXato)
+#           add new function buffers_detach add|del|reset
+# 2012-03-09, Sebastien Helleu <[email protected]>:
+#     v3.1: fix reload of config file
+# 2012-01-29, nils_2 <[email protected]>:
+#     v3.0: fix: buffers did not update directly during window_switch (reported by FiXato)
+# 2012-01-29, nils_2 <[email protected]>:
+#     v2.9: add options "name_size_max" and "name_crop_suffix"
+# 2012-01-08, nils_2 <[email protected]>:
+#     v2.8: fix indenting for option "show_number off"
+#           fix unset of buffer activity in hotlist when buffer was moved with mouse
+#           add buffer with free content and core buffer sorted first (suggested  by nyuszika7h)
+#           add options queries_default_fg/bg and queries_message_fg/bg (suggested by FiXato)
+#           add clicking with left button on current buffer will do a jump_previously_visited_buffer (suggested by FiXato)
+#           add clicking with right button on current buffer will do a jump_next_visited_buffer
+#           add additional informations in help texts
+#           add default_fg and default_bg for whitelist channels
+#           internal changes  (script is now 3Kb smaller)
+# 2012-01-04, Sebastien Helleu <[email protected]>:
+#     v2.7: fix regex lookup in whitelist buffers list
+# 2011-12-04, nils_2 <[email protected]>:
+#     v2.6: add own config file (buffers.conf)
+#           add new behavior for indenting (under_name)
+#           add new option to set different color for server buffers and buffers with free content
+# 2011-10-30, nils_2 <[email protected]>:
+#     v2.5: add new options "show_number_char" and "color_number_char",
+#           add help-description for options
+# 2011-08-24, Sebastien Helleu <[email protected]>:
+#     v2.4: add mouse support
+# 2011-06-06, nils_2 <[email protected]>:
+#     v2.3: added: missed option "color_whitelist_default"
+# 2011-03-23, Sebastien Helleu <[email protected]>:
+#     v2.2: fix color of nick prefix with WeeChat >= 0.3.5
+# 2011-02-13, nils_2 <[email protected]>:
+#     v2.1: add options "color_whitelist_*"
+# 2010-10-05, Sebastien Helleu <[email protected]>:
+#     v2.0: add options "sort" and "show_number"
+# 2010-04-12, Sebastien Helleu <[email protected]>:
+#     v1.9: replace call to log() by length() to align buffer numbers
+# 2010-04-02, Sebastien Helleu <[email protected]>:
+#     v1.8: fix bug with background color and option indenting_number
+# 2010-04-02, Helios <[email protected]>:
+#     v1.7: add indenting_number option
+# 2010-02-25, m4v <[email protected]>:
+#     v1.6: add option to hide empty prefixes
+# 2010-02-12, Sebastien Helleu <[email protected]>:
+#     v1.5: add optional nick prefix for buffers like IRC channels
+# 2009-09-30, Sebastien Helleu <[email protected]>:
+#     v1.4: remove spaces for indenting when bar position is top/bottom
+# 2009-06-14, Sebastien Helleu <[email protected]>:
+#     v1.3: add option "hide_merged_buffers"
+# 2009-06-14, Sebastien Helleu <[email protected]>:
+#     v1.2: improve display with merged buffers
+# 2009-05-02, Sebastien Helleu <[email protected]>:
+#     v1.1: sync with last API changes
+# 2009-02-21, Sebastien Helleu <[email protected]>:
+#     v1.0: remove timer used to update bar item first time (not needed any more)
+# 2009-02-17, Sebastien Helleu <[email protected]>:
+#     v0.9: fix bug with indenting of private buffers
+# 2009-01-04, Sebastien Helleu <[email protected]>:
+#     v0.8: update syntax for command /set (comments)
+# 2008-10-20, Jiri Golembiovsky <[email protected]>:
+#     v0.7: add indenting option
+# 2008-10-01, Sebastien Helleu <[email protected]>:
+#     v0.6: add default color for buffers, and color for current active buffer
+# 2008-09-18, Sebastien Helleu <[email protected]>:
+#     v0.5: fix color for "low" level entry in hotlist
+# 2008-09-18, Sebastien Helleu <[email protected]>:
+#     v0.4: rename option "show_category" to "short_names",
+#           remove option "color_slash"
+# 2008-09-15, Sebastien Helleu <[email protected]>:
+#     v0.3: fix bug with priority in hotlist (var not defined)
+# 2008-09-02, Sebastien Helleu <[email protected]>:
+#     v0.2: add color for buffers with activity and config options for
+#           colors, add config option to display/hide categories
+# 2008-03-15, Sebastien Helleu <[email protected]>:
+#     v0.1: script creation
+#
+# Help about settings:
+#   display all settings for script (or use iset.pl script to change settings):
+#      /set buffers*
+#   show help text for option buffers.look.whitelist_buffers:
+#      /help buffers.look.whitelist_buffers
+#
+# Mouse-support (standard key bindings):
+#   left mouse-button:
+#       - click on a buffer to switch to selected buffer
+#       - click on current buffer will do action jump_previously_visited_buffer
+#       - drag a buffer and drop it on another position will move the buffer to position
+#   right mouse-button:
+#       - click on current buffer will do action jump_next_visited_buffer
+#       - moving buffer to the left/right will close buffer.
+#
+
+use strict;
+use Encode qw( decode encode );
+# -----------------------------[ internal ]-------------------------------------
+my $SCRIPT_NAME = "buffers";
+my $SCRIPT_VERSION = "4.9";
+
+my $BUFFERS_CONFIG_FILE_NAME = "buffers";
+my $buffers_config_file;
+my $cmd_buffers_whitelist= "buffers_whitelist";
+my $cmd_buffers_detach   = "buffers_detach";
+
+my %mouse_keys = ("\@item(buffers):button1*" => "hsignal:buffers_mouse",
+                  "\@item(buffers):button2*" => "hsignal:buffers_mouse",
+                  "\@bar(buffers):ctrl-wheelup" => "hsignal:buffers_mouse",
+                  "\@bar(buffers):ctrl-wheeldown" => "hsignal:buffers_mouse");
+my %options;
+my %hotlist_level = (0 => "low", 1 => "message", 2 => "private", 3 => "highlight");
+my @whitelist_buffers = ();
+my @immune_detach_buffers= ();
+my @detach_buffer_immediately= ();
+my @buffers_focus = ();
+my %buffers_timer = ();
+my %Hooks = ();
+
+# --------------------------------[ init ]--------------------------------------
+weechat::register($SCRIPT_NAME, "Sebastien Helleu <flashcode\@flashtux.org>",
+                  $SCRIPT_VERSION, "GPL3",
+                  "Sidebar with list of buffers", "shutdown_cb", "");
+my $weechat_version = weechat::info_get("version_number", "") || 0;
+
+buffers_config_init();
+buffers_config_read();
+
+weechat::bar_item_new($SCRIPT_NAME, "build_buffers", "");
+weechat::bar_new($SCRIPT_NAME, "0", "0", "root", "", "left", "columns_vertical",
+                 "vertical", "0", "0", "default", "default", "default", "1",
+                 $SCRIPT_NAME);
+
+if ( check_bar_item() == 0 )
+{
+    weechat::command("", "/bar show " . $SCRIPT_NAME) if ( weechat::config_boolean($options{"toggle_bar"}) eq 1 );
+}
+
+weechat::hook_signal("buffer_opened", "buffers_signal_buffer", "");
+weechat::hook_signal("buffer_closed", "buffers_signal_buffer", "");
+weechat::hook_signal("buffer_merged", "buffers_signal_buffer", "");
+weechat::hook_signal("buffer_unmerged", "buffers_signal_buffer", "");
+weechat::hook_signal("buffer_moved", "buffers_signal_buffer", "");
+weechat::hook_signal("buffer_renamed", "buffers_signal_buffer", "");
+weechat::hook_signal("buffer_switch", "buffers_signal_buffer", "");
+weechat::hook_signal("buffer_hidden", "buffers_signal_buffer", "");  # WeeChat >= 0.4.4
+weechat::hook_signal("buffer_unhidden", "buffers_signal_buffer", "");  # WeeChat >= 0.4.4
+weechat::hook_signal("buffer_localvar_added", "buffers_signal_buffer", "");
+weechat::hook_signal("buffer_localvar_changed", "buffers_signal_buffer", "");
+
+weechat::hook_signal("window_switch", "buffers_signal_buffer", "");
+weechat::hook_signal("hotlist_changed", "buffers_signal_hotlist", "");
+#weechat::hook_command_run("/input switch_active_*", "buffers_signal_buffer", "");
+weechat::bar_item_update($SCRIPT_NAME);
+
+
+if ($weechat_version >= 0x00030600)
+{
+    weechat::hook_focus($SCRIPT_NAME, "buffers_focus_buffers", "");
+    weechat::hook_hsignal("buffers_mouse", "buffers_hsignal_mouse", "");
+    weechat::key_bind("mouse", \%mouse_keys);
+}
+
+weechat::hook_command($cmd_buffers_whitelist,
+                      "add/del current buffer to/from buffers whitelist",
+                      "[add] || [del] || [reset]",
+                      "  add: add current buffer in configuration file\n".
+                      "  del: delete current buffer from configuration file\n".
+                      "reset: reset all buffers from configuration file ".
+                      "(no confirmation!)\n\n".
+                      "Examples:\n".
+                      "/$cmd_buffers_whitelist add\n",
+                      "add %-||".
+                      "del %-||".
+                      "reset %-",
+                      "buffers_cmd_whitelist", "");
+weechat::hook_command($cmd_buffers_detach,
+                      "add/del current buffer to/from buffers detach",
+                      "[add] || [del] || [reset]",
+                      "  add: add current buffer in configuration file\n".
+                      "  del: delete current buffer from configuration file\n".
+                      "reset: reset all buffers from configuration file ".
+                      "(no confirmation!)\n\n".
+                      "Examples:\n".
+                      "/$cmd_buffers_detach add\n",
+                      "add %-||".
+                      "del %-||".
+                      "reset %-",
+                      "buffers_cmd_detach", "");
+
+if ($weechat_version >= 0x00030800)
+{
+    weechat::hook_config("buffers.look.detach", "hook_timer_detach", "");
+    if (weechat::config_integer($options{"detach"}) > 0)
+    {
+        $Hooks{timer_detach} = weechat::hook_timer(weechat::config_integer($options{"detach"}) * 1000,
+                                                   60, 0, "buffers_signal_hotlist", "");
+    }
+}
+
+weechat::hook_config("buffers.look.show_lag", "hook_timer_lag", "");
+
+if (weechat::config_boolean($options{"show_lag"}))
+{
+    $Hooks{timer_lag} = weechat::hook_timer(
+        weechat::config_integer(weechat::config_get("irc.network.lag_refresh_interval")) * 1000,
+        0, 0, "buffers_signal_hotlist", "");
+}
+
+# -------------------------------- [ command ] --------------------------------
+sub buffers_cmd_whitelist
+{
+my ( $data, $buffer, $args ) = @_;
+    $args = lc($args);
+    my $buffers_whitelist = weechat::config_string( weechat::config_get("buffers.look.whitelist_buffers") );
+    return weechat::WEECHAT_RC_OK if ( $buffers_whitelist eq "" and $args eq "del" or $buffers_whitelist eq "" and $args eq "reset" );
+    my @buffers_list = split( /,/, $buffers_whitelist );
+    # get buffers name
+    my $infolist = weechat::infolist_get("buffer", weechat::current_buffer(), "");
+    weechat::infolist_next($infolist);
+    my $buffers_name = weechat::infolist_string($infolist, "name");
+    weechat::infolist_free($infolist);
+    return weechat::WEECHAT_RC_OK if ( $buffers_name eq "" );                   # should never happen
+
+    if ( $args eq "add" )
+    {
+        return weechat::WEECHAT_RC_OK if ( grep /^$buffers_name$/, @buffers_list );     # check if buffer already in list
+        push @buffers_list, ( $buffers_name );
+        my $buffers_list = &create_whitelist(\@buffers_list);
+        weechat::config_option_set( weechat::config_get("buffers.look.whitelist_buffers"), $buffers_list, 1);
+        weechat::print(weechat::current_buffer(), "buffer \"$buffers_name\" added to buffers whitelist");
+    }
+    elsif ( $args eq "del" )
+    {
+        return weechat::WEECHAT_RC_OK unless ( grep /^$buffers_name$/, @buffers_list );     # check if buffer is in list
+        @buffers_list = grep {$_ ne $buffers_name} @buffers_list;                           # delete entry
+        my $buffers_list = &create_whitelist(\@buffers_list);
+        weechat::config_option_set( weechat::config_get("buffers.look.whitelist_buffers"), $buffers_list, 1);
+        weechat::print(weechat::current_buffer(), "buffer \"$buffers_name\" deleted from buffers whitelist");
+    }
+    elsif ( $args eq "reset" )
+    {
+        return weechat::WEECHAT_RC_OK if ( $buffers_whitelist eq "" );
+        weechat::config_option_set( weechat::config_get("buffers.look.whitelist_buffers"), "", 1);
+        weechat::print(weechat::current_buffer(), "buffers whitelist is empty, now...");
+    }
+    return weechat::WEECHAT_RC_OK;
+}
+sub buffers_cmd_detach
+{
+    my ( $data, $buffer, $args ) = @_;
+    $args = lc($args);
+    my $immune_detach_buffers = weechat::config_string( weechat::config_get("buffers.look.immune_detach_buffers") );
+    return weechat::WEECHAT_RC_OK if ( $immune_detach_buffers eq "" and $args eq "del" or $immune_detach_buffers eq "" and $args eq "reset" );
+
+    my @buffers_list = split( /,/, $immune_detach_buffers );
+    # get buffers name
+    my $infolist = weechat::infolist_get("buffer", weechat::current_buffer(), "");
+    weechat::infolist_next($infolist);
+    my $buffers_name = weechat::infolist_string($infolist, "name");
+    weechat::infolist_free($infolist);
+    return weechat::WEECHAT_RC_OK if ( $buffers_name eq "" );                   # should never happen
+
+    if ( $args eq "add" )
+    {
+        return weechat::WEECHAT_RC_OK if ( grep /^$buffers_name$/, @buffers_list );     # check if buffer already in list
+        push @buffers_list, ( $buffers_name );
+        my $buffers_list = &create_whitelist(\@buffers_list);
+        weechat::config_option_set( weechat::config_get("buffers.look.immune_detach_buffers"), $buffers_list, 1);
+        weechat::print(weechat::current_buffer(), "buffer \"$buffers_name\" added to immune detach buffers");
+    }
+    elsif ( $args eq "del" )
+    {
+        return weechat::WEECHAT_RC_OK unless ( grep /^$buffers_name$/, @buffers_list );     # check if buffer is in list
+        @buffers_list = grep {$_ ne $buffers_name} @buffers_list;                           # delete entry
+        my $buffers_list = &create_whitelist(\@buffers_list);
+        weechat::config_option_set( weechat::config_get("buffers.look.immune_detach_buffers"), $buffers_list, 1);
+        weechat::print(weechat::current_buffer(), "buffer \"$buffers_name\" deleted from immune detach buffers");
+    }
+    elsif ( $args eq "reset" )
+    {
+        return weechat::WEECHAT_RC_OK if ( $immune_detach_buffers eq "" );
+        weechat::config_option_set( weechat::config_get("buffers.look.immune_detach_buffers"), "", 1);
+        weechat::print(weechat::current_buffer(), "immune detach buffers is empty, now...");
+    }
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub create_whitelist
+{
+    my @buffers_list = @{$_[0]};
+    my $buffers_list = "";
+        foreach (@buffers_list)
+        {
+            $buffers_list .= $_ .",";
+        }
+        # remove last ","
+        chop $buffers_list;
+    return $buffers_list;
+}
+
+# -------------------------------- [ config ] --------------------------------
+sub hook_timer_detach
+{
+    my $detach = $_[2];
+    if ( $detach eq 0 )
+    {
+        weechat::unhook($Hooks{timer_detach}) if $Hooks{timer_detach};
+        $Hooks{timer_detach} = "";
+    }
+    else
+    {
+        weechat::unhook($Hooks{timer_detach}) if $Hooks{timer_detach};
+        $Hooks{timer_detach} = weechat::hook_timer( weechat::config_integer( $options{"detach"}) * 1000, 60, 0, "buffers_signal_hotlist", "");
+    }
+    weechat::bar_item_update($SCRIPT_NAME);
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub hook_timer_lag
+{
+    my $lag = $_[2];
+    if ( $lag eq "off" )
+    {
+        weechat::unhook($Hooks{timer_lag}) if $Hooks{timer_lag};
+        $Hooks{timer_lag} = "";
+    }
+    else
+    {
+        weechat::unhook($Hooks{timer_lag}) if $Hooks{timer_lag};
+        $Hooks{timer_lag} = weechat::hook_timer( weechat::config_integer(weechat::config_get("irc.network.lag_refresh_interval")) * 1000, 0, 0, "buffers_signal_hotlist", "");
+    }
+    weechat::bar_item_update($SCRIPT_NAME);
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub buffers_config_read
+{
+    return weechat::config_read($buffers_config_file) if ($buffers_config_file ne "");
+}
+sub buffers_config_write
+{
+    return weechat::config_write($buffers_config_file) if ($buffers_config_file ne "");
+}
+sub buffers_config_reload_cb
+{
+    my ($data, $config_file) = ($_[0], $_[1]);
+    return weechat::config_reload($config_file)
+}
+sub buffers_config_init
+{
+    $buffers_config_file = weechat::config_new($BUFFERS_CONFIG_FILE_NAME,
+                                               "buffers_config_reload_cb", "");
+    return if ($buffers_config_file eq "");
+
+my %default_options_color =
+("color_current_fg" => [
+     "current_fg", "color",
+     "foreground color for current buffer",
+     "", 0, 0, "lightcyan", "lightcyan", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_current_bg" => [
+     "current_bg", "color",
+     "background color for current buffer",
+     "", 0, 0, "red", "red", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_default_fg" => [
+     "default_fg", "color",
+     "default foreground color for buffer name",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_default_bg" => [
+     "default_bg", "color",
+     "default background color for buffer name",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_hotlist_highlight_fg" => [
+     "hotlist_highlight_fg", "color",
+     "change foreground color of buffer name if a highlight messaged received",
+     "", 0, 0, "magenta", "magenta", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_hotlist_highlight_bg" => [
+     "hotlist_highlight_bg", "color",
+     "change background color of buffer name if a highlight messaged received",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_hotlist_low_fg" => [
+     "hotlist_low_fg", "color",
+     "change foreground color of buffer name if a low message received",
+     "", 0, 0, "white", "white", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_hotlist_low_bg" => [
+     "hotlist_low_bg", "color",
+     "change background color of buffer name if a low message received",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_hotlist_message_fg" => [
+     "hotlist_message_fg", "color",
+     "change foreground color of buffer name if a normal message received",
+     "", 0, 0, "yellow", "yellow", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_hotlist_message_bg" => [
+     "hotlist_message_bg", "color",
+     "change background color of buffer name if a normal message received",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_hotlist_private_fg" => [
+     "hotlist_private_fg", "color",
+     "change foreground color of buffer name if a private message received",
+     "", 0, 0, "lightgreen", "lightgreen", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_hotlist_private_bg" => [
+     "hotlist_private_bg", "color",
+     "change background color of buffer name if a private message received",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_number" => [
+     "number", "color",
+     "color for buffer number",
+     "", 0, 0, "lightgreen", "lightgreen", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_number_char" => [
+     "number_char", "color",
+     "color for buffer number char",
+     "", 0, 0, "lightgreen", "lightgreen", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_whitelist_default_fg" => [
+     "whitelist_default_fg", "color",
+     "default foreground color for whitelist buffer name",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_whitelist_default_bg" => [
+     "whitelist_default_bg", "color",
+     "default background color for whitelist buffer name",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_whitelist_low_fg" => [
+     "whitelist_low_fg", "color",
+     "low color of whitelist buffer name",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_whitelist_low_bg" => [
+     "whitelist_low_bg", "color",
+     "low color of whitelist buffer name",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_whitelist_message_fg" => [
+     "whitelist_message_fg", "color",
+     "message color of whitelist buffer name",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_whitelist_message_bg" => [
+     "whitelist_message_bg", "color",
+     "message color of whitelist buffer name",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_whitelist_private_fg" => [
+     "whitelist_private_fg", "color",
+     "private color of whitelist buffer name",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_whitelist_private_bg" => [
+     "whitelist_private_bg", "color",
+     "private color of whitelist buffer name",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_whitelist_highlight_fg" => [
+     "whitelist_highlight_fg", "color",
+     "highlight color of whitelist buffer name",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_whitelist_highlight_bg" => [
+     "whitelist_highlight_bg", "color",
+     "highlight color of whitelist buffer name",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_none_channel_fg" => [
+     "none_channel_fg", "color",
+     "foreground color for none channel buffer (e.g.: core/server/plugin ".
+     "buffer)",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_none_channel_bg" => [
+     "none_channel_bg", "color",
+     "background color for none channel buffer (e.g.: core/server/plugin ".
+     "buffer)",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "queries_default_fg" => [
+     "queries_default_fg", "color",
+     "foreground color for query buffer without message",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "queries_default_bg" => [
+     "queries_default_bg", "color",
+     "background color for query buffer without message",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "queries_message_fg" => [
+     "queries_message_fg", "color",
+     "foreground color for query buffer with unread message",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "queries_message_bg" => [
+     "queries_message_bg", "color",
+     "background color for query buffer with unread message",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "queries_highlight_fg" => [
+     "queries_highlight_fg", "color",
+     "foreground color for query buffer with unread highlight",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "queries_highlight_bg" => [
+     "queries_highlight_bg", "color",
+     "background color for query buffer with unread highlight",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_prefix_bufname" => [
+     "prefix_bufname", "color",
+     "color for prefix of buffer name",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_suffix_bufname" => [
+     "suffix_bufname", "color",
+     "color for suffix of buffer name",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+);
+
+my %default_options_look =
+(
+ "hotlist_counter" => [
+     "hotlist_counter", "boolean",
+     "show number of message for the buffer (this option needs WeeChat >= ".
+     "0.3.5). The relevant option for notification is \"weechat.look.".
+     "buffer_notify_default\"",
+     "", 0, 0, "off", "off", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "show_lag" => [
+     "show_lag", "boolean",
+     "show lag behind server name. This option is using \"irc.color.".
+     "item_lag_finished\", ".
+     "\"irc.network.lag_min_show\" and \"irc.network.lag_refresh_interval\"",
+     "", 0, 0, "off", "off", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "look_whitelist_buffers" => [
+     "whitelist_buffers", "string",
+     "comma separated list of buffers for using a different color scheme ".
+     "(for example: freenode.#weechat,freenode.#weechat-fr)",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config_whitelist", "", "", ""
+ ],
+ "hide_merged_buffers" => [
+     "hide_merged_buffers", "integer",
+     "hide merged buffers. The value determines which merged buffers should ".
+     "be hidden, keepserver meaning 'all except server buffers'. Other values ".
+     "correspondent to the buffer type.",
+     "server|channel|private|keepserver|all|none", 0, 0, "none", "none", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "indenting" => [
+     "indenting", "integer", "use indenting for channel and query buffers. ".
+     "This option only takes effect if bar is left/right positioned",
+     "off|on|under_name", 0, 0, "off", "off", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "indenting_number" => [
+     "indenting_number", "boolean",
+     "use indenting for numbers. This option only takes effect if bar is ".
+     "left/right positioned",
+     "", 0, 0, "on", "on", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "short_names" => [
+     "short_names", "boolean",
+     "display short names (remove text before first \".\" in buffer name)",
+     "", 0, 0, "on", "on", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "show_number" => [
+     "show_number", "boolean",
+     "display buffer number in front of buffer name",
+     "", 0, 0, "on", "on", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "show_number_char" => [
+     "number_char", "string",
+     "display a char behind buffer number",
+     "", 0, 0, ".", ".", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "show_prefix_bufname" => [
+     "prefix_bufname", "string",
+     "prefix displayed in front of buffer name",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "show_suffix_bufname" => [
+     "suffix_bufname", "string",
+     "suffix displayed at end of buffer name",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "show_prefix" => [
+     "prefix", "boolean",
+     "displays your prefix for channel in front of buffer name",
+     "", 0, 0, "off", "off", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "show_prefix_empty" => [
+     "prefix_empty", "boolean",
+     "use a placeholder for channels without prefix",
+     "", 0, 0, "on", "on", 0,
+     "", "",  "buffers_signal_config", "", "", ""
+ ],
+ "show_prefix_query" => [
+     "prefix_for_query", "string",
+     "prefix displayed in front of query buffer",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "sort" => [
+     "sort", "integer",
+     "sort buffer-list by \"number\" or \"name\"",
+     "number|name", 0, 0, "number", "number", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "core_to_front" => [
+     "core_to_front", "boolean",
+     "core buffer and buffers with free content will be listed first. ".
+     "Take only effect if buffer sort is by name",
+     "", 0, 0, "off", "off", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "jump_prev_next_visited_buffer" => [
+     "jump_prev_next_visited_buffer", "boolean",
+     "jump to previously or next visited buffer if you click with ".
+     "left/right mouse button on currently visiting buffer",
+     "", 0, 0, "off", "off", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "name_size_max" => [
+     "name_size_max", "integer",
+     "maximum size of buffer name. 0 means no limitation",
+     "", 0, 256, 0, 0, 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "name_crop_suffix" => [
+     "name_crop_suffix", "string",
+     "contains an optional char(s) that is appended when buffer name is ".
+     "shortened",
+     "", 0, 0, "+", "+", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "detach" => [
+     "detach", "integer",
+     "detach buffer from buffers list after a specific period of time ".
+     "(in seconds) without action (weechat ≥ 0.3.8 required) (0 means \"off\")",
+     "", 0, 31536000, 0, "number", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "immune_detach_buffers" => [
+     "immune_detach_buffers", "string",
+     "comma separated list of buffers to NOT automatically detach. ".
+     "Allows \"*\" wildcard. Ex: \"BitlBee,freenode.*\"",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config_immune_detach_buffers", "", "", ""
+ ],
+ "detach_query" => [
+     "detach_query", "boolean",
+     "query buffer will be detached",
+     "", 0, 0, "off", "off", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "detach_buffer_immediately" => [
+     "detach_buffer_immediately", "string",
+     "comma separated list of buffers to detach immediately. A query and ".
+     "highlight message will attach buffer again. Allows \"*\" wildcard. ".
+     "Ex: \"BitlBee,freenode.*\"",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config_detach_buffer_immediately", "", "", ""
+ ],
+ "detach_free_content" => [
+     "detach_free_content", "boolean",
+     "buffers with free content will be detached (Ex: iset, chanmon)",
+     "", 0, 0, "off", "off", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "detach_displayed_buffers" => [
+     "detach_displayed_buffers", "boolean",
+     "buffers displayed in a (split) window will be detached",
+     "", 0, 0, "on", "on", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "detach_display_window_number" => [
+     "detach_display_window_number", "boolean",
+     "window number will be add, behind buffer name (this option takes only ".
+     "effect with \"detach_displayed_buffers\" option)",
+     "", 0, 0, "off", "off", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "mark_inactive" => [
+     "mark_inactive", "boolean",
+     "if option is \"on\", inactive buffers (those you are not in) will have ".
+     "parentheses around them. An inactive buffer will not be detached.",
+     "", 0, 0, "off", "off", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "toggle_bar" => [
+     "toggle_bar", "boolean",
+     "if option is \"on\", buffers bar will hide/show when script is ".
+     "(un)loaded.",
+     "", 0, 0, "on", "on", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "mouse_move_buffer" => [
+     "mouse_move_buffer", "boolean",
+     "if option is \"on\", mouse gestures (drag & drop) can move buffers in list.",
+     "", 0, 0, "on", "on", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "mouse_wheel" => [
+     "mouse_wheel", "boolean",
+     "if option is \"on\", mouse wheel jumps to previous/next buffer in list.",
+     "", 0, 0, "on", "on", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+);
+    # section "color"
+    my $section_color = weechat::config_new_section(
+        $buffers_config_file,
+        "color", 0, 0, "", "", "", "", "", "", "", "", "", "");
+    if ($section_color eq "")
+    {
+        weechat::config_free($buffers_config_file);
+        return;
+    }
+    foreach my $option (keys %default_options_color)
+    {
+        $options{$option} = weechat::config_new_option(
+            $buffers_config_file,
+            $section_color,
+            $default_options_color{$option}[0],
+            $default_options_color{$option}[1],
+            $default_options_color{$option}[2],
+            $default_options_color{$option}[3],
+            $default_options_color{$option}[4],
+            $default_options_color{$option}[5],
+            $default_options_color{$option}[6],
+            $default_options_color{$option}[7],
+            $default_options_color{$option}[8],
+            $default_options_color{$option}[9],
+            $default_options_color{$option}[10],
+            $default_options_color{$option}[11],
+            $default_options_color{$option}[12],
+            $default_options_color{$option}[13],
+            $default_options_color{$option}[14]);
+    }
+
+    # section "look"
+    my $section_look = weechat::config_new_section(
+        $buffers_config_file,
+        "look", 0, 0, "", "", "", "", "", "", "", "", "", "");
+    if ($section_look eq "")
+    {
+        weechat::config_free($buffers_config_file);
+        return;
+    }
+    foreach my $option (keys %default_options_look)
+    {
+        $options{$option} = weechat::config_new_option(
+            $buffers_config_file,
+            $section_look,
+            $default_options_look{$option}[0],
+            $default_options_look{$option}[1],
+            $default_options_look{$option}[2],
+            $default_options_look{$option}[3],
+            $default_options_look{$option}[4],
+            $default_options_look{$option}[5],
+            $default_options_look{$option}[6],
+            $default_options_look{$option}[7],
+            $default_options_look{$option}[8],
+            $default_options_look{$option}[9],
+            $default_options_look{$option}[10],
+            $default_options_look{$option}[11],
+            $default_options_look{$option}[12],
+            $default_options_look{$option}[13],
+            $default_options_look{$option}[14],
+            $default_options_look{$option}[15]);
+    }
+}
+
+sub build_buffers
+{
+    my $str = "";
+
+    # get bar position (left/right/top/bottom)
+    my $position = "left";
+    my $option_position = weechat::config_get("weechat.bar.buffers.position");
+    if ($option_position ne "")
+    {
+        $position = weechat::config_string($option_position);
+    }
+
+    # read hotlist
+    my %hotlist;
+    my $infolist = weechat::infolist_get("hotlist", "", "");
+    while (weechat::infolist_next($infolist))
+    {
+        $hotlist{weechat::infolist_pointer($infolist, "buffer_pointer")} =
+            weechat::infolist_integer($infolist, "priority");
+        if ( weechat::config_boolean( $options{"hotlist_counter"} ) eq 1 and $weechat_version >= 0x00030500)
+        {
+            $hotlist{weechat::infolist_pointer($infolist, "buffer_pointer")."_count_00"} =
+                weechat::infolist_integer($infolist, "count_00");   # low message
+            $hotlist{weechat::infolist_pointer($infolist, "buffer_pointer")."_count_01"} =
+                weechat::infolist_integer($infolist, "count_01");   # channel message
+            $hotlist{weechat::infolist_pointer($infolist, "buffer_pointer")."_count_02"} =
+                weechat::infolist_integer($infolist, "count_02");   # private message
+            $hotlist{weechat::infolist_pointer($infolist, "buffer_pointer")."_count_03"} =
+                weechat::infolist_integer($infolist, "count_03");   # highlight message
+        }
+    }
+    weechat::infolist_free($infolist);
+
+    # read buffers list
+    @buffers_focus = ();
+    my @buffers;
+    my @current1 = ();
+    my @current2 = ();
+    my $old_number = -1;
+    my $max_number = 0;
+    my $max_number_digits = 0;
+    my $active_seen = 0;
+    $infolist = weechat::infolist_get("buffer", "", "");
+    while (weechat::infolist_next($infolist))
+    {
+        # ignore hidden buffers (WeeChat >= 0.4.4)
+        if ($weechat_version >= 0x00040400)
+        {
+            next if (weechat::infolist_integer($infolist, "hidden"));
+        }
+        my $buffer;
+        my $number = weechat::infolist_integer($infolist, "number");
+        if ($number ne $old_number)
+        {
+            @buffers = (@buffers, @current2, @current1);
+            @current1 = ();
+            @current2 = ();
+            $active_seen = 0;
+        }
+        if ($number > $max_number)
+        {
+            $max_number = $number;
+        }
+        $old_number = $number;
+        my $active = weechat::infolist_integer($infolist, "active");
+        if ($active)
+        {
+            $active_seen = 1;
+        }
+        $buffer->{"pointer"} = weechat::infolist_pointer($infolist, "pointer");
+        $buffer->{"number"} = $number;
+        $buffer->{"active"} = $active;
+        $buffer->{"current_buffer"} = weechat::infolist_integer($infolist, "current_buffer");
+        $buffer->{"num_displayed"} = weechat::infolist_integer($infolist, "num_displayed");
+        $buffer->{"plugin_name"} = weechat::infolist_string($infolist, "plugin_name");
+        $buffer->{"name"} = weechat::infolist_string($infolist, "name");
+        $buffer->{"short_name"} = weechat::infolist_string($infolist, "short_name");
+        $buffer->{"full_name"} = $buffer->{"plugin_name"}.".".$buffer->{"name"};
+        $buffer->{"type"} = weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type");
+        #weechat::print("", $buffer->{"type"});
+
+        # check if buffer is active (or maybe a /part, /kick channel)
+        if ($buffer->{"type"} eq "channel" and weechat::config_boolean( $options{"mark_inactive"} ) eq 1)
+        {
+            my $server = weechat::buffer_get_string($buffer->{"pointer"}, "localvar_server");
+            my $channel = weechat::buffer_get_string($buffer->{"pointer"}, "localvar_channel");
+            my $infolist_channel = weechat::infolist_get("irc_channel", "", $server.",".$channel);
+            if ($infolist_channel)
+            {
+                weechat::infolist_next($infolist_channel);
+                $buffer->{"nicks_count"} = weechat::infolist_integer($infolist_channel, "nicks_count");
+            }else
+            {
+                $buffer->{"nicks_count"} = 0;
+            }
+            weechat::infolist_free($infolist_channel);
+        }
+
+        my $result = check_immune_detached_buffers($buffer->{"name"});          # checking for wildcard 
+
+        next if ( check_detach_buffer_immediately($buffer->{"name"}) eq 1
+                 and $buffer->{"current_buffer"} eq 0
+                 and ( not exists $hotlist{$buffer->{"pointer"}} or $hotlist{$buffer->{"pointer"}} < 2) );          # checking for buffer to immediately detach
+
+        unless ($result)
+        {
+            my $detach_time = weechat::config_integer( $options{"detach"});
+            my $current_time = time();
+            # set timer for buffers with no hotlist action
+            $buffers_timer{$buffer->{"pointer"}} = $current_time
+             if ( not exists $hotlist{$buffer->{"pointer"}}
+             and $buffer->{"type"} eq "channel"
+             and not exists $buffers_timer{$buffer->{"pointer"}}
+             and $detach_time > 0);
+
+            $buffers_timer{$buffer->{"pointer"}} = $current_time
+            if (weechat::config_boolean($options{"detach_query"}) eq 1
+            and not exists $hotlist{$buffer->{"pointer"}}
+            and $buffer->{"type"} eq "private"
+            and not exists $buffers_timer{$buffer->{"pointer"}}
+            and $detach_time > 0);
+
+            $detach_time = 0
+            if (weechat::config_boolean($options{"detach_query"}) eq 0
+            and $buffer->{"type"} eq "private");
+
+            # free content buffer
+            $buffers_timer{$buffer->{"pointer"}} = $current_time
+            if (weechat::config_boolean($options{"detach_free_content"}) eq 1
+            and not exists $hotlist{$buffer->{"pointer"}}
+            and $buffer->{"type"} eq ""
+            and not exists $buffers_timer{$buffer->{"pointer"}}
+            and $detach_time > 0);
+            $detach_time = 0
+            if (weechat::config_boolean($options{"detach_free_content"}) eq 0
+            and $buffer->{"type"} eq "");
+
+            $detach_time = 0 if (weechat::config_boolean($options{"mark_inactive"}) eq 1 and defined $buffer->{"nicks_count"} and $buffer->{"nicks_count"} == 0);
+
+            # check for detach
+            unless ( $buffer->{"current_buffer"} eq 0
+            and not exists $hotlist{$buffer->{"pointer"}}
+#            and $buffer->{"type"} eq "channel"
+            and exists $buffers_timer{$buffer->{"pointer"}}
+            and $detach_time > 0
+            and $weechat_version >= 0x00030800
+            and $current_time - $buffers_timer{$buffer->{"pointer"}} >= $detach_time)
+            {
+                if ($active_seen)
+                {
+                    push(@current2, $buffer);
+                }
+                else
+                {
+                    push(@current1, $buffer);
+                }
+            }
+            elsif ( $buffer->{"current_buffer"} eq 0
+            and not exists $hotlist{$buffer->{"pointer"}}
+#            and $buffer->{"type"} eq "channel"
+            and exists $buffers_timer{$buffer->{"pointer"}}
+            and $detach_time > 0
+            and $weechat_version >= 0x00030800
+            and $current_time - $buffers_timer{$buffer->{"pointer"}} >= $detach_time)
+            {   # check for option detach_displayed_buffers and if buffer is displayed in a split window
+                if ( $buffer->{"num_displayed"} eq 1
+                    and weechat::config_boolean($options{"detach_displayed_buffers"}) eq 0 )
+                {
+                    my $infolist_window = weechat::infolist_get("window", "", "");
+                    while (weechat::infolist_next($infolist_window))
+                    {
+                        my $buffer_ptr = weechat::infolist_pointer($infolist_window, "buffer");
+                        if ($buffer_ptr eq $buffer->{"pointer"})
+                        {
+                            $buffer->{"window"} = weechat::infolist_integer($infolist_window, "number");
+                        }
+                    }
+                    weechat::infolist_free($infolist_window);
+
+                    push(@current2, $buffer);
+                }
+            }
+        }
+        else    # buffer in "immune_detach_buffers"
+        {
+                if ($active_seen)
+                {
+                    push(@current2, $buffer);
+                }
+                else
+                {
+                    push(@current1, $buffer);
+                }
+        }
+    }   # while end
+
+
+    if ($max_number >= 1)
+    {
+        $max_number_digits = length(int($max_number));
+    }
+    @buffers = (@buffers, @current2, @current1);
+    weechat::infolist_free($infolist);
+
+    # sort buffers by number, name or shortname
+    my %sorted_buffers;
+    if (1)
+    {
+        my $number = 0;
+        for my $buffer (@buffers)
+        {
+            my $key;
+            if (weechat::config_integer( $options{"sort"} ) eq 1) # number = 0; name = 1
+            {
+                my $name = weechat::buffer_get_string($buffer->{"pointer"}, "localvar_custom_name");
+                if (not defined $name or $name eq "") {
+                    if (weechat::config_boolean( $options{"short_names"} ) eq 1) {
+                        $name = $buffer->{"short_name"};
+                    } else {
+                        $name = $buffer->{"name"};
+                    }
+                }
+                if (weechat::config_integer($options{"name_size_max"}) >= 1){
+                    $name = encode("UTF-8", substr(decode("UTF-8", $name), 0, weechat::config_integer($options{"name_size_max"})));
+                }
+                if ( weechat::config_boolean($options{"core_to_front"}) eq 1)
+                {
+                    if ( (weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") ne "channel" ) and ( weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") ne "private") )
+                    {
+                        my $type = weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type");
+                        if ( $type eq "" and $name ne "weechat")
+                        {
+                            $name = " " . $name
+                        }else
+                        {
+                            $name = "  " . $name;
+                        }
+                    }
+                }
+                $key = sprintf("%s%08d", lc($name), $buffer->{"number"});
+            }
+            else
+            {
+                $key = sprintf("%08d", $number);
+            }
+            $sorted_buffers{$key} = $buffer;
+            $number++;
+        }
+    }
+
+    # build string with buffers
+    $old_number = -1;
+    foreach my $key (sort keys %sorted_buffers)
+    {
+        my $buffer = $sorted_buffers{$key};
+
+        if ( weechat::config_string($options{"hide_merged_buffers"}) eq "server" )
+        {
+            # buffer type "server" or merged with core?
+            if ( ($buffer->{"type"} eq "server" or $buffer->{"plugin_name"} eq "core") && (! $buffer->{"active"}) )
+            {
+                next;
+            }
+        }
+        if ( weechat::config_string($options{"hide_merged_buffers"}) eq "channel" )
+        {
+            # buffer type "channel" or merged with core?
+            if ( ($buffer->{"type"} eq "channel" or $buffer->{"plugin_name"} eq "core") && (! $buffer->{"active"}) )
+            {
+                next;
+            }
+        }
+        if ( weechat::config_string($options{"hide_merged_buffers"}) eq "private" )
+        {
+            # buffer type "private" or merged with core?
+            if ( ($buffer->{"type"} eq "private" or $buffer->{"plugin_name"} eq "core") && (! $buffer->{"active"}) )
+            {
+                next;
+            }
+        }
+        if ( weechat::config_string($options{"hide_merged_buffers"}) eq "keepserver" )
+        {
+            if ( ($buffer->{"type"} ne "server" or $buffer->{"plugin_name"} eq "core") && (! $buffer->{"active"}) )
+            {
+                next;
+            }
+        }
+        if ( weechat::config_string($options{"hide_merged_buffers"}) eq "all" )
+        {
+            if ( ! $buffer->{"active"} )
+            {
+                next;
+            }
+        }
+
+        push(@buffers_focus, $buffer);                                          # buffer > buffers_focus, for mouse support
+        my $color = "";
+        my $bg = "";
+
+        $color = weechat::config_color( $options{"color_default_fg"} );
+        $bg = weechat::config_color( $options{"color_default_bg"} );
+
+        if ( weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") eq "private" )
+        {
+            if ( (weechat::config_color($options{"queries_default_bg"})) ne "default" || (weechat::config_color($options{"queries_default_fg"})) ne "default" )
+            {
+              $bg = weechat::config_color( $options{"queries_default_bg"} );
+              $color = weechat::config_color( $options{"queries_default_fg"} );
+            }
+        }
+        # check for core and buffer with free content
+        if ( (weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") ne "channel" ) and ( weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") ne "private") )
+        {
+            $color = weechat::config_color( $options{"color_none_channel_fg"} );
+            $bg = weechat::config_color( $options{"color_none_channel_bg"} );
+        }
+        # default whitelist buffer?
+        if (grep {$_ eq $buffer->{"name"}} @whitelist_buffers)
+        {
+                $color = weechat::config_color( $options{"color_whitelist_default_fg"} );
+                $bg = weechat::config_color( $options{"color_whitelist_default_bg"} );
+        }
+
+        $color = "default" if ($color eq "");
+
+        # color for channel and query buffer
+        if (exists $hotlist{$buffer->{"pointer"}})
+        {
+        delete $buffers_timer{$buffer->{"pointer"}};
+            # check if buffer is in whitelist buffer
+            if (grep {$_ eq $buffer->{"name"}} @whitelist_buffers)
+            {
+                $bg = weechat::config_color( $options{"color_whitelist_".$hotlist_level{$hotlist{$buffer->{"pointer"}}}."_bg"} );
+                $color = weechat::config_color( $options{"color_whitelist_".$hotlist_level{$hotlist{$buffer->{"pointer"}}}."_fg"} );
+            }
+            elsif ( weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") eq "private" )
+            {
+                # queries_default_fg/bg and buffers.color.queries_message_fg/bg
+                if ( (weechat::config_color($options{"queries_highlight_fg"})) ne "default" ||
+                      (weechat::config_color($options{"queries_highlight_bg"})) ne "default" ||
+                       (weechat::config_color($options{"queries_message_fg"})) ne "default" ||
+                        (weechat::config_color($options{"queries_message_bg"})) ne "default" )
+                {
+                  if ( ($hotlist{$buffer->{"pointer"}}) == 2 )
+                  {
+                      $bg = weechat::config_color( $options{"queries_message_bg"} );
+                      $color = weechat::config_color( $options{"queries_message_fg"} );
+                  }
+
+                  elsif ( ($hotlist{$buffer->{"pointer"}}) == 3 )
+                  {
+                      $bg = weechat::config_color( $options{"queries_highlight_bg"} );
+                      $color = weechat::config_color( $options{"queries_highlight_fg"} );
+                  }
+                }else
+                {
+                      $bg = weechat::config_color( $options{"color_hotlist_".$hotlist_level{$hotlist{$buffer->{"pointer"}}}."_bg"} );
+                      $color = weechat::config_color( $options{"color_hotlist_".$hotlist_level{$hotlist{$buffer->{"pointer"}}}."_fg"}  );
+                }
+            }else
+            {
+                      $bg = weechat::config_color( $options{"color_hotlist_".$hotlist_level{$hotlist{$buffer->{"pointer"}}}."_bg"} );
+                      $color = weechat::config_color( $options{"color_hotlist_".$hotlist_level{$hotlist{$buffer->{"pointer"}}}."_fg"}  );
+            }
+        }
+
+        if ($buffer->{"current_buffer"})
+        {
+            $color = weechat::config_color( $options{"color_current_fg"} );
+            $bg = weechat::config_color( $options{"color_current_bg"} );
+        }
+        my $color_bg = "";
+        $color_bg = weechat::color(",".$bg) if ($bg ne "");
+
+        # create channel number for output
+        if ( weechat::config_string( $options{"show_prefix_bufname"} ) ne "" )
+        {
+            $str .= $color_bg .
+                    weechat::color( weechat::config_color( $options{"color_prefix_bufname"} ) ).
+                    weechat::config_string( $options{"show_prefix_bufname"} ).
+                    weechat::color("default");
+        }
+
+        if ( weechat::config_boolean( $options{"show_number"} ) eq 1 )   # on
+        {
+            if (( weechat::config_boolean( $options{"indenting_number"} ) eq 1)
+                && (($position eq "left") || ($position eq "right")))
+            {
+                $str .= weechat::color("default").$color_bg
+                    .(" " x ($max_number_digits - length(int($buffer->{"number"}))));
+            }
+            if ($old_number ne $buffer->{"number"})
+            {
+                $str .= weechat::color( weechat::config_color( $options{"color_number"} ) )
+                    .$color_bg
+                    .$buffer->{"number"}
+                    .weechat::color("default")
+                    .$color_bg
+                    .weechat::color( weechat::config_color( $options{"color_number_char"} ) )
+                    .weechat::config_string( $options{"show_number_char"} )
+                    .$color_bg;
+            }
+            else
+            {
+                my $indent = "";
+                $indent = ((" " x length($buffer->{"number"}))." ") if (($position eq "left") || ($position eq "right"));
+                $str .= weechat::color("default")
+                    .$color_bg
+                    .$indent;
+            }
+        }
+
+        if (( weechat::config_integer( $options{"indenting"} ) ne 0 )            # indenting NOT off
+            && (($position eq "left") || ($position eq "right")))
+        {
+            my $type = weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type");
+            if (($type eq "channel") || ($type eq "private"))
+            {
+                if ( weechat::config_integer( $options{"indenting"} ) eq 1 )
+                {
+                    $str .= "  ";
+                }
+                elsif ( (weechat::config_integer($options{"indenting"}) eq 2) and (weechat::config_integer($options{"indenting_number"}) eq 0) )        #under_name
+                {
+                    if ( weechat::config_boolean( $options{"show_number"} ) eq 0 )
+                    {
+                      $str .= "  ";
+                    }else
+                    {
+                      $str .= ( (" " x ( $max_number_digits - length($buffer->{"number"}) ))." " );
+                    }
+                }
+            }
+        }
+
+        $str .= weechat::config_string( $options{"show_prefix_query"}) if (weechat::config_string( $options{"show_prefix_query"} ) ne "" and  $buffer->{"type"} eq "private");
+
+        if (weechat::config_boolean( $options{"show_prefix"} ) eq 1)
+        {
+            my $nickname = weechat::buffer_get_string($buffer->{"pointer"}, "localvar_nick");
+            if ($nickname ne "")
+            {
+                # with version >= 0.3.2, this infolist will return only nick
+                # with older versions, whole nicklist is returned for buffer, and this can be very slow
+                my $infolist_nick = weechat::infolist_get("nicklist", $buffer->{"pointer"}, "nick_".$nickname);
+                if ($infolist_nick ne "")
+                {
+                    while (weechat::infolist_next($infolist_nick))
+                    {
+                        if ((weechat::infolist_string($infolist_nick, "type") eq "nick")
+                            && (weechat::infolist_string($infolist_nick, "name") eq $nickname))
+                        {
+                            my $prefix = weechat::infolist_string($infolist_nick, "prefix");
+                            if (($prefix ne " ") or (weechat::config_boolean( $options{"show_prefix_empty"} ) eq 1))
+                            {
+                                # with version >= 0.3.5, it is now a color name (for older versions: option name with color)
+                                if (int($weechat_version) >= 0x00030500)
+                                {
+                                    $str .= weechat::color(weechat::infolist_string($infolist_nick, "prefix_color"));
+                                }
+                                else
+                                {
+                                    $str .= weechat::color(weechat::config_color(
+                                                               weechat::config_get(
+                                                                   weechat::infolist_string($infolist_nick, "prefix_color"))));
+                                }
+                                $str .= $prefix;
+                            }
+                            last;
+                        }
+                    }
+                    weechat::infolist_free($infolist_nick);
+                }
+            }
+        }
+        if ($buffer->{"type"} eq "channel" and weechat::config_boolean( $options{"mark_inactive"} ) eq 1 and $buffer->{"nicks_count"} == 0)
+        {
+            $str .= "(";
+        }
+
+        $str .= weechat::color($color) . weechat::color(",".$bg);
+
+        my $name = weechat::buffer_get_string($buffer->{"pointer"}, "localvar_custom_name");
+        if (not defined $name or $name eq "")
+        {
+            if (weechat::config_boolean( $options{"short_names"} ) eq 1) {
+                $name = $buffer->{"short_name"};
+            } else {
+                $name = $buffer->{"name"};
+            }
+        }
+
+        if (weechat::config_integer($options{"name_size_max"}) >= 1)                # check max_size of buffer name
+        {
+            $str .= encode("UTF-8", substr(decode("UTF-8", $name), 0, weechat::config_integer($options{"name_size_max"})));
+            $str .= weechat::color(weechat::config_color( $options{"color_number_char"})).weechat::config_string($options{"name_crop_suffix"}) if (length($name) > weechat::config_integer($options{"name_size_max"}));
+            $str .= add_inactive_parentless($buffer->{"type"}, $buffer->{"nicks_count"});
+            $str .= add_hotlist_count($buffer->{"pointer"}, %hotlist);
+        }
+        else
+        {
+            $str .= $name;
+            $str .= add_inactive_parentless($buffer->{"type"}, $buffer->{"nicks_count"});
+            $str .= add_hotlist_count($buffer->{"pointer"}, %hotlist);
+        }
+
+        if ( weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") eq "server" and weechat::config_boolean($options{"show_lag"}) eq 1)
+        {
+            my $color_lag = weechat::config_color(weechat::config_get("irc.color.item_lag_finished"));
+            my $min_lag = weechat::config_integer(weechat::config_get("irc.network.lag_min_show"));
+            my $infolist_server = weechat::infolist_get("irc_server", "", $buffer->{"short_name"});
+            weechat::infolist_next($infolist_server);
+            my $lag = (weechat::infolist_integer($infolist_server, "lag"));
+            weechat::infolist_free($infolist_server);
+            if ( int($lag) > int($min_lag) )
+            {
+                $lag = $lag / 1000;
+                $str .= weechat::color("default") . " (" . weechat::color($color_lag) . $lag . weechat::color("default") . ")";
+            }
+        }
+        if (weechat::config_boolean($options{"detach_displayed_buffers"}) eq 0
+            and weechat::config_boolean($options{"detach_display_window_number"}) eq 1)
+        {
+            if ($buffer->{"window"})
+            {
+                $str .= weechat::color("default") . " (" . weechat::color(weechat::config_color( $options{"color_number"})) . $buffer->{"window"} . weechat::color("default") . ")";
+            }
+        }
+        $str .= weechat::color("default");
+
+        if ( weechat::config_string( $options{"show_suffix_bufname"} ) ne "" )
+        {
+            $str .= weechat::color( weechat::config_color( $options{"color_suffix_bufname"} ) ).
+                    weechat::config_string( $options{"show_suffix_bufname"} ).
+                    weechat::color("default");
+        }
+
+        $str .= "\n";
+        $old_number = $buffer->{"number"};
+    }
+
+    # remove spaces and/or linefeed at the end
+    $str =~ s/\s+$//;
+    chomp($str);
+    return $str;
+}
+
+sub add_inactive_parentless
+{
+my ($buf_type, $buf_nicks_count) = @_;
+my $str = "";
+    if ($buf_type eq "channel" and weechat::config_boolean( $options{"mark_inactive"} ) eq 1 and $buf_nicks_count == 0)
+    {
+        $str .= weechat::color(weechat::config_color( $options{"color_number_char"}));
+        $str .= ")";
+    }
+return $str;
+}
+
+sub add_hotlist_count
+{
+my ($bufpointer, %hotlist) = @_;
+
+return "" if ( weechat::config_boolean( $options{"hotlist_counter"} ) eq 0 or ($weechat_version < 0x00030500));   # off
+my $col_number_char = weechat::color(weechat::config_color( $options{"color_number_char"}) );
+my $str = " ".$col_number_char."(";
+
+# 0 = low level
+if (defined $hotlist{$bufpointer."_count_00"})
+{
+    my $bg = weechat::config_color( $options{"color_hotlist_low_bg"} );
+    my $color = weechat::config_color( $options{"color_hotlist_low_fg"} );
+    $str .= weechat::color($bg).
+            weechat::color($color).
+            $hotlist{$bufpointer."_count_00"} if ($hotlist{$bufpointer."_count_00"} ne "0");
+}
+
+# 1 = message
+if (defined $hotlist{$bufpointer."_count_01"})
+{
+    my $bg = weechat::config_color( $options{"color_hotlist_message_bg"} );
+    my $color = weechat::config_color( $options{"color_hotlist_message_fg"} );
+    if ($str =~ /[0-9]$/)
+    {
+        $str .= ",".
+                weechat::color($bg).
+                weechat::color($color).
+                $hotlist{$bufpointer."_count_01"} if ($hotlist{$bufpointer."_count_01"} ne "0");
+    }else
+    {
+        $str .= weechat::color($bg).
+                weechat::color($color).
+                $hotlist{$bufpointer."_count_01"} if ($hotlist{$bufpointer."_count_01"} ne "0");
+    }
+}
+# 2 = private
+if (defined $hotlist{$bufpointer."_count_02"})
+{
+    my $bg = weechat::config_color( $options{"color_hotlist_private_bg"} );
+    my $color = weechat::config_color( $options{"color_hotlist_private_fg"} );
+    if ($str =~ /[0-9]$/)
+    {
+        $str .= ",".
+                weechat::color($bg).
+                weechat::color($color).
+                $hotlist{$bufpointer."_count_02"} if ($hotlist{$bufpointer."_count_02"} ne "0");
+    }else
+    {
+        $str .= weechat::color($bg).
+                weechat::color($color).
+                $hotlist{$bufpointer."_count_02"} if ($hotlist{$bufpointer."_count_02"} ne "0");
+    }
+}
+# 3 = highlight
+if (defined $hotlist{$bufpointer."_count_03"})
+{
+    my $bg = weechat::config_color( $options{"color_hotlist_highlight_bg"} );
+    my $color = weechat::config_color( $options{"color_hotlist_highlight_fg"} );
+    if ($str =~ /[0-9]$/)
+    {
+        $str .= ",".
+                weechat::color($bg).
+                weechat::color($color).
+                $hotlist{$bufpointer."_count_03"} if ($hotlist{$bufpointer."_count_03"} ne "0");
+    }else
+    {
+        $str .= weechat::color($bg).
+                weechat::color($color).
+                $hotlist{$bufpointer."_count_03"} if ($hotlist{$bufpointer."_count_03"} ne "0");
+    }
+}
+$str .= $col_number_char. ")";
+
+$str = "" if (weechat::string_remove_color($str, "") eq " ()");         # remove color and check for buffer with no messages
+return $str;
+}
+
+sub buffers_signal_buffer
+{
+    my ($data, $signal, $signal_data) = @_;
+
+    # check for buffer_switch and set or remove detach time
+    if ($weechat_version >= 0x00030800)
+    {
+        if ($signal eq "buffer_switch")
+        {
+            my $pointer = weechat::hdata_get_list (weechat::hdata_get("buffer"), "gui_buffer_last_displayed"); # get switched buffer
+            my $current_time = time();
+            if ( weechat::buffer_get_string($pointer, "localvar_type") eq "channel")
+            {
+                $buffers_timer{$pointer} = $current_time;
+            }
+            else
+            {
+                delete $buffers_timer{$pointer};
+            }
+        }
+        if ($signal eq "buffer_opened")
+        {
+            my $current_time = time();
+            $buffers_timer{$signal_data} = $current_time;
+        }
+        if ($signal eq "buffer_closing")
+        {
+            delete $buffers_timer{$signal_data};
+        }
+    }
+    weechat::bar_item_update($SCRIPT_NAME);
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub buffers_signal_hotlist
+{
+    weechat::bar_item_update($SCRIPT_NAME);
+    return weechat::WEECHAT_RC_OK;
+}
+
+
+sub buffers_signal_config_whitelist
+{
+    @whitelist_buffers = ();
+    @whitelist_buffers = split( /,/, weechat::config_string( $options{"look_whitelist_buffers"} ) );
+    weechat::bar_item_update($SCRIPT_NAME);
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub buffers_signal_config_immune_detach_buffers
+{
+    @immune_detach_buffers = ();
+    @immune_detach_buffers = split( /,/, weechat::config_string( $options{"immune_detach_buffers"} ) );
+    weechat::bar_item_update($SCRIPT_NAME);
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub buffers_signal_config_detach_buffer_immediately
+{
+    @detach_buffer_immediately = ();
+    @detach_buffer_immediately = split( /,/, weechat::config_string( $options{"detach_buffer_immediately"} ) );
+    weechat::bar_item_update($SCRIPT_NAME);
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub buffers_signal_config
+{
+    weechat::bar_item_update($SCRIPT_NAME);
+    return weechat::WEECHAT_RC_OK;
+}
+
+# called when mouse click occured in buffers item: this callback returns buffer
+# hash according to line of item where click occured
+sub buffers_focus_buffers
+{
+    my %info = %{$_[1]};
+    my $item_line = int($info{"_bar_item_line"});
+    undef my $hash;
+    if (($info{"_bar_item_name"} eq $SCRIPT_NAME) && ($item_line >= 0) && ($item_line <= $#buffers_focus))
+    {
+        $hash = $buffers_focus[$item_line];
+    }
+    else
+    {
+        $hash = {};
+        my $hash_focus = $buffers_focus[0];
+        foreach my $key (keys %$hash_focus)
+        {
+            $hash->{$key} = "?";
+        }
+    }
+    return $hash;
+}
+
+# called when a mouse action is done on buffers item, to execute action
+# possible actions: jump to a buffer or move buffer in list (drag & drop of buffer)
+sub buffers_hsignal_mouse
+{
+    my ($data, $signal, %hash) = ($_[0], $_[1], %{$_[2]});
+    my $current_buffer = weechat::buffer_get_integer(weechat::current_buffer(), "number"); # get current buffer number
+
+    if ( $hash{"_key"} eq "button1" )
+    {
+        # left mouse button
+        if ($hash{"number"} eq $hash{"number2"})
+        {
+            if ( weechat::config_boolean($options{"jump_prev_next_visited_buffer"}) )
+            {
+                if ( $current_buffer eq $hash{"number"} )
+                {
+                    weechat::command("", "/input jump_previously_visited_buffer");
+                }
+                else
+                {
+                    weechat::command("", "/buffer ".$hash{"full_name"});
+                }
+            }
+            else
+            {
+                weechat::command("", "/buffer ".$hash{"full_name"});
+            }
+        }
+        else
+        {
+            move_buffer(%hash) if (weechat::config_boolean($options{"mouse_move_buffer"}));
+        }
+    }
+    elsif ( ($hash{"_key"} eq "button2") && (weechat::config_boolean($options{"jump_prev_next_visited_buffer"})) )
+    {
+        # right mouse button
+        if ( $current_buffer eq $hash{"number2"} )
+        {
+            weechat::command("", "/input jump_next_visited_buffer");
+        }
+    }
+    elsif ( $hash{"_key"} =~ /wheelup$/ )
+    {
+        # wheel up
+        if (weechat::config_boolean($options{"mouse_wheel"}))
+        {
+            weechat::command("", "/buffer -1");
+        }
+    }
+    elsif ( $hash{"_key"} =~ /wheeldown$/ )
+    {
+        # wheel down
+        if (weechat::config_boolean($options{"mouse_wheel"}))
+        {
+            weechat::command("", "/buffer +1");
+        }
+    }
+    else
+    {
+        my $infolist = weechat::infolist_get("hook", "", "command,menu");
+        my $has_menu_command = weechat::infolist_next($infolist);
+        weechat::infolist_free($infolist);
+
+        if ( $has_menu_command && $hash{"_key"} =~ /button2/ )
+        {
+            if ($hash{"number"} eq $hash{"number2"})
+            {
+                weechat::command($hash{"pointer"}, "/menu buffer1 $hash{short_name} $hash{number}");
+            }
+            else
+            {
+                weechat::command($hash{"pointer"}, "/menu buffer2 $hash{short_name}/$hash{short_name2} $hash{number} $hash{number2}")
+            }
+        }
+        else
+        {
+            move_buffer(%hash) if (weechat::config_boolean($options{"mouse_move_buffer"}));
+        }
+    }
+}
+
+sub move_buffer
+{
+  my %hash = @_;
+  my $number2 = $hash{"number2"};
+  if ($number2 eq "?")
+  {
+      # if number 2 is not known (end of gesture outside buffers list), then set it
+      # according to mouse gesture
+      $number2 = "1";
+      if (($hash{"_key"} =~ /gesture-right/) || ($hash{"_key"} =~ /gesture-down/))
+      {
+          $number2 = "999999";
+          if ($weechat_version >= 0x00030600)
+          {
+              my $hdata_buffer = weechat::hdata_get("buffer");
+              my $last_gui_buffer = weechat::hdata_get_list($hdata_buffer, "last_gui_buffer");
+              if ($last_gui_buffer)
+              {
+                  $number2 = weechat::hdata_integer($hdata_buffer, $last_gui_buffer, "number") + 1;
+              }
+          }
+      }
+  }
+  my $ptrbuf = weechat::current_buffer();
+  weechat::command($hash{"pointer"}, "/buffer move ".$number2);
+}
+
+sub check_immune_detached_buffers
+{
+    my ($buffername) = @_;
+    foreach ( @immune_detach_buffers ){
+        my $immune_buffer = weechat::string_mask_to_regex($_);
+        if ($buffername =~ /^$immune_buffer$/i)
+        {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+sub check_detach_buffer_immediately
+{
+    my ($buffername) = @_;
+    foreach ( @detach_buffer_immediately ){
+        my $detach_buffer = weechat::string_mask_to_regex($_);
+        if ($buffername =~ /^$detach_buffer$/i)
+        {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+sub shutdown_cb
+{
+    weechat::command("", "/bar hide " . $SCRIPT_NAME) if ( weechat::config_boolean($options{"toggle_bar"}) eq 1 );
+    return weechat::WEECHAT_RC_OK
+}
+
+sub check_bar_item
+{
+    my $item = 0;
+    my $infolist = weechat::infolist_get("bar", "", "");
+    while (weechat::infolist_next($infolist))
+    {
+        my $bar_items = weechat::infolist_string($infolist, "items");
+        if (index($bar_items, $SCRIPT_NAME) != -1)
+        {
+            my $name = weechat::infolist_string($infolist, "name");
+            if ($name ne $SCRIPT_NAME)
+            {
+                $item = 1;
+                last;
+            }
+        }
+    }
+    weechat::infolist_free($infolist);
+    return $item;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/weechat/perl/autoload/iset.pl	Wed Nov 19 19:24:17 2014 +0100
@@ -0,0 +1,1462 @@
+#
+# Copyright (C) 2008-2014 Sebastien Helleu <[email protected]>
+# Copyright (C) 2010-2014 Nils Görs <[email protected]>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Set WeeChat and plugins options interactively.
+#
+# History:
+#
+# 2014-09-30, arza <[email protected]>:
+#     version 3.6: fix current line counter when options aren't found
+# 2014-06-03, nils_2 <[email protected]>:
+#     version 3.5: add new option "use_mute"
+# 2014-01-30, stfn <[email protected]>:
+#     version 3.4: add new options "color_value_diff" and "color_value_diff_selected"
+# 2014-01-16, luz <[email protected]>:
+#     version 3.3: fix bug with column alignment in iset buffer when option
+#                  name contains unicode characters
+# 2013-08-03, Sebastien Helleu <[email protected]>:
+#     version 3.2: allow "q" as input in iset buffer to close it
+# 2013-07-14, Sebastien Helleu <[email protected]>:
+#     version 3.1: remove unneeded calls to iset_refresh() in mouse callback
+#                  (faster mouse actions when lot of options are displayed),
+#                  fix bug when clicking on a line after the last option displayed
+# 2013-04-30, arza <[email protected]>:
+#     version 3.0: simpler title, fix refresh on unset
+# 2012-12-16, nils_2 <[email protected]>:
+#     version 2.9: fix focus window with iset buffer on mouse click
+# 2012-08-25, nils_2 <[email protected]>:
+#     version 2.8: most important key and mouse bindings for iset buffer added to title-bar (idea The-Compiler)
+# 2012-07-31, nils_2 <[email protected]>:
+#     version 2.7: add combined option and value search (see /help iset)
+#                : add exact value search (see /help iset)
+#                : fix problem with metacharacter in value search
+#                : fix use of uninitialized value for unset option and reset value of option
+# 2012-07-25, nils_2 <[email protected]>:
+#     version 2.6: switch to iset buffer (if existing) when command /iset is called with arguments
+# 2012-03-17, Sebastien Helleu <[email protected]>:
+#     version 2.5: fix check of sections when creating config file
+# 2012-03-09, Sebastien Helleu <[email protected]>:
+#     version 2.4: fix reload of config file
+# 2012-02-02, nils_2 <[email protected]>:
+#     version 2.3: fixed: refresh problem with new search results and cursor was outside window.
+#                : add: new option "current_line" in title bar
+#     version 2.2: fixed: refresh error when toggling plugins description
+# 2011-11-05, nils_2 <[email protected]>:
+#     version 2.1: use own config file (iset.conf), fix own help color (used immediately)
+# 2011-10-16, nils_2 <[email protected]>:
+#     version 2.0: add support for left-mouse-button and more sensitive mouse gesture (for integer/color options)
+#                  add help text for mouse support
+# 2011-09-20, Sebastien Helleu <[email protected]>:
+#     version 1.9: add mouse support, fix iset buffer, fix errors on first load under FreeBSD
+# 2011-07-21, nils_2 <[email protected]>:
+#     version 1.8: added: option "show_plugin_description" (alt+p)
+#                  fixed: typos in /help iset (lower case for alt+'x' keys)
+# 2011-05-29, nils_2 <[email protected]>:
+#     version 1.7: added: version check for future needs
+#                  added: new option (scroll_horiz) and usage of scroll_horiz function (weechat >= 0.3.6 required)
+#                  fixed: help_bar did not pop up immediately using key-shortcut
+# 2011-02-19, nils_2 <[email protected]>:
+#     version 1.6: added: display of all possible values in help bar (show_help_extra_info)
+#                  fixed: external user options never loaded when starting iset first time
+# 2011-02-13, Sebastien Helleu <[email protected]>:
+#     version 1.5: use new help format for command arguments
+# 2011-02-03, nils_2 <[email protected]>:
+#     version 1.4: fixed: restore value filter after /upgrade using buffer local variable.
+# 2011-01-14, nils_2 <[email protected]>:
+#     version 1.3: added function to search for values (option value_search_char).
+#                  code optimization.
+# 2010-12-26, Sebastien Helleu <[email protected]>:
+#     version 1.2: improve speed of /upgrade when iset buffer is open,
+#                  restore filter used after /upgrade using buffer local variable,
+#                  use /iset filter argument if buffer is open.
+# 2010-11-21, drubin <[email protected]>:
+#     version 1.1.1: fix bugs with cursor position
+# 2010-11-20, nils_2 <[email protected]>:
+#     version 1.1: cursor position set to value
+# 2010-08-03, Sebastien Helleu <[email protected]>:
+#     version 1.0: move misplaced call to infolist_free()
+# 2010-02-02, rettub <[email protected]>:
+#     version 0.9: turn all the help stuff off if option 'show_help_bar' is 'off',
+#                  new key binding <alt>-<v> to toggle help_bar and help stuff on/off
+# 2010-01-30, nils_2 <[email protected]>:
+#     version 0.8: fix error when option does not exist
+# 2010-01-24, Sebastien Helleu <[email protected]>:
+#     version 0.7: display iset bar only on iset buffer
+# 2010-01-22, nils_2 <[email protected]> and drubin:
+#     version 0.6: add description in a bar, fix singular/plural bug in title bar,
+#                  fix selected line when switching buffer
+# 2009-06-21, Sebastien Helleu <[email protected]>:
+#     version 0.5: fix bug with iset buffer after /upgrade
+# 2009-05-02, Sebastien Helleu <[email protected]>:
+#     version 0.4: sync with last API changes
+# 2009-01-04, Sebastien Helleu <[email protected]>:
+#     version 0.3: open iset buffer when /iset command is executed
+# 2009-01-04, Sebastien Helleu <[email protected]>:
+#     version 0.2: use null values for options, add colors, fix refresh bugs,
+#                  use new keys to reset/unset options, sort options by name,
+#                  display number of options in buffer's title
+# 2008-11-05, Sebastien Helleu <[email protected]>:
+#     version 0.1: first official version
+# 2008-04-19, Sebastien Helleu <[email protected]>:
+#     script creation
+
+use strict;
+
+my $PRGNAME = "iset";
+my $VERSION = "3.6";
+my $DESCR   = "Interactive Set for configuration options";
+my $AUTHOR  = "Sebastien Helleu <flashcode\@flashtux.org>";
+my $LICENSE = "GPL3";
+my $LANG    = "perl";
+my $ISET_CONFIG_FILE_NAME = "iset";
+
+my $iset_config_file;
+my $iset_buffer = "";
+my $wee_version_number = 0;
+my @iset_focus = ();
+my @options_names = ();
+my @options_types = ();
+my @options_values = ();
+my @options_default_values = ();
+my @options_is_null = ();
+my $option_max_length = 0;
+my $current_line = 0;
+my $filter = "*";
+my $description = "";
+my $options_name_copy = "";
+my $iset_filter_title = "";
+# search modes: 0 = index() on value, 1 = grep() on value, 2 = grep() on option, 3 = grep on option & value
+my $search_mode = 2;
+my $search_value = "";
+my $help_text_keys = "alt + space: toggle, +/-: increase/decrease, enter: change, ir: reset, iu: unset, v: toggle help bar";
+my $help_text_mouse = "Mouse: left: select, right: toggle/set, right + drag left/right: increase/decrease";
+my %options_iset;
+
+my %mouse_keys = ("\@chat(perl.$PRGNAME):button1" => "hsignal:iset_mouse",
+                  "\@chat(perl.$PRGNAME):button2*" => "hsignal:iset_mouse",
+                  "\@chat(perl.$PRGNAME):wheelup" => "/repeat 5 /iset **up",
+                  "\@chat(perl.$PRGNAME):wheeldown" => "/repeat 5 /iset **down");
+
+
+sub iset_title
+{
+    if ($iset_buffer ne "")
+    {
+        my $current_line_counter = "";
+        if (weechat::config_boolean($options_iset{"show_current_line"}) == 1)
+        {
+            if (@options_names eq 0)
+            {
+                $current_line_counter = "0/";
+            }
+            else
+            {
+                $current_line_counter = ($current_line + 1) . "/";
+            }
+        }
+        my $show_filter = "";
+        if ($search_mode eq 0)
+        {
+            $iset_filter_title = "(value) ";
+            $show_filter = $search_value;
+            if ( substr($show_filter,0,1) eq weechat::config_string($options_iset{"value_search_char"}) )
+            {
+                $show_filter = substr($show_filter,1,length($show_filter));
+            }
+        }
+        elsif ($search_mode eq 1)
+        {
+            $iset_filter_title = "(value) ";
+            $show_filter = "*".$search_value."*";
+        }
+        elsif ($search_mode eq 2)
+        {
+            $iset_filter_title = "";
+            $filter = "*" if ($filter eq "");
+            $show_filter = $filter;
+        }
+        elsif ($search_mode eq 3)
+        {
+            $iset_filter_title = "(option) ";
+            $show_filter = $filter
+                            .weechat::color("default")
+                            ." / (value) "
+                            .weechat::color("yellow")
+                            ."*".$search_value."*";
+        }
+        weechat::buffer_set($iset_buffer, "title",
+                             $iset_filter_title
+                            .weechat::color("yellow")
+                            .$show_filter
+                            .weechat::color("default")." | "
+                            .$current_line_counter
+                            .@options_names
+                            ." | "
+                            .$help_text_keys
+                            ." | "
+                            .$help_text_mouse);
+    }
+}
+
+sub iset_create_filter
+{
+    $filter = $_[0];
+    if ( $search_mode == 3 )
+    {
+        my @cmd_array = split(/ /,$filter);
+        my $array_count = @cmd_array;
+        $filter = $cmd_array[0];
+        $filter = $cmd_array[0] . " " . $cmd_array[1] if ( $array_count >2 );
+    }
+    $filter = "$1.*" if ($filter =~ /f (.*)/); # search file
+    $filter = "*.$1.*" if ($filter =~ /s (.*)/); # search section
+    if ((substr($filter, 0, 1) ne "*") && (substr($filter, -1, 1) ne "*"))
+    {
+        $filter = "*".$filter."*";
+    }
+    if ($iset_buffer ne "")
+    {
+        weechat::buffer_set($iset_buffer, "localvar_set_iset_filter", $filter);
+    }
+}
+
+sub iset_buffer_input
+{
+    my ($data, $buffer, $string) = ($_[0], $_[1], $_[2]);
+    if ($string eq "q")
+    {
+        weechat::buffer_close($buffer);
+        return weechat::WEECHAT_RC_OK;
+    }
+    $search_value = "";
+    my @cmd_array = split(/ /,$string);
+    my $array_count = @cmd_array;
+    my $string2 = substr($string, 0, 1);
+    if ($string2 eq weechat::config_string($options_iset{"value_search_char"})
+    or (defined $cmd_array[0] and $cmd_array[0] eq weechat::config_string($options_iset{"value_search_char"}).weechat::config_string($options_iset{"value_search_char"})) )
+    {
+        $search_mode = 1;
+        $search_value = substr($string, 1);
+        iset_get_values($search_value);
+        if ($iset_buffer ne "")
+        {
+            weechat::buffer_set($iset_buffer, "localvar_set_iset_search_value", $search_value);
+        }
+    }
+    else
+    {
+        $search_mode = 2;
+        if ( $array_count >= 2 and $cmd_array[0] ne "f" or $cmd_array[0] ne "s")
+        {
+            if ( defined $cmd_array[1] and substr($cmd_array[1], 0, 1) eq weechat::config_string($options_iset{"value_search_char"})
+            or defined $cmd_array[2] and substr($cmd_array[2], 0, 1) eq weechat::config_string($options_iset{"value_search_char"}) )
+            {
+                $search_mode = 3;
+                $search_value = substr($cmd_array[1], 1);  # cut value_search_char
+                $search_value = substr($cmd_array[2], 1) if ( $array_count > 2);  # cut value_search_char
+            }
+        }
+        if ( $search_mode == 3)
+        {
+            iset_create_filter($string);
+            iset_get_options($search_value);
+        }else
+        {
+            iset_create_filter($string);
+            iset_get_options("");
+        }
+    }
+    weechat::buffer_set($iset_buffer, "localvar_set_iset_search_mode", $search_mode);
+    weechat::buffer_clear($buffer);
+    $current_line = 0;
+    iset_refresh();
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub iset_buffer_close
+{
+    $iset_buffer = "";
+
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub iset_init
+{
+    $current_line = 0;
+    $iset_buffer = weechat::buffer_search($LANG, $PRGNAME);
+    if ($iset_buffer eq "")
+    {
+        $iset_buffer = weechat::buffer_new($PRGNAME, "iset_buffer_input", "", "iset_buffer_close", "");
+    }
+    else
+    {
+        my $new_filter = weechat::buffer_get_string($iset_buffer, "localvar_iset_filter");
+        $search_mode = weechat::buffer_get_string($iset_buffer, "localvar_iset_search_mode");
+        $search_value = weechat::buffer_get_string($iset_buffer, "localvar_iset_search_value");
+        $filter = $new_filter if ($new_filter ne "");
+    }
+    if ($iset_buffer ne "")
+    {
+        weechat::buffer_set($iset_buffer, "type", "free");
+        iset_title();
+        weechat::buffer_set($iset_buffer, "key_bind_ctrl-L",        "/iset **refresh");
+        weechat::buffer_set($iset_buffer, "key_bind_meta2-A",       "/iset **up");
+        weechat::buffer_set($iset_buffer, "key_bind_meta2-B",       "/iset **down");
+        weechat::buffer_set($iset_buffer, "key_bind_meta2-23~",     "/iset **left");
+        weechat::buffer_set($iset_buffer, "key_bind_meta2-24~" ,    "/iset **right");
+        weechat::buffer_set($iset_buffer, "key_bind_meta- ",        "/iset **toggle");
+        weechat::buffer_set($iset_buffer, "key_bind_meta-+",        "/iset **incr");
+        weechat::buffer_set($iset_buffer, "key_bind_meta--",        "/iset **decr");
+        weechat::buffer_set($iset_buffer, "key_bind_meta-imeta-r",  "/iset **reset");
+        weechat::buffer_set($iset_buffer, "key_bind_meta-imeta-u",  "/iset **unset");
+        weechat::buffer_set($iset_buffer, "key_bind_meta-ctrl-J",   "/iset **set");
+        weechat::buffer_set($iset_buffer, "key_bind_meta-ctrl-M",   "/iset **set");
+        weechat::buffer_set($iset_buffer, "key_bind_meta-meta2-1~", "/iset **scroll_top");
+        weechat::buffer_set($iset_buffer, "key_bind_meta-meta2-4~", "/iset **scroll_bottom");
+        weechat::buffer_set($iset_buffer, "key_bind_meta-v",        "/iset **toggle_help");
+        weechat::buffer_set($iset_buffer, "key_bind_meta-p",        "/iset **toggle_show_plugin_desc");
+        weechat::buffer_set($iset_buffer, "localvar_set_iset_filter", $filter);
+        weechat::buffer_set($iset_buffer, "localvar_set_iset_search_mode", $search_mode);
+        weechat::buffer_set($iset_buffer, "localvar_set_iset_search_value", $search_value);
+    }
+}
+
+sub iset_get_options
+{
+    my $var_value = $_[0];
+    $var_value = "" if (not defined $var_value);
+    $var_value = lc($var_value);
+    $search_value = $var_value;
+    @iset_focus = ();
+    @options_names = ();
+    @options_types = ();
+    @options_values = ();
+    @options_default_values = ();
+    @options_is_null = ();
+    $option_max_length = 0;
+    my %options_internal = ();
+    my $i = 0;
+    my $key;
+    my $iset_struct;
+    my %iset_struct;
+
+    weechat::buffer_set($iset_buffer, "localvar_set_iset_search_value", $var_value) if ($search_mode == 3);
+
+    my $infolist = weechat::infolist_get("option", "", $filter);
+    while (weechat::infolist_next($infolist))
+    {
+        $key = sprintf("%08d", $i);
+        my $name = weechat::infolist_string($infolist, "full_name");
+        next if (weechat::config_boolean($options_iset{"show_plugin_description"}) == 0 and index ($name, "plugins.desc.") != -1);
+        my $type = weechat::infolist_string($infolist, "type");
+        my $value = weechat::infolist_string($infolist, "value");
+        my $default_value = weechat::infolist_string($infolist, "default_value");
+        my $is_null = weechat::infolist_integer($infolist, "value_is_null");
+        if ($search_mode == 3)
+        {
+            my $value = weechat::infolist_string($infolist, "value");
+            if ( grep /\Q$var_value/,lc($value) )
+            {
+                $options_internal{$name}{"type"} = $type;
+                $options_internal{$name}{"value"} = $value;
+                $options_internal{$name}{"default_value"} = $default_value;
+                $options_internal{$name}{"is_null"} = $is_null;
+                $option_max_length = length($name) if (length($name) > $option_max_length);
+        $iset_struct{$key} = $options_internal{$name};
+        push(@iset_focus, $iset_struct{$key});
+            }
+        }
+        else
+        {
+            $options_internal{$name}{"type"} = $type;
+            $options_internal{$name}{"value"} = $value;
+            $options_internal{$name}{"default_value"} = $default_value;
+            $options_internal{$name}{"is_null"} = $is_null;
+            $option_max_length = length($name) if (length($name) > $option_max_length);
+        $iset_struct{$key} = $options_internal{$name};
+        push(@iset_focus, $iset_struct{$key});
+        }
+        $i++;
+    }
+    weechat::infolist_free($infolist);
+
+    foreach my $name (sort keys %options_internal)
+    {
+        push(@options_names, $name);
+        push(@options_types, $options_internal{$name}{"type"});
+        push(@options_values, $options_internal{$name}{"value"});
+        push(@options_default_values, $options_internal{$name}{"default_value"});
+        push(@options_is_null, $options_internal{$name}{"is_null"});
+    }
+}
+
+sub iset_get_values
+{
+    my $var_value = $_[0];
+    $var_value = lc($var_value);
+    if (substr($var_value,0,1) eq weechat::config_string($options_iset{"value_search_char"}) and $var_value ne weechat::config_string($options_iset{"value_search_char"}))
+    {
+        $var_value = substr($var_value,1,length($var_value));
+        $search_mode = 0;
+    }
+    iset_search_values($var_value,$search_mode);
+    weechat::buffer_set($iset_buffer, "localvar_set_iset_search_mode", $search_mode);
+    weechat::buffer_set($iset_buffer, "localvar_set_iset_search_value", $var_value);
+    $search_value = $var_value;
+}
+sub iset_search_values
+{
+    my ($var_value,$search_mode) = ($_[0],$_[1]);
+    @options_names = ();
+    @options_types = ();
+    @options_values = ();
+    @options_default_values = ();
+    @options_is_null = ();
+    $option_max_length = 0;
+    my %options_internal = ();
+    my $i = 0;
+    my $infolist = weechat::infolist_get("option", "", "*");
+    while (weechat::infolist_next($infolist))
+    {
+        my $name = weechat::infolist_string($infolist, "full_name");
+        next if (weechat::config_boolean($options_iset{"show_plugin_description"}) == 0 and index ($name, "plugins.desc.") != -1);
+        my $type = weechat::infolist_string($infolist, "type");
+        my $is_null = weechat::infolist_integer($infolist, "value_is_null");
+        my $value = weechat::infolist_string($infolist, "value");
+        my $default_value = weechat::infolist_string($infolist, "default_value");
+        if ($search_mode)
+        {
+            if ( grep /\Q$var_value/,lc($value) )
+            {
+                $options_internal{$name}{"type"} = $type;
+                $options_internal{$name}{"value"} = $value;
+                $options_internal{$name}{"default_value"} = $default_value;
+                $options_internal{$name}{"is_null"} = $is_null;
+                $option_max_length = length($name) if (length($name) > $option_max_length);
+            }
+        }
+        else
+        {
+#            if ($value =~ /\Q$var_value/si)
+            if (lc($value) eq $var_value)
+            {
+                $options_internal{$name}{"type"} = $type;
+                $options_internal{$name}{"value"} = $value;
+                $options_internal{$name}{"default_value"} = $default_value;
+                $options_internal{$name}{"is_null"} = $is_null;
+                $option_max_length = length($name) if (length($name) > $option_max_length);
+            }
+        }
+        $i++;
+    }
+    weechat::infolist_free($infolist);
+    foreach my $name (sort keys %options_internal)
+    {
+        push(@options_names, $name);
+        push(@options_types, $options_internal{$name}{"type"});
+        push(@options_values, $options_internal{$name}{"value"});
+        push(@options_default_values, $options_internal{$name}{"default_value"});
+        push(@options_is_null, $options_internal{$name}{"is_null"});
+    }
+}
+
+sub iset_refresh_line
+{
+    if ($iset_buffer ne "")
+    {
+        my $y = $_[0];
+        if ($y <= $#options_names)
+        {
+            return if (! defined($options_types[$y]));
+            my $format = sprintf("%%s%%s%%s %%s %%-7s %%s %%s%%s%%s");
+            my $padding;
+            if ($wee_version_number >= 0x00040200)
+            {
+                $padding = " " x ($option_max_length - weechat::strlen_screen($options_names[$y]));
+            }
+            else
+            {
+                $padding = " " x ($option_max_length - length($options_names[$y]));
+            }
+            my $around = "";
+            $around = "\"" if ((!$options_is_null[$y]) && ($options_types[$y] eq "string"));
+
+            my $color1 = weechat::color(weechat::config_color($options_iset{"color_option"}));
+            my $color2 = weechat::color(weechat::config_color($options_iset{"color_type"}));
+            my $color3 = "";
+            if ($options_is_null[$y])
+            {
+                $color3 = weechat::color(weechat::config_color($options_iset{"color_value_undef"}));
+            }
+            elsif ($options_values[$y] ne $options_default_values[$y])
+            {
+                $color3 = weechat::color(weechat::config_color($options_iset{"color_value_diff"}));
+            }
+            else
+            {
+                $color3 = weechat::color(weechat::config_color($options_iset{"color_value"}));
+            }
+            if ($y == $current_line)
+            {
+                $color1 = weechat::color(weechat::config_color($options_iset{"color_option_selected"}).",".weechat::config_color($options_iset{"color_bg_selected"}));
+                $color2 = weechat::color(weechat::config_color($options_iset{"color_type_selected"}).",".weechat::config_color($options_iset{"color_bg_selected"}));
+                if ($options_is_null[$y])
+                {
+                    $color3 = weechat::color(weechat::config_color($options_iset{"color_value_undef_selected"}).",".weechat::config_color($options_iset{"color_bg_selected"}));
+                }
+                elsif ($options_values[$y] ne $options_default_values[$y])
+                {
+                    $color3 = weechat::color(weechat::config_color($options_iset{"color_value_diff_selected"}).",".weechat::config_color($options_iset{"color_bg_selected"}));
+                }
+                else
+                {
+                    $color3 = weechat::color(weechat::config_color($options_iset{"color_value_selected"}).",".weechat::config_color($options_iset{"color_bg_selected"}));
+                }
+            }
+            my $value = $options_values[$y];
+            $value = "(undef)" if ($options_is_null[$y]);
+            my $strline = sprintf($format,
+                                  $color1, $options_names[$y], $padding,
+                                  $color2, $options_types[$y],
+                                  $color3, $around, $value, $around);
+            weechat::print_y($iset_buffer, $y, $strline);
+        }
+    }
+}
+
+sub iset_refresh
+{
+    iset_title();
+    if (($iset_buffer ne "") && ($#options_names >= 0))
+    {
+        foreach my $y (0 .. $#options_names)
+        {
+            iset_refresh_line($y);
+        }
+    }
+
+    weechat::bar_item_update("isetbar_help") if (weechat::config_boolean($options_iset{"show_help_bar"}) == 1);
+}
+
+sub iset_full_refresh
+{
+    $iset_buffer = weechat::buffer_search($LANG, $PRGNAME);
+    if ($iset_buffer ne "")
+    {
+        weechat::buffer_clear($iset_buffer) unless defined $_[0]; # iset_full_refresh(1) does a full refresh without clearing buffer
+        # search for "*" in $filter.
+        if ($filter =~ m/\*/ and $search_mode == 2)
+        {
+            iset_get_options("");
+        }
+        else
+        {
+            if ($search_mode == 0)
+            {
+                $search_value = "=" . $search_value;
+                iset_get_values($search_value);
+            }
+            elsif ($search_mode == 1)
+            {
+                iset_get_values($search_value);
+            }
+            elsif ($search_mode == 3)
+            {
+                iset_create_filter($filter);
+                iset_get_options($search_value);
+            }
+        }
+        if (weechat::config_boolean($options_iset{"show_plugin_description"}) == 1)
+        {
+            iset_set_current_line($current_line);
+        }else
+        {
+            $current_line = $#options_names if ($current_line > $#options_names);
+        }
+        iset_refresh();
+        weechat::command($iset_buffer, "/window refresh");
+    }
+}
+
+sub iset_set_current_line
+{
+    my $new_current_line = $_[0];
+    if ($new_current_line >= 0)
+    {
+        my $old_current_line = $current_line;
+        $current_line = $new_current_line;
+        $current_line = $#options_names if ($current_line > $#options_names);
+        if ($old_current_line != $current_line)
+        {
+            iset_refresh_line($old_current_line);
+            iset_refresh_line($current_line);
+            weechat::bar_item_update("isetbar_help") if (weechat::config_boolean($options_iset{"show_help_bar"}) == 1);
+        }
+    }
+}
+
+sub iset_signal_window_scrolled_cb
+{
+    my ($data, $signal, $signal_data) = ($_[0], $_[1], $_[2]);
+    if ($iset_buffer ne "")
+    {
+        my $infolist = weechat::infolist_get("window", $signal_data, "");
+        if (weechat::infolist_next($infolist))
+        {
+            if (weechat::infolist_pointer($infolist, "buffer") eq $iset_buffer)
+            {
+                my $old_current_line = $current_line;
+                my $new_current_line = $current_line;
+                my $start_line_y = weechat::infolist_integer($infolist, "start_line_y");
+                my $chat_height = weechat::infolist_integer($infolist, "chat_height");
+                $new_current_line += $chat_height if ($new_current_line < $start_line_y);
+                $new_current_line -= $chat_height if ($new_current_line >= $start_line_y + $chat_height);
+                $new_current_line = $start_line_y if ($new_current_line < $start_line_y);
+                $new_current_line = $start_line_y + $chat_height - 1 if ($new_current_line >= $start_line_y + $chat_height);
+                iset_set_current_line($new_current_line);
+            }
+        }
+        weechat::infolist_free($infolist);
+    }
+
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub iset_get_window_number
+{
+    if ($iset_buffer ne "")
+    {
+        my $window = weechat::window_search_with_buffer($iset_buffer);
+        return "-window ".weechat::window_get_integer ($window, "number")." " if ($window ne "");
+    }
+    return "";
+}
+
+sub iset_check_line_outside_window
+{
+    if ($iset_buffer ne "")
+    {
+        undef my $infolist;
+        if ($wee_version_number >= 0x00030500)
+        {
+            my $window = weechat::window_search_with_buffer($iset_buffer);
+            $infolist = weechat::infolist_get("window", $window, "") if $window;
+        }
+        else
+        {
+            $infolist = weechat::infolist_get("window", "", "current");
+        }
+        if ($infolist)
+        {
+            if (weechat::infolist_next($infolist))
+            {
+                my $start_line_y = weechat::infolist_integer($infolist, "start_line_y");
+                my $chat_height = weechat::infolist_integer($infolist, "chat_height");
+                my $window_number = "";
+                if ($wee_version_number >= 0x00030500)
+                {
+                    $window_number = "-window ".weechat::infolist_integer($infolist, "number")." ";
+                }
+                if ($start_line_y > $current_line)
+                {
+                    weechat::command($iset_buffer, "/window scroll ".$window_number."-".($start_line_y - $current_line));
+                }
+                else
+                {
+                    if ($start_line_y <= $current_line - $chat_height)
+                    {
+                        weechat::command($iset_buffer, "/window scroll ".$window_number."+".($current_line - $start_line_y - $chat_height + 1));
+
+                    }
+                }
+            }
+            weechat::infolist_free($infolist);
+        }
+    }
+}
+
+sub iset_get_option_name_index
+{
+    my $option_name = $_[0];
+    my $index = 0;
+    while ($index <= $#options_names)
+    {
+        return -1 if ($options_names[$index] gt $option_name);
+        return $index if ($options_names[$index] eq $option_name);
+        $index++;
+    }
+    return -1;
+}
+
+sub iset_config_cb
+{
+    my ($data, $option_name, $value) = ($_[0], $_[1], $_[2]);
+
+    if ($iset_buffer ne "")
+    {
+        return weechat::WEECHAT_RC_OK if (weechat::info_get("weechat_upgrading", "") eq "1");
+
+        my $index = iset_get_option_name_index($option_name);
+        if ($index >= 0)
+        {
+            # refresh info about changed option
+            my $infolist = weechat::infolist_get("option", "", $option_name);
+            if ($infolist)
+            {
+                weechat::infolist_next($infolist);
+                if (weechat::infolist_fields($infolist))
+                {
+                    $options_types[$index] = weechat::infolist_string($infolist, "type");
+                    $options_values[$index] = weechat::infolist_string($infolist, "value");
+                    $options_default_values[$index] = weechat::infolist_string($infolist, "default_value");
+                    $options_is_null[$index] = weechat::infolist_integer($infolist, "value_is_null");
+                    iset_refresh_line($index);
+                    iset_title() if ($option_name eq "iset.look.show_current_line");
+                }
+                else
+                {
+                    iset_full_refresh(1); # if not found, refresh fully without clearing buffer
+                    weechat::print_y($iset_buffer, $#options_names + 1, "");
+                }
+                weechat::infolist_free($infolist);
+            }
+        }
+        else
+        {
+            iset_full_refresh() if ($option_name ne "weechat.bar.isetbar.hidden");
+        }
+    }
+
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub iset_set_option
+{
+    my ($option, $value) = ($_[0],$_[1]);
+    if (defined $option and defined $value)
+    {
+        $option = weechat::config_get($option);
+        weechat::config_option_set($option, $value, 1) if ($option ne "");
+    }
+}
+
+sub iset_reset_option
+{
+    my $option = $_[0];
+    if (defined $option)
+    {
+        $option = weechat::config_get($option);
+        weechat::config_option_reset($option, 1) if ($option ne "");
+    }
+}
+
+sub iset_unset_option
+{
+    my $option = $_[0];
+    if (defined $option)
+    {
+        $option = weechat::config_get($option);
+        weechat::config_option_unset($option) if ($option ne "");
+    }
+}
+
+
+sub iset_cmd_cb
+{
+    my ($data, $buffer, $args) = ($_[0], $_[1], $_[2]);
+    my $filter_set = 0;
+#    $search_value = "";
+    if (($args ne "") && (substr($args, 0, 2) ne "**"))
+    {
+        my @cmd_array = split(/ /,$args);
+        my $array_count = @cmd_array;
+        if (substr($args, 0, 1) eq weechat::config_string($options_iset{"value_search_char"})
+        or (defined $cmd_array[0] and $cmd_array[0] eq weechat::config_string($options_iset{"value_search_char"}).weechat::config_string($options_iset{"value_search_char"})) )
+        {
+            $search_mode = 1;
+            my $search_value = substr($args, 1);  # cut value_search_char
+            if ($iset_buffer ne "")
+            {
+                weechat::buffer_clear($iset_buffer);
+                weechat::command($iset_buffer, "/window refresh");
+            }
+            weechat::buffer_set($iset_buffer, "localvar_set_iset_search_mode", $search_mode);
+            weechat::buffer_set($iset_buffer, "localvar_set_iset_search_value", $search_value);
+            iset_init();
+            iset_get_values($search_value);
+            iset_refresh();
+            weechat::buffer_set($iset_buffer, "display", "1");
+#            $filter = $var_value;
+            return weechat::WEECHAT_RC_OK;
+        }
+        else
+        {
+            # f/s option =value
+            # option =value
+            $search_mode = 2;
+            if ( $array_count >= 2 and $cmd_array[0] ne "f" or $cmd_array[0] ne "s")
+            {
+                if ( defined $cmd_array[1] and substr($cmd_array[1], 0, 1) eq weechat::config_string($options_iset{"value_search_char"})
+                or defined $cmd_array[2] and substr($cmd_array[2], 0, 1) eq weechat::config_string($options_iset{"value_search_char"}) )
+                {
+                    $search_mode = 3;
+                    $search_value = substr($cmd_array[1], 1);  # cut value_search_char
+                    $search_value = substr($cmd_array[2], 1) if ( $array_count > 2);  # cut value_search_char
+                }
+            }
+            iset_create_filter($args);
+            $filter_set = 1;
+            my $ptrbuf = weechat::buffer_search($LANG, $PRGNAME);
+            if ($ptrbuf eq "")
+            {
+                iset_init();
+                iset_get_options($search_value);
+                iset_full_refresh();
+                weechat::buffer_set(weechat::buffer_search($LANG, $PRGNAME), "display", "1");
+                weechat::buffer_set($iset_buffer, "localvar_set_iset_search_value", $search_value);
+                weechat::buffer_set($iset_buffer, "localvar_set_iset_search_mode", $search_mode);
+                return weechat::WEECHAT_RC_OK;
+            }
+            else
+            {
+                iset_get_options($search_value);
+                iset_full_refresh();
+                weechat::buffer_set($ptrbuf, "display", "1");
+            }
+        }
+    weechat::buffer_set($iset_buffer, "localvar_set_iset_search_mode", $search_mode);
+    weechat::buffer_set($iset_buffer, "localvar_set_iset_search_value", $search_value);
+    }
+    if ($iset_buffer eq "")
+    {
+        iset_init();
+        iset_get_options("");
+        iset_refresh();
+    }
+    else
+    {
+#        iset_get_options($search_value);
+        iset_full_refresh() if ($filter_set);
+    }
+
+    if ($args eq "")
+    {
+        weechat::buffer_set($iset_buffer, "display", "1");
+    }
+    else
+    {
+        if ($args eq "**refresh")
+        {
+            iset_full_refresh();
+        }
+        if ($args eq "**up")
+        {
+            if ($current_line > 0)
+            {
+                $current_line--;
+                iset_refresh_line($current_line + 1);
+                iset_refresh_line($current_line);
+                iset_check_line_outside_window();
+            }
+        }
+        if ($args eq "**down")
+        {
+            if ($current_line < $#options_names)
+            {
+                $current_line++;
+                iset_refresh_line($current_line - 1);
+                iset_refresh_line($current_line);
+                iset_check_line_outside_window();
+            }
+        }
+        if ($args eq "**left" && $wee_version_number >= 0x00030600)
+        {
+            weechat::command($iset_buffer, "/window scroll_horiz ".iset_get_window_number()."-".weechat::config_integer($options_iset{"scroll_horiz"})."%");
+        }
+        if ($args eq "**right" && $wee_version_number >= 0x00030600)
+        {
+            weechat::command($iset_buffer, "/window scroll_horiz ".iset_get_window_number().weechat::config_integer($options_iset{"scroll_horiz"})."%");
+        }
+        if ($args eq "**scroll_top")
+        {
+            my $old_current_line = $current_line;
+            $current_line = 0;
+            iset_refresh_line ($old_current_line);
+            iset_refresh_line ($current_line);
+            iset_title();
+            weechat::command($iset_buffer, "/window scroll_top ".iset_get_window_number());
+        }
+        if ($args eq "**scroll_bottom")
+        {
+            my $old_current_line = $current_line;
+            $current_line = $#options_names;
+            iset_refresh_line ($old_current_line);
+            iset_refresh_line ($current_line);
+            iset_title();
+            weechat::command($iset_buffer, "/window scroll_bottom ".iset_get_window_number());
+        }
+        if ($args eq "**toggle")
+        {
+            if ($options_types[$current_line] eq "boolean")
+            {
+                iset_set_option($options_names[$current_line], "toggle");
+            }
+        }
+        if ($args eq "**incr")
+        {
+            if (($options_types[$current_line] eq "integer")
+                || ($options_types[$current_line] eq "color"))
+            {
+                iset_set_option($options_names[$current_line], "++1");
+            }
+        }
+        if ($args eq "**decr")
+        {
+            if (($options_types[$current_line] eq "integer")
+                || ($options_types[$current_line] eq "color"))
+            {
+                iset_set_option($options_names[$current_line], "--1");
+            }
+        }
+        if ($args eq "**reset")
+        {
+            iset_reset_option($options_names[$current_line]);
+        }
+        if ($args eq "**unset")
+        {
+            iset_unset_option($options_names[$current_line]);
+        }
+        if ($args eq "**toggle_help")
+        {
+            if (weechat::config_boolean($options_iset{"show_help_bar"})  == 1)
+            {
+                weechat::config_option_set($options_iset{"show_help_bar"},0,1);
+                iset_show_bar(0);
+            }
+            else
+            {
+                weechat::config_option_set($options_iset{"show_help_bar"},1,1);
+                iset_show_bar(1);
+            }
+        }
+        if ($args eq "**toggle_show_plugin_desc")
+        {
+            if (weechat::config_boolean($options_iset{"show_plugin_description"}) == 1)
+            {
+                weechat::config_option_set($options_iset{"show_plugin_description"},0,1);
+                iset_full_refresh();
+                iset_check_line_outside_window();
+                iset_title();
+            }
+            else
+            {
+                weechat::config_option_set($options_iset{"show_plugin_description"},1,1);
+                iset_full_refresh();
+                iset_check_line_outside_window();
+                iset_title();
+            }
+        }
+        if ($args eq "**set")
+        {
+            my $quote = "";
+            my $value = $options_values[$current_line];
+            if ($options_is_null[$current_line])
+            {
+                $value = "null";
+            }
+            else
+            {
+                $quote = "\"" if ($options_types[$current_line] eq "string");
+            }
+            my $set_command = "/set";
+            $set_command = "/mute " . $set_command if (weechat::config_boolean($options_iset{"use_mute"}) == 1);
+
+            weechat::buffer_set($iset_buffer, "input", $set_command." ".$options_names[$current_line]." ".$quote.$value.$quote);
+            weechat::command($iset_buffer, "/input move_beginning_of_line");
+            weechat::command($iset_buffer, "/input move_next_word");
+            weechat::command($iset_buffer, "/input move_next_word");
+            weechat::command($iset_buffer, "/input move_next_word") if (weechat::config_boolean($options_iset{"use_mute"}) == 1);
+            weechat::command($iset_buffer, "/input move_next_char");
+            weechat::command($iset_buffer, "/input move_next_char") if ($quote ne "");
+        }
+    }
+    weechat::bar_item_update("isetbar_help") if (weechat::config_boolean($options_iset{"show_help_bar"}) == 1);
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub iset_get_help
+{
+    my ($redraw) = ($_[0]);
+
+    return '' if (weechat::config_boolean($options_iset{"show_help_bar"}) == 0);
+
+    if (not defined $options_names[$current_line])
+    {
+        return "No option selected. Set a new filter using command line (use '*' to see all options)";
+    }
+    if ($options_name_copy eq $options_names[$current_line] and not defined $redraw)
+    {
+        return $description;
+    }
+    $options_name_copy = $options_names[$current_line];
+    my $optionlist ="";
+    $optionlist = weechat::infolist_get("option", "", $options_names[$current_line]);
+    weechat::infolist_next($optionlist);
+    my $full_name = weechat::infolist_string($optionlist,"full_name");
+    my $option_desc = "";
+    my $option_default_value = "";
+    my $option_range = "";
+    my $possible_values = "";
+    my $re = qq(\Q$full_name);
+    if (grep (/^$re$/,$options_names[$current_line]))
+    {
+        $option_desc = weechat::infolist_string($optionlist, "description_nls");
+        $option_desc = weechat::infolist_string($optionlist, "description") if ($option_desc eq "");
+        $option_desc = "No help found" if ($option_desc eq "");
+        $option_default_value = weechat::infolist_string($optionlist, "default_value");
+        $possible_values = weechat::infolist_string($optionlist, "string_values") if (weechat::infolist_string($optionlist, "string_values") ne "");
+        if ((weechat::infolist_string($optionlist, "type") eq "integer") && ($possible_values eq ""))
+        {
+            $option_range = weechat::infolist_integer($optionlist, "min")
+                ." .. ".weechat::infolist_integer($optionlist, "max");
+        }
+    }
+    weechat::infolist_free($optionlist);
+    iset_title();
+
+    $description = weechat::color(weechat::config_color($options_iset{"color_help_option_name"})).$options_names[$current_line]
+        .weechat::color("bar_fg").": "
+        .weechat::color(weechat::config_color($options_iset{"color_help_text"})).$option_desc;
+
+    # show additional infos like default value and possible values
+
+    if (weechat::config_boolean($options_iset{"show_help_extra_info"}) == 1)
+    {
+        $description .=
+            weechat::color("bar_delim")." ["
+            .weechat::color("bar_fg")."default: "
+            .weechat::color("bar_delim")."\""
+            .weechat::color(weechat::config_color($options_iset{"color_help_default_value"})).$option_default_value
+            .weechat::color("bar_delim")."\"";
+        if ($option_range ne "")
+        {
+            $description .= weechat::color("bar_fg").", values: ".$option_range;
+        }
+        if ($possible_values ne "")
+        {
+            $possible_values =~ s/\|/", "/g;      # replace '|' to '", "'
+            $description .= weechat::color("bar_fg").", values: ". "\"" . $possible_values . "\"";
+
+        }
+        $description .= weechat::color("bar_delim")."]";
+    }
+    return $description;
+}
+
+sub iset_check_condition_isetbar_cb
+{
+    my ($data, $modifier, $modifier_data, $string) = ($_[0], $_[1], $_[2], $_[3]);
+    my $buffer = weechat::window_get_pointer($modifier_data, "buffer");
+    if ($buffer ne "")
+    {
+        if ((weechat::buffer_get_string($buffer, "plugin") eq $LANG)
+            && (weechat::buffer_get_string($buffer, "name") eq $PRGNAME))
+        {
+            return "1";
+        }
+    }
+    return "0";
+}
+
+sub iset_show_bar
+{
+    my $show = $_[0];
+    my $barhidden = weechat::config_get("weechat.bar.isetbar.hidden");
+    if ($barhidden)
+    {
+        if ($show)
+        {
+            if (weechat::config_boolean($options_iset{"show_help_bar"}) == 1)
+            {
+                if (weechat::config_boolean($barhidden))
+                {
+                    weechat::config_option_set($barhidden, 0, 1);
+                }
+            }
+        }
+        else
+        {
+            if (!weechat::config_boolean($barhidden))
+            {
+                weechat::config_option_set($barhidden, 1, 1);
+            }
+        }
+    }
+}
+
+sub iset_signal_buffer_switch_cb
+{
+    my $buffer_pointer = $_[2];
+    my $show_bar = 0;
+    $show_bar = 1 if (weechat::buffer_get_integer($iset_buffer, "num_displayed") > 0);
+    iset_show_bar($show_bar);
+    iset_check_line_outside_window() if ($buffer_pointer eq $iset_buffer);
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub iset_item_cb
+{
+    return iset_get_help();
+}
+
+sub iset_upgrade_ended
+{
+    iset_full_refresh();
+}
+
+sub iset_end
+{
+    # when script is unloaded, we hide bar
+    iset_show_bar(0);
+}
+
+# -------------------------------[ mouse support ]-------------------------------------
+
+sub hook_focus_iset_cb
+{
+    my %info = %{$_[1]};
+    my $bar_item_line = int($info{"_bar_item_line"});
+    undef my $hash;
+    if (($info{"_buffer_name"} eq $PRGNAME) && $info{"_buffer_plugin"} eq $LANG && ($bar_item_line >= 0) && ($bar_item_line <= $#iset_focus))
+    {
+        $hash = $iset_focus[$bar_item_line];
+    }
+    else
+    {
+        $hash = {};
+        my $hash_focus = $iset_focus[0];
+        foreach my $key (keys %$hash_focus)
+        {
+            $hash->{$key} = "?";
+        }
+    }
+    return $hash;
+}
+
+# _chat_line_y contains selected line
+sub iset_hsignal_mouse_cb
+{
+    my ($data, $signal, %hash) = ($_[0], $_[1], %{$_[2]});
+
+    if ($hash{"_buffer_name"} eq $PRGNAME && ($hash{"_buffer_plugin"} eq $LANG))
+    {
+        if ($hash{"_key"} eq "button1")
+        {
+            iset_set_current_line($hash{"_chat_line_y"});
+        }
+        elsif ($hash{"_key"} eq "button2")
+        {
+            if ($options_types[$hash{"_chat_line_y"}] eq "boolean")
+            {
+                iset_set_option($options_names[$hash{"_chat_line_y"}], "toggle");
+                iset_set_current_line($hash{"_chat_line_y"});
+            }
+            elsif ($options_types[$hash{"_chat_line_y"}] eq "string")
+            {
+                iset_set_current_line($hash{"_chat_line_y"});
+                weechat::command("", "/$PRGNAME **set");
+            }
+        }
+        elsif ($hash{"_key"} eq "button2-gesture-left" or $hash{"_key"} eq "button2-gesture-left-long")
+        {
+            if ($options_types[$hash{"_chat_line_y"}] eq "integer" or ($options_types[$hash{"_chat_line_y"}] eq "color"))
+            {
+                iset_set_current_line($hash{"_chat_line_y"});
+                my $distance = distance($hash{"_chat_line_x"},$hash{"_chat_line_x2"});
+                weechat::command("", "/repeat $distance /$PRGNAME **decr");
+            }
+        }
+        elsif ($hash{"_key"} eq "button2-gesture-right" or $hash{"_key"} eq "button2-gesture-right-long")
+        {
+            if ($options_types[$hash{"_chat_line_y"}] eq "integer" or ($options_types[$hash{"_chat_line_y"}] eq "color"))
+            {
+                iset_set_current_line($hash{"_chat_line_y"});
+                my $distance = distance($hash{"_chat_line_x"},$hash{"_chat_line_x2"});
+                weechat::command("", "/repeat $distance /$PRGNAME **incr");
+            }
+        }
+    }
+    window_switch();
+}
+
+sub window_switch
+{
+    my $current_window = weechat::current_window();
+    my $dest_window = weechat::window_search_with_buffer(weechat::buffer_search("perl","iset"));
+    return 0 if ($dest_window eq "" or $current_window eq $dest_window);
+
+    my $infolist = weechat::infolist_get("window", $dest_window, "");
+    weechat::infolist_next($infolist);
+    my $number = weechat::infolist_integer($infolist, "number");
+    weechat::infolist_free($infolist);
+    weechat::command("","/window " . $number);
+}
+
+sub distance
+{
+    my ($x1,$x2) = ($_[0], $_[1]);
+    my $distance;
+    $distance = $x1 - $x2;
+    $distance = abs($distance);
+    if ($distance > 0)
+    {
+        use integer;
+        $distance  =  $distance / 3;
+        $distance = 1 if ($distance == 0);
+    }
+    elsif ($distance == 0)
+    {
+        $distance = 1;
+    }
+    return $distance;
+}
+
+# -----------------------------------[ config ]---------------------------------------
+
+sub iset_config_init
+{
+    $iset_config_file = weechat::config_new($ISET_CONFIG_FILE_NAME,"iset_config_reload_cb","");
+    return if ($iset_config_file eq "");
+
+    # section "color"
+    my $section_color = weechat::config_new_section($iset_config_file,"color", 0, 0, "", "", "", "", "", "", "", "", "", "");
+    if ($section_color eq "")
+    {
+        weechat::config_free($iset_config_file);
+        return;
+    }
+    $options_iset{"color_option"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "option", "color", "Color for option name in iset buffer", "", 0, 0,
+        "default", "default", 0, "", "", "full_refresh_cb", "", "", "");
+    $options_iset{"color_option_selected"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "option_selected", "color", "Color for selected option name in iset buffer", "", 0, 0,
+        "white", "white", 0, "", "", "full_refresh_cb", "", "", "");
+    $options_iset{"color_type"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "type", "color", "Color for option type (integer, boolean, string)", "", 0, 0,
+        "brown", "brown", 0, "", "", "full_refresh_cb", "", "", "");
+    $options_iset{"color_type_selected"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "type_selected", "color", "Color for selected option type (integer, boolean, string)", "", 0, 0,
+        "yellow", "yellow", 0, "", "", "full_refresh_cb", "", "", "");
+    $options_iset{"color_value"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "value", "color", "Color for option value", "", 0, 0,
+        "cyan", "cyan", 0, "", "", "full_refresh_cb", "", "", "");
+    $options_iset{"color_value_selected"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "value_selected", "color", "Color for selected option value", "", 0, 0,
+        "lightcyan", "lightcyan", 0, "", "", "full_refresh_cb", "", "", "");
+    $options_iset{"color_value_diff"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "value_diff", "color", "Color for option value different from default", "", 0, 0,
+        "magenta", "magenta", 0, "", "", "full_refresh_cb", "", "", "");
+    $options_iset{"color_value_diff_selected"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "value_diff_selected", "color", "Color for selected option value different from default", "", 0, 0,
+        "lightmagenta", "lightmagenta", 0, "", "", "full_refresh_cb", "", "", "");
+    $options_iset{"color_value_undef"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "value_undef", "color", "Color for option value undef", "", 0, 0,
+        "green", "green", 0, "", "", "full_refresh_cb", "", "", "");
+    $options_iset{"color_value_undef_selected"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "value_undef_selected", "color", "Color for selected option value undef", "", 0, 0,
+        "lightgreen", "lightgreen", 0, "", "", "full_refresh_cb", "", "", "");
+    $options_iset{"color_bg_selected"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "bg_selected", "color", "Background color for current selected option", "", 0, 0,
+        "red", "red", 0, "", "", "full_refresh_cb", "", "", "");
+    $options_iset{"color_help_option_name"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "help_option_name", "color", "Color for option name in help-bar", "", 0, 0,
+        "white", "white", 0, "", "", "bar_refresh", "", "", "");
+    $options_iset{"color_help_text"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "help_text", "color", "Color for option description in help-bar", "", 0, 0,
+        "default", "default", 0, "", "", "bar_refresh", "", "", "");
+    $options_iset{"color_help_default_value"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "help_default_value", "color", "Color for default option value in help-bar", "", 0, 0,
+        "green", "green", 0, "", "", "bar_refresh", "", "", "");
+
+    # section "help"
+    my $section_help = weechat::config_new_section($iset_config_file,"help", 0, 0, "", "", "", "", "", "", "", "", "", "");
+    if ($section_help eq "")
+    {
+        weechat::config_free($iset_config_file);
+        return;
+    }
+    $options_iset{"show_help_bar"} = weechat::config_new_option(
+        $iset_config_file, $section_help,
+        "show_help_bar", "boolean", "Show help bar", "", 0, 0,
+        "on", "on", 0, "", "", "toggle_help_cb", "", "", "");
+    $options_iset{"show_help_extra_info"} = weechat::config_new_option(
+        $iset_config_file, $section_help,
+        "show_help_extra_info", "boolean", "Show additional information in help bar (default value, max./min. value) ", "", 0, 0,
+        "on", "on", 0, "", "", "", "", "", "");
+    $options_iset{"show_plugin_description"} = weechat::config_new_option(
+        $iset_config_file, $section_help,
+        "show_plugin_description", "boolean", "Show plugin description in iset buffer", "", 0, 0,
+        "off", "off", 0, "", "", "full_refresh_cb", "", "", "");
+
+    # section "look"
+    my $section_look = weechat::config_new_section($iset_config_file, "look", 0, 0, "", "", "", "", "", "", "", "", "", "");
+    if ($section_look eq "")
+    {
+        weechat::config_free($iset_config_file);
+        return;
+    }
+    $options_iset{"value_search_char"} = weechat::config_new_option(
+        $iset_config_file, $section_look,
+        "value_search_char", "string", "Trigger char to tell iset to search for value instead of option (for example: =red)", "", 0, 0,
+        "=", "=", 0, "", "", "", "", "", "");
+    $options_iset{"scroll_horiz"} = weechat::config_new_option(
+        $iset_config_file, $section_look,
+        "scroll_horiz", "integer", "scroll content of iset buffer n%", "", 1, 100,
+        "10", "10", 0, "", "", "", "", "", "");
+    $options_iset{"show_current_line"} = weechat::config_new_option(
+        $iset_config_file, $section_look,
+        "show_current_line", "boolean", "show current line in title bar.", "", 0, 0,
+        "on", "on", 0, "", "", "", "", "", "");
+    $options_iset{"use_mute"} = weechat::config_new_option(
+        $iset_config_file, $section_look,
+        "use_mute", "boolean", "/mute command will be used in input bar", "", 0, 0,
+        "off", "off", 0, "", "", "", "", "", "");
+}
+
+sub iset_config_reload_cb
+{
+    my ($data,$config_file) = ($_[0], $_[1]);
+    return weechat::config_reload($config_file)
+}
+
+sub iset_config_read
+{
+    return weechat::config_read($iset_config_file) if ($iset_config_file ne "");
+}
+
+sub iset_config_write
+{
+    return weechat::config_write($iset_config_file) if ($iset_config_file ne "");
+}
+
+sub full_refresh_cb
+{
+    iset_full_refresh();
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub bar_refresh
+{
+    iset_get_help(1);
+    weechat::bar_item_update("isetbar_help") if (weechat::config_boolean($options_iset{"show_help_bar"}) == 1);
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub toggle_help_cb
+{
+    my $value = weechat::config_boolean($options_iset{"show_help_bar"});
+    iset_show_bar($value);
+    return weechat::WEECHAT_RC_OK;
+}
+
+# -----------------------------------[ main ]-----------------------------------------
+
+weechat::register($PRGNAME, $AUTHOR, $VERSION, $LICENSE,
+                  $DESCR, "iset_end", "");
+
+$wee_version_number = weechat::info_get("version_number", "") || 0;
+
+iset_config_init();
+iset_config_read();
+
+weechat::hook_command($PRGNAME, "Interactive set", "f <file> || s <section> || [=][=]<text>",
+                      "f file   : show options for a file\n".
+                      "s section: show options for a section\n".
+                      "text     : show options with 'text' in name\n".
+                      weechat::config_string($options_iset{"value_search_char"})."text    : show options with 'text' in value\n".
+                      weechat::config_string($options_iset{"value_search_char"}).weechat::config_string($options_iset{"value_search_char"})."text   : show options with exact 'text' in value\n\n".
+                      "Keys for iset buffer:\n".
+                      "f11,f12        : move iset content left/right\n".
+                      "up,down        : move one option up/down\n".
+                      "pgup,pdwn      : move one page up/down\n".
+                      "home,end       : move to first/last option\n".
+                      "ctrl+'L'       : refresh options and screen\n".
+                      "alt+space      : toggle boolean on/off\n".
+                      "alt+'+'        : increase value (for integer or color)\n".
+                      "alt+'-'        : decrease value (for integer or color)\n".
+                      "alt+'i',alt+'r': reset value of option\n".
+                      "alt+'i',alt+'u': unset option\n".
+                      "alt+enter      : set new value for option (edit it with command line)\n".
+                      "text,enter     : set a new filter using command line (use '*' to see all options)\n".
+                      "alt+'v'        : toggle help bar on/off\n".
+                      "alt+'p'        : toggle option \"show_plugin_description\" on/off\n".
+                      "\n".
+                      "Mouse actions:\n".
+                      "wheel up/down                 : move cursor up/down\n".
+                      "left button                   : select an option from list\n".
+                      "right button                  : toggle boolean (on/off) or set a new value for option (edit it with command line)\n".
+                      "right button + drag left/right: increase/decrease value (for integer or color)\n".
+                      "\n".
+                      "Examples:\n".
+                      "  show options for file 'weechat'\n".
+                      "    /iset f weechat\n".
+                      "  show options for file 'irc'\n".
+                      "    /iset f irc\n".
+                      "  show options for section 'look'\n".
+                      "    /iset s look\n".
+                      "  show all options with text 'nicklist' in name\n".
+                      "    /iset nicklist\n".
+                      "  show all values which contain 'red'. ('" . weechat::config_string($options_iset{"value_search_char"}) . "' is a trigger char).\n".
+                      "    /iset ". weechat::config_string($options_iset{"value_search_char"}) ."red\n".
+                      "  show all values which hit 'off'. ('" . weechat::config_string($options_iset{"value_search_char"}) . weechat::config_string($options_iset{"value_search_char"}) . "' is a trigger char).\n".
+                      "    /iset ". weechat::config_string($options_iset{"value_search_char"}) . weechat::config_string($options_iset{"value_search_char"}) ."off\n".
+                      "  show options for file 'weechat' which contains value 'off'\n".
+                      "    /iset f weechat ".weechat::config_string($options_iset{"value_search_char"})."off\n".
+                      "",
+                      "", "iset_cmd_cb", "");
+weechat::hook_signal("upgrade_ended", "iset_upgrade_ended", "");
+weechat::hook_signal("window_scrolled", "iset_signal_window_scrolled_cb", "");
+weechat::hook_signal("buffer_switch", "iset_signal_buffer_switch_cb","");
+weechat::bar_item_new("isetbar_help", "iset_item_cb", "");
+weechat::bar_new("isetbar", "on", "0", "window", "", "top", "horizontal",
+                 "vertical", "3", "3", "default", "cyan", "default", "1",
+                 "isetbar_help");
+weechat::hook_modifier("bar_condition_isetbar", "iset_check_condition_isetbar_cb", "");
+weechat::hook_config("*", "iset_config_cb", "");
+$iset_buffer = weechat::buffer_search($LANG, $PRGNAME);
+iset_init() if ($iset_buffer ne "");
+
+if ($wee_version_number >= 0x00030600)
+{
+    weechat::hook_focus("chat", "hook_focus_iset_cb", "");
+    weechat::hook_hsignal($PRGNAME."_mouse", "iset_hsignal_mouse_cb", "");
+    weechat::key_bind("mouse", \%mouse_keys);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/weechat/perl/buffers.pl	Wed Nov 19 19:24:17 2014 +0100
@@ -0,0 +1,1785 @@
+#
+# Copyright (C) 2008-2014 Sebastien Helleu <[email protected]>
+# Copyright (C) 2011-2013 Nils G <[email protected]>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+#
+# Display sidebar with list of buffers.
+#
+# History:
+#
+# 2014-08-29, Patrick Steinhardt <[email protected]>:
+#     v4.9: add support for specifying custom buffer names
+# 2014-07-19, Sebastien Helleu <[email protected]>:
+#     v4.8: add support of ctrl + mouse wheel to jump to previous/next buffer,
+#           new option "mouse_wheel"
+# 2014-06-22, Sebastien Helleu <[email protected]>:
+#     v4.7: fix typos in options
+# 2014-04-05, Sebastien Helleu <[email protected]>:
+#     v4.6: add support of hidden buffers (WeeChat >= 0.4.4)
+# 2014-01-01, Sebastien Helleu <[email protected]>:
+#     v4.5: add option "mouse_move_buffer"
+# 2013-12-11, Sebastien Helleu <[email protected]>:
+#     v4.4: fix buffer number on drag to the end of list when option
+#           weechat.look.buffer_auto_renumber is off
+# 2013-12-10, nils_2@freenode.#weechat:
+#     v4.3: add options "prefix_bufname" and "suffix_bufname (idea by silverd)
+#         : fix hook_timer() for show_lag wasn't disabled
+#         : improved signal handling (less updating of buffers list)
+# 2013-11-07, Sebastien Helleu <[email protected]>:
+#     v4.2: use default filling "columns_vertical" when bar position is top/bottom
+# 2013-10-31, nils_2@freenode.#weechat:
+#     v4.1: add option "detach_buffer_immediately" (idea by farn)
+# 2013-10-20, nils_2@freenode.#weechat:
+#     v4.0: add options "detach_displayed_buffers", "detach_display_window_number"
+# 2013-09-27, nils_2@freenode.#weechat:
+#     v3.9: add option "toggle_bar" and option "show_prefix_query" (idea by IvarB)
+#         : fix problem with linefeed at end of list of buffers (reported by grawity)
+# 2012-10-18, nils_2@freenode.#weechat:
+#     v3.8: add option "mark_inactive", to mark buffers you are not in (idea by xrdodrx)
+#         : add wildcard "*" for immune_detach_buffers (idea by StarWeaver)
+#         : add new options "detach_query" and "detach_free_content" (idea by StarWeaver)
+# 2012-10-06, Nei <anti.teamidiot.de>:
+#     v3.7: call menu on right mouse if menu script is loaded.
+# 2012-10-06, nils_2 <[email protected]>:
+#     v3.6: add new option "hotlist_counter" (idea by torque).
+# 2012-06-02, nils_2 <[email protected]>:
+#     v3.5: add values "server|channel|private|all|keepserver|none" to option "hide_merged_buffers" (suggested by dominikh).
+# 2012-05-25, nils_2 <[email protected]>:
+#     v3.4: add new option "show_lag".
+# 2012-04-07, Sebastien Helleu <[email protected]>:
+#     v3.3: fix truncation of wide chars in buffer name (option name_size_max) (bug #36034)
+# 2012-03-15, nils_2 <[email protected]>:
+#     v3.2: add new option "detach"(weechat >= 0.3.8)
+#           add new option "immune_detach_buffers" (requested by Mkaysi)
+#           add new function buffers_whitelist add|del|reset (suggested by FiXato)
+#           add new function buffers_detach add|del|reset
+# 2012-03-09, Sebastien Helleu <[email protected]>:
+#     v3.1: fix reload of config file
+# 2012-01-29, nils_2 <[email protected]>:
+#     v3.0: fix: buffers did not update directly during window_switch (reported by FiXato)
+# 2012-01-29, nils_2 <[email protected]>:
+#     v2.9: add options "name_size_max" and "name_crop_suffix"
+# 2012-01-08, nils_2 <[email protected]>:
+#     v2.8: fix indenting for option "show_number off"
+#           fix unset of buffer activity in hotlist when buffer was moved with mouse
+#           add buffer with free content and core buffer sorted first (suggested  by nyuszika7h)
+#           add options queries_default_fg/bg and queries_message_fg/bg (suggested by FiXato)
+#           add clicking with left button on current buffer will do a jump_previously_visited_buffer (suggested by FiXato)
+#           add clicking with right button on current buffer will do a jump_next_visited_buffer
+#           add additional informations in help texts
+#           add default_fg and default_bg for whitelist channels
+#           internal changes  (script is now 3Kb smaller)
+# 2012-01-04, Sebastien Helleu <[email protected]>:
+#     v2.7: fix regex lookup in whitelist buffers list
+# 2011-12-04, nils_2 <[email protected]>:
+#     v2.6: add own config file (buffers.conf)
+#           add new behavior for indenting (under_name)
+#           add new option to set different color for server buffers and buffers with free content
+# 2011-10-30, nils_2 <[email protected]>:
+#     v2.5: add new options "show_number_char" and "color_number_char",
+#           add help-description for options
+# 2011-08-24, Sebastien Helleu <[email protected]>:
+#     v2.4: add mouse support
+# 2011-06-06, nils_2 <[email protected]>:
+#     v2.3: added: missed option "color_whitelist_default"
+# 2011-03-23, Sebastien Helleu <[email protected]>:
+#     v2.2: fix color of nick prefix with WeeChat >= 0.3.5
+# 2011-02-13, nils_2 <[email protected]>:
+#     v2.1: add options "color_whitelist_*"
+# 2010-10-05, Sebastien Helleu <[email protected]>:
+#     v2.0: add options "sort" and "show_number"
+# 2010-04-12, Sebastien Helleu <[email protected]>:
+#     v1.9: replace call to log() by length() to align buffer numbers
+# 2010-04-02, Sebastien Helleu <[email protected]>:
+#     v1.8: fix bug with background color and option indenting_number
+# 2010-04-02, Helios <[email protected]>:
+#     v1.7: add indenting_number option
+# 2010-02-25, m4v <[email protected]>:
+#     v1.6: add option to hide empty prefixes
+# 2010-02-12, Sebastien Helleu <[email protected]>:
+#     v1.5: add optional nick prefix for buffers like IRC channels
+# 2009-09-30, Sebastien Helleu <[email protected]>:
+#     v1.4: remove spaces for indenting when bar position is top/bottom
+# 2009-06-14, Sebastien Helleu <[email protected]>:
+#     v1.3: add option "hide_merged_buffers"
+# 2009-06-14, Sebastien Helleu <[email protected]>:
+#     v1.2: improve display with merged buffers
+# 2009-05-02, Sebastien Helleu <[email protected]>:
+#     v1.1: sync with last API changes
+# 2009-02-21, Sebastien Helleu <[email protected]>:
+#     v1.0: remove timer used to update bar item first time (not needed any more)
+# 2009-02-17, Sebastien Helleu <[email protected]>:
+#     v0.9: fix bug with indenting of private buffers
+# 2009-01-04, Sebastien Helleu <[email protected]>:
+#     v0.8: update syntax for command /set (comments)
+# 2008-10-20, Jiri Golembiovsky <[email protected]>:
+#     v0.7: add indenting option
+# 2008-10-01, Sebastien Helleu <[email protected]>:
+#     v0.6: add default color for buffers, and color for current active buffer
+# 2008-09-18, Sebastien Helleu <[email protected]>:
+#     v0.5: fix color for "low" level entry in hotlist
+# 2008-09-18, Sebastien Helleu <[email protected]>:
+#     v0.4: rename option "show_category" to "short_names",
+#           remove option "color_slash"
+# 2008-09-15, Sebastien Helleu <[email protected]>:
+#     v0.3: fix bug with priority in hotlist (var not defined)
+# 2008-09-02, Sebastien Helleu <[email protected]>:
+#     v0.2: add color for buffers with activity and config options for
+#           colors, add config option to display/hide categories
+# 2008-03-15, Sebastien Helleu <[email protected]>:
+#     v0.1: script creation
+#
+# Help about settings:
+#   display all settings for script (or use iset.pl script to change settings):
+#      /set buffers*
+#   show help text for option buffers.look.whitelist_buffers:
+#      /help buffers.look.whitelist_buffers
+#
+# Mouse-support (standard key bindings):
+#   left mouse-button:
+#       - click on a buffer to switch to selected buffer
+#       - click on current buffer will do action jump_previously_visited_buffer
+#       - drag a buffer and drop it on another position will move the buffer to position
+#   right mouse-button:
+#       - click on current buffer will do action jump_next_visited_buffer
+#       - moving buffer to the left/right will close buffer.
+#
+
+use strict;
+use Encode qw( decode encode );
+# -----------------------------[ internal ]-------------------------------------
+my $SCRIPT_NAME = "buffers";
+my $SCRIPT_VERSION = "4.9";
+
+my $BUFFERS_CONFIG_FILE_NAME = "buffers";
+my $buffers_config_file;
+my $cmd_buffers_whitelist= "buffers_whitelist";
+my $cmd_buffers_detach   = "buffers_detach";
+
+my %mouse_keys = ("\@item(buffers):button1*" => "hsignal:buffers_mouse",
+                  "\@item(buffers):button2*" => "hsignal:buffers_mouse",
+                  "\@bar(buffers):ctrl-wheelup" => "hsignal:buffers_mouse",
+                  "\@bar(buffers):ctrl-wheeldown" => "hsignal:buffers_mouse");
+my %options;
+my %hotlist_level = (0 => "low", 1 => "message", 2 => "private", 3 => "highlight");
+my @whitelist_buffers = ();
+my @immune_detach_buffers= ();
+my @detach_buffer_immediately= ();
+my @buffers_focus = ();
+my %buffers_timer = ();
+my %Hooks = ();
+
+# --------------------------------[ init ]--------------------------------------
+weechat::register($SCRIPT_NAME, "Sebastien Helleu <flashcode\@flashtux.org>",
+                  $SCRIPT_VERSION, "GPL3",
+                  "Sidebar with list of buffers", "shutdown_cb", "");
+my $weechat_version = weechat::info_get("version_number", "") || 0;
+
+buffers_config_init();
+buffers_config_read();
+
+weechat::bar_item_new($SCRIPT_NAME, "build_buffers", "");
+weechat::bar_new($SCRIPT_NAME, "0", "0", "root", "", "left", "columns_vertical",
+                 "vertical", "0", "0", "default", "default", "default", "1",
+                 $SCRIPT_NAME);
+
+if ( check_bar_item() == 0 )
+{
+    weechat::command("", "/bar show " . $SCRIPT_NAME) if ( weechat::config_boolean($options{"toggle_bar"}) eq 1 );
+}
+
+weechat::hook_signal("buffer_opened", "buffers_signal_buffer", "");
+weechat::hook_signal("buffer_closed", "buffers_signal_buffer", "");
+weechat::hook_signal("buffer_merged", "buffers_signal_buffer", "");
+weechat::hook_signal("buffer_unmerged", "buffers_signal_buffer", "");
+weechat::hook_signal("buffer_moved", "buffers_signal_buffer", "");
+weechat::hook_signal("buffer_renamed", "buffers_signal_buffer", "");
+weechat::hook_signal("buffer_switch", "buffers_signal_buffer", "");
+weechat::hook_signal("buffer_hidden", "buffers_signal_buffer", "");  # WeeChat >= 0.4.4
+weechat::hook_signal("buffer_unhidden", "buffers_signal_buffer", "");  # WeeChat >= 0.4.4
+weechat::hook_signal("buffer_localvar_added", "buffers_signal_buffer", "");
+weechat::hook_signal("buffer_localvar_changed", "buffers_signal_buffer", "");
+
+weechat::hook_signal("window_switch", "buffers_signal_buffer", "");
+weechat::hook_signal("hotlist_changed", "buffers_signal_hotlist", "");
+#weechat::hook_command_run("/input switch_active_*", "buffers_signal_buffer", "");
+weechat::bar_item_update($SCRIPT_NAME);
+
+
+if ($weechat_version >= 0x00030600)
+{
+    weechat::hook_focus($SCRIPT_NAME, "buffers_focus_buffers", "");
+    weechat::hook_hsignal("buffers_mouse", "buffers_hsignal_mouse", "");
+    weechat::key_bind("mouse", \%mouse_keys);
+}
+
+weechat::hook_command($cmd_buffers_whitelist,
+                      "add/del current buffer to/from buffers whitelist",
+                      "[add] || [del] || [reset]",
+                      "  add: add current buffer in configuration file\n".
+                      "  del: delete current buffer from configuration file\n".
+                      "reset: reset all buffers from configuration file ".
+                      "(no confirmation!)\n\n".
+                      "Examples:\n".
+                      "/$cmd_buffers_whitelist add\n",
+                      "add %-||".
+                      "del %-||".
+                      "reset %-",
+                      "buffers_cmd_whitelist", "");
+weechat::hook_command($cmd_buffers_detach,
+                      "add/del current buffer to/from buffers detach",
+                      "[add] || [del] || [reset]",
+                      "  add: add current buffer in configuration file\n".
+                      "  del: delete current buffer from configuration file\n".
+                      "reset: reset all buffers from configuration file ".
+                      "(no confirmation!)\n\n".
+                      "Examples:\n".
+                      "/$cmd_buffers_detach add\n",
+                      "add %-||".
+                      "del %-||".
+                      "reset %-",
+                      "buffers_cmd_detach", "");
+
+if ($weechat_version >= 0x00030800)
+{
+    weechat::hook_config("buffers.look.detach", "hook_timer_detach", "");
+    if (weechat::config_integer($options{"detach"}) > 0)
+    {
+        $Hooks{timer_detach} = weechat::hook_timer(weechat::config_integer($options{"detach"}) * 1000,
+                                                   60, 0, "buffers_signal_hotlist", "");
+    }
+}
+
+weechat::hook_config("buffers.look.show_lag", "hook_timer_lag", "");
+
+if (weechat::config_boolean($options{"show_lag"}))
+{
+    $Hooks{timer_lag} = weechat::hook_timer(
+        weechat::config_integer(weechat::config_get("irc.network.lag_refresh_interval")) * 1000,
+        0, 0, "buffers_signal_hotlist", "");
+}
+
+# -------------------------------- [ command ] --------------------------------
+sub buffers_cmd_whitelist
+{
+my ( $data, $buffer, $args ) = @_;
+    $args = lc($args);
+    my $buffers_whitelist = weechat::config_string( weechat::config_get("buffers.look.whitelist_buffers") );
+    return weechat::WEECHAT_RC_OK if ( $buffers_whitelist eq "" and $args eq "del" or $buffers_whitelist eq "" and $args eq "reset" );
+    my @buffers_list = split( /,/, $buffers_whitelist );
+    # get buffers name
+    my $infolist = weechat::infolist_get("buffer", weechat::current_buffer(), "");
+    weechat::infolist_next($infolist);
+    my $buffers_name = weechat::infolist_string($infolist, "name");
+    weechat::infolist_free($infolist);
+    return weechat::WEECHAT_RC_OK if ( $buffers_name eq "" );                   # should never happen
+
+    if ( $args eq "add" )
+    {
+        return weechat::WEECHAT_RC_OK if ( grep /^$buffers_name$/, @buffers_list );     # check if buffer already in list
+        push @buffers_list, ( $buffers_name );
+        my $buffers_list = &create_whitelist(\@buffers_list);
+        weechat::config_option_set( weechat::config_get("buffers.look.whitelist_buffers"), $buffers_list, 1);
+        weechat::print(weechat::current_buffer(), "buffer \"$buffers_name\" added to buffers whitelist");
+    }
+    elsif ( $args eq "del" )
+    {
+        return weechat::WEECHAT_RC_OK unless ( grep /^$buffers_name$/, @buffers_list );     # check if buffer is in list
+        @buffers_list = grep {$_ ne $buffers_name} @buffers_list;                           # delete entry
+        my $buffers_list = &create_whitelist(\@buffers_list);
+        weechat::config_option_set( weechat::config_get("buffers.look.whitelist_buffers"), $buffers_list, 1);
+        weechat::print(weechat::current_buffer(), "buffer \"$buffers_name\" deleted from buffers whitelist");
+    }
+    elsif ( $args eq "reset" )
+    {
+        return weechat::WEECHAT_RC_OK if ( $buffers_whitelist eq "" );
+        weechat::config_option_set( weechat::config_get("buffers.look.whitelist_buffers"), "", 1);
+        weechat::print(weechat::current_buffer(), "buffers whitelist is empty, now...");
+    }
+    return weechat::WEECHAT_RC_OK;
+}
+sub buffers_cmd_detach
+{
+    my ( $data, $buffer, $args ) = @_;
+    $args = lc($args);
+    my $immune_detach_buffers = weechat::config_string( weechat::config_get("buffers.look.immune_detach_buffers") );
+    return weechat::WEECHAT_RC_OK if ( $immune_detach_buffers eq "" and $args eq "del" or $immune_detach_buffers eq "" and $args eq "reset" );
+
+    my @buffers_list = split( /,/, $immune_detach_buffers );
+    # get buffers name
+    my $infolist = weechat::infolist_get("buffer", weechat::current_buffer(), "");
+    weechat::infolist_next($infolist);
+    my $buffers_name = weechat::infolist_string($infolist, "name");
+    weechat::infolist_free($infolist);
+    return weechat::WEECHAT_RC_OK if ( $buffers_name eq "" );                   # should never happen
+
+    if ( $args eq "add" )
+    {
+        return weechat::WEECHAT_RC_OK if ( grep /^$buffers_name$/, @buffers_list );     # check if buffer already in list
+        push @buffers_list, ( $buffers_name );
+        my $buffers_list = &create_whitelist(\@buffers_list);
+        weechat::config_option_set( weechat::config_get("buffers.look.immune_detach_buffers"), $buffers_list, 1);
+        weechat::print(weechat::current_buffer(), "buffer \"$buffers_name\" added to immune detach buffers");
+    }
+    elsif ( $args eq "del" )
+    {
+        return weechat::WEECHAT_RC_OK unless ( grep /^$buffers_name$/, @buffers_list );     # check if buffer is in list
+        @buffers_list = grep {$_ ne $buffers_name} @buffers_list;                           # delete entry
+        my $buffers_list = &create_whitelist(\@buffers_list);
+        weechat::config_option_set( weechat::config_get("buffers.look.immune_detach_buffers"), $buffers_list, 1);
+        weechat::print(weechat::current_buffer(), "buffer \"$buffers_name\" deleted from immune detach buffers");
+    }
+    elsif ( $args eq "reset" )
+    {
+        return weechat::WEECHAT_RC_OK if ( $immune_detach_buffers eq "" );
+        weechat::config_option_set( weechat::config_get("buffers.look.immune_detach_buffers"), "", 1);
+        weechat::print(weechat::current_buffer(), "immune detach buffers is empty, now...");
+    }
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub create_whitelist
+{
+    my @buffers_list = @{$_[0]};
+    my $buffers_list = "";
+        foreach (@buffers_list)
+        {
+            $buffers_list .= $_ .",";
+        }
+        # remove last ","
+        chop $buffers_list;
+    return $buffers_list;
+}
+
+# -------------------------------- [ config ] --------------------------------
+sub hook_timer_detach
+{
+    my $detach = $_[2];
+    if ( $detach eq 0 )
+    {
+        weechat::unhook($Hooks{timer_detach}) if $Hooks{timer_detach};
+        $Hooks{timer_detach} = "";
+    }
+    else
+    {
+        weechat::unhook($Hooks{timer_detach}) if $Hooks{timer_detach};
+        $Hooks{timer_detach} = weechat::hook_timer( weechat::config_integer( $options{"detach"}) * 1000, 60, 0, "buffers_signal_hotlist", "");
+    }
+    weechat::bar_item_update($SCRIPT_NAME);
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub hook_timer_lag
+{
+    my $lag = $_[2];
+    if ( $lag eq "off" )
+    {
+        weechat::unhook($Hooks{timer_lag}) if $Hooks{timer_lag};
+        $Hooks{timer_lag} = "";
+    }
+    else
+    {
+        weechat::unhook($Hooks{timer_lag}) if $Hooks{timer_lag};
+        $Hooks{timer_lag} = weechat::hook_timer( weechat::config_integer(weechat::config_get("irc.network.lag_refresh_interval")) * 1000, 0, 0, "buffers_signal_hotlist", "");
+    }
+    weechat::bar_item_update($SCRIPT_NAME);
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub buffers_config_read
+{
+    return weechat::config_read($buffers_config_file) if ($buffers_config_file ne "");
+}
+sub buffers_config_write
+{
+    return weechat::config_write($buffers_config_file) if ($buffers_config_file ne "");
+}
+sub buffers_config_reload_cb
+{
+    my ($data, $config_file) = ($_[0], $_[1]);
+    return weechat::config_reload($config_file)
+}
+sub buffers_config_init
+{
+    $buffers_config_file = weechat::config_new($BUFFERS_CONFIG_FILE_NAME,
+                                               "buffers_config_reload_cb", "");
+    return if ($buffers_config_file eq "");
+
+my %default_options_color =
+("color_current_fg" => [
+     "current_fg", "color",
+     "foreground color for current buffer",
+     "", 0, 0, "lightcyan", "lightcyan", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_current_bg" => [
+     "current_bg", "color",
+     "background color for current buffer",
+     "", 0, 0, "red", "red", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_default_fg" => [
+     "default_fg", "color",
+     "default foreground color for buffer name",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_default_bg" => [
+     "default_bg", "color",
+     "default background color for buffer name",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_hotlist_highlight_fg" => [
+     "hotlist_highlight_fg", "color",
+     "change foreground color of buffer name if a highlight messaged received",
+     "", 0, 0, "magenta", "magenta", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_hotlist_highlight_bg" => [
+     "hotlist_highlight_bg", "color",
+     "change background color of buffer name if a highlight messaged received",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_hotlist_low_fg" => [
+     "hotlist_low_fg", "color",
+     "change foreground color of buffer name if a low message received",
+     "", 0, 0, "white", "white", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_hotlist_low_bg" => [
+     "hotlist_low_bg", "color",
+     "change background color of buffer name if a low message received",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_hotlist_message_fg" => [
+     "hotlist_message_fg", "color",
+     "change foreground color of buffer name if a normal message received",
+     "", 0, 0, "yellow", "yellow", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_hotlist_message_bg" => [
+     "hotlist_message_bg", "color",
+     "change background color of buffer name if a normal message received",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_hotlist_private_fg" => [
+     "hotlist_private_fg", "color",
+     "change foreground color of buffer name if a private message received",
+     "", 0, 0, "lightgreen", "lightgreen", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_hotlist_private_bg" => [
+     "hotlist_private_bg", "color",
+     "change background color of buffer name if a private message received",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_number" => [
+     "number", "color",
+     "color for buffer number",
+     "", 0, 0, "lightgreen", "lightgreen", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_number_char" => [
+     "number_char", "color",
+     "color for buffer number char",
+     "", 0, 0, "lightgreen", "lightgreen", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_whitelist_default_fg" => [
+     "whitelist_default_fg", "color",
+     "default foreground color for whitelist buffer name",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_whitelist_default_bg" => [
+     "whitelist_default_bg", "color",
+     "default background color for whitelist buffer name",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_whitelist_low_fg" => [
+     "whitelist_low_fg", "color",
+     "low color of whitelist buffer name",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_whitelist_low_bg" => [
+     "whitelist_low_bg", "color",
+     "low color of whitelist buffer name",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_whitelist_message_fg" => [
+     "whitelist_message_fg", "color",
+     "message color of whitelist buffer name",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_whitelist_message_bg" => [
+     "whitelist_message_bg", "color",
+     "message color of whitelist buffer name",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_whitelist_private_fg" => [
+     "whitelist_private_fg", "color",
+     "private color of whitelist buffer name",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_whitelist_private_bg" => [
+     "whitelist_private_bg", "color",
+     "private color of whitelist buffer name",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_whitelist_highlight_fg" => [
+     "whitelist_highlight_fg", "color",
+     "highlight color of whitelist buffer name",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_whitelist_highlight_bg" => [
+     "whitelist_highlight_bg", "color",
+     "highlight color of whitelist buffer name",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_none_channel_fg" => [
+     "none_channel_fg", "color",
+     "foreground color for none channel buffer (e.g.: core/server/plugin ".
+     "buffer)",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_none_channel_bg" => [
+     "none_channel_bg", "color",
+     "background color for none channel buffer (e.g.: core/server/plugin ".
+     "buffer)",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "queries_default_fg" => [
+     "queries_default_fg", "color",
+     "foreground color for query buffer without message",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "queries_default_bg" => [
+     "queries_default_bg", "color",
+     "background color for query buffer without message",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "queries_message_fg" => [
+     "queries_message_fg", "color",
+     "foreground color for query buffer with unread message",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "queries_message_bg" => [
+     "queries_message_bg", "color",
+     "background color for query buffer with unread message",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "queries_highlight_fg" => [
+     "queries_highlight_fg", "color",
+     "foreground color for query buffer with unread highlight",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "queries_highlight_bg" => [
+     "queries_highlight_bg", "color",
+     "background color for query buffer with unread highlight",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_prefix_bufname" => [
+     "prefix_bufname", "color",
+     "color for prefix of buffer name",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "color_suffix_bufname" => [
+     "suffix_bufname", "color",
+     "color for suffix of buffer name",
+     "", 0, 0, "default", "default", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+);
+
+my %default_options_look =
+(
+ "hotlist_counter" => [
+     "hotlist_counter", "boolean",
+     "show number of message for the buffer (this option needs WeeChat >= ".
+     "0.3.5). The relevant option for notification is \"weechat.look.".
+     "buffer_notify_default\"",
+     "", 0, 0, "off", "off", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "show_lag" => [
+     "show_lag", "boolean",
+     "show lag behind server name. This option is using \"irc.color.".
+     "item_lag_finished\", ".
+     "\"irc.network.lag_min_show\" and \"irc.network.lag_refresh_interval\"",
+     "", 0, 0, "off", "off", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "look_whitelist_buffers" => [
+     "whitelist_buffers", "string",
+     "comma separated list of buffers for using a different color scheme ".
+     "(for example: freenode.#weechat,freenode.#weechat-fr)",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config_whitelist", "", "", ""
+ ],
+ "hide_merged_buffers" => [
+     "hide_merged_buffers", "integer",
+     "hide merged buffers. The value determines which merged buffers should ".
+     "be hidden, keepserver meaning 'all except server buffers'. Other values ".
+     "correspondent to the buffer type.",
+     "server|channel|private|keepserver|all|none", 0, 0, "none", "none", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "indenting" => [
+     "indenting", "integer", "use indenting for channel and query buffers. ".
+     "This option only takes effect if bar is left/right positioned",
+     "off|on|under_name", 0, 0, "off", "off", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "indenting_number" => [
+     "indenting_number", "boolean",
+     "use indenting for numbers. This option only takes effect if bar is ".
+     "left/right positioned",
+     "", 0, 0, "on", "on", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "short_names" => [
+     "short_names", "boolean",
+     "display short names (remove text before first \".\" in buffer name)",
+     "", 0, 0, "on", "on", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "show_number" => [
+     "show_number", "boolean",
+     "display buffer number in front of buffer name",
+     "", 0, 0, "on", "on", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "show_number_char" => [
+     "number_char", "string",
+     "display a char behind buffer number",
+     "", 0, 0, ".", ".", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "show_prefix_bufname" => [
+     "prefix_bufname", "string",
+     "prefix displayed in front of buffer name",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "show_suffix_bufname" => [
+     "suffix_bufname", "string",
+     "suffix displayed at end of buffer name",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "show_prefix" => [
+     "prefix", "boolean",
+     "displays your prefix for channel in front of buffer name",
+     "", 0, 0, "off", "off", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "show_prefix_empty" => [
+     "prefix_empty", "boolean",
+     "use a placeholder for channels without prefix",
+     "", 0, 0, "on", "on", 0,
+     "", "",  "buffers_signal_config", "", "", ""
+ ],
+ "show_prefix_query" => [
+     "prefix_for_query", "string",
+     "prefix displayed in front of query buffer",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "sort" => [
+     "sort", "integer",
+     "sort buffer-list by \"number\" or \"name\"",
+     "number|name", 0, 0, "number", "number", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "core_to_front" => [
+     "core_to_front", "boolean",
+     "core buffer and buffers with free content will be listed first. ".
+     "Take only effect if buffer sort is by name",
+     "", 0, 0, "off", "off", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "jump_prev_next_visited_buffer" => [
+     "jump_prev_next_visited_buffer", "boolean",
+     "jump to previously or next visited buffer if you click with ".
+     "left/right mouse button on currently visiting buffer",
+     "", 0, 0, "off", "off", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "name_size_max" => [
+     "name_size_max", "integer",
+     "maximum size of buffer name. 0 means no limitation",
+     "", 0, 256, 0, 0, 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "name_crop_suffix" => [
+     "name_crop_suffix", "string",
+     "contains an optional char(s) that is appended when buffer name is ".
+     "shortened",
+     "", 0, 0, "+", "+", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "detach" => [
+     "detach", "integer",
+     "detach buffer from buffers list after a specific period of time ".
+     "(in seconds) without action (weechat ≥ 0.3.8 required) (0 means \"off\")",
+     "", 0, 31536000, 0, "number", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "immune_detach_buffers" => [
+     "immune_detach_buffers", "string",
+     "comma separated list of buffers to NOT automatically detach. ".
+     "Allows \"*\" wildcard. Ex: \"BitlBee,freenode.*\"",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config_immune_detach_buffers", "", "", ""
+ ],
+ "detach_query" => [
+     "detach_query", "boolean",
+     "query buffer will be detached",
+     "", 0, 0, "off", "off", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "detach_buffer_immediately" => [
+     "detach_buffer_immediately", "string",
+     "comma separated list of buffers to detach immediately. A query and ".
+     "highlight message will attach buffer again. Allows \"*\" wildcard. ".
+     "Ex: \"BitlBee,freenode.*\"",
+     "", 0, 0, "", "", 0,
+     "", "", "buffers_signal_config_detach_buffer_immediately", "", "", ""
+ ],
+ "detach_free_content" => [
+     "detach_free_content", "boolean",
+     "buffers with free content will be detached (Ex: iset, chanmon)",
+     "", 0, 0, "off", "off", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "detach_displayed_buffers" => [
+     "detach_displayed_buffers", "boolean",
+     "buffers displayed in a (split) window will be detached",
+     "", 0, 0, "on", "on", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "detach_display_window_number" => [
+     "detach_display_window_number", "boolean",
+     "window number will be add, behind buffer name (this option takes only ".
+     "effect with \"detach_displayed_buffers\" option)",
+     "", 0, 0, "off", "off", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "mark_inactive" => [
+     "mark_inactive", "boolean",
+     "if option is \"on\", inactive buffers (those you are not in) will have ".
+     "parentheses around them. An inactive buffer will not be detached.",
+     "", 0, 0, "off", "off", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "toggle_bar" => [
+     "toggle_bar", "boolean",
+     "if option is \"on\", buffers bar will hide/show when script is ".
+     "(un)loaded.",
+     "", 0, 0, "on", "on", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "mouse_move_buffer" => [
+     "mouse_move_buffer", "boolean",
+     "if option is \"on\", mouse gestures (drag & drop) can move buffers in list.",
+     "", 0, 0, "on", "on", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+ "mouse_wheel" => [
+     "mouse_wheel", "boolean",
+     "if option is \"on\", mouse wheel jumps to previous/next buffer in list.",
+     "", 0, 0, "on", "on", 0,
+     "", "", "buffers_signal_config", "", "", ""
+ ],
+);
+    # section "color"
+    my $section_color = weechat::config_new_section(
+        $buffers_config_file,
+        "color", 0, 0, "", "", "", "", "", "", "", "", "", "");
+    if ($section_color eq "")
+    {
+        weechat::config_free($buffers_config_file);
+        return;
+    }
+    foreach my $option (keys %default_options_color)
+    {
+        $options{$option} = weechat::config_new_option(
+            $buffers_config_file,
+            $section_color,
+            $default_options_color{$option}[0],
+            $default_options_color{$option}[1],
+            $default_options_color{$option}[2],
+            $default_options_color{$option}[3],
+            $default_options_color{$option}[4],
+            $default_options_color{$option}[5],
+            $default_options_color{$option}[6],
+            $default_options_color{$option}[7],
+            $default_options_color{$option}[8],
+            $default_options_color{$option}[9],
+            $default_options_color{$option}[10],
+            $default_options_color{$option}[11],
+            $default_options_color{$option}[12],
+            $default_options_color{$option}[13],
+            $default_options_color{$option}[14]);
+    }
+
+    # section "look"
+    my $section_look = weechat::config_new_section(
+        $buffers_config_file,
+        "look", 0, 0, "", "", "", "", "", "", "", "", "", "");
+    if ($section_look eq "")
+    {
+        weechat::config_free($buffers_config_file);
+        return;
+    }
+    foreach my $option (keys %default_options_look)
+    {
+        $options{$option} = weechat::config_new_option(
+            $buffers_config_file,
+            $section_look,
+            $default_options_look{$option}[0],
+            $default_options_look{$option}[1],
+            $default_options_look{$option}[2],
+            $default_options_look{$option}[3],
+            $default_options_look{$option}[4],
+            $default_options_look{$option}[5],
+            $default_options_look{$option}[6],
+            $default_options_look{$option}[7],
+            $default_options_look{$option}[8],
+            $default_options_look{$option}[9],
+            $default_options_look{$option}[10],
+            $default_options_look{$option}[11],
+            $default_options_look{$option}[12],
+            $default_options_look{$option}[13],
+            $default_options_look{$option}[14],
+            $default_options_look{$option}[15]);
+    }
+}
+
+sub build_buffers
+{
+    my $str = "";
+
+    # get bar position (left/right/top/bottom)
+    my $position = "left";
+    my $option_position = weechat::config_get("weechat.bar.buffers.position");
+    if ($option_position ne "")
+    {
+        $position = weechat::config_string($option_position);
+    }
+
+    # read hotlist
+    my %hotlist;
+    my $infolist = weechat::infolist_get("hotlist", "", "");
+    while (weechat::infolist_next($infolist))
+    {
+        $hotlist{weechat::infolist_pointer($infolist, "buffer_pointer")} =
+            weechat::infolist_integer($infolist, "priority");
+        if ( weechat::config_boolean( $options{"hotlist_counter"} ) eq 1 and $weechat_version >= 0x00030500)
+        {
+            $hotlist{weechat::infolist_pointer($infolist, "buffer_pointer")."_count_00"} =
+                weechat::infolist_integer($infolist, "count_00");   # low message
+            $hotlist{weechat::infolist_pointer($infolist, "buffer_pointer")."_count_01"} =
+                weechat::infolist_integer($infolist, "count_01");   # channel message
+            $hotlist{weechat::infolist_pointer($infolist, "buffer_pointer")."_count_02"} =
+                weechat::infolist_integer($infolist, "count_02");   # private message
+            $hotlist{weechat::infolist_pointer($infolist, "buffer_pointer")."_count_03"} =
+                weechat::infolist_integer($infolist, "count_03");   # highlight message
+        }
+    }
+    weechat::infolist_free($infolist);
+
+    # read buffers list
+    @buffers_focus = ();
+    my @buffers;
+    my @current1 = ();
+    my @current2 = ();
+    my $old_number = -1;
+    my $max_number = 0;
+    my $max_number_digits = 0;
+    my $active_seen = 0;
+    $infolist = weechat::infolist_get("buffer", "", "");
+    while (weechat::infolist_next($infolist))
+    {
+        # ignore hidden buffers (WeeChat >= 0.4.4)
+        if ($weechat_version >= 0x00040400)
+        {
+            next if (weechat::infolist_integer($infolist, "hidden"));
+        }
+        my $buffer;
+        my $number = weechat::infolist_integer($infolist, "number");
+        if ($number ne $old_number)
+        {
+            @buffers = (@buffers, @current2, @current1);
+            @current1 = ();
+            @current2 = ();
+            $active_seen = 0;
+        }
+        if ($number > $max_number)
+        {
+            $max_number = $number;
+        }
+        $old_number = $number;
+        my $active = weechat::infolist_integer($infolist, "active");
+        if ($active)
+        {
+            $active_seen = 1;
+        }
+        $buffer->{"pointer"} = weechat::infolist_pointer($infolist, "pointer");
+        $buffer->{"number"} = $number;
+        $buffer->{"active"} = $active;
+        $buffer->{"current_buffer"} = weechat::infolist_integer($infolist, "current_buffer");
+        $buffer->{"num_displayed"} = weechat::infolist_integer($infolist, "num_displayed");
+        $buffer->{"plugin_name"} = weechat::infolist_string($infolist, "plugin_name");
+        $buffer->{"name"} = weechat::infolist_string($infolist, "name");
+        $buffer->{"short_name"} = weechat::infolist_string($infolist, "short_name");
+        $buffer->{"full_name"} = $buffer->{"plugin_name"}.".".$buffer->{"name"};
+        $buffer->{"type"} = weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type");
+        #weechat::print("", $buffer->{"type"});
+
+        # check if buffer is active (or maybe a /part, /kick channel)
+        if ($buffer->{"type"} eq "channel" and weechat::config_boolean( $options{"mark_inactive"} ) eq 1)
+        {
+            my $server = weechat::buffer_get_string($buffer->{"pointer"}, "localvar_server");
+            my $channel = weechat::buffer_get_string($buffer->{"pointer"}, "localvar_channel");
+            my $infolist_channel = weechat::infolist_get("irc_channel", "", $server.",".$channel);
+            if ($infolist_channel)
+            {
+                weechat::infolist_next($infolist_channel);
+                $buffer->{"nicks_count"} = weechat::infolist_integer($infolist_channel, "nicks_count");
+            }else
+            {
+                $buffer->{"nicks_count"} = 0;
+            }
+            weechat::infolist_free($infolist_channel);
+        }
+
+        my $result = check_immune_detached_buffers($buffer->{"name"});          # checking for wildcard 
+
+        next if ( check_detach_buffer_immediately($buffer->{"name"}) eq 1
+                 and $buffer->{"current_buffer"} eq 0
+                 and ( not exists $hotlist{$buffer->{"pointer"}} or $hotlist{$buffer->{"pointer"}} < 2) );          # checking for buffer to immediately detach
+
+        unless ($result)
+        {
+            my $detach_time = weechat::config_integer( $options{"detach"});
+            my $current_time = time();
+            # set timer for buffers with no hotlist action
+            $buffers_timer{$buffer->{"pointer"}} = $current_time
+             if ( not exists $hotlist{$buffer->{"pointer"}}
+             and $buffer->{"type"} eq "channel"
+             and not exists $buffers_timer{$buffer->{"pointer"}}
+             and $detach_time > 0);
+
+            $buffers_timer{$buffer->{"pointer"}} = $current_time
+            if (weechat::config_boolean($options{"detach_query"}) eq 1
+            and not exists $hotlist{$buffer->{"pointer"}}
+            and $buffer->{"type"} eq "private"
+            and not exists $buffers_timer{$buffer->{"pointer"}}
+            and $detach_time > 0);
+
+            $detach_time = 0
+            if (weechat::config_boolean($options{"detach_query"}) eq 0
+            and $buffer->{"type"} eq "private");
+
+            # free content buffer
+            $buffers_timer{$buffer->{"pointer"}} = $current_time
+            if (weechat::config_boolean($options{"detach_free_content"}) eq 1
+            and not exists $hotlist{$buffer->{"pointer"}}
+            and $buffer->{"type"} eq ""
+            and not exists $buffers_timer{$buffer->{"pointer"}}
+            and $detach_time > 0);
+            $detach_time = 0
+            if (weechat::config_boolean($options{"detach_free_content"}) eq 0
+            and $buffer->{"type"} eq "");
+
+            $detach_time = 0 if (weechat::config_boolean($options{"mark_inactive"}) eq 1 and defined $buffer->{"nicks_count"} and $buffer->{"nicks_count"} == 0);
+
+            # check for detach
+            unless ( $buffer->{"current_buffer"} eq 0
+            and not exists $hotlist{$buffer->{"pointer"}}
+#            and $buffer->{"type"} eq "channel"
+            and exists $buffers_timer{$buffer->{"pointer"}}
+            and $detach_time > 0
+            and $weechat_version >= 0x00030800
+            and $current_time - $buffers_timer{$buffer->{"pointer"}} >= $detach_time)
+            {
+                if ($active_seen)
+                {
+                    push(@current2, $buffer);
+                }
+                else
+                {
+                    push(@current1, $buffer);
+                }
+            }
+            elsif ( $buffer->{"current_buffer"} eq 0
+            and not exists $hotlist{$buffer->{"pointer"}}
+#            and $buffer->{"type"} eq "channel"
+            and exists $buffers_timer{$buffer->{"pointer"}}
+            and $detach_time > 0
+            and $weechat_version >= 0x00030800
+            and $current_time - $buffers_timer{$buffer->{"pointer"}} >= $detach_time)
+            {   # check for option detach_displayed_buffers and if buffer is displayed in a split window
+                if ( $buffer->{"num_displayed"} eq 1
+                    and weechat::config_boolean($options{"detach_displayed_buffers"}) eq 0 )
+                {
+                    my $infolist_window = weechat::infolist_get("window", "", "");
+                    while (weechat::infolist_next($infolist_window))
+                    {
+                        my $buffer_ptr = weechat::infolist_pointer($infolist_window, "buffer");
+                        if ($buffer_ptr eq $buffer->{"pointer"})
+                        {
+                            $buffer->{"window"} = weechat::infolist_integer($infolist_window, "number");
+                        }
+                    }
+                    weechat::infolist_free($infolist_window);
+
+                    push(@current2, $buffer);
+                }
+            }
+        }
+        else    # buffer in "immune_detach_buffers"
+        {
+                if ($active_seen)
+                {
+                    push(@current2, $buffer);
+                }
+                else
+                {
+                    push(@current1, $buffer);
+                }
+        }
+    }   # while end
+
+
+    if ($max_number >= 1)
+    {
+        $max_number_digits = length(int($max_number));
+    }
+    @buffers = (@buffers, @current2, @current1);
+    weechat::infolist_free($infolist);
+
+    # sort buffers by number, name or shortname
+    my %sorted_buffers;
+    if (1)
+    {
+        my $number = 0;
+        for my $buffer (@buffers)
+        {
+            my $key;
+            if (weechat::config_integer( $options{"sort"} ) eq 1) # number = 0; name = 1
+            {
+                my $name = weechat::buffer_get_string($buffer->{"pointer"}, "localvar_custom_name");
+                if (not defined $name or $name eq "") {
+                    if (weechat::config_boolean( $options{"short_names"} ) eq 1) {
+                        $name = $buffer->{"short_name"};
+                    } else {
+                        $name = $buffer->{"name"};
+                    }
+                }
+                if (weechat::config_integer($options{"name_size_max"}) >= 1){
+                    $name = encode("UTF-8", substr(decode("UTF-8", $name), 0, weechat::config_integer($options{"name_size_max"})));
+                }
+                if ( weechat::config_boolean($options{"core_to_front"}) eq 1)
+                {
+                    if ( (weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") ne "channel" ) and ( weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") ne "private") )
+                    {
+                        my $type = weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type");
+                        if ( $type eq "" and $name ne "weechat")
+                        {
+                            $name = " " . $name
+                        }else
+                        {
+                            $name = "  " . $name;
+                        }
+                    }
+                }
+                $key = sprintf("%s%08d", lc($name), $buffer->{"number"});
+            }
+            else
+            {
+                $key = sprintf("%08d", $number);
+            }
+            $sorted_buffers{$key} = $buffer;
+            $number++;
+        }
+    }
+
+    # build string with buffers
+    $old_number = -1;
+    foreach my $key (sort keys %sorted_buffers)
+    {
+        my $buffer = $sorted_buffers{$key};
+
+        if ( weechat::config_string($options{"hide_merged_buffers"}) eq "server" )
+        {
+            # buffer type "server" or merged with core?
+            if ( ($buffer->{"type"} eq "server" or $buffer->{"plugin_name"} eq "core") && (! $buffer->{"active"}) )
+            {
+                next;
+            }
+        }
+        if ( weechat::config_string($options{"hide_merged_buffers"}) eq "channel" )
+        {
+            # buffer type "channel" or merged with core?
+            if ( ($buffer->{"type"} eq "channel" or $buffer->{"plugin_name"} eq "core") && (! $buffer->{"active"}) )
+            {
+                next;
+            }
+        }
+        if ( weechat::config_string($options{"hide_merged_buffers"}) eq "private" )
+        {
+            # buffer type "private" or merged with core?
+            if ( ($buffer->{"type"} eq "private" or $buffer->{"plugin_name"} eq "core") && (! $buffer->{"active"}) )
+            {
+                next;
+            }
+        }
+        if ( weechat::config_string($options{"hide_merged_buffers"}) eq "keepserver" )
+        {
+            if ( ($buffer->{"type"} ne "server" or $buffer->{"plugin_name"} eq "core") && (! $buffer->{"active"}) )
+            {
+                next;
+            }
+        }
+        if ( weechat::config_string($options{"hide_merged_buffers"}) eq "all" )
+        {
+            if ( ! $buffer->{"active"} )
+            {
+                next;
+            }
+        }
+
+        push(@buffers_focus, $buffer);                                          # buffer > buffers_focus, for mouse support
+        my $color = "";
+        my $bg = "";
+
+        $color = weechat::config_color( $options{"color_default_fg"} );
+        $bg = weechat::config_color( $options{"color_default_bg"} );
+
+        if ( weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") eq "private" )
+        {
+            if ( (weechat::config_color($options{"queries_default_bg"})) ne "default" || (weechat::config_color($options{"queries_default_fg"})) ne "default" )
+            {
+              $bg = weechat::config_color( $options{"queries_default_bg"} );
+              $color = weechat::config_color( $options{"queries_default_fg"} );
+            }
+        }
+        # check for core and buffer with free content
+        if ( (weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") ne "channel" ) and ( weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") ne "private") )
+        {
+            $color = weechat::config_color( $options{"color_none_channel_fg"} );
+            $bg = weechat::config_color( $options{"color_none_channel_bg"} );
+        }
+        # default whitelist buffer?
+        if (grep {$_ eq $buffer->{"name"}} @whitelist_buffers)
+        {
+                $color = weechat::config_color( $options{"color_whitelist_default_fg"} );
+                $bg = weechat::config_color( $options{"color_whitelist_default_bg"} );
+        }
+
+        $color = "default" if ($color eq "");
+
+        # color for channel and query buffer
+        if (exists $hotlist{$buffer->{"pointer"}})
+        {
+        delete $buffers_timer{$buffer->{"pointer"}};
+            # check if buffer is in whitelist buffer
+            if (grep {$_ eq $buffer->{"name"}} @whitelist_buffers)
+            {
+                $bg = weechat::config_color( $options{"color_whitelist_".$hotlist_level{$hotlist{$buffer->{"pointer"}}}."_bg"} );
+                $color = weechat::config_color( $options{"color_whitelist_".$hotlist_level{$hotlist{$buffer->{"pointer"}}}."_fg"} );
+            }
+            elsif ( weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") eq "private" )
+            {
+                # queries_default_fg/bg and buffers.color.queries_message_fg/bg
+                if ( (weechat::config_color($options{"queries_highlight_fg"})) ne "default" ||
+                      (weechat::config_color($options{"queries_highlight_bg"})) ne "default" ||
+                       (weechat::config_color($options{"queries_message_fg"})) ne "default" ||
+                        (weechat::config_color($options{"queries_message_bg"})) ne "default" )
+                {
+                  if ( ($hotlist{$buffer->{"pointer"}}) == 2 )
+                  {
+                      $bg = weechat::config_color( $options{"queries_message_bg"} );
+                      $color = weechat::config_color( $options{"queries_message_fg"} );
+                  }
+
+                  elsif ( ($hotlist{$buffer->{"pointer"}}) == 3 )
+                  {
+                      $bg = weechat::config_color( $options{"queries_highlight_bg"} );
+                      $color = weechat::config_color( $options{"queries_highlight_fg"} );
+                  }
+                }else
+                {
+                      $bg = weechat::config_color( $options{"color_hotlist_".$hotlist_level{$hotlist{$buffer->{"pointer"}}}."_bg"} );
+                      $color = weechat::config_color( $options{"color_hotlist_".$hotlist_level{$hotlist{$buffer->{"pointer"}}}."_fg"}  );
+                }
+            }else
+            {
+                      $bg = weechat::config_color( $options{"color_hotlist_".$hotlist_level{$hotlist{$buffer->{"pointer"}}}."_bg"} );
+                      $color = weechat::config_color( $options{"color_hotlist_".$hotlist_level{$hotlist{$buffer->{"pointer"}}}."_fg"}  );
+            }
+        }
+
+        if ($buffer->{"current_buffer"})
+        {
+            $color = weechat::config_color( $options{"color_current_fg"} );
+            $bg = weechat::config_color( $options{"color_current_bg"} );
+        }
+        my $color_bg = "";
+        $color_bg = weechat::color(",".$bg) if ($bg ne "");
+
+        # create channel number for output
+        if ( weechat::config_string( $options{"show_prefix_bufname"} ) ne "" )
+        {
+            $str .= $color_bg .
+                    weechat::color( weechat::config_color( $options{"color_prefix_bufname"} ) ).
+                    weechat::config_string( $options{"show_prefix_bufname"} ).
+                    weechat::color("default");
+        }
+
+        if ( weechat::config_boolean( $options{"show_number"} ) eq 1 )   # on
+        {
+            if (( weechat::config_boolean( $options{"indenting_number"} ) eq 1)
+                && (($position eq "left") || ($position eq "right")))
+            {
+                $str .= weechat::color("default").$color_bg
+                    .(" " x ($max_number_digits - length(int($buffer->{"number"}))));
+            }
+            if ($old_number ne $buffer->{"number"})
+            {
+                $str .= weechat::color( weechat::config_color( $options{"color_number"} ) )
+                    .$color_bg
+                    .$buffer->{"number"}
+                    .weechat::color("default")
+                    .$color_bg
+                    .weechat::color( weechat::config_color( $options{"color_number_char"} ) )
+                    .weechat::config_string( $options{"show_number_char"} )
+                    .$color_bg;
+            }
+            else
+            {
+                my $indent = "";
+                $indent = ((" " x length($buffer->{"number"}))." ") if (($position eq "left") || ($position eq "right"));
+                $str .= weechat::color("default")
+                    .$color_bg
+                    .$indent;
+            }
+        }
+
+        if (( weechat::config_integer( $options{"indenting"} ) ne 0 )            # indenting NOT off
+            && (($position eq "left") || ($position eq "right")))
+        {
+            my $type = weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type");
+            if (($type eq "channel") || ($type eq "private"))
+            {
+                if ( weechat::config_integer( $options{"indenting"} ) eq 1 )
+                {
+                    $str .= "  ";
+                }
+                elsif ( (weechat::config_integer($options{"indenting"}) eq 2) and (weechat::config_integer($options{"indenting_number"}) eq 0) )        #under_name
+                {
+                    if ( weechat::config_boolean( $options{"show_number"} ) eq 0 )
+                    {
+                      $str .= "  ";
+                    }else
+                    {
+                      $str .= ( (" " x ( $max_number_digits - length($buffer->{"number"}) ))." " );
+                    }
+                }
+            }
+        }
+
+        $str .= weechat::config_string( $options{"show_prefix_query"}) if (weechat::config_string( $options{"show_prefix_query"} ) ne "" and  $buffer->{"type"} eq "private");
+
+        if (weechat::config_boolean( $options{"show_prefix"} ) eq 1)
+        {
+            my $nickname = weechat::buffer_get_string($buffer->{"pointer"}, "localvar_nick");
+            if ($nickname ne "")
+            {
+                # with version >= 0.3.2, this infolist will return only nick
+                # with older versions, whole nicklist is returned for buffer, and this can be very slow
+                my $infolist_nick = weechat::infolist_get("nicklist", $buffer->{"pointer"}, "nick_".$nickname);
+                if ($infolist_nick ne "")
+                {
+                    while (weechat::infolist_next($infolist_nick))
+                    {
+                        if ((weechat::infolist_string($infolist_nick, "type") eq "nick")
+                            && (weechat::infolist_string($infolist_nick, "name") eq $nickname))
+                        {
+                            my $prefix = weechat::infolist_string($infolist_nick, "prefix");
+                            if (($prefix ne " ") or (weechat::config_boolean( $options{"show_prefix_empty"} ) eq 1))
+                            {
+                                # with version >= 0.3.5, it is now a color name (for older versions: option name with color)
+                                if (int($weechat_version) >= 0x00030500)
+                                {
+                                    $str .= weechat::color(weechat::infolist_string($infolist_nick, "prefix_color"));
+                                }
+                                else
+                                {
+                                    $str .= weechat::color(weechat::config_color(
+                                                               weechat::config_get(
+                                                                   weechat::infolist_string($infolist_nick, "prefix_color"))));
+                                }
+                                $str .= $prefix;
+                            }
+                            last;
+                        }
+                    }
+                    weechat::infolist_free($infolist_nick);
+                }
+            }
+        }
+        if ($buffer->{"type"} eq "channel" and weechat::config_boolean( $options{"mark_inactive"} ) eq 1 and $buffer->{"nicks_count"} == 0)
+        {
+            $str .= "(";
+        }
+
+        $str .= weechat::color($color) . weechat::color(",".$bg);
+
+        my $name = weechat::buffer_get_string($buffer->{"pointer"}, "localvar_custom_name");
+        if (not defined $name or $name eq "")
+        {
+            if (weechat::config_boolean( $options{"short_names"} ) eq 1) {
+                $name = $buffer->{"short_name"};
+            } else {
+                $name = $buffer->{"name"};
+            }
+        }
+
+        if (weechat::config_integer($options{"name_size_max"}) >= 1)                # check max_size of buffer name
+        {
+            $str .= encode("UTF-8", substr(decode("UTF-8", $name), 0, weechat::config_integer($options{"name_size_max"})));
+            $str .= weechat::color(weechat::config_color( $options{"color_number_char"})).weechat::config_string($options{"name_crop_suffix"}) if (length($name) > weechat::config_integer($options{"name_size_max"}));
+            $str .= add_inactive_parentless($buffer->{"type"}, $buffer->{"nicks_count"});
+            $str .= add_hotlist_count($buffer->{"pointer"}, %hotlist);
+        }
+        else
+        {
+            $str .= $name;
+            $str .= add_inactive_parentless($buffer->{"type"}, $buffer->{"nicks_count"});
+            $str .= add_hotlist_count($buffer->{"pointer"}, %hotlist);
+        }
+
+        if ( weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") eq "server" and weechat::config_boolean($options{"show_lag"}) eq 1)
+        {
+            my $color_lag = weechat::config_color(weechat::config_get("irc.color.item_lag_finished"));
+            my $min_lag = weechat::config_integer(weechat::config_get("irc.network.lag_min_show"));
+            my $infolist_server = weechat::infolist_get("irc_server", "", $buffer->{"short_name"});
+            weechat::infolist_next($infolist_server);
+            my $lag = (weechat::infolist_integer($infolist_server, "lag"));
+            weechat::infolist_free($infolist_server);
+            if ( int($lag) > int($min_lag) )
+            {
+                $lag = $lag / 1000;
+                $str .= weechat::color("default") . " (" . weechat::color($color_lag) . $lag . weechat::color("default") . ")";
+            }
+        }
+        if (weechat::config_boolean($options{"detach_displayed_buffers"}) eq 0
+            and weechat::config_boolean($options{"detach_display_window_number"}) eq 1)
+        {
+            if ($buffer->{"window"})
+            {
+                $str .= weechat::color("default") . " (" . weechat::color(weechat::config_color( $options{"color_number"})) . $buffer->{"window"} . weechat::color("default") . ")";
+            }
+        }
+        $str .= weechat::color("default");
+
+        if ( weechat::config_string( $options{"show_suffix_bufname"} ) ne "" )
+        {
+            $str .= weechat::color( weechat::config_color( $options{"color_suffix_bufname"} ) ).
+                    weechat::config_string( $options{"show_suffix_bufname"} ).
+                    weechat::color("default");
+        }
+
+        $str .= "\n";
+        $old_number = $buffer->{"number"};
+    }
+
+    # remove spaces and/or linefeed at the end
+    $str =~ s/\s+$//;
+    chomp($str);
+    return $str;
+}
+
+sub add_inactive_parentless
+{
+my ($buf_type, $buf_nicks_count) = @_;
+my $str = "";
+    if ($buf_type eq "channel" and weechat::config_boolean( $options{"mark_inactive"} ) eq 1 and $buf_nicks_count == 0)
+    {
+        $str .= weechat::color(weechat::config_color( $options{"color_number_char"}));
+        $str .= ")";
+    }
+return $str;
+}
+
+sub add_hotlist_count
+{
+my ($bufpointer, %hotlist) = @_;
+
+return "" if ( weechat::config_boolean( $options{"hotlist_counter"} ) eq 0 or ($weechat_version < 0x00030500));   # off
+my $col_number_char = weechat::color(weechat::config_color( $options{"color_number_char"}) );
+my $str = " ".$col_number_char."(";
+
+# 0 = low level
+if (defined $hotlist{$bufpointer."_count_00"})
+{
+    my $bg = weechat::config_color( $options{"color_hotlist_low_bg"} );
+    my $color = weechat::config_color( $options{"color_hotlist_low_fg"} );
+    $str .= weechat::color($bg).
+            weechat::color($color).
+            $hotlist{$bufpointer."_count_00"} if ($hotlist{$bufpointer."_count_00"} ne "0");
+}
+
+# 1 = message
+if (defined $hotlist{$bufpointer."_count_01"})
+{
+    my $bg = weechat::config_color( $options{"color_hotlist_message_bg"} );
+    my $color = weechat::config_color( $options{"color_hotlist_message_fg"} );
+    if ($str =~ /[0-9]$/)
+    {
+        $str .= ",".
+                weechat::color($bg).
+                weechat::color($color).
+                $hotlist{$bufpointer."_count_01"} if ($hotlist{$bufpointer."_count_01"} ne "0");
+    }else
+    {
+        $str .= weechat::color($bg).
+                weechat::color($color).
+                $hotlist{$bufpointer."_count_01"} if ($hotlist{$bufpointer."_count_01"} ne "0");
+    }
+}
+# 2 = private
+if (defined $hotlist{$bufpointer."_count_02"})
+{
+    my $bg = weechat::config_color( $options{"color_hotlist_private_bg"} );
+    my $color = weechat::config_color( $options{"color_hotlist_private_fg"} );
+    if ($str =~ /[0-9]$/)
+    {
+        $str .= ",".
+                weechat::color($bg).
+                weechat::color($color).
+                $hotlist{$bufpointer."_count_02"} if ($hotlist{$bufpointer."_count_02"} ne "0");
+    }else
+    {
+        $str .= weechat::color($bg).
+                weechat::color($color).
+                $hotlist{$bufpointer."_count_02"} if ($hotlist{$bufpointer."_count_02"} ne "0");
+    }
+}
+# 3 = highlight
+if (defined $hotlist{$bufpointer."_count_03"})
+{
+    my $bg = weechat::config_color( $options{"color_hotlist_highlight_bg"} );
+    my $color = weechat::config_color( $options{"color_hotlist_highlight_fg"} );
+    if ($str =~ /[0-9]$/)
+    {
+        $str .= ",".
+                weechat::color($bg).
+                weechat::color($color).
+                $hotlist{$bufpointer."_count_03"} if ($hotlist{$bufpointer."_count_03"} ne "0");
+    }else
+    {
+        $str .= weechat::color($bg).
+                weechat::color($color).
+                $hotlist{$bufpointer."_count_03"} if ($hotlist{$bufpointer."_count_03"} ne "0");
+    }
+}
+$str .= $col_number_char. ")";
+
+$str = "" if (weechat::string_remove_color($str, "") eq " ()");         # remove color and check for buffer with no messages
+return $str;
+}
+
+sub buffers_signal_buffer
+{
+    my ($data, $signal, $signal_data) = @_;
+
+    # check for buffer_switch and set or remove detach time
+    if ($weechat_version >= 0x00030800)
+    {
+        if ($signal eq "buffer_switch")
+        {
+            my $pointer = weechat::hdata_get_list (weechat::hdata_get("buffer"), "gui_buffer_last_displayed"); # get switched buffer
+            my $current_time = time();
+            if ( weechat::buffer_get_string($pointer, "localvar_type") eq "channel")
+            {
+                $buffers_timer{$pointer} = $current_time;
+            }
+            else
+            {
+                delete $buffers_timer{$pointer};
+            }
+        }
+        if ($signal eq "buffer_opened")
+        {
+            my $current_time = time();
+            $buffers_timer{$signal_data} = $current_time;
+        }
+        if ($signal eq "buffer_closing")
+        {
+            delete $buffers_timer{$signal_data};
+        }
+    }
+    weechat::bar_item_update($SCRIPT_NAME);
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub buffers_signal_hotlist
+{
+    weechat::bar_item_update($SCRIPT_NAME);
+    return weechat::WEECHAT_RC_OK;
+}
+
+
+sub buffers_signal_config_whitelist
+{
+    @whitelist_buffers = ();
+    @whitelist_buffers = split( /,/, weechat::config_string( $options{"look_whitelist_buffers"} ) );
+    weechat::bar_item_update($SCRIPT_NAME);
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub buffers_signal_config_immune_detach_buffers
+{
+    @immune_detach_buffers = ();
+    @immune_detach_buffers = split( /,/, weechat::config_string( $options{"immune_detach_buffers"} ) );
+    weechat::bar_item_update($SCRIPT_NAME);
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub buffers_signal_config_detach_buffer_immediately
+{
+    @detach_buffer_immediately = ();
+    @detach_buffer_immediately = split( /,/, weechat::config_string( $options{"detach_buffer_immediately"} ) );
+    weechat::bar_item_update($SCRIPT_NAME);
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub buffers_signal_config
+{
+    weechat::bar_item_update($SCRIPT_NAME);
+    return weechat::WEECHAT_RC_OK;
+}
+
+# called when mouse click occured in buffers item: this callback returns buffer
+# hash according to line of item where click occured
+sub buffers_focus_buffers
+{
+    my %info = %{$_[1]};
+    my $item_line = int($info{"_bar_item_line"});
+    undef my $hash;
+    if (($info{"_bar_item_name"} eq $SCRIPT_NAME) && ($item_line >= 0) && ($item_line <= $#buffers_focus))
+    {
+        $hash = $buffers_focus[$item_line];
+    }
+    else
+    {
+        $hash = {};
+        my $hash_focus = $buffers_focus[0];
+        foreach my $key (keys %$hash_focus)
+        {
+            $hash->{$key} = "?";
+        }
+    }
+    return $hash;
+}
+
+# called when a mouse action is done on buffers item, to execute action
+# possible actions: jump to a buffer or move buffer in list (drag & drop of buffer)
+sub buffers_hsignal_mouse
+{
+    my ($data, $signal, %hash) = ($_[0], $_[1], %{$_[2]});
+    my $current_buffer = weechat::buffer_get_integer(weechat::current_buffer(), "number"); # get current buffer number
+
+    if ( $hash{"_key"} eq "button1" )
+    {
+        # left mouse button
+        if ($hash{"number"} eq $hash{"number2"})
+        {
+            if ( weechat::config_boolean($options{"jump_prev_next_visited_buffer"}) )
+            {
+                if ( $current_buffer eq $hash{"number"} )
+                {
+                    weechat::command("", "/input jump_previously_visited_buffer");
+                }
+                else
+                {
+                    weechat::command("", "/buffer ".$hash{"full_name"});
+                }
+            }
+            else
+            {
+                weechat::command("", "/buffer ".$hash{"full_name"});
+            }
+        }
+        else
+        {
+            move_buffer(%hash) if (weechat::config_boolean($options{"mouse_move_buffer"}));
+        }
+    }
+    elsif ( ($hash{"_key"} eq "button2") && (weechat::config_boolean($options{"jump_prev_next_visited_buffer"})) )
+    {
+        # right mouse button
+        if ( $current_buffer eq $hash{"number2"} )
+        {
+            weechat::command("", "/input jump_next_visited_buffer");
+        }
+    }
+    elsif ( $hash{"_key"} =~ /wheelup$/ )
+    {
+        # wheel up
+        if (weechat::config_boolean($options{"mouse_wheel"}))
+        {
+            weechat::command("", "/buffer -1");
+        }
+    }
+    elsif ( $hash{"_key"} =~ /wheeldown$/ )
+    {
+        # wheel down
+        if (weechat::config_boolean($options{"mouse_wheel"}))
+        {
+            weechat::command("", "/buffer +1");
+        }
+    }
+    else
+    {
+        my $infolist = weechat::infolist_get("hook", "", "command,menu");
+        my $has_menu_command = weechat::infolist_next($infolist);
+        weechat::infolist_free($infolist);
+
+        if ( $has_menu_command && $hash{"_key"} =~ /button2/ )
+        {
+            if ($hash{"number"} eq $hash{"number2"})
+            {
+                weechat::command($hash{"pointer"}, "/menu buffer1 $hash{short_name} $hash{number}");
+            }
+            else
+            {
+                weechat::command($hash{"pointer"}, "/menu buffer2 $hash{short_name}/$hash{short_name2} $hash{number} $hash{number2}")
+            }
+        }
+        else
+        {
+            move_buffer(%hash) if (weechat::config_boolean($options{"mouse_move_buffer"}));
+        }
+    }
+}
+
+sub move_buffer
+{
+  my %hash = @_;
+  my $number2 = $hash{"number2"};
+  if ($number2 eq "?")
+  {
+      # if number 2 is not known (end of gesture outside buffers list), then set it
+      # according to mouse gesture
+      $number2 = "1";
+      if (($hash{"_key"} =~ /gesture-right/) || ($hash{"_key"} =~ /gesture-down/))
+      {
+          $number2 = "999999";
+          if ($weechat_version >= 0x00030600)
+          {
+              my $hdata_buffer = weechat::hdata_get("buffer");
+              my $last_gui_buffer = weechat::hdata_get_list($hdata_buffer, "last_gui_buffer");
+              if ($last_gui_buffer)
+              {
+                  $number2 = weechat::hdata_integer($hdata_buffer, $last_gui_buffer, "number") + 1;
+              }
+          }
+      }
+  }
+  my $ptrbuf = weechat::current_buffer();
+  weechat::command($hash{"pointer"}, "/buffer move ".$number2);
+}
+
+sub check_immune_detached_buffers
+{
+    my ($buffername) = @_;
+    foreach ( @immune_detach_buffers ){
+        my $immune_buffer = weechat::string_mask_to_regex($_);
+        if ($buffername =~ /^$immune_buffer$/i)
+        {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+sub check_detach_buffer_immediately
+{
+    my ($buffername) = @_;
+    foreach ( @detach_buffer_immediately ){
+        my $detach_buffer = weechat::string_mask_to_regex($_);
+        if ($buffername =~ /^$detach_buffer$/i)
+        {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+sub shutdown_cb
+{
+    weechat::command("", "/bar hide " . $SCRIPT_NAME) if ( weechat::config_boolean($options{"toggle_bar"}) eq 1 );
+    return weechat::WEECHAT_RC_OK
+}
+
+sub check_bar_item
+{
+    my $item = 0;
+    my $infolist = weechat::infolist_get("bar", "", "");
+    while (weechat::infolist_next($infolist))
+    {
+        my $bar_items = weechat::infolist_string($infolist, "items");
+        if (index($bar_items, $SCRIPT_NAME) != -1)
+        {
+            my $name = weechat::infolist_string($infolist, "name");
+            if ($name ne $SCRIPT_NAME)
+            {
+                $item = 1;
+                last;
+            }
+        }
+    }
+    weechat::infolist_free($infolist);
+    return $item;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/weechat/perl/iset.pl	Wed Nov 19 19:24:17 2014 +0100
@@ -0,0 +1,1462 @@
+#
+# Copyright (C) 2008-2014 Sebastien Helleu <[email protected]>
+# Copyright (C) 2010-2014 Nils Görs <[email protected]>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Set WeeChat and plugins options interactively.
+#
+# History:
+#
+# 2014-09-30, arza <[email protected]>:
+#     version 3.6: fix current line counter when options aren't found
+# 2014-06-03, nils_2 <[email protected]>:
+#     version 3.5: add new option "use_mute"
+# 2014-01-30, stfn <[email protected]>:
+#     version 3.4: add new options "color_value_diff" and "color_value_diff_selected"
+# 2014-01-16, luz <[email protected]>:
+#     version 3.3: fix bug with column alignment in iset buffer when option
+#                  name contains unicode characters
+# 2013-08-03, Sebastien Helleu <[email protected]>:
+#     version 3.2: allow "q" as input in iset buffer to close it
+# 2013-07-14, Sebastien Helleu <[email protected]>:
+#     version 3.1: remove unneeded calls to iset_refresh() in mouse callback
+#                  (faster mouse actions when lot of options are displayed),
+#                  fix bug when clicking on a line after the last option displayed
+# 2013-04-30, arza <[email protected]>:
+#     version 3.0: simpler title, fix refresh on unset
+# 2012-12-16, nils_2 <[email protected]>:
+#     version 2.9: fix focus window with iset buffer on mouse click
+# 2012-08-25, nils_2 <[email protected]>:
+#     version 2.8: most important key and mouse bindings for iset buffer added to title-bar (idea The-Compiler)
+# 2012-07-31, nils_2 <[email protected]>:
+#     version 2.7: add combined option and value search (see /help iset)
+#                : add exact value search (see /help iset)
+#                : fix problem with metacharacter in value search
+#                : fix use of uninitialized value for unset option and reset value of option
+# 2012-07-25, nils_2 <[email protected]>:
+#     version 2.6: switch to iset buffer (if existing) when command /iset is called with arguments
+# 2012-03-17, Sebastien Helleu <[email protected]>:
+#     version 2.5: fix check of sections when creating config file
+# 2012-03-09, Sebastien Helleu <[email protected]>:
+#     version 2.4: fix reload of config file
+# 2012-02-02, nils_2 <[email protected]>:
+#     version 2.3: fixed: refresh problem with new search results and cursor was outside window.
+#                : add: new option "current_line" in title bar
+#     version 2.2: fixed: refresh error when toggling plugins description
+# 2011-11-05, nils_2 <[email protected]>:
+#     version 2.1: use own config file (iset.conf), fix own help color (used immediately)
+# 2011-10-16, nils_2 <[email protected]>:
+#     version 2.0: add support for left-mouse-button and more sensitive mouse gesture (for integer/color options)
+#                  add help text for mouse support
+# 2011-09-20, Sebastien Helleu <[email protected]>:
+#     version 1.9: add mouse support, fix iset buffer, fix errors on first load under FreeBSD
+# 2011-07-21, nils_2 <[email protected]>:
+#     version 1.8: added: option "show_plugin_description" (alt+p)
+#                  fixed: typos in /help iset (lower case for alt+'x' keys)
+# 2011-05-29, nils_2 <[email protected]>:
+#     version 1.7: added: version check for future needs
+#                  added: new option (scroll_horiz) and usage of scroll_horiz function (weechat >= 0.3.6 required)
+#                  fixed: help_bar did not pop up immediately using key-shortcut
+# 2011-02-19, nils_2 <[email protected]>:
+#     version 1.6: added: display of all possible values in help bar (show_help_extra_info)
+#                  fixed: external user options never loaded when starting iset first time
+# 2011-02-13, Sebastien Helleu <[email protected]>:
+#     version 1.5: use new help format for command arguments
+# 2011-02-03, nils_2 <[email protected]>:
+#     version 1.4: fixed: restore value filter after /upgrade using buffer local variable.
+# 2011-01-14, nils_2 <[email protected]>:
+#     version 1.3: added function to search for values (option value_search_char).
+#                  code optimization.
+# 2010-12-26, Sebastien Helleu <[email protected]>:
+#     version 1.2: improve speed of /upgrade when iset buffer is open,
+#                  restore filter used after /upgrade using buffer local variable,
+#                  use /iset filter argument if buffer is open.
+# 2010-11-21, drubin <[email protected]>:
+#     version 1.1.1: fix bugs with cursor position
+# 2010-11-20, nils_2 <[email protected]>:
+#     version 1.1: cursor position set to value
+# 2010-08-03, Sebastien Helleu <[email protected]>:
+#     version 1.0: move misplaced call to infolist_free()
+# 2010-02-02, rettub <[email protected]>:
+#     version 0.9: turn all the help stuff off if option 'show_help_bar' is 'off',
+#                  new key binding <alt>-<v> to toggle help_bar and help stuff on/off
+# 2010-01-30, nils_2 <[email protected]>:
+#     version 0.8: fix error when option does not exist
+# 2010-01-24, Sebastien Helleu <[email protected]>:
+#     version 0.7: display iset bar only on iset buffer
+# 2010-01-22, nils_2 <[email protected]> and drubin:
+#     version 0.6: add description in a bar, fix singular/plural bug in title bar,
+#                  fix selected line when switching buffer
+# 2009-06-21, Sebastien Helleu <[email protected]>:
+#     version 0.5: fix bug with iset buffer after /upgrade
+# 2009-05-02, Sebastien Helleu <[email protected]>:
+#     version 0.4: sync with last API changes
+# 2009-01-04, Sebastien Helleu <[email protected]>:
+#     version 0.3: open iset buffer when /iset command is executed
+# 2009-01-04, Sebastien Helleu <[email protected]>:
+#     version 0.2: use null values for options, add colors, fix refresh bugs,
+#                  use new keys to reset/unset options, sort options by name,
+#                  display number of options in buffer's title
+# 2008-11-05, Sebastien Helleu <[email protected]>:
+#     version 0.1: first official version
+# 2008-04-19, Sebastien Helleu <[email protected]>:
+#     script creation
+
+use strict;
+
+my $PRGNAME = "iset";
+my $VERSION = "3.6";
+my $DESCR   = "Interactive Set for configuration options";
+my $AUTHOR  = "Sebastien Helleu <flashcode\@flashtux.org>";
+my $LICENSE = "GPL3";
+my $LANG    = "perl";
+my $ISET_CONFIG_FILE_NAME = "iset";
+
+my $iset_config_file;
+my $iset_buffer = "";
+my $wee_version_number = 0;
+my @iset_focus = ();
+my @options_names = ();
+my @options_types = ();
+my @options_values = ();
+my @options_default_values = ();
+my @options_is_null = ();
+my $option_max_length = 0;
+my $current_line = 0;
+my $filter = "*";
+my $description = "";
+my $options_name_copy = "";
+my $iset_filter_title = "";
+# search modes: 0 = index() on value, 1 = grep() on value, 2 = grep() on option, 3 = grep on option & value
+my $search_mode = 2;
+my $search_value = "";
+my $help_text_keys = "alt + space: toggle, +/-: increase/decrease, enter: change, ir: reset, iu: unset, v: toggle help bar";
+my $help_text_mouse = "Mouse: left: select, right: toggle/set, right + drag left/right: increase/decrease";
+my %options_iset;
+
+my %mouse_keys = ("\@chat(perl.$PRGNAME):button1" => "hsignal:iset_mouse",
+                  "\@chat(perl.$PRGNAME):button2*" => "hsignal:iset_mouse",
+                  "\@chat(perl.$PRGNAME):wheelup" => "/repeat 5 /iset **up",
+                  "\@chat(perl.$PRGNAME):wheeldown" => "/repeat 5 /iset **down");
+
+
+sub iset_title
+{
+    if ($iset_buffer ne "")
+    {
+        my $current_line_counter = "";
+        if (weechat::config_boolean($options_iset{"show_current_line"}) == 1)
+        {
+            if (@options_names eq 0)
+            {
+                $current_line_counter = "0/";
+            }
+            else
+            {
+                $current_line_counter = ($current_line + 1) . "/";
+            }
+        }
+        my $show_filter = "";
+        if ($search_mode eq 0)
+        {
+            $iset_filter_title = "(value) ";
+            $show_filter = $search_value;
+            if ( substr($show_filter,0,1) eq weechat::config_string($options_iset{"value_search_char"}) )
+            {
+                $show_filter = substr($show_filter,1,length($show_filter));
+            }
+        }
+        elsif ($search_mode eq 1)
+        {
+            $iset_filter_title = "(value) ";
+            $show_filter = "*".$search_value."*";
+        }
+        elsif ($search_mode eq 2)
+        {
+            $iset_filter_title = "";
+            $filter = "*" if ($filter eq "");
+            $show_filter = $filter;
+        }
+        elsif ($search_mode eq 3)
+        {
+            $iset_filter_title = "(option) ";
+            $show_filter = $filter
+                            .weechat::color("default")
+                            ." / (value) "
+                            .weechat::color("yellow")
+                            ."*".$search_value."*";
+        }
+        weechat::buffer_set($iset_buffer, "title",
+                             $iset_filter_title
+                            .weechat::color("yellow")
+                            .$show_filter
+                            .weechat::color("default")." | "
+                            .$current_line_counter
+                            .@options_names
+                            ." | "
+                            .$help_text_keys
+                            ." | "
+                            .$help_text_mouse);
+    }
+}
+
+sub iset_create_filter
+{
+    $filter = $_[0];
+    if ( $search_mode == 3 )
+    {
+        my @cmd_array = split(/ /,$filter);
+        my $array_count = @cmd_array;
+        $filter = $cmd_array[0];
+        $filter = $cmd_array[0] . " " . $cmd_array[1] if ( $array_count >2 );
+    }
+    $filter = "$1.*" if ($filter =~ /f (.*)/); # search file
+    $filter = "*.$1.*" if ($filter =~ /s (.*)/); # search section
+    if ((substr($filter, 0, 1) ne "*") && (substr($filter, -1, 1) ne "*"))
+    {
+        $filter = "*".$filter."*";
+    }
+    if ($iset_buffer ne "")
+    {
+        weechat::buffer_set($iset_buffer, "localvar_set_iset_filter", $filter);
+    }
+}
+
+sub iset_buffer_input
+{
+    my ($data, $buffer, $string) = ($_[0], $_[1], $_[2]);
+    if ($string eq "q")
+    {
+        weechat::buffer_close($buffer);
+        return weechat::WEECHAT_RC_OK;
+    }
+    $search_value = "";
+    my @cmd_array = split(/ /,$string);
+    my $array_count = @cmd_array;
+    my $string2 = substr($string, 0, 1);
+    if ($string2 eq weechat::config_string($options_iset{"value_search_char"})
+    or (defined $cmd_array[0] and $cmd_array[0] eq weechat::config_string($options_iset{"value_search_char"}).weechat::config_string($options_iset{"value_search_char"})) )
+    {
+        $search_mode = 1;
+        $search_value = substr($string, 1);
+        iset_get_values($search_value);
+        if ($iset_buffer ne "")
+        {
+            weechat::buffer_set($iset_buffer, "localvar_set_iset_search_value", $search_value);
+        }
+    }
+    else
+    {
+        $search_mode = 2;
+        if ( $array_count >= 2 and $cmd_array[0] ne "f" or $cmd_array[0] ne "s")
+        {
+            if ( defined $cmd_array[1] and substr($cmd_array[1], 0, 1) eq weechat::config_string($options_iset{"value_search_char"})
+            or defined $cmd_array[2] and substr($cmd_array[2], 0, 1) eq weechat::config_string($options_iset{"value_search_char"}) )
+            {
+                $search_mode = 3;
+                $search_value = substr($cmd_array[1], 1);  # cut value_search_char
+                $search_value = substr($cmd_array[2], 1) if ( $array_count > 2);  # cut value_search_char
+            }
+        }
+        if ( $search_mode == 3)
+        {
+            iset_create_filter($string);
+            iset_get_options($search_value);
+        }else
+        {
+            iset_create_filter($string);
+            iset_get_options("");
+        }
+    }
+    weechat::buffer_set($iset_buffer, "localvar_set_iset_search_mode", $search_mode);
+    weechat::buffer_clear($buffer);
+    $current_line = 0;
+    iset_refresh();
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub iset_buffer_close
+{
+    $iset_buffer = "";
+
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub iset_init
+{
+    $current_line = 0;
+    $iset_buffer = weechat::buffer_search($LANG, $PRGNAME);
+    if ($iset_buffer eq "")
+    {
+        $iset_buffer = weechat::buffer_new($PRGNAME, "iset_buffer_input", "", "iset_buffer_close", "");
+    }
+    else
+    {
+        my $new_filter = weechat::buffer_get_string($iset_buffer, "localvar_iset_filter");
+        $search_mode = weechat::buffer_get_string($iset_buffer, "localvar_iset_search_mode");
+        $search_value = weechat::buffer_get_string($iset_buffer, "localvar_iset_search_value");
+        $filter = $new_filter if ($new_filter ne "");
+    }
+    if ($iset_buffer ne "")
+    {
+        weechat::buffer_set($iset_buffer, "type", "free");
+        iset_title();
+        weechat::buffer_set($iset_buffer, "key_bind_ctrl-L",        "/iset **refresh");
+        weechat::buffer_set($iset_buffer, "key_bind_meta2-A",       "/iset **up");
+        weechat::buffer_set($iset_buffer, "key_bind_meta2-B",       "/iset **down");
+        weechat::buffer_set($iset_buffer, "key_bind_meta2-23~",     "/iset **left");
+        weechat::buffer_set($iset_buffer, "key_bind_meta2-24~" ,    "/iset **right");
+        weechat::buffer_set($iset_buffer, "key_bind_meta- ",        "/iset **toggle");
+        weechat::buffer_set($iset_buffer, "key_bind_meta-+",        "/iset **incr");
+        weechat::buffer_set($iset_buffer, "key_bind_meta--",        "/iset **decr");
+        weechat::buffer_set($iset_buffer, "key_bind_meta-imeta-r",  "/iset **reset");
+        weechat::buffer_set($iset_buffer, "key_bind_meta-imeta-u",  "/iset **unset");
+        weechat::buffer_set($iset_buffer, "key_bind_meta-ctrl-J",   "/iset **set");
+        weechat::buffer_set($iset_buffer, "key_bind_meta-ctrl-M",   "/iset **set");
+        weechat::buffer_set($iset_buffer, "key_bind_meta-meta2-1~", "/iset **scroll_top");
+        weechat::buffer_set($iset_buffer, "key_bind_meta-meta2-4~", "/iset **scroll_bottom");
+        weechat::buffer_set($iset_buffer, "key_bind_meta-v",        "/iset **toggle_help");
+        weechat::buffer_set($iset_buffer, "key_bind_meta-p",        "/iset **toggle_show_plugin_desc");
+        weechat::buffer_set($iset_buffer, "localvar_set_iset_filter", $filter);
+        weechat::buffer_set($iset_buffer, "localvar_set_iset_search_mode", $search_mode);
+        weechat::buffer_set($iset_buffer, "localvar_set_iset_search_value", $search_value);
+    }
+}
+
+sub iset_get_options
+{
+    my $var_value = $_[0];
+    $var_value = "" if (not defined $var_value);
+    $var_value = lc($var_value);
+    $search_value = $var_value;
+    @iset_focus = ();
+    @options_names = ();
+    @options_types = ();
+    @options_values = ();
+    @options_default_values = ();
+    @options_is_null = ();
+    $option_max_length = 0;
+    my %options_internal = ();
+    my $i = 0;
+    my $key;
+    my $iset_struct;
+    my %iset_struct;
+
+    weechat::buffer_set($iset_buffer, "localvar_set_iset_search_value", $var_value) if ($search_mode == 3);
+
+    my $infolist = weechat::infolist_get("option", "", $filter);
+    while (weechat::infolist_next($infolist))
+    {
+        $key = sprintf("%08d", $i);
+        my $name = weechat::infolist_string($infolist, "full_name");
+        next if (weechat::config_boolean($options_iset{"show_plugin_description"}) == 0 and index ($name, "plugins.desc.") != -1);
+        my $type = weechat::infolist_string($infolist, "type");
+        my $value = weechat::infolist_string($infolist, "value");
+        my $default_value = weechat::infolist_string($infolist, "default_value");
+        my $is_null = weechat::infolist_integer($infolist, "value_is_null");
+        if ($search_mode == 3)
+        {
+            my $value = weechat::infolist_string($infolist, "value");
+            if ( grep /\Q$var_value/,lc($value) )
+            {
+                $options_internal{$name}{"type"} = $type;
+                $options_internal{$name}{"value"} = $value;
+                $options_internal{$name}{"default_value"} = $default_value;
+                $options_internal{$name}{"is_null"} = $is_null;
+                $option_max_length = length($name) if (length($name) > $option_max_length);
+        $iset_struct{$key} = $options_internal{$name};
+        push(@iset_focus, $iset_struct{$key});
+            }
+        }
+        else
+        {
+            $options_internal{$name}{"type"} = $type;
+            $options_internal{$name}{"value"} = $value;
+            $options_internal{$name}{"default_value"} = $default_value;
+            $options_internal{$name}{"is_null"} = $is_null;
+            $option_max_length = length($name) if (length($name) > $option_max_length);
+        $iset_struct{$key} = $options_internal{$name};
+        push(@iset_focus, $iset_struct{$key});
+        }
+        $i++;
+    }
+    weechat::infolist_free($infolist);
+
+    foreach my $name (sort keys %options_internal)
+    {
+        push(@options_names, $name);
+        push(@options_types, $options_internal{$name}{"type"});
+        push(@options_values, $options_internal{$name}{"value"});
+        push(@options_default_values, $options_internal{$name}{"default_value"});
+        push(@options_is_null, $options_internal{$name}{"is_null"});
+    }
+}
+
+sub iset_get_values
+{
+    my $var_value = $_[0];
+    $var_value = lc($var_value);
+    if (substr($var_value,0,1) eq weechat::config_string($options_iset{"value_search_char"}) and $var_value ne weechat::config_string($options_iset{"value_search_char"}))
+    {
+        $var_value = substr($var_value,1,length($var_value));
+        $search_mode = 0;
+    }
+    iset_search_values($var_value,$search_mode);
+    weechat::buffer_set($iset_buffer, "localvar_set_iset_search_mode", $search_mode);
+    weechat::buffer_set($iset_buffer, "localvar_set_iset_search_value", $var_value);
+    $search_value = $var_value;
+}
+sub iset_search_values
+{
+    my ($var_value,$search_mode) = ($_[0],$_[1]);
+    @options_names = ();
+    @options_types = ();
+    @options_values = ();
+    @options_default_values = ();
+    @options_is_null = ();
+    $option_max_length = 0;
+    my %options_internal = ();
+    my $i = 0;
+    my $infolist = weechat::infolist_get("option", "", "*");
+    while (weechat::infolist_next($infolist))
+    {
+        my $name = weechat::infolist_string($infolist, "full_name");
+        next if (weechat::config_boolean($options_iset{"show_plugin_description"}) == 0 and index ($name, "plugins.desc.") != -1);
+        my $type = weechat::infolist_string($infolist, "type");
+        my $is_null = weechat::infolist_integer($infolist, "value_is_null");
+        my $value = weechat::infolist_string($infolist, "value");
+        my $default_value = weechat::infolist_string($infolist, "default_value");
+        if ($search_mode)
+        {
+            if ( grep /\Q$var_value/,lc($value) )
+            {
+                $options_internal{$name}{"type"} = $type;
+                $options_internal{$name}{"value"} = $value;
+                $options_internal{$name}{"default_value"} = $default_value;
+                $options_internal{$name}{"is_null"} = $is_null;
+                $option_max_length = length($name) if (length($name) > $option_max_length);
+            }
+        }
+        else
+        {
+#            if ($value =~ /\Q$var_value/si)
+            if (lc($value) eq $var_value)
+            {
+                $options_internal{$name}{"type"} = $type;
+                $options_internal{$name}{"value"} = $value;
+                $options_internal{$name}{"default_value"} = $default_value;
+                $options_internal{$name}{"is_null"} = $is_null;
+                $option_max_length = length($name) if (length($name) > $option_max_length);
+            }
+        }
+        $i++;
+    }
+    weechat::infolist_free($infolist);
+    foreach my $name (sort keys %options_internal)
+    {
+        push(@options_names, $name);
+        push(@options_types, $options_internal{$name}{"type"});
+        push(@options_values, $options_internal{$name}{"value"});
+        push(@options_default_values, $options_internal{$name}{"default_value"});
+        push(@options_is_null, $options_internal{$name}{"is_null"});
+    }
+}
+
+sub iset_refresh_line
+{
+    if ($iset_buffer ne "")
+    {
+        my $y = $_[0];
+        if ($y <= $#options_names)
+        {
+            return if (! defined($options_types[$y]));
+            my $format = sprintf("%%s%%s%%s %%s %%-7s %%s %%s%%s%%s");
+            my $padding;
+            if ($wee_version_number >= 0x00040200)
+            {
+                $padding = " " x ($option_max_length - weechat::strlen_screen($options_names[$y]));
+            }
+            else
+            {
+                $padding = " " x ($option_max_length - length($options_names[$y]));
+            }
+            my $around = "";
+            $around = "\"" if ((!$options_is_null[$y]) && ($options_types[$y] eq "string"));
+
+            my $color1 = weechat::color(weechat::config_color($options_iset{"color_option"}));
+            my $color2 = weechat::color(weechat::config_color($options_iset{"color_type"}));
+            my $color3 = "";
+            if ($options_is_null[$y])
+            {
+                $color3 = weechat::color(weechat::config_color($options_iset{"color_value_undef"}));
+            }
+            elsif ($options_values[$y] ne $options_default_values[$y])
+            {
+                $color3 = weechat::color(weechat::config_color($options_iset{"color_value_diff"}));
+            }
+            else
+            {
+                $color3 = weechat::color(weechat::config_color($options_iset{"color_value"}));
+            }
+            if ($y == $current_line)
+            {
+                $color1 = weechat::color(weechat::config_color($options_iset{"color_option_selected"}).",".weechat::config_color($options_iset{"color_bg_selected"}));
+                $color2 = weechat::color(weechat::config_color($options_iset{"color_type_selected"}).",".weechat::config_color($options_iset{"color_bg_selected"}));
+                if ($options_is_null[$y])
+                {
+                    $color3 = weechat::color(weechat::config_color($options_iset{"color_value_undef_selected"}).",".weechat::config_color($options_iset{"color_bg_selected"}));
+                }
+                elsif ($options_values[$y] ne $options_default_values[$y])
+                {
+                    $color3 = weechat::color(weechat::config_color($options_iset{"color_value_diff_selected"}).",".weechat::config_color($options_iset{"color_bg_selected"}));
+                }
+                else
+                {
+                    $color3 = weechat::color(weechat::config_color($options_iset{"color_value_selected"}).",".weechat::config_color($options_iset{"color_bg_selected"}));
+                }
+            }
+            my $value = $options_values[$y];
+            $value = "(undef)" if ($options_is_null[$y]);
+            my $strline = sprintf($format,
+                                  $color1, $options_names[$y], $padding,
+                                  $color2, $options_types[$y],
+                                  $color3, $around, $value, $around);
+            weechat::print_y($iset_buffer, $y, $strline);
+        }
+    }
+}
+
+sub iset_refresh
+{
+    iset_title();
+    if (($iset_buffer ne "") && ($#options_names >= 0))
+    {
+        foreach my $y (0 .. $#options_names)
+        {
+            iset_refresh_line($y);
+        }
+    }
+
+    weechat::bar_item_update("isetbar_help") if (weechat::config_boolean($options_iset{"show_help_bar"}) == 1);
+}
+
+sub iset_full_refresh
+{
+    $iset_buffer = weechat::buffer_search($LANG, $PRGNAME);
+    if ($iset_buffer ne "")
+    {
+        weechat::buffer_clear($iset_buffer) unless defined $_[0]; # iset_full_refresh(1) does a full refresh without clearing buffer
+        # search for "*" in $filter.
+        if ($filter =~ m/\*/ and $search_mode == 2)
+        {
+            iset_get_options("");
+        }
+        else
+        {
+            if ($search_mode == 0)
+            {
+                $search_value = "=" . $search_value;
+                iset_get_values($search_value);
+            }
+            elsif ($search_mode == 1)
+            {
+                iset_get_values($search_value);
+            }
+            elsif ($search_mode == 3)
+            {
+                iset_create_filter($filter);
+                iset_get_options($search_value);
+            }
+        }
+        if (weechat::config_boolean($options_iset{"show_plugin_description"}) == 1)
+        {
+            iset_set_current_line($current_line);
+        }else
+        {
+            $current_line = $#options_names if ($current_line > $#options_names);
+        }
+        iset_refresh();
+        weechat::command($iset_buffer, "/window refresh");
+    }
+}
+
+sub iset_set_current_line
+{
+    my $new_current_line = $_[0];
+    if ($new_current_line >= 0)
+    {
+        my $old_current_line = $current_line;
+        $current_line = $new_current_line;
+        $current_line = $#options_names if ($current_line > $#options_names);
+        if ($old_current_line != $current_line)
+        {
+            iset_refresh_line($old_current_line);
+            iset_refresh_line($current_line);
+            weechat::bar_item_update("isetbar_help") if (weechat::config_boolean($options_iset{"show_help_bar"}) == 1);
+        }
+    }
+}
+
+sub iset_signal_window_scrolled_cb
+{
+    my ($data, $signal, $signal_data) = ($_[0], $_[1], $_[2]);
+    if ($iset_buffer ne "")
+    {
+        my $infolist = weechat::infolist_get("window", $signal_data, "");
+        if (weechat::infolist_next($infolist))
+        {
+            if (weechat::infolist_pointer($infolist, "buffer") eq $iset_buffer)
+            {
+                my $old_current_line = $current_line;
+                my $new_current_line = $current_line;
+                my $start_line_y = weechat::infolist_integer($infolist, "start_line_y");
+                my $chat_height = weechat::infolist_integer($infolist, "chat_height");
+                $new_current_line += $chat_height if ($new_current_line < $start_line_y);
+                $new_current_line -= $chat_height if ($new_current_line >= $start_line_y + $chat_height);
+                $new_current_line = $start_line_y if ($new_current_line < $start_line_y);
+                $new_current_line = $start_line_y + $chat_height - 1 if ($new_current_line >= $start_line_y + $chat_height);
+                iset_set_current_line($new_current_line);
+            }
+        }
+        weechat::infolist_free($infolist);
+    }
+
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub iset_get_window_number
+{
+    if ($iset_buffer ne "")
+    {
+        my $window = weechat::window_search_with_buffer($iset_buffer);
+        return "-window ".weechat::window_get_integer ($window, "number")." " if ($window ne "");
+    }
+    return "";
+}
+
+sub iset_check_line_outside_window
+{
+    if ($iset_buffer ne "")
+    {
+        undef my $infolist;
+        if ($wee_version_number >= 0x00030500)
+        {
+            my $window = weechat::window_search_with_buffer($iset_buffer);
+            $infolist = weechat::infolist_get("window", $window, "") if $window;
+        }
+        else
+        {
+            $infolist = weechat::infolist_get("window", "", "current");
+        }
+        if ($infolist)
+        {
+            if (weechat::infolist_next($infolist))
+            {
+                my $start_line_y = weechat::infolist_integer($infolist, "start_line_y");
+                my $chat_height = weechat::infolist_integer($infolist, "chat_height");
+                my $window_number = "";
+                if ($wee_version_number >= 0x00030500)
+                {
+                    $window_number = "-window ".weechat::infolist_integer($infolist, "number")." ";
+                }
+                if ($start_line_y > $current_line)
+                {
+                    weechat::command($iset_buffer, "/window scroll ".$window_number."-".($start_line_y - $current_line));
+                }
+                else
+                {
+                    if ($start_line_y <= $current_line - $chat_height)
+                    {
+                        weechat::command($iset_buffer, "/window scroll ".$window_number."+".($current_line - $start_line_y - $chat_height + 1));
+
+                    }
+                }
+            }
+            weechat::infolist_free($infolist);
+        }
+    }
+}
+
+sub iset_get_option_name_index
+{
+    my $option_name = $_[0];
+    my $index = 0;
+    while ($index <= $#options_names)
+    {
+        return -1 if ($options_names[$index] gt $option_name);
+        return $index if ($options_names[$index] eq $option_name);
+        $index++;
+    }
+    return -1;
+}
+
+sub iset_config_cb
+{
+    my ($data, $option_name, $value) = ($_[0], $_[1], $_[2]);
+
+    if ($iset_buffer ne "")
+    {
+        return weechat::WEECHAT_RC_OK if (weechat::info_get("weechat_upgrading", "") eq "1");
+
+        my $index = iset_get_option_name_index($option_name);
+        if ($index >= 0)
+        {
+            # refresh info about changed option
+            my $infolist = weechat::infolist_get("option", "", $option_name);
+            if ($infolist)
+            {
+                weechat::infolist_next($infolist);
+                if (weechat::infolist_fields($infolist))
+                {
+                    $options_types[$index] = weechat::infolist_string($infolist, "type");
+                    $options_values[$index] = weechat::infolist_string($infolist, "value");
+                    $options_default_values[$index] = weechat::infolist_string($infolist, "default_value");
+                    $options_is_null[$index] = weechat::infolist_integer($infolist, "value_is_null");
+                    iset_refresh_line($index);
+                    iset_title() if ($option_name eq "iset.look.show_current_line");
+                }
+                else
+                {
+                    iset_full_refresh(1); # if not found, refresh fully without clearing buffer
+                    weechat::print_y($iset_buffer, $#options_names + 1, "");
+                }
+                weechat::infolist_free($infolist);
+            }
+        }
+        else
+        {
+            iset_full_refresh() if ($option_name ne "weechat.bar.isetbar.hidden");
+        }
+    }
+
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub iset_set_option
+{
+    my ($option, $value) = ($_[0],$_[1]);
+    if (defined $option and defined $value)
+    {
+        $option = weechat::config_get($option);
+        weechat::config_option_set($option, $value, 1) if ($option ne "");
+    }
+}
+
+sub iset_reset_option
+{
+    my $option = $_[0];
+    if (defined $option)
+    {
+        $option = weechat::config_get($option);
+        weechat::config_option_reset($option, 1) if ($option ne "");
+    }
+}
+
+sub iset_unset_option
+{
+    my $option = $_[0];
+    if (defined $option)
+    {
+        $option = weechat::config_get($option);
+        weechat::config_option_unset($option) if ($option ne "");
+    }
+}
+
+
+sub iset_cmd_cb
+{
+    my ($data, $buffer, $args) = ($_[0], $_[1], $_[2]);
+    my $filter_set = 0;
+#    $search_value = "";
+    if (($args ne "") && (substr($args, 0, 2) ne "**"))
+    {
+        my @cmd_array = split(/ /,$args);
+        my $array_count = @cmd_array;
+        if (substr($args, 0, 1) eq weechat::config_string($options_iset{"value_search_char"})
+        or (defined $cmd_array[0] and $cmd_array[0] eq weechat::config_string($options_iset{"value_search_char"}).weechat::config_string($options_iset{"value_search_char"})) )
+        {
+            $search_mode = 1;
+            my $search_value = substr($args, 1);  # cut value_search_char
+            if ($iset_buffer ne "")
+            {
+                weechat::buffer_clear($iset_buffer);
+                weechat::command($iset_buffer, "/window refresh");
+            }
+            weechat::buffer_set($iset_buffer, "localvar_set_iset_search_mode", $search_mode);
+            weechat::buffer_set($iset_buffer, "localvar_set_iset_search_value", $search_value);
+            iset_init();
+            iset_get_values($search_value);
+            iset_refresh();
+            weechat::buffer_set($iset_buffer, "display", "1");
+#            $filter = $var_value;
+            return weechat::WEECHAT_RC_OK;
+        }
+        else
+        {
+            # f/s option =value
+            # option =value
+            $search_mode = 2;
+            if ( $array_count >= 2 and $cmd_array[0] ne "f" or $cmd_array[0] ne "s")
+            {
+                if ( defined $cmd_array[1] and substr($cmd_array[1], 0, 1) eq weechat::config_string($options_iset{"value_search_char"})
+                or defined $cmd_array[2] and substr($cmd_array[2], 0, 1) eq weechat::config_string($options_iset{"value_search_char"}) )
+                {
+                    $search_mode = 3;
+                    $search_value = substr($cmd_array[1], 1);  # cut value_search_char
+                    $search_value = substr($cmd_array[2], 1) if ( $array_count > 2);  # cut value_search_char
+                }
+            }
+            iset_create_filter($args);
+            $filter_set = 1;
+            my $ptrbuf = weechat::buffer_search($LANG, $PRGNAME);
+            if ($ptrbuf eq "")
+            {
+                iset_init();
+                iset_get_options($search_value);
+                iset_full_refresh();
+                weechat::buffer_set(weechat::buffer_search($LANG, $PRGNAME), "display", "1");
+                weechat::buffer_set($iset_buffer, "localvar_set_iset_search_value", $search_value);
+                weechat::buffer_set($iset_buffer, "localvar_set_iset_search_mode", $search_mode);
+                return weechat::WEECHAT_RC_OK;
+            }
+            else
+            {
+                iset_get_options($search_value);
+                iset_full_refresh();
+                weechat::buffer_set($ptrbuf, "display", "1");
+            }
+        }
+    weechat::buffer_set($iset_buffer, "localvar_set_iset_search_mode", $search_mode);
+    weechat::buffer_set($iset_buffer, "localvar_set_iset_search_value", $search_value);
+    }
+    if ($iset_buffer eq "")
+    {
+        iset_init();
+        iset_get_options("");
+        iset_refresh();
+    }
+    else
+    {
+#        iset_get_options($search_value);
+        iset_full_refresh() if ($filter_set);
+    }
+
+    if ($args eq "")
+    {
+        weechat::buffer_set($iset_buffer, "display", "1");
+    }
+    else
+    {
+        if ($args eq "**refresh")
+        {
+            iset_full_refresh();
+        }
+        if ($args eq "**up")
+        {
+            if ($current_line > 0)
+            {
+                $current_line--;
+                iset_refresh_line($current_line + 1);
+                iset_refresh_line($current_line);
+                iset_check_line_outside_window();
+            }
+        }
+        if ($args eq "**down")
+        {
+            if ($current_line < $#options_names)
+            {
+                $current_line++;
+                iset_refresh_line($current_line - 1);
+                iset_refresh_line($current_line);
+                iset_check_line_outside_window();
+            }
+        }
+        if ($args eq "**left" && $wee_version_number >= 0x00030600)
+        {
+            weechat::command($iset_buffer, "/window scroll_horiz ".iset_get_window_number()."-".weechat::config_integer($options_iset{"scroll_horiz"})."%");
+        }
+        if ($args eq "**right" && $wee_version_number >= 0x00030600)
+        {
+            weechat::command($iset_buffer, "/window scroll_horiz ".iset_get_window_number().weechat::config_integer($options_iset{"scroll_horiz"})."%");
+        }
+        if ($args eq "**scroll_top")
+        {
+            my $old_current_line = $current_line;
+            $current_line = 0;
+            iset_refresh_line ($old_current_line);
+            iset_refresh_line ($current_line);
+            iset_title();
+            weechat::command($iset_buffer, "/window scroll_top ".iset_get_window_number());
+        }
+        if ($args eq "**scroll_bottom")
+        {
+            my $old_current_line = $current_line;
+            $current_line = $#options_names;
+            iset_refresh_line ($old_current_line);
+            iset_refresh_line ($current_line);
+            iset_title();
+            weechat::command($iset_buffer, "/window scroll_bottom ".iset_get_window_number());
+        }
+        if ($args eq "**toggle")
+        {
+            if ($options_types[$current_line] eq "boolean")
+            {
+                iset_set_option($options_names[$current_line], "toggle");
+            }
+        }
+        if ($args eq "**incr")
+        {
+            if (($options_types[$current_line] eq "integer")
+                || ($options_types[$current_line] eq "color"))
+            {
+                iset_set_option($options_names[$current_line], "++1");
+            }
+        }
+        if ($args eq "**decr")
+        {
+            if (($options_types[$current_line] eq "integer")
+                || ($options_types[$current_line] eq "color"))
+            {
+                iset_set_option($options_names[$current_line], "--1");
+            }
+        }
+        if ($args eq "**reset")
+        {
+            iset_reset_option($options_names[$current_line]);
+        }
+        if ($args eq "**unset")
+        {
+            iset_unset_option($options_names[$current_line]);
+        }
+        if ($args eq "**toggle_help")
+        {
+            if (weechat::config_boolean($options_iset{"show_help_bar"})  == 1)
+            {
+                weechat::config_option_set($options_iset{"show_help_bar"},0,1);
+                iset_show_bar(0);
+            }
+            else
+            {
+                weechat::config_option_set($options_iset{"show_help_bar"},1,1);
+                iset_show_bar(1);
+            }
+        }
+        if ($args eq "**toggle_show_plugin_desc")
+        {
+            if (weechat::config_boolean($options_iset{"show_plugin_description"}) == 1)
+            {
+                weechat::config_option_set($options_iset{"show_plugin_description"},0,1);
+                iset_full_refresh();
+                iset_check_line_outside_window();
+                iset_title();
+            }
+            else
+            {
+                weechat::config_option_set($options_iset{"show_plugin_description"},1,1);
+                iset_full_refresh();
+                iset_check_line_outside_window();
+                iset_title();
+            }
+        }
+        if ($args eq "**set")
+        {
+            my $quote = "";
+            my $value = $options_values[$current_line];
+            if ($options_is_null[$current_line])
+            {
+                $value = "null";
+            }
+            else
+            {
+                $quote = "\"" if ($options_types[$current_line] eq "string");
+            }
+            my $set_command = "/set";
+            $set_command = "/mute " . $set_command if (weechat::config_boolean($options_iset{"use_mute"}) == 1);
+
+            weechat::buffer_set($iset_buffer, "input", $set_command." ".$options_names[$current_line]." ".$quote.$value.$quote);
+            weechat::command($iset_buffer, "/input move_beginning_of_line");
+            weechat::command($iset_buffer, "/input move_next_word");
+            weechat::command($iset_buffer, "/input move_next_word");
+            weechat::command($iset_buffer, "/input move_next_word") if (weechat::config_boolean($options_iset{"use_mute"}) == 1);
+            weechat::command($iset_buffer, "/input move_next_char");
+            weechat::command($iset_buffer, "/input move_next_char") if ($quote ne "");
+        }
+    }
+    weechat::bar_item_update("isetbar_help") if (weechat::config_boolean($options_iset{"show_help_bar"}) == 1);
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub iset_get_help
+{
+    my ($redraw) = ($_[0]);
+
+    return '' if (weechat::config_boolean($options_iset{"show_help_bar"}) == 0);
+
+    if (not defined $options_names[$current_line])
+    {
+        return "No option selected. Set a new filter using command line (use '*' to see all options)";
+    }
+    if ($options_name_copy eq $options_names[$current_line] and not defined $redraw)
+    {
+        return $description;
+    }
+    $options_name_copy = $options_names[$current_line];
+    my $optionlist ="";
+    $optionlist = weechat::infolist_get("option", "", $options_names[$current_line]);
+    weechat::infolist_next($optionlist);
+    my $full_name = weechat::infolist_string($optionlist,"full_name");
+    my $option_desc = "";
+    my $option_default_value = "";
+    my $option_range = "";
+    my $possible_values = "";
+    my $re = qq(\Q$full_name);
+    if (grep (/^$re$/,$options_names[$current_line]))
+    {
+        $option_desc = weechat::infolist_string($optionlist, "description_nls");
+        $option_desc = weechat::infolist_string($optionlist, "description") if ($option_desc eq "");
+        $option_desc = "No help found" if ($option_desc eq "");
+        $option_default_value = weechat::infolist_string($optionlist, "default_value");
+        $possible_values = weechat::infolist_string($optionlist, "string_values") if (weechat::infolist_string($optionlist, "string_values") ne "");
+        if ((weechat::infolist_string($optionlist, "type") eq "integer") && ($possible_values eq ""))
+        {
+            $option_range = weechat::infolist_integer($optionlist, "min")
+                ." .. ".weechat::infolist_integer($optionlist, "max");
+        }
+    }
+    weechat::infolist_free($optionlist);
+    iset_title();
+
+    $description = weechat::color(weechat::config_color($options_iset{"color_help_option_name"})).$options_names[$current_line]
+        .weechat::color("bar_fg").": "
+        .weechat::color(weechat::config_color($options_iset{"color_help_text"})).$option_desc;
+
+    # show additional infos like default value and possible values
+
+    if (weechat::config_boolean($options_iset{"show_help_extra_info"}) == 1)
+    {
+        $description .=
+            weechat::color("bar_delim")." ["
+            .weechat::color("bar_fg")."default: "
+            .weechat::color("bar_delim")."\""
+            .weechat::color(weechat::config_color($options_iset{"color_help_default_value"})).$option_default_value
+            .weechat::color("bar_delim")."\"";
+        if ($option_range ne "")
+        {
+            $description .= weechat::color("bar_fg").", values: ".$option_range;
+        }
+        if ($possible_values ne "")
+        {
+            $possible_values =~ s/\|/", "/g;      # replace '|' to '", "'
+            $description .= weechat::color("bar_fg").", values: ". "\"" . $possible_values . "\"";
+
+        }
+        $description .= weechat::color("bar_delim")."]";
+    }
+    return $description;
+}
+
+sub iset_check_condition_isetbar_cb
+{
+    my ($data, $modifier, $modifier_data, $string) = ($_[0], $_[1], $_[2], $_[3]);
+    my $buffer = weechat::window_get_pointer($modifier_data, "buffer");
+    if ($buffer ne "")
+    {
+        if ((weechat::buffer_get_string($buffer, "plugin") eq $LANG)
+            && (weechat::buffer_get_string($buffer, "name") eq $PRGNAME))
+        {
+            return "1";
+        }
+    }
+    return "0";
+}
+
+sub iset_show_bar
+{
+    my $show = $_[0];
+    my $barhidden = weechat::config_get("weechat.bar.isetbar.hidden");
+    if ($barhidden)
+    {
+        if ($show)
+        {
+            if (weechat::config_boolean($options_iset{"show_help_bar"}) == 1)
+            {
+                if (weechat::config_boolean($barhidden))
+                {
+                    weechat::config_option_set($barhidden, 0, 1);
+                }
+            }
+        }
+        else
+        {
+            if (!weechat::config_boolean($barhidden))
+            {
+                weechat::config_option_set($barhidden, 1, 1);
+            }
+        }
+    }
+}
+
+sub iset_signal_buffer_switch_cb
+{
+    my $buffer_pointer = $_[2];
+    my $show_bar = 0;
+    $show_bar = 1 if (weechat::buffer_get_integer($iset_buffer, "num_displayed") > 0);
+    iset_show_bar($show_bar);
+    iset_check_line_outside_window() if ($buffer_pointer eq $iset_buffer);
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub iset_item_cb
+{
+    return iset_get_help();
+}
+
+sub iset_upgrade_ended
+{
+    iset_full_refresh();
+}
+
+sub iset_end
+{
+    # when script is unloaded, we hide bar
+    iset_show_bar(0);
+}
+
+# -------------------------------[ mouse support ]-------------------------------------
+
+sub hook_focus_iset_cb
+{
+    my %info = %{$_[1]};
+    my $bar_item_line = int($info{"_bar_item_line"});
+    undef my $hash;
+    if (($info{"_buffer_name"} eq $PRGNAME) && $info{"_buffer_plugin"} eq $LANG && ($bar_item_line >= 0) && ($bar_item_line <= $#iset_focus))
+    {
+        $hash = $iset_focus[$bar_item_line];
+    }
+    else
+    {
+        $hash = {};
+        my $hash_focus = $iset_focus[0];
+        foreach my $key (keys %$hash_focus)
+        {
+            $hash->{$key} = "?";
+        }
+    }
+    return $hash;
+}
+
+# _chat_line_y contains selected line
+sub iset_hsignal_mouse_cb
+{
+    my ($data, $signal, %hash) = ($_[0], $_[1], %{$_[2]});
+
+    if ($hash{"_buffer_name"} eq $PRGNAME && ($hash{"_buffer_plugin"} eq $LANG))
+    {
+        if ($hash{"_key"} eq "button1")
+        {
+            iset_set_current_line($hash{"_chat_line_y"});
+        }
+        elsif ($hash{"_key"} eq "button2")
+        {
+            if ($options_types[$hash{"_chat_line_y"}] eq "boolean")
+            {
+                iset_set_option($options_names[$hash{"_chat_line_y"}], "toggle");
+                iset_set_current_line($hash{"_chat_line_y"});
+            }
+            elsif ($options_types[$hash{"_chat_line_y"}] eq "string")
+            {
+                iset_set_current_line($hash{"_chat_line_y"});
+                weechat::command("", "/$PRGNAME **set");
+            }
+        }
+        elsif ($hash{"_key"} eq "button2-gesture-left" or $hash{"_key"} eq "button2-gesture-left-long")
+        {
+            if ($options_types[$hash{"_chat_line_y"}] eq "integer" or ($options_types[$hash{"_chat_line_y"}] eq "color"))
+            {
+                iset_set_current_line($hash{"_chat_line_y"});
+                my $distance = distance($hash{"_chat_line_x"},$hash{"_chat_line_x2"});
+                weechat::command("", "/repeat $distance /$PRGNAME **decr");
+            }
+        }
+        elsif ($hash{"_key"} eq "button2-gesture-right" or $hash{"_key"} eq "button2-gesture-right-long")
+        {
+            if ($options_types[$hash{"_chat_line_y"}] eq "integer" or ($options_types[$hash{"_chat_line_y"}] eq "color"))
+            {
+                iset_set_current_line($hash{"_chat_line_y"});
+                my $distance = distance($hash{"_chat_line_x"},$hash{"_chat_line_x2"});
+                weechat::command("", "/repeat $distance /$PRGNAME **incr");
+            }
+        }
+    }
+    window_switch();
+}
+
+sub window_switch
+{
+    my $current_window = weechat::current_window();
+    my $dest_window = weechat::window_search_with_buffer(weechat::buffer_search("perl","iset"));
+    return 0 if ($dest_window eq "" or $current_window eq $dest_window);
+
+    my $infolist = weechat::infolist_get("window", $dest_window, "");
+    weechat::infolist_next($infolist);
+    my $number = weechat::infolist_integer($infolist, "number");
+    weechat::infolist_free($infolist);
+    weechat::command("","/window " . $number);
+}
+
+sub distance
+{
+    my ($x1,$x2) = ($_[0], $_[1]);
+    my $distance;
+    $distance = $x1 - $x2;
+    $distance = abs($distance);
+    if ($distance > 0)
+    {
+        use integer;
+        $distance  =  $distance / 3;
+        $distance = 1 if ($distance == 0);
+    }
+    elsif ($distance == 0)
+    {
+        $distance = 1;
+    }
+    return $distance;
+}
+
+# -----------------------------------[ config ]---------------------------------------
+
+sub iset_config_init
+{
+    $iset_config_file = weechat::config_new($ISET_CONFIG_FILE_NAME,"iset_config_reload_cb","");
+    return if ($iset_config_file eq "");
+
+    # section "color"
+    my $section_color = weechat::config_new_section($iset_config_file,"color", 0, 0, "", "", "", "", "", "", "", "", "", "");
+    if ($section_color eq "")
+    {
+        weechat::config_free($iset_config_file);
+        return;
+    }
+    $options_iset{"color_option"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "option", "color", "Color for option name in iset buffer", "", 0, 0,
+        "default", "default", 0, "", "", "full_refresh_cb", "", "", "");
+    $options_iset{"color_option_selected"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "option_selected", "color", "Color for selected option name in iset buffer", "", 0, 0,
+        "white", "white", 0, "", "", "full_refresh_cb", "", "", "");
+    $options_iset{"color_type"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "type", "color", "Color for option type (integer, boolean, string)", "", 0, 0,
+        "brown", "brown", 0, "", "", "full_refresh_cb", "", "", "");
+    $options_iset{"color_type_selected"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "type_selected", "color", "Color for selected option type (integer, boolean, string)", "", 0, 0,
+        "yellow", "yellow", 0, "", "", "full_refresh_cb", "", "", "");
+    $options_iset{"color_value"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "value", "color", "Color for option value", "", 0, 0,
+        "cyan", "cyan", 0, "", "", "full_refresh_cb", "", "", "");
+    $options_iset{"color_value_selected"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "value_selected", "color", "Color for selected option value", "", 0, 0,
+        "lightcyan", "lightcyan", 0, "", "", "full_refresh_cb", "", "", "");
+    $options_iset{"color_value_diff"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "value_diff", "color", "Color for option value different from default", "", 0, 0,
+        "magenta", "magenta", 0, "", "", "full_refresh_cb", "", "", "");
+    $options_iset{"color_value_diff_selected"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "value_diff_selected", "color", "Color for selected option value different from default", "", 0, 0,
+        "lightmagenta", "lightmagenta", 0, "", "", "full_refresh_cb", "", "", "");
+    $options_iset{"color_value_undef"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "value_undef", "color", "Color for option value undef", "", 0, 0,
+        "green", "green", 0, "", "", "full_refresh_cb", "", "", "");
+    $options_iset{"color_value_undef_selected"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "value_undef_selected", "color", "Color for selected option value undef", "", 0, 0,
+        "lightgreen", "lightgreen", 0, "", "", "full_refresh_cb", "", "", "");
+    $options_iset{"color_bg_selected"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "bg_selected", "color", "Background color for current selected option", "", 0, 0,
+        "red", "red", 0, "", "", "full_refresh_cb", "", "", "");
+    $options_iset{"color_help_option_name"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "help_option_name", "color", "Color for option name in help-bar", "", 0, 0,
+        "white", "white", 0, "", "", "bar_refresh", "", "", "");
+    $options_iset{"color_help_text"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "help_text", "color", "Color for option description in help-bar", "", 0, 0,
+        "default", "default", 0, "", "", "bar_refresh", "", "", "");
+    $options_iset{"color_help_default_value"} = weechat::config_new_option(
+        $iset_config_file, $section_color,
+        "help_default_value", "color", "Color for default option value in help-bar", "", 0, 0,
+        "green", "green", 0, "", "", "bar_refresh", "", "", "");
+
+    # section "help"
+    my $section_help = weechat::config_new_section($iset_config_file,"help", 0, 0, "", "", "", "", "", "", "", "", "", "");
+    if ($section_help eq "")
+    {
+        weechat::config_free($iset_config_file);
+        return;
+    }
+    $options_iset{"show_help_bar"} = weechat::config_new_option(
+        $iset_config_file, $section_help,
+        "show_help_bar", "boolean", "Show help bar", "", 0, 0,
+        "on", "on", 0, "", "", "toggle_help_cb", "", "", "");
+    $options_iset{"show_help_extra_info"} = weechat::config_new_option(
+        $iset_config_file, $section_help,
+        "show_help_extra_info", "boolean", "Show additional information in help bar (default value, max./min. value) ", "", 0, 0,
+        "on", "on", 0, "", "", "", "", "", "");
+    $options_iset{"show_plugin_description"} = weechat::config_new_option(
+        $iset_config_file, $section_help,
+        "show_plugin_description", "boolean", "Show plugin description in iset buffer", "", 0, 0,
+        "off", "off", 0, "", "", "full_refresh_cb", "", "", "");
+
+    # section "look"
+    my $section_look = weechat::config_new_section($iset_config_file, "look", 0, 0, "", "", "", "", "", "", "", "", "", "");
+    if ($section_look eq "")
+    {
+        weechat::config_free($iset_config_file);
+        return;
+    }
+    $options_iset{"value_search_char"} = weechat::config_new_option(
+        $iset_config_file, $section_look,
+        "value_search_char", "string", "Trigger char to tell iset to search for value instead of option (for example: =red)", "", 0, 0,
+        "=", "=", 0, "", "", "", "", "", "");
+    $options_iset{"scroll_horiz"} = weechat::config_new_option(
+        $iset_config_file, $section_look,
+        "scroll_horiz", "integer", "scroll content of iset buffer n%", "", 1, 100,
+        "10", "10", 0, "", "", "", "", "", "");
+    $options_iset{"show_current_line"} = weechat::config_new_option(
+        $iset_config_file, $section_look,
+        "show_current_line", "boolean", "show current line in title bar.", "", 0, 0,
+        "on", "on", 0, "", "", "", "", "", "");
+    $options_iset{"use_mute"} = weechat::config_new_option(
+        $iset_config_file, $section_look,
+        "use_mute", "boolean", "/mute command will be used in input bar", "", 0, 0,
+        "off", "off", 0, "", "", "", "", "", "");
+}
+
+sub iset_config_reload_cb
+{
+    my ($data,$config_file) = ($_[0], $_[1]);
+    return weechat::config_reload($config_file)
+}
+
+sub iset_config_read
+{
+    return weechat::config_read($iset_config_file) if ($iset_config_file ne "");
+}
+
+sub iset_config_write
+{
+    return weechat::config_write($iset_config_file) if ($iset_config_file ne "");
+}
+
+sub full_refresh_cb
+{
+    iset_full_refresh();
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub bar_refresh
+{
+    iset_get_help(1);
+    weechat::bar_item_update("isetbar_help") if (weechat::config_boolean($options_iset{"show_help_bar"}) == 1);
+    return weechat::WEECHAT_RC_OK;
+}
+
+sub toggle_help_cb
+{
+    my $value = weechat::config_boolean($options_iset{"show_help_bar"});
+    iset_show_bar($value);
+    return weechat::WEECHAT_RC_OK;
+}
+
+# -----------------------------------[ main ]-----------------------------------------
+
+weechat::register($PRGNAME, $AUTHOR, $VERSION, $LICENSE,
+                  $DESCR, "iset_end", "");
+
+$wee_version_number = weechat::info_get("version_number", "") || 0;
+
+iset_config_init();
+iset_config_read();
+
+weechat::hook_command($PRGNAME, "Interactive set", "f <file> || s <section> || [=][=]<text>",
+                      "f file   : show options for a file\n".
+                      "s section: show options for a section\n".
+                      "text     : show options with 'text' in name\n".
+                      weechat::config_string($options_iset{"value_search_char"})."text    : show options with 'text' in value\n".
+                      weechat::config_string($options_iset{"value_search_char"}).weechat::config_string($options_iset{"value_search_char"})."text   : show options with exact 'text' in value\n\n".
+                      "Keys for iset buffer:\n".
+                      "f11,f12        : move iset content left/right\n".
+                      "up,down        : move one option up/down\n".
+                      "pgup,pdwn      : move one page up/down\n".
+                      "home,end       : move to first/last option\n".
+                      "ctrl+'L'       : refresh options and screen\n".
+                      "alt+space      : toggle boolean on/off\n".
+                      "alt+'+'        : increase value (for integer or color)\n".
+                      "alt+'-'        : decrease value (for integer or color)\n".
+                      "alt+'i',alt+'r': reset value of option\n".
+                      "alt+'i',alt+'u': unset option\n".
+                      "alt+enter      : set new value for option (edit it with command line)\n".
+                      "text,enter     : set a new filter using command line (use '*' to see all options)\n".
+                      "alt+'v'        : toggle help bar on/off\n".
+                      "alt+'p'        : toggle option \"show_plugin_description\" on/off\n".
+                      "\n".
+                      "Mouse actions:\n".
+                      "wheel up/down                 : move cursor up/down\n".
+                      "left button                   : select an option from list\n".
+                      "right button                  : toggle boolean (on/off) or set a new value for option (edit it with command line)\n".
+                      "right button + drag left/right: increase/decrease value (for integer or color)\n".
+                      "\n".
+                      "Examples:\n".
+                      "  show options for file 'weechat'\n".
+                      "    /iset f weechat\n".
+                      "  show options for file 'irc'\n".
+                      "    /iset f irc\n".
+                      "  show options for section 'look'\n".
+                      "    /iset s look\n".
+                      "  show all options with text 'nicklist' in name\n".
+                      "    /iset nicklist\n".
+                      "  show all values which contain 'red'. ('" . weechat::config_string($options_iset{"value_search_char"}) . "' is a trigger char).\n".
+                      "    /iset ". weechat::config_string($options_iset{"value_search_char"}) ."red\n".
+                      "  show all values which hit 'off'. ('" . weechat::config_string($options_iset{"value_search_char"}) . weechat::config_string($options_iset{"value_search_char"}) . "' is a trigger char).\n".
+                      "    /iset ". weechat::config_string($options_iset{"value_search_char"}) . weechat::config_string($options_iset{"value_search_char"}) ."off\n".
+                      "  show options for file 'weechat' which contains value 'off'\n".
+                      "    /iset f weechat ".weechat::config_string($options_iset{"value_search_char"})."off\n".
+                      "",
+                      "", "iset_cmd_cb", "");
+weechat::hook_signal("upgrade_ended", "iset_upgrade_ended", "");
+weechat::hook_signal("window_scrolled", "iset_signal_window_scrolled_cb", "");
+weechat::hook_signal("buffer_switch", "iset_signal_buffer_switch_cb","");
+weechat::bar_item_new("isetbar_help", "iset_item_cb", "");
+weechat::bar_new("isetbar", "on", "0", "window", "", "top", "horizontal",
+                 "vertical", "3", "3", "default", "cyan", "default", "1",
+                 "isetbar_help");
+weechat::hook_modifier("bar_condition_isetbar", "iset_check_condition_isetbar_cb", "");
+weechat::hook_config("*", "iset_config_cb", "");
+$iset_buffer = weechat::buffer_search($LANG, $PRGNAME);
+iset_init() if ($iset_buffer ne "");
+
+if ($wee_version_number >= 0x00030600)
+{
+    weechat::hook_focus("chat", "hook_focus_iset_cb", "");
+    weechat::hook_hsignal($PRGNAME."_mouse", "iset_hsignal_mouse_cb", "");
+    weechat::key_bind("mouse", \%mouse_keys);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/weechat/weechat.conf	Wed Nov 19 19:24:17 2014 +0100
@@ -0,0 +1,893 @@
+#
+# weechat.conf -- weechat v1.0.1
+#
+
+[debug]
+
+[startup]
+command_after_plugins = ""
+command_before_plugins = ""
+display_logo = on
+display_version = on
+sys_rlimit = ""
+
+[look]
+align_end_of_lines = message
+bar_more_down = "▼"
+bar_more_left = "◀"
+bar_more_right = "▶"
+bar_more_up = "▲"
+bare_display_exit_on_input = on
+bare_display_time_format = "%H:%M"
+buffer_auto_renumber = on
+buffer_notify_default = all
+buffer_position = end
+buffer_search_case_sensitive = off
+buffer_search_force_default = off
+buffer_search_regex = off
+buffer_search_where = message
+buffer_time_format = " "
+color_basic_force_bold = off
+color_inactive_buffer = off
+color_inactive_message = off
+color_inactive_prefix = on
+color_inactive_prefix_buffer = on
+color_inactive_time = off
+color_inactive_window = off
+color_nick_offline = off
+color_pairs_auto_reset = 5
+color_real_white = off
+command_chars = ""
+confirm_quit = off
+day_change = on
+day_change_message_1date = "-- %a, %d %b %Y --"
+day_change_message_2dates = "-- %%a, %%d %%b %%Y (%a, %d %b %Y) --"
+eat_newline_glitch = off
+emphasized_attributes = ""
+highlight = "zeger,zegervdv"
+highlight_regex = ""
+highlight_tags = ""
+hotlist_add_conditions = "${away} || ${buffer.num_displayed} == 0"
+hotlist_buffer_separator = ", "
+hotlist_count_max = 2
+hotlist_count_min_msg = 2
+hotlist_names_count = 3
+hotlist_names_length = 0
+hotlist_names_level = 12
+hotlist_names_merged_buffers = off
+hotlist_prefix = "H: "
+hotlist_remove = merged
+hotlist_short_names = on
+hotlist_sort = group_time_asc
+hotlist_suffix = ""
+hotlist_unique_numbers = on
+input_cursor_scroll = 20
+input_share = none
+input_share_overwrite = off
+input_undo_max = 32
+item_buffer_filter = "⚑"
+item_buffer_zoom = "!"
+item_time_format = "%H:%M"
+jump_current_to_previous_buffer = on
+jump_previous_buffer_when_closing = on
+jump_smart_back_to_buffer = on
+key_bind_safe = on
+mouse = off
+mouse_timer_delay = 100
+nick_prefix = ""
+nick_suffix = ""
+paste_bracketed = off
+paste_bracketed_timer_delay = 10
+paste_max_lines = 1
+prefix_action = "⚡"
+prefix_align = right
+prefix_align_max = 10
+prefix_align_min = 10
+prefix_align_more = " "
+prefix_align_more_after = on
+prefix_buffer_align = right
+prefix_buffer_align_max = 0
+prefix_buffer_align_more = "+"
+prefix_buffer_align_more_after = on
+prefix_error = "⚠ "
+prefix_join = "◥"
+prefix_network = "ℹ "
+prefix_quit = "◣"
+prefix_same_nick = ""
+prefix_suffix = "│"
+read_marker = line
+read_marker_always_show = off
+read_marker_string = ""
+save_config_on_exit = on
+save_layout_on_exit = none
+scroll_amount = 3
+scroll_bottom_after_switch = off
+scroll_page_percent = 100
+search_text_not_found_alert = on
+separator_horizontal = ""
+separator_vertical = ""
+tab_width = 1
+time_format = "%a, %d %b %Y %T"
+window_auto_zoom = off
+window_separator_horizontal = on
+window_separator_vertical = on
+window_title = "WeeChat"
+
+[palette]
+100 = ""
+101 = ""
+102 = ""
+103 = ""
+104 = ""
+105 = ""
+106 = ""
+107 = ""
+108 = ""
+109 = ""
+110 = ""
+111 = ""
+112 = ""
+113 = ""
+114 = ""
+115 = ""
+116 = ""
+117 = ""
+118 = ""
+119 = ""
+120 = ""
+121 = ""
+122 = ""
+123 = ""
+124 = ""
+125 = ""
+126 = ""
+127 = ""
+128 = ""
+129 = ""
+130 = ""
+131 = ""
+132 = ""
+133 = ""
+134 = ""
+135 = ""
+136 = ""
+137 = ""
+138 = ""
+139 = ""
+140 = ""
+141 = ""
+142 = ""
+143 = ""
+144 = ""
+145 = ""
+146 = ""
+147 = ""
+148 = ""
+149 = ""
+150 = ""
+151 = ""
+152 = ""
+153 = ""
+154 = ""
+155 = ""
+156 = ""
+157 = ""
+158 = ""
+159 = ""
+160 = ""
+161 = ""
+162 = ""
+163 = ""
+164 = ""
+165 = ""
+166 = ""
+167 = ""
+168 = ""
+169 = ""
+17 = ""
+170 = ""
+171 = ""
+172 = ""
+173 = ""
+174 = ""
+175 = ""
+176 = ""
+177 = ""
+178 = ""
+179 = ""
+18 = ""
+180 = ""
+181 = ""
+182 = ""
+183 = ""
+184 = ""
+185 = ""
+186 = ""
+187 = ""
+188 = ""
+189 = ""
+19 = ""
+190 = ""
+191 = ""
+192 = ""
+193 = ""
+194 = ""
+195 = ""
+196 = ""
+197 = ""
+198 = ""
+199 = ""
+20 = ""
+200 = ""
+201 = ""
+202 = ""
+203 = ""
+204 = ""
+205 = ""
+206 = ""
+207 = ""
+208 = ""
+209 = ""
+21 = ""
+210 = ""
+211 = ""
+212 = ""
+213 = ""
+214 = ""
+215 = ""
+216 = ""
+217 = ""
+218 = ""
+219 = ""
+22 = ""
+220 = ""
+221 = ""
+222 = ""
+223 = ""
+224 = ""
+225 = ""
+226 = ""
+227 = ""
+228 = ""
+229 = ""
+23 = ""
+230 = ""
+231 = ""
+232 = ""
+233 = ""
+234 = ""
+235 = ""
+236 = ""
+237 = ""
+238 = ""
+239 = ""
+24 = ""
+240 = ""
+241 = ""
+242 = ""
+243 = ""
+244 = ""
+245 = ""
+246 = ""
+247 = ""
+248 = ""
+249 = ""
+25 = ""
+250 = ""
+251 = ""
+252 = ""
+253 = ""
+254 = ""
+255 = ""
+256 = ""
+26 = ""
+27 = ""
+28 = ""
+29 = ""
+30 = ""
+31 = ""
+32 = ""
+33 = ""
+34 = ""
+35 = ""
+36 = ""
+37 = ""
+38 = ""
+39 = ""
+40 = ""
+41 = ""
+42 = ""
+43 = ""
+44 = ""
+45 = ""
+46 = ""
+47 = ""
+48 = ""
+49 = ""
+50 = ""
+51 = ""
+52 = ""
+53 = ""
+54 = ""
+55 = ""
+56 = ""
+57 = ""
+58 = ""
+59 = ""
+60 = ""
+61 = ""
+62 = ""
+63 = ""
+64 = ""
+65 = ""
+66 = ""
+67 = ""
+68 = ""
+69 = ""
+70 = ""
+71 = ""
+72 = ""
+73 = ""
+74 = ""
+75 = ""
+76 = ""
+77 = ""
+78 = ""
+79 = ""
+80 = ""
+81 = ""
+82 = ""
+83 = ""
+84 = ""
+85 = ""
+86 = ""
+87 = ""
+88 = ""
+89 = ""
+90 = ""
+91 = ""
+92 = ""
+93 = ""
+94 = ""
+95 = ""
+96 = ""
+97 = ""
+98 = ""
+99 = ""
+
+[color]
+bar_more = lightmagenta
+chat = default
+chat_bg = default
+chat_buffer = white
+chat_channel = gray
+chat_day_change = cyan
+chat_delimiters = default
+chat_highlight = default
+chat_highlight_bg = default
+chat_host = cyan
+chat_inactive_buffer = darkgray
+chat_inactive_window = darkgray
+chat_nick = lightcyan
+chat_nick_colors = "darkgray,red,lightred,green,lightgreen,blue,lightblue,brown,cyan,lightcyan,magenta"
+chat_nick_offline = darkgray
+chat_nick_offline_highlight = default
+chat_nick_offline_highlight_bg = darkgray
+chat_nick_other = cyan
+chat_nick_prefix = green
+chat_nick_self = darkgray
+chat_nick_suffix = green
+chat_prefix_action = white
+chat_prefix_buffer = brown
+chat_prefix_buffer_inactive_buffer = darkgray
+chat_prefix_error = yellow
+chat_prefix_join = darkgray
+chat_prefix_more = lightmagenta
+chat_prefix_network = magenta
+chat_prefix_quit = gray
+chat_prefix_suffix = gray
+chat_read_marker = gray
+chat_read_marker_bg = default
+chat_server = brown
+chat_tags = red
+chat_text_found = yellow
+chat_text_found_bg = lightmagenta
+chat_time = gray
+chat_time_delimiters = gray
+chat_value = cyan
+emphasized = yellow
+emphasized_bg = magenta
+input_actions = lightgreen
+input_text_not_found = red
+nicklist_away = cyan
+nicklist_group = green
+nicklist_offline = blue
+separator = gray
+status_count_highlight = magenta
+status_count_msg = brown
+status_count_other = default
+status_count_private = green
+status_data_highlight = lightmagenta
+status_data_msg = yellow
+status_data_other = default
+status_data_private = lightgreen
+status_filter = green
+status_more = yellow
+status_name = darkgray
+status_name_ssl = lightgreen
+status_nicklist_count = default
+status_number = yellow
+status_time = default
+
+[completion]
+base_word_until_cursor = on
+default_template = "%(nicks)|%(irc_channels)"
+nick_add_space = on
+nick_completer = ":"
+nick_first_only = off
+nick_ignore_chars = "[]`_-^"
+partial_completion_alert = on
+partial_completion_command = off
+partial_completion_command_arg = off
+partial_completion_count = on
+partial_completion_other = off
+
+[history]
+display_default = 5
+max_buffer_lines_minutes = 0
+max_buffer_lines_number = 4096
+max_commands = 100
+max_visited_buffers = 50
+
+[proxy]
+
+[network]
+connection_timeout = 60
+gnutls_ca_file = "/usr/share/curl/ca-bundle.crt"
+gnutls_handshake_timeout = 30
+proxy_curl = ""
+
+[plugin]
+autoload = "*"
+debug = off
+extension = ".so,.dll"
+path = "%h/plugins"
+save_config_on_unload = on
+
+[bar]
+buffers.color_bg = default
+buffers.color_delim = default
+buffers.color_fg = default
+buffers.conditions = ""
+buffers.filling_left_right = vertical
+buffers.filling_top_bottom = horizontal
+buffers.hidden = on
+buffers.items = "buffers"
+buffers.position = top
+buffers.priority = 0
+buffers.separator = off
+buffers.size = 0
+buffers.size_max = 0
+buffers.type = root
+input.color_bg = default
+input.color_delim = red
+input.color_fg = default
+input.conditions = "active"
+input.filling_left_right = vertical
+input.filling_top_bottom = horizontal
+input.hidden = off
+input.items = "+    » +,input_text"
+input.position = bottom
+input.priority = 1000
+input.separator = off
+input.size = 1
+input.size_max = 0
+input.type = window
+isetbar.color_bg = default
+isetbar.color_delim = cyan
+isetbar.color_fg = default
+isetbar.conditions = ""
+isetbar.filling_left_right = vertical
+isetbar.filling_top_bottom = horizontal
+isetbar.hidden = on
+isetbar.items = "isetbar_help"
+isetbar.position = top
+isetbar.priority = 0
+isetbar.separator = on
+isetbar.size = 3
+isetbar.size_max = 3
+isetbar.type = window
+nicklist.color_bg = default
+nicklist.color_delim = cyan
+nicklist.color_fg = darkgray
+nicklist.conditions = "${active}"
+nicklist.filling_left_right = vertical
+nicklist.filling_top_bottom = columns_vertical
+nicklist.hidden = on
+nicklist.items = "buffer_nicklist"
+nicklist.position = right
+nicklist.priority = 200
+nicklist.separator = on
+nicklist.size = 0
+nicklist.size_max = 0
+nicklist.type = window
+rootinput.color_bg = default
+rootinput.color_delim = red
+rootinput.color_fg = default
+rootinput.conditions = ""
+rootinput.filling_left_right = vertical
+rootinput.filling_top_bottom = horizontal
+rootinput.hidden = on
+rootinput.items = "+    » +,input_text"
+rootinput.position = bottom
+rootinput.priority = 0
+rootinput.separator = off
+rootinput.size = 1
+rootinput.size_max = 0
+rootinput.type = root
+spacer.color_bg = default
+spacer.color_delim = gray
+spacer.color_fg = gray
+spacer.conditions = "inactive"
+spacer.filling_left_right = vertical
+spacer.filling_top_bottom = horizontal
+spacer.hidden = off
+spacer.items = "+ +irc_channel+ (+buffer_plugin+)"
+spacer.position = bottom
+spacer.priority = 1100
+spacer.separator = off
+spacer.size = 0
+spacer.size_max = 0
+spacer.type = window
+spacer2.color_bg = default
+spacer2.color_delim = default
+spacer2.color_fg = default
+spacer2.conditions = ""
+spacer2.filling_left_right = vertical
+spacer2.filling_top_bottom = horizontal
+spacer2.hidden = off
+spacer2.items = "+ +"
+spacer2.position = top
+spacer2.priority = 0
+spacer2.separator = off
+spacer2.size = 0
+spacer2.size_max = 0
+spacer2.type = window
+status.color_bg = default
+status.color_delim = cyan
+status.color_fg = default
+status.conditions = ""
+status.filling_left_right = vertical
+status.filling_top_bottom = horizontal
+status.hidden = off
+status.items = "\n"
+status.position = bottom
+status.priority = 500
+status.separator = off
+status.size = 1
+status.size_max = 0
+status.type = window
+title.color_bg = default
+title.color_delim = white
+title.color_fg = blue
+title.conditions = ""
+title.filling_left_right = vertical
+title.filling_top_bottom = horizontal
+title.hidden = on
+title.items = "buffer_title"
+title.position = top
+title.priority = 500
+title.separator = off
+title.size = 1
+title.size_max = 0
+title.type = window
+
+[layout]
+_zoom.window = "1;0;0;0;irc;freenode.##hackernews"
+
+[notify]
+
+[filter]
+joinquit = off;*;irc_join,irc_part,irc_quit;*
+modes = on;*;irc_324,irc_mode;*
+irc_smart = on;*;irc_smart_filter;*
+
+[key]
+ctrl-? = "/input delete_previous_char"
+ctrl-A = "/input move_beginning_of_line"
+ctrl-B = "/input move_previous_char"
+ctrl-C = "/window splith"
+ctrl-Cb = "/input insert \x02"
+ctrl-Cc = "/input insert \x03"
+ctrl-Ci = "/input insert \x1D"
+ctrl-Co = "/input insert \x0F"
+ctrl-Cr = "/input insert \x12"
+ctrl-Cu = "/input insert \x15"
+ctrl-D = "/input delete_next_char"
+ctrl-E = "/input move_end_of_line"
+ctrl-F = "/input move_next_char"
+ctrl-H = "/window left"
+ctrl-I = "/input complete_next"
+ctrl-J = "/window down"
+ctrl-K = "/window up"
+ctrl-L = "/window right"
+ctrl-M = "/input return"
+ctrl-N = "/buffer +1"
+ctrl-P = "/buffer -1"
+ctrl-R = "/input search_text"
+ctrl-Sctrl-U = "/input set_unread"
+ctrl-T = "/input transpose_chars"
+ctrl-U = "/input delete_beginning_of_line"
+ctrl-W = "/input delete_previous_word"
+ctrl-X = "/input switch_active_buffer"
+ctrl-Y = "/input clipboard_paste"
+meta-meta2-1~ = "/window scroll_top"
+meta-meta2-23~ = "/bar scroll nicklist * b"
+meta-meta2-24~ = "/bar scroll nicklist * e"
+meta-meta2-4~ = "/window scroll_bottom"
+meta-meta2-5~ = "/window scroll_up"
+meta-meta2-6~ = "/window scroll_down"
+meta-meta2-7~ = "/window scroll_top"
+meta-meta2-8~ = "/window scroll_bottom"
+meta-meta2-A = "/buffer -1"
+meta-meta2-B = "/buffer +1"
+meta-meta2-C = "/buffer +1"
+meta-meta2-D = "/buffer -1"
+meta-/ = "/input jump_last_buffer_displayed"
+meta-0 = "/buffer *10"
+meta-1 = "/buffer *1"
+meta-2 = "/buffer *2"
+meta-3 = "/buffer *3"
+meta-4 = "/buffer *4"
+meta-5 = "/buffer *5"
+meta-6 = "/buffer *6"
+meta-7 = "/buffer *7"
+meta-8 = "/buffer *8"
+meta-9 = "/buffer *9"
+meta-< = "/input jump_previously_visited_buffer"
+meta-= = "/filter toggle"
+meta-> = "/input jump_next_visited_buffer"
+meta-OA = "/input history_global_previous"
+meta-OB = "/input history_global_next"
+meta-OC = "/input move_next_word"
+meta-OD = "/input move_previous_word"
+meta-OF = "/input move_end_of_line"
+meta-OH = "/input move_beginning_of_line"
+meta-Oa = "/input history_global_previous"
+meta-Ob = "/input history_global_next"
+meta-Oc = "/input move_next_word"
+meta-Od = "/input move_previous_word"
+meta2-15~ = "/buffer -1"
+meta2-17~ = "/buffer +1"
+meta2-18~ = "/window -1"
+meta2-19~ = "/window +1"
+meta2-1;3A = "/buffer -1"
+meta2-1;3B = "/buffer +1"
+meta2-1;3C = "/buffer +1"
+meta2-1;3D = "/buffer -1"
+meta2-1;5A = "/input history_global_previous"
+meta2-1;5B = "/input history_global_next"
+meta2-1;5C = "/input move_next_word"
+meta2-1;5D = "/input move_previous_word"
+meta2-1~ = "/input move_beginning_of_line"
+meta2-200~ = "/input paste_start"
+meta2-201~ = "/input paste_stop"
+meta2-20~ = "/bar scroll title * -30%"
+meta2-21~ = "/bar scroll title * +30%"
+meta2-23~ = "/bar scroll nicklist * -100%"
+meta2-24~ = "/bar scroll nicklist * +100%"
+meta2-3~ = "/input delete_next_char"
+meta2-4~ = "/input move_end_of_line"
+meta2-5;3~ = "/window scroll_up"
+meta2-5~ = "/window page_up"
+meta2-6;3~ = "/window scroll_down"
+meta2-6~ = "/window page_down"
+meta2-7~ = "/input move_beginning_of_line"
+meta2-8~ = "/input move_end_of_line"
+meta2-A = "/input history_previous"
+meta2-B = "/input history_next"
+meta2-C = "/input move_next_char"
+meta2-D = "/input move_previous_char"
+meta2-F = "/input move_end_of_line"
+meta2-G = "/window page_down"
+meta2-H = "/input move_beginning_of_line"
+meta2-I = "/window page_up"
+meta2-Z = "/input complete_previous"
+meta2-[E = "/buffer -1"
+meta-_ = "/input redo"
+meta-a = "/input jump_smart"
+meta-b = "/input move_previous_word"
+meta-d = "/input delete_next_word"
+meta-f = "/input move_next_word"
+meta-h = "/input hotlist_clear"
+meta-jmeta-l = "/input jump_last_buffer"
+meta-jmeta-r = "/server raw"
+meta-jmeta-s = "/server jump"
+meta-j01 = "/buffer 1"
+meta-j02 = "/buffer 2"
+meta-j03 = "/buffer 3"
+meta-j04 = "/buffer 4"
+meta-j05 = "/buffer 5"
+meta-j06 = "/buffer 6"
+meta-j07 = "/buffer 7"
+meta-j08 = "/buffer 8"
+meta-j09 = "/buffer 9"
+meta-j10 = "/buffer 10"
+meta-j11 = "/buffer 11"
+meta-j12 = "/buffer 12"
+meta-j13 = "/buffer 13"
+meta-j14 = "/buffer 14"
+meta-j15 = "/buffer 15"
+meta-j16 = "/buffer 16"
+meta-j17 = "/buffer 17"
+meta-j18 = "/buffer 18"
+meta-j19 = "/buffer 19"
+meta-j20 = "/buffer 20"
+meta-j21 = "/buffer 21"
+meta-j22 = "/buffer 22"
+meta-j23 = "/buffer 23"
+meta-j24 = "/buffer 24"
+meta-j25 = "/buffer 25"
+meta-j26 = "/buffer 26"
+meta-j27 = "/buffer 27"
+meta-j28 = "/buffer 28"
+meta-j29 = "/buffer 29"
+meta-j30 = "/buffer 30"
+meta-j31 = "/buffer 31"
+meta-j32 = "/buffer 32"
+meta-j33 = "/buffer 33"
+meta-j34 = "/buffer 34"
+meta-j35 = "/buffer 35"
+meta-j36 = "/buffer 36"
+meta-j37 = "/buffer 37"
+meta-j38 = "/buffer 38"
+meta-j39 = "/buffer 39"
+meta-j40 = "/buffer 40"
+meta-j41 = "/buffer 41"
+meta-j42 = "/buffer 42"
+meta-j43 = "/buffer 43"
+meta-j44 = "/buffer 44"
+meta-j45 = "/buffer 45"
+meta-j46 = "/buffer 46"
+meta-j47 = "/buffer 47"
+meta-j48 = "/buffer 48"
+meta-j49 = "/buffer 49"
+meta-j50 = "/buffer 50"
+meta-j51 = "/buffer 51"
+meta-j52 = "/buffer 52"
+meta-j53 = "/buffer 53"
+meta-j54 = "/buffer 54"
+meta-j55 = "/buffer 55"
+meta-j56 = "/buffer 56"
+meta-j57 = "/buffer 57"
+meta-j58 = "/buffer 58"
+meta-j59 = "/buffer 59"
+meta-j60 = "/buffer 60"
+meta-j61 = "/buffer 61"
+meta-j62 = "/buffer 62"
+meta-j63 = "/buffer 63"
+meta-j64 = "/buffer 64"
+meta-j65 = "/buffer 65"
+meta-j66 = "/buffer 66"
+meta-j67 = "/buffer 67"
+meta-j68 = "/buffer 68"
+meta-j69 = "/buffer 69"
+meta-j70 = "/buffer 70"
+meta-j71 = "/buffer 71"
+meta-j72 = "/buffer 72"
+meta-j73 = "/buffer 73"
+meta-j74 = "/buffer 74"
+meta-j75 = "/buffer 75"
+meta-j76 = "/buffer 76"
+meta-j77 = "/buffer 77"
+meta-j78 = "/buffer 78"
+meta-j79 = "/buffer 79"
+meta-j80 = "/buffer 80"
+meta-j81 = "/buffer 81"
+meta-j82 = "/buffer 82"
+meta-j83 = "/buffer 83"
+meta-j84 = "/buffer 84"
+meta-j85 = "/buffer 85"
+meta-j86 = "/buffer 86"
+meta-j87 = "/buffer 87"
+meta-j88 = "/buffer 88"
+meta-j89 = "/buffer 89"
+meta-j90 = "/buffer 90"
+meta-j91 = "/buffer 91"
+meta-j92 = "/buffer 92"
+meta-j93 = "/buffer 93"
+meta-j94 = "/buffer 94"
+meta-j95 = "/buffer 95"
+meta-j96 = "/buffer 96"
+meta-j97 = "/buffer 97"
+meta-j98 = "/buffer 98"
+meta-j99 = "/buffer 99"
+meta-k = "/input grab_key_command"
+meta-m = "/mute mouse toggle"
+meta-n = "/window scroll_next_highlight"
+meta-p = "/window scroll_previous_highlight"
+meta-r = "/input delete_line"
+meta-s = "/mute aspell toggle"
+meta-u = "/window scroll_unread"
+meta-wmeta-meta2-A = "/window up"
+meta-wmeta-meta2-B = "/window down"
+meta-wmeta-meta2-C = "/window right"
+meta-wmeta-meta2-D = "/window left"
+meta-wmeta2-1;3A = "/window up"
+meta-wmeta2-1;3B = "/window down"
+meta-wmeta2-1;3C = "/window right"
+meta-wmeta2-1;3D = "/window left"
+meta-wmeta-b = "/window balance"
+meta-wmeta-s = "/window swap"
+meta-x = "/input zoom_merged_buffer"
+meta-z = "/window zoom"
+ctrl-_ = "/input undo"
+
+[key_search]
+ctrl-I = "/input search_switch_where"
+ctrl-J = "/input search_stop"
+ctrl-M = "/input search_stop"
+ctrl-R = "/input search_switch_regex"
+meta2-A = "/input search_previous"
+meta2-B = "/input search_next"
+meta-c = "/input search_switch_case"
+
+[key_cursor]
+ctrl-J = "/cursor stop"
+ctrl-M = "/cursor stop"
+meta-meta2-A = "/cursor move area_up"
+meta-meta2-B = "/cursor move area_down"
+meta-meta2-C = "/cursor move area_right"
+meta-meta2-D = "/cursor move area_left"
+meta2-1;3A = "/cursor move area_up"
+meta2-1;3B = "/cursor move area_down"
+meta2-1;3C = "/cursor move area_right"
+meta2-1;3D = "/cursor move area_left"
+meta2-A = "/cursor move up"
+meta2-B = "/cursor move down"
+meta2-C = "/cursor move right"
+meta2-D = "/cursor move left"
+@item(buffer_nicklist):K = "/window ${_window_number};/kickban ${nick}"
+@item(buffer_nicklist):b = "/window ${_window_number};/ban ${nick}"
+@item(buffer_nicklist):k = "/window ${_window_number};/kick ${nick}"
+@item(buffer_nicklist):q = "/window ${_window_number};/query ${nick};/cursor stop"
+@item(buffer_nicklist):w = "/window ${_window_number};/whois ${nick}"
+@chat:Q = "hsignal:chat_quote_time_prefix_message;/cursor stop"
+@chat:m = "hsignal:chat_quote_message;/cursor stop"
+@chat:q = "hsignal:chat_quote_prefix_message;/cursor stop"
+
+[key_mouse]
+@bar(buffers):ctrl-wheeldown = "hsignal:buffers_mouse"
+@bar(buffers):ctrl-wheelup = "hsignal:buffers_mouse"
+@bar(input):button2 = "/input grab_mouse_area"
+@bar(nicklist):button1-gesture-down = "/bar scroll nicklist ${_window_number} +100%"
+@bar(nicklist):button1-gesture-down-long = "/bar scroll nicklist ${_window_number} e"
+@bar(nicklist):button1-gesture-up = "/bar scroll nicklist ${_window_number} -100%"
+@bar(nicklist):button1-gesture-up-long = "/bar scroll nicklist ${_window_number} b"
+@chat(perl.iset):button1 = "hsignal:iset_mouse"
+@chat(perl.iset):button2* = "hsignal:iset_mouse"
+@chat(perl.iset):wheeldown = "/repeat 5 /iset **down"
+@chat(perl.iset):wheelup = "/repeat 5 /iset **up"
+@chat(script.scripts):button1 = "/window ${_window_number};/script go ${_chat_line_y}"
+@chat(script.scripts):button2 = "/window ${_window_number};/script go ${_chat_line_y};/script installremove -q ${script_name_with_extension}"
+@chat(script.scripts):wheeldown = "/script down 5"
+@chat(script.scripts):wheelup = "/script up 5"
+@item(buffer_nicklist):button1 = "/window ${_window_number};/query ${nick}"
+@item(buffer_nicklist):button1-gesture-left = "/window ${_window_number};/kick ${nick}"
+@item(buffer_nicklist):button1-gesture-left-long = "/window ${_window_number};/kickban ${nick}"
+@item(buffer_nicklist):button2 = "/window ${_window_number};/whois ${nick}"
+@item(buffer_nicklist):button2-gesture-left = "/window ${_window_number};/ban ${nick}"
+@item(buffers):button1* = "hsignal:buffers_mouse"
+@item(buffers):button2* = "hsignal:buffers_mouse"
+@bar:wheeldown = "/bar scroll ${_bar_name} ${_window_number} +20%"
+@bar:wheelup = "/bar scroll ${_bar_name} ${_window_number} -20%"
+@chat:button1 = "/window ${_window_number}"
+@chat:button1-gesture-left = "/window ${_window_number};/buffer -1"
+@chat:button1-gesture-left-long = "/window ${_window_number};/buffer 1"
+@chat:button1-gesture-right = "/window ${_window_number};/buffer +1"
+@chat:button1-gesture-right-long = "/window ${_window_number};/input jump_last_buffer"
+@chat:ctrl-wheeldown = "/window scroll_horiz -window ${_window_number} +10%"
+@chat:ctrl-wheelup = "/window scroll_horiz -window ${_window_number} -10%"
+@chat:wheeldown = "/window scroll_down -window ${_window_number}"
+@chat:wheelup = "/window scroll_up -window ${_window_number}"
+@*:button3 = "/cursor go ${_x},${_y}"