Index: src/appl/ROUTINES
===================================================================
RCS file: /u8/rdevel/CVS-ARCHIVE/R/src/appl/ROUTINES,v
retrieving revision 1.38
diff -c -r1.38 ROUTINES
*** src/appl/ROUTINES	7 Jan 2002 17:20:20 -0000	1.38
--- src/appl/ROUTINES	25 Jan 2002 14:39:37 -0000
***************
*** 96,98 ****
--- 96,101 ----
  C_FUNCTION(R_addTaskCallback)
  # Reflectance for the dynamically loaded native symbols
  C_FUNCTION(R_getSymbolInfo)
+ #
+ C_FUNCTION(R_load_gnome_device_methods)
+ C_FUNCTION(R_gnome_init_libs)
Index: src/include/Internal.h
===================================================================
RCS file: /u8/rdevel/CVS-ARCHIVE/R/src/include/Internal.h,v
retrieving revision 1.47
diff -c -r1.47 Internal.h
*** src/include/Internal.h	21 Dec 2001 18:10:18 -0000	1.47
--- src/include/Internal.h	25 Jan 2002 14:39:41 -0000
***************
*** 33,38 ****
--- 33,39 ----
  SEXP do_PicTeX(SEXP, SEXP, SEXP, SEXP);
  SEXP do_Gnome(SEXP, SEXP, SEXP, SEXP);
  SEXP do_GTK(SEXP, SEXP, SEXP, SEXP);
+ SEXP do_asGTKDevice(SEXP, SEXP, SEXP, SEXP);
  SEXP do_XFig(SEXP, SEXP, SEXP, SEXP);
  SEXP do_PDF(SEXP, SEXP, SEXP, SEXP);
  #ifdef Macintosh
Index: src/library/base/R/unix/x11.R
===================================================================
RCS file: /u8/rdevel/CVS-ARCHIVE/R/src/library/base/R/unix/x11.R,v
retrieving revision 1.5
diff -c -r1.5 x11.R
*** src/library/base/R/unix/x11.R	19 Nov 2001 20:18:06 -0000	1.5
--- src/library/base/R/unix/x11.R	25 Jan 2002 14:39:44 -0000
***************
*** 12,17 ****
  ## no Gnome <- .Alias(gnome)
  GNOME <- gnome
  
! gtk <- function(display = "", width = 7, height = 7, pointsize = 12)
!     .Internal(GTK(display, width, height, pointsize))
  GTK <- gtk
--- 12,22 ----
  ## no Gnome <- .Alias(gnome)
  GNOME <- gnome
  
! gtk <- function(display = "", width = 7, height = 7, pointsize = 12, no.window = FALSE)
!     .Internal(GTK(display, width, height, pointsize, no.window))
  GTK <- gtk
+ 
+ asGtkDevice <- function(drawingArea, pointsize = 12) {
+   .C("R_load_gnome_device_methods")
+   .Internal(asGTKDevice(drawingArea, pointsize))
+ }
Index: src/main/names.c
===================================================================
RCS file: /u8/rdevel/CVS-ARCHIVE/R/src/main/names.c,v
retrieving revision 1.247
diff -c -r1.247 names.c
*** src/main/names.c	26 Dec 2001 10:21:44 -0000	1.247
--- src/main/names.c	25 Jan 2002 14:39:49 -0000
***************
*** 679,684 ****
--- 679,685 ----
  {"X11",		do_X11,		0,	111,	8,	PP_FUNCALL},
  {"gnome",	do_Gnome,	0,	111,	4,	PP_FUNCALL},
  {"GTK",		do_GTK,		0,	111,	4,	PP_FUNCALL},
+ {"asGTKDevice",	do_asGTKDevice,	0,	111,	2,	PP_FUNCALL},
  #endif
  #ifdef Macintosh
  {"Macintosh",	do_Macintosh,	0,	111,	4,	PP_FUNCALL},
Index: src/modules/gnome/devGTK.c
===================================================================
RCS file: /u8/rdevel/CVS-ARCHIVE/R/src/modules/gnome/devGTK.c,v
retrieving revision 1.14
diff -c -r1.14 devGTK.c
*** src/modules/gnome/devGTK.c	4 Dec 2001 22:44:27 -0000	1.14
--- src/modules/gnome/devGTK.c	25 Jan 2002 14:39:54 -0000
***************
*** 73,79 ****
  
  /* routines from here */
  Rboolean GTKDeviceDriver(DevDesc *dd, char *display, double width, 
! 			 double height, double pointsize);
  
  /* Device driver actions */
  static void GTK_Activate(NewDevDesc *dd);
--- 73,79 ----
  
  /* routines from here */
  Rboolean GTKDeviceDriver(DevDesc *dd, char *display, double width, 
! 			 double height, double pointsize, Rboolean);
  
  /* Device driver actions */
  static void GTK_Activate(NewDevDesc *dd);
***************
*** 112,118 ****
  		     double rot, double hadj, 
  		     int col, double gamma, int font, double cex, double ps,
  		     NewDevDesc *dd);
! static Rboolean GTK_Open(NewDevDesc*, gtkDesc*, char*, double, double);
  
  /* Pixel Dimensions (Inches) */
  
--- 112,120 ----
  		     double rot, double hadj, 
  		     int col, double gamma, int font, double cex, double ps,
  		     NewDevDesc *dd);
! static Rboolean GTK_Open(NewDevDesc*, gtkDesc*, char*, double, double, Rboolean);
! 
! static gint initialize(NewDevDesc *dd);
  
  /* Pixel Dimensions (Inches) */
  
