You can see that this would be a problem when users are chatting, having to always take your attention off of the session just to scroll down and view the whole message. Currently the program uses the code $chat_textview->scroll_to_mark where mark is defined as the end iter of the buffer. I cant figure how to get this to work and show the whole text without the user having to manually scroll down. I am wondering if the word wrapping is causing it since this behavior is true for a single unwrapped line. I would appreciate any help on this since it seems like such a simple thing and I cant figure it.
#!/usr/local/bin/perl -w
use strict;
use Gtk2 '-init';
use Glib qw/TRUE FALSE/;
use Net::IRC;
use threads;
use threads::shared;
my $irc = new Net::IRC;
my $chat_state = 'Connect';
my $chat_entry;
my $chat_send_sig;
my $chat_textview;
my $chat_button;
my $sys_msg;
my $tag;
my $die:shared = 0;
my $chat_start:shared = 0;
my $channel:shared = "#GRRUVI";
my $irc_server:shared = "irc.servercentral.net";
my $nick:shared = "VCBase";
my $msg:shared;
my $post:shared = 0;
my $name:shared = 0;
my $list:shared;
#################################################
#Threads
my $thread_chat = threads->new(\&chat);
#################################################
#################################################
#Timeout
my $timer_post = Glib::Timeout->add(100, \&post);
#################################################
#-------------------Main Loop-------------------
&chat_build;
Gtk2->main;
####################CHAT BLOCK####################
#-------------------chat Build-------------------
sub chat_build {
my $chat_window = Gtk2::Window->new('toplevel');
$chat_window->set_title('Chat Client');
$chat_window->set_position('center');
$chat_window->set_default_size( 300, 300 );
$chat_window->signal_connect(delete_event=> sub{
$die = 1;
$thread_chat->join;
Gtk2->main_quit;
});
$chat_entry = Gtk2::Entry->new;
my $chat_vbox = Gtk2::VBox->new;
my $chat_scroll = Gtk2::ScrolledWindow->new(undef, undef);
$chat_scroll->set_policy('never', 'always');
$chat_scroll->set_shadow_type( 'etched-out');
$chat_textview = Gtk2::TextView->new;
my $chat_buffer = $chat_textview->get_buffer;
$chat_buffer->create_mark( 'end', $chat_buffer->get_end_iter, FALSE );
$chat_buffer->signal_connect(insert_text => sub {
$chat_textview->scroll_to_mark( $chat_buffer->get_mark('end'), 0.0, TRUE, 0.0, 1.0 );
});
$chat_button = Gtk2::Button->new;
$chat_button->set_label($chat_state);
# allows for sending each line with an enter keypress
$chat_send_sig = $chat_entry->signal_connect ('key-press-event' =>
sub {
my ($widget,$event)= @_;
if( $event->keyval() == 65293){ # a return key press
$msg = $chat_entry->get_text;
$chat_entry->set_text('');
$chat_entry->set_position(0);
$chat_start = 2;
$name = $nick;
$post = 6;
#print "$chat_start\n";
}
});
$chat_entry->signal_handler_block($chat_send_sig); #not connected yet
$chat_entry->set_editable(0);
$chat_textview->set_editable(0);
$chat_textview->set_cursor_visible(0);
$chat_textview->set_wrap_mode('char');
$chat_scroll->add($chat_textview);
$chat_vbox->add($chat_scroll);
$chat_vbox->pack_start( $chat_entry, FALSE, FALSE, 0 );
$chat_vbox->pack_start( $chat_button, FALSE, FALSE, 0 );
$chat_window->add($chat_vbox);
$chat_window->show_all;
$chat_button->signal_connect("clicked" => sub {
if ($chat_state eq 'Connect') {
$chat_button->set_label('Disconnect');
$chat_state='Disconnect';
$chat_start = 1;
$post = 1;
}
else {
$chat_button->set_label('Connect');
$chat_state='Connect';
$chat_start = 0;
$post = 5;
}
});
return 1;
my $chat_buffer = $chat_textview->get_buffer;
#connecting
if ($post == 1){
$chat_buffer->insert( $chat_buffer->get_end_iter, "Connecting
to $irc_server..\n" );
$post = 0;
}
#Connected
if ($post == 2){
$chat_buffer->insert( $chat_buffer->get_end_iter, "Connected to $irc_server\n" );
$chat_entry->set_editable(1);
$chat_entry->grab_focus;
$chat_entry->signal_handler_unblock ($chat_send_sig);
$post = 0;
}
#Joined
if ($post == 3){
if ($name ne $nick){
$chat_buffer->insert_with_tags( $chat_buffer->get_end_iter, "$name Joined $channel$post_time\n", $chat_buffer->create_tag($tag, foreground=>'red'));
}
else{
$chat_buffer->insert( $chat_buffer->get_end_iter, "$name Joined $channel$post_time\n");
}
return 1;
$conn = $irc->newconn(Server => $irc_server,
Port => 6667,
Nick => $nick,
Ircname => "CoCoNUE Member $nick")
or die "Can't connect to IRC server\n";
#Install Handlers
$conn->add_handler('cping', \&on_ping); #
$conn->add_handler('crping', \&on_ping_reply); #
$conn->add_handler('join', \&on_join); #3
$conn->add_handler('quit', \&on_quit); #9
$conn->add_handler('public', \&on_public); #6
$conn->add_global_handler([ 251,252,253,254,302,255 ], \&on_init);
$conn->add_global_handler('disconnect', \&on_disconnect); #7
$conn->add_global_handler(376, \&on_connect); #2
$conn->add_global_handler(433, \&on_nick_taken); #8
$conn->add_global_handler(353, \&on_names); #4
for (;;){
$irc->do_one_loop;
if ($chat_start == 2){
$conn->privmsg("$channel", "$msg");
$chat_start = 1 if $chat_start != 0;
}
goto END if $die == 1;
last if $chat_start == 0;
}
$irc->removeconn($conn);
}
}
END:
# What to do when the bot successfully connects.
sub on_connect {
my $self = shift;
$post = 2;
sleep 1;
print "Joining $channel...\n";
$self->join("$channel");
$post = 3;
sleep 1;
printf "*** %s (%s) has joined channel %s\n",
$event->nick, $event->userhost, $channel;
if ($event->userhost =~ /^corbeau\ *execpc\ com/) { # Auto-ops anyone who
$self->mode("#IRC.pm", "+o", $event->nick); # matches hostmask.
}
$post = 4;
print "Users on $channel: @list\n";
$self->ctcp_reply($name, join (' ', ($event->args)));
print "*** CTCP PING request from $name received\n";
$args = time - $args;
print "*** CTCP PING reply from $name: $args sec.\n";
$post = 7;
print "Disconnected from ", $event->from(), " (",
($event->args())[0], "). Attempting to reconnect...\n";
$self->connect();
$post = 6;
# Note that $event->to() returns a list (or arrayref, in scalar
# context) of the message's recipients, since there can easily be
# more than one.