1use strict; # use warnings;
2
3# FIXME COULD SOMEONE PLEASE TELL ME HOW TO SHUT UP
4#
5# ...
6# Variable "*" will not stay shared at (eval *) line *.
7# Variable "*" will not stay shared at (eval *) line *.
8# ...
9# Can't locate package Irssi::Nick for @Irssi::Irc::Nick::ISA at (eval *) line *.
10# ...
11#
12# THANKS
13
14use Irssi (); # which is the minimum required version of Irssi ?
15use Irssi::TextUI;
16
17use vars qw($VERSION %IRSSI);
18
19$VERSION = '0.5';
20%IRSSI = (
21    authors     => 'BC-bd, Veli, Timo \'cras\' Sirainen, Wouter Coekaerts, Nei',
22    contact     => 'bd@bc-bd.org, veli@piipiip.net, tss@iki.fi, wouter@coekaerts.be, Nei@QuakeNet',
23    name        => 'wlstat',
24    description => 'Adds a window list in the status area. Based on chanact.pl by above authors.',
25    license     => 'GNU GPLv2 or later',
26);
27
28# adapted by Nei
29
30###############
31# original comment
32# ###########
33# # Adds new powerful and customizable [Act: ...] item (chanelnames,modes,alias).
34# # Lets you give alias characters to windows so that you can select those with
35# # meta-<char>.
36# #
37# # for irssi 0.8.2 by bd@bc-bd.org
38# #
39# # inspired by chanlist.pl by 'cumol@hammerhart.de'
40# #
41# #########
42# # Contributors
43# #########
44# #
45# # veli@piipiip.net   /window_alias code
46# # qrczak@knm.org.pl  chanact_abbreviate_names
47# # qerub@home.se      Extra chanact_show_mode and chanact_chop_status
48# #
49#
50# FURTHER THANKS TO
51# ############
52# # buu, fxn, Somni, Khisanth, integral, tybalt89   for much support in any aspect perl
53# # and the channel in general ( #perl @ freenode ) and especially the ir_* functions
54# #
55# # Valentin 'senneth' Batz ( vb@g-23.org ) for the pointer to grep.pl, continuous support
56# #                                         and help in digging up ir_strip_codes
57# #
58# # OnetrixNET technology networks for the debian environment
59# #
60# # Monkey-Pirate.com / Spaceman Spiff for the webspace
61# #
62#
63
64######
65# M A I N    P R O B L E M
66#####
67#
68# It is impossible to place the wlstat on a statusbar together with other items, because I
69# do not know how to calculate the size that it is going to get granted, and therefore I
70# cannot do the linebreaks properly.
71# This is what is missing to make a nice script out of wlstat.
72# If you have any ideas, please contact me ASAP :).
73#
74######
75
76######
77# UTF-8 PROBLEM
78#####
79#
80# Please help me find a solution to this:
81# this be your statusbar, it is using up the maximum term size
82# [[1=1]#abc [2=2]#defghi]
83#
84# now consider this example: "ascii" characters are marked with ., utf-8 characters with *
85# [[1=1]#... [2=2]#...***]
86#
87# you should think that this is how it would be displayed? WRONG!
88# [[1=1]#... [2=2]#...***   ]
89#
90# this is what Irssi does.. I believe my length calculating code to be correct, however, I'd
91# love to be proven wrong (or receive any other fix, too, of course!)
92#
93######
94
95#########
96# USAGE
97###
98#
99# copy the script to ~/.irssi/scripts/
100#
101# In irssi:
102#
103#		/script load wlstat
104#
105#
106# Hint: to get rid of the old [Act:] display
107#     /statusbar window remove act
108#
109# to get it back:
110#     /statusbar window add -after lag -priority 10 act
111#
112##########
113# OPTIONS
114########
115#
116# /set wlstat_display_nokey <string>
117# /set wlstat_display_key <string>
118#		* string : Format String for one window. The following $'s are expanded:
119#		    $C : Name
120#		    $N : Number of the Window
121#		    $Q : meta-Keymap
122#		    $H : Start highlighting
123#		    $S : Stop highlighting
124#     IMPORTANT: don't forget to use $S if you used $H before!
125#
126# /set wlstat_separator <string>
127#     * string : Charater to use between the channel entries
128#     you'll need to escape " " space and "$" like this:
129#     "/set wlstat_separator \ "
130#     "/set wlstat_separator \$"
131#     and {}% like this:
132#     "/set wlstat_separator %{"
133#     "/set wlstat_separator %}"
134#     "/set wlstat_separator %%"
135#     (reason being, that the separator is used inside a {format })
136#
137# /set wlstat_hide_data <num>
138#     * num : hide the window if its data_level is below num
139#     set it to 0 to basically disable this feature,
140#               1 if you don't want windows without activity to be shown
141#               2 to show only those windows with channel text or hilight
142#               3 to show only windows with hilight
143#
144# /set wlstat_maxlines <num>
145#     * num : number of lines to use for the window list (0 to disable)
146#
147# /set wlstat_sort <-data_level|-last_line|refnum>
148#     * you can change the window sort order with this variable
149#         -data_level : sort windows with hilight first
150#         -last_line  : sort windows in order of activity
151#         refnum      : sort windows by window number
152#
153# /set wlstat_placement <top|bottom>
154# /set wlstat_position <num>
155#     * these settings correspond to /statusbar because wlstat will create
156#       statusbars for you
157#     (see /help statusbar to learn more)
158#
159# /set wlstat_all_disable <ON|OFF>
160#     * if you set wlstat_all_disable to ON, wlstat will also remove the
161#       last statusbar it created if it is empty.
162#       As you might guess, this only makes sense with wlstat_hide_data > 0 ;)
163#
164###
165# WISHES
166####
167#
168# if you fiddle with my mess, provide me with your fixes so I can benefit as well
169#
170# Nei =^.^= ( QuakeNet accountname: ailin )
171#
172
173my $actString = [];   # statusbar texts
174my $currentLines = 0;
175my $resetNeeded;      # layout/screen has changed, redo everything
176my $needRemake;       # "normal" changes
177#my $callcount = 0;
178my $globTime = undef; # timer to limit remake() calls
179
180my %statusbars;       # currently active statusbars
181
182# maybe I should just tie the array ?
183sub add_statusbar {
184	for (@_) {
185		# add subs
186		for my $l ($_) { eval {
187			no strict 'refs'; # :P
188			*{"wlstat$l"} = sub { wlstat($l, @_) };
189		}; }
190		Irssi::command("statusbar wl$_ reset");
191		Irssi::command("statusbar wl$_ enable");
192		if (lc Irssi::settings_get_str('wlstat_placement') eq 'top') {
193			Irssi::command("statusbar wl$_ placement top");
194		}
195		if ((my $x = int Irssi::settings_get_int('wlstat_position')) != 0) {
196			Irssi::command("statusbar wl$_ position $x");
197		}
198		Irssi::command("statusbar wl$_ add -priority 100 -alignment left barstar");
199		Irssi::command("statusbar wl$_ add wlstat$_");
200		Irssi::command("statusbar wl$_ add -priority 100 -alignment right barend");
201		Irssi::command("statusbar wl$_ disable");
202		Irssi::statusbar_item_register("wlstat$_", '$0', "wlstat$_");
203		$statusbars{$_} = {};
204	}
205}
206
207sub remove_statusbar {
208	for (@_) {
209		Irssi::command("statusbar wl$_ reset");
210		Irssi::statusbar_item_unregister("wlstat$_"); # XXX does this actually work ?
211		# DO NOT REMOVE the sub before you have unregistered it :))
212		for my $l ($_) { eval {
213			no strict 'refs';
214			undef &{"wlstat$l"};
215		}; }
216		delete $statusbars{$_};
217	}
218}
219
220sub syncLines {
221	my $temp = $currentLines;
222	$currentLines = @$actString;
223	#Irssi::print("current lines: $temp new lines: $currentLines");
224	my $currMaxLines = Irssi::settings_get_int('wlstat_maxlines');
225	if ($currMaxLines > 0 and @$actString > $currMaxLines) {
226		$currentLines = $currMaxLines;
227	}
228	return if ($temp == $currentLines);
229	if ($currentLines > $temp) {
230		for ($temp .. ($currentLines - 1)) {
231			add_statusbar($_);
232			Irssi::command("statusbar wl$_ enable");
233		}
234	}
235	else {
236		for ($_ = ($temp - 1); $_ >= $currentLines; $_--) {
237			Irssi::command("statusbar wl$_ disable");
238			remove_statusbar($_);
239		}
240	}
241}
242
243my %keymap;
244
245sub get_keymap {
246	my ($textDest, undef, $cont_stripped) = @_;
247	if ($textDest->{'level'} == 524288 and $textDest->{'target'} eq '' and !defined($textDest->{'server'})) {
248		if ($cont_stripped =~ m/meta-(.)\s+change_window (\d+)/) { $keymap{$2} = "$1"; }
249		Irssi::signal_stop();
250	}
251}
252
253sub update_keymap {
254	%keymap = ();
255	Irssi::signal_remove('command bind' => 'watch_keymap');
256	Irssi::signal_add_first('print text' => 'get_keymap');
257	Irssi::command('bind'); # stolen from grep
258	Irssi::signal_remove('print text' => 'get_keymap');
259	Irssi::signal_add('command bind' => 'watch_keymap');
260	Irssi::timeout_add_once(100, 'eventChanged', undef);
261}
262
263# watch keymap changes
264sub watch_keymap {
265	Irssi::timeout_add_once(1000, 'update_keymap', undef);
266}
267
268update_keymap();
269
270sub expand {
271	my ($string, %format) = @_;
272	my ($exp, $repl);
273	$string =~ s/\$$exp/$repl/g while (($exp, $repl) = each(%format));
274	return $string;
275}
276
277# FIXME implement $get_size_only check, and user $item->{min|max-size} ??
278sub wlstat {
279	my ($line, $item, $get_size_only) = @_;
280
281	if ($needRemake) {
282		$needRemake = undef;
283		remake();
284	}
285
286	my $text = $actString->[$line];  # DO NOT set the actual $actString->[$line] to '' here or
287	$text = '' unless defined $text; # you'll screw up the statusbar counter ($currentLines)
288	$item->default_handler($get_size_only, $text, '', 1);
289}
290
291my %strip_table = (
292	# fe-common::core::formats.c:format_expand_styles
293	#      delete                format_backs  format_fores bold_fores   other stuff
294	(map { $_ => '' } (split //, '04261537' .  'kbgcrmyw' . 'KBGCRMYW' . 'U9_8:|FnN>#[')),
295	#      escape
296	(map { $_ => $_ } (split //, '{}%')),
297);
298sub ir_strip_codes { # strip %codes
299	my $o = shift;
300	$o =~ s/(%(.))/exists $strip_table{$2} ? $strip_table{$2} : $1/gex;
301	$o
302}
303
304sub ir_parse_special {
305	my $o; my $i = shift;
306	my $win = Irssi::active_win();
307	my $server = Irssi::active_server();
308	if (ref $win and ref $win->{'active'}) {
309		$o = $win->{'active'}->parse_special($i);
310	}
311	elsif (ref $win and ref $win->{'active_server'}) {
312		$o = $win->{'active_server'}->parse_special($i);
313	}
314	elsif (ref $server) {
315		$o =  $server->parse_special($i);
316	}
317	else {
318		$o = Irssi::parse_special($i);
319	}
320	$o
321}
322
323sub sb_expand { # expand {format }s (and apply parse_special for $vars)
324	ir_parse_special(
325		Irssi::current_theme->format_expand(
326			shift,
327			(
328				Irssi::EXPAND_FLAG_IGNORE_REPLACES
329					|
330				Irssi::EXPAND_FLAG_IGNORE_EMPTY
331			)
332		)
333	)
334}
335sub sb_strip {
336	ir_strip_codes(
337		sb_expand(shift)
338	); # does this get us the actual length of that s*ty bar :P ?
339}
340sub sb_length {
341	# unicode cludge, d*mn broken Irssi
342	# screw it, this will fail from broken joining anyway (and cause warnings)
343	if (lc Irssi::settings_get_str('term_type') eq 'utf-8') {
344		my $temp = sb_strip(shift);
345		# try to switch on utf8
346		eval {
347			no warnings;
348			require Encode;
349			#$temp = Encode::decode_utf8($temp); # thanks for the hint, but I have my reasons for _utf8_on
350			Encode::_utf8_on($temp);
351		};
352		length($temp)
353	}
354	else {
355		length(sb_strip(shift))
356	}
357}
358
359# !!! G*DD*MN Irssi is adding an additional layer of backslashitis per { } layer
360# !!! AND I still don't know what I need to escape.
361# !!! and NOONE else seems to know or care either.
362# !!! f*ck open source. I mean it.
363# XXX any Irssi::print debug statement leads to SEGFAULT - why ?
364
365# major parts of the idea by buu (#perl @ freenode)
366# thanks to fxn and Somni for debugging
367#	while ($_[0] =~ /(.)/g) {
368#		my $c = $1; # XXX sooo... goto kills $1
369#		if ($q eq '%') { goto ESC; }
370
371## <freenode:#perl:tybalt89> s/%(.)|(\{)|(\})|(\\|\$)/$1?$1:$2?($level++,$2):$3?($level>$min_level&&$level--,$3):'\\'x(2**$level-1).$4/ge;  # untested...
372sub ir_escape {
373	my $min_level = $_[1] || 0; my $level = $min_level;
374	my $o = shift;
375	$o =~ s/
376		(	%.	)	| # $1
377		(	\{	)	| # $2
378		(	\}	)	| # $3
379		(	\\	)	| # $4
380		(	\$(?=.)	)	| # $5
381		(	\$	) # $6
382	/
383		if ($1) { $1 } # %. escape
384		elsif ($2) { $level++; $2 } # { nesting start
385		elsif ($3) { if ($level > $min_level) { $level--; } $3 } # } nesting end
386		elsif ($4) { '\\'x(2**$level) } # \ needs \\escaping
387		elsif ($5) { '\\'x(2**$level-1) . '$' . '\\'x(2**$level-1) } # and $ needs even more because of "parse_special"
388		else { '\\'x(2**$level-1) . '$' } # $ needs \$ escaping
389	/gex;
390	$o
391}
392#sub ir_escape {
393#	my $min_level = $_[1] || 0; my $level = $min_level;
394#	my $o = shift;
395#	$o =~ s/
396#		(	%.	)	| # $1
397#		(	\{	)	| # $2
398#		(	\}	)	| # $3
399#		(	\\	|	\$	)	# $4
400#	/
401#		if ($1) { $1 } # %. escape
402#		elsif ($2) { $level++; $2 } # { nesting start
403#		elsif ($3) { if ($level > $min_level) { $level--; } $3 } # } nesting end
404#		else { '\\'x(2**($level-1)-1) . $4 } # \ or $ needs \\escaping
405#	/gex;
406#	$o
407#}
408
409sub ir_fe { # try to fix format stuff
410	my $x = shift;
411	# XXX why do I have to use two/four % here instead of one/two ?? answer: you screwed up in ir_escape
412	$x =~ s/([%{}])/%$1/g;
413	$x =~ s/(\\|\$)/\\$1/g;
414	#$x =~ s/(\$(?=.))|(\$)/$1?"\\\$\\":"\\\$"/ge; # I think this should be here (logic), but it doesn't work that way :P
415	#$x =~ s/\\/\\\\/g; # that's right, escape escapes
416	$x
417}
418
419sub remake () {
420	#$callcount++;
421	#my $xx = $callcount; Irssi::print("starting remake [ $xx ]");
422	my ($hilight, $number, $display);
423	my $separator = '{sb_act_sep ' . Irssi::settings_get_str('wlstat_separator') . '}';
424	my $custSort = Irssi::settings_get_str('wlstat_sort');
425	my $custSortDir = 1;
426	if ($custSort =~ /^[-!](.*)/) {
427		$custSortDir = -1;
428		$custSort = $1;
429	}
430
431	$actString = [];
432	my ($line, $width) = (0, [Irssi::windows]->[0]{'width'} - sb_length('{sb x}'));
433	foreach my $win (
434		sort {
435			(
436				( (int($a->{$custSort}) <=> int($b->{$custSort})) * $custSortDir )
437					||
438				($a->{'refnum'} <=> $b->{'refnum'})
439			)
440		} Irssi::windows
441	) {
442		$actString->[$line] = '' unless defined $actString->[$line] or Irssi::settings_get_bool('wlstat_all_disable');
443
444		# all stolen from chanact, what does this code do and why do we need it ?
445		!ref($win) && next;
446
447		my $name = $win->get_active_name;
448		my $active = $win->{'active'};
449		my $colour = $win->{'hilight_color'};
450		if (!defined $colour) { $colour = ''; }
451
452		if ($win->{'data_level'} < Irssi::settings_get_int('wlstat_hide_data')) { next; } # for Geert
453		if    ($win->{'data_level'} == 0) { $hilight = '{sb_act_none '; }
454		elsif ($win->{'data_level'} == 1) { $hilight = '{sb_act_text '; }
455		elsif ($win->{'data_level'} == 2) { $hilight = '{sb_act_msg '; }
456		elsif ($colour             ne '') { $hilight = "{sb_act_hilight_color $colour "; }
457		elsif ($win->{'data_level'} == 3) { $hilight = '{sb_act_hilight '; }
458		else                              { $hilight = '{sb_act_special '; }
459
460		$number = $win->{'refnum'};
461		$display = (defined $keymap{$number} and $keymap{$number} ne '')
462				?
463			(
464				Irssi::settings_get_str('wlstat_display_key')
465					||
466				Irssi::settings_get_str('wlstat_display_nokey')
467			)
468				:
469			Irssi::settings_get_str('wlstat_display_nokey')
470		;
471
472		my $add = expand($display,
473			C => ir_fe($name),
474			N => $number,
475			Q => ir_fe($keymap{$number}),
476			H => $hilight,
477			S => '}{sb_background}'
478		);
479		#$temp =~ s/\{\S+?(?:\s(.*?))?\}/$1/g;
480		#$temp =~ s/\\\\\\\\/\\/g; # XXX I'm actually guessing here, someone point me to docs please
481		$actString->[$line] = '' unless defined $actString->[$line];
482
483		# XXX how can I check whether the content still fits in the bar? this would allow
484		# XXX wlstatus to reside on a statusbar together with other items...
485		if (sb_length(ir_escape($actString->[$line] . $add)) >= $width) { # XXX doesn't correctly handle utf-8 multibyte ... help !!?
486			$actString->[$line] .= ' ' x ($width - sb_length(ir_escape($actString->[$line])));
487			$line++;
488		}
489		$actString->[$line] .= $add . $separator;
490		# XXX if I use these prints, output layout gets screwed up... why ?
491		#Irssi::print("line $line: ".$actString->[$line]);
492		#Irssi::print("temp $line: ".$temp);
493	}
494
495	# XXX the Irssi::print statements lead to the MOST WEIRD results
496	# e.g.: the loop gets executed TWICE for p > 0 ?!?
497	for (my $p = 0; $p < @$actString; $p++) { # wrap each line in {sb }, escape it properly, etc.
498		my $x = $actString->[$p];
499		$x =~ s/\Q$separator\E([ ]*)$/$1/;
500		#Irssi::print("[$p]".'current:'.join'.',split//,sb_strip(ir_escape($x,0)));
501		#Irssi::print("assumed length before:".sb_length(ir_escape($x,0)));
502		$x = "{sb $x}";
503		#Irssi::print("[$p]".'new:'.join'.',split//,sb_expand(ir_escape($x,0)));
504		#Irssi::print("[$p]".'new:'.join'.',split//,ir_escape($x,0));
505		#Irssi::print("assumed length after:".sb_length(ir_escape($x,0)));
506		$x = ir_escape($x);
507		#Irssi::print("[$p]".'REALnew:'.join'.',split//,sb_strip($x));
508		$actString->[$p] = $x;
509		# XXX any Irssi::print debug statement leads to SEGFAULT (sometimes) - why ?
510	}
511	#Irssi::print("remake [ $xx ] finished");
512}
513
514sub wlstatHasChanged () {
515	$globTime = undef;
516	my $temp = Irssi::settings_get_str('wlstat_placement').Irssi::settings_get_int('wlstat_position');
517	if ($temp ne $resetNeeded) { wlreset(); return; }
518	#Irssi::print("wlstat has changed, calls to remake so far: $callcount");
519	$needRemake = 1;
520
521	#remake();
522	if (
523		($needRemake and Irssi::settings_get_bool('wlstat_all_disable'))
524			or
525		(!Irssi::settings_get_bool('wlstat_all_disable') and $currentLines < 1)
526	) {
527		$needRemake = undef;
528		remake();
529	}
530	# XXX Irssi crashes if I try to do this without timer, why ? What's the minimum delay I need to use in the timer ?
531	Irssi::timeout_add_once(100, 'syncLines', undef);
532
533	for (keys %statusbars) {
534		Irssi::statusbar_items_redraw("wlstat$_");
535	}
536}
537
538sub eventChanged () { # Implement a change queue/blocker -.-)
539	if (defined $globTime) {
540		Irssi::timeout_remove($globTime);
541	} # delay the update further
542	$globTime = Irssi::timeout_add_once(10, 'wlstatHasChanged', undef);
543}
544
545#$needRemake = 1;
546sub resizeTerm () {
547	Irssi::timeout_add_once(100, 'eventChanged', undef);
548}
549
550Irssi::settings_add_str('wlstat', 'wlstat_display_nokey', '[$N]$H$C$S');
551Irssi::settings_add_str('wlstat', 'wlstat_display_key', '[$Q=$N]$H$C$S');
552Irssi::settings_add_str('wlstat', 'wlstat_separator', "\\ ");
553Irssi::settings_add_int('wlstat', 'wlstat_hide_data', 0);
554Irssi::settings_add_int('wlstat', 'wlstat_maxlines', 9);
555Irssi::settings_add_str('wlstat', 'wlstat_sort', 'refnum');
556Irssi::settings_add_str('wlstat', 'wlstat_placement', 'bottom');
557Irssi::settings_add_int('wlstat', 'wlstat_position', 0);
558Irssi::settings_add_bool('wlstat', 'wlstat_all_disable', 0);
559
560# remove old statusbars
561my %killBar;
562sub get_old_status {
563	my ($textDest, $cont, $cont_stripped) = @_;
564	if ($textDest->{'level'} == 524288 and $textDest->{'target'} eq '' and !defined($textDest->{'server'})) {
565		if ($cont_stripped =~ m/^wl(\d+)\s/) { $killBar{$1} = {}; }
566		Irssi::signal_stop();
567	}
568}
569sub killOldStatus {
570	%killBar = ();
571	Irssi::signal_add_first('print text' => 'get_old_status');
572	Irssi::command('statusbar');
573	Irssi::signal_remove('print text' => 'get_old_status');
574	remove_statusbar(keys %killBar);
575}
576#killOldStatus();
577
578sub wlreset {
579	$actString = [];
580	$currentLines = 0; # 1; # mhmmmm .. we actually enable one line down there so let's try this.
581	$resetNeeded = Irssi::settings_get_str('wlstat_placement').Irssi::settings_get_int('wlstat_position');
582	#update_keymap();
583	killOldStatus();
584	# Register statusbar
585	#add_statusbar(0);
586	#Irssi::command('statusbar wl0 enable');
587	resizeTerm();
588}
589
590wlreset();
591
592my $Unload;
593sub unload ($$$) {
594	$Unload = 1;
595	Irssi::timeout_add_once(10, sub { $Unload = undef; }, undef); # pretend we didn't do anything ASAP
596}
597Irssi::signal_add_first('gui exit' => sub { $Unload = undef; }); # last try to catch a sigsegv
598sub UNLOAD {
599	if ($Unload) { # this might well crash Irssi... try /eval /script unload someotherscript ; /quit (= SEGFAULT !)
600		$actString = ['']; # syncLines(); # XXX Irssi crashes when trying to disable all statusbars ?
601		killOldStatus();
602	}
603}
604
605sub addPrintTextHook { # update on print text
606	return if $_[0]->{'level'} == 262144 and $_[0]->{'target'} eq '' and !defined($_[0]->{'server'});
607	if (Irssi::settings_get_str('wlstat_sort') =~ /^[-!]?last_line$/) {
608		Irssi::timeout_add_once(100, 'eventChanged', undef);
609	}
610}
611
612#sub _x { my ($x, $y) = @_; ($x, sub { Irssi::print('-->signal '.$x); eval "$y();"; }) }
613#sub _x { @_ }
614Irssi::signal_add_first(
615	'command script unload' => 'unload'
616);
617Irssi::signal_add_last({
618	'setup changed' => 'eventChanged',
619	'print text' => 'addPrintTextHook',
620	'terminal resized' => 'resizeTerm',
621	'setup reread' => 'wlreset',
622	'window hilight' => 'eventChanged',
623});
624Irssi::signal_add({
625	'window created' => 'eventChanged',
626	'window destroyed' => 'eventChanged',
627	'window name changed' => 'eventChanged',
628	'window refnum changed' => 'eventChanged',
629	'window changed' => 'eventChanged',
630	'window changed automatic' => 'eventChanged',
631});
632
633#Irssi::signal_add('nick mode changed', 'chanactHasChanged'); # relicts
634
635###############
636###
637#
638# Changelog
639#
640# 0.5a
641# - add setting to also hide the last statusbar if empty (wlstat_all_disable)
642# - reverted to old utf8 code to also calculate broken utf8 length correctly
643# - simplified dealing with statusbars in wlreset
644#
645# 0.4d
646# - fixed order of disabling statusbars
647# - several attempts at special chars, without any real success
648#   and much more weird new bugs caused by this
649# - setting to specify sort order
650# - reduced timeout values
651# - added wlstat_hide_data for Geert Hauwaerts ( geert@irssi.org ) :)
652# - make it so the dynamic sub is actually deleted
653# - fix a bug with removing of the last separator
654# - take into consideration parse_special
655#
656# 0.3b
657# - automatically kill old statusbars
658# - reset on /reload
659# - position/placement settings
660#
661# 0.2
662# - automated retrieval of key bindings (thanks grep.pl authors)
663# - improved removing of statusbars
664# - got rid of status chop
665#
666# 0.1
667# - rewritten to suit my needs
668# - based on chanact 0.5.5
669
670