Changeset a827529


Ignore:
Timestamp:
Jan 11, 2008, 2:28:36 PM (16 years ago)
Author:
Alejandro R. Sedeño <asedeno@mit.edu>
Branches:
master, barnowl_perlaim, debian, release-1.10, release-1.4, release-1.5, release-1.6, release-1.7, release-1.8, release-1.9
Children:
fac5463
Parents:
16c6cca (diff), 9e02bb7 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:
Merged revisions 812-830 via svnmerge from 
file:///afs/sipb.mit.edu/project/barnowl/src/svn/trunk

........
  r814 | nelhage | 2008-01-09 23:14:20 -0500 (Wed, 09 Jan 2008) | 3 lines
  
   r27181@lunatique:  nelhage | 2008-01-09 23:13:52 -0500
   Implement /part and /names. We don't parse the /names response yet
........
  r815 | nelhage | 2008-01-10 00:12:52 -0500 (Thu, 10 Jan 2008) | 1 line
  
  Show PART and JOIN messages
........
  r816 | nelhage | 2008-01-10 00:13:11 -0500 (Thu, 10 Jan 2008) | 2 lines
  
  Show the channel in LOG{IN,OUT} messages
........
  r817 | geofft | 2008-01-10 00:32:44 -0500 (Thu, 10 Jan 2008) | 6 lines
  
  A (broken) attempt at handling motds and other IRC admin messages
  
  Export owl_function_beep() to Perl, and ring the bell on receiving a message
  containing your nick (on that network)
........
  r818 | nelhage | 2008-01-10 01:01:32 -0500 (Thu, 10 Jan 2008) | 2 lines
  
  Document the IRC variables
........
  r819 | nelhage | 2008-01-10 01:02:06 -0500 (Thu, 10 Jan 2008) | 3 lines
  
  Handle recreation of an existing variable better. Copy over the
  default and docstrings, but preserve the old value.