***************
*** 300,310 ****
  static gint realize_event(GtkWidget *widget, gpointer data)
  {
      NewDevDesc *dd;
-     gtkDesc *gtkd;
  
      dd = (NewDevDesc *) data;
      g_return_val_if_fail(dd != NULL, FALSE);
  
      gtkd = (gtkDesc *) dd->deviceSpecific;
      g_return_val_if_fail(gtkd != NULL, FALSE);
      g_return_val_if_fail(gtkd->drawing != NULL, FALSE);
--- 302,317 ----
  static gint realize_event(GtkWidget *widget, gpointer data)
  {
      NewDevDesc *dd;
  
      dd = (NewDevDesc *) data;
      g_return_val_if_fail(dd != NULL, FALSE);
  
+     return(initialize(dd));
+ }
+ 
+ static gint initialize(NewDevDesc *dd)
+ {
+     gtkDesc *gtkd;
      gtkd = (gtkDesc *) dd->deviceSpecific;
      g_return_val_if_fail(gtkd != NULL, FALSE);
      g_return_val_if_fail(gtkd->drawing != NULL, FALSE);
***************
*** 320,325 ****
--- 327,344 ----
      /* set window bg */
      gdk_window_set_background(gtkd->drawing->window, &gtkd->gcol_bg);
  
+     if(gtkd->wgc)
+ 	gdk_gc_set_foreground(gtkd->wgc, &gtkd->gcol_bg);
+ 
+     /* create offscreen drawable */
+     if(gtkd->windowWidth > 0 && gtkd->windowHeight > 0) {
+ 	gtkd->pixmap = gdk_pixmap_new(gtkd->drawing->window,
+ 				      gtkd->windowWidth, gtkd->windowHeight,
+ 				      -1);
+ 	gdk_draw_rectangle(gtkd->pixmap, gtkd->wgc, TRUE, 0, 0,
+ 			   gtkd->windowWidth, gtkd->windowHeight);
+     }
+ 
      return FALSE;
  }
  
***************
*** 362,375 ****
      g_return_val_if_fail(gtkd->drawing != NULL, FALSE);
      g_return_val_if_fail(GTK_IS_DRAWING_AREA(gtkd->drawing), FALSE);
  
      if(gtkd->resize != 0) {
  	GTK_resize(dd); 
      }
  
!   
!     gdk_draw_pixmap(gtkd->drawing->window, gtkd->wgc, gtkd->pixmap,
! 		    event->area.x, event->area.y, event->area.x, event->area.y,
! 		    event->area.width, event->area.height);
  
      GEplayDisplayList((GEDevDesc*) GetDevice(devNumber((DevDesc*)dd)));
  
--- 381,397 ----
      g_return_val_if_fail(gtkd->drawing != NULL, FALSE);
      g_return_val_if_fail(GTK_IS_DRAWING_AREA(gtkd->drawing), FALSE);
  
+     if(gtkd->wgc == NULL)
+ 	realize_event(gtkd->drawing, dd);
+ 
      if(gtkd->resize != 0) {
  	GTK_resize(dd); 
      }
  
!     if(gtkd->pixmap)
! 	gdk_draw_pixmap(gtkd->drawing->window, gtkd->wgc, gtkd->pixmap,
! 			event->area.x, event->area.y, event->area.x, event->area.y,
! 			event->area.width, event->area.height);
  
      GEplayDisplayList((GEDevDesc*) GetDevice(devNumber((DevDesc*)dd)));
  
***************
*** 417,423 ****
  };
  
  /* create window etc */
! static Rboolean GTK_Open(NewDevDesc *dd, gtkDesc *gtkd, char *dsp, double w, double h)
  {
      gint iw, ih;
  
--- 439,445 ----
  };
  
  /* create window etc */
