[sane-devel] [Suggestion/Patch] xsane-preview: select scann area with given proportions

Peter Seiderer Peter.Seiderer@ciselant.de
Mon, 15 Apr 2002 12:09:19 +0200


--n8g4imXOkfNTN/H1
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hello,
this is a suggestion for adding a new feature to xsane preview window.

I think it would be a nice feature to have the ability to determine a
given proportion of the selected scan area in the preview window,
e.g. 3:4, 4:3 for 1024x768 result pictures or 1:1 for quadratic results etc..

Attached a little patch with an first version for this feature.

Is there a possibility to set the cursor to a given position
in the window in gtk/gdk?

Any further suggestions/advices?

Peter

-- 
------------------------------------------------------------------------
Peter Seiderer                     E-Mail:  Peter.Seiderer@ciselant.de

--n8g4imXOkfNTN/H1
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="patch-preview_selection_proportion-0.1"

diff -ru xsane-0.85_orig/src/xsane-preview.c xsane-0.85/src/xsane-preview.c
--- xsane-0.85_orig/src/xsane-preview.c	Mon Apr 15 09:41:27 2002
+++ xsane-0.85/src/xsane-preview.c	Mon Apr 15 11:48:33 2002
@@ -180,6 +180,7 @@
 static gint preview_preset_area_move_down_callback(GtkWidget *widget, GtkWidget *preset_area_widget);
 static gint preview_preset_area_context_menu_callback(GtkWidget *widget, GdkEvent *event);
 static void preview_preset_area_callback(GtkWidget *widget, gpointer call_data);
+static void preview_selection_proportion_callback(GtkWidget *widget, gpointer call_data);
 static void preview_rotation_callback(GtkWidget *widget, gpointer call_data);
 static void preview_autoselect_scanarea_callback(GtkWidget *window, gpointer data);
 
@@ -550,7 +551,7 @@
       p->selection.coordinate[p->index_xmin] = p->selection.coordinate[p->index_xmax];
       p->selection.coordinate[p->index_xmax] = tmp_coordinate;
 
-      p->selection_xedge = (p->selection_xedge + 2) & 3;
+      p->selection_xedge = (p->selection_xedge + 2) % 4;
     }
 
     if (p->selection.coordinate[p->index_ymin] > p->selection.coordinate[p->index_ymax])
@@ -559,7 +560,7 @@
       p->selection.coordinate[p->index_ymin] = p->selection.coordinate[p->index_ymax];
       p->selection.coordinate[p->index_ymax] = tmp_coordinate;
 
-      p->selection_yedge = (p->selection_yedge + 2) & 3;
+      p->selection_yedge = (p->selection_yedge + 2) % 4;
     }
   }
 }
@@ -2418,6 +2419,12 @@
 }
 
 /* ---------------------------------------------------------------------------------------------------------------------- */
