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

Re: PATCH: Shear function and useful selection operations



Ahem.  This time for sure.

--- zigzag.55	Tue Oct 27 22:55:17 1998
+++ zigzag.shearselect	Fri Oct 30 15:58:33 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,8 +172,10 @@
    "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);',
@@ -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.
 #
-