........
  r820 | nelhage | 2008-01-10 01:16:33 -0500 (Thu, 10 Jan 2008) | 2 lines
  
  Handle zephyrs to users on non -c message better (fixes #39)
........
  r821 | nelhage | 2008-01-10 01:28:59 -0500 (Thu, 10 Jan 2008) | 2 lines
  
  sprintf -> snprintf
........
  r822 | nelhage | 2008-01-10 01:43:11 -0500 (Thu, 10 Jan 2008) | 2 lines
  
  Make :reload-modules work correctly with PARs
........
  r823 | nelhage | 2008-01-10 15:47:00 -0500 (Thu, 10 Jan 2008) | 1 line
  
  Require 'isprivate' to be a literal 'true', not merely present for a message to be considered private
........
  r824 | nelhage | 2008-01-10 15:48:00 -0500 (Thu, 10 Jan 2008) | 2 lines
  
  Document (nearly) every public function in the BarnOwl:: namespace
........
  r825 | nelhage | 2008-01-10 15:49:27 -0500 (Thu, 10 Jan 2008) | 2 lines
  
  `beep' is already a barnowl command, so this binding is superfluous
........
  r826 | nelhage | 2008-01-10 15:58:49 -0500 (Thu, 10 Jan 2008) | 1 line
  
  strip IRC coloring from IRC messages
........
  r827 | nelhage | 2008-01-10 17:22:46 -0500 (Thu, 10 Jan 2008) | 2 lines
  
  Document ::Hook and ::Hooks
........
  r828 | geofft | 2008-01-10 21:01:27 -0500 (Thu, 10 Jan 2008) | 1 line
  
  Move comment around so that perlglue.xs compiles.
........
  r829 | nelhage | 2008-01-10 23:25:27 -0500 (Thu, 10 Jan 2008) | 1 line
  
  doc nits
........
  r830 | nelhage | 2008-01-11 01:38:50 -0500 (Fri, 11 Jan 2008) | 2 lines
  
  Handle `nickinuse' errors and disconnects
........
Files:
2 added
30 edited

Legend:

Unmodified
Added
Removed
  • message.c

    r3a7cf49 ra827529  
    330330  res=owl_message_get_attribute_value(m, "isprivate");
    331331  if (!res) return(0);
    332   return(1);
     332  return !strcmp(res, "true");
    333333}
    334334
  • perl/lib/BarnOwl/ModuleLoader.pm

    rbe98ba5 rb0c8011  
    99
    1010sub load_all {
     11    PAR::reload_libs();
    1112    my %modules;
    1213    my @modules;
     
    3637    for my $class (keys %modules) {
    3738        if(!defined eval "use BarnOwl::Module::$class") {
    38             BarnOwl::error("Unable to load module $class: $!") if $!;
     39            # BarnOwl::error("Unable to load module $class: $!") if $!;
    3940            BarnOwl::error("Unable to load module $class: $@") if $@;
    4041        }
     
    4748    BarnOwl::new_command('reload-modules', sub {BarnOwl::ModuleLoader->reload}, {
    4849                           summary => 'Reload all modules',
    49                            usage   => 'reload',
     50                           usage   => 'reload-modules',
    5051                           description => q{Reloads all modules located in ~/.owl/modules and the system modules directory}
    5152                          });
  • perl/modules/IRC/lib/BarnOwl/Message/IRC.pm

    r0e52069 r2fb58e4  
    5656sub long_sender {shift->{from} || ""};
    5757
     58sub login_extra { shift->channel; }
     59
    5860
    59611;
  • perl/modules/IRC/lib/BarnOwl/Module/IRC.pm

    r6286f26 rb0c8011  
    3030
    3131sub startup {
    32     BarnOwl::new_variable_string('irc:nick', {default => $ENV{USER}});
    33     BarnOwl::new_variable_string('irc:user', {default => $ENV{USER}});
    34     BarnOwl::new_variable_string('irc:name', {default => ""});
    35     BarnOwl::new_variable_bool('irc:spew', {default => 0});
     32    BarnOwl::new_variable_string('irc:nick', {
     33        default     => $ENV{USER},
     34        summary     => 'The default IRC nickname',
     35        description => 'By default, irc-connect will use this nick '  .
     36        'when connecting to a new server. See :help irc-connect for ' .
     37        'more information.'
     38       });
     39
     40    BarnOwl::new_variable_string('irc:user', {
     41        default => $ENV{USER},
     42        summary => 'The IRC "username" field'
     43       });
     44        BarnOwl::new_variable_string('irc:name', {
     45        default => "",
     46        summary     => 'A short name field for IRC',
     47        description => 'A short (maybe 60 or so chars) piece of text, ' .
     48        'originally intended to display your real name, which people '  .
     49        'often use for pithy quotes and URLs.'
     50       });
     51   
     52    BarnOwl::new_variable_bool('irc:spew', {
     53        default     => 0,
     54        summary     => 'Show unhandled IRC events',
     55        description => 'If set, display all unrecognized IRC events as ' .
     56        'admin messages. Intended for debugging and development use only '
     57       });
     58   
    3659    register_commands();
    3760    register_handlers();
     
    6184
    6285sub register_commands {
    63     BarnOwl::new_command('irc-connect' => \&cmd_connect);
     86    BarnOwl::new_command('irc-connect' => \&cmd_connect,
     87                       {
     88                           summary      => 'Connect to an IRC server',
     89                           usage        => 'irc-connect [-a ALIAS ] [-s] [-p PASSWORD] [-n NICK] SERVER [port]',
     90                           description  =>
     91
     92                           "Connect to an IRC server. Supported options are\n\n" .
     93                           "-a <alias>          Define an alias for this server\n" .
     94                           "-s                  Use SSL\n" .
     95                           "-p <password>       Specify the password to use\n" .
     96                           "-n <nick>           Use a non-default nick"
     97                       });
    6498    BarnOwl::new_command('irc-disconnect' => \&cmd_disconnect);
    65     BarnOwl::new_command('irc-msg'     => \&cmd_msg);
    66     BarnOwl::new_command('irc-join' => \&cmd_join);
    67     BarnOwl::new_command('irc-nick' => \&cmd_nick);
     99    BarnOwl::new_command('irc-msg'        => \&cmd_msg);
     100    BarnOwl::new_command('irc-join'       => \&cmd_join);
     101    BarnOwl::new_command('irc-part'       => \&cmd_part);
     102    BarnOwl::new_command('irc-nick'       => \&cmd_nick);
     103    BarnOwl::new_command('irc-names'      => \&cmd_names);
     104    BarnOwl::new_command('irc-whois'      => \&cmd_whois);
    68105}
    69106
     
    94131            "ssl"        => \$ssl,
    95132            "password=s" => \$password,
    96             "port=i"     => \$port,
     133            "nick=s"     => \$nick,
    97134        );
    98135        $host = shift @ARGV or die("Usage: $cmd HOST\n");
    99136        if(!$alias) {
    100             $alias = $1 if $host =~ /^(?:irc[.])?(\w+)[.]\w+$/;
    101             $alias ||= $host;
     137            if($host =~ /^(?:irc[.])?(\w+)[.]\w+$/) {
     138                $alias = $1;
     139            } else {
     140                $alias = $host;
     141            }
    102142        }
    103         $port ||= 6667;
     143        $port = shift @ARGV || 6667;
    104144        $ssl ||= 0;
     145    }
     146
     147    if(exists $ircnets{$alias}) {
     148        die("Already connected to a server with alias '$alias'. Either disconnect or specify an alias with -a.\n");
    105149    }
    106150
     
    148192    my $msg = BarnOwl::Message->new(
    149193        type        => 'IRC',
    150         direction   => 'out',
     194        direction   => is_private($to) ? 'out' : 'in',
    151195        server      => $conn->server,
    152196        network     => $conn->alias,
     
    169213}
    170214
     215sub cmd_part {
     216    my $cmd = shift;
     217    my $conn = get_connection(\@_);
     218    my $chan = get_channel(\@_) || die("Usage: $cmd <channel>\n");
     219    $conn->part($chan);
     220}
     221
    171222sub cmd_nick {
    172223    my $cmd = shift;
    173224    my $conn = get_connection(\@_);
    174     my $nick = shift or die("Usage: $cmd <new nick>");
     225    my $nick = shift or die("Usage: $cmd <new nick>\n");
    175226    $conn->nick($nick);
     227}
     228
     229sub cmd_names {
     230    my $cmd = shift;
     231    my $conn = get_connection(\@_);
     232    my $chan = get_channel(\@_) || die("Usage: $cmd <channel>\n");
     233    $conn->names($chan);
     234}
     235
     236sub cmd_whois {
     237    my $cmd = shift;
     238    my $conn = get_connection(\@_);
     239    my $who = shift || die("Usage: $cmd <user>\n");
     240    $conn->whois($who);
    176241}
    177242
     
    196261}
    197262
     263sub get_channel {
     264    my $args = shift;
     265    if(scalar @$args) {
     266        return shift @$args;
     267    }
     268    my $m = BarnOwl::getcurmsg();
     269    if($m && $m->type eq 'IRC') {
     270        return $m->channel if !$m->is_private;
     271    }
     272    return undef;
     273}
     274
    198275sub get_connection_by_alias {
    199276    my $key = shift;
  • perl/modules/IRC/lib/BarnOwl/Module/IRC/Connection.pm

    r0e52069 r9e02bb7  
    1616
    1717use base qw(Net::IRC::Connection Class::Accessor Exporter);
    18 __PACKAGE__->mk_accessors(qw(alias channels));
     18__PACKAGE__->mk_accessors(qw(alias channels motd));
    1919our @EXPORT_OK = qw(&is_private);
    2020
     
    2929    $self->alias($alias);
    3030    $self->channels([]);
     31    $self->motd("");
    3132    bless($self, $class);
    3233
    33     $self->add_global_handler(376 => sub { goto &on_connect });
    34     $self->add_global_handler(['msg', 'notice', 'public', 'caction'],
     34    $self->add_default_handler(sub { goto &on_event; });
     35    $self->add_handler(376 => sub { goto &on_connect });
     36    $self->add_handler(['msg', 'notice', 'public', 'caction'],
    3537            sub { goto &on_msg });
    36     $self->add_global_handler(cping => sub { goto &on_ping });
    37     $self->add_default_handler(sub { goto &on_event; });
     38    $self->add_handler(['welcome', 'yourhost', 'created',
     39            'luserclient', 'luserop', 'luserchannels', 'luserme'],
     40            sub { goto &on_admin_msg });
     41    $self->add_handler(['myinfo', 'map', 'n_local', 'n_global',
     42            'luserconns'],
     43            sub { });
     44    $self->add_handler(motdstart => sub { goto &on_motdstart });
     45    $self->add_handler(motd      => sub { goto &on_motd });
     46    $self->add_handler(endofmotd => sub { goto &on_endofmotd });
     47    $self->add_handler(join      => sub { goto &on_join });
     48    $self->add_handler(part      => sub { goto &on_part });
     49    $self->add_handler(disconnect => sub { goto &on_disconnect });
     50    $self->add_handler(nicknameinuse => sub { goto &on_nickinuse });
     51    $self->add_handler(cping     => sub { goto &on_ping });
    3852
    3953    return $self;
     
    4963}
    5064
    51 sub on_msg {
    52     my ($self, $evt) = @_;
    53     my ($recipient) = $evt->to;
    54     my $body = strip_irc_formatting([$evt->args]->[0]);
    55     $body = BarnOwl::Style::boldify($evt->nick.' '.$body) if $evt->type eq 'caction';
    56     my $msg = BarnOwl::Message->new(
     65sub new_message {
     66    my $self = shift;
     67    my $evt = shift;
     68    return BarnOwl::Message->new(
    5769        type        => 'IRC',
    58         direction   => 'in',
    5970        server      => $self->server,
    6071        network     => $self->alias,
    61         recipient   => $recipient,
    62         body        => $body,
    6372        sender      => $evt->nick,
    6473        hostname    => $evt->host,
    6574        from        => $evt->from,
     75        @_
     76       );
     77}
     78
     79sub on_msg {
     80    my ($self, $evt) = @_;
     81    my ($recipient) = $evt->to;
     82    my $body = strip_irc_formatting([$evt->args]->[0]);
     83    my $nick = $self->nick;
     84    BarnOwl::beep() if $body =~ /\b\Q$nick\E\b/;
     85    $body = BarnOwl::Style::boldify($evt->nick.' '.$body) if $evt->type eq 'caction';
     86    my $msg = $self->new_message($evt,
     87        direction   => 'in',
     88        recipient   => $recipient,
     89        body => $body,
    6690        $evt->type eq 'notice' ?
    6791          (notice     => 'true') : (),
     
    7094        replycmd    => 'irc-msg ' .
    7195            (is_private($recipient) ? $evt->nick : $recipient),
    72         replysendercmd => 'irc-msg ' . $evt->nick,
     96        replysendercmd => 'irc-msg ' . $evt->nick
    7397       );
     98
    7499    BarnOwl::queue_message($msg);
    75100}
     
    80105}
    81106
     107sub on_admin_msg {
     108    my ($self, $evt) = @_;
     109    BarnOwl::admin_message("IRC",
     110            BarnOwl::Style::boldify('IRC ' . $evt->type . ' message from '
     111                . $evt->alias) . "\n"
     112            . strip_irc_formatting(join '\n', cdr $evt->args));
     113}
     114
     115sub on_motdstart {
     116    my ($self, $evt) = @_;
     117    $self->motd(join "\n", cdr $evt->args);
     118}
     119
     120sub on_motd {
     121    my ($self, $evt) = @_;
     122    $self->motd(join "\n", $self->motd, cdr $evt->args);
     123}
     124
     125sub on_endofmotd {
     126    my ($self, $evt) = @_;
     127    $self->motd(join "\n", $self->motd, cdr $evt->args);
     128    BarnOwl::admin_message("IRC",
     129            BarnOwl::Style::boldify('MOTD for ' . $evt->alias) . "\n"
     130            . strip_irc_formatting($self->motd));
     131}
     132
     133sub on_join {
     134    my ($self, $evt) = @_;
     135    my $msg = $self->new_message($evt,
     136        loginout   => 'login',
     137        channel    => $evt->to,
     138        );
     139    BarnOwl::queue_message($msg);
     140}
     141
     142sub on_part {
     143    my ($self, $evt) = @_;
     144    my $msg = $self->new_message($evt,
     145        loginout   => 'logout',
     146        channel    => $evt->to,
     147        );
     148    BarnOwl::queue_message($msg);
     149}
     150
     151sub on_disconnect {
     152    my $self = shift;
     153    delete $BarnOwl::Module::IRC::ircnets{$self->alias};
     154
     155    BarnOwl::admin_message('IRC',
     156                           "[" . $self->alias . "] Disconnected from server");
     157}
     158
     159sub on_nickinuse {
     160    my ($self, $evt) = @_;
     161    BarnOwl::admin_message("IRC",
     162                           "[" . $self->alias . "] " .
     163                           [$evt->args]->[1] . ": Nick already in use");
     164}
     165
    82166sub on_event {
    83167    my ($self, $evt) = @_;
    84168    BarnOwl::admin_message("IRC",
    85             "Unhandled IRC event of type " . $evt->type . ":\n"
     169            "[" . $self->alias . "] Unhandled IRC event of type " . $evt->type . ":\n"
    86170            . strip_irc_formatting(join("\n", $evt->args)))
    87171        if BarnOwl::getvar('irc:spew') eq 'on';
    88172}
    89173
     174
    90175################################################################################
    91176########################### Utilities/Helpers ##################################
     
    94179sub strip_irc_formatting {
    95180    my $body = shift;
    96     my @pieces = split /\x02/, $body;
     181    # Strip mIRC colors. If someone wants to write code to convert
     182    # these to zephyr colors, be my guest.
     183    $body =~ s/\cC\d+(?:,\d+)?//g;
     184    $body =~ s/\cO//g;
     185   
     186    my @pieces = split /\cB/, $body;
    97187     my $out;
    98188    while(@pieces) {
     
    109199}
    110200
     201sub cdr {
     202    shift;
     203    return @_;
     204}
     205
    1112061;
  • perlglue.xs

    rb363d83 r65fea01  
    1313#define SV_IS_CODEREF(sv) (SvROK((sv)) && SvTYPE(SvRV((sv))) == SVt_PVCV)
    1414
    15 MODULE = BarnOwl                PACKAGE = BarnOwl               
     15        /*************************************************************
     16         * NOTE
     17         *************************************************************
     18         * These functions, when they are intended to be user-visible,
     19         * are document in perlwrap.pm. If you add functions to this
     20         * file, add the appropriate documentation there!
     21         *
     22         * If the function is simple enough, we simply define its
     23         * entire functionality here in XS. If, however, it needs
     24         * complex argument processing or something, we define a
     25         * simple version here that takes arguments in as flat a
     26         * manner as possible, to simplify the XS code, with a name
     27         * with a trailing `_internal', and write a perl wrapper in
     28         * perlwrap.pm that munges the arguments as appropriate and
     29         * calls the internal version.
     30         */
     31
     32MODULE = BarnOwl                PACKAGE = BarnOwl
    1633
    1734char *
  • perlwrap.pm

    r18fb3d4f rb0c8011  
    1414
    1515package BarnOwl;
     16
     17=head1 NAME
     18
     19BarnOwl
     20
     21=head1 DESCRIPTION
     22
     23The BarnOwl module contains the core of BarnOwl's perl
     24bindings. Source in this module is also run at startup to bootstrap
     25barnowl by defining things like the default style.
     26
     27=for NOTE
     28These following functions are defined in perlglue.xs. Keep the
     29documentation here in sync with the user-visible commands defined
     30there!
     31
     32=head2 command STRING
     33
     34Executes a BarnOwl command in the same manner as if the user had
     35executed it at the BarnOwl command prompt. If the command returns a
     36value, return it as a string, otherwise return undef.
     37
     38=head2 getcurmsg
     39
     40Returns the current message as a C<BarnOwl::Message> subclass, or
     41undef if there is no message selected
     42
     43=head2 getnumcols
     44
     45Returns the width of the display window BarnOwl is currently using
     46
     47=head2 getidletime
     48
     49Returns the length of time since the user has pressed a key, in
     50seconds.
     51
     52=head2 zephyr_getrealm
     53
     54Returns the zephyr realm barnowl is running in
     55
     56=head2 zephyr_getsender
     57
     58Returns the fully-qualified name of the zephyr sender barnowl is
     59running as, e.g. C<nelhage@ATHENA.MIT.EDU>
     60
     61=head2 zephyr_zwrite COMMAND MESSAGE
     62
     63Sends a zephyr programmatically. C<COMMAND> should be a C<zwrite>
     64command line, and C<MESSAGE> is the zephyr body to send.
     65
     66=head2 ztext_stylestrip STRING
     67
     68Strips zephyr formatting from a string and returns the result
     69
     70=head2 queue_message MESSAGE
     71
     72Enqueue a message in the BarnOwl message list, logging it and
     73processing it appropriately. C<MESSAGE> should be an instance of
     74BarnOwl::Message or a subclass.
     75
     76=head2 admin_message HEADER BODY
     77
     78Display a BarnOwl B<Admin> message, with the given header and body.
     79
     80=head2 start_question PROMPT CALLBACK
     81
     82Displays C<PROMPT> on the screen and lets the user enter a line of
     83text, and calls C<CALLBACK>, which must be a perl subroutine
     84reference, with the text the user entered
     85
     86=head2 start_password PROMPT CALLBACK
     87
     88Like C<start_question>, but echoes the user's input as C<*>s when they
     89input.
     90
     91=head2 start_editwin PROMPT CALLBACK
     92
     93Like C<start_question>, but displays C<PROMPT> on a line of its own
     94and opens the editwin. If the user cancels the edit win, C<CALLBACK>
     95is not invoked.
     96
     97=head2 get_data_dir
     98
     99Returns the BarnOwl system data directory, where system libraries and
     100modules are stored
     101
     102=head2 get_config_dir
     103
     104Returns the BarnOwl user configuration directory, where user modules
     105and configuration are stored (by default, C<$HOME/.owl>)
     106
     107=head2 popless_text TEXT
     108
     109Show a popup window containing the given C<TEXT>
     110
     111=head2 popless_ztext TEXT
     112
     113Show a popup window containing the provided zephyr-formatted C<TEXT>
     114
     115=head2 error STRING
     116
     117Reports an error and log it in `show errors'. Note that in any
     118callback or hook called in perl code from BarnOwl, a C<die> will be
     119caught and passed to C<error>.
     120
     121=head2 getnumcolors
     122
     123Returns the number of colors this BarnOwl is capable of displaying
     124
     125=cut
     126
    16127
    17128BEGIN {
     
    46157    return &BarnOwl::Hooks::_receive_msg($m);
    47158}
     159
     160=head2 AUTOLOAD
     161
     162BarnOwl.pm has a C<AUTOLOAD> method that translates unused names in
     163the BarnOwl:: namespace to a call to BarnOwl::command() with that
     164command. Underscores are also translated to C<->s, so you can do
     165e.g. C<BarnOwl::start_command()> and it will be translated into
     166C<start-command>.
     167
     168So, if you're looking for functionality that you can't find in the
     169perl interface, check C<:show commands> or C<commands.c> in the
     170BarnOwl source tree -- there's a good chance it exists as a BarnOwl
     171command.
     172
     173=head3 BUGS
     174
     175There are horrible quoting issues here. The AUTOLOAD simple joins your
     176commands with spaces and passes them unmodified to C<::command>
     177
     178=cut
    48179
    49180# make BarnOwl::<command>("foo") be aliases to BarnOwl::command("<command> foo");
     
    63194
    64195ARGS should be a hashref containing any or all of C<summary>,
    65 C<usage>, or C<description> keys.
     196C<usage>, or C<description> keys:
     197
     198=over 4
     199
     200=item summary
     201
     202A one-line summary of the purpose of the command
     203
     204=item usage
     205
     206A one-line usage synopsis, showing available options and syntax
     207
     208=item description
     209
     210A longer description of the syntax and semantics of the command,
     211explaining usage and options
     212
     213=back
    66214
    67215=cut
     
    410558package BarnOwl::Hook;
    411559
     560=head1 BarnOwl::Hook
     561
     562=head1 DESCRIPTION
     563
     564A C<BarnOwl::Hook> represents a list of functions to be triggered on
     565some event. C<BarnOwl> exports a default set of these (see
     566C<BarnOwl::Hooks>), but can also be created and used by module code.
     567
     568=head2 new
     569
     570Creates a new Hook object
     571
     572=cut
     573
    412574sub new {
    413575    my $class = shift;
    414576    return bless [], $class;
    415577}
     578
     579=head2 run [ARGS]
     580
     581Calls each of the functions registered with this hook with the given
     582arguments.
     583
     584=cut
    416585
    417586sub run {
     
    420589    return map {$_->(@args)} @$self;
    421590}
     591
     592=head2 add SUBREF
     593
     594Registers a given subroutine with this hook
     595
     596=cut
    422597
    423598sub add {
     
    428603}
    429604
     605=head2 clear
     606
     607Remove all functions registered with this hook.
     608
     609=cut
     610
    430611sub clear {
    431612    my $self = shift;
     
    434615
    435616package BarnOwl::Hooks;
     617
     618=head1 BarnOwl::Hooks
     619
     620=head1 DESCRIPTION
     621
     622C<BarnOwl::Hooks> exports a set of C<BarnOwl::Hook> objects made
     623available by BarnOwl internally.
     624
     625=head2 USAGE
     626
     627Modules wishing to respond to events in BarnOwl should register
     628functions with these hooks.
     629
     630=head2 EXPORTS
     631
     632None by default. Either import the hooks you need explicitly, or refer
     633to them with fully-qualified names. Available hooks are:
     634
     635=over 4
     636
     637=item $startup
     638
     639Called on BarnOwl startup, and whenever modules are
     640reloaded. Functions registered with the C<$startup> hook get a true
     641argument if this is a reload, and false if this is a true startup
     642
     643=item $shutdown
     644
     645Called before BarnOwl shutdown
     646
     647=item $receiveMessage
     648
     649Called with a C<BarnOwl::Message> object every time BarnOwl appends a
     650new message to its message list
     651
     652=item $mainLoop
     653
     654Called on B<every pass> through the C<BarnOwl> main loop. Any
     655functions with this hook should be very cheap, as they are very
     656frequently by the runtime.
     657
     658=item $getBuddyList
     659
     660Called to display buddy lists for all protocol handlers. The result
     661from every function registered with this hook will be appended and
     662displayed in a popup window, with zephyr formatting parsed.
     663
     664=back
     665
     666=cut
    436667
    437668use Exporter;
     
    468699    }
    469700}
     701
     702# These are the internal hooks called by the barnowl C code, which
     703# take care of dispatching to the appropriate perl hooks, and deal
     704# with compatibility by calling the old, fixed-name hooks.
    470705
    471706sub _startup {
  • variable.c

    rad15610 rd536e72  
    455455
    456456int owl_variable_dict_setup(owl_vardict *vd) {
    457   owl_variable *cur;
     457  owl_variable *var, *cur;
    458458  if (owl_dict_create(vd)) return(-1);
    459   for (cur = variables_to_init; cur->name != NULL; cur++) {
     459  for (var = variables_to_init; var->name != NULL; var++) {
     460    cur = owl_malloc(sizeof(owl_variable));
     461    memcpy(cur, var, sizeof(owl_variable));
    460462    switch (cur->type) {
    461463    case OWL_VARIABLE_OTHER:
     
    520522void owl_variable_dict_add_variable(owl_vardict * vardict,
    521523                                    owl_variable * var) {
    522   owl_dict_insert_element(vardict, var->name, (void*)var, NULL);
     524  owl_dict_insert_element(vardict, var->name, (void*)var, (void(*)(void*))owl_variable_free);
    523525}
    524526
     
    532534}
    533535
     536void owl_variable_update(owl_variable *var, char *summary, char *desc) {
     537  if(var->summary) owl_free(var->summary);
     538  var->summary = owl_strdup(summary);
     539  if(var->description) owl_free(var->description);
     540  var->description = owl_strdup(desc);
     541}
     542
    534543void owl_variable_dict_newvar_string(owl_vardict * vd, char *name, char *summ, char * desc, char * initval) {
    535   owl_variable * var = owl_variable_newvar(name, summ, desc);
    536   var->type = OWL_VARIABLE_STRING;
    537   var->pval_default = owl_strdup(initval);
    538   var->set_fn = owl_variable_string_set_default;
    539   var->set_fromstring_fn = owl_variable_string_set_fromstring_default;
    540   var->get_fn = owl_variable_get_default;
    541   var->get_tostring_fn = owl_variable_string_get_tostring_default;
    542   var->free_fn = owl_variable_free_default;
    543   var->set_fn(var, initval);
    544   owl_variable_dict_add_variable(vd, var);
     544  owl_variable *old = owl_variable_get_var(vd, name, OWL_VARIABLE_STRING);
     545  if(old) {
     546    owl_variable_update(old, summ, desc);
     547    if(old->pval_default) owl_free(old->pval_default);
     548    old->pval_default = owl_strdup(initval);
     549  } else {
     550    owl_variable * var = owl_variable_newvar(name, summ, desc);
     551    var->type = OWL_VARIABLE_STRING;
     552    var->pval_default = owl_strdup(initval);
     553    var->set_fn = owl_variable_string_set_default;
     554    var->set_fromstring_fn = owl_variable_string_set_fromstring_default;
     555    var->get_fn = owl_variable_get_default;
     556    var->get_tostring_fn = owl_variable_string_get_tostring_default;
     557    var->free_fn = owl_variable_free_default;
     558    var->set_fn(var, initval);
     559    owl_variable_dict_add_variable(vd, var);
     560  }
    545561}
    546562
    547563void owl_variable_dict_newvar_int(owl_vardict * vd, char *name, char *summ, char * desc, int initval) {
    548   owl_variable * var = owl_variable_newvar(name, summ, desc);
    549   var->type = OWL_VARIABLE_INT;
    550   var->ival_default = initval;
    551   var->validate_fn = owl_variable_int_validate_default;
    552   var->set_fn = owl_variable_int_set_default;
    553   var->set_fromstring_fn = owl_variable_int_set_fromstring_default;
    554   var->get_fn = owl_variable_get_default;
    555   var->get_tostring_fn = owl_variable_int_get_tostring_default;
    556   var->free_fn = owl_variable_free_default;
    557   var->val = owl_malloc(sizeof(int));
    558   var->set_fn(var, &initval);
    559   owl_variable_dict_add_variable(vd, var);
     564  owl_variable *old = owl_variable_get_var(vd, name, OWL_VARIABLE_INT);
     565  if(old) {
     566    owl_variable_update(old, summ, desc);
     567    old->ival_default = initval;
     568  } else {
     569    owl_variable * var = owl_variable_newvar(name, summ, desc);
     570    var->type = OWL_VARIABLE_INT;
     571    var->ival_default = initval;
     572    var->validate_fn = owl_variable_int_validate_default;
     573    var->set_fn = owl_variable_int_set_default;
     574    var->set_fromstring_fn = owl_variable_int_set_fromstring_default;
     575    var->get_fn = owl_variable_get_default;
     576    var->get_tostring_fn = owl_variable_int_get_tostring_default;
     577    var->free_fn = owl_variable_free_default;
     578    var->val = owl_malloc(sizeof(int));
     579    var->set_fn(var, &initval);
     580    owl_variable_dict_add_variable(vd, var);
     581  }
    560582}
    561583
    562584void owl_variable_dict_newvar_bool(owl_vardict * vd, char *name, char *summ, char * desc, int initval) {
    563   owl_variable * var = owl_variable_newvar(name, summ, desc);
    564   var->type = OWL_VARIABLE_BOOL;
    565   var->ival_default = initval;
    566   var->validate_fn = owl_variable_bool_validate_default;
    567   var->set_fn = owl_variable_bool_set_default;
    568   var->set_fromstring_fn = owl_variable_bool_set_fromstring_default;
    569   var->get_fn = owl_variable_get_default;
    570   var->get_tostring_fn = owl_variable_bool_get_tostring_default;
    571   var->free_fn = owl_variable_free_default;
    572   var->val = owl_malloc(sizeof(int));
    573   var->set_fn(var, &initval);
    574   owl_variable_dict_add_variable(vd, var);
     585  owl_variable *old = owl_variable_get_var(vd, name, OWL_VARIABLE_BOOL);
     586  if(old) {
     587    owl_variable_update(old, summ, desc);
     588    old->ival_default = initval;
     589  } else {
     590    owl_variable * var = owl_variable_newvar(name, summ, desc);
     591    var->type = OWL_VARIABLE_BOOL;
     592    var->ival_default = initval;
     593    var->validate_fn = owl_variable_bool_validate_default;
     594    var->set_fn = owl_variable_bool_set_default;
     595    var->set_fromstring_fn = owl_variable_bool_set_fromstring_default;
     596    var->get_fn = owl_variable_get_default;
     597    var->get_tostring_fn = owl_variable_bool_get_tostring_default;
     598    var->free_fn = owl_variable_free_default;
     599    var->val = owl_malloc(sizeof(int));
     600    var->set_fn(var, &initval);
     601    owl_variable_dict_add_variable(vd, var);
     602  }
    575603}
    576604
     
    590618void owl_variable_free(owl_variable *v) {
    591619  if (v->free_fn) v->free_fn(v);
     620  owl_free(v);
    592621}
    593622
     
    687716}
    688717
    689 /* returns a reference */
    690 void *owl_variable_get(owl_vardict *d, char *name, int require_type) {
     718owl_variable *owl_variable_get_var(owl_vardict *d, char *name, int require_type) {
    691719  owl_variable *v;
    692720  if (!name) return(NULL);
    693721  v = owl_dict_find_element(d, name);
    694722  if (v == NULL || !v->get_fn || v->type != require_type) return(NULL);
     723  return v;
     724}
     725
     726/* returns a reference */
     727void *owl_variable_get(owl_vardict *d, char *name, int require_type) {
     728  owl_variable *v = owl_variable_get_var(d, name, require_type);
     729  if(v == NULL) return NULL;
    695730  return v->get_fn(v);
    696731}
  • zephyr.c

    r6201646 ra827529  
    601601    }
    602602  } else if (!strcmp(retnotice->z_message, ZSRVACK_NOTSENT)) {
    603     if (strcasecmp(retnotice->z_class, "message")) {
    604       char buff[1024];
    605       owl_function_error("No one subscribed to class class %s", retnotice->z_class);
    606       sprintf(buff, "Could not send message to class %s: no one subscribed.\n", retnotice->z_class);
     603    #define BUFFLEN 1024
     604    if (retnotice->z_recipient == NULL
     605        || *retnotice->z_recipient == NULL
     606        || *retnotice->z_recipient == '@') {
     607      char buff[BUFFLEN];
     608      owl_function_error("No one subscribed to class %s", retnotice->z_class);
     609      snprintf(buff, BUFFLEN, "Could not send message to class %s: no one subscribed.\n", retnotice->z_class);
    607610      owl_function_adminmsg("", buff);
    608611    } else {
    609       char buff[1024];
     612      char buff[BUFFLEN];
    610613      tmp = short_zuser(retnotice->z_recipient);
    611       owl_function_error("%s: Not logged in or subscribing to messages.", tmp);
    612       sprintf(buff, "Could not send message to %s: not logged in or subscribing to messages.\n", tmp);
     614      owl_function_error("%s: Not logged in or subscribing.", tmp);
     615      snprintf(buff, BUFFLEN, "Could not send message to %s: not logged in or subscribing to", tmp);
     616      if(strcmp(retnotice->z_class, "message")) {
     617        snprintf(buff, BUFFLEN,
     618                 "%s class %s, instance %s.\n", buff,
     619                 retnotice->z_class,
     620                 retnotice->z_class_inst);
     621      } else {
     622        snprintf(buff, BUFFLEN,
     623                 "%s messages.\n", buff);
     624      }
    613625      owl_function_adminmsg("", buff);
    614626      owl_log_outgoing_zephyr_error(tmp, buff);
  • Makefile.in

    r2bdfed9 rc60ade2  
    2626     keypress.c keymap.c keybinding.c cmd.c context.c zcrypt.c \
    2727     aim.c buddy.c buddylist.c timer.c style.c stylefunc.c errqueue.c \
    28      zbuddylist.c muxevents.c popexec.c obarray.c
     28     zbuddylist.c muxevents.c popexec.c obarray.c wcwidth.c glib_compat.c
    2929OWL_SRC = owl.c
    3030TESTER_SRC = tester.c
  • aim.c

    r9854278 r34509d5  
    948948 
    949949  if (modname) {
    950     if (!(filename = malloc(strlen(priv->aimbinarypath)+1+strlen(modname)+4+1))) {
     950    if (!(filename = owl_malloc(strlen(priv->aimbinarypath)+1+strlen(modname)+4+1))) {
    951951      /* perror("memrequest: malloc"); */
    952952      return -1;
     
    954954    sprintf(filename, "%s/%s.ocm", priv->aimbinarypath, modname);
    955955  } else {
    956     if (!(filename = malloc(strlen(priv->aimbinarypath)+1+strlen(defaultmod)+1))) {
     956    if (!(filename = owl_malloc(strlen(priv->aimbinarypath)+1+strlen(defaultmod)+1))) {
    957957      /* perror("memrequest: malloc"); */
    958958      return -1;
     
    964964    if (!modname) {
    965965      /* perror("memrequest: stat"); */
    966       free(filename);
     966      owl_free(filename);
    967967      return -1;
    968968    }
     
    986986    int i;
    987987   
    988     free(filename); /* not needed */
     988    owl_free(filename); /* not needed */
    989989    owl_function_error("getaimdata memrequest: recieved invalid request for 0x%08lx bytes at 0x%08lx (file %s)\n", len, offset, modname);
    990990    i = 8;
     
    993993    }
    994994   
    995     if (!(buf = malloc(i))) {
     995    if (!(buf = owl_malloc(i))) {
    996996      return -1;
    997997    }
     
    10171017    *buflenret = i;
    10181018  } else {
    1019     if (!(buf = malloc(len))) {
    1020       free(filename);
     1019    if (!(buf = owl_malloc(len))) {
     1020      owl_free(filename);
    10211021      return -1;
    10221022    }
     
    10241024    if (!(f = fopen(filename, "r"))) {
    10251025      /* perror("memrequest: fopen"); */
    1026       free(filename);
    1027       free(buf);
     1026      owl_free(filename);
     1027      owl_free(buf);
    10281028      return -1;
    10291029    }
    10301030   
    1031     free(filename);
     1031    owl_free(filename);
    10321032   
    10331033    if (fseek(f, offset, SEEK_SET) == -1) {
    10341034      /* perror("memrequest: fseek"); */
    10351035      fclose(f);
    1036       free(buf);
     1036      owl_free(buf);
    10371037      return -1;
    10381038    }
     
    10411041      /* perror("memrequest: fread"); */
    10421042      fclose(f);
    1043       free(buf);
     1043      owl_free(buf);
    10441044      return -1;
    10451045    }
     
    10761076  if (priv->aimbinarypath && (getaimdata(sess, &buf, &buflen, offset, len, modname) == 0)) {
    10771077    aim_sendmemblock(sess, fr->conn, offset, buflen, buf, AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
    1078     free(buf);
     1078    owl_free(buf);
    10791079  } else {
    10801080    owl_function_debugmsg("faimtest_memrequest: unable to use AIM binary (\"%s/%s\"), sending defaults...\n", priv->aimbinarypath, modname);
     
    13421342      int z;
    13431343     
    1344       newbuf = malloc(i+1);
     1344      newbuf = owl_malloc(i+1);
    13451345      for (z = 0; z < i; z++)
    13461346        newbuf[z] = (z % 10)+0x30;
    13471347      newbuf[i] = '\0';
    13481348      /* aim_send_im(sess, userinfo->sn, AIM_IMFLAGS_ACK | AIM_IMFLAGS_AWAY, newbuf); */
    1349       free(newbuf);
     1349      owl_free(newbuf);
    13501350    }
    13511351  } else if (strstr(tmpstr, "seticqstatus")) {
  • cmd.c

    r6922edd r34509d5  
    7474  owl_cmd *cmd;
    7575
    76   tmpbuff=strdup(cmdbuff);
     76  tmpbuff=owl_strdup(cmdbuff);
    7777  argv=owl_parseline(tmpbuff, &argc);
    7878  if (argc < 0) {
  • config.h.in

    r03cf6b9 re23eb2b  
    2222#undef HAVE_LIBCOM_ERR
    2323
    24 /* Define to 1 if you have the `curses' library (-lcurses). */
    25 #undef HAVE_LIBCURSES
    26 
    2724/* Define to 1 if you have the `des425' library (-ldes425). */
    2825#undef HAVE_LIBDES425
     
    3936/* Define to 1 if you have the `krb5' library (-lkrb5). */
    4037#undef HAVE_LIBKRB5
    41 
    42 /* Define to 1 if you have the `ncurses' library (-lncurses). */
    43 #undef HAVE_LIBNCURSES
    4438
    4539/* Define to 1 if you have the `ncursesw' library (-lncursesw). */
  • configure.in

    r18e28a4 re23eb2b  
    1212fi
    1313
     14m4_include(/usr/share/aclocal/pkg.m4)
     15dnl m4_include(pkg.m4)
    1416
    1517dnl Check for Athena
     
    4446fi
    4547
    46 AC_CHECK_LIB(ncursesw, initscr,,
    47   AC_CHECK_LIB(ncurses, initscr,,
    48     AC_CHECK_LIB(curses, initscr,, AC_MSG_ERROR(No curses library found.))))
     48AC_CHECK_LIB(ncursesw, initscr,, AC_MSG_ERROR(No curses library found.))
    4949AC_CHECK_LIB(com_err, com_err)
    5050AC_CHECK_LIB(nsl, gethostbyname)
     
    109109LDFLAGS=${LDFLAGS}\ ${FOO}
    110110
     111dnl Add CFLAGS and LDFLAGS for glib-2.0
     112PKG_CHECK_MODULES(GLIB,glib-2.0)
     113
     114echo Adding glib-2.0 CFLAGS ${GLIB_CFLAGS}
     115CFLAGS=${CFLAGS}\ ${GLIB_CFLAGS}
     116echo Adding glib-2.0 LDFLAGS ${GLIB_LIBS}
     117LDFLAGS=${LDFLAGS}\ ${GLIB_LIBS}
     118
     119
    111120dnl Checks for typedefs, structures, and compiler characteristics.
    112121
  • editwin.c

    r9a6cc40 r830c36e  
    143143  e->buffy=0;
    144144  owl_editwin_overwrite_string(e, text);
     145  owl_editwin_overwrite_char(e, '\0');
    145146  e->lock=strlen(text);
    146147  /* if (text[e->lock-1]=='\n') e->lock--; */
    147   e->buffx=x;
    148   e->buffy=y;
     148  /*  e->buffx=x; */
     149  /*  e->buffy=y; */
    149150  owl_editwin_adjust_for_locktext(e);
    150151  owl_editwin_redisplay(e, 0);
     
    251252
    252253  /* start at topline */
    253   ptr1=e->buff;
    254   for (i=0; i<e->topline; i++) {
    255     ptr2=strchr(ptr1, '\n');
     254  ptr1 = e->buff;
     255  for (i = 0; i < e->topline; i++) {
     256    ptr2 = strchr(ptr1, '\n');
    256257    if (!ptr2) {
    257258      /* we're already on the last line */
    258259      break;
    259260    }
    260     ptr1=ptr2+1;
     261    ptr1 = ptr2 + 1;
    261262  }
    262263  /* ptr1 now stores the starting point */
    263264
    264265  /* find the ending point and store it in ptr3 */
    265   ptr2=ptr1;
    266   ptr3=ptr1;
    267   for (i=0; i<e->winlines; i++) {
    268     ptr3=strchr(ptr2, '\n');
     266  ptr2 = ptr1;
     267  ptr3 = ptr1;
     268  for (i = 0; i < e->winlines; i++) {
     269    ptr3 = strchr(ptr2, '\n');
    269270    if (!ptr3) {
    270271      /* we've hit the last line */
    271272      /* print everything to the end */
    272       ptr3=e->buff+e->bufflen-1;
     273      ptr3 = e->buff + e->bufflen - 1;
    273274      ptr3--;
    274275      break;
    275276    }
    276     ptr2=ptr3+1;
    277   }
    278   ptr3+=2;
    279 
    280   buff=owl_malloc(ptr3-ptr1+50);
    281   strncpy(buff, ptr1, ptr3-ptr1);
    282   buff[ptr3-ptr1]='\0';
    283   if (e->echochar=='\0') {
     277    ptr2 = ptr3 + 1;
     278  }
     279  ptr3 += 2;
     280
     281  buff = owl_malloc(ptr3 - ptr1 + 50);
     282  strncpy(buff, ptr1, ptr3 - ptr1);
     283  buff[ptr3 - ptr1] = '\0';
     284  if (e->echochar == '\0') {
    284285    waddstr(e->curswin, buff);
    285286  } else {
    286287    /* translate to echochar, *except* for the locktext */
    287288    int len;
    288     int dolocklen=e->lock-(ptr1-e->buff);
    289 
    290     for (i=0; i<dolocklen; i++) {
     289    int dolocklen = e->lock - (ptr1 - e->buff);
     290
     291    for (i = 0; i < dolocklen; i++) {
    291292      waddch(e->curswin, buff[i]);
    292293    }
    293     len=strlen(buff);
    294     for (i=0; i<len-dolocklen; i++) {
     294    len = strlen(buff);
     295    for (i = 0; i < len-dolocklen; i++) {
    295296      waddch(e->curswin, e->echochar);
    296297    }
    297298  }
    298   wmove(e->curswin, e->buffy-e->topline, e->buffx);
     299  wmove(e->curswin, e->buffy-e->topline, e->buffx + _owl_editwin_cursor_adjustment(e));
    299300  wnoutrefresh(e->curswin);
    300   if (update==1) {
     301  if (update == 1) {
    301302    doupdate();
    302303  }
    303304  owl_free(buff);
     305}
     306
     307/* Remove n bytes at cursor. */
     308void _owl_editwin_remove_bytes(owl_editwin *e, int n) /*noproto*/
     309{
     310  int i = _owl_editwin_get_index_from_xy(e) + n;
     311  for (; i < e->bufflen; i++) {
     312    e->buff[i-n] = e->buff[i];
     313  }
     314 
     315  e->bufflen -= n;
     316  e->buff[e->bufflen] = '\0';
     317}
     318
     319/* Insert n bytes at cursor.*/
     320void _owl_editwin_insert_bytes(owl_editwin *e, int n) /*noproto*/
     321{
     322  int i, z;
     323 
     324  if ((e->bufflen + n) > (e->allocated - 5)) {
     325    _owl_editwin_addspace(e);
     326  }
     327
     328  e->bufflen += n;
     329  e->buff[e->bufflen] = '\0';
     330 
     331  z = _owl_editwin_get_index_from_xy(e);
     332  for (i = e->bufflen - 1; i > z; i--) {
     333    e->buff[i] = e->buff[i - n];
     334  }
    304335}
    305336
     
    313344  int i, z;
    314345
    315   z=_owl_editwin_get_index_from_xy(e);
     346  z = _owl_editwin_get_index_from_xy(e);
    316347  /* move back and line wrap the previous word */
    317   for (i=z-1; ; i--) {
     348  for (i = z - 1; ; i--) {
    318349    /* move back until you find a space or hit the beginning of the line */
    319     if (e->buff[i]==' ') {
     350    if (e->buff[i] == ' ') {
    320351      /* replace the space with a newline */
    321       e->buff[i]='\n';
     352      e->buff[i] = '\n';
    322353      e->buffy++;
    323       e->buffx=z-i-1;
     354      e->buffx = z - i - 1;
    324355      /* were we on the last line */
    325356      return(0);
    326     } else if (e->buff[i]=='\n' || i<=e->lock) {
    327       /* we hit the begginning of the line or the buffer, we cannot
     357    } else if (e->buff[i] == '\n' || i <= e->lock) {
     358      /* we hit the beginning of the line or the buffer, we cannot
    328359       * wrap.
    329360       */
     
    336367 * characters over)
    337368 */
    338 void owl_editwin_insert_char(owl_editwin *e, char c)
    339 {
    340  
    341   int z, i, ret;
     369void owl_editwin_insert_char(owl_editwin *e, gunichar c)
     370{
     371  int z, i, ret, len;
     372  char tmp[6];
     373  memset(tmp, '\0', 6);
    342374
    343375  /* \r is \n */
    344   if (c=='\r') {
    345     c='\n';
    346   }
    347 
    348   if (c=='\n' && e->style==OWL_EDITWIN_STYLE_ONELINE) {
     376  if (c == '\r') {
     377    c = '\n';
     378  }
     379
     380  if (c == '\n' && e->style == OWL_EDITWIN_STYLE_ONELINE) {
    349381    /* perhaps later this will change some state that allows the string
    350382       to be read */
     
    352384  }
    353385
     386  g_unichar_to_utf8(c, tmp);
     387  len = strlen(tmp);
     388
    354389  /* make sure there is enough memory for the new text */
    355   if ((e->bufflen+1) > (e->allocated-5)) {
     390  if ((e->bufflen + len) > (e->allocated - 5)) {
    356391    _owl_editwin_addspace(e);
    357392  }
    358393
    359394  /* get the insertion point */
    360   z=_owl_editwin_get_index_from_xy(e);
     395  z = _owl_editwin_get_index_from_xy(e);
    361396
    362397  /* If we're going to insert at the last column do word wrapping, unless it's a \n */
    363   if ((e->buffx+1==e->wrapcol) && (c!='\n')) {
    364     ret=_owl_editwin_linewrap_word(e);
    365     if (ret==-1) {
     398  if ((e->buffx + 1 == e->wrapcol) && (c != '\n')) {
     399    ret = _owl_editwin_linewrap_word(e);
     400    if (ret == -1) {
    366401      /* we couldn't wrap, insert a hard newline instead */
    367402      owl_editwin_insert_char(e, '\n');
     
    369404  }
    370405
    371   z=_owl_editwin_get_index_from_xy(e);
    372406  /* shift all the other characters right */
    373   for (i=e->bufflen; i>z; i--) {
    374     e->buff[i]=e->buff[i-1];
    375   }
    376 
    377   /* insert the new one */
    378   e->buff[z]=c;
     407  if (z != e->bufflen) {
     408    _owl_editwin_insert_bytes(e, len);
     409  }
     410
     411  /* insert the new character */
     412  for(i = 0; i < len; i++) {
     413    e->buff[z + i] = tmp[i];
     414  }
    379415
    380416  /* housekeeping */
    381   e->bufflen++;
    382   e->buff[e->bufflen]='\0';
    383 
     417  e->bufflen += len;
     418  e->buff[e->bufflen] = '\0';
     419 
    384420  /* advance the cursor */
    385   if (c=='\n') {
    386     e->buffx=0;
    387     e->buffy++;
    388   } else {
    389     e->buffx++;
    390   }
     421  z += len;
     422  _owl_editwin_set_xy_by_index(e, z);
    391423}
    392424
    393425/* overwrite the character at the current point with 'c' */
    394 void owl_editwin_overwrite_char(owl_editwin *e, char c)
    395 {
    396   int z;
    397  
     426void owl_editwin_overwrite_char(owl_editwin *e, gunichar c)
     427{
     428  int z, oldlen, newlen, i;
     429  char tmp[6];
     430  memset(tmp, '\0', 6);
     431
    398432  /* \r is \n */
    399   if (c=='\r') {
    400     c='\n';
    401   }
    402 
    403   if (c=='\n' && e->style==OWL_EDITWIN_STYLE_ONELINE) {
     433  if (c == '\r') {
     434    c = '\n';
     435  }
     436 
     437  if (c == '\n' && e->style == OWL_EDITWIN_STYLE_ONELINE) {
    404438    /* perhaps later this will change some state that allows the string
    405439       to be read */
     
    407441  }
    408442
    409   z=_owl_editwin_get_index_from_xy(e);
    410 
    411   /* only if we are at the end of the buffer do we create new space */
    412   if (z==e->bufflen) {
    413     if ((e->bufflen+1) > (e->allocated-5)) {
     443  g_unichar_to_utf8(c, tmp);
     444  newlen = strlen(tmp);
     445
     446  z = _owl_editwin_get_index_from_xy(e);
     447  {
     448    char *t = g_utf8_find_next_char(e->buff + z, NULL);
     449    oldlen = (t ? (t - (e->buff + z)) : 0);
     450  }
     451
     452  /* only if we are at the end of the buffer do we create new space here */
     453  if (z == e->bufflen) {
     454    if ((e->bufflen+newlen) > (e->allocated-5)) {
    414455      _owl_editwin_addspace(e);
    415456    }
    416457  }
    417  
    418   e->buff[z]=c;
    419 
    420   /* housekeeping if we are at the end of the buffer */
    421   if (z==e->bufflen) {
    422     e->bufflen++;
    423     e->buff[e->bufflen]='\0';
    424   }
    425 
     458  /* if not at the end of the buffer, adjust based in char size difference. */
     459  else if (oldlen > newlen) {
     460    _owl_editwin_remove_bytes(e, oldlen-newlen);
     461  }
     462  else /* oldlen < newlen */ {
     463    _owl_editwin_insert_bytes(e, newlen-oldlen);
     464  }
     465  /* Overwrite the old char*/
     466  for (i = 0; i < newlen; i++) {
     467    e->buff[z+i] = tmp[i];
     468  }
     469       
     470  /* housekeeping */
     471  if (z == e->bufflen) {
     472    e->bufflen += newlen;
     473    e->buff[e->bufflen] = '\0';
     474  }
     475 
    426476  /* advance the cursor */
    427   if (c=='\n') {
    428     e->buffx=0;
    429     e->buffy++;
    430   } else {
    431     e->buffx++;
    432   }
    433 
     477  z += newlen;
     478  _owl_editwin_set_xy_by_index(e, z);
    434479}
    435480
     
    439484void owl_editwin_delete_char(owl_editwin *e)
    440485{
    441   int z, i;
    442 
    443   if (e->bufflen==0) return;
     486  int z;
     487  char *p1, *p2;
     488  gunichar c;
     489
     490  if (e->bufflen == 0) return;
    444491 
    445492  /* get the deletion point */
    446   z=_owl_editwin_get_index_from_xy(e);
    447 
    448   if (z==e->bufflen) return;
    449 
    450   for (i=z; i<e->bufflen; i++) {
    451     e->buff[i]=e->buff[i+1];
    452   }
    453   e->bufflen--;
    454   e->buff[e->bufflen]='\0';
     493  z = _owl_editwin_get_index_from_xy(e);
     494
     495  if (z == e->bufflen) return;
     496
     497  p1 = e->buff + z;
     498  p2 = g_utf8_next_char(p1);
     499  c = g_utf8_get_char(p2);
     500  while (g_unichar_ismark(c)) {
     501    p2 = g_utf8_next_char(p2);
     502    c = g_utf8_get_char(p2);
     503  }
     504  _owl_editwin_remove_bytes(e, p2-p1);
    455505}
    456506
     
    463513{
    464514  int z;
    465   char tmp;
    466 
    467   if (e->bufflen==0) return;
     515  char *p1, *p2, *p3, *tmp;
     516
     517  if (e->bufflen == 0) return;
    468518 
    469519  /* get the cursor point */
    470   z=_owl_editwin_get_index_from_xy(e);
    471 
    472   if (z==e->bufflen) {
     520  z = _owl_editwin_get_index_from_xy(e);
     521
     522  if (z == e->bufflen) {
    473523    /* point is after last character */
    474524    z--;
    475525  } 
    476526
    477   if (z-1 < e->lock) {
     527  if (z - 1 < e->lock) {
    478528    /* point is at beginning of buffer, do nothing */
    479529    return;
    480530  }
    481531
    482   tmp=e->buff[z];
    483   e->buff[z]=e->buff[z-1];
    484   e->buff[z-1]=tmp;
    485   owl_editwin_key_right(e);
     532  /* Transpose two utf-8 unicode glyphs. */
     533  p1 = e->buff + z;
     534
     535  p2 = g_utf8_find_next_char(p1, NULL);
     536  while (p2 != NULL && g_unichar_ismark(g_utf8_get_char(p2))) {
     537    p2 = g_utf8_find_next_char(p2, NULL);
     538  }
     539  if (p2 == NULL) return;
     540
     541  p3 = g_utf8_find_prev_char(e->buff, p1);
     542  while (p3 != NULL && g_unichar_ismark(g_utf8_get_char(p3))) {
     543    p3 = g_utf8_find_prev_char(p3, NULL);
     544  }
     545  if (p3 == NULL) return;
     546
     547  tmp = owl_malloc(p2 - p3 + 5);
     548  *tmp = '\0';
     549  strncat(tmp, p1, p2 - p1);
     550  strncat(tmp, p3, p1 - p3);
     551  strncpy(p3, tmp, p2 - p3);
     552  owl_free(tmp);
     553  _owl_editwin_set_xy_by_index(e, p3 - e->buff);
    486554}
    487555
     
    491559void owl_editwin_insert_string(owl_editwin *e, char *string)
    492560{
    493   int i, j;
    494 
    495   j=strlen(string);
    496   for (i=0; i<j; i++) {
    497     owl_editwin_insert_char(e, string[i]);
     561  char *p;
     562  gunichar c;
     563  if (!g_utf8_validate(string, -1, NULL)) {
     564    owl_function_debugmsg("owl_editwin_insert_string: received non-utf-8 string.");
     565    return;
     566  }
     567  p = string;
     568  c = g_utf8_get_char(p);
     569  while (c) {
     570    owl_editwin_process_char(e, c);
     571    p = g_utf8_next_char(p);
     572    c = g_utf8_get_char(p);
    498573  }
    499574}
     
    505580void owl_editwin_overwrite_string(owl_editwin *e, char *string)
    506581{
    507   int i, j;
    508 
    509   j=strlen(string);
    510   for (i=0; i<j; i++) {
    511     owl_editwin_overwrite_char(e, string[i]);
     582  char *p;
     583  gunichar c;
     584
     585  if (!g_utf8_validate(string, -1, NULL)) {
     586    owl_function_debugmsg("owl_editwin_overwrite_string: received non-utf-8 string.");
     587    return;
     588  }
     589  p = string;
     590  c = g_utf8_get_char(p);
     591  while (c) {
     592    owl_editwin_overwrite_char(e, c);
     593    p = g_utf8_next_char(p);
     594    c = g_utf8_get_char(p);
    512595  }
    513596}
     
    520603  int i;
    521604  char *ptr1, *ptr2;
    522 
    523   if (e->bufflen==0) return(0);
     605  gunichar c;
     606
     607  if (e->bufflen == 0) return(0);
    524608 
    525609  /* first go to the yth line */
    526   ptr1=e->buff;
    527   for (i=0; i<e->buffy; i++) {
    528     ptr2=strchr(ptr1, '\n');
     610  ptr1 = e->buff;
     611  for (i = 0; i < e->buffy; i++) {
     612    ptr2= strchr(ptr1, '\n');
    529613    if (!ptr2) {
    530614      /* we're already on the last line */
    531615      break;
    532616    }
    533     ptr1=ptr2+1;
    534   }
    535 
    536   /* now go to the xth character */
    537   ptr2=strchr(ptr1, '\n');
    538   if (!ptr2) {
    539     ptr2=e->buff+e->bufflen;
    540   }
    541 
    542   if ((ptr2-ptr1) < e->buffx) {
    543     ptr1=ptr2-1;
    544   } else {
    545     ptr1+=e->buffx;
    546   }
    547 
    548   /* printf("DEBUG: index is %i\r\n", ptr1-e->buff); */
    549   return(ptr1-e->buff);
     617    ptr1 = ptr2 + 1;
     618  }
     619
     620  /* now go to the xth cell */
     621  ptr2 = ptr1;
     622  i = 0;
     623  while (ptr2 != NULL && i < e->buffx && (ptr2 - e->buff) < e->bufflen) {
     624    c = g_utf8_get_char(ptr2);
     625    i += (c == '\n' ? 1 : mk_wcwidth(c));
     626    ptr2 = g_utf8_next_char(ptr2);
     627  }
     628  while(ptr2 != NULL && g_unichar_ismark(g_utf8_get_char(ptr2))) {
     629    ptr2 = g_utf8_next_char(ptr2);
     630  }
     631  if (ptr2 == NULL) return e->bufflen;
     632  return(ptr2 - e->buff);
    550633}
    551634
    552635void _owl_editwin_set_xy_by_index(owl_editwin *e, int index)
    553636{
    554   int z, i;
    555 
    556   z=_owl_editwin_get_index_from_xy(e);
    557   if (index>z) {
    558     for (i=0; i<index-z; i++) {
    559       owl_editwin_key_right(e);
    560     }
    561   } else if (index<z) {
    562     for (i=0; i<z-index; i++) {
    563       owl_editwin_key_left(e);
    564     }
    565   }
     637  char *ptr1, *ptr2, *target;
     638  gunichar c;
     639
     640  e->buffx = 0;
     641  e->buffy = 0;
     642
     643  ptr1 = e->buff;
     644  target = ptr1 + index;
     645  /* target sanitizing */
     646  if ((target[0] & 0x80) && (~target[0] & 0x40)) {
     647    /* middle of a utf-8 character, back up to previous character. */
     648    target = g_utf8_find_prev_char(e->buff, target);
     649  }
     650  c = g_utf8_get_char(target);
     651  while (g_unichar_ismark(c) && target > e->buff) {
     652    /* Adjust the target off of combining characters and the like. */
     653    target = g_utf8_find_prev_char(e->buff, target);
     654    c = g_utf8_get_char(target);
     655  }
     656  /* If we start with a mark, something is wrong.*/
     657  if (g_unichar_ismark(c)) return;
     658
     659  /* Now our target should be acceptable. */
     660  ptr2 = strchr(ptr1, '\n');
     661  while (ptr2 != NULL && ptr2 < target) {
     662    e->buffy++;
     663    ptr1 = ptr2 + 1;
     664    ptr2 = strchr(ptr1, '\n');
     665  }
     666  ptr2 = ptr1;
     667  while (ptr2 != NULL && ptr2 < target) {
     668    c = g_utf8_get_char(ptr2);
     669    e->buffx += mk_wcwidth(c);
     670    ptr2 = g_utf8_next_char(ptr2);
     671  }
     672}
     673
     674int _owl_editwin_cursor_adjustment(owl_editwin *e)
     675{
     676  char *ptr1, *ptr2;
     677  gunichar c;
     678  int x, i;
     679
     680  ptr1 = e->buff;
     681  ptr2 = strchr(ptr1, '\n');
     682  for (i = 0; ptr2 != NULL && i < e->buffy; i++) {
     683    ptr1 = ptr2 + 1;
     684    ptr2 = strchr(ptr1, '\n');
     685  }
     686  ptr2 = ptr1;
     687  x = 0;
     688  while (ptr2 != NULL && x < e->buffx) {
     689    if (*ptr2 == '\n') return 0;
     690    c = g_utf8_get_char(ptr2);
     691    x += mk_wcwidth(c);
     692    ptr2 = g_utf8_next_char(ptr2);
     693  }
     694  return x - e->buffx;
    566695}
    567696
     
    570699  /* if we happen to have the cursor over locked text
    571700   * move it to be out of the locktext region */
    572   if (_owl_editwin_get_index_from_xy(e)<e->lock) {
     701  if (_owl_editwin_get_index_from_xy(e) < e->lock) {
    573702    _owl_editwin_set_xy_by_index(e, e->lock);
    574703  }
     
    590719{
    591720  if (e->buffy > 0) e->buffy--;
    592   if (e->buffx >= owl_editwin_get_numchars_on_line(e, e->buffy)) {
    593     e->buffx=owl_editwin_get_numchars_on_line(e, e->buffy);
     721  if (e->buffx >= owl_editwin_get_numcells_on_line(e, e->buffy)) {
     722    e->buffx=owl_editwin_get_numcells_on_line(e, e->buffy);
    594723  }
    595724
     
    608737
    609738  /* if we're past the last character move back */
    610   if (e->buffx >= owl_editwin_get_numchars_on_line(e, e->buffy)) {
    611     e->buffx=owl_editwin_get_numchars_on_line(e, e->buffy);
     739  if (e->buffx >= owl_editwin_get_numcells_on_line(e, e->buffy)) {
     740    e->buffx=owl_editwin_get_numcells_on_line(e, e->buffy);
    612741  }
    613742
     
    623752void owl_editwin_key_left(owl_editwin *e)
    624753{
    625   /* move left if we can, and maybe up a line */
    626   if (e->buffx>0) {
    627     e->buffx--;
    628   } else if (e->buffy>0) {
    629     e->buffy--;
    630     e->buffx=owl_editwin_get_numchars_on_line(e, e->buffy);
    631   }
    632 
    633   /* do we need to scroll up? */
    634   if (e->buffy-e->topline < 0) {
    635     e->topline-=e->winlines/2;
     754  int i;
     755  char * p;
     756  i = _owl_editwin_get_index_from_xy(e);
     757  p = e->buff + i;
     758  p = g_utf8_find_prev_char(e->buff, p);
     759  while (p && g_unichar_ismark(g_utf8_get_char(p))) {
     760    p = g_utf8_find_prev_char(e->buff, p);
     761  }
     762  if (p == NULL) p = e->buff;
     763  _owl_editwin_set_xy_by_index(e, p - e->buff);
     764
     765  if (e->buffy - e->topline < 0) {
     766    e->topline -= e->winlines / 2;
    636767  }
    637768
     
    643774{
    644775  int i;
    645 
    646   /* move right if we can, and skip down a line if needed */
    647   i=owl_editwin_get_numchars_on_line(e, e->buffy);
    648   if (e->buffx < i) {
    649     e->buffx++;
    650     /*  } else if (e->buffy+1 < owl_editwin_get_numlines(e)) { */
    651   } else if (_owl_editwin_get_index_from_xy(e) < e->bufflen) {
    652     if (e->style==OWL_EDITWIN_STYLE_MULTILINE) {
    653       e->buffx=0;
    654       e->buffy++;
    655     }
     776  char * p;
     777  i = _owl_editwin_get_index_from_xy(e);
     778  p = e->buff + i;
     779  p = g_utf8_find_next_char(p, NULL);
     780  while (p && g_unichar_ismark(g_utf8_get_char(p))) {
     781    p = g_utf8_find_next_char(p, NULL);
     782  }
     783  if (p == NULL) {
     784    _owl_editwin_set_xy_by_index(e, e->bufflen);
     785  }
     786  else {
     787    _owl_editwin_set_xy_by_index(e, p - e->buff);
    656788  }
    657789
    658790  /* do we need to scroll down? */
    659   if (e->buffy-e->topline >= e->winlines) {
    660     e->topline+=e->winlines/2;
     791  if (e->buffy - e->topline >= e->winlines) {
     792    e->topline += e->winlines / 2;
    661793  }
    662794}
     
    664796void owl_editwin_move_to_nextword(owl_editwin *e)
    665797{
     798  /* asedeno: needs fixing for utf-8*/
    666799  int i, x;
    667800
     
    703836void owl_editwin_move_to_previousword(owl_editwin *e)
    704837{
     838  /* asedeno: needs fixing for utf-8*/
    705839  int i, x;
    706840
     
    738872void owl_editwin_delete_nextword(owl_editwin *e)
    739873{
     874  /* asedeno: needs fixing for utf-8*/
    740875  int z;
    741876
     
    768903void owl_editwin_delete_previousword(owl_editwin *e)
    769904{
     905  /* asedeno: needs fixing for utf-8*/
    770906  /* go backwards to the last non-space character, then delete chars */
    771907  int i, startpos, endpos;
     
    781917void owl_editwin_delete_to_endofline(owl_editwin *e)
    782918{
     919  /* asedeno: needs fixing for utf-8*/
    783920  int i;
    784921
    785   if (owl_editwin_get_numchars_on_line(e, e->buffy)>e->buffx) {
     922  if (owl_editwin_get_numchars_on_line(e, e->buffy) > e->buffx) {
    786923    /* normal line */
    787924    i=_owl_editwin_get_index_from_xy(e);
     
    804941void owl_editwin_move_to_line_end(owl_editwin *e)
    805942{
    806   e->buffx=owl_editwin_get_numchars_on_line(e, e->buffy);
     943  e->buffx=owl_editwin_get_numcells_on_line(e, e->buffy);
    807944}
    808945
     
    817954  /* go to last char */
    818955  e->buffy=owl_editwin_get_numlines(e)-1;
    819   e->buffx=owl_editwin_get_numchars_on_line(e, e->buffy);
     956  e->buffx=owl_editwin_get_numcells_on_line(e, e->buffy);
    820957  owl_editwin_key_right(e);
    821958
     
    841978void owl_editwin_fill_paragraph(owl_editwin *e)
    842979{
     980  /* asedeno: needs fixing for utf-8*/
    843981  int i, save;
    844982
     
    857995  /* main loop */
    858996  while (1) {
    859     i=_owl_editwin_get_index_from_xy(e);
     997    i = _owl_editwin_get_index_from_xy(e);
    860998
    861999    /* bail if we hit the end of the buffer */
    862     if (i>=e->bufflen) break;
     1000    if (i >= e->bufflen || e->buff[i] == '\0') break;
    8631001
    8641002    /* bail if we hit the end of the paragraph */
    865     if (e->buff[i]=='\n' && e->buff[i+1]=='\n') break;
     1003    if (e->buff[i] == '\n' && e->buff[i+1] == '\n') break;
    8661004
    8671005    /* if we've travelled too far, linewrap */
     
    8711009
    8721010    /* did we hit the end of a line too soon? */
    873     i=_owl_editwin_get_index_from_xy(e);
    874     if (e->buff[i]=='\n' && e->buffx<e->fillcol-1) {
     1011    i = _owl_editwin_get_index_from_xy(e);
     1012    if (e->buff[i] == '\n' && e->buffx < e->fillcol - 1) {
    8751013      /* ********* we need to make sure we don't pull in a word that's too long ***********/
    8761014      e->buff[i]=' ';
     
    8781016   
    8791017    /* fix spacing */
    880     i=_owl_editwin_get_index_from_xy(e);
    881     if (e->buff[i]==' ' && e->buff[i+1]==' ') {
    882       if (e->buff[i-1]=='.' || e->buff[i-1]=='!' || e->buff[i-1]=='?') {
     1018    i = _owl_editwin_get_index_from_xy(e);
     1019    if (e->buff[i] == ' ' && e->buff[i+1] == ' ') {
     1020      if (e->buff[i-1] == '.' || e->buff[i-1] == '!' || e->buff[i-1] == '?') {
    8831021        owl_editwin_key_right(e);
    8841022      } else {
    8851023        owl_editwin_delete_char(e);
    8861024        /* if we did this ahead of the save point, adjust it */
    887         if (i<save) save--;
     1025        if (i < save) save--;
    8881026      }
    8891027    } else {
     
    9111049int owl_editwin_check_dotsend(owl_editwin *e)
    9121050{
    913   int i;
     1051  char *p, *p_n, *p_p;
     1052  gunichar c;
    9141053
    9151054  if (!e->dotsend) return(0);
    916   for (i=e->bufflen-1; i>0; i--) {
    917     if (e->buff[i] == '.'
    918         && (e->buff[i-1] == '\n' || e->buff[i-1] == '\r')
    919         && (e->buff[i+1] == '\n' || e->buff[i+1] == '\r')) {
    920       e->bufflen = i;
    921       e->buff[i] = '\0';
     1055
     1056  p = g_utf8_find_prev_char(e->buff, e->buff + e->bufflen);
     1057  p_n = g_utf8_find_next_char(p, NULL);
     1058  p_p = g_utf8_find_prev_char(e->buff, p);
     1059  c = g_utf8_get_char(p);
     1060  while (p != NULL) {
     1061    if (*p == '.'
     1062        && p_p != NULL && (*p_p == '\n' || *p_p == '\r')
     1063        && p_n != NULL && (*p_n == '\n' || *p_n == '\r')) {
     1064      e->bufflen = p - e->buff;
     1065      e->buff[e->bufflen] = '\0';
    9221066      return(1);
    9231067    }
    924     if (!isspace((int) e->buff[i])) {
    925       return(0);
    926     }
     1068    if (c != '\0' && !g_unichar_isspace(c)) return(0);
     1069    p_n = p;
     1070    p = p_p;
     1071    c = g_utf8_get_char(p);
     1072    p_p = g_utf8_find_prev_char(e->buff, p);
    9271073  }
    9281074  return(0);
    9291075}
    9301076
    931 void owl_editwin_post_process_char(owl_editwin *e, int j)
     1077void owl_editwin_post_process_char(owl_editwin *e, gunichar j)
    9321078{
    9331079  /* check if we need to scroll down */
     
    9421088}
    9431089
    944 void owl_editwin_process_char(owl_editwin *e, int j)
     1090void owl_editwin_process_char(owl_editwin *e, gunichar j)
    9451091{
    9461092  if (j == ERR) return;
    947   if (j>127 || ((j<32) && (j!=10) && (j!=13))) {
     1093  if (g_unichar_iscntrl(j) && (j != 10) && (j != 13)) {
    9481094    return;
    949   } else {
     1095  }
     1096  else {
    9501097    owl_editwin_insert_char(e, j);
    9511098  }
     
    9751122  }
    9761123
    977   /* now go to the xth character */
    978   ptr2=strchr(ptr1, '\n');
    979   if (!ptr2) {
    980     return(e->buff + e->bufflen - ptr1);
    981   }
    982   return(ptr2-ptr1); /* don't count the newline for now */
     1124  /* now count characters */
     1125  i = 0;
     1126  ptr2 = ptr1;
     1127  while (ptr2 - e->buff < e->bufflen
     1128         && *ptr2 != '\n') {
     1129    ++i;
     1130    ptr2 = g_utf8_next_char(ptr2);
     1131  }
     1132  return i;
     1133}
     1134
     1135int owl_editwin_get_numcells_on_line(owl_editwin *e, int line)
     1136{
     1137  int i;
     1138  char *ptr1, *ptr2;
     1139  gunichar c;
     1140
     1141  if (e->bufflen==0) return(0);
     1142 
     1143  /* first go to the yth line */
     1144  ptr1=e->buff;
     1145  for (i=0; i<line; i++) {
     1146    ptr2=strchr(ptr1, '\n');
     1147    if (!ptr2) {
     1148      /* we're already on the last line */
     1149      return(0);
     1150    }
     1151    ptr1=ptr2+1;
     1152  }
     1153
     1154  /* now count cells */
     1155  i = 0;
     1156  ptr2 = ptr1;
     1157  while (ptr2 - e->buff < e->bufflen
     1158         && *ptr2 != '\n') {
     1159    c = g_utf8_get_char(ptr2);
     1160    i += mk_wcwidth(c);
     1161    ptr2 = g_utf8_next_char(ptr2);
     1162  }
     1163  return i;
    9831164}
    9841165
  • fmtext.c

    rfa3290d r16c6cca  
    88void owl_fmtext_init_null(owl_fmtext *f)
    99{
    10   f->textlen=0;
    11   f->bufflen=5;
    12   f->textbuff=owl_malloc(5);
    13   f->fmbuff=owl_malloc(5);
    14   f->fgcolorbuff=owl_malloc(5 * sizeof(short));
    15   f->bgcolorbuff=owl_malloc(5 * sizeof(short));
    16   f->textbuff[0]=0;
    17   f->fmbuff[0]=OWL_FMTEXT_ATTR_NONE;
    18   f->fgcolorbuff[0]=OWL_COLOR_DEFAULT;
    19   f->bgcolorbuff[0]=OWL_COLOR_DEFAULT;
     10  f->textlen = 0;
     11  f->bufflen = 5;
     12  f->textbuff = owl_malloc(5);
     13  f->textbuff[0] = 0;
     14  f->default_attrs = OWL_FMTEXT_ATTR_NONE;
     15  f->default_fgcolor = OWL_COLOR_DEFAULT;
     16  f->default_fgcolor = OWL_COLOR_DEFAULT;
    2017}
    2118
     
    2421void owl_fmtext_clear(owl_fmtext *f)
    2522{
    26     f->textlen = 0;
    27     f->textbuff[0] = 0;
    28     f->fmbuff[0]=OWL_FMTEXT_ATTR_NONE;
    29     f->fgcolorbuff[0]=OWL_COLOR_DEFAULT;
    30     f->bgcolorbuff[0]=OWL_COLOR_DEFAULT;
    31 }
    32 
    33 /* Internal function.  Set the attribute 'attr' from index 'first' to
    34  * index 'last'
    35  */
    36 void _owl_fmtext_set_attr(owl_fmtext *f, int attr, int first, int last)
    37 {
    38   int i;
    39   for (i=first; i<=last; i++) {
    40     f->fmbuff[i]=(unsigned char) attr;
    41   }
    42 }
    43 
    44 /* Internal function.  Add the attribute 'attr' to the existing
    45  * attributes from index 'first' to index 'last'
    46  */
    47 void _owl_fmtext_add_attr(owl_fmtext *f, int attr, int first, int last)
    48 {
    49   int i;
    50   for (i=first; i<=last; i++) {
    51     f->fmbuff[i]|=(unsigned char) attr;
    52   }
    53 }
    54 
    55 /* Internal function.  Set the color to be 'color' from index 'first'
    56  * to index 'last
    57  */
    58 void _owl_fmtext_set_fgcolor(owl_fmtext *f, int color, int first, int last)
    59 {
    60   int i;
    61   for (i=first; i<=last; i++) {
    62     f->fgcolorbuff[i]=(short)color;
    63   }
    64 }
    65 
    66 void _owl_fmtext_set_bgcolor(owl_fmtext *f, int color, int first, int last)
    67 {
    68   int i;
    69   for (i=first; i<=last; i++) {
    70     f->bgcolorbuff[i]=(short)color;
    71   }
     23  f->textlen = 0;
     24  f->textbuff[0] = 0;
     25  f->default_attrs = OWL_FMTEXT_ATTR_NONE;
     26  f->default_fgcolor = OWL_COLOR_DEFAULT;
     27  f->default_fgcolor = OWL_COLOR_DEFAULT;
    7228}
    7329
     
    7531{
    7632    if(newlen + 1 > f->bufflen) {
    77       f->textbuff=owl_realloc(f->textbuff, newlen+1);
    78       f->fmbuff=owl_realloc(f->fmbuff, newlen+1);
    79       f->fgcolorbuff=owl_realloc(f->fgcolorbuff, (newlen+1) * sizeof(short));
    80       f->bgcolorbuff=owl_realloc(f->bgcolorbuff, (newlen+1) * sizeof(short));
     33      f->textbuff = owl_realloc(f->textbuff, newlen + 1);
    8134      f->bufflen = newlen+1;
    8235  }
    8336}
    8437
     38int _owl_fmtext_is_format_char(gunichar c) /*noproto*/
     39{
     40  if ((c & ~OWL_FMTEXT_UC_ATTR_MASK) == OWL_FMTEXT_UC_ATTR) return 1;
     41  if ((c & ~(OWL_FMTEXT_UC_ALLCOLOR_MASK)) == OWL_FMTEXT_UC_COLOR_BASE) return 1;
     42  return 0;
     43}
    8544/* append text to the end of 'f' with attribute 'attr' and color
    8645 * 'color'
    8746 */
    88 void owl_fmtext_append_attr(owl_fmtext *f, char *text, int attr, int fgcolor, int bgcolor)
    89 {
    90   int newlen;
    91   newlen=strlen(f->textbuff)+strlen(text);
     47void owl_fmtext_append_attr(owl_fmtext *f, char *text, char attr, short fgcolor, short bgcolor)
     48{
     49  char attrbuff[6];
     50  int newlen, a = 0, fg = 0, bg = 0;
     51 
     52  if (attr != OWL_FMTEXT_ATTR_NONE) a=1;
     53  if (fgcolor != OWL_COLOR_DEFAULT) fg=1;
     54  if (bgcolor != OWL_COLOR_DEFAULT) bg=1;
     55
     56  /* Plane-16 characters in UTF-8 are 4 bytes long. */
     57  newlen = strlen(f->textbuff) + strlen(text) + (8 * (a + fg + bg));
    9258  _owl_fmtext_realloc(f, newlen);
     59
     60  /* Set attributes */
     61  if (a) {
     62    memset(attrbuff,0,6);
     63    g_unichar_to_utf8(OWL_FMTEXT_UC_ATTR | attr, attrbuff);
     64    strcat(f->textbuff, attrbuff);     
     65  }
     66  if (fg) {
     67    memset(attrbuff,0,6);
     68    g_unichar_to_utf8(OWL_FMTEXT_UC_FGCOLOR | fgcolor, attrbuff);
     69    strcat(f->textbuff, attrbuff);     
     70  }
     71  if (bg) {
     72    memset(attrbuff,0,6);
     73    g_unichar_to_utf8(OWL_FMTEXT_UC_BGCOLOR | bgcolor, attrbuff);
     74    strcat(f->textbuff, attrbuff);     
     75  }
    9376 
    9477  strcat(f->textbuff, text);
    95   _owl_fmtext_set_attr(f, attr, f->textlen, newlen);
    96   _owl_fmtext_set_fgcolor(f, fgcolor, f->textlen, newlen);
    97   _owl_fmtext_set_bgcolor(f, bgcolor, f->textlen, newlen);
     78
     79  /* Reset attributes */
     80  if (bg) strcat(f->textbuff, OWL_FMTEXT_UTF8_BGDEFAULT);
     81  if (fg) strcat(f->textbuff, OWL_FMTEXT_UTF8_FGDEFAULT);
     82  if (a)  strcat(f->textbuff, OWL_FMTEXT_UTF8_ATTR_NONE);
    9883  f->textlen=newlen;
    9984}
     
    129114}
    130115
    131 /* Add the attribute 'attr' to all text in 'f' */
    132 void owl_fmtext_addattr(owl_fmtext *f, int attr)
     116/* Add the attribute 'attr' to the default atts for the text in 'f' */
     117void owl_fmtext_addattr(owl_fmtext *f, char attr)
    133118{
    134119  /* add the attribute to all text */
    135   int i, j;
    136 
    137   j=f->textlen;
    138   for (i=0; i<j; i++) {
    139     f->fmbuff[i] |= attr;
    140   }
    141 }
    142 
    143 /* Anywhere the color is NOT ALREDY SET, set the color to 'color'.
    144  * Other colors are left unchanged
     120  f->default_attrs |= attr;
     121}
     122
     123/* Set the default foreground color for this fmtext to 'color'.
     124 * Only affects text that is colored default.
    145125 */
    146126void owl_fmtext_colorize(owl_fmtext *f, int color)
    147127{
    148   /* everywhere the fgcolor is OWL_COLOR_DEFAULT, change it to be 'color' */
    149   int i, j;
    150 
    151   j=f->textlen;
    152   for(i=0; i<j; i++) {
    153     if (f->fgcolorbuff[i]==OWL_COLOR_DEFAULT) f->fgcolorbuff[i] = (short)color;
    154   }
    155 }
    156 
     128  f->default_fgcolor = color;
     129}
     130
     131/* Set the default foreground color for this fmtext to 'color'.
     132 * Only affects text that is colored default.
     133 */
    157134void owl_fmtext_colorizebg(owl_fmtext *f, int color)
    158135{
    159   /* everywhere the bgcolor is OWL_COLOR_DEFAULT, change it to be 'color' */
    160   int i, j;
    161 
    162   j=f->textlen;
    163   for(i=0; i<j; i++) {
    164     if (f->bgcolorbuff[i]==OWL_COLOR_DEFAULT) f->bgcolorbuff[i] = (short)color;
    165   }
    166 }
     136  f->default_bgcolor = color;
     137}
     138
     139/* Internal function. Parse attrbute character. */
     140void _owl_fmtext_update_attributes(gunichar c, char *attr, short *fgcolor, short *bgcolor) /*noproto*/
     141{
     142  if ((c & OWL_FMTEXT_UC_ATTR) == OWL_FMTEXT_UC_ATTR) {
     143    *attr = c & OWL_FMTEXT_UC_ATTR_MASK;
     144  }
     145  else if ((c & OWL_FMTEXT_UC_FGCOLOR) == OWL_FMTEXT_UC_FGCOLOR) {
     146    *fgcolor = (c == OWL_FMTEXT_UC_FGDEFAULT
     147                ? OWL_COLOR_DEFAULT
     148                : c & OWL_FMTEXT_UC_COLOR_MASK);
     149  }
     150  else if ((c & OWL_FMTEXT_UC_BGCOLOR) == OWL_FMTEXT_UC_BGCOLOR) {
     151    *bgcolor = (c == OWL_FMTEXT_UC_BGDEFAULT
     152                ? OWL_COLOR_DEFAULT
     153                : c & OWL_FMTEXT_UC_COLOR_MASK);
     154  }
     155}
     156
     157/* Internal function. Scan for attribute characters. */
     158void _owl_fmtext_scan_attributes(owl_fmtext *f, int start, char *attr, short *fgcolor, short *bgcolor) /*noproto*/
     159{
     160  char *p;
     161  p = strchr(f->textbuff, OWL_FMTEXT_UC_STARTBYTE_UTF8);
     162  while (p && p < f->textbuff + start) {
     163    _owl_fmtext_update_attributes(g_utf8_get_char(p), attr, fgcolor, bgcolor);
     164    p = strchr(p+1, OWL_FMTEXT_UC_STARTBYTE_UTF8);
     165  }
     166
    167167
    168168/* Internal function.  Append text from 'in' between index 'start' and
    169169 * 'stop' to the end of 'f'
    170170 */
    171 void _owl_fmtext_append_fmtext(owl_fmtext *f, owl_fmtext *in, int start, int stop)
    172 {
    173   int newlen, i;
    174 
    175   newlen=strlen(f->textbuff)+(stop-start+1);
     171void _owl_fmtext_append_fmtext(owl_fmtext *f, owl_fmtext *in, int start, int stop) /*noproto*/
     172{
     173  char attrbuff[6];
     174  int newlen, a = 0, fg = 0, bg = 0;
     175  char attr = 0;
     176  short fgcolor = OWL_COLOR_DEFAULT;
     177  short bgcolor = OWL_COLOR_DEFAULT;
     178
     179  _owl_fmtext_scan_attributes(in, start, &attr, &fgcolor, &bgcolor);
     180  if (attr != OWL_FMTEXT_ATTR_NONE) a=1;
     181  if (fgcolor != OWL_COLOR_DEFAULT) fg=1;
     182  if (bgcolor != OWL_COLOR_DEFAULT) bg=1;
     183
     184  /* We will reset to defaults after appending the text. We may need
     185     to set initial attributes. */
     186  newlen=strlen(f->textbuff)+(stop-start+1) + (4 * (a + fg + bg)) + 12;
    176187  _owl_fmtext_realloc(f, newlen);
    177188
     189  if (a) {
     190    memset(attrbuff,0,6);
     191    g_unichar_to_utf8(OWL_FMTEXT_UC_ATTR | attr, attrbuff);
     192    strcat(f->textbuff, attrbuff);     
     193  }
     194  if (fg) {
     195    memset(attrbuff,0,6);
     196    g_unichar_to_utf8(OWL_FMTEXT_UC_FGCOLOR | fgcolor, attrbuff);
     197    strcat(f->textbuff, attrbuff);     
     198  }
     199  if (bg) {
     200    memset(attrbuff,0,6);
     201    g_unichar_to_utf8(OWL_FMTEXT_UC_BGCOLOR | bgcolor, attrbuff);
     202    strcat(f->textbuff, attrbuff);     
     203  }
     204
    178205  strncat(f->textbuff, in->textbuff+start, stop-start+1);
     206
     207  /* Reset attributes */
     208  strcat(f->textbuff, OWL_FMTEXT_UTF8_BGDEFAULT);
     209  strcat(f->textbuff, OWL_FMTEXT_UTF8_FGDEFAULT);
     210  strcat(f->textbuff, OWL_FMTEXT_UTF8_ATTR_NONE);
     211
    179212  f->textbuff[newlen]='\0';
    180   for (i=start; i<=stop; i++) {
    181     f->fmbuff[f->textlen+(i-start)]=in->fmbuff[i];
    182     f->fgcolorbuff[f->textlen+(i-start)]=in->fgcolorbuff[i];
    183     f->bgcolorbuff[f->textlen+(i-start)]=in->bgcolorbuff[i];
    184   }
    185213  f->textlen=newlen;
    186214}
     
    207235char *owl_fmtext_print_plain(owl_fmtext *f)
    208236{
    209   return(owl_strdup(f->textbuff));
     237  return owl_strip_format_chars(f->textbuff);
     238}
     239
     240void _owl_fmtext_wattrset(WINDOW *w, int attrs) /*noproto*/
     241{
     242  wattrset(w, A_NORMAL);
     243  if (attrs & OWL_FMTEXT_ATTR_BOLD) wattron(w, A_BOLD);
     244  if (attrs & OWL_FMTEXT_ATTR_REVERSE) wattron(w, A_REVERSE);
     245  if (attrs & OWL_FMTEXT_ATTR_UNDERLINE) wattron(w, A_UNDERLINE);
     246}
     247
     248void _owl_fmtext_update_colorpair(short fg, short bg, short *pair) /*noproto*/
     249{
     250  if (owl_global_get_hascolors(&g)) {
     251    *pair = owl_fmtext_get_colorpair(fg, bg);
     252  }
     253}
     254
     255void _owl_fmtext_wcolor_set(WINDOW *w, short pair) /*noproto*/
     256{
     257  if (owl_global_get_hascolors(&g)) {
     258      wcolor_set(w,pair,NULL);
     259  }
    210260}
    211261
     
    213263 * must already be initiatlized with curses
    214264 */
    215 void owl_fmtext_curs_waddstr(owl_fmtext *f, WINDOW *w)
    216 {
    217   char *tmpbuff;
    218   int position, trans1, trans2, trans3, len, lastsame;
    219 
     265void _owl_fmtext_curs_waddstr(owl_fmtext *f, WINDOW *w, int do_search) /*noproto*/
     266{
     267  /* char *tmpbuff; */
     268  /* int position, trans1, trans2, trans3, len, lastsame; */
     269  char *s, *p;
     270  char attr;
     271  short fg, bg, pair;
     272  int search_results, search_len;
     273 
    220274  if (w==NULL) {
    221275    owl_function_debugmsg("Hit a null window in owl_fmtext_curs_waddstr.");
     
    223277  }
    224278
    225   tmpbuff=owl_malloc(f->textlen+10);
    226 
    227   position=0;
    228   len=f->textlen;
    229   while (position<=len) {
    230     /* find the last char with the current format and color */
    231     trans1=owl_util_find_trans(f->fmbuff+position, len-position);
    232     trans2=owl_util_find_trans_short(f->fgcolorbuff+position, len-position);
    233     trans3=owl_util_find_trans_short(f->bgcolorbuff+position, len-position);
    234 
    235     lastsame = (trans1 < trans2) ? trans1 : trans2;
    236     lastsame = (lastsame < trans3) ? lastsame : trans3;
    237     lastsame += position;
    238 
    239     /* set the format */
    240     wattrset(w, A_NORMAL);
    241     if (f->fmbuff[position] & OWL_FMTEXT_ATTR_BOLD) {
    242       wattron(w, A_BOLD);
    243     }
    244     if (f->fmbuff[position] & OWL_FMTEXT_ATTR_REVERSE) {
    245       wattron(w, A_REVERSE);
    246     }
    247     if (f->fmbuff[position] & OWL_FMTEXT_ATTR_UNDERLINE) {
    248       wattron(w, A_UNDERLINE);
    249     }
    250 
    251     /* set the color */
    252     /* warning, this is sort of a hack */
    253     if (owl_global_get_hascolors(&g)) {
    254       short fg, bg, pair;
    255       fg = f->fgcolorbuff[position];
    256       bg = f->bgcolorbuff[position];
    257 
    258       pair = owl_fmtext_get_colorpair(fg, bg);
    259       if (pair != -1) {
    260         wcolor_set(w,pair,NULL);
    261       }
    262     }
    263 
    264     /* add the text */
    265     strncpy(tmpbuff, f->textbuff + position, lastsame-position+1);
    266     tmpbuff[lastsame-position+1]='\0';
    267     waddstr(w, tmpbuff);
    268 
    269     position=lastsame+1;
    270   }
    271   owl_free(tmpbuff);
    272 }
    273 
     279  search_results = (do_search
     280                    ? owl_fmtext_search(f, owl_global_get_search_string(&g))
     281                    : 0);
     282  search_len = (search_results
     283                ? strlen(owl_global_get_search_string(&g))
     284                : 0);
     285  s = f->textbuff;
     286  /* Set default attributes. */
     287  attr = f->default_attrs;
     288  fg = f->default_fgcolor;
     289  bg = f->default_bgcolor;
     290  _owl_fmtext_wattrset(w, attr);
     291  _owl_fmtext_update_colorpair(fg, bg, &pair);
     292  _owl_fmtext_wcolor_set(w, pair);
     293
     294  /* Find next possible format character. */
     295  p = strchr(s, OWL_FMTEXT_UC_STARTBYTE_UTF8);
     296  while(p) {
     297    if (_owl_fmtext_is_format_char(g_utf8_get_char(p))) {
     298      /* Deal with all text from last insert to here. */
     299      char tmp;
     300   
     301      tmp = p[0];
     302      p[0] = '\0';
     303      if (search_results) {
     304        /* Search is active, so highlight search results. */
     305        char tmp2, *ss;
     306        ss = stristr(s, owl_global_get_search_string(&g));
     307        while (ss) {
     308          /* Found search string, highlight it. */
     309
     310          tmp2 = ss[0];
     311          ss[0] = '\0';
     312          waddstr(w, s);
     313          ss[0] = tmp2;
     314
     315          _owl_fmtext_wattrset(w, attr ^ OWL_FMTEXT_ATTR_REVERSE);
     316          _owl_fmtext_wcolor_set(w, pair);
     317         
     318          tmp2 = ss[search_len];
     319          ss[search_len] = '\0';
     320          waddstr(w, ss);
     321          ss[search_len] = tmp2;
     322
     323          _owl_fmtext_wattrset(w, attr);
     324          _owl_fmtext_wcolor_set(w, pair);
     325
     326          s = ss + search_len;
     327          ss = stristr(s, owl_global_get_search_string(&g));
     328        }
     329      }
     330      /* Deal with remaining part of string. */
     331      waddstr(w, s);
     332      p[0] = tmp;
     333
     334      /* Deal with new attributes. Initialize to defaults, then
     335         process all consecutive formatting characters. */
     336      attr = f->default_attrs;
     337      fg = f->default_fgcolor;
     338      bg = f->default_bgcolor;
     339      while (p && _owl_fmtext_is_format_char(g_utf8_get_char(p))) {
     340        _owl_fmtext_update_attributes(g_utf8_get_char(p), &attr, &fg, &bg);
     341        p = g_utf8_next_char(p);
     342      }
     343      _owl_fmtext_wattrset(w, attr | f->default_attrs);
     344      if (fg == OWL_COLOR_DEFAULT) fg = f->default_fgcolor;
     345      if (bg == OWL_COLOR_DEFAULT) bg = f->default_bgcolor;
     346      _owl_fmtext_update_colorpair(fg, bg, &pair);
     347      _owl_fmtext_wcolor_set(w, pair);
     348
     349      /* Advance to next non-formatting character. */
     350      s = p;
     351      p = strchr(s, OWL_FMTEXT_UC_STARTBYTE_UTF8);
     352    }
     353    else {
     354      p = strchr(p+1, OWL_FMTEXT_UC_STARTBYTE_UTF8);
     355    }
     356  }
     357  if (s) {
     358    waddstr(w, s);
     359  }
     360}
     361
     362void owl_fmtext_curs_waddstr(owl_fmtext *f, WINDOW *w)
     363{
     364  _owl_fmtext_curs_waddstr(f, w, owl_global_is_search_active(&g));
     365}
     366
     367void owl_fmtext_curs_waddstr_without_search(owl_fmtext *f, WINDOW *w)
     368{
     369  _owl_fmtext_curs_waddstr(f, w, 0);
     370}
    274371
    275372/* start with line 'aline' (where the first line is 0) and print
     
    282379 
    283380  /* find the starting line */
    284   ptr1=in->textbuff;
    285   if (aline!=0) {
    286     for (i=0; i<aline; i++) {
    287       ptr1=strchr(ptr1, '\n');
    288       if (!ptr1) return(-1);
    289       ptr1++;
    290     }
    291   }
     381  ptr1 = in->textbuff;
     382  for (i = 0; i < aline; i++) {
     383    ptr1 = strchr(ptr1, '\n');
     384    if (!ptr1) return(-1);
     385    ptr1++;
     386  }
     387 
    292388  /* ptr1 now holds the starting point */
    293389
    294390  /* copy in the next 'lines' lines */
    295   if (lines<1) return(-1);
    296 
    297   for (i=0; i<lines; i++) {
    298     offset=ptr1-in->textbuff;
    299     ptr2=strchr(ptr1, '\n');
     391  if (lines < 1) return(-1);
     392
     393  for (i = 0; i < lines; i++) {
     394    offset = ptr1 - in->textbuff;
     395    ptr2 = strchr(ptr1, '\n');
    300396    if (!ptr2) {
    301       _owl_fmtext_append_fmtext(out, in, offset, (in->textlen)-1);
     397      _owl_fmtext_append_fmtext(out, in, offset, (in->textlen) - 1);
    302398      return(-1);
    303399    }
    304     _owl_fmtext_append_fmtext(out, in, offset, (ptr2-ptr1)+offset);
    305     ptr1=ptr2+1;
     400    _owl_fmtext_append_fmtext(out, in, offset, (ptr2 - ptr1) + offset);
     401    ptr1 = ptr2 + 1;
    306402  }
    307403  return(0);
     
    311407 * ends at 'bcol' or sooner.  The first column is number 0.  The new
    312408 * message is placed in 'out'.  The message is * expected to end in a
    313  * new line for now
     409 * new line for now. NOTE: This needs to be modified to deal with
     410 * backing up if we find a SPACING COMBINING MARK at the end of a
     411 * line. If that happens, we should back up to the last non-mark
     412 * character and stop there.
    314413 */
    315414void owl_fmtext_truncate_cols(owl_fmtext *in, int acol, int bcol, owl_fmtext *out)
    316415{
    317   char *ptr1, *ptr2, *last;
    318   int len, offset;
     416  char *ptr_s, *ptr_e, *ptr_c, *last;
     417  int col, st, padding, chwidth;
    319418
    320419  last=in->textbuff+in->textlen-1;
    321   ptr1=in->textbuff;
    322   while (ptr1<=last) {
    323     ptr2=strchr(ptr1, '\n');
    324     if (!ptr2) {
     420  ptr_s=in->textbuff;
     421  while (ptr_s <= last) {
     422    ptr_e=strchr(ptr_s, '\n');
     423    if (!ptr_e) {
    325424      /* but this shouldn't happen if we end in a \n */
    326425      break;
    327426    }
    328427   
    329     if (ptr2==ptr1) {
     428    if (ptr_e == ptr_s) {
    330429      owl_fmtext_append_normal(out, "\n");
    331       ptr1++;
     430      ++ptr_s;
    332431      continue;
    333432    }
    334433
    335     /* we need to check that we won't run over here */
    336     len=bcol-acol;
    337     if (len > (ptr2-(ptr1+acol))) {
    338       /* the whole line fits with room to spare, don't take a full 'len' */
    339       len=ptr2-(ptr1+acol);
    340     }
    341     if (len>last-ptr1) {
    342       /* the whole rest of the text fits with room to spare, adjust for it */
    343       len-=(last-ptr1);
    344     }
    345     if (len<=0) {
    346       /* saftey check */
     434    col = 0;
     435    st = 0;
     436    padding = 0;
     437    chwidth = 0;
     438    ptr_c = ptr_s;
     439    while(ptr_c < ptr_e) {
     440      gunichar c = g_utf8_get_char(ptr_c);
     441      if (!_owl_fmtext_is_format_char(c)) {
     442        chwidth = mk_wcwidth(c);
     443        if (col + chwidth > bcol) break;
     444       
     445        if (col >= acol) {
     446          if (st == 0) {
     447            ptr_s = ptr_c;
     448            padding = col - acol;
     449            ++st;
     450          }
     451        }
     452        col += chwidth;
     453        chwidth = 0;
     454      }
     455      ptr_c = g_utf8_next_char(ptr_c);
     456    }
     457    if (st) {
     458      /* lead padding */
     459      owl_fmtext_append_spaces(out, padding);
     460      if (ptr_c == ptr_e) {
     461        /* We made it to the newline. */
     462        _owl_fmtext_append_fmtext(out, in, ptr_s - in->textbuff, ptr_c - in->textbuff);
     463      }
     464      else {
     465        if (chwidth > 1) {
     466          /* Last char is wide, truncate. */
     467          _owl_fmtext_append_fmtext(out, in, ptr_s - in->textbuff, ptr_c - in->textbuff - 1);
     468          owl_fmtext_append_normal(out, "\n");
     469        }
     470        else {
     471          /* Last char fits perfectly, leave alone.*/
     472          _owl_fmtext_append_fmtext(out, in, ptr_s - in->textbuff, ptr_c - in->textbuff);
     473        }
     474      }
     475    }
     476    else {
    347477      owl_fmtext_append_normal(out, "\n");
    348       ptr1=ptr2+1;
    349       continue;
    350     }
    351 
    352     offset=ptr1-in->textbuff;
    353     _owl_fmtext_append_fmtext(out, in, offset+acol, offset+acol+len);
    354 
    355     ptr1=ptr2+1;
     478    }
     479    ptr_s = g_utf8_next_char(ptr_e);
    356480  }
    357481}
     
    381505
    382506/* set the charater at 'index' to be 'char'.  If index is out of
    383  * bounds don't do anything */
    384 void owl_fmtext_set_char(owl_fmtext *f, int index, int ch)
     507 * bounds don't do anything. If c or char at index is not ASCII, don't
     508 * do anything because it's not UTF-8 safe. */
     509void owl_fmtext_set_char(owl_fmtext *f, int index, char ch)
    385510{
    386511  if ((index < 0) || (index > f->textlen-1)) return;
     512  /* NOT ASCII*/
     513  if (f->textbuff[index] & 0x80 || ch & 0x80) return;
    387514  f->textbuff[index]=ch;
    388515}
     
    400527  dst->textlen=src->textlen;
    401528  dst->textbuff=owl_malloc(mallocsize);
    402   dst->fmbuff=owl_malloc(mallocsize);
    403   dst->fgcolorbuff=owl_malloc(mallocsize * sizeof(short));
    404   dst->bgcolorbuff=owl_malloc(mallocsize * sizeof(short));
    405529  memcpy(dst->textbuff, src->textbuff, src->textlen+1);
    406   memcpy(dst->fmbuff, src->fmbuff, src->textlen);
    407   memcpy(dst->fgcolorbuff, src->fgcolorbuff, src->textlen * sizeof(short));
    408   memcpy(dst->bgcolorbuff, src->bgcolorbuff, src->textlen * sizeof(short));
    409 }
    410 
    411 /* highlight all instances of "string".  Return the number of
    412  * instances found.  This is a case insensitive search.
    413  */
    414 int owl_fmtext_search_and_highlight(owl_fmtext *f, char *string)
    415 {
    416 
    417   int found, len;
    418   char *ptr1, *ptr2;
    419 
    420   len=strlen(string);
    421   found=0;
    422   ptr1=f->textbuff;
    423   while (ptr1-f->textbuff <= f->textlen) {
    424     ptr2=stristr(ptr1, string);
    425     if (!ptr2) return(found);
    426 
    427     found++;
    428     _owl_fmtext_add_attr(f, OWL_FMTEXT_ATTR_REVERSE,
    429                          ptr2 - f->textbuff,
    430                          ptr2 - f->textbuff + len - 1);
    431 
    432     ptr1=ptr2+len;
    433   }
    434   return(found);
     530  dst->default_attrs = src->default_attrs;
     531  dst->default_fgcolor = src->default_fgcolor;
     532  dst->default_bgcolor = src->default_bgcolor;
    435533}
    436534
     
    440538int owl_fmtext_search(owl_fmtext *f, char *string)
    441539{
    442 
    443540  if (stristr(f->textbuff, string)) return(1);
    444541  return(0);
     
    681778{
    682779  if (f->textbuff) owl_free(f->textbuff);
    683   if (f->fmbuff) owl_free(f->fmbuff);
    684   if (f->fgcolorbuff) owl_free(f->fgcolorbuff);
    685   if (f->bgcolorbuff) owl_free(f->bgcolorbuff);
    686780}
    687781
  • functions.c

    r3617286 rf9eea4c  
    16061606          sprintf(buff, "  Field %i   : ", i+1);
    16071607         
    1608           ptr=owl_zephyr_get_field(n, i+1);
     1608          ptr=owl_zephyr_get_field_as_utf8(n, i+1);
    16091609          len=strlen(ptr);
    16101610          if (len<30) {
     
    21872187void owl_function_start_command(char *line)
    21882188{
    2189   int i, j;
    21902189  owl_editwin *tw;
    21912190
     
    21982197  owl_global_set_needrefresh(&g);
    21992198
    2200   j=strlen(line);
    2201   for (i=0; i<j; i++) {
    2202     owl_editwin_process_char(tw, line[i]);
    2203   }
     2199  owl_editwin_insert_string(tw, line);
    22042200  owl_editwin_redisplay(tw, 0);
    22052201
     
    25992595  }
    26002596  /* downcase it */
    2601   downstr(filtname);
     2597  {
     2598    char *temp = g_utf8_strdown(filtname, -1);
     2599    if (temp) {
     2600      owl_free(filtname);
     2601      filtname = temp;
     2602    }
     2603  }
    26022604  /* turn spaces, single quotes, and double quotes into dots */
    26032605  owl_text_tr(filtname, ' ', '.');
     
    30243026  char *quoted;
    30253027
    3026   buff=malloc(strlen(class)+strlen(inst)+strlen(recip)+100);
     3028  buff=owl_malloc(strlen(class)+strlen(inst)+strlen(recip)+100);
    30273029  strcpy(buff, "class");
    30283030  if (!strcmp(class, "*")) {
     
    33283330          if (ret==0) {
    33293331            for (x=0; x<numlocs; x++) {
    3330               line=malloc(strlen(location[x].host)+strlen(location[x].time)+strlen(location[x].tty)+100);
     3332              line=owl_malloc(strlen(location[x].host)+strlen(location[x].time)+strlen(location[x].tty)+100);
    33313333              tmp=short_zuser(user);
    33323334              sprintf(line, "  %-10.10s %-24.24s %-12.12s  %20.20s\n",
     
    33713373  owl_view *v;
    33723374  FILE *file;
     3375  char *plaintext;
    33733376
    33743377  v=owl_global_get_current_view(&g);
     
    33933396  for (i=0; i<j; i++) {
    33943397    m=owl_view_get_element(v, i);
    3395     fputs(owl_message_get_text(m), file);
     3398    plaintext = owl_strip_format_chars(owl_message_get_text(m));
     3399    if (plaintext) {
     3400      fputs(plaintext, file);
     3401      owl_free(plaintext);
     3402    }
    33963403  }
    33973404  fclose(file);
     
    34343441          _exit(127);
    34353442        }
    3436         parsed=realloc(parsed, sizeof(*parsed) * (myargc+1));
     3443        parsed=owl_realloc(parsed, sizeof(*parsed) * (myargc+1));
    34373444        parsed[myargc] = NULL;
    34383445       
  • global.c

    rc0f9e30 rc277d89  
    549549    len+=strlen(argv[i])+5;
    550550  }
    551   g->startupargs=malloc(len+5);
     551  g->startupargs=owl_malloc(len+5);
    552552
    553553  strcpy(g->startupargs, "");
  • keymap.c

    rcf83b7a r428834d  
    55
    66/* returns 0 on success */
    7 int owl_keymap_init(owl_keymap *km, char *name, char *desc, void (*default_fn)(int), void (*prealways_fn)(int), void (*postalways_fn)(int))
     7int owl_keymap_init(owl_keymap *km, char *name, char *desc, void (*default_fn)(owl_input), void (*prealways_fn)(owl_input), void (*postalways_fn)(owl_input))
    88{
    99  if (!name || !desc) return(-1);
     
    151151}
    152152
    153 owl_keymap *owl_keyhandler_create_and_add_keymap(owl_keyhandler *kh, char *name, char *desc, void (*default_fn)(int), void (*prealways_fn)(int), void (*postalways_fn)(int))
     153owl_keymap *owl_keyhandler_create_and_add_keymap(owl_keyhandler *kh, char *name, char *desc, void (*default_fn)(owl_input), void (*prealways_fn)(owl_input), void (*postalways_fn)(owl_input))
    154154{
    155155  owl_keymap *km;
     
    202202/* processes a keypress.  returns 0 if the keypress was handled,
    203203 * 1 if not handled, -1 on error, and -2 if j==ERR. */
    204 int owl_keyhandler_process(owl_keyhandler *kh, int j)
     204int owl_keyhandler_process(owl_keyhandler *kh, owl_input j)
    205205{
    206206  owl_keymap     *km;
     
    214214
    215215  /* temporarily disallow C-`/C-SPACE until we fix associated bugs */
    216   if (j==ERR || j==0) {
     216  if (j.ch == ERR || j.ch == 0) {
    217217        return(-1);
    218218  }
     
    224224
    225225  /* deal with ESC prefixing */
    226   if (!kh->in_esc && j==27) {
     226  if (!kh->in_esc && j.ch == 27) {
    227227    kh->in_esc = 1;
    228228    return(0);
    229229  }
    230230  if (kh->in_esc) {
    231     j = OWL_META(j);
     231    j.ch = OWL_META(j.ch);
    232232    kh->in_esc = 0;
    233233  }
    234234 
    235   kh->kpstack[++(kh->kpstackpos)] = j;
     235  kh->kpstack[++(kh->kpstackpos)] = j.ch;
    236236  if (kh->kpstackpos >= OWL_KEYMAP_MAXSTACK) {
    237237    owl_keyhandler_reset(kh);
     
    260260      } else if (match == 2) {  /* exact match */
    261261        /* owl_function_debugmsg("processkey: found exact match in %s", km->name); */
    262         owl_keybinding_execute(kb, j);
     262        owl_keybinding_execute(kb, j.ch);
    263263        owl_keyhandler_reset(kh);
    264264        if (km->postalways_fn) {
  • keypress.c

    r948b942 r428834d  
    148148  }
    149149  if (!*kb) {
    150     if (j&OWL_META(0)) {
     150    if (j & OWL_META(0)) {
    151151      strcat(kb, "M-");
    152152      j &= ~OWL_META(0);
     
    163163      strcat(kb, kb2);   
    164164    }
     165   
    165166  } 
    166167  if (!*kb) {
  • keys.c

    r8938188 r428834d  
    294294/****************************************************************/
    295295
    296 void owl_keys_recwin_prealways(int j) {
     296void owl_keys_recwin_prealways(owl_input j) {
    297297  /* Clear the message line on subsequent key presses */
    298298  owl_function_makemsg("");
    299299}
    300300
    301 void owl_keys_editwin_default(int j) {
     301void owl_keys_editwin_default(owl_input j) {
    302302  owl_editwin *e;
    303   if (NULL != (e=owl_global_get_typwin(&g))) {
    304     owl_editwin_process_char(e, j);
     303  if (NULL != (e=owl_global_get_typwin(&g))
     304      && j.ch < 0x100) {
     305       owl_editwin_process_char(e, j.uch);
    305306  }
    306307}
    307308
    308 void owl_keys_editwin_postalways(int j) {
     309void owl_keys_editwin_postalways(owl_input j) {
    309310  owl_editwin *e;
    310   if (NULL != (e=owl_global_get_typwin(&g))) {
    311     owl_editwin_post_process_char(e, j);
     311  if (NULL != (e=owl_global_get_typwin(&g))
     312      && j.ch < 0x100) {
     313    owl_editwin_post_process_char(e, j.uch);
    312314  } 
    313315  owl_global_set_needrefresh(&g);
    314316}
    315317
    316 void owl_keys_popless_postalways(int j) {
     318void owl_keys_popless_postalways(owl_input j) {
    317319  owl_viewwin *v = owl_global_get_viewwin(&g);
    318320  owl_popwin *pw = owl_global_get_popwin(&g);
     
    323325}
    324326
    325 void owl_keys_default_invalid(int j) {
    326   if (j==ERR) return;
    327   if (j==410) return;
     327void owl_keys_default_invalid(owl_input j) {
     328  if (j.ch==ERR) return;
     329  if (j.ch==410) return;
    328330  owl_keyhandler_invalidkey(owl_global_get_keyhandler(&g));
    329331}
  • logging.c

    rd0961fe r28ee32b  
    155155    to = owl_sprintf("jabber:%s", owl_message_get_recipient(m));
    156156  } else if (owl_message_is_type_aim(m)) {
     157    char *temp2;
    157158    temp = owl_aim_normalize_screenname(owl_message_get_recipient(m));
    158     downstr(temp);
    159     to = owl_sprintf("aim:%s", temp);
     159    temp2 = g_utf8_strdown(temp,-1);
     160    to = owl_sprintf("aim:%s", temp2);
     161    owl_free(temp2);
    160162    owl_free(temp);
    161163  } else {
     
    267269  } else if (owl_message_is_type_aim(m)) {
    268270    /* we do not yet handle chat rooms */
    269     char *normalto;
    270     normalto=owl_aim_normalize_screenname(owl_message_get_sender(m));
    271     downstr(normalto);
     271    char *normalto, *temp;
     272    temp = owl_aim_normalize_screenname(owl_message_get_sender(m));
     273    normalto = g_utf8_strdown(temp, -1);
    272274    from=frombuff=owl_sprintf("aim:%s", normalto);
    273275    owl_free(normalto);
     276    owl_free(temp);
    274277  } else if (owl_message_is_type_loopback(m)) {
    275278    from=frombuff=owl_strdup("loopback");
     
    290293
    291294  ch=frombuff[0];
    292   if (!isalnum(ch)) from="weird";
     295  if (!g_ascii_isalnum(ch)) from="weird";
    293296
    294297  for (i=0; i<len; i++) {
     
    299302
    300303  if (!personal) {
    301     if (strcmp(from, "weird")) downstr(from);
     304    if (strcmp(from, "weird")) {
     305      char* temp = g_utf8_strdown(frombuff, -1);
     306      if (temp) {
     307        owl_free(frombuff);
     308        from = frombuff = temp;
     309      }
     310    }
    302311  }
    303312
  • owl.c

    r89f5338 r428834d  
    4848#include <termios.h>
    4949#include <sys/stat.h>
     50#include <locale.h>
    5051#include "owl.h"
    5152
     
    6970  owl_editwin *tw;
    7071  owl_popwin *pw;
    71   int j, ret, initialsubs, debug, argcsave, followlast;
     72  int ret, initialsubs, debug, argcsave, followlast;
     73  owl_input j;
    7274  int newmsgs, nexttimediff;
    7375  struct sigaction sigact;
     
    8486  int newstderr;
    8587#endif
     88 
     89  if (!GLIB_CHECK_VERSION (2, 12, 0))
     90    g_error ("GLib version 2.12.0 or above is needed.");
    8691
    8792  argcsave=argc;
     
    9297  debug=0;
    9398  initialsubs=1;
     99
     100  setlocale(LC_ALL, "");
     101 
    94102  if (argc>0) {
    95103    argv++;
     
    538546     * little bit, but otherwise do not.  This lets input be grabbed
    539547     * as quickly as possbile */
    540     j=wgetch(typwin);
    541     if (j==ERR) {
     548    j.ch = wgetch(typwin);
     549    if (j.ch == ERR) {
    542550      usleep(10000);
    543551    } else {
     552      j.uch = '\0';
     553      if (j.ch >= KEY_MIN && j.ch <= KEY_MAX) {
     554        /* This is a curses control character. */
     555      }
     556      else if (j.ch > 0x7f && j.ch < 0xfe) {
     557        /* Pull in a full utf-8 character. */
     558        int bytes, i;
     559        char *utf8buf[7];
     560        memset(utf8buf, '\0', 7);
     561
     562        utf8buf[0] = j.ch;
     563
     564        if ((j.ch & 0xc0) && (~j.ch & 0x20)) bytes = 2;
     565        else if ((j.ch & 0xe0) && (~j.ch & 0x10)) bytes = 3;
     566        else if ((j.ch & 0xf0) && (~j.ch & 0x08)) bytes = 4;
     567        else if ((j.ch & 0xf8) && (~j.ch & 0x04)) bytes = 5;
     568        else if ((j.ch & 0xfc) && (~j.ch & 0x02)) bytes = 6;
     569        else bytes = 1;
     570       
     571        for (i = 1; i < bytes; i++) {
     572          utf8buf[i] = wgetch(typwin);
     573        }
     574        if (g_utf8_validate(utf8buf, -1, NULL)) {
     575          j.uch = g_utf8_get_char(utf8buf);
     576        }
     577        else {
     578          j.ch = ERR;
     579        }
     580      }
     581      else if (j.ch <= 0x7f) {
     582        j.uch = j.ch;
     583      }
     584     
    544585      owl_global_update_lastinputtime(&g);
    545586      /* find and activate the current keymap.
  • owl.h

    r18e28a4 r428834d  
    5252#include <termios.h>
    5353#include <libfaim/aim.h>
     54#include <wchar.h>
    5455#include "config.h"
     56#include "glib.h"
    5557#ifdef HAVE_LIBZEPHYR
    5658#include <zephyr/zephyr.h>
     
    98100#define OWL_FMTEXT_ATTR_REVERSE   2
    99101#define OWL_FMTEXT_ATTR_UNDERLINE 4
     102
     103#define OWL_FMTEXT_UC_BASE 0x100000 /* Unicode Plane 16 - Supplementary Private Use Area-B*/
     104#define OWL_FMTEXT_UC_ATTR ( OWL_FMTEXT_UC_BASE | 0x800 )
     105#define OWL_FMTEXT_UC_ATTR_MASK 0x7
     106#define OWL_FMTEXT_UC_COLOR_BASE ( OWL_FMTEXT_UC_BASE | 0x400 )
     107#define OWL_FMTEXT_UC_FGCOLOR OWL_FMTEXT_UC_COLOR_BASE
     108#define OWL_FMTEXT_UC_BGCOLOR ( OWL_FMTEXT_UC_COLOR_BASE | 0x200 )
     109#define OWL_FMTEXT_UC_DEFAULT_COLOR 0x100
     110#define OWL_FMTEXT_UC_FGDEFAULT ( OWL_FMTEXT_UC_FGCOLOR | OWL_FMTEXT_UC_DEFAULT_COLOR )
     111#define OWL_FMTEXT_UC_BGDEFAULT ( OWL_FMTEXT_UC_BGCOLOR | OWL_FMTEXT_UC_DEFAULT_COLOR )
     112#define OWL_FMTEXT_UC_COLOR_MASK 0xFF
     113#define OWL_FMTEXT_UC_ALLCOLOR_MASK ( OWL_FMTEXT_UC_COLOR_MASK | OWL_FMTEXT_UC_DEFAULT_COLOR | 0x200)
     114#define OWL_FMTEXT_UC_STARTBYTE_UTF8 '\xf4'
     115
     116#define OWL_FMTEXT_UTF8_ATTR_NONE "\xf4\x80\xa0\x80"
     117#define OWL_FMTEXT_UTF8_FGDEFAULT "\xf4\x80\x94\x80"
     118#define OWL_FMTEXT_UTF8_BGDEFAULT "\xf4\x80\x96\x80"
     119
     120
     121
    100122
    101123#define OWL_COLOR_BLACK     0
     
    250272} owl_variable;
    251273
     274typedef struct _owl_input {
     275  int ch;
     276  char utf8buf[8];
     277  gunichar uch;
     278} owl_input;
     279
    252280typedef struct _owl_fmtext {
    253281  int textlen;
    254282  int bufflen;
    255283  char *textbuff;
    256   char *fmbuff;
    257   short *fgcolorbuff;
    258   short *bgcolorbuff;
     284  char default_attrs;
     285  short default_fgcolor;
     286  short default_bgcolor;
    259287} owl_fmtext;
    260288
     
    489517  owl_list  bindings;           /* key bindings */
    490518  struct _owl_keymap *submap;   /* submap */
    491   void (*default_fn)(int j);    /* default action (takes a keypress) */
    492   void (*prealways_fn)(int j);  /* always called before a keypress is received */
    493   void (*postalways_fn)(int j); /* always called after keypress is processed */
     519  void (*default_fn)(owl_input j);      /* default action (takes a keypress) */
     520  void (*prealways_fn)(owl_input j);   /* always called before a keypress is received */
     521  void (*postalways_fn)(owl_input j);  /* always called after keypress is processed */
    494522} owl_keymap;
    495523
  • perlconfig.c

    rad15610 r5376a95  
    5555    j=owl_zephyr_get_num_fields(owl_message_get_notice(m));
    5656    for (i=0; i<j; i++) {
    57       ptr=owl_zephyr_get_field(owl_message_get_notice(m), i+1);
     57      ptr=owl_zephyr_get_field_as_utf8(owl_message_get_notice(m), i+1);
    5858      av_push(av_zfields, newSVpvn(ptr, strlen(ptr)));
    5959      owl_free(ptr);
  • text.c

    r72db971 r47519e1b  
    5050void owl_text_truncate_cols(char *out, char *in, int acol, int bcol)
    5151{
    52   char *ptr1, *ptr2, *tmpbuff, *last;
    53   int len;
    54 
     52  char *ptr_s, *ptr_e, *ptr_c, *tmpbuff, *last;
     53  int col, cnt, padding;
     54 
    5555  tmpbuff=owl_malloc(strlen(in)+20);
    5656
    5757  strcpy(tmpbuff, "");
    5858  last=in+strlen(in)-1;
    59   ptr1=in;
    60   while (ptr1<last) {
    61     ptr2=strchr(ptr1, '\n');
    62     if (!ptr2) {
     59  ptr_s=in;
     60  while (ptr_s<last) {
     61    ptr_e=strchr(ptr_s, '\n');
     62    if (!ptr_e) {
    6363      /* but this shouldn't happen if we end in a \n */
    6464      break;
    6565    }
    6666   
    67     if (ptr2==ptr1) {
     67    if (ptr_e==ptr_s) {
    6868      strcat(tmpbuff, "\n");
    69       ptr1++;
    70       continue;
    71     }
    72 
     69      ptr_s++;
     70      continue;
     71    }
     72
     73    col = 0;
     74    cnt = 0;
     75    padding = 0;
     76    ptr_c = ptr_s;
     77    while(col < bcol && ptr_c < ptr_e) {
     78      gunichar c = g_utf8_get_char(ptr_c);
     79      if (col + mk_wcwidth(c) > bcol) break;
     80      col += mk_wcwidth(c);
     81      ptr_c = g_utf8_next_char(ptr_c);
     82      if (col >= acol) {
     83        if (cnt == 0) {
     84          ptr_s = ptr_c;
     85          padding = col - acol;
     86        }
     87        ++cnt;
     88      }
     89    }
     90    if (cnt) {
     91      while(padding-- > 0) {
     92        strcat(tmpbuff, " ");
     93      }
     94      strncat(tmpbuff, ptr_s, ptr_c - ptr_s - 1);
     95    }
     96    strcat(tmpbuff, "\n");
     97    ptr_s = ptr_e + 1;
     98#if 0
    7399    /* we need to check that we won't run over here */
    74     if ( (ptr2-ptr1) < (bcol-acol) ) {
    75       len=ptr2-(ptr1+acol);
     100    if ( (ptr_e-ptr_s) < (bcol-acol) ) {
     101      len=ptr_e-(ptr_s+acol);
    76102    } else {
    77103      len=bcol-acol;
    78104    }
    79     if ((ptr1+len)>=last) {
    80       len-=last-(ptr1+len);
    81     }
    82 
    83     strncat(tmpbuff, ptr1+acol, len);
     105    if ((ptr_s+len)>=last) {
     106      len-=last-(ptr_s+len);
     107    }
     108
     109    strncat(tmpbuff, ptr_s+acol, len);
    84110    strcat(tmpbuff, "\n");
    85111
    86     ptr1=ptr2+1;
     112    ptr_s=ptr_e+1;
     113#endif
    87114  }
    88115  strcpy(out, tmpbuff);
     
    275302char *stristr(char *a, char *b)
    276303{
    277   char *x, *y, *ret;
    278 
    279   if ((x=owl_strdup(a))==NULL) return(NULL);
    280   if ((y=owl_strdup(b))==NULL) return(NULL);
    281   downstr(x);
    282   downstr(y);
    283   ret=strstr(x, y);
    284   if (ret==NULL) {
    285     owl_free(x);
    286     owl_free(y);
    287     return(NULL);
    288   }
    289   ret=ret-x+a;
    290   owl_free(x);
    291   owl_free(y);
     304  char *x, *y;
     305  char *ret = NULL;
     306  if ((x = g_utf8_casefold(a, -1)) != NULL) {
     307    if ((y = g_utf8_casefold(b, -1)) != NULL) {
     308      ret = strstr(x, y);
     309      if (ret != NULL) {
     310        ret = ret - x + a;
     311      }
     312      g_free(y);
     313    }
     314    g_free(x);
     315  }
    292316  return(ret);
    293317}
     
    296320int only_whitespace(char *s)
    297321{
    298   int i;
    299   for (i=0; s[i]; i++) {
    300     if (!isspace((int) s[i])) return(0);
     322  if (g_utf8_validate(s,-1,NULL)) {
     323    char *p;
     324    for(p = s; p[0]; p=g_utf8_next_char(p)) {
     325      if (!g_unichar_isspace(g_utf8_get_char(p))) return 0;
     326    }
     327  }
     328  else {
     329    int i;
     330    for (i=0; s[i]; i++) {
     331      if (!isspace((int) s[i])) return(0);
     332    }
    301333  }
    302334  return(1);
     
    327359  tolen  = strlen(to);
    328360  fromlen  = strlen(from);
    329   out = malloc(outlen);
     361  out = owl_malloc(outlen);
    330362
    331363  while (in[inpos]) {
  • util.c

    r89f5338 r7b1d048  
    399399}
    400400
    401 /* downcase the string 'foo' */
    402 void downstr(char *foo)
    403 {
    404   int i;
    405   for (i=0; foo[i]!='\0'; i++) {
    406     foo[i]=tolower(foo[i]);
    407   }
    408 }
    409 
    410401/* Caller must free response.
    411402 * Takes in strings which are space-separated lists of tokens
     
    446437void *owl_malloc(size_t size)
    447438{
    448   return(malloc(size));
     439  return(g_malloc(size));
    449440}
    450441
    451442void owl_free(void *ptr)
    452443{
    453   free(ptr);
     444  g_free(ptr);
    454445}
    455446
    456447char *owl_strdup(const char *s1)
    457448{
    458   return(strdup(s1));
     449  return(g_strdup(s1));
    459450}
    460451
    461452void *owl_realloc(void *ptr, size_t size)
    462453{
    463   return(realloc(ptr, size));
     454  return(g_realloc(ptr, size));
    464455}
    465456
    466457/* allocates memory and returns the string or null.
    467458 * caller must free the string.
    468  * from Linux sprintf man page.
    469459 */
    470460char *owl_sprintf(const char *fmt, ...)
    471461{
    472   int n, size = 100;
    473   char *p;
    474462  va_list ap;
    475   if ((p = owl_malloc (size)) == NULL) return (NULL);
    476   while (1) {
    477     /* Try to print in the allocated space. */
    478     va_start(ap, fmt);
    479     n = vsnprintf (p, size, fmt, ap);
    480     va_end(ap);
    481     /* If that worked, return the string. */
    482     if (n > -1 && n < size)
    483       return p;
    484     /* Else try again with more space. */
    485     if (n > -1)    /* glibc 2.1 */
    486       size = n+1; /* precisely what is needed */
    487     else           /* glibc 2.0 */
    488       size *= 2;  /* twice the old size */
    489     if ((p = owl_realloc (p, size)) == NULL)
    490       return NULL;
    491   }
    492 }
     463  char *ret = NULL;
     464  va_start(ap, fmt);
     465  ret = g_strdup_vprintf(fmt, ap);
     466  va_end(ap);
     467  return ret;
     468}
     469
    493470
    494471/* Return the owl color associated with the named color.  Return -1
     
    776753}
    777754
    778 char * owl_get_datadir() {
    779     char * datadir = getenv("BARNOWL_DATA_DIR");
    780     if(datadir != NULL)
    781         return strchr(datadir, '=') + 1;
    782     return DATADIR;
     755char * owl_get_datadir()
     756{
     757  char * datadir = getenv("BARNOWL_DATA_DIR");
     758  if(datadir != NULL)
     759    return strchr(datadir, '=') + 1;
     760  return DATADIR;
     761}
     762
     763/* Strips format characters from a valid utf-8 string. Returns the
     764   empty string if 'in' does not validate. */
     765char * owl_strip_format_chars(char *in)
     766{
     767  char *r;
     768  if (g_utf8_validate(in, -1, NULL)) {
     769    char *s, *p;
     770    r = owl_malloc(strlen(in)+1);
     771    r[0] = '\0';
     772    s = in;
     773    p = strchr(s, OWL_FMTEXT_UC_STARTBYTE_UTF8);
     774    while(p) {
     775      /* If it's a format character, copy up to it, and skip all
     776         immediately following format characters. */
     777      if (_owl_fmtext_is_format_char(g_utf8_get_char(p))) {
     778        strncat(r, s, p-s);
     779        p = g_utf8_next_char(p);
     780        while (p && _owl_fmtext_is_format_char(g_utf8_get_char(p))) {
     781          p = g_utf8_next_char(p);
     782        }
     783        s = p;
     784        p = strchr(s, OWL_FMTEXT_UC_STARTBYTE_UTF8);
     785      }
     786      else {
     787        p = strchr(p+1, OWL_FMTEXT_UC_STARTBYTE_UTF8);
     788      }
     789    }
     790    if (s) strcat(r,s);
     791  }
     792  else {
     793    r = owl_strdup("");
     794  }
     795  return r;
     796}
     797
     798/* If in is not UTF-8, convert from ISO-8859-1. We may want to allow
     799 * the caller to specify an alternative in the future. We also strip
     800 * out characters in Unicode Plane 16, as we use that plane internally
     801 * for formatting.
     802 */
     803char * owl_validate_or_convert(char *in)
     804{
     805  if (g_utf8_validate(in, -1, NULL)) {
     806    return owl_strip_format_chars(in);
     807  }
     808  else {
     809    return g_convert(in, -1,
     810                     "UTF-8", "ISO-8859-1",
     811                     NULL, NULL, NULL);
     812  }
     813}
     814/* Attempts to convert 'in' to ISO-8859-1. Returns that if possible,
     815   else returns UTF-8.
     816 */
     817char * owl_get_iso_8859_1_if_possible(char *in)
     818{
     819  char *out;
     820  if (g_utf8_validate(in, -1, NULL)) {
     821    out = g_convert(in, -1,
     822                    "ISO-8859-1", "UTF-8",
     823                    NULL, NULL, NULL);
     824    if (!out) {
     825      out = owl_strdup(in);
     826    }
     827  }
     828  else {
     829    out = owl_strdup("");
     830  }
     831  return out;
    783832}
    784833
  • viewwin.c

    r8721756 r47519e1b  
    7373  owl_fmtext_truncate_cols(&fm1, v->rightshift, v->wincols-1+v->rightshift, &fm2);
    7474
    75   owl_fmtext_curs_waddstr(&fm2, v->curswin);
     75  owl_fmtext_curs_waddstr_without_search(&fm2, v->curswin);
    7676
    7777  /* print the message at the bottom */
  • zcrypt.c

    r9ceee9d r34509d5  
    385385
    386386/* Build a space-separated string from argv from elements between start  *
    387  * and end - 1.  malloc()'s the returned string. */
     387 * and end - 1.  owl_malloc()'s the returned string. */
    388388char *BuildArgString(char **argv, int start, int end) {
    389389  int len = 1;
     
    397397
    398398  /* Allocate memory */
    399   result = (char *)malloc(len);
     399  result = (char *)owl_malloc(len);
    400400  if (result) {
    401401    /* Build the string */
     
    482482      /* Prepare result to be returned */
    483483      char *temp = keyfile;
    484       keyfile = (char *)malloc(strlen(temp) + 1);
     484      keyfile = (char *)owl_malloc(strlen(temp) + 1);
    485485      if (keyfile) {
    486486        strcpy(keyfile, temp);
     
    611611      }
    612612      use_buffer = TRUE;
    613       if ((inptr = inbuff = (char *)malloc(MAX_RESULT)) == NULL) {
     613      if ((inptr = inbuff = (char *)owl_malloc(MAX_RESULT)) == NULL) {
    614614        printf("Memory allocation error\n");
    615615        return FALSE;
     
    639639      printf("Could not run zwrite\n");
    640640      if (freein && inbuff) {
    641         free(inbuff);
     641        owl_free(inbuff);
    642642      }
    643643      return(FALSE);
     
    685685
    686686  /* Free the input buffer, if necessary */
    687   if (freein && inbuff) free(inbuff);
     687  if (freein && inbuff) owl_free(inbuff);
    688688
    689689  return(!error);
  • zwrite.c

    r1fe100c r7b1d048  
    4444        break;
    4545      }
    46       z->class=owl_strdup(myargv[1]);
     46      z->class=owl_get_iso_8859_1_if_possible(myargv[1]);
    4747      myargv+=2;
    4848      myargc-=2;
     
    5252        break;
    5353      }
    54       z->inst=owl_strdup(myargv[1]);
     54      z->inst=owl_get_iso_8859_1_if_possible(myargv[1]);
    5555      myargv+=2;
    5656      myargc-=2;
     
    6060        break;
    6161      }
    62       z->realm=owl_strdup(myargv[1]);
     62      z->realm=owl_get_iso_8859_1_if_possible(myargv[1]);
    6363      myargv+=2;
    6464      myargc-=2;
     
    6868        break;
    6969      }
    70       z->zsig=owl_strdup(myargv[1]);
     70      z->zsig=owl_get_iso_8859_1_if_possible(myargv[1]);
    7171      myargv+=2;
    7272      myargc-=2;
     
    7676        break;
    7777      }
    78       z->opcode=owl_strdup(myargv[1]);
     78      z->opcode=owl_get_iso_8859_1_if_possible(myargv[1]);
    7979      myargv+=2;
    8080      myargc-=2;
     
    9393      myargv++;
    9494      myargc--;
    95       z->message=owl_strdup("");
     95      z->message=owl_get_iso_8859_1_if_possible("");
    9696      while (myargc) {
    97         z->message=realloc(z->message, strlen(z->message)+strlen(myargv[0])+5);
     97        z->message=owl_realloc(z->message, strlen(z->message)+strlen(myargv[0])+5);
    9898        strcat(z->message, myargv[0]);
    9999        strcat(z->message, " ");
     
    113113    } else {
    114114      /* anything unattached is a recipient */
    115       owl_list_append_element(&(z->recips), strdup(myargv[0]));
     115      owl_list_append_element(&(z->recips), owl_get_iso_8859_1_if_possible(myargv[0]));
    116116      myargv++;
    117117      myargc--;
     
    146146
    147147    if (zsigowlvar && *zsigowlvar) {
    148       z->zsig=owl_strdup(zsigowlvar);
     148      z->zsig=owl_get_iso_8859_1_if_possible(zsigowlvar);
    149149    } else if (zsigproc && *zsigproc) {
    150150      FILE *file;
     
    161161      if (!file) {
    162162        if (zsigzvar && *zsigzvar) {
    163           z->zsig=owl_strdup(zsigzvar);
     163          z->zsig=owl_get_iso_8859_1_if_possible(zsigzvar);
    164164        }
    165165      } else {
     
    175175      }
    176176    } else if (zsigzvar) {
    177       z->zsig=owl_strdup(zsigzvar);
     177      z->zsig=owl_get_iso_8859_1_if_possible(zsigzvar);
    178178    } else if (((pw=getpwuid(getuid()))!=NULL) && (pw->pw_gecos)) {
    179       z->zsig=strdup(pw->pw_gecos);
     179      z->zsig=owl_get_iso_8859_1_if_possible(pw->pw_gecos);
    180180      ptr=strchr(z->zsig, ',');
    181181      if (ptr) {
     
    218218  int i, j;
    219219  char toline[LINE];
     220  char *tmp = NULL;
    220221
    221222  if (z->message) owl_free(z->message);
     
    231232      }
    232233    }
    233     z->message=owl_sprintf("%s\n%s", toline, msg);
     234    tmp = owl_get_iso_8859_1_if_possible(msg);
     235    z->message=owl_sprintf("%s\n%s", toline, tmp);
    234236  } else {
    235     z->message=owl_strdup(msg);
    236   }
     237    z->message=owl_get_iso_8859_1_if_possible(msg);
     238  }
     239  if (tmp) owl_free(tmp);
    237240}
    238241
     
    305308{
    306309  if (z->opcode) owl_free(z->opcode);
    307   z->opcode=owl_strdup(opcode);
     310  z->opcode=owl_get_iso_8859_1_if_possible(opcode);
    308311}
    309312
Note: See TracChangeset for help on using the changeset viewer.