[Date Prev][Date Next][Thread Prev][Thread Next][Author Index][Date Index][Thread Index]

:zz: SHEAR MAGNIFICENCE! (Was: PATCH: Shear function and useful selection operations



I'm speechless.

Will study it and reply next week.  Looks wonderful.

Best, Ted



At 02:14 AM 10/29/98 -0500, you wrote:
>
>The enclosed patch implements the following functions:
>
>I. The `shear' function is implemented.  
>
>   A. I replaced the #Shear action cell with four related shear action
>      cells.  They are:
>
>	#Shear -^
>	#Shear -v
>	#Shear ^+
>	#Shear v+
>
>      All shear action cells operate on the vertical rank headed by
>      cursor 1.  We'll take ^+ as an example.  The + sign means that
>      the rank to be moved will have its Right links detached and
>      reattached; if it were a - we would detach the Left links
>      instead.  The ^ means that the cells will be moved down one step
>      each; if it were v we would move them up instead.  (We'll see
>      why up and down are reversed in a minute.)
>
>      Here is an example:
>
>	A1 -- B1
>        |
>        A2 -- B2
>        |
>        A3   
>        |
>        A4 -- B4
>        |
>        A5 -- B5
>
>      Suppose cursor 1 is on cell A1.  After the ^+ shear, the links
>      are like this:
>
>	A1 -- B2
>        |    
>        A2 
>        |       
>        A3 -- B4
>        |       
>        A4 -- B5
>        |       
>        A5 -- B1
>                
>      The A1...A5 have all moved down one step.  A1 is linked to the
>      cell that A2 used to be linked to.  A2 is linked to the cell
>      that A3 used to be linked to (none).  A3 is linked to the cell
>      that A4 used to be linked to, etc.  A5 has wrapped around and is
>      now linked to the cell that A1 used to be linked to.  (This
>      `wrap' behavior is optional.)
>	        
>      Since the cursor is still on A1, it looks as though the B column
>      moved up instead of the A column moving down.  That's why ^+
>      means to shear down instead of to shear up:  What you see on
>      the screen is an upward movement in the B column, even though
>      the real truth is that the A column moved down.
>
>      Caution:  If the cursor had been on A3, only the links from A3,
>      A4, and A5 would have changed.  This is because the accursed
>      cell is the *head* of the rank that shears.  The result would
>      look like this:
>
>	A1 -- B1
>        |
>        A2 -- B2
>        |       
>        A3 -- B4   
>        |       
>        A4 -- B5
>        | 
>        A5
>
>      We may want to change this behavior.  It is sometimes
>      counterintuitive.  For example, if the cursor is on A1 and we
>      shear up, nothing will happen, because A1 is already at the top
>      of the rank.  It gets disconnected from B1, and then `wraps
>      around' and reconnects to B1.
>
>   B. Shearing is implemented internally by the `do_shear' function.
>      This inaugurates a new series of functions named do_*.
>
>      do_shear accepts between three and five arguments:
>
>	do_shear($first_cell, $shear_dim, $link_dim, $n, $hang);
>
>      The last two are optional.  $first_cell is the head of the rank
>      that is sheared.  $shear_dim is the dimension in which the rank
>      extends.  For example, if $shear_dim is +d.1, then all the cells
>      +d.1ward from $first_cell will be sheared.
>
>      $link_dim is the dimension of the links that are broken and
>      relinked.  If $shear_dim is +d.1 and $link_dim is +d.2, then the
>      +d.2 links from all the cells in the sheared rank will be
>      broken, and each cell in the rank will be re-linked to the cell
>      that was formerly +d.1+d.2 from it, if there was such a cell.
>
>      $n says how many steps to shear.  If absent, it defaults to 1.
>
>      If $hang is a true value, then the last cell in the rank will be
>      left unlinked instead of wrapping around to the beginning.
>
>
>   C. The function `atcursor_shear($number, $sheardir, $linkdir)'
>      shears cells in window #$number.  The sheared cells are the
>      rank starting at cursor #$number in the $sheardir direction.
>      Their $linkdir links are detached and reattached.
>
>      $sheardir and $linkdir must each one of L, R, U, D, I, or O.
>
>II. Cell marking is improved.
>
>    A. ZigZag now supports arbitrarily many `selections'.  A selection
>       is a set of marked cells.  Initially, there is one selection,
>       called the `active selection' or `selection zero'.  The cells
>       that are considered `marked' are those in the active selection
>       and are displayed specially.
>
>    B. A cell is in the active selection when it is linked +d.markward
>       from the $SELECT_HOME, which is cell 21.  The default
>       ZigZagSpace initializes cell 21 to contain the word `Selection'.
>
>    C. The user can select or unselect a cell with the `m' and `M'
>       commands as before.  These add the accursed cell in window 1 or
>       window 0 to the active selection by inserting it +d.markward
>       from $SELECT_HOME.  If the cell is already in the active
>       selection, it is removed from the $SELECT_HOME+d.mark rank.
>
>    D. The key sequence `meta-M' creates a new selection and saves the
>       active selection in it.  It then makes the active selection
>       empty.  The new selection gets a name like `Selection #1' or
>       `Selection #2'.
>
>    E. Inactive selections are linked d.2ward from $SELECT_HOME.
>       Each has a special cell which heads a +d.markward rank which
>       includes all the cells in the selection it represents.  The
>       head cells of all the selections form a ring rank in dimension
>       d.2.
>
>    F. The key sequence `meta-m' shears the selection space d.2ward so
>       that what used to be selection #2 becomes selection #1, what
>       used to be selection #1 becomes the active selection, and what
>       used to be the active selection becomes some high-numbered
>       selection.  In this way, the user can manage several different
>       selected sets.  One selection might be the set of all the
>       Monarchs in the geneaology, and another might be the set of all
>       the cells that represent red things.  The user can make any
>       selection active with `meta-m', and can then add cells to it or
>       remove cells from it with `m' and `M'.
>
>    G. I expect that we will provide operations that apply to
>       selections.  For example ``Intersect these two selections.''
>       ``Remove all the cells in selection #X from selection #Y.''
>       ``Select all the cells in a certain rank.'' ``Select all the
>       cells that can be reached from here.''
>       
>    H. Because of the way I organized the selection structure, no cell
>       can be in two selections at once.  This is a bug.
>
>    I. I renamed all the *_mark functions to *_select.
>
>    J. There is a new function, `rotate_selection', which shears the
>       selection space +d.2wards to cycle through the selections.
>       It takes no arguments, but it does check the input buffer for a
>       number.  If present, the number says how many notches to turn
>       the selection wheel; the default is 1.
>
>    K. There is a new function, `push_selection', which creates a new
>       selection head and pushes it into the $SELECTION_HOME+d.2 rank.
>       After it does this, it shears the selection space so that the
>       old active selection is attached to the new head, and the
>       active selection head, $SELECT_HOME, is selecting nothing.
>
>    L. There is a new action note, `#Rot.Selection', which invokes the
>       `rotate_selection' command.
>
>III. Miscellaneous utilities.
>
>    A. The function `get_accursed($number)' returns the accursed cell
>       in the specified window.
>
>    B. The function `cells_row($head, $dimension)' returns a list of
>       all the cells in the rank that starts at cell $head and
>       continues in the direction specified by $dimension.  It behaves
>       properly in the presence of rings.
>
>       In scalar context, it returns the number of cells in the rank.
>
>
>
>The patch:
>
>--- zigzag.55	Tue Oct 27 22:55:17 1998
>+++ zigzag	Thu Oct 29 01:26:21 1998
>@@ -29,7 +29,7 @@
> #
> # $Log: zigzag,v $
> # Revision 0.55  1998/10/26 05:37:32  xanni
>-# Change default file extension and incorporate EDITOR selection patch
>+# Change default file extension and incorporate $EDITOR selection patch
> # from Mark-Jason Dominus <mjd@xxxxxxxxxx>
> #
> # Revision 0.54  1998/10/08 03:56:21  xanni
>@@ -88,6 +88,7 @@
> my $CELLS_PER_WIN = 5;           # Number of cells displayed across each
window
> my $CURSOR_HOME = 10;            # NOTE!  This assumes it stays fixed!
> my $DELETE_HOME = 99;            # NOTE!  This assumes it stays fixed!
>+my $SELECT_HOME = 21;            # NOTE!  This assumes it stays fixed!
> my $EDITOR = choose_editor();    
> my $FILENAME = "zigzag.zz";      # Default filename for initial slice
> my $TEMP_FILE = "/tmp/zigzag-$<-$^T"; # Filename used for external editing
>@@ -171,13 +172,15 @@
>    "N"                => 'cell_create(0);',
>    &KEY_IC            => 'cell_create(0);',
>    "n"                => 'cell_create(1);',
>-   "M"                => 'atcursor_mark(0);',
>-   "m"                => 'atcursor_mark(1);',
>+   "M"                => 'atcursor_select(0);',
>+   "m"                => 'atcursor_select(1);',
>+   &meta_key("m")     => 'rotate_selection()',
>+   &meta_key("M")     => 'push_selection()',
>    "Q"                => 'view_quadrant_toggle(0);',
>    "q"                => 'view_quadrant_toggle(1);',
>    "R"		      => 'view_reset(0);',
>    "r"		      => 'view_reset(1);',
>    "T"                => 'atcursor_clone(0);',
>    "t"                => 'atcursor_clone(1);',
>    "V"                => 'view_raster_toggle(0);',
>@@ -236,6 +239,7 @@
>    10 =>        "Cursor home",
>       "10+d.1" =>	1,
>       "10+d.2" =>	11,
>+      "10-d.1" =>	21,
>    11 =>        "Action",
>       "11+d.1" =>	12,
>       "11-d.2" =>	10,
>@@ -268,6 +272,10 @@
>       "19+d.1" =>	20,
>    20 =>        "I",
>       "20-d.1" =>	19,
>+   21 => "Selection",
>+      "21+d.1" =>       10, 
>+      "21+d.2" =>       21, 
>+      "21-d.2" =>       21, 
>    30 =>        "#Edit\natcursor_edit(1);",
>       "30+d.1" =>	35,
>       "30-d.2" =>	0,
>@@ -313,9 +321,12 @@
>       "55+d.1" =>	56,
>    56 =>        "#O-break\natcursor_break_link(1, 'O');",
>       "56-d.1" =>	55,
>-   60 =>        "#Mark\natcursor_mark(1);",
>+   60 =>        "#Select\natcursor_select(1);",
>       "60-d.2" =>	50,
>       "60+d.2" =>	70,
>+      "60+d.1" =>       61,
>+   61 =>        "#Rot.Selection\nrotate_selection();",
>+      "61-d.1" =>       60,
>    70 =>        "#L-Hop\natcursor_hop(1, 'L');",
>       "70+d.1" =>	71,
>       "70-d.2" =>	60,
>@@ -334,9 +345,18 @@
>       "74+d.1" =>	75,
>    75 =>        "#O-Hop\natcursor_hop(1, 'O');",
>       "75-d.1" =>	74,
>-   80 =>        "#Shear",
>+   80 =>        "#Shear -^\natcursor_shear(1, 'D', 'L')",
>       "80-d.2" =>	70,
>       "80+d.2" =>	85,
>+      "80+d.1" =>       81,
>+   81 =>        "#Shear -v\natcursor_shear(1, 'U', 'L')",
>+      "81-d.1" =>       80,
>+      "81+d.1" =>       82,
>+   82 =>        "#Shear ^+\natcursor_shear(1, 'D', 'R')",
>+      "82-d.1" =>       81,
>+      "82+d.1" =>       83,
>+   83 =>        "#Shear v+\natcursor_shear(1, 'U', 'R')",
>+      "83-d.1" =>       82,
>    85 =>        "#Chug",
>       "85-d.2" =>	80,
>       "85+d.2" =>	90,
>@@ -427,10 +447,11 @@
>    return (defined($ZZ{"$cell-d.clone"}) || defined($ZZ{"$cell+d.clone"}));
> }
> 
>-sub is_marked($)
>+sub is_selected($)
> {
>   my $cell = shift;
>-  return (defined($ZZ{"$cell-d.mark"}) || defined($ZZ{"$cell+d.mark"}));
>+  my $headcell = get_lastcell($cell, '-d.mark');
>+  return $headcell == $SELECT_HOME && $cell != $SELECT_HOME;
> }
> 
> 
>@@ -454,6 +475,15 @@
> # Retrieving Information
> # Named get_*
> #
>+
>+sub get_accursed($)
>+# Get the cell that is accursed in the specified window
>+# or by the specified cursor
>+{
>+  my $n = shift;
>+  &get_lastcell(&get_cursor($n), "-d.cursor");
>+}
>+
> sub get_lastcell($$)
> # Find the last cell along a given dimension
> {
>@@ -625,6 +655,79 @@
>   return @_;
> }
> 
>+#
>+# Multiple-cell operations
>+# Named do_*
>+#
>+sub do_shear($$$;$$) 
>+# Given a row of cells starting at $first_cell,
>+# move them all $n cells in the $dir direction.
>+# Cells that were linked in the $link direction
>+# have their links broken and relinked to new cells.
>+#
>+# Before: do_shear(A1, d.1, d.2, 1);
>+# 
>+# ---> d.1
>+# V d.2
>+#
>+# A1 --- B1 --- C1 --- D1 --- E1
>+# |      |             |      |
>+# A2     B2     C2     D2     E2
>+#
>+# After:
>+#
>+#        A1 --- B1 --- C1 --- D1 --- E1
>+#        |      |             |
>+# A2     B2     C2     D2     E2
>+#
>+# Optional fourth argument $n defaults to 1.
>+# Optional fifth argument $hang says whether the cell on the end
>+# should be linked back at the beginning or whether it should just
>+# be left hanging.  $hang=false: Back at beginning.  
>+# $hang = true: Leave hanging.  Default: false.
>+{
>+  my ($first_cell, $dir, $link, $n, $hang) = @_;
>+  $n = 1 unless defined $n;
>+  $hang = 0 unless defined $hang;
>+
>+  my $cell;
>+  my ($prev_cell, $prev_linked);
>+  my $first_linked = $ZZ{"$first_cell$link"};
>+
>+  my @shear_cells = &cells_row($first_cell, $dir);
>+  my @linked_cells = map {$ZZ{"$_$link"}} @shear_cells;
>+
>+  my @new_link = @linked_cells;
>+  # Move some of these from the beginning
>+  my @x = splice(@new_link, 0, $n);
>+  # And put them back at the end.
>+  push @new_link, @x;
>+
>+  my $i;
>+  my $linkno = 0;
>+  my $last_linked;
>+  # Break all the links
>+  for ($i=0; $i < @shear_cells; $i++) {
>+    my $old_link = $linked_cells[$i];
>+    next unless defined $old_link;
>+    my $shear_cell = $shear_cells[$i];
>+    link_break($shear_cell, $old_link, $link);
>+  }
>+
>+  $linkno = 0;
>+  for ($i=0; $i < @shear_cells; $i++) {
>+    my $new_link = $new_link[$i];
>+    next unless defined $new_link;
>+    next if $i == $#shear_cells && $hang;
>+    my $shear_cell = $shear_cells[$i];
>+    link_make($shear_cell,  $new_link, $link);
>+  }
>+
>+  foreach (@Window_Dirty)
>+  {
>+     $_ = $TRUE;
>+  }
>+}
> 
> #
> # Functions that operate on links between cells
>@@ -841,25 +944,52 @@
>   }
> }
> 
>-sub atcursor_mark($)
>-# mark the current cell
>+sub atcursor_select($)
>+# select or unselect the current cell
> {
>   my $curs = &get_cursor($_[0]);
>   my $cell = &get_lastcell($curs, "-d.cursor");
> 
>-  my $new = $ZZ{"n"}++;
>-  $ZZ{$new} = "mark";
>-  &cell_insert($new, $cell, "+d.mark");
>-  &status_draw("Marked cell $cell");
>+  if (&is_selected($cell)) {
>+    &cell_excise($cell, "d.mark");
>+    &status_draw("Selected cell $cell");
>+  } else {
>+    &cell_insert($cell, $SELECT_HOME, "+d.mark");
>+    &status_draw("Selected cell $cell");
>+  }
>   #&cursor_move_dimension($curs, "+d.mark");
> 
>-
>   foreach (@Window_Dirty)
>   {
>      $_ = $TRUE;
>   }
> }
> 
>+sub rotate_selection () 
>+# Exchange the current selection with one of the saved selections.  If
>+# there's an input buffer, it holds the number of the desired
>+# selection, so shear all the selections +d.2ward by that many.
>+# (Selection #0 is currently active.)  Otherwise, just shear by 1.
>+{
>+  my $shear_count = (defined($Input_Buffer) ? $Input_Buffer : 1);
>+#  my $num_selections = &cells_row($SELECT_HOME, "+d.2");
>+  
>+  do_shear($SELECT_HOME, '-d.2', '+d.mark', $shear_count);
>+}
>+
>+sub push_selection()
>+# Push the current selection onto the selection stack.
>+# All saved selections move +d.2ward one step.
>+# The current selection is now empty.
>+{  
>+  my $new_sel = $ZZ{"n"}++;
>+  my $num_selections = &cells_row($SELECT_HOME, "+d.2");
>+  $ZZ{$new_sel} = "Selection #$num_selections";
>+  cell_insert($new_sel, $SELECT_HOME, "+d.2");
>+  do_shear($SELECT_HOME, "+d.2", "+d.mark", 1);
>+}
>+
>+
> sub atcursor_insert($$)
> # Insert a new cell at a given cursor in a given direction
> {
>@@ -988,6 +1118,25 @@
>   }
> }
> 
>+sub atcursor_shear($$$)
>+# Arguments: $curs = cursor/window number
>+# $sheardir = direction and +/-
>+# $linkdir = direction and +/-
>+# directions name axes.  They get turned into dimensions
>+# for the do_shear call.
>+# Head cell of the shear is the accursed cell
>+{
>+  my ($number, $shear_dir, $link_dir) = @_;
>+
>+  my $cursor = &get_cursor($number);
>+  my $shear_dim = &get_dimension($cursor, $shear_dir);
>+  my $link_dim  = &get_dimension($cursor, $link_dir);
>+
>+  my $headcell = &get_accursed($number);
>+
>+  &do_shear($headcell, $shear_dim, $link_dim, 1);
>+}
>+
> sub atcursor_edit($)
> # Invoke an external text editor to edit the cell under a given cursor
> {
>@@ -1156,6 +1305,22 @@
>   unlink $TEMP_FILE;
> }
> 
>+sub cells_row($$) 
>+# Final all the cells in the row starting from $cell
>+# in the $dir dimension.  Return a list or a count
>+# depending on calling context.
>+{
>+  my ($cell1, $dir) = @_;
>+  my $cell;
>+  my @result = ($cell1);
>+  for ($cell = $ZZ{"$cell1$dir"}; 
>+       defined($cell) && $cell != $cell1; 
>+       $cell = $ZZ{"$cell$dir"}
>+      ) {
>+    push @result, $cell;
>+  }
>+  @result;
>+}
> 
> #
> # Functions that operate on the whole screen
>@@ -1299,8 +1464,8 @@
>   if (!$LOTS_OF_COLOURS && &is_clone($cell))
>   { addch($win, $row - 1, $col, "c"); }
> 
>-  # Display marked-cell flag if we aren't using lots of colours
>-  if (!$LOTS_OF_COLOURS && &is_marked($cell))
>+  # Display selected-cell flag if we aren't using lots of colours
>+  if (!$LOTS_OF_COLOURS && &is_selected($cell))
>   { addch($win, $row - 1, $col, "m"); }
> 
>   # Display dimension guide
>@@ -1509,9 +1674,9 @@
>   # Clone cells get a special colour in high-colour mode
>   attron($win, COLOR_PAIR(2) | A_BOLD) 
>     if $LOTS_OF_COLOURS && &is_clone($cell);
>-  # Ditto marked cells
>+  # Ditto selected cells
>   attron($win, COLOR_PAIR(3) | A_BOLD) 
>-    if $LOTS_OF_COLOURS && &is_marked($cell);
>+    if $LOTS_OF_COLOURS && &is_selected($cell);
> 
>   # Colour/highlight the cursors
>   attron($win, $Display_Has_Colour ? COLOR_PAIR(6) : A_UNDERLINE) if
$number == 1;
>@@ -1907,4 +2072,3 @@
> #
> # End.
> #
>-
>
>
>
>
>
>
____________________________________________________
Theodor Holm Nelson, Visiting Professor of Environmental Information
 Keio University, Shonan Fujisawa Campus, Fujisawa, Japan
 Home Fax from USA: 011-81-466-46-7368  (If in Japan, 0466-46-7368)
Professorial home page http://www.sfc.keio.ac.jp/~ted/ 
_____________________________________________________
Permanent: Project Xanadu, 3020 Bridgeway #295, Sausalito CA 94965
 Tel. 415/ 331-4422, fax 415/332-0136  
http://www.xanadu.net
PERMANENT E-MAIL: ted@xxxxxxxxxx
_____________________________________________________
Quotation of the day, 98.10.29:
Last words of Oscar Wilde: "Either that wallpaper goes, or I do."