# sit on unmatched partial esc[30m etc # Copyright 2007, 2008, 2009, 2010 Kevin Ryde # This file is part of Chart. # # Chart is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License as published by the Free Software # Foundation; either version 3, or (at your option) any later version. # # Chart is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along # with Chart. If not, see . package App::Chart::Pango::Ex::ANSItoMarkup; use 5.008; use strict; use warnings; my %shorthand = (' 'b', ' 'i', ' 's', ' 'u'); my @colour = ('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white'); use constant { _A_FOREGROUND => 0, _A_BACKGROUND => 1, _A_STRIKETHROUGH => 2, _A_STYLE => 3, _A_UNDERLINE => 4, _A_WEIGHT => 5, _A_RISE => 6, }; sub new { my ($class) = @_; return bless { attr => [], }, $class; } sub convert { my ($class_or_self, $str) = @_; my $self = (ref $class_or_self ? $class_or_self : $class_or_self->new); my $attr = $self->{'attr'}; if (defined (my $prev = delete $self->{'previous'})) { $str = $prev . $str; } defined (my $pos = index ($str, "\e")) or return $str; pos($str) = $pos; my $ret = substr ($str, 0, $pos); while ($str =~ /\G ( # $1 whole esc+text (?:\e( # $2 after esc \[([0-9;]*) # $3 SGR numbers m | [KL])?)? ([^\e]*)) # $4 plain text after /gx) { my $part = $4; if (defined $3) { foreach my $num (split /;/, $3) { if ($num == 0) { @$attr = (); } elsif ($num == 1) { # bold $attr->[_A_WEIGHT] = 'weight=bold'; } elsif ($num == 2) { # faint, or dark, or something $attr->[_A_WEIGHT] = 'weight=light'; } elsif ($num == 3) { # italic $attr->[_A_STYLE] = 'style=italic'; } elsif ($num == 4) { # single underline $attr->[_A_UNDERLINE] = 'underline=single'; # 5 slow blink # 6 fast blink # nothing for these in pango # 7 "negative image", reverse video # would kinda need to know what the normal colours are # 8 concealed # does this mean invisible? } elsif ($num == 9) { $attr->[_A_STRIKETHROUGH] = 'strikethrough=true'; # 10 primary font # 11 first alternative font # ... # 19 ninth alternative font # 20 fraktur gothic } elsif ($num == 21) { # double underline $attr->[_A_UNDERLINE] = 'underline=double'; } elsif ($num == 22) { # normal colour/intensity, ie. neither bold nor faint $attr->[_A_WEIGHT] = undef; } elsif ($num == 23) { # not italic $attr->[_A_STYLE] = undef; } elsif ($num == 24) { # not underlined $attr->[_A_UNDERLINE] = undef; # 25 not blinking # nothing for blinking in pango # 26 reserved (for proportional spacing) # 27 positive image, ie. not reverse video # 28 revealled chars, ie. not concealed } elsif ($num == 29) { # not strikethrough $attr->[_A_STRIKETHROUGH] = undef; } elsif ($num >= 30 && $num <= 37) { $attr->[_A_FOREGROUND] = 'foreground=' . $colour[$num-30]; # 38 reserved (for foreground colour) } elsif ($num == 39) { # default foreground colour $attr->[_A_FOREGROUND] = undef; } elsif ($num >= 40 && $num <= 47) { $attr->[_A_BACKGROUND] = 'background=' . $colour[$num-40]; # 48 reserved (for background colour) } elsif ($num == 49) { # default background colour $attr->[_A_BACKGROUND] = undef; # 50 reserved (for cancelling 26 proportional spacing) # 51 framed # 52 encircled # 53 overlined # no overline in pango markup # 54 not framed or encircled # 55 not overlined # 56-59 reserved # 60 ideogram underline right side line # 61 ideogram double underline right side line # 62 ideogram overline left side line # 63 ideogram double overline left side # 64 ideogram stress # 65 ideogram normal, ie. undo 60-64 } } } elsif (defined $2) { # sub/sup rise 5000, meaning 0.5 em, same as pango-markup.c does for # , shorthands if ($2 eq 'K') { # PLD partial line down subscript or cancel superscript $self->{'rise'} -= 5000; } elsif ($2 eq 'L') { # PLU partial line up superscript or cancel subscript $self->{'rise'} += 5000; } $attr->[_A_RISE] = (($self->{'rise'}||0) == 0 ? undef : "rise=".$self->{'rise'}); } else { $part = $1; } my $span = join (' ', 'convert("\eKsub\eLn\eZorm\e[1mxyz\e[0mabc\e[30mxyz\e[0m"); 1; __END__