head 1.29; access; symbols AS_CUI_0_5_0:1.28 AS_AFTER_RESTRUCTURING:1.4; locks; strict; comment @# @; 1.29 date 2002.12.18.11.18.20; author rse; state dead; branches; next 1.28; 1.28 date 2002.12.17.13.47.50; author thl; state Exp; branches; next 1.27; 1.27 date 2002.12.17.13.39.18; author thl; state Exp; branches; next 1.26; 1.26 date 2002.12.17.10.50.00; author thl; state Exp; branches; next 1.25; 1.25 date 2002.12.11.14.02.08; author thl; state Exp; branches; next 1.24; 1.24 date 2002.12.11.13.31.50; author thl; state Exp; branches; next 1.23; 1.23 date 2002.12.11.11.12.30; author thl; state Exp; branches; next 1.22; 1.22 date 2002.12.11.10.21.43; author thl; state Exp; branches; next 1.21; 1.21 date 2002.12.10.15.09.55; author thl; state Exp; branches; next 1.20; 1.20 date 2002.12.10.14.17.31; author thl; state Exp; branches; next 1.19; 1.19 date 2002.12.10.13.37.43; author thl; state Exp; branches; next 1.18; 1.18 date 2002.12.10.10.26.36; author thl; state Exp; branches; next 1.17; 1.17 date 2002.12.05.15.00.05; author thl; state Exp; branches; next 1.16; 1.16 date 2002.12.05.14.45.59; author thl; state Exp; branches; next 1.15; 1.15 date 2002.12.05.14.04.57; author thl; state Exp; branches; next 1.14; 1.14 date 2002.12.04.14.59.08; author thl; state Exp; branches; next 1.13; 1.13 date 2002.12.04.13.42.02; author thl; state Exp; branches; next 1.12; 1.12 date 2002.12.04.09.56.42; author thl; state Exp; branches; next 1.11; 1.11 date 2002.12.03.19.21.11; author thl; state Exp; branches; next 1.10; 1.10 date 2002.12.03.12.09.19; author thl; state Exp; branches; next 1.9; 1.9 date 2002.12.03.10.33.50; author thl; state Exp; branches; next 1.8; 1.8 date 2002.12.03.09.41.16; author thl; state Exp; branches; next 1.7; 1.7 date 2002.12.03.08.30.20; author thl; state Exp; branches; next 1.6; 1.6 date 2002.12.02.13.58.33; author thl; state Exp; branches; next 1.5; 1.5 date 2002.12.02.13.46.27; author thl; state Exp; branches; next 1.4; 1.4 date 2002.11.27.15.53.11; author thl; state Exp; branches; next 1.3; 1.3 date 2002.11.27.14.34.04; author thl; state Exp; branches; next 1.2; 1.2 date 2002.11.27.13.02.41; author thl; state Exp; branches; next 1.1; 1.1 date 2002.11.26.15.44.21; author thl; state Exp; branches; next ; desc @@ 1.29 log @polish for initial release @ text @## ## Spreadsheet ## package matrix; #this is a direct descendant from basic research at /u/thl/research/SAVE-cuiA.pl use strict; use Curses; #OpenPKG perl-curses use Curses::UI; #OpenPKG perl-curses my $matrixdata = {}; my $verbose = 0; my $breakout = 0; #flag to break out from inner loop my $vcscroll = 0; #callback tells inner loop to scroll wholly view n steps horizontally (neg = left, pos = right) my $vrscroll = 0; #callback tells inner loop to scroll wholly view n steps vertically (neg = up, pos = down) my $datacoll = 0; #callback tells inner loop to redraw wholly view while trying to reuse widgets if size permits my $vcpos = 0; #callback tells inner loop to scroll wholly view horizontally (neg = left, pos = right) my $vrpos = 0; #callback tells inner loop to scroll wholly view vertically (neg = up, pos = down) my $editcell = 0; my $widget = {}; my $matrixwidget = {}; my $matrixwidgetvisualcell = {}; my $matrixwidgetdatacell = {}; my $cui = undef; my @@keys_move = ( #FIXME now we catch all chars not only keys_move. So this remains for documenation only. "h", KEY_LEFT(), "j", KEY_DOWN(), "k", KEY_UP(), "l", KEY_RIGHT(), KEY_NPAGE(), KEY_PPAGE(), KEY_HOME(), KEY_END(), KEY_ENTER(), #same as F2 KEY_F(1), #help KEY_F(2), #edit "o", KEY_F(3), #on a new line "O", KEY_F(4), #On a new line "d", KEY_F(5), #delete line #KEY_F(6), #copy line KEY_F(7), #column show/hide KEY_F(8), #column sorting KEY_F(9), #column shrink to min KEY_F(10), #column shrink KEY_F(11), #column grow KEY_F(12), #column grow to max "1", #scroll screen up to the top and place cursor on the first line "G", #scroll screen down to the bottom and place cursor on the last line "\cU", #scroll screen up, cursor stays at current position KEY_DC(), #scroll screen down, cursor stays at current position "^", #scroll screen left to the border and place cursor on the first cell "\$", #scroll screen right to the border and place cursor on the last cell "y", #yank "p", #paste "P" #Paste ); sub rightmostvisiblefit { my $c; my $lastc; my $wremain; my $realw; my $visualc; # find leftmost column for the rightmost visible fit $visualc = 0; $lastc = $matrixdata->{"Columns"} - 1; $wremain = $matrixwidget->{"Width"}; #printf STDERR "rightmostvisiblefit lastc=%d\n", (defined $lastc) ? $lastc : "undef"; #printf STDERR "rightmostvisiblefit wremain=%d\n", (defined $wremain) ? $wremain : "undef"; for ($c = -1; $c >= -1; $c = $c == -1 ? $lastc: --$c) { if (not $matrixdata->{"CH.$c"}->{"Colhide"}) { my $w = $matrixdata->{"CH.$c"}->{"Width"}; $realw = $w + $matrixdata->{"CH.$c"}->{"Colgap"}; $wremain -= $realw; $visualc++ if ($c >= 0 and $wremain >= 0); } last if ($wremain < 0); } $c++; #printf STDERR "rightmostvisiblefit c=%d, visualc=%d\n", $c, $visualc; return ($c, $visualc); } sub bottommostvisiblefit { my $r; my $lastr; my $hremain; my $realh; my $visualr; # find topmost column for the bottommost visible fit $visualr = 0; $lastr = $matrixdata->{"Rows"} - 1; $hremain = $matrixwidget->{"Height"}; #printf STDERR "bottommostvisiblefit lastr=%d\n", (defined $lastr) ? $lastr : "undef"; #printf STDERR "bottommostvisiblefit hremain=%d\n", (defined $hremain) ? $hremain : "undef"; for ($r = -1; $r >= -1; $r = $r == -1 ? $lastr: --$r) { if (not $matrixdata->{"RH.$r"}->{"Rowhide"}) { my $h = $matrixdata->{"RH.$r"}->{"Height"}; $realh = $h + $matrixdata->{"RH.$r"}->{"Rowgap"}; $hremain -= $realh; $visualr++ if ($r >= 0 and $hremain >= 0); } last if ($hremain < 0); } $r++; #printf STDERR "bottommostvisiblefit r=%d, visualr=%d\n", $r, $visualr; return ($r, $visualr); } sub optimalcolwidth { my $x; my $c; my $cols; my $lastc; my $visualc; # column heading, sizing, counting and cachetag creation $cols = $matrixdata->{"Columns"}; $x = $matrixwidget->{"XOffset"}; $visualc = 0; my $wremain = $matrixwidget->{"Width"}; my $wweight = 0; for ($c = -1; $c < $cols; $c = $c >= 0 ? ++$c : $matrixwidget->{"FirstVisualCol"}) { next if ($matrixdata->{"CH.$c"}->{"Colhide"}); my $w = $matrixdata->{"CH.$c"}->{"Width"}; my $realw = $w + $matrixdata->{"CH.$c"}->{"Colgap"}; last if ($wremain < $realw); if ($c >= 0) { $visualc++; } $x += $realw; $wremain -= $realw; if ($matrixdata->{"CH.$c"}->{"Widthmin"} == $matrixdata->{"CH.$c"}->{"Widthmax"}) { $matrixdata->{"CH.$c"}->{"Widthweight"} = 0; } $matrixdata->{"CH.$c"}->{"Widthweight"} = 1 unless (defined $matrixdata->{"CH.$c"}->{"Widthweight"}); $wweight += $matrixdata->{"CH.$c"}->{"Widthweight"} } $wweight = 1 if ($wweight == 0); #if no weight was given at all, treat all equal and avoid div by zero $lastc = $c; if ($wremain >= 1) { my $wfraction = $wremain / $wweight; my $wfractrem = 0; $x = $matrixwidget->{"XOffset"}; my $wremain = $matrixwidget->{"Width"}; my $wweight = 0; for ($c = -1; $c < $cols; $c = $c >= 0 ? ++$c : $matrixwidget->{"FirstVisualCol"}) { next if ($matrixdata->{"CH.$c"}->{"Colhide"}); my $w = $matrixdata->{"CH.$c"}->{"Width"}; my $fadditional = $matrixdata->{"CH.$c"}->{"Widthweight"} * $wfraction + $wfractrem; my $iadditional = int($fadditional); $wfractrem = $fadditional - $iadditional; $w += $iadditional; my $realw = $w + $matrixdata->{"CH.$c"}->{"Colgap"}; $matrixdata->{"CH.$c"}->{"Width"} = $w; last if ($wremain < $realw); if ($c >= 0) { $visualc++; } $x += $realw; $wremain -= $realw; } } $matrixwidget->{"NumVisualCol"} = $visualc; return; } sub optimalrowheight { my $y; my $r; my $rows; my $lastr; my $visualr; # row heading, sizing, counting and cachetag creation $rows = $matrixdata->{"Rows"}; $y = $matrixwidget->{"YOffset"}; $visualr = 0; my $hremain = $matrixwidget->{"Height"}; my $hweight = 0; for ($r = -1; $r < $rows; $r = $r >= 0 ? ++$r : $matrixwidget->{"FirstVisualRow"}) { next if ($matrixdata->{"RH.$r"}->{"Rowhide"}); my $h = $matrixdata->{"RH.$r"}->{"Height"}; my $realh = $h + $matrixdata->{"RH.$r"}->{"Rowgap"}; last if ($hremain < $realh); if ($r >= 0) { $visualr++; } $y += $realh; $hremain -= $realh; if ($matrixdata->{"RH.$r"}->{"Heightmin"} == $matrixdata->{"RH.$r"}->{"Heightmax"}) { $matrixdata->{"RH.$r"}->{"Heightweight"} = 0; } $matrixdata->{"RH.$r"}->{"Heightweight"} = 1 unless (defined $matrixdata->{"RH.$r"}->{"Heightweight"}); $hweight += $matrixdata->{"RH.$r"}->{"Heightweight"} } $hweight = 1 if ($hweight == 0); #if no weight was given at all, treat all equal and avoid div by zero $lastr = $r; if ($hremain >= 1) { my $hfraction = $hremain / $hweight; my $hfractrem = 0; $y = $matrixwidget->{"YOffset"}; my $hremain = $matrixwidget->{"Height"}; my $hweight = 0; for ($r = -1; $r < $rows; $r = $r >= 0 ? ++$r : $matrixwidget->{"FirstVisualRow"}) { next if ($matrixdata->{"RH.$r"}->{"Rowhide"}); my $h = $matrixdata->{"RH.$r"}->{"Height"}; my $fadditional = $matrixdata->{"RH.$r"}->{"Heightweight"} * $hfraction + $hfractrem; my $iadditional = int($fadditional); $hfractrem = $fadditional - $iadditional; $h += $iadditional; my $realh = $h + $matrixdata->{"RH.$r"}->{"Rowgap"}; $matrixdata->{"RH.$r"}->{"Height"} = $h; last if ($hremain < $realh); if ($r >= 0) { $visualr++; } $y += $realh; $hremain -= $realh; } } $matrixwidget->{"NumVisualRow"} = $visualr; return; } sub colheading { my ($doit) = @@_; my $x; my $y; my $c; my $cols; my $dataxoffset; my $lastc; my $visualc; my $colcachetag; # column heading, sizing, counting and cachetag creation $cols = $matrixdata->{"Columns"}; $dataxoffset = 0; $x = $matrixwidget->{"XOffset"}; $y = $matrixwidget->{"YOffset"}; $colcachetag = ''; $visualc = 0; my $wremain = $matrixwidget->{"Width"}; for ($c = -1; $c < $cols; $c = $c >= 0 ? ++$c : $matrixwidget->{"FirstVisualCol"}) { next if ($matrixdata->{"CH.$c"}->{"Colhide"}); my $w = $matrixdata->{"CH.$c"}->{"Width"}; my $realw = $w + $matrixdata->{"CH.$c"}->{"Colgap"}; my $realh = $matrixdata->{"RH.-1"}->{"Heigth"}; last if ($wremain < $realw); if ($c >= 0) { $dataxoffset = $x if ($dataxoffset == 0); $matrixwidget->{"CH.$visualc"} = $widget->{'container'}->add("CH.$visualc", 'Label', -x => $x, -y => $y, -text => $matrixdata->{"CH.$c"}->{"Labelhide"} ? " " : $matrixdata->{"CH.$c"}->{"Label"}, -width => $realw, -height => $realh ) if ($doit); $visualc++; $colcachetag .= ".$realw"; } $x += $realw; $wremain -= $realw; } $lastc = $c; if ($wremain >= 1) { $matrixwidget->{"CH.fillright"} = $widget->{'container'}->add("CH.fillright", 'Label', -x => $x, -y => $y, -text => '#'x$wremain, -width => $wremain, -heigth => 1 ) if ($doit); } return ($dataxoffset, $lastc, $colcachetag); } sub rowheading { my ($doit) = @@_; my $x; my $y; my $r; my $rows; my $datayoffset; my $lastr; my $visualr; my $rowcachetag; # row heading, sizing, counting and cachetag creation $rows = $matrixdata->{"Rows"}; $datayoffset = 0; $x = $matrixwidget->{"XOffset"}; $y = $matrixwidget->{"YOffset"}; $rowcachetag = ''; $visualr = 0; my $hremain = $matrixwidget->{"Height"}; for ($r = -1; $r < $rows; $r = $r >= 0 ? ++$r : $matrixwidget->{"FirstVisualRow"}) { next if ($matrixdata->{"RH.$r"}->{"Rowhide"}); my $h = $matrixdata->{"RH.$r"}->{"Height"}; my $realw = $matrixdata->{"CH.-1"}->{"Width"}; my $realh = $h + $matrixdata->{"RH.$r"}->{"Rowgap"}; last if ($hremain < $realh); if ($r >= 0) { $datayoffset = $y if ($datayoffset == 0); $matrixwidget->{"RH.$visualr"} = $widget->{'container'}->add("RH.$visualr", 'Label', -x => $x, -y => $y, -text => $matrixdata->{"RH.$r"}->{"Labelhide"} ? " " : $matrixdata->{"RH.$r"}->{"Label"}, -width => $realw, -height => $realh ) if ($doit); $visualr++; $rowcachetag .= ".$realh"; } $y += $realh; $hremain -= $realh; } $lastr = $r; if ($hremain >= 1) { $matrixwidget->{"RH.fillbottom"} = $widget->{'container'}->add("RH.fillbottom", 'Label', -x => $x, -y => $y, -text => '#'x$hremain, -width => 1, -height => $hremain ) if($doit); } return ($datayoffset, $lastr, $rowcachetag); } sub updatecolheading { my $c; my $n; my $visualc; # update column heading label $visualc = 0; $c = $matrixwidget->{"FirstVisualCol"}; $n = $matrixwidget->{"NumVisualCol"}; for (; $n > 0; $c++) { next if ($matrixdata->{"CH.$c"}->{"Colhide"}); $n--; die "col Baeh!" if (not defined $matrixwidget->{"CH.$visualc"}); $matrixwidget->{"CH.$visualc"}->{-text} = $matrixdata->{"CH.$c"}->{"Labelhide"} ? " " : $matrixdata->{"CH.$c"}->{"Label"}; $matrixwidget->{"CH.$visualc"}->draw; #$matrixwidget->{"CH.$visualc"}->focus; $visualc++; } } sub updaterowheading { my $r; my $n; my $visualr; # update row heading label $visualr = 0; $r = $matrixwidget->{"FirstVisualRow"}; $n = $matrixwidget->{"NumVisualRow"}; for (; $n > 0; $r++) { next if ($matrixdata->{"RH.$r"}->{"Rowhide"}); $n--; die "row Baeh!" if (not defined $matrixwidget->{"RH.$visualr"}); $matrixwidget->{"RH.$visualr"}->{-text} = $matrixdata->{"RH.$r"}->{"Labelhide"} ? " " : $matrixdata->{"RH.$r"}->{"Label"}; $matrixwidget->{"RH.$visualr"}->draw; #$matrixwidget->{"RH.$visualr"}->focus; $visualr++; } } sub newmatrixwidget { my ($dc, $dr, $vc, $vr) = @@_; $matrixwidget->{"XOffset"} = 0; #horizontal position relative to screen $matrixwidget->{"YOffset"} = 0; #vertical position relative to screen $matrixwidget->{"Width"} = $widget->{'container'}->width - $matrixwidget->{"XOffset"}; $matrixwidget->{"Height"} = $widget->{'container'}->height - $matrixwidget->{"YOffset"}; $matrixwidget->{"FirstVisualCol"} = $dc || 0; #leftmost data column presented on screen $matrixwidget->{"FirstVisualRow"} = $dr || 0; #topmost data row presented on screen $matrixwidget->{"Cursorcol"} = $vc || 0; #cursor column $matrixwidget->{"Cursorcol"} = $vr || 0; #cursor row $matrixwidget->{"NumVisualCol"} = undef; #number of visible column (calculated later) $matrixwidget->{"NumVisualRow"} = undef; #number of visible row (calculated later) $matrixwidget->{"Cachetag"} = undef; #tracks if widgets can be reused (must start undefined) } sub layoutmatrixwidget { my ($dc, $dr, $vc, $vr) = @@_; $matrixwidget->{"FirstVisualCol"} = $dc if (defined $dc); #leftmost data column presented on screen $matrixwidget->{"FirstVisualRow"} = $dr if (defined $dr); #topmost data row presented on screen $matrixwidget->{"Cursorcol"} = $vc if (defined $vc); #cursor column $matrixwidget->{"Cursorrow"} = $vr if (defined $vr); #cursor row my $c; my $r; my $x; my $y; my $lastc; my $lastr; my $dataxoffset; my $datayoffset; my $colcachetag; my $rowcachetag; my $cachetag; my $cachehit; $cachehit = 0; if (defined $matrixwidget->{"Cachetag"}) { ($dataxoffset, $lastc, $colcachetag) = &colheading(0); ($datayoffset, $lastr, $rowcachetag) = &rowheading(0); $cachetag = $colcachetag . '\\' . $rowcachetag; if ($cachetag eq $matrixwidget->{"Cachetag"}) { $cachehit = 1; } else { &destroymatrixwidgetcells(); } } else { &optimalcolwidth(); &optimalrowheight(); } if (not $cachehit) { ($dataxoffset, $lastc, $colcachetag) = &colheading(1); ($datayoffset, $lastr, $rowcachetag) = &rowheading(1); $cachetag = $colcachetag . '\\' . $rowcachetag; $matrixwidget->{"Cachetag"} = $cachetag; } # now do the matrix content my $visualr; my $visualc; $y = $datayoffset; $visualr = 0; for ($r = $matrixwidget->{"FirstVisualRow"}; $r < $lastr; ++$r) { next if ($matrixdata->{"RH.$r"}->{"Rowhide"}); my $h = $matrixdata->{"RH.$r"}->{"Height"}; my $realh = $h + $matrixdata->{"RH.$r"}->{"Rowgap"}; $x = $dataxoffset; $visualc = 0; for ($c = $matrixwidget->{"FirstVisualCol"}; $c < $lastc; ++$c) { next if ($matrixdata->{"CH.$c"}->{"Colhide"}); my $w = $matrixdata->{"CH.$c"}->{"Width"}; my $realw = $w + $matrixdata->{"CH.$c"}->{"Colgap"}; if (not $cachehit) { $matrixwidget->{"VC.$visualc.$visualr"} = $widget->{'container'}->add("VC.$visualc.$visualr", 'TextEntry', -x => $x, -y => $y, -text => (defined $matrixdata->{"CD.$c.$r"}->{"Data"}) ? $matrixdata->{"CD.$c.$r"}->{"Data"} : ">", -width => $realw, #FIXME -height => $realh, -maxlength => $matrixdata->{"CH.$c"}->{"Widthmax"} #-maxdown => $matrixdata->{"RH.$r"}->{"Heightmax"} ); $matrixwidgetvisualcell->{$matrixwidget->{"VC.$visualc.$visualr"}} = [ $visualc, $visualr ]; } else { $matrixwidget->{"VC.$visualc.$visualr"}->{-text} = (defined $matrixdata->{"CD.$c.$r"}->{"Data"}) ? $matrixdata->{"CD.$c.$r"}->{"Data"} : ">"; } $matrixwidgetdatacell->{$matrixwidget->{"VC.$visualc.$visualr"}} = [ $c, $r ]; $visualc++; $x += $realw; } $visualr++; $y += $realh; } $matrixwidget->{"NumVisualCol"} = $visualc; $matrixwidget->{"NumVisualRow"} = $visualr; &updatecolheading(); &updaterowheading(); # key bindings and event handling if (not $cachehit) { for ($c = 0; $c < $visualc; $c++) { for ($r = 0; $r < $visualr; $r++) { $matrixwidget->{"VC.$c.$r"}->set_binding(\&tabbinder, "\cI", KEY_ENTER(), KEY_F(2)); $matrixwidget->{"VC.$c.$r"}->set_event("-onfocus", sub { my $this = shift; my ($vc, $vr) = @@{$matrixwidgetvisualcell->{$this}}; my ($dc, $dr) = @@{$matrixwidgetdatacell->{$this}}; $matrixwidget->{"VC.$vc.$vr"}->{-canvasscr}->standout unless($editcell); if (defined $matrixdata->{"CD.$dc.$dr"}->{"Focuscallback"}) { &{$matrixdata->{"CD.$dc.$dr"}->{"Focuscallback"}}($matrixwidget, $dc, $dr, $vc, $vr); } } ); $matrixwidget->{"VC.$c.$r"}->set_event("-onblur", sub { my $this = shift; my ($vc, $vr) = @@{$matrixwidgetvisualcell->{$this}}; my ($dc, $dr) = @@{$matrixwidgetdatacell->{$this}}; $matrixwidget->{"VC.$vc.$vr"}->{-canvasscr}->standend; if ($editcell) { if (defined $matrixdata->{"CD.$dc.$dr"}->{"Blurcallback"}) { $datacoll = &{$matrixdata->{"CD.$dc.$dr"}->{"Blurcallback"}}($matrixwidget, $dc, $dr, $vc, $vr); } } $editcell = 0; } ); } } } } sub tabbinder { my $this = shift; my $key = shift; $key = "\cD" if ($key == KEY_DC()); #make CTRL-D a normal key my $nvc = $matrixwidget->{"NumVisualCol"} - 1; my $nvr = $matrixwidget->{"NumVisualRow"} - 1; if ((not $editcell) or (not defined $matrixwidgetvisualcell->{$this})) { return 'DELEGATE'; } my ($vc, $vr) = @@{$matrixwidgetvisualcell->{$this}}; if ($editcell and $key eq "\cI") { my ($vc, $vr) = @@{$matrixwidgetvisualcell->{$this}}; my ($dc, $dr) = @@{$matrixwidgetdatacell->{$this}}; my $datacollabel = $matrixdata->{"CH.$dc"}->{"Keyname"}; if ($datacollabel =~ m/^(date)$/) { $this->{-text} = &{$matrixdata->{"completedate"}}($matrixwidget, $dc, $dr, $vc, $vr, $this->{-text}); $this->{-pos} = length($this->{-text}); } elsif ($datacollabel =~ m/^(begin|end|amount)$/) { $this->{-text} = &{$matrixdata->{"completetime"}}($matrixwidget, $dc, $dr, $vc, $vr, $this->{-text}); $this->{-pos} = length($this->{-text}); } elsif ($datacollabel eq "account") { my $accounts = []; my $values = []; my $labels = {}; if (defined $matrixdata->{"completeaccount"}) { my ($vc, $vr) = @@{$matrixwidgetvisualcell->{$this}}; my ($dc, $dr) = @@{$matrixwidgetdatacell->{$this}}; $accounts = &{$matrixdata->{"completeaccount"}}($matrixwidget, $dc, $dr, $vc, $vr, $this->{-text}); } my $count = @@{$accounts}; if ($count == 0) { #FIXME error } elsif ($count == 1) { if (defined $matrixdata->{"CD.$dc.$dr"}->{"Blurcallback"}) { $matrixwidget->{"VC.$vc.$vr"}->{-text} = $accounts->[0]; &{$matrixdata->{"CD.$dc.$dr"}->{"Blurcallback"}}($matrixwidget, $dc, $dr, $vc, $vr); } $editcell = 0; $datacoll = 1; } else { my $i = 0; foreach my $a (@@{$accounts}) { $values->[$i] = $i; $labels->{$i} = $a; $i++; } my $w = $this->parent->add("accountselection", 'Listbox', -x => $matrixwidget->{"XOffset"}, -y => $matrixwidget->{"YOffset"}, -values => $values, -labels => $labels, -width => $matrixwidget->{"Width"}, -height => $matrixwidget->{"Height"}, -border => 1, #-multi => 1, -title => $matrixdata->{"CH.$dc"}->{"Label"}, -vscrollbar => 1, #-onchange => \&listbox_callback, ); $w->set_binding( sub { my $this = shift; my $key = shift; $this->{-has_modal_focus} = 0; }, KEY_ENTER()); $w->draw; $w->modalfocus; $this->parent->delete("accountselection"); if (defined $w->{-selected}) { if (defined $matrixdata->{"CD.$dc.$dr"}->{"Blurcallback"}) { $matrixwidget->{"VC.$vc.$vr"}->{-text} = $accounts->[$w->{-selected}]; &{$matrixdata->{"CD.$dc.$dr"}->{"Blurcallback"}}($matrixwidget, $dc, $dr, $vc, $vr); } } $editcell = 0; $datacoll = 1; } } } elsif ($key == KEY_F(2) or $key == KEY_ENTER) { my ($vc, $vr) = @@{$matrixwidgetvisualcell->{$this}}; my ($dc, $dr) = @@{$matrixwidgetdatacell->{$this}}; if ($editcell) { if (defined $matrixdata->{"CD.$dc.$dr"}->{"Blurcallback"}) { $datacoll = &{$matrixdata->{"CD.$dc.$dr"}->{"Blurcallback"}}($matrixwidget, $dc, $dr, $vc, $vr); } } $matrixwidget->{"VC.$vc.$vr"}->{-canvasscr}->standout; $matrixwidget->{"VC.$vc.$vr"}->draw; $editcell = 0; return; } else { return 'DELEGATE'; } } sub keybinder { my $this = shift; my $key = shift; $key = "\cD" if ($key == KEY_DC()); #make CTRL-D a normal key my $nvc = $matrixwidget->{"NumVisualCol"} - 1; my $nvr = $matrixwidget->{"NumVisualRow"} - 1; if ($editcell) { return 'DELEGATE'; } # special handling when table is empty (dummy is focused) if (not defined $matrixwidgetvisualcell->{$this->getfocusobj}) { if ($key eq "o") { if (defined $matrixdata->{"onanewline"}) { &{$matrixdata->{"onanewline"}}($matrixwidget, 0, 0, 0, 0); $datacoll = 1; } $this->root->feedkey(KEY_F(2)); #enter edit mode after datacoll was handled } elsif ($key eq "p" and defined $matrixdata->{"paste"} and $matrixdata->{"clipboardtype"} eq "line") { if (defined $matrixdata->{"paste"}) { &{$matrixdata->{"paste"}}($matrixwidget, 0, 0, 0, 0); $datacoll = 1; } } if ($datacoll) { #$matrixwidget->{"Cursorcol"} = 0; #$matrixwidget->{"Cursorrow"} = 0; return; } return 'DELEGATE'; } my ($vc, $vr) = @@{$matrixwidgetvisualcell->{$this->getfocusobj}}; if ($key == KEY_UP() or (not $editcell and $key eq "k")) { $vr--; if ($vr < 0) { $vrscroll = -1; $vr = 0; } } elsif ($key == KEY_PPAGE()) { my $j; $j = int($matrixwidget->{"NumVisualRow"} / 3 * 1); $j = 10 if ( $j < 10 ); $vr-=$j; if ($vr < 0) { $vrscroll = $vr; $vr = 0; } } elsif ($key == KEY_DOWN() or (not $editcell and $key eq "j")) { $vr++; if ($vr > $nvr) { $vrscroll = 1; $vr = $nvr; } } elsif ($key == KEY_NPAGE()) { my $j; $j = int($matrixwidget->{"NumVisualRow"} / 3 * 1); $j = 10 if ( $j < 10); $vr+=$j; if ($vr > $nvr) { $vrscroll = $vr - $nvr; $vr = $nvr; } } elsif (not $editcell and ($key == KEY_LEFT() or $key eq "h")) { $vc--; if ($vc < 0) { $vcscroll = -1; $vc = 0; } } elsif (not $editcell and ($key == KEY_RIGHT() or $key eq "l")) { $vc++; if ($vc > $nvc) { $vcscroll = 1; $vc = $nvc } } elsif ($key == KEY_HOME() && not $editcell) { $vr = 0; $vc = 0; } elsif ($key == KEY_END() && not $editcell) { $vr = $nvr; $vc = $nvc; } elsif (not $editcell and ($key eq "^" or $key eq "0")) { $vc = 0; $vcpos = -1; } elsif (not $editcell and $key eq "\$") { $vc = $nvc; $vcpos = +1; } elsif (not $editcell and $key eq "1") { $vr = 0; $vrpos = -1; } elsif (not $editcell and $key eq "G") { $vr = $nvr; $vrpos = +1; } elsif (not $editcell and $key eq "\cU") { my $j; $j = int($matrixwidget->{"NumVisualRow"} / 3 * 1); $j = 10 if ( $j < 10 ); $vrscroll = -$j; } elsif (not $editcell and $key eq "\cD") { my $j; $j = int($matrixwidget->{"NumVisualRow"} / 3 * 1); $j = 10 if ( $j < 10 ); $vrscroll = +$j; } elsif (not $editcell and $key eq "\cB") { $vrscroll = -$matrixwidget->{"NumVisualRow"}; } elsif (not $editcell and $key eq "\cF") { $vrscroll = +$matrixwidget->{"NumVisualRow"}; } elsif ($key == KEY_F(1)) { $this->root->dialog( "\n ==== action ====\n" . " CTRL-X - menu\n" . " CTRL-Q - save and quit\n" . " F1 - help\n" . " RET/F2 - edit existing line\n" . " o/F3 - edit on new next line\n" . " O/F4 - edit on new this line\n" . " d/F5 - mark line for deletion\n" . "\n ==== control column view ====\n" . " F7 - show/hide\n" . " F8 - sort\n" . " F9 - shrink to min\n" . " F10 - shrink\n" . " F11 - grow\n" . " F12 - grow to max\n" . "\n ==== movement ====\n" . " hjkl/CURSOR - left, down, up, right\n" . "PAGE UP/DOWN - move 10 line\n" . " TAB - next cell\n" . " HOME/END - jump to first/last cell\n" ); return; #do not change focus } elsif (not $editcell and ($key eq " ")) { $matrixwidget->{"VC.$vc.$vr"}->{-text} = ''; $matrixwidget->{"VC.$vc.$vr"}->{-pos} = 0; $matrixwidget->{"VC.$vc.$vr"}->{-canvasscr}->standend; $matrixwidget->{"VC.$vc.$vr"}->draw; $editcell = 1; return; #do not change focus } elsif (not $editcell and ($key == KEY_F(2) or $key == KEY_ENTER)) { $matrixwidget->{"VC.$vc.$vr"}->{-canvasscr}->standend; $matrixwidget->{"VC.$vc.$vr"}->draw; $editcell = 1; return; #do not change focus } elsif (not $editcell and ($key == KEY_F(3) or $key eq "o")) { if (defined $matrixdata->{"onanewline"}) { my ($vc, $vr) = @@{$matrixwidgetvisualcell->{$this->getfocusobj}}; my ($dc, $dr) = @@{$matrixwidgetdatacell->{$this->getfocusobj}}; &{$matrixdata->{"onanewline"}}($matrixwidget, $dc, $dr, $vc, $vr); $datacoll = 1; } $this->root->feedkey(KEY_F(2)); #enter edit mode after datacoll was handled # implicit immediate KEY_DOWN $vr++; if ($vr > $nvr) { $vrscroll = 1; $vr = $nvr; } } elsif (not $editcell and ($key == KEY_F(4) or $key eq "O")) { if (defined $matrixdata->{"Onanewline"}) { my ($vc, $vr) = @@{$matrixwidgetvisualcell->{$this->getfocusobj}}; my ($dc, $dr) = @@{$matrixwidgetdatacell->{$this->getfocusobj}}; &{$matrixdata->{"Onanewline"}}($matrixwidget, $dc, $dr, $vc, $vr); $datacoll = 1; } $this->root->feedkey(KEY_F(2)); #enter edit mode after datacoll was handled return; #do not change focus } elsif (not $editcell and ($key == KEY_F(5) or $key eq "d")) { if (defined $matrixdata->{"deletedelete"}) { my ($vc, $vr) = @@{$matrixwidgetvisualcell->{$this->getfocusobj}}; my ($dc, $dr) = @@{$matrixwidgetdatacell->{$this->getfocusobj}}; if (&{$matrixdata->{"deletedelete"}}($matrixwidget, $dc, $dr, $vc, $vr)) { # implicit immediate KEY_UP when trailing line was deleted $vr--; if ($vr < 0) { $vrscroll = -1; $vr = 0; } } $datacoll = 1; } return; #do not change focus } elsif (not $editcell and $key eq "u") { if (defined $matrixdata->{"undo"}) { my ($vc, $vr) = @@{$matrixwidgetvisualcell->{$this->getfocusobj}}; my ($dc, $dr) = @@{$matrixwidgetdatacell->{$this->getfocusobj}}; return unless &{$matrixdata->{"undo"}}($matrixwidget, $dc, $dr, $vc, $vr); $datacoll = 1; } } elsif ($key == KEY_F(7)) { my $c; my $values = []; my $labels = {}; my $select = {}; for ($c = 0; $c < $matrixdata->{"Columns"}; $c++) { push @@{$values}, "$c"; $labels->{"$c"} = $matrixdata->{"CH.$c"}->{"Label"}; $select->{"$c"} = $matrixdata->{"CH.$c"}->{"Colhide"} ? 0 : 1; } my $w = $this->add("hideandseek", 'Listbox', -x => $matrixwidget->{"XOffset"}, -y => $matrixwidget->{"YOffset"}, -values => $values, -labels => $labels, -selected => $select, -width => 20, -height => 20, -border => 1, -multi => 1, -title => 'Show', -vscrollbar => 1, #-onchange => \&listbox_callback, ); $w->set_binding( sub { my $this = shift; my $key = shift; $this->{-has_modal_focus} = 0; }, KEY_ENTER()); $w->draw; $w->modalfocus; #foreach my $key (keys %{$w}) { printf STDERR " key=$key, value=$w->{$key}\n" }; #foreach my $sel (keys %{$select}) { printf STDERR "select sel=$sel, value=$select->{$sel}\n" }; for ($c = 0; $c < $matrixdata->{"Columns"}; $c++) { $matrixdata->{"CH.$c"}->{"Colhide"} = $select->{"$c"} ? 0 : 1; } $this->delete("hideandseek"); $this->root->focus(undef, 1); $datacoll = 1; return; #do not change focus } elsif ($key == KEY_F(8)) { my $c; my $i; my $values = []; my $labels = {}; my $select = {}; my $trackc = {}; $i = 0; foreach $c (@@{$matrixdata->{"Sortorder"}}) { $values->[$i] = "$c"; $labels->{$c} = $matrixdata->{"CH.$c"}->{"Label"}; $select->{$i} = 1; $trackc->{$c} = 1; $i++; } for ($c = 0; $c < $matrixdata->{"Columns"}; $c++) { if (not $trackc->{$c}) { $values->[$i] = "$c"; $labels->{$c} = $matrixdata->{"CH.$c"}->{"Label"}; $select->{$i} = 0; $i++; } } my $w = $this->add("sortselection", 'Listbox', -x => $matrixwidget->{"XOffset"}, -y => $matrixwidget->{"YOffset"}, -values => $values, -selected => $select, -labels => $labels, #-values => ["b", "a", "c"], #-selected => {0 => 1, 2 => 1}, #means 0 (b/bar) and 2 (c/quux) is selected #-labels => {"a" => "foo", "b" => "bar", "c" => "quux"}, -width => 20, -height => 20, -border => 1, -multi => 1, -title => 'Sort', -vscrollbar => 1, #-onchange => \&listbox_callback, ); $w->set_binding( sub { my $this = shift; my $key = shift; $this->{-has_modal_focus} = 0; }, KEY_ENTER()); $w->draw; $w->modalfocus; #foreach my $key (sort keys %{$w}) { printf STDERR "key=$key, value=$w->{$key}\n" }; #printf STDERR "values[] = @@{$w->{-values}}\n"; #foreach my $key (sort keys %{$w->{-selected}}) { printf STDERR "key=$key, value=$w->{-selected}->{$key} indirect value $w->{-values}->[$key]\n" }; #foreach my $key (keys %{$w->{-selected}}) { printf STDERR "$w->{-values}->[$key]\n" if ($w->{-selected}->{$key}); }; #die "buh3"; $matrixdata->{"Sortorder"} = []; for ($i = 0; $i <= $#{$values}; $i++) { $c = $w->{-values}->[$i]; #printf STDERR "$c (at index $i) = $w->{-selected}->{$i}\n"; push @@{$matrixdata->{"Sortorder"}}, $c if ($w->{-selected}->{$i}); } $this->delete("sortselection"); $this->root->focus(undef, 1); if (defined $matrixdata->{"sort"}) { my ($vc, $vr) = @@{$matrixwidgetvisualcell->{$this->getfocusobj}}; my ($dc, $dr) = @@{$matrixwidgetdatacell->{$this->getfocusobj}}; &{$matrixdata->{"sort"}}($matrixwidget, $dc, $dr, $vc, $vr); $datacoll = 1; } return; #do not change focus } elsif (not $editcell and $key eq "y") { if (defined $matrixdata->{"yankcell"}) { my ($vc, $vr) = @@{$matrixwidgetvisualcell->{$this->getfocusobj}}; my ($dc, $dr) = @@{$matrixwidgetdatacell->{$this->getfocusobj}}; &{$matrixdata->{"yankcell"}}($matrixwidget, $dc, $dr, $vc, $vr); $datacoll = 1; } } elsif (not $editcell and $key eq "Y") { if (defined $matrixdata->{"Yankline"}) { my ($vc, $vr) = @@{$matrixwidgetvisualcell->{$this->getfocusobj}}; my ($dc, $dr) = @@{$matrixwidgetdatacell->{$this->getfocusobj}}; &{$matrixdata->{"Yankline"}}($matrixwidget, $dc, $dr, $vc, $vr); $datacoll = 1; } } elsif (not $editcell and $key eq "p") { if (defined $matrixdata->{"paste"} and $matrixdata->{"clipboardtype"} eq "cell") { my ($vc, $vr) = @@{$matrixwidgetvisualcell->{$this->getfocusobj}}; my ($dc, $dr) = @@{$matrixwidgetdatacell->{$this->getfocusobj}}; return unless &{$matrixdata->{"paste"}}($matrixwidget, $dc, $dr, $vc, $vr); $datacoll = 1; } elsif (defined $matrixdata->{"paste"} and $matrixdata->{"clipboardtype"} eq "line") { my ($vc, $vr) = @@{$matrixwidgetvisualcell->{$this->getfocusobj}}; my ($dc, $dr) = @@{$matrixwidgetdatacell->{$this->getfocusobj}}; return unless &{$matrixdata->{"paste"}}($matrixwidget, $dc, $dr, $vc, $vr); $datacoll = 1; $vr++; if ($vr > $nvr) { $vrscroll = 1; $vr = $nvr; } } } elsif (not $editcell and $key eq "P") { if (defined $matrixdata->{"Paste"}) { my ($vc, $vr) = @@{$matrixwidgetvisualcell->{$this->getfocusobj}}; my ($dc, $dr) = @@{$matrixwidgetdatacell->{$this->getfocusobj}}; return unless &{$matrixdata->{"Paste"}}($matrixwidget, $dc, $dr, $vc, $vr); $datacoll = 1; } #$this->root->feedkey(KEY_F(2)); #enter edit mode after datacoll was handled return; #do not change focus } elsif (not $editcell and $key eq ".") { if (defined $matrixdata->{"currentdatetime"}) { my ($vc, $vr) = @@{$matrixwidgetvisualcell->{$this->getfocusobj}}; my ($dc, $dr) = @@{$matrixwidgetdatacell->{$this->getfocusobj}}; return unless &{$matrixdata->{"currentdatetime"}}($matrixwidget, $dc, $dr, $vc, $vr); $datacoll = 1; } } elsif ($key == KEY_F(9)) { my ($vc, $vr) = @@{$matrixwidgetvisualcell->{$this->getfocusobj}}; my ($dc, $dr) = @@{$matrixwidgetdatacell->{$this->getfocusobj}}; my $width = $matrixdata->{"CH.$dc"}->{"Width"}; if ($width != $matrixdata->{"CH.$dc"}->{"Widthmin"}) { $matrixdata->{"CH.$dc"}->{"Width"} = $matrixdata->{"CH.$dc"}->{"Widthmin"}; $datacoll = 1; } return; #do not change focus } elsif ($key == KEY_F(10)) { my ($vc, $vr) = @@{$matrixwidgetvisualcell->{$this->getfocusobj}}; my ($dc, $dr) = @@{$matrixwidgetdatacell->{$this->getfocusobj}}; my $width = $matrixdata->{"CH.$dc"}->{"Width"}; $width--; if ($width >= $matrixdata->{"CH.$dc"}->{"Widthmin"}) { $matrixdata->{"CH.$dc"}->{"Width"} = $width; $datacoll = 1; } return; #do not change focus } elsif ($key == KEY_F(11)) { my ($vc, $vr) = @@{$matrixwidgetvisualcell->{$this->getfocusobj}}; my ($dc, $dr) = @@{$matrixwidgetdatacell->{$this->getfocusobj}}; my $width = $matrixdata->{"CH.$dc"}->{"Width"}; $width++; if ($width <= $matrixdata->{"CH.$dc"}->{"Widthmax"}) { $matrixdata->{"CH.$dc"}->{"Width"} = $width; $datacoll = 1; } return; #do not change focus } elsif ($key == KEY_F(12)) { my ($vc, $vr) = @@{$matrixwidgetvisualcell->{$this->getfocusobj}}; my ($dc, $dr) = @@{$matrixwidgetdatacell->{$this->getfocusobj}}; my $width = $matrixdata->{"CH.$dc"}->{"Width"}; if ($width != $matrixdata->{"CH.$dc"}->{"Widthmax"}) { $matrixdata->{"CH.$dc"}->{"Width"} = $matrixdata->{"CH.$dc"}->{"Widthmax"}; $datacoll = 1; } return; #do not change focus } $matrixwidget->{"Cursorcol"} = $vc; $matrixwidget->{"Cursorrow"} = $vr; if ($vcscroll == 0 && $vrscroll == 0) { $matrixwidget->{"VC.$vc.$vr"}->focus; } else { $widget->{"dummy"}->focus; } } sub destroymatrixwidgetcells { foreach my $i (sort keys %{$matrixwidget}) { if ($i =~ m/^VC\.\d+\.\d+/ || $i =~ m/^(CH|RH)\.(\d+|fill.*)/) { $matrixwidget->{$i}->parent->delete($i); delete $matrixwidget->{$i}; } } } sub destroymatrixwidget { &destroymatrixwidgetcells(); undef $matrixwidget; } sub drawallmatrixwidgets { $widget->{'container'}->draw; return; foreach my $i (sort keys %{$matrixwidget}) { if ($i =~ m/^VC\.\d+\.\d+/ || $i =~ m/^(CH|RH)\.(\d+|fill.*)/) { #printf STDERR "DRAW: $i\n"; $matrixwidget->{$i}->draw; } } } sub drawfocusmatrixwidget { my $c; my $r; my $lastc; my $lastr; &drawallmatrixwidgets(); $c = defined $matrixwidget->{"Cursorcol"} ? $matrixwidget->{"Cursorcol"} : 0; $r = defined $matrixwidget->{"Cursorrow"} ? $matrixwidget->{"Cursorrow"} : 0; $lastc = $matrixwidget->{"NumVisualCol"} - 1; #Col0=heading, Col1...n=cursor area $lastr = $matrixwidget->{"NumVisualRow"} - 1; #Row0=heading, Row1...n=cursor area $widget->{"dummy"}->focus; if ($lastc >= 0 and $lastr >= 0) { $c = $lastc if ($c > $lastc); $r = $lastr if ($r > $lastr); $matrixwidget->{"VC.$c.$r"}->{-canvasscr}->standout; $matrixwidget->{"VC.$c.$r"}->draw; $matrixwidget->{"VC.$c.$r"}->focus; } } sub ascui { ($matrixdata, $verbose) = (@@_); # in CUI mode we do not want STDERR to clutter our screen. ($verbose && open STDERR, ">>2.log") || (open STDERR, ">/dev/null"); # create the root object $cui = new Curses::UI ( -clear_on_exit => 0, # -debug => $debug, ); $cui->overlapping(0); #activates rse performance enhancement patch for non-overlapping layouts # die handler $SIG{__DIE__} = sub { my ($err) = @@_; $err =~ s|\s+at\s+.*||s if (not $verbose); my $txt = "$err ". ($! ? "($!)" : ""); ($verbose || open STDERR, ">>2.log") || (open STDERR, ">>$ENV{HOME}/2.log") || (open STDERR, ">>/tmp/2.log"); print STDERR "ERROR: $txt\n"; $cui->error("$txt") if (defined $cui); exit(1); }; # create menu widget my $menu_file = [ { -label => 'Quit program', -value => sub {exit(0)} }, ]; my $menu_as = [ { -label => 'Testerli 1', -value => sub {exit(0)} }, { -label => 'Testerli 2', -value => sub {exit(0)} }, ]; my $menu = [ { -label => 'File', -submenu => $menu_file }, { -label => 'Accounting', -submenu => $menu_as }, ]; $widget->{'menu'} = $cui->add('menu', 'Menubar', -menu => $menu ); # add main window $widget->{'main'} = $cui->add('main', 'Window', -padtop => 1, #leave space for menu on the top -padbottom => 1, #leave space for status on the bottom -border => 0 ); # add status window $widget->{'stat'} = $cui->add('stat', 'Window', -height => 1, -y => -1, -border => 0 ); # add a status line my $wstat = $widget->{'stat'}->width; my $textl = "Accounting System (AS)"; my $textr = "CTRL+X: menu CTRL+Q: quit"; my $textf = " " x ($wstat -2 -length($textl) -1 -1 -length($textr) - 2); my $text = sprintf(" %s %s %s ", $textl, $textf, $textr); $widget->{'status'}->{-text} = $text; $widget->{'info'} = $widget->{'stat'}->add('info', 'Label', -text => $text, -reverse => 1, ); # add a container $widget->{'container'} = $widget->{'main'}->add(undef, 'Container'); # add dummy to focus and to indirectly force blur $widget->{'dummy'} = $widget->{'container'}->add(undef, 'TextEntry', -x => 0, -y => 0, -text => "", -width => 3, -height => 1 ); $cui->set_binding(sub{ $breakout = 1 }, "\cQ"); $cui->set_binding(sub{ shift()->root->focus('menu') }, "\cX"); $widget->{'container'}->set_binding(\&keybinder, ''); #now we catch all chars not just @@keys_move $cui->draw; &newmatrixwidget(); my ($upperleftcol, $cursorcol) = ($matrixdata->{"CK.date"}, 0); #&rightmostvisiblefit(); my ($upperleftrow, $cursorrow) = &bottommostvisiblefit(); &layoutmatrixwidget($upperleftcol, $upperleftrow, $cursorcol, $cursorrow); &drawfocusmatrixwidget(); $breakout = 0; do { $vcscroll = 0; $vrscroll = 0; $datacoll = 0; $vcpos = 0; $vrpos = 0; $cui->root->do_one_event; if ($vcscroll < 0) { $upperleftcol += $vcscroll; $upperleftcol = 0 if ($upperleftcol < 0); } elsif ($vcscroll > 0) { $upperleftcol += $vcscroll; my ($upperleftcolfit, $dummy) = &rightmostvisiblefit(); $upperleftcol = $upperleftcolfit if ($upperleftcol > $upperleftcolfit); } if ($vrscroll < 0) { $upperleftrow += $vrscroll; $upperleftrow = 0 if ($upperleftrow < 0); } elsif ($vrscroll > 0) { $upperleftrow += $vrscroll; my ($upperleftrowfit, $dummy) = &bottommostvisiblefit(); $upperleftrow = $upperleftrowfit if ($upperleftrow > $upperleftrowfit); } if ($vcpos < 0) { $upperleftcol = 0; } elsif ($vcpos > 0) { ($upperleftcol, my $dummy) = &rightmostvisiblefit(); } if ($vrpos < 0) { $upperleftrow = 0; } elsif ($vrpos > 0) { ($upperleftrow, my $dummy) = &bottommostvisiblefit(); } if ($vcscroll != 0 or $vrscroll != 0 or $datacoll != 0 or $vcpos != 0 or $vrpos != 0) { &layoutmatrixwidget($upperleftcol, $upperleftrow); &drawfocusmatrixwidget(); } } until ($breakout); &destroymatrixwidget(); $cui->dialog("Bye bye!"); } 1; @ 1.28 log @Remove lots of debugging stuff. @ text @@ 1.27 log @cosmetic changes only - replace tabs with spaces - align blocks on four char boundaries - make sure all functions are executed with & prefix @ text @a198 1 #printf STDERR "DEBUG: matrixdata->{RH.%d}->Heightweight=%d\n", $r, $matrixdata->{"RH.$r"}->{"Heightweight"}; a269 1 #printf STDERR "DEBUG: colcachetag=$colcachetag\n"; a270 1 #printf STDERR "DEBUG: lastc=$lastc, dataxoffset=$dataxoffset, wremain=$wremain\n"; a322 1 #printf STDERR "DEBUG: rowcachetag=$rowcachetag\n"; a323 1 #printf STDERR "DEBUG: lastr=$lastr, datayoffset=$datayoffset, hremain=$hremain\n"; a341 1 #printf STDERR "DEBUG: col von start\n"; a344 1 #printf STDERR "DEBUG: col von $c, num=$n, visualc=$visualc\n"; a345 1 #printf STDERR "DEBUG: von $c, num=$n, visualc=$visualc\n"; a348 1 #$matrixwidget->{"CH.$visualc"}->{-text} = "$visualc $c"; #DEBUG a353 1 #printf STDERR "DEBUG: col bis end\n"; a361 1 #printf STDERR "DEBUG: row von start\n"; a364 1 #printf STDERR "DEBUG: von $r, num=$n, visualr=$visualr\n"; a365 1 #printf STDERR "DEBUG: row von $r, num=$n, visualc=$visualr\n"; a368 1 #$matrixwidget->{"RH.$visualr"}->{-text} = "$visualr $r"; #DEBUG a373 1 #printf STDERR "DEBUG: row bis end\n"; a475 1 #printf STDERR "DEBUG: visualc=$visualc, visualr=$visualr\n"; a521 1 #printf STDERR "DEBUG: key was (%d) \"%s\"\n", ord($key), $key; a527 1 #printf STDERR "DEBUG: start with vc,vr=%d,%d\n", $vc, $vr; a552 1 #printf STDERR "DEBUG: count=$count\n"; die; a566 1 #printf STDERR "DEBUG: a=\"$a\"\n"; a596 1 #printf STDERR "DEBUG: text=$accounts->[$w->{-selected}]\n"; a607 1 #printf STDERR "DEBUG: captured F2/ENTER in tabbinder\n"; a631 1 #printf STDERR "DEBUG: key was (%d) \"%s\"\n", ord($key), $key; die; a660 1 #printf STDERR "DEBUG: start with vc,vr=%d,%d\n", $vc, $vr; a785 1 #printf STDERR "DEBUG: captured F2/ENTER in keybinder\n"; a1014 1 #printf STDERR "DEBUG: width=$width\n"; a1025 1 #printf STDERR "DEBUG: width=$width\n"; a1036 1 #printf STDERR "DEBUG: width=$width\n"; a1046 1 #printf STDERR "DEBUG: width=$width\n"; a1055 1 #printf STDERR "DEBUG: end up with vc,vr=%d,%d and set focus to this\n", $vc, $vr; a1058 1 #printf STDERR "DEBUG: end up with vc,vr=%d,%d and set focus to dummy\n", $vc, $vr; a1062 6 #foreach my $i (sort keys %{$matrixwidget}) { #DEBUG # if ($i =~ m/^VC\.\d+\.\d+/ || $i =~ m/^(CH|RH)\.(\d+|fill.*)/) { #DEBUG # $matrixwidget->{$i}->{-canvasscr}->standout; #DEBUG # $matrixwidget->{$i}->draw; #DEBUG # } #DEBUG #} #DEBUG a1064 3 #printf STDERR "DEBUG: destroying $i\n"; #DEBUG $matrixwidget->{$i}->{-canvasscr}->standend; #DEBUG $matrixwidget->{$i}->draw; #DEBUG a1067 3 #else { #DEBUG # printf STDERR "DEBUG: saved \"$i\"\n"; #DEBUG #} #DEBUG a1097 1 #printf STDERR "DEBUG: c=$c, r=$r, lastc=$lastc, lastr=$lastr\n"; @ 1.26 log @lots of work to unify internal processing of cli and cui properly distinguish naming between single event and all events add &isvalid(user|uuid|crc32|revision|date|begin|end|amount|account|remark) check functions &completeaccount now escapes special characters using quotemeta &readevents rewritten to use new cli/cui-unified functions "e used more consequently; does no longer escape dots; handels empty strings &bydateline no longer compares (sorts) by "end" &calccrc32 runs a loop but hardcoded fields; single event makes uuid no longer special &cuinewevent properly supports fractional pasting with fallback to default for each key Blurcallbacks rewritten to support single event fixed name/column lookup problem providing and using Keyname and CK.Label lookups status now kept in event and events; supported by &matrixrowstatus error supports multiple annotations &event2ln and &ln2event convert from single event to plain text lines &getevent and &setevent convert from single event to events &matrixrow2event converts a matrix row to single event &matrix2events rewritten to use new cli/cui-unified functions added &dumpevent for debugging "onanewline" and "Onanewline" now prefills date @ text @d501 1 a501 1 $matrixwidget->{"VC.$c.$r"}->set_event("-onfocus", d503 7 a509 7 my $this = shift; my ($vc, $vr) = @@{$matrixwidgetvisualcell->{$this}}; my ($dc, $dr) = @@{$matrixwidgetdatacell->{$this}}; $matrixwidget->{"VC.$vc.$vr"}->{-canvasscr}->standout unless($editcell); if (defined $matrixdata->{"CD.$dc.$dr"}->{"Focuscallback"}) { &{$matrixdata->{"CD.$dc.$dr"}->{"Focuscallback"}}($matrixwidget, $dc, $dr, $vc, $vr); } d512 1 a512 1 $matrixwidget->{"VC.$c.$r"}->set_event("-onblur", d514 10 a523 10 my $this = shift; my ($vc, $vr) = @@{$matrixwidgetvisualcell->{$this}}; my ($dc, $dr) = @@{$matrixwidgetdatacell->{$this}}; $matrixwidget->{"VC.$vc.$vr"}->{-canvasscr}->standend; if ($editcell) { if (defined $matrixdata->{"CD.$dc.$dr"}->{"Blurcallback"}) { $datacoll = &{$matrixdata->{"CD.$dc.$dr"}->{"Blurcallback"}}($matrixwidget, $dc, $dr, $vc, $vr); } } $editcell = 0; d687 5 a691 5 $vr--; if ($vr < 0) { $vrscroll = -1; $vr = 0; } d694 8 a701 8 my $j; $j = int($matrixwidget->{"NumVisualRow"} / 3 * 1); $j = 10 if ( $j < 10 ); $vr-=$j; if ($vr < 0) { $vrscroll = $vr; $vr = 0; } d704 5 a708 5 $vr++; if ($vr > $nvr) { $vrscroll = 1; $vr = $nvr; } d711 8 a718 8 my $j; $j = int($matrixwidget->{"NumVisualRow"} / 3 * 1); $j = 10 if ( $j < 10); $vr+=$j; if ($vr > $nvr) { $vrscroll = $vr - $nvr; $vr = $nvr; } d721 5 a725 5 $vc--; if ($vc < 0) { $vcscroll = -1; $vc = 0; } d728 5 a732 5 $vc++; if ($vc > $nvc) { $vcscroll = 1; $vc = $nvc } d735 2 a736 2 $vr = 0; $vc = 0; d739 2 a740 2 $vr = $nvr; $vc = $nvc; d743 2 a744 2 $vc = 0; $vcpos = -1; d747 2 a748 2 $vc = $nvc; $vcpos = +1; d751 2 a752 2 $vr = 0; $vrpos = -1; d755 2 a756 2 $vr = $nvr; $vrpos = +1; d759 4 a762 4 my $j; $j = int($matrixwidget->{"NumVisualRow"} / 3 * 1); $j = 10 if ( $j < 10 ); $vrscroll = -$j; d765 4 a768 4 my $j; $j = int($matrixwidget->{"NumVisualRow"} / 3 * 1); $j = 10 if ( $j < 10 ); $vrscroll = +$j; d771 1 a771 1 $vrscroll = -$matrixwidget->{"NumVisualRow"}; d774 1 a774 1 $vrscroll = +$matrixwidget->{"NumVisualRow"}; d1158 2 a1159 2 $cui = new Curses::UI ( -clear_on_exit => 0, d1187 1 a1187 1 $widget->{'menu'} = $cui->add('menu', 'Menubar', d1192 1 a1192 1 $widget->{'main'} = $cui->add('main', 'Window', d1195 1 a1195 1 -border => 0 d1199 1 a1199 1 $widget->{'stat'} = $cui->add('stat', 'Window', d1202 1 a1202 1 -border => 0 d1212 1 a1212 1 $widget->{'info'} = $widget->{'stat'}->add('info', 'Label', d1225 1 a1225 1 -width => 1, @ 1.25 log @delete/undo with unlimited history stack @ text @d538 1 a538 1 #printf STDERR "DEBUG: key was (%d) \"%s\"\n", ord($key), $key; die; d550 1 a550 1 my $datacollabel = $matrixdata->{"CH.$dc"}->{"Label"}; #FIXME name/position lookup problem d555 1 a555 1 elsif ($datacollabel =~ m/^(begin|end|amnt\.)$/) { d567 1 a567 1 $accounts = &{$matrixdata->{"completeaccount"}}($matrixwidget, $dc, $dr, $vc, $vr, quotemeta($this->{-text})); d1235 1 a1235 1 my ($upperleftcol, $cursorcol) = (4, 0); #&rightmostvisiblefit(); @ 1.24 log @handling case where no entries currently exist moved from main to matrixwidget fixed bug where yank a line does only work on entries that were read in not newly created ones support for row deletion through matrixdeleterow() support for shrinking matrix by one row through matrixshrinkrow() improve initial screen drawing by calling draw method on wholly cui object d deletes the line visibly, no more mark for deletion @ text @d857 8 @ 1.23 log @die() handler with log to a file and popup @ text @d261 1 a261 1 -text => "