! static Rboolean GTK_Open(NewDevDesc *dd, gtkDesc *gtkd, char *dsp, double w, double h, Rboolean noWindow)
  {
      gint iw, ih;
  
***************
*** 435,447 ****
      gtkd->windowWidth = iw = w / pixelWidth();
      gtkd->windowHeight = ih = h / pixelHeight();
  
!     gtkd->window = gnome_app_new("R.graphics", "R Graphics");
  
!     gtk_window_set_policy(GTK_WINDOW(gtkd->window), TRUE, TRUE, FALSE);
!     gtk_widget_realize(gtkd->window);
  
-     /* create toolbar */
-     gnome_app_create_toolbar_with_data(GNOME_APP(gtkd->window), graphics_toolbar, (gpointer) dd);
  
      /* create drawingarea */
      gtkd->drawing = gtk_drawing_area_new();
--- 457,473 ----
      gtkd->windowWidth = iw = w / pixelWidth();
      gtkd->windowHeight = ih = h / pixelHeight();
  
!     if(noWindow == FALSE) {
! 	gtkd->window = gnome_app_new("R.graphics", "R Graphics");
  
! 	gtk_window_set_policy(GTK_WINDOW(gtkd->window), TRUE, TRUE, FALSE);
! 	gtk_widget_realize(gtkd->window);
! 
! 	/* create toolbar */
! 	gnome_app_create_toolbar_with_data(GNOME_APP(gtkd->window), graphics_toolbar, (gpointer) dd);
!     } else
! 	gtkd->window = NULL;
  
  
      /* create drawingarea */
      gtkd->drawing = gtk_drawing_area_new();
***************
*** 460,491 ****
      SetColor(&gtkd->gcol_bg, R_RGB(255, 255, 255)); //FIXME canvas color
  
      /* place and realize the drawing area */
!     gnome_app_set_contents(GNOME_APP(gtkd->window), gtkd->drawing);
!     gtk_widget_realize(gtkd->drawing);
  
      /* connect to signal handlers, etc */
      gtk_signal_connect(GTK_OBJECT(gtkd->drawing), "configure_event",
  		       (GtkSignalFunc) configure_event, (gpointer) dd);
      gtk_signal_connect(GTK_OBJECT(gtkd->drawing), "expose_event",
  		       (GtkSignalFunc) expose_event, (gpointer) dd);
!     gtk_signal_connect(GTK_OBJECT(gtkd->window), "delete_event",
! 		       (GtkSignalFunc) delete_event, (gpointer) dd);
  
!     /* show everything */
!     gtk_widget_show_all(gtkd->window);
    
      /* initialise line params */
      gtkd->lty = -1;
      gtkd->lwd = -1;
  
-     /* create offscreen drawable */
-     gtkd->pixmap = gdk_pixmap_new(gtkd->drawing->window,
- 				  gtkd->windowWidth, gtkd->windowHeight,
- 				  -1);
-     gdk_gc_set_foreground(gtkd->wgc, &gtkd->gcol_bg);
-     gdk_draw_rectangle(gtkd->pixmap, gtkd->wgc, TRUE, 0, 0,
- 		       gtkd->windowWidth, gtkd->windowHeight);
- 
  
      /* let other widgets use the default colour settings */
      gtk_widget_pop_visual();
--- 486,513 ----
      SetColor(&gtkd->gcol_bg, R_RGB(255, 255, 255)); //FIXME canvas color
  
      /* place and realize the drawing area */
!     if(noWindow == FALSE) {
! 	gnome_app_set_contents(GNOME_APP(gtkd->window), gtkd->drawing);
! 	gtk_widget_realize(gtkd->drawing);
!     }
  
      /* connect to signal handlers, etc */
      gtk_signal_connect(GTK_OBJECT(gtkd->drawing), "configure_event",
  		       (GtkSignalFunc) configure_event, (gpointer) dd);
      gtk_signal_connect(GTK_OBJECT(gtkd->drawing), "expose_event",
  		       (GtkSignalFunc) expose_event, (gpointer) dd);
!     if(noWindow == FALSE) {
! 	gtk_signal_connect(GTK_OBJECT(gtkd->window), "delete_event",
! 			   (GtkSignalFunc) delete_event, (gpointer) dd);
  
! 	/* show everything */
! 	gtk_widget_show_all(gtkd->window);
!     }
    
      /* initialise line params */
      gtkd->lty = -1;
      gtkd->lwd = -1;
  
  
      /* let other widgets use the default colour settings */
      gtk_widget_pop_visual();
***************
*** 594,606 ****
  	dd->top = 0.0;
  	gtkd->resize = 0;
  
! 	gdk_pixmap_unref(gtkd->pixmap);
! 	gtkd->pixmap = gdk_pixmap_new(gtkd->drawing->window,
! 				      gtkd->windowWidth, gtkd->windowHeight,
! 				      -1);
! 	gdk_gc_set_foreground(gtkd->wgc, &gtkd->gcol_bg);
! 	gdk_draw_rectangle(gtkd->pixmap, gtkd->wgc, TRUE, 0, 0,
! 			   gtkd->windowWidth, gtkd->windowHeight);
      }
  }
  
--- 616,634 ----
  	dd->top = 0.0;
  	gtkd->resize = 0;
  
! 	if(gtkd->pixmap)
! 	    gdk_pixmap_unref(gtkd->pixmap);
! 	if(gtkd->windowWidth > 0 && gtkd->windowHeight > 0) {
! 	    gtkd->pixmap = gdk_pixmap_new(gtkd->drawing->window,
! 					  gtkd->windowWidth, gtkd->windowHeight,
! 					  -1);
! 
! 	    if(gtkd->wgc) {
! 		gdk_gc_set_foreground(gtkd->wgc, &gtkd->gcol_bg);
! 	        gdk_draw_rectangle(gtkd->pixmap, gtkd->wgc, TRUE, 0, 0,
! 				   gtkd->windowWidth, gtkd->windowHeight);
! 	    }
! 	}
      }
  }
  
***************
*** 624,632 ****
  
      gdk_window_clear(gtkd->drawing->window);
  
!     gdk_gc_set_foreground(gtkd->wgc, &gtkd->gcol_bg);
!     gdk_draw_rectangle(gtkd->pixmap, gtkd->wgc, TRUE, 0, 0,
! 		       gtkd->windowWidth, gtkd->windowHeight);
  }
  
  /* kill off the window etc */
--- 652,662 ----
  
      gdk_window_clear(gtkd->drawing->window);
  
!     if(gtkd->wgc) {
! 	gdk_gc_set_foreground(gtkd->wgc, &gtkd->gcol_bg);
! 	gdk_draw_rectangle(gtkd->pixmap, gtkd->wgc, TRUE, 0, 0,
! 			   gtkd->windowWidth, gtkd->windowHeight);
!     }
  }
  
  /* kill off the window etc */
***************
*** 634,642 ****
  {
      gtkDesc *gtkd = (gtkDesc *) dd->deviceSpecific;
  
!     gtk_widget_destroy(gtkd->window);
  
!     gdk_pixmap_unref(gtkd->pixmap);
  
      free(gtkd);
  }
--- 664,674 ----
  {
      gtkDesc *gtkd = (gtkDesc *) dd->deviceSpecific;
  
!     if(gtkd->window)
! 	gtk_widget_destroy(gtkd->window);
  
!     if(gtkd->pixmap)
! 	gdk_pixmap_unref(gtkd->pixmap);
  
      free(gtkd);
  }
***************
*** 655,665 ****
  
      devnum = devNumber((DevDesc*)dd) + 1;
  
!     title_text = g_strdup_printf(title_text_active, devnum);
  
!     gtk_window_set_title(GTK_WINDOW(gtkd->window), title_text);
  
!     g_free(title_text);
  }
  
  static void GTK_Deactivate(NewDevDesc *dd)
--- 687,699 ----
  
      devnum = devNumber((DevDesc*)dd) + 1;
  
