diff --git a/src/modules/punk/ansi-999999.0a1.0.tm b/src/modules/punk/ansi-999999.0a1.0.tm index 8ac1fa61..bf56e8ce 100644 --- a/src/modules/punk/ansi-999999.0a1.0.tm +++ b/src/modules/punk/ansi-999999.0a1.0.tm @@ -221,7 +221,7 @@ namespace eval punk::ansi { #(This is a potential conflict because we use nul as a filler to mean empty column in overtype rendering) REVIEW dict set cp437_map \u0000 " " ;#space dict set cp437_map \u0001 \u263A ;#smiley - dict set cp437_map \u0003 \u263B ;#smiley-filled + dict set cp437_map \u0002 \u263B ;#smiley-filled dict set cp437_map \u0003 \u2665 ;#heart dict set cp437_map \u0004 \u2666 ;#diamond dict set cp437_map \u0005 \u2663 ;#club @@ -252,6 +252,41 @@ namespace eval punk::ansi { dict set cp437_map \u001E \u25B2 ;#up arrow triangle dict set cp437_map \u001F \u25BC ;#down arrow triangle + variable map_special_graphics + #DEC Special Graphics set https://en.wikipedia.org/wiki/DEC_Special_Graphics + #AKA IBM Code page 1090 + dict set map_special_graphics _ \u00a0 ;#no-break space + dict set map_special_graphics "`" \u25c6 ;#black diamond + dict set map_special_graphics a \u2592 ;#shaded block (checkerboard stipple), medium shade - Block Elements + dict set map_special_graphics b \u2409 ;#symbol for HT + dict set map_special_graphics c \u240c ;#symbol for FF + dict set map_special_graphics d \u240d ;#symbol for CR + dict set map_special_graphics e \u240a ;#symbol for LF + dict set map_special_graphics f \u00b0 ;#degree sign + dict set map_special_graphics g \u00b1 ;#plus-minus sign + dict set map_special_graphics h \u2424 ;#symbol for NL + dict set map_special_graphics i \u240b ;#symbol for VT + dict set map_special_graphics j \u2518 ;#brc, light up and left - box drawing + dict set map_special_graphics k \u2510 ;#trc, light down and left - box drawing + dict set map_special_graphics l \u250c ;#tlc, light down and right - box drawing + dict set map_special_graphics m \u2514 ;#blc, light up and right - box drawing + dict set map_special_graphics n \u253c ;#light vertical and horizontal - box drawing + dict set map_special_graphics o \u23ba ;#horizontal scan line-1 + dict set map_special_graphics p \u23bb ;#horizontal scan line-3 + dict set map_special_graphics q \u2500 ;#light horizontal - box drawing + dict set map_special_graphics r \u23bc ;#horizontal scan line-7 + dict set map_special_graphics s \u23bd ;#horizontal scan line-9 + dict set map_special_graphics t \u251c ;#light vertical and right - box drawing + dict set map_special_graphics u \u2524 ;#light vertical and left - box drawing + dict set map_special_graphics v \u2534 ;#light up and horizontal - box drawing + dict set map_special_graphics w \u252c ;#light down and horizontal - box drawing + dict set map_special_graphics x \u2502 ;#light vertical - box drawing + dict set map_special_graphics y \u2264 ;#less than or equal + dict set map_special_graphics z \u2265 ;#greater than or equal + dict set map_special_graphics "\{" \u03c0 ;#greek small letter pi + dict set map_special_graphics "|" \u2260 ;#not equal to + dict set map_special_graphics "\}" \u00a3 ;#pound sign + dict set map_special_graphics ~ \u00b7 ;#middle dot #see also ansicolor page on wiki https://wiki.tcl-lang.org/page/ANSI+color+control @@ -577,17 +612,17 @@ namespace eval punk::ansi { } #review - what happens when no terminator? - #todo - map other chars to unicode equivs + #todo - map other character sets to unicode equivs? There seems to be little support for other than the DEC special graphics set.. ISO2022 character switching not widely supported - may be best considered deprecated(?) # convert esc(0 -> esc(B graphics sequences to single char unicode equivalents e.g box drawing set # esc) ?? proc convert_g0 {text} { + variable map_special_graphics + #using not \033 inside to stop greediness - review how does it compare to ".*?" #variable re_altg0_group {(?:\x1b\(0)(?:(?!\x1b\(B).)*\x1b\(B} #set re {\033\(0[^\033]*\033\(B} #set re {(?:\x1b\(0)(?:(?!\x1b\(B).)*\x1b\(B} - - - set re2 {\033\(0(.*)\033\(B} ;#capturing + #set re2 {\033\(0(.*)\033\(B} ;#capturing #puts --$g-- #box sample @@ -595,29 +630,29 @@ namespace eval punk::ansi { #x x #mqj #m = boxd_lur - #set map [list l \u250f k \u2513] ;#heavy - set map [list l \u250c q \u2500 k \u2510 x \u2502 m \u2514 j \u2518] ;#light box drawing lines - #todo - map the rest https://vt100.net/docs/vt220-rm/chapter2.html + set re_g0_open_or_close {\x1b\(0|\x1b\(B} set parts [::punk::ansi::ta::_perlish_split $re_g0_open_or_close $text] set out "" set g0_on 0 - foreach {pt g} $parts { + foreach {other g} $parts { if {$g0_on} { #split for non graphics-set codes - set othersplits [punk::ansi::ta::split_codes $pt] ;#we don't need single codes here - foreach {innerpt innercodes} $othersplits { - append out [string map $map $innerpt] - append out $innercodes ;#Simplifying assumption - ST codes, titlesets etc don't require/use g0 content + set othersplits [punk::ansi::ta::split_codes $other] ;#we don't need single codes here + foreach {inner_plaintext inner_codes} $othersplits { + append out [string map $map_special_graphics $inner_plaintext] $inner_codes + #Simplifying assumption: no mapping required on any inner_codes - ST codes, titlesets etc don't require/use g0 content } } else { - append out $pt ;#may include other codes - put it all through. + append out $other ;#may be a mix of plaintext and other ansi codes - put it all through. } - if {$g ne ""} { - if {[punk::ansi::codetype::is_gx_open $g]} { + #trust our splitting regex has done the work to leave us with only \x1b\(0 or \x1b(B - test last char rather than use punk::ansi::codetype::is_gx_open/is_gx_close + switch -- [string index $g end] { + 0 { set g0_on 1 - } elseif {[punk::ansi::codetype::is_gx_close $g]} { + } + B { set g0_on 0 } } @@ -653,6 +688,8 @@ namespace eval punk::ansi { } return $out } + + #Wrap text in ansi codes to switch to DEC alternate graphics character set. proc g0 {text} { return \x1b(0$text\x1b(B } diff --git a/src/modules/punk/console-999999.0a1.0.tm b/src/modules/punk/console-999999.0a1.0.tm index 32c630a5..91d5dcb5 100644 --- a/src/modules/punk/console-999999.0a1.0.tm +++ b/src/modules/punk/console-999999.0a1.0.tm @@ -1580,7 +1580,7 @@ namespace eval punk::console { set cix 0 foreach c [split $charline {}] { if {$c} { - append output [punk::ansi::move_emit [expr {$row + $line}] [expr {$col + $charno * 8 + $cix}] "[a reverse] [a noreverse]"] + append output [punk::ansi::move_emit [expr {$row + $line}] [expr {$col + $charno * 8 + $cix}] "[a+ reverse] [a+ noreverse]"] #curses attr on reverse #curses move [expr $row + $line] [expr $col + $charno * 8 + $cix] #curses puts " " @@ -1592,6 +1592,11 @@ namespace eval punk::console { } return $output } + proc get_time {} { + overtype::left -width 70 "" [bigstr [clock format [clock seconds] -format %H:%M:%S] 1 1] + } + + proc display1 {} { #punk::console::clear punk::console::move_call_return 20 20 {punk::console::clear_above} diff --git a/src/vendormodules/overtype-1.6.0.tm b/src/vendormodules/overtype-1.6.0.tm index 4e7844bf..385ec10a 100644 --- a/src/vendormodules/overtype-1.6.0.tm +++ b/src/vendormodules/overtype-1.6.0.tm @@ -1279,6 +1279,8 @@ proc overtype::grapheme_width_cached {ch} { # ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### +# renderline written from a left-right line orientation perspective as a first-shot at getting something useful. +# ultimately right-to-left, top-to-bottom and bottom-to-top are probably needed. # ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### # # @@ -1802,7 +1804,7 @@ proc overtype::renderline {args} { #\x85 NEL in the c1 control set is treated by some terminal emulators (e.g Hyper) as a newline, #on some it's invisble but doesn't change the line, on some it's a visible glyph of width 1. #This is hard to process in any standard manner - but I think the Hyper behaviour of doing what it was intended is perhaps most reasonable - #We will map it to the same behaviour as lf here. + #We will map it to the same behaviour as lf here for now... but we need also to consider the equivalent ANSI sequence: \x1bE set chtest [string map [list \n \x85 \b \r \v \x7f ] $ch] #puts --->chtest:$chtest @@ -1811,10 +1813,9 @@ proc overtype::renderline {args} { "" { set replay_codes_overlay [punk::ansi::codetype::sgr_merge_list {*}[lindex $overlay_grapheme_control_stacks $gci]] if {$idx == 0} { - puts "---b at column 1" #leave the overflow_idx - set instruction lf_start ;#specific instruction for newline at column 1 #idx_over already incremented + set instruction lf_start ;#specific instruction for newline at column 1 priv::render_unapplied $overlay_grapheme_control_list $gci break } elseif {$overflow_idx != -1 && $idx == $overflow_idx} { @@ -2134,6 +2135,7 @@ proc overtype::renderline {args} { set re_cursor_restore {\x1b\[u$} set re_cursor_save_dec {\x1b7$} set re_cursor_restore_dec {\x1b8$} + set re_other_single {\x1b(D|M|E)$} set re_decstbm {\x1b\[([0-9]*)(?:;){0,1}([0-9]*)r$} ;#DECSTBM set top and bottom margins set matchinfo [list] @@ -2301,7 +2303,6 @@ proc overtype::renderline {args} { } B { set replay_codes_overlay [punk::ansi::codetype::sgr_merge_list {*}[lindex $overlay_grapheme_control_stacks $gci]] - set row_before_move $cursor_row #move down if {$num eq ""} {set num 1} incr cursor_row $num @@ -2376,7 +2377,7 @@ proc overtype::renderline {args} { #rather than set the cursor - we return the insert mode state so the caller can decide } } elseif {$key eq "3"} { - #Delete + #Delete - presumably this shifts other chars in the line, with empty cells coming in from the end switch -- $mod { "" { priv::render_delchar $idx @@ -2533,6 +2534,44 @@ proc overtype::renderline {args} { set instruction restore_cursor break }\ + $re_other_single { + lassign $matchinfo _match type + switch -- $type { + D { + #index (IND) + #vt102-docs: "Moves cursor down one line in same column. If cursor is at bottom margin, screen performs a scroll-up" + puts stderr "ESC D not fully implemented" + incr cursor_row + priv::render_unapplied $overlay_grapheme_control_list $gci + set instruction down + #retain cursor_column + break + } + M { + #Reverse Index (RI) + #vt102-docs: "Moves cursor up one line in same column. If cursor is at top margin, screen performs a scroll-down" + puts stderr "ESC M not fully implemented" + + set replay_codes_overlay [punk::ansi::codetype::sgr_merge_list {*}[lindex $overlay_grapheme_control_stacks $gci]] + #move up + incr cursor_row -1 + if {$cursor_row < 1} { + set cursor_row 1 + } + #ensure rest of *overlay* is emitted to remainder + priv::render_unapplied $overlay_grapheme_control_list $gci + set instruction up ;#need instruction for scroll-down? + #retain cursor_column + break + } + E { + #review - is behaviour different to 8bit c1 NEL \x85? lf? + #Next Line (NEL) + puts stderr "ESC E" + + } + } + }\ $re_mode { lassign $matchinfo _match num type switch -- $num { @@ -2584,7 +2623,7 @@ proc overtype::renderline {args} { } }\ default { - #puts stderr "overtype::renderline code [ansistring VIEW -lf 1 -vt 1 -nul 1 $code] not implemented" + puts stderr "overtype::renderline code [ansistring VIEW -lf 1 -vt 1 -nul 1 $code] not implemented" } }