+#define CURSOR_IN_LEFT_RANGE   ((preview_selection[0]-SELECTION_RANGE_OUT<event->button.x)&&(event->button.x<preview_selection[0]+SELECTION_RANGE_IN))
+#define CURSOR_IN_TOP_RANGE    ((preview_selection[1]-SELECTION_RANGE_OUT<event->button.y)&&(event->button.y<preview_selection[1]+SELECTION_RANGE_IN))
+#define CURSOR_IN_RIGHT_RANGE  ((preview_selection[2]-SELECTION_RANGE_IN<event->button.x)&&(event->button.x<preview_selection[2]+SELECTION_RANGE_OUT))
+#define CURSOR_IN_BOTTOM_RANGE ((preview_selection[3]-SELECTION_RANGE_IN<event->button.y)&&(event->button.y<preview_selection[3]+SELECTION_RANGE_OUT))
+#define CURSOR_IN_HEIGHT_RANGE ((event->button.y>preview_selection[1])&&(event->button.y<preview_selection[3]))
+#define CURSOR_IN_WIDTH_RANGE  ((event->button.x>preview_selection[0])&&(event->button.x<preview_selection[2]))
 
 static gint preview_motion_event_handler(GtkWidget *window, GdkEvent *event, gpointer data)
 {
@@ -2442,122 +2449,126 @@
   {
     switch (((GdkEventMotion *)event)->state &
             GDK_Num_Lock & GDK_Caps_Lock & GDK_Shift_Lock & GDK_Scroll_Lock) /* mask all Locks */
-    {
+      {
       case 256: /* left button */
-
+	
         DBG(DBG_info2, "left button\n");
-
+	
         if ( (p->selection_drag) || (p->selection_drag_edge) )
-        {
-          p->selection.active = TRUE;
-          p->selection.coordinate[p->selection_xedge] = preview_x;
-          p->selection.coordinate[p->selection_yedge] = preview_y;
-
-          preview_order_selection(p);
-          preview_bound_selection(p);
-
-          if (preferences.gtk_update_policy == GTK_UPDATE_CONTINUOUS)
-          {
-            if (!p->hold_timer) /* hold timer active? then remove it, we had a motion */
-            {
-              p->hold_timer = gtk_timeout_add(XSANE_CONTINUOUS_HOLD_TIME, preview_hold_event_handler, (gpointer *) p);
-            }
-            preview_update_maximum_output_size(p);
-            preview_draw_selection(p);
-          }
-          else if (preferences.gtk_update_policy == GTK_UPDATE_DELAYED)
-          {
-            /* call preview_hold_event_hanlder if mouse is not moved for ??? ms */
-            if (p->hold_timer) /* hold timer active? then remove it, we had a motion */
-            {
-              gtk_timeout_remove(p->hold_timer);
-              p->hold_timer = 0;
-            }
-            p->hold_timer = gtk_timeout_add(XSANE_HOLD_TIME, preview_hold_event_handler, (gpointer *) p);
-            preview_update_maximum_output_size(p);
-            preview_draw_selection(p);
-          }
-          else /* discontinuous */
-          {
-            preview_update_maximum_output_size(p);
-            preview_draw_selection(p); /* only draw selection, do not update backend geometry options */
-          }
-        }
+	  {
+	    p->selection.active = TRUE;
+	    if ( p->selection_proportion == -1.0 ) {
+	      /* unbound */
+	      p->selection.coordinate[p->selection_xedge] = preview_x;
+	      p->selection.coordinate[p->selection_yedge] = preview_y;
+	      preview_order_selection(p);
+	      preview_bound_selection(p);
+	    } else {
+	      int width;
+	      int height;
+	      
+	      if ( p->selection.coordinate[p->selection_xedge] != preview_x ) {
+		p->selection.coordinate[p->selection_xedge] = preview_x;
+		width = p->selection.coordinate[p->selection_xedge] - p->selection.coordinate[(p->selection_xedge+2)%4];
+		height = width / p->selection_proportion;
+		p->selection.coordinate[p->selection_yedge] = p->selection.coordinate[(p->selection_yedge+2)%4] + height;
+	      } else {
+		p->selection.coordinate[p->selection_yedge] = preview_y;
+		height = p->selection.coordinate[p->selection_yedge] - p->selection.coordinate[(p->selection_yedge+2)%4];
+		width = height * p->selection_proportion;
+		p->selection.coordinate[p->selection_xedge] = p->selection.coordinate[(p->selection_xedge+2)%4] + width;
+	      }
+	      /* XXXXX set cursor to calcualted position !!!!!!!!! */
+	      preview_order_selection(p);
+	      preview_bound_selection(p);
+	    }
+	    
+	    if (preferences.gtk_update_policy == GTK_UPDATE_CONTINUOUS)
+	      {
+		if (!p->hold_timer) /* hold timer active? then remove it, we had a motion */
+		  {
+		    p->hold_timer = gtk_timeout_add(XSANE_CONTINUOUS_HOLD_TIME, preview_hold_event_handler, (gpointer *) p);
+		  }
+		preview_update_maximum_output_size(p);
+		preview_draw_selection(p);
+	      }
+	    else if (preferences.gtk_update_policy == GTK_UPDATE_DELAYED)
+	      {
+		/* call preview_hold_event_hanlder if mouse is not moved for ??? ms */
+		if (p->hold_timer) /* hold timer active? then remove it, we had a motion */
+		  {
+		    gtk_timeout_remove(p->hold_timer);
+		    p->hold_timer = 0;
+		  }
+		p->hold_timer = gtk_timeout_add(XSANE_HOLD_TIME, preview_hold_event_handler, (gpointer *) p);
+		preview_update_maximum_output_size(p);
+		preview_draw_selection(p);
+	      }
+	    else /* discontinuous */
+	      {
+		preview_update_maximum_output_size(p);
+		preview_draw_selection(p); /* only draw selection, do not update backend geometry options */
+	      }
+	  }
 
         cursornr = p->cursornr;
-
-        if ( (p->selection_xedge != -1) && (p->selection_yedge != -1) ) /* move corner */
-        {
-          if ( ( (preview_selection[0] - SELECTION_RANGE_OUT < event->button.x) &&
-                 (event->button.x < preview_selection[0] + SELECTION_RANGE_IN) ) && /* left  */
-               ( (preview_selection[1] - SELECTION_RANGE_OUT < event->button.y) &&
-                 (event->button.y < preview_selection[1] + SELECTION_RANGE_IN) ) ) /* top */
-          {
-            cursornr = GDK_TOP_LEFT_CORNER;
-          }
-          else if ( ( (preview_selection[2] - SELECTION_RANGE_IN < event->button.x) &&
-                      (event->button.x < preview_selection[2] + SELECTION_RANGE_OUT) ) && /* right */
-                    ( (preview_selection[1] - SELECTION_RANGE_OUT < event->button.y) &&
-                      (event->button.y < preview_selection[1] + SELECTION_RANGE_IN) ) ) /* top */
-          {
-            cursornr = GDK_TOP_RIGHT_CORNER;
-          }
-          else if ( ( (preview_selection[0] - SELECTION_RANGE_OUT < event->button.x) &&
-                      (event->button.x < preview_selection[0] + SELECTION_RANGE_IN) ) && /* left  */
-                    ( (preview_selection[3] - SELECTION_RANGE_IN < event->button.y) &&
-                      (event->button.y < preview_selection[3] + SELECTION_RANGE_OUT) ) ) /* bottom */
-          {
-            cursornr = GDK_BOTTOM_LEFT_CORNER;
-          }
-          else if ( ( (preview_selection[2] - SELECTION_RANGE_IN < event->button.x) &&
-                      (event->button.x < preview_selection[2] + SELECTION_RANGE_OUT) ) && /* right */
-                    ( (preview_selection[3] - SELECTION_RANGE_IN < event->button.y) &&
-                      (event->button.y < preview_selection[3] + SELECTION_RANGE_OUT) ) ) /* bottom */
-          {
-            cursornr = GDK_BOTTOM_RIGHT_CORNER;
-          }
-        }
-        else if ( (preview_selection[0] - SELECTION_RANGE_OUT < event->button.x) &&
-                  (event->button.x < preview_selection[0] + SELECTION_RANGE_IN) ) /* left */
-        {
-          if (cursornr == GDK_RIGHT_SIDE)
-          {
-            cursornr = GDK_LEFT_SIDE;
-          }
-        }
-        else if ( (preview_selection[2] - SELECTION_RANGE_IN < event->button.x) &&
-                  (event->button.x < preview_selection[2] + SELECTION_RANGE_OUT) )  /* right */
-        {
-          if (cursornr == GDK_LEFT_SIDE)
-          {
-            cursornr = GDK_RIGHT_SIDE;
-          }
-        }
-        else if ( (preview_selection[1] - SELECTION_RANGE_OUT < event->button.y) &&
-                  (event->button.y < preview_selection[1] + SELECTION_RANGE_IN) )  /* top */
-        {
-          if (cursornr == GDK_BOTTOM_SIDE)
-          {
-            cursornr = GDK_TOP_SIDE;
-          }
-        }
-        else if ( (preview_selection[3] - SELECTION_RANGE_IN < event->button.y) &&
-                    (event->button.y < preview_selection[3] + SELECTION_RANGE_OUT) )  /* bottom */
-        {
-          if (cursornr == GDK_TOP_SIDE)
-          {
-            cursornr = GDK_BOTTOM_SIDE;
-          }
-        }
+	
+	if ( (p->selection_xedge != -1) && (p->selection_yedge != -1) ) /* move corner */
+	  {
+	    if ( CURSOR_IN_LEFT_RANGE && CURSOR_IN_TOP_RANGE )
+	      {
+		cursornr = GDK_TOP_LEFT_CORNER;
+	      }
+	    else if ( CURSOR_IN_RIGHT_RANGE && CURSOR_IN_TOP_RANGE )
+	      {
+		cursornr = GDK_TOP_RIGHT_CORNER;
+	      }
+	    else if ( CURSOR_IN_LEFT_RANGE && CURSOR_IN_BOTTOM_RANGE )
+	      {
+		cursornr = GDK_BOTTOM_LEFT_CORNER;
+	      }
+	    else if ( CURSOR_IN_RIGHT_RANGE && CURSOR_IN_BOTTOM_RANGE )
+	      {
+		cursornr = GDK_BOTTOM_RIGHT_CORNER;
+	      }
+	  }
+        else if ( CURSOR_IN_LEFT_RANGE )
+	  {
+	    if (cursornr == GDK_RIGHT_SIDE)
+	      {
+		cursornr = GDK_LEFT_SIDE;
+	      }
+	  }
+        else if ( CURSOR_IN_RIGHT_RANGE )
+	  {
+	    if (cursornr == GDK_LEFT_SIDE)
+	      {
+		cursornr = GDK_RIGHT_SIDE;
+	      }
+	  }
+        else if ( CURSOR_IN_TOP_RANGE )
+	  {
+	    if (cursornr == GDK_BOTTOM_SIDE)
+	      {
+		cursornr = GDK_TOP_SIDE;
+	      }
+	  }
+        else if ( CURSOR_IN_BOTTOM_RANGE )
+	  {
+	    if (cursornr == GDK_TOP_SIDE)
+	      {
+		cursornr = GDK_BOTTOM_SIDE;
+	      }
+	  }
 
         if (cursornr != p->cursornr)
-        {
-          cursor = gdk_cursor_new(cursornr);	/* set curosr */
-          gdk_window_set_cursor(p->window->window, cursor);
-          gdk_cursor_unref(cursor);
-          p->cursornr = cursornr;
-        }
-       break;
+	  {
+	    cursor = gdk_cursor_new(cursornr);	/* set curosr */
+	    gdk_window_set_cursor(p->window->window, cursor);
+	    gdk_cursor_unref(cursor);
+	    p->cursornr = cursornr;
+	  }
+	break;
 
       case 512: /* middle button */
       case 1024: /* right button */
@@ -2669,62 +2680,42 @@
        break;
 
       default:
-        if ( ( (preview_selection[0] - SELECTION_RANGE_OUT < event->button.x) &&
-               (event->button.x < preview_selection[0] + SELECTION_RANGE_IN) ) && /* left  */
-             ( (preview_selection[1] - SELECTION_RANGE_OUT < event->button.y) &&
-               (event->button.y < preview_selection[1] + SELECTION_RANGE_IN) ) ) /* top */
-        {
-          cursornr = GDK_TOP_LEFT_CORNER;
-        }
-        else if ( ( (preview_selection[2] - SELECTION_RANGE_IN < event->button.x) &&
-                    (event->button.x < preview_selection[2] + SELECTION_RANGE_OUT) ) && /* right */
-                  ( (preview_selection[1] - SELECTION_RANGE_OUT < event->button.y) &&
-                    (event->button.y < preview_selection[1] + SELECTION_RANGE_IN) ) ) /* top */
-        {
-          cursornr = GDK_TOP_RIGHT_CORNER;
-        }
-        else if ( ( (preview_selection[0] - SELECTION_RANGE_OUT < event->button.x) &&
-                    (event->button.x < preview_selection[0] + SELECTION_RANGE_IN) ) && /* left  */
-                  ( (preview_selection[3] - SELECTION_RANGE_IN < event->button.y) &&
-                    (event->button.y < preview_selection[3] + SELECTION_RANGE_OUT) ) ) /* bottom */
-        {
-          cursornr = GDK_BOTTOM_LEFT_CORNER;
-        }
-        else if ( ( (preview_selection[2] - SELECTION_RANGE_IN < event->button.x) &&
-                    (event->button.x < preview_selection[2] + SELECTION_RANGE_OUT) ) && /* right */
-                  ( (preview_selection[3] - SELECTION_RANGE_IN < event->button.y) &&
-                    (event->button.y < preview_selection[3] + SELECTION_RANGE_OUT) ) ) /* bottom */
-        {
-          cursornr = GDK_BOTTOM_RIGHT_CORNER;
-        }
-        else if ( ( (preview_selection[0] - SELECTION_RANGE_OUT < event->button.x) &&
-                    (event->button.x < preview_selection[0] + SELECTION_RANGE_IN) ) &&  /* left */
-                  ( (event->button.y > preview_selection[1]) && (event->button.y < preview_selection[3]) ) ) /* in height */
-        {
-           cursornr = GDK_LEFT_SIDE;
-        }
-        else if ( ( (preview_selection[2] - SELECTION_RANGE_IN < event->button.x) &&
-                    (event->button.x < preview_selection[2] + SELECTION_RANGE_OUT) ) &&  /* right */
-                  ( (event->button.y > preview_selection[1]) && (event->button.y < preview_selection[3]) ) ) /* in height */
-        {
-           cursornr = GDK_RIGHT_SIDE;
-        }
-        else if ( ( (preview_selection[1] - SELECTION_RANGE_OUT < event->button.y) &&
-                    (event->button.y < preview_selection[1] + SELECTION_RANGE_IN) ) &&  /* top */
-                  ( (event->button.x > preview_selection[0]) && (event->button.x < preview_selection[2]) ) ) /* in width */
-        {
-           cursornr = GDK_TOP_SIDE;
-        }
-        else if ( ( (preview_selection[3] - SELECTION_RANGE_IN < event->button.y) &&
-                    (event->button.y < preview_selection[3] + SELECTION_RANGE_OUT) ) &&  /* bottom */
-                  ( (event->button.x > preview_selection[0]) && (event->button.x < preview_selection[2]) ) ) /* in width */
-        {
-           cursornr = GDK_BOTTOM_SIDE;
-        }
+        if ( CURSOR_IN_LEFT_RANGE && CURSOR_IN_TOP_RANGE )
+	  {
+	    cursornr = GDK_TOP_LEFT_CORNER;
+	  }
+        else if ( CURSOR_IN_RIGHT_RANGE && CURSOR_IN_TOP_RANGE )
+	  {
+	    cursornr = GDK_TOP_RIGHT_CORNER;
+	  }
+        else if ( CURSOR_IN_LEFT_RANGE && CURSOR_IN_BOTTOM_RANGE )
+	  {
+	    cursornr = GDK_BOTTOM_LEFT_CORNER;
+	  }
+        else if ( CURSOR_IN_RIGHT_RANGE && CURSOR_IN_BOTTOM_RANGE )
+	  {
+	    cursornr = GDK_BOTTOM_RIGHT_CORNER;
+	  }
+        else if ( CURSOR_IN_LEFT_RANGE && CURSOR_IN_HEIGHT_RANGE )
+	  {
+	    cursornr = GDK_LEFT_SIDE;
+	  }
+        else if ( CURSOR_IN_RIGHT_RANGE && CURSOR_IN_HEIGHT_RANGE )
+	  {
+	    cursornr = GDK_RIGHT_SIDE;
+	  }
+        else if ( CURSOR_IN_TOP_RANGE && CURSOR_IN_WIDTH_RANGE )
+	  {
+	    cursornr = GDK_TOP_SIDE;
+	  }
+        else if ( CURSOR_IN_BOTTOM_RANGE && CURSOR_IN_WIDTH_RANGE )
+	  {
+	    cursornr = GDK_BOTTOM_SIDE;
+	  }
         else
-        {
-          cursornr = XSANE_CURSOR_PREVIEW;
-        }
+	  {
+	    cursornr = XSANE_CURSOR_PREVIEW;
+	  }
 
         if ((cursornr != p->cursornr) && (p->cursornr != -1))
         {
@@ -3076,32 +3067,28 @@
               DBG(DBG_info, "left button\n");
 
               p->selection_xedge = -1;
-              if ( (preview_selection[0] - SELECTION_RANGE_OUT < event->button.x) &&
-                   (event->button.x < preview_selection[0] + SELECTION_RANGE_IN) ) /* left */
-              {
-                DBG(DBG_info, "-left\n");
-                p->selection_xedge = 0;
-              }
-              else if ( (preview_selection[2] - SELECTION_RANGE_IN < event->button.x) &&
-                        (event->button.x < preview_selection[2] + SELECTION_RANGE_OUT) ) /* right */
-              {
-                DBG(DBG_info, "-right\n");
-                p->selection_xedge = 2;
-              }
+              if ( CURSOR_IN_LEFT_RANGE )
+		{
+		  DBG(DBG_info, "-left\n");
+		  p->selection_xedge = 0;
+		}
+              else if ( CURSOR_IN_RIGHT_RANGE )
+		{
+		  DBG(DBG_info, "-right\n");
+		  p->selection_xedge = 2;
+		}
 
               p->selection_yedge = -1;
-              if ( (preview_selection[1] - SELECTION_RANGE_OUT < event->button.y) &&
-                   (event->button.y < preview_selection[1] + SELECTION_RANGE_IN) ) /* top */
-              {
-                DBG(DBG_info, "-top\n");
-                p->selection_yedge = 1;
-              }
-              else if ( (preview_selection[3] - SELECTION_RANGE_IN < event->button.y) &&
-                        (event->button.y < preview_selection[3] + SELECTION_RANGE_OUT) ) /* bottom */
-              {
-                DBG(DBG_info, "-bottom\n");
-                p->selection_yedge = 3;
-              }
+              if ( CURSOR_IN_TOP_RANGE )
+		{
+		  DBG(DBG_info, "-top\n");
+		  p->selection_yedge = 1;
+		}
+              else if ( CURSOR_IN_BOTTOM_RANGE )
+		{
+		  DBG(DBG_info, "-bottom\n");
+		  p->selection_yedge = 3;
+		}
 
               if ( (p->selection_xedge != -1) && (p->selection_yedge != -1) ) /* move corner */
               {
@@ -3372,6 +3359,44 @@
   gtk_widget_queue_draw(p->preset_area_option_menu);
 }
 
+typedef struct selection_proportion_s {
+  char *name;
+  float value;
+} selection_proportion_t;
+
+#define NR_SELECTION_PROPORTIONS 4
+
+static selection_proportion_t selection_proportions[NR_SELECTION_PROPORTIONS] =
+{ {"unbound", -1.0 },
+  {"1:1",      1.0 },
+  {"3:4",      (3.0 / 4.0)},
+  {"4:3",      (4.0 / 3.0)}
+};
+
+static void
+preview_create_selection_proportion_menu(Preview *p, int selected)
+{
+  GtkWidget *selection_proportion_menu, *menu_item;
+  int i;
+
+  selection_proportion_menu = gtk_menu_new();
+
+  for ( i = 0; i < NR_SELECTION_PROPORTIONS; i++ ) {
+    menu_item = gtk_menu_item_new_with_label(selection_proportions[i].name);
+    gtk_container_add(GTK_CONTAINER(selection_proportion_menu), menu_item);
+    g_signal_connect(GTK_OBJECT(menu_item), "activate", (GtkSignalFunc) preview_selection_proportion_callback, p);
+    gtk_object_set_data(GTK_OBJECT(menu_item), "Selection",  (void *) i);  
+    gtk_object_set_data(GTK_OBJECT(menu_item), "Preview",    (void *) p);
+    gtk_object_set_data(GTK_OBJECT(menu_item), "Proportion", (void *) (&selection_proportions[i].value));
+    gtk_widget_show(menu_item);
+  }
+  
+  gtk_option_menu_set_menu(GTK_OPTION_MENU(p->preview_selection_proportion_menu), selection_proportion_menu);
+  gtk_option_menu_set_history(GTK_OPTION_MENU(p->preview_selection_proportion_menu), selected);
+  gtk_widget_show(selection_proportion_menu);
+  gtk_widget_queue_draw(p->preview_selection_proportion_menu);
+}
+
 /* ---------------------------------------------------------------------------------------------------------------------- */
 
 void preview_generate_preview_filenames(Preview *p)
@@ -3494,6 +3519,8 @@
   p->preview_colors = -1;
   p->invalid = TRUE; /* no valid preview */
 
+  p->selection_proportion = -1.0; /* unbound selection proportion */
+
 #ifndef XSERVER_WITH_BUGGY_VISUALS
   gtk_widget_push_visual(gtk_preview_get_visual()); /* this has no function for gtk+-2.0 */
 #endif
@@ -3562,6 +3589,12 @@
   p->preset_area_option_menu = preset_area_option_menu;
   preview_create_preset_area_menu(p, 0); /* build menu and set default to 0=full size */
 
+  /* select preview selection proportion */
+  p->preview_selection_proportion_menu = gtk_option_menu_new();
+  xsane_back_gtk_set_tooltip(xsane.tooltips, p->preview_selection_proportion_menu, DESC_SELECTION_PROPORTION);
+  gtk_box_pack_start(GTK_BOX(p->button_box), p->preview_selection_proportion_menu, FALSE, FALSE, 0);
+  gtk_widget_show(p->preview_selection_proportion_menu);
+  preview_create_selection_proportion_menu(p, 0); /* default to 0=unbound */
 
   /* select rotation */
   rotation_menu = gtk_menu_new();
@@ -5046,6 +5079,24 @@
 
   preview_update_surface(p, 0);
   preview_zoom_not(NULL, p);
+}
+
+static void
+preview_selection_proportion_callback(GtkWidget *widget, gpointer call_data)
+{
+  Preview *p = call_data;
+  float proportion;
+  
+  DBG(DBG_proc, "preview_selection_proportion_callback\n");
+  
+  proportion = *((float *) gtk_object_get_data(GTK_OBJECT(widget), "Proportion"));
+
+  DBG(DBG_proc, " - porportion = %f\n", proportion);
+
+  if ( p->selection_proportion != proportion ) {
+    p->selection_proportion = proportion;
+    /* XXXXX adjust actual selection to proportion !!!!!!!!!!! */
+  }
 }
 
 /* ---------------------------------------------------------------------------------------------------------------------- */
diff -ru xsane-0.85_orig/src/xsane-preview.h xsane-0.85/src/xsane-preview.h
--- xsane-0.85_orig/src/xsane-preview.h	Mon Apr 15 09:41:27 2002
+++ xsane-0.85/src/xsane-preview.h	Mon Apr 15 11:24:29 2002
@@ -138,7 +138,9 @@
   int selection_ypos;
   int selection_xedge;
   int selection_yedge;
-
+  
+  float selection_proportion;
+  
   Tselection selection;				/* selected area to scan */
   Tselection previous_selection;		/* previous ... */
   Tselection selection_maximum;			/* maximum selection size (photocopy) */
@@ -169,6 +171,7 @@
   GtkWidget *autoraise;		/* autoraise scanarea */
   GtkWidget *autoselect;	/* autoselect scanarea */
   GtkWidget *preset_area_option_menu;	/* menu for selection of preview area */
+  GtkWidget *preview_selection_proportion_menu; /* menu for proportion of selection of preview area */
   GtkWidget *rotation_option_menu;	/* menu for selection of rotation */
   GtkWidget *scanning_pixmap;	/* pixmap that shows preview is in scanning progress */
   GtkWidget *valid_pixmap;	/* pixmap that shows preview is valid */
diff -ru xsane-0.85_orig/src/xsane-text.h xsane-0.85/src/xsane-text.h
--- xsane-0.85_orig/src/xsane-text.h	Mon Apr 15 09:41:28 2002
+++ xsane-0.85/src/xsane-text.h	Mon Apr 15 10:39:39 2002
@@ -553,6 +553,7 @@
 #define DESC_DELETE_IMAGES		_("Delete preview image cache")
 
 #define DESC_PRESET_AREA		_("Preset area")
+#define DESC_SELECTION_PROPORTION       _("Selection proportion")
 #define DESC_ROTATION			_("Rotate preview and scan")
 
 #define DESC_VIEWER_SAVE		_("Save image")

--n8g4imXOkfNTN/H1--