summaryrefslogtreecommitdiffstats
path: root/src/perl/xim-onthespot
diff options
context:
space:
mode:
Diffstat (limited to 'src/perl/xim-onthespot')
-rw-r--r--src/perl/xim-onthespot90
1 files changed, 90 insertions, 0 deletions
diff --git a/src/perl/xim-onthespot b/src/perl/xim-onthespot
new file mode 100644
index 0000000..b5acee2
--- /dev/null
+++ b/src/perl/xim-onthespot
@@ -0,0 +1,90 @@
+#! 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<OnTheSpot>, 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;
+
+ ()
+}
+
+