#! perl =head1 NAME xim-onthespot - implement XIM "on-the-spot" behaviour =head1 DESCRIPTION This perl extension implements OnTheSpot editing. It does not work perfectly, and some input methods don't seem to work well with OnTheSpot editing in general, but it seems to work at least for SCIM and kinput2. You enable it by specifying this extension and a preedit style of C, i.e.: urxvt -pt OnTheSpot -pe xim-onthespot =cut # # problems with this implementation include # # - primary, secondary, tertiary are NO different to other highlighting styles # - if rend values are missing, they are not being interpolated # my $SIZEOF_LONG = length pack "l!", 0; sub refresh { my ($self) = @_; delete $self->{overlay}; my $text = $self->{text}; return unless length $text; my ($row, $col) = $self->screen_cur; my $idx = 0; my @rend = map { my $rstyle = $self->{caret} == $idx ? urxvt::OVERLAY_RSTYLE : $self->rstyle; $rstyle |= urxvt::RS_Uline if $_ & (urxvt::XIMUnderline | urxvt::XIMPrimary); $rstyle |= urxvt::RS_RVid if $_ & (urxvt::XIMReverse | urxvt::XIMSecondary); $rstyle |= urxvt::RS_Italic if $_ & (urxvt::XIMHighlight | urxvt::XIMTertiary); ($rstyle) x ($self->strwidth (substr $text, $idx++, 1)) } unpack "l!*", $self->{rend}; if ($self->{caret} >= length $text) { $text .= " "; push @rend, urxvt::OVERLAY_RSTYLE; } $self->{overlay} = $self->overlay ($col, $row, $self->strwidth ($text), 1, $self->rstyle, 0); $self->{overlay}->set (0, 0, $self->special_encode ($text), \@rend); } sub on_xim_preedit_start { my ($self) = @_; () } sub on_xim_preedit_done { my ($self) = @_; delete $self->{overlay}; delete $self->{text}; delete $self->{rend}; () } sub on_xim_preedit_draw { my ($self, $caret, $pos, $len, $feedback, $chars) = @_; $self->{caret} = $caret; substr $self->{rend}, $pos * $SIZEOF_LONG, $len * $SIZEOF_LONG, $feedback; substr $self->{text}, $pos , $len , $chars if defined $feedback || !defined $chars; $self->refresh; () }