!     if(gtkd->window) {
! 	title_text = g_strdup_printf(title_text_active, devnum);
  
! 	gtk_window_set_title(GTK_WINDOW(gtkd->window), title_text);
  
! 	g_free(title_text);
!     }
  }
  
  static void GTK_Deactivate(NewDevDesc *dd)
***************
*** 673,683 ****
  
      devnum = devNumber((DevDesc*)dd) + 1;
  
!     title_text = g_strdup_printf(title_text_inactive, devnum);
  
!     gtk_window_set_title(GTK_WINDOW(gtkd->window), title_text);
  
!     g_free(title_text);
  }
  
  /* drawing stuff */
--- 707,719 ----
  
      devnum = devNumber((DevDesc*)dd) + 1;
  
!     if(gtkd->window) {
! 	title_text = g_strdup_printf(title_text_inactive, devnum);
  
! 	gtk_window_set_title(GTK_WINDOW(gtkd->window), title_text);
  
! 	g_free(title_text);
!     }
  }
  
  /* drawing stuff */
***************
*** 985,991 ****
  /* Device driver entry point */
  Rboolean
  GTKDeviceDriver(DevDesc *odd, char *display, double width, 
! 		double height, double pointsize)
  {
      NewDevDesc *dd;
      int ps;
--- 1021,1027 ----
  /* Device driver entry point */
  Rboolean
  GTKDeviceDriver(DevDesc *odd, char *display, double width, 
! 		double height, double pointsize, Rboolean noWindow)
  {
      NewDevDesc *dd;
      int ps;
***************
*** 1015,1021 ****
      dd->startgamma = 1;
  
      /* device driver start */
!     if(!GTK_Open(dd, gtkd, display, width, height)) {
  	free(gtkd);
  	return FALSE;
      }
--- 1051,1057 ----
      dd->startgamma = 1;
  
      /* device driver start */
!     if(!GTK_Open(dd, gtkd, display, width, height, noWindow)) {
  	free(gtkd);
  	return FALSE;
      }
***************
*** 1094,1096 ****
--- 1130,1308 ----
      return TRUE;
  }
  
+ GtkWidget *
+ GTKDeviceGetDrawingWidget(NewDevDesc *dev)
+ {
+   gtkDesc *desc;
+   desc = dev->deviceSpecific;
+   return(desc->drawing);
+ }
+ 
+ Rboolean
+ asGTKDevice(NewDevDesc *dd, SEXP widget, double pointsize)
+ {
+   double ps = pointsize;
+   gint iw, ih, w, h;
+   GtkWidget *drawing = (GtkWidget*) R_ExternalPtrAddr(widget);
+   gtkDesc *gtkd;
+ 
+   gchar tmp[2];
+   gint cumwidth, c, rbearing, lbearing;
+   double max_rbearing, min_lbearing;
+ 
+   GTK_DRAWING_AREA(drawing);
+ 
+   if(!(gtkd = (gtkDesc *) malloc(sizeof(gtkDesc))))
+       return FALSE;
+ 
+   w = 300; h = 300;
+   gtkd->window = NULL;
+   gtkd->drawing = NULL;
+   gtkd->wgc = NULL;
+   gtkd->gcursor = NULL;
+   gtkd->resize = 1;
+ 
+     /* font loading */
+   ps = pointsize;
+   if(ps < 6 || ps > 24) ps = 12;
+   ps = 2 * (ps / 2);
+   gtkd->fontface = -1;
+   gtkd->fontsize = -1;
+   dd->startfont = 1; 
+   dd->startps = ps;
+   dd->startcol = 0;
+   dd->startfill = NA_INTEGER;
+   dd->startlty = LTY_SOLID; 
+   dd->startgamma = 1;
+ 
+     /* device driver start */
+   {
+ #if 0
+       GtkArg args[2];
+       args[0].name = "GtkWidget::width";  
+       args[1].name = "GtkWidget::height";  
+       gtk_object_getv(GTK_OBJECT(drawing), 2, args);
+       w = GTK_VALUE_INT(args[0]);
+       if(w < 0)
+ 	  w = 0;
+       h = GTK_VALUE_INT(args[1]);
+       if(h < 0)
+ 	  h = 0;
+ #endif
+ 
+   gtkd->drawing = drawing;
+   if(GTK_WIDGET_REALIZED(gtkd->drawing))
+       gtk_widget_add_events(gtkd->drawing,
+ 			    GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
+   else
+       gtk_widget_set_events(gtkd->drawing,
+ 			    GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
+   gdk_rgb_init();
+   gtk_widget_push_visual(gdk_rgb_get_visual());
+   gtk_widget_push_colormap(gdk_rgb_get_cmap());
+ 
+   gtkd->windowWidth = iw = w / pixelWidth();
+   gtkd->windowHeight = ih = h / pixelHeight();
+     /* connect to signal handlers, etc */
+   gtk_signal_connect(GTK_OBJECT(gtkd->drawing), "realize",
+ 		     (GtkSignalFunc) realize_event, (gpointer) dd);
+ 
+ 
+   SetColor(&gtkd->gcol_bg, R_RGB(255, 255, 255)); //FIXME canvas color
+ 
+     /* connect to signal handlers, etc */
+   gtk_signal_connect(GTK_OBJECT(gtkd->drawing), "configure_event",
+ 		     (GtkSignalFunc) configure_event, (gpointer) dd);
+   gtk_signal_connect(GTK_OBJECT(gtkd->drawing), "expose_event",
+ 		     (GtkSignalFunc) expose_event, (gpointer) dd);
+ 
+   dd->deviceSpecific = (void *) gtkd;
+ 
+     /* initialise line params */
+     gtkd->lty = -1;
+     gtkd->lwd = -1;
+ 
+ 
+     /* let other widgets use the default colour settings */
+     gtk_widget_pop_visual();
+     gtk_widget_pop_colormap();
+ 
+     /* Set base font */
+     if(!SetBaseFont(gtkd)) {
+ 	Rprintf("can't find X11 font\n");
+ 	return FALSE;
+     }
+   }
+ 
+   dd->newDevStruct = 1;
+ 
+     /* setup data structure */
+   dd->open = GTK_Open;
+   dd->close = GTK_Close;
+   dd->activate = GTK_Activate;
+   dd->deactivate = GTK_Deactivate;
+   dd->size = GTK_Size;
+   dd->newPage = GTK_NewPage;
+   dd->clip = GTK_Clip;
+   dd->strWidth = GTK_StrWidth;
+   dd->text = GTK_Text;
+   dd->rect = GTK_Rect;
+   dd->circle = GTK_Circle;
+   dd->line = GTK_Line;
+   dd->polyline = GTK_Polyline;
+   dd->polygon = GTK_Polygon;
+   dd->locator = GTK_Locator;
+   dd->mode = GTK_Mode;
+   dd->hold = GTK_Hold;
+   dd->metricInfo = GTK_MetricInfo;
+ 
+   dd->left = 0;
+   dd->right = gtkd->windowWidth;
+   dd->bottom = gtkd->windowHeight;
+   dd->top = 0;
+ 
+     /* nominal character sizes */
+   max_rbearing = 0;
+   min_lbearing = 10000; /* just a random big number */
+   for(c = 0; c <= 255; c++) {
+       g_snprintf(tmp, 2, "%c", (gchar) c);
+       gdk_string_extents(gtkd->font, tmp,
+ 			 &lbearing, &rbearing,
+ 			 NULL, NULL, NULL);
+       if(lbearing < min_lbearing || c == 0)
+ 	  min_lbearing = lbearing;
+       if(rbearing > max_rbearing)
+ 	  max_rbearing = rbearing;
+     }
+ 
+   dd->cra[0] = max_rbearing - min_lbearing;
+   dd->cra[1] = (double) gtkd->font->ascent + (double) gtkd->font->descent;
+ 
+     /* character addressing offsets */
+   dd->xCharOffset = 0.4900;
+   dd->yCharOffset = 0.3333;
+   dd->yLineBias = 0.1;
+ 
+     /* inches per raster unit */
+   dd->ipr[0] = pixelWidth();
+   dd->ipr[1] = pixelHeight();
+ 
+     /* device capabilities */
+   dd->canResizePlot= TRUE;
+   dd->canChangeFont= FALSE;
+   dd->canRotateText= TRUE;
+   dd->canResizeText= TRUE;
+   dd->canClip = FALSE;/* FIXME: really? */
+   dd->canHAdj = 0;/* not better? {0, 0.5, 1} */
+   dd->canChangeGamma = FALSE;
+ 
+     /* gtk device description stuff */
+   gtkd->cex = 1.0;
+   gtkd->srt = 0.0;
+   gtkd->resize = TRUE;
+ 
+   dd->displayListOn = TRUE;
+ 
+     /* finish */
+   return TRUE;
+ }
Index: src/modules/gnome/system.c
===================================================================
RCS file: /u8/rdevel/CVS-ARCHIVE/R/src/modules/gnome/system.c,v
retrieving revision 1.6
diff -c -r1.6 system.c
*** src/modules/gnome/system.c	4 Sep 2001 20:57:17 -0000	1.6
--- src/modules/gnome/system.c	25 Jan 2002 14:39:59 -0000
***************
*** 344,346 ****
--- 344,382 ----
      mainloop();
      /*++++++  in ../main/main.c */
  }
+ 
+ /**
+   This is used to initialize the gnome and glade libraries.
+   It is intended for use in a regular R session and not the 
+   Gnome GUI but when one wants stand-alone Gtk devices.
+   This separates the dependency for the Gtk devices from the 
+   Gnome UI.
+   R_gnome_init_libs()
+  */
+ void gnome_init_libs(int ac, char **av)
+ {
+     char *p;
+     int value, ierr;
+     struct stat sb;
+     structRstart rstart;
+     Rstart Rp = &rstart;
+ 
+     /* Gnome startup preferences */
+     gnomelib_init("R",
+ 		  g_strdup_printf("%s.%s %s (%s-%s-%s)", R_MAJOR,
+ 				  R_MINOR, R_STATUS, R_YEAR, R_MONTH,
+ 				  R_DAY));
+ 
+     /* Initialise Gnome library */
+     gnome_init("R",
+ 	       g_strdup_printf("%s.%s %s (%s-%s-%s)", R_MAJOR, R_MINOR,
+ 			       R_STATUS, R_YEAR, R_MONTH, R_DAY),
+ 	       ac, av);
+     R_gnome_initialised = TRUE;
+ 
+     /* Initialise libglade */
+     glade_gnome_init();
+ 
+     /* Gnome GUI preferences */
+     R_gnome_prefs_gui_load();
+ }
Index: src/unix/devUI.h
===================================================================
RCS file: /u8/rdevel/CVS-ARCHIVE/R/src/unix/devUI.h,v
retrieving revision 1.11
diff -c -r1.11 devUI.h
*** src/unix/devUI.h	27 Aug 2001 12:15:31 -0000	1.11
--- src/unix/devUI.h	25 Jan 2002 14:40:02 -0000
***************
*** 17,23 ****
  extern Rboolean (*ptr_R_GetX11Image)(int, void *, int *, int *);
  extern Rboolean (*ptr_GnomeDeviceDriver)(DevDesc*, char*, double, double, double);
  
! extern Rboolean (*ptr_GTKDeviceDriver)(DevDesc*, char*, double, double, double);
  
  extern SEXP (*ptr_dataentry)(SEXP call, SEXP op, SEXP args, SEXP rho);
  
--- 17,25 ----
  extern Rboolean (*ptr_R_GetX11Image)(int, void *, int *, int *);
  extern Rboolean (*ptr_GnomeDeviceDriver)(DevDesc*, char*, double, double, double);
  
! extern Rboolean (*ptr_GTKDeviceDriver)(DevDesc*, char*, double, double, double, Rboolean);
! extern void*    (*ptr_GTKDeviceGetDrawingWidget)(DevDesc*);
! extern Rboolean (*ptr_asGTKDevice)(DevDesc*, SEXP, double);
  
  extern SEXP (*ptr_dataentry)(SEXP call, SEXP op, SEXP args, SEXP rho);
  
***************
*** 52,58 ****
  extern Rboolean stub_R_GetX11Image(int, void *, int *, int *);
  
  Rboolean stub_GnomeDeviceDriver(DevDesc*, char*, double, double, double);
! Rboolean stub_GTKDeviceDriver(DevDesc*, char*, double, double, double);
  
  extern SEXP stub_dataentry(SEXP call, SEXP op, SEXP args, SEXP rho);
  
--- 54,61 ----
  extern Rboolean stub_R_GetX11Image(int, void *, int *, int *);
  
  Rboolean stub_GnomeDeviceDriver(DevDesc*, char*, double, double, double);
! Rboolean stub_GTKDeviceDriver(DevDesc*, char*, double, double, double, Rboolean);
! Rboolean stub_asGTKDevice(DevDesc *dd, SEXP widget, double pointsize);
  
  extern SEXP stub_dataentry(SEXP call, SEXP op, SEXP args, SEXP rho);
  
Index: src/unix/devices.c
===================================================================
RCS file: /u8/rdevel/CVS-ARCHIVE/R/src/unix/devices.c,v
retrieving revision 1.22
diff -c -r1.22 devices.c
*** src/unix/devices.c	4 Dec 2001 00:54:48 -0000	1.22
--- src/unix/devices.c	25 Jan 2002 14:40:05 -0000
***************
*** 150,159 ****
--- 150,161 ----
  
  SEXP do_GTK(SEXP call, SEXP op, SEXP args, SEXP env)
  {
+     SEXP value = R_NilValue;
      NewDevDesc *dev;
      GEDevDesc *dd;
      char *display, *vmax;
      double height, width, ps;
+     Rboolean noWindow;
      gcall = call;
      vmax = vmaxget();
      display = SaveString(CAR(args), 0); args = CDR(args);
***************
*** 161,167 ****
      height = asReal(CAR(args)); args = CDR(args);
      if (width <= 0 || height <= 0)
  	errorcall(call, "invalid width or height");
!     ps = asReal(CAR(args));
  
      R_CheckDeviceAvailable();
      BEGIN_SUSPEND_INTERRUPTS {
--- 163,170 ----
      height = asReal(CAR(args)); args = CDR(args);
      if (width <= 0 || height <= 0)
  	errorcall(call, "invalid width or height");
!     ps = asReal(CAR(args)); args = CDR(args);
!     noWindow = asLogical(CAR(args)); 
  
      R_CheckDeviceAvailable();
      BEGIN_SUSPEND_INTERRUPTS {
***************
*** 170,180 ****
  	    return 0;
  	/* Do this for early redraw attempts */
  	dev->displayList = R_NilValue;
! 	if (!ptr_GTKDeviceDriver ((DevDesc*)dev, display, width, height, ps)) {
  	    free(dev);
  	    errorcall(call, "unable to start device gtk");
  	}
  	gsetVar(install(".Device"), mkString("GTK"), R_NilValue);
  	dd = GEcreateDevDesc(dev);
          dd->newDevStruct = 1;
  	addDevice((DevDesc*) dd);
--- 173,220 ----
  	    return 0;
  	/* Do this for early redraw attempts */
  	dev->displayList = R_NilValue;
! 	if (!ptr_GTKDeviceDriver ((DevDesc*)dev, display, width, height, ps, noWindow)) {
  	    free(dev);
  	    errorcall(call, "unable to start device gtk");
  	}
  	gsetVar(install(".Device"), mkString("GTK"), R_NilValue);
+ 	dd = GEcreateDevDesc(dev);
+         dd->newDevStruct = 1;
+ 	addDevice((DevDesc*) dd);
+ 	GEinitDisplayList(dd);
+ 	if(noWindow) { /* Is this protected adequately? */
+ 	    value = R_MakeExternalPtr((void*) ptr_GTKDeviceGetDrawingWidget(dd->dev), install("GtkWidget"), NULL);
+ 	}
+     } END_SUSPEND_INTERRUPTS;
+     vmaxset(vmax);
+     return value;
+ }
+ 
+ 
+ SEXP do_asGTKDevice(SEXP call, SEXP op, SEXP args, SEXP env)
+ {
+     SEXP value = R_NilValue;
+     NewDevDesc *dev;
+     GEDevDesc *dd;
+     char *vmax;
+     double ps;
+     SEXP widget;
+     gcall = call;
+     vmax = vmaxget();
+     widget = CAR(args); args = CDR(args);
+     ps = asReal(CAR(args)); 
+     R_CheckDeviceAvailable();
+     BEGIN_SUSPEND_INTERRUPTS {
+ 	/* Allocate and initialize the device driver data */
+ 	if (!(dev = (NewDevDesc *) calloc(1, sizeof(NewDevDesc))))
+ 	    return 0;
+ 	/* Do this for early redraw attempts */
+ 	dev->displayList = R_NilValue;
+ 	if (!ptr_asGTKDevice((DevDesc*)dev, widget, ps)) {
+ 	    free(dev);
+ 	    errorcall(call, "unable to start device gtk");
+ 	}
+ 	gsetVar(install(".Device"), mkString("InternalGTK"), R_NilValue);
  	dd = GEcreateDevDesc(dev);
          dd->newDevStruct = 1;
  	addDevice((DevDesc*) dd);
Index: src/unix/gnome.c
===================================================================
RCS file: /u8/rdevel/CVS-ARCHIVE/R/src/unix/gnome.c,v
retrieving revision 1.7
diff -c -r1.7 gnome.c
*** src/unix/gnome.c	5 Dec 2001 14:41:01 -0000	1.7
--- src/unix/gnome.c	25 Jan 2002 14:40:08 -0000
***************
*** 66,103 ****
  extern DL_FUNC ptr_R_Suicide, ptr_R_ShowMessage, ptr_R_ReadConsole,
      ptr_R_WriteConsole, ptr_R_ResetConsole, ptr_R_FlushConsole,
      ptr_R_ClearerrConsole, ptr_R_Busy, ptr_R_CleanUp, ptr_R_ShowFiles,
!     ptr_R_ChooseFile, ptr_gnome_start,
!     ptr_GnomeDeviceDriver, ptr_GTKDeviceDriver,
      ptr_R_loadhistory, ptr_R_savehistory;
  
  
! /* This is called too early to use moduleCdynload */
! void R_load_gnome_shlib(void)
  {
!     char gnome_DLL[PATH_MAX], buf[1000], *p;
!     void *handle;
!     struct stat sb;
  
!     p = getenv("R_HOME");
!     if(!p) {
! 	sprintf(buf, "R_HOME was not set");
! 	R_Suicide(buf);
!     }
!     strcpy(gnome_DLL, p);
!     strcat(gnome_DLL, "/modules/R_gnome");
!     strcat(gnome_DLL, SHLIB_EXT); /* from config.h */
!     if(stat(gnome_DLL, &sb))
! 	R_Suicide("Probably no GNOME support: the shared library was not found");
! /* cannot use computeDLOpenFlag as warnings will crash R at this stage */
! #ifdef RTLD_NOW
!     handle = dlopen(gnome_DLL, RTLD_NOW);
! #else
!     handle = dlopen(gnome_DLL, 0);
! #endif
!     if(handle == NULL) {
! 	sprintf(buf, "The GNOME shared library could not be loaded.\n  The error was %s\n", dlerror());
! 	R_Suicide(buf);
!     }
      ptr_R_Suicide = Rdlsym(handle, "Rgnome_Suicide");
      if(!ptr_R_Suicide) Rstd_Suicide("Cannot load R_Suicide");
      ptr_R_ShowMessage = Rdlsym(handle, "Rgnome_ShowMessage");
--- 66,97 ----
  extern DL_FUNC ptr_R_Suicide, ptr_R_ShowMessage, ptr_R_ReadConsole,
      ptr_R_WriteConsole, ptr_R_ResetConsole, ptr_R_FlushConsole,
      ptr_R_ClearerrConsole, ptr_R_Busy, ptr_R_CleanUp, ptr_R_ShowFiles,
!     ptr_R_ChooseFile, ptr_gnome_start, ptr_gnome_init_libs,
!     ptr_GnomeDeviceDriver, ptr_GTKDeviceDriver, 
!     ptr_GTKDeviceGetDrawingWidget, ptr_asGTKDevice,
      ptr_R_loadhistory, ptr_R_savehistory;
  
  
! void *R_load_gnome_shlib_module(void);
! 
! void
! R_find_gtk_device_methods(void *handle)
  {
!     ptr_GTKDeviceDriver = Rdlsym(handle, "GTKDeviceDriver");
!     if(!ptr_GTKDeviceDriver) R_Suicide("Cannot load GTKDeviceDriver");
!     ptr_GTKDeviceGetDrawingWidget = Rdlsym(handle, "GTKDeviceGetDrawingWidget");
!     if(!ptr_GTKDeviceGetDrawingWidget) R_Suicide("Cannot load GTKDeviceGetDrawingWidget");
!     ptr_asGTKDevice = Rdlsym(handle, "asGTKDevice");
!     if(!ptr_asGTKDevice) R_Suicide("Cannot load asGTKDevice");
!     ptr_GnomeDeviceDriver = Rdlsym(handle, "GnomeDeviceDriver");
!     if(!ptr_GnomeDeviceDriver) R_Suicide("Cannot load GnomeDeviceDriver");
  
!     ptr_gnome_init_libs = Rdlsym(handle, "gnome_init_libs");
! }
! 
! void
! R_find_gnome_methods(void *handle)
! {
      ptr_R_Suicide = Rdlsym(handle, "Rgnome_Suicide");
      if(!ptr_R_Suicide) Rstd_Suicide("Cannot load R_Suicide");
      ptr_R_ShowMessage = Rdlsym(handle, "Rgnome_ShowMessage");
***************
*** 122,135 ****
      if(!ptr_R_ChooseFile) R_Suicide("Cannot load R_ChooseFile");
      ptr_gnome_start = Rdlsym(handle, "gnome_start");
      if(!ptr_gnome_start) R_Suicide("Cannot load gnome_start");
!     ptr_GTKDeviceDriver = Rdlsym(handle, "GTKDeviceDriver");
!     if(!ptr_GTKDeviceDriver) R_Suicide("Cannot load GTKDeviceDriver");
      ptr_R_loadhistory = Rdlsym(handle, "Rgnome_loadhistory");
      if(!ptr_R_loadhistory) R_Suicide("Cannot load Rgnome_loadhsitoryr");
      ptr_R_savehistory = Rdlsym(handle, "Rgnome_savehistory");
      if(!ptr_R_savehistory) R_Suicide("Cannot load Rgnome_savehistory");
!     ptr_GnomeDeviceDriver = Rdlsym(handle, "GnomeDeviceDriver");
!     if(!ptr_GnomeDeviceDriver) R_Suicide("Cannot load GnomeDeviceDriver");
  }
  
  #else
--- 116,187 ----
      if(!ptr_R_ChooseFile) R_Suicide("Cannot load R_ChooseFile");
      ptr_gnome_start = Rdlsym(handle, "gnome_start");
      if(!ptr_gnome_start) R_Suicide("Cannot load gnome_start");
! 
      ptr_R_loadhistory = Rdlsym(handle, "Rgnome_loadhistory");
      if(!ptr_R_loadhistory) R_Suicide("Cannot load Rgnome_loadhsitoryr");
      ptr_R_savehistory = Rdlsym(handle, "Rgnome_savehistory");
      if(!ptr_R_savehistory) R_Suicide("Cannot load Rgnome_savehistory");
! 
!     R_find_gtk_device_methods(handle);
! }
! 
! void *R_load_gnome_shlib_module(void)
! {
!     char gnome_DLL[PATH_MAX], buf[1000], *p;
!     void *handle;
!     struct stat sb;
! 
!     p = getenv("R_HOME");
!     if(!p) {
! 	sprintf(buf, "R_HOME was not set");
! 	R_Suicide(buf);
!     }
!     strcpy(gnome_DLL, p);
!     strcat(gnome_DLL, "/modules/R_gnome");
!     strcat(gnome_DLL, SHLIB_EXT); /* from config.h */
!     if(stat(gnome_DLL, &sb))
! 	R_Suicide("Probably no GNOME support: the shared library was not found");
! /* cannot use computeDLOpenFlag as warnings will crash R at this stage */
! #ifdef RTLD_NOW
!     handle = dlopen(gnome_DLL, RTLD_NOW);
! #else
!     handle = dlopen(gnome_DLL, 0);
! #endif
!     if(handle == NULL) {
! 	sprintf(buf, "The GNOME shared library could not be loaded.\n  The error was %s\n", dlerror());
! 	R_Suicide(buf);
!     }
! 
!     return(handle);
! }
! 
! /* This is called too early to use moduleCdynload */
! void R_load_gnome_shlib(void)
! {
!     void *handle;
!     handle = R_load_gnome_shlib_module();
!     if(handle)
! 	R_find_gnome_methods(handle);
! }
! 
! void R_load_gnome_device_methods()
! {
!     static void *handle = NULL;
!     if(handle == NULL) {
! 	handle = R_load_gnome_shlib_module();
!         if(handle)
! 	    R_find_gtk_device_methods(handle);
!     }
! }
! 
! 
! void R_gnome_init_libs(char **argv, long *argc)
! {
!     int argCount = *argc;
!     R_load_gnome_device_methods();
!     if(ptr_gnome_init_libs) {
! 	ptr_gnome_init_libs(argCount, argv);
!     }
  }
  
  #else
***************
*** 139,142 ****
--- 191,203 ----
      R_Suicide("no support to load gnome shared library in this R version");
  }
  
+ void R_load_gnome_device_methods()
+ {
+     R_Suicide("no support to load gnome shared library in this R version");
+ }
+ 
+ void R_gnome_init_libs()
+ {
+     error("no support to load gnome shared library in this R version");
+ }
  #endif
Index: src/unix/stubs.c
===================================================================
RCS file: /u8/rdevel/CVS-ARCHIVE/R/src/unix/stubs.c,v
retrieving revision 1.11
diff -c -r1.11 stubs.c
*** src/unix/stubs.c	22 Aug 2001 06:35:15 -0000	1.11
--- src/unix/stubs.c	25 Jan 2002 14:40:12 -0000
***************
*** 52,60 ****
  }
  
  Rboolean stub_GTKDeviceDriver(DevDesc *dd, char *display, double width, 
! 			  double height, double pointsize)
  {
      error("the gtk device is only available with --gui=GNOME");
      return FALSE;
  }
  
--- 52,67 ----
  }
  
  Rboolean stub_GTKDeviceDriver(DevDesc *dd, char *display, double width, 
! 			  double height, double pointsize, Rboolean noWindow)
  {
      error("the gtk device is only available with --gui=GNOME");
+     return FALSE;
+ }
+ 
+ 
+ Rboolean stub_asGTKDevice(DevDesc *dd, SEXP widget, double pointsize)
+ {
+     error("no support for creating a gtk device from a widget");
      return FALSE;
  }
  
Index: src/unix/system.c
===================================================================
RCS file: /u8/rdevel/CVS-ARCHIVE/R/src/unix/system.c,v
retrieving revision 1.113
diff -c -r1.113 system.c
*** src/unix/system.c	30 Nov 2001 00:29:16 -0000	1.113
--- src/unix/system.c	25 Jan 2002 14:40:15 -0000
***************
*** 73,78 ****
--- 73,79 ----
  { return ptr_R_ChooseFile(new, buf, len); }
  
  void (*ptr_gnome_start)(int ac, char **av, Rstart Rp);
+ void (*ptr_gnome_init_libs)(int ac, char **av);
  
  void R_setStartTime(void); /* in sys-unix.c */
  void R_load_X11_shlib(void); /* in dynload.c */
***************
*** 171,176 ****
--- 172,178 ----
  
      ptr_GnomeDeviceDriver = stub_GnomeDeviceDriver;
      ptr_GTKDeviceDriver = stub_GTKDeviceDriver;
+     ptr_asGTKDevice = stub_asGTKDevice;
      ptr_X11DeviceDriver = stub_X11DeviceDriver;
      ptr_dataentry = stub_dataentry;
      ptr_R_GetX11Image = stub_R_GetX11Image;