Index: src/Fl_Copy_Surface.cxx
===================================================================
--- src/Fl_Copy_Surface.cxx	(revision 0)
+++ src/Fl_Copy_Surface.cxx	(revision 0)
@@ -0,0 +1,447 @@
+#include <FL/Fl_Copy_Surface.H>
+#include <FL/Fl.H>
+
+
+#if defined(__APPLE__)
+#include <ApplicationServices/ApplicationServices.h>
+#if defined(__ppc__)
+#include <QuickTime/QuickTimeComponents.h>
+#endif // __ppc__
+
+Fl_Quartz_Surface::Fl_Quartz_Surface(int w, int h) : Fl_System_Printer(), width(w), height(h) {
+}
+
+int Fl_Quartz_Surface::printable_rect(int *w, int *h) {
+  *w = width;
+  *h = height;
+  return 0;
+}
+
+const char *Fl_Quartz_Surface::class_id = "Fl_Quartz_Surface";
+
+#elif defined(WIN32)
+
+Fl_GDI_Surface::Fl_GDI_Surface() : Fl_Paged_Device() {
+  driver(new Fl_GDI_Graphics_Driver);
+  depth = 0;
+}
+
+Fl_GDI_Surface::~Fl_GDI_Surface() {
+  delete driver();
+}
+
+void Fl_GDI_Surface::translate(int x, int y) {
+  GetWindowOrgEx(fl_gc, origins+depth);
+  SetWindowOrgEx(fl_gc, origins[depth].x - x, origins[depth].y - y, NULL);
+  if (depth < sizeof(origins)/sizeof(POINT)) depth++;
+  else Fl::warning("Fl_GDI_Surface: translate stack overflow!");
+}
+
+void Fl_GDI_Surface::untranslate() {
+  depth--;
+  SetWindowOrgEx(fl_gc, origins[depth].x, origins[depth].y, NULL);
+}
+  
+const char *Fl_GDI_Surface::class_id = "Fl_GDI_Surface";
+
+#endif
+
+
+const char *Fl_Copy_Surface::class_id = "Fl_Copy_Surface";
+
+/** Constructor. 
+ \param w and \param h are the width and height of the clipboard surface
+ in pixels where drawing will occur.
+ */
+Fl_Copy_Surface::Fl_Copy_Surface(int w, int h) :  Fl_Surface_Device(NULL)
+{
+  width = w;
+  height = h;
+#ifdef __APPLE__
+  helper = new Fl_Quartz_Surface(width, height);
+  driver(helper->driver());
+  prepare_copy_pdf_and_tiff(w, h);
+  oldgc = fl_gc;
+#elif defined(WIN32)
+  helper = new Fl_GDI_Surface();
+  driver(helper->driver());
+  oldgc = fl_gc;
+  // exact computation of factor from screen units to EnhMetaFile units (0.01 mm)
+  HDC hdc = GetDC(NULL);
+  int hmm = GetDeviceCaps(hdc, HORZSIZE);
+  int hdots = GetDeviceCaps(hdc, HORZRES);
+  int vmm = GetDeviceCaps(hdc, VERTSIZE);
+  int vdots = GetDeviceCaps(hdc, VERTRES);
+  ReleaseDC(NULL, hdc);
+  float factorw =  (100. * hmm) / hdots;
+  float factorh =  (100. * vmm) / vdots + 0.5;
+  
+  RECT rect; rect.left = 0; rect.top = 0; rect.right = w * factorw; rect.bottom = h * factorh;
+  gc = CreateEnhMetaFile (NULL, NULL, &rect, NULL);
+  if (gc != NULL) {
+    SetTextAlign(gc, TA_BASELINE|TA_LEFT);
+    SetBkMode(gc, TRANSPARENT);
+  } 
+#else // Xlib
+  helper = new Fl_Xlib_Surface();
+  driver(helper->driver());
+  Fl::first_window()->make_current();
+  oldwindow = fl_xid(Fl::first_window());
+  xid = fl_create_offscreen(w,h);
+  Fl_Surface_Device *present_surface = Fl_Surface_Device::surface();
+  set_current();
+  fl_color(FL_WHITE);
+  fl_rectf(0, 0, w, h);
+  present_surface->set_current();
+#endif
+}
+
+/** Destructor.
+ */
+Fl_Copy_Surface::~Fl_Copy_Surface()
+{
+#ifdef __APPLE__
+  complete_copy_pdf_and_tiff();
+  fl_gc = oldgc;
+  delete (Fl_Quartz_Surface*)helper;
+#elif defined(WIN32)
+  if(oldgc == fl_gc) oldgc = NULL;
+  HENHMETAFILE hmf = CloseEnhMetaFile (gc);
+  if ( hmf != NULL ) {
+    if ( OpenClipboard (NULL) ){
+      EmptyClipboard ();
+      SetClipboardData (CF_ENHMETAFILE, hmf);
+      CloseClipboard ();
+    }
+    DeleteEnhMetaFile(hmf);
+  }
+  DeleteDC(gc);
+  fl_gc = oldgc;
+  delete (Fl_GDI_Surface*)helper;
+#else // Xlib
+  fl_pop_clip(); 
+  unsigned char *data = fl_read_image(NULL,0,0,width,height,0);
+  fl_window = oldwindow; 
+  _ss->set_current();
+  Fl::copy_image(data,width,height,1);
+  delete[] data;
+  fl_delete_offscreen(xid);
+  delete (Fl_Xlib_Surface*)helper;
+#endif
+}
+
+/** Copies a widget in the clipboard
+ 
+ \param widget any FLTK widget (e.g., standard, custom, window, GL view) to copy
+ \param delta_x and \param delta_y give 
+ the position in the clipboard of the top-left corner of the widget
+ */
+void Fl_Copy_Surface::draw(Fl_Widget* widget, int delta_x, int delta_y) 
+{
+  helper->print_widget(widget, delta_x, delta_y);
+}
+
+void Fl_Copy_Surface::set_current()
+{
+#if defined(__APPLE__) || defined(WIN32)
+  fl_gc = gc;
+  fl_window = (Window)1;
+  Fl_Surface_Device::set_current();
+#else
+  fl_window=xid; 
+  _ss = Fl_Surface_Device::surface(); 
+  Fl_Surface_Device::set_current();
+  fl_push_no_clip();
+#endif
+}
+
+
+#if defined(__APPLE__)
+
+size_t Fl_Copy_Surface::MyPutBytes(void* info, const void* buffer, size_t count)
+  {
+  CFDataAppendBytes ((CFMutableDataRef) info, (const UInt8 *)buffer, count);
+  return count;
+}
+
+void Fl_Copy_Surface::init_PDF_context(int w, int h)
+{
+  CGRect bounds = CGRectMake(0, 0, w, h );	
+  pdfdata = CFDataCreateMutable(NULL, 0);
+  CGDataConsumerRef myconsumer;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
+  if(CGDataConsumerCreateWithCFData != NULL) {
+    myconsumer = CGDataConsumerCreateWithCFData(pdfdata); // 10.4
+  }
+  else 
+#endif
+  {
+    static CGDataConsumerCallbacks callbacks = { Fl_Copy_Surface::MyPutBytes, NULL };
+    myconsumer = CGDataConsumerCreate ((void*) pdfdata, &callbacks);
+  }
+  gc = CGPDFContextCreate (myconsumer, &bounds, NULL);
+  CGDataConsumerRelease (myconsumer);
+}
+
+void Fl_Copy_Surface::prepare_copy_pdf_and_tiff(int w, int h)
+{
+  init_PDF_context(w, h);
+  if (gc == NULL) return;
+  CGRect bounds = CGRectMake(0, 0, w, h );	
+  CGContextBeginPage (gc, &bounds);
+  CGContextTranslateCTM(gc, 0, h);
+  CGContextScaleCTM(gc, 1.0f, -1.0f);
+  CGContextSaveGState(gc);
+}
+
+static void bitmap_to_tiff_clipboard(CGContextRef c, PasteboardRef clipboard)
+{
+  if (fl_mac_os_version >= 100400) {
+    CFStringRef tiff = CFSTR("public.tiff");
+    CFMutableDataRef data = CFDataCreateMutable(NULL, 0);
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
+    CGImageRef image = CGBitmapContextCreateImage(c); // 10.4
+    CGImageDestinationRef dest = CGImageDestinationCreateWithData(data,tiff, 1, NULL); // 10.4
+    CGImageDestinationAddImage(dest, image, NULL); // 10.4
+    CGImageDestinationFinalize(dest); // 10.4
+    CGImageRelease(image);
+    CFRelease(dest);
+#endif
+    PasteboardPutItemFlavor(clipboard, (PasteboardItemID)1, tiff, data, kPasteboardFlavorNoFlags );
+    CFRelease(data);
+    }
+  else {
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 && defined(__ppc__)
+#warning Compilation with -mmacosx-version-min=10.3 requires -framework QuickTime at link time
+	GraphicsExportComponent exporter;
+   	OSErr err = OpenADefaultComponent(GraphicsExporterComponentType, /*kQTFileTypePicture*/ 'PICT', &exporter);
+   	ComponentResult cerr = GraphicsExportSetInputCGBitmapContext(exporter, c); // 10.3 -framework QuickTime
+   	Handle dataHandle = NewHandle(0);
+   	cerr = GraphicsExportSetOutputHandle(exporter, dataHandle); // -framework QuickTime
+  	unsigned long size;
+   	cerr = GraphicsExportDoExport(exporter, &size); // -framework QuickTime
+   	err = CloseComponent(exporter);
+   	if (GetHandleSize(dataHandle) > 512) {
+     	HLock(dataHandle);
+     	// The clipboard REQUIRES only the image data, not the header.
+     	CFDataRef pictdata = CFDataCreate(NULL, (const UInt8 *)*dataHandle + 512, GetHandleSize(dataHandle) - 512);
+     	HUnlock(dataHandle);
+     	PasteboardPutItemFlavor(clipboard, (PasteboardItemID)1,
+					 	CFSTR("com.apple.pict"),
+					 	pictdata,
+					 	kPasteboardFlavorNoFlags );
+     	CFRelease(pictdata);
+     	}
+   	DisposeHandle(dataHandle);
+#endif
+  }
+}
+
+
+void Fl_Copy_Surface::complete_copy_pdf_and_tiff()
+{
+  CGContextRestoreGState(gc);
+  CGContextEndPage(gc);
+  CGContextRelease(gc);
+  PasteboardRef clipboard = NULL;
+  PasteboardCreate(kPasteboardClipboard, &clipboard);
+  PasteboardClear(clipboard); //	first, copy PDF to clipboard 
+  PasteboardPutItemFlavor (clipboard, (PasteboardItemID)1, 
+			   CFSTR("com.adobe.pdf"), // kUTTypePDF
+			   pdfdata, kPasteboardFlavorNoFlags);
+  //second, transform this PDF to a bitmap image and put it as tiff in clipboard
+  CGDataProviderRef prov;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
+  if(fl_mac_os_version >= 100400)
+    prov = CGDataProviderCreateWithCFData(pdfdata); // 10.4
+  else 
+#endif
+    prov = CGDataProviderCreateWithData(NULL, CFDataGetBytePtr(pdfdata), CFDataGetLength(pdfdata), NULL);
+  CGPDFDocumentRef pdfdoc = CGPDFDocumentCreateWithProvider(prov);
+  CGPDFPageRef pdfpage = CGPDFDocumentGetPage(pdfdoc, 1);
+  CGDataProviderRelease(prov);
+  CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
+  void *mem = ( fl_mac_os_version >= 100600 ? NULL : malloc(width * height * 4) );
+  gc = CGBitmapContextCreate(mem, width, height, 8, width * 4, space, kCGImageAlphaNoneSkipLast);
+  CFRelease(space);
+  if (gc == NULL) { if (mem) free(mem); return; }
+  CGRect rect = CGRectMake(0, 0, width, height);
+  CGContextSetRGBFillColor(gc,  1,1,1,1);//need to clear background
+  CGContextFillRect(gc, rect);
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+  CGContextDrawPDFPage(gc, pdfpage);  // requires 10.3
+#endif
+  CGPDFDocumentRelease(pdfdoc);
+  CFRelease(pdfdata);
+  bitmap_to_tiff_clipboard(gc, clipboard);
+  CFRelease(clipboard);    
+  CGContextRelease(gc);
+  if (mem) free(mem);
+}
+
+#endif  // __APPLE__
+
+#if !(defined(__APPLE__) || defined(WIN32) || defined(FL_DOXYGEN))
+/** graphics driver that translates all graphics coordinates before using a real Xlib driver*/
+class Fl_translated_Xlib_Graphics_Driver : public Fl_Xlib_Graphics_Driver {
+  Fl_Xlib_Graphics_Driver *direct;
+  int offset_x, offset_y; // translation between user and graphical coordinates
+  int depth; // depth of translation stack
+  int stack_x[10], stack_y[10]; // translation stack allowing cumulative translations
+public:
+  static const char *class_id;
+  const char *class_name() {return class_id;};
+  Fl_translated_Xlib_Graphics_Driver(Fl_Xlib_Graphics_Driver *driver) {
+    direct = driver;
+    offset_x = 0; offset_y = 0;
+    depth = 0;
+    }
+  virtual ~Fl_translated_Xlib_Graphics_Driver() {};
+  void translate_all(int x, int y) { // add offset between user and graphical coordinates
+    stack_x[depth] = offset_x;
+    stack_y[depth] = offset_y;
+    offset_x = stack_x[depth] + x;
+    offset_y = stack_y[depth] + y;
+    push_matrix();
+    translate(x, y);
+    if (depth < sizeof(stack_x)/sizeof(int)) depth++;
+    else Fl::warning("%s: translate stack overflow!", class_id);
+  }
+  void untranslate_all() { // undoes previous translate_all()
+    if (depth > 0) depth--;
+    offset_x = stack_x[depth];
+    offset_y = stack_y[depth];
+    pop_matrix();
+  }
+  void color(uchar r, uchar g, uchar b) {
+    direct->color(r, g, b); 
+    Fl_Graphics_Driver::color(direct->Fl_Graphics_Driver::color());
+  }
+  void color(Fl_Color c) {
+    direct->color(c); 
+    Fl_Graphics_Driver::color(c);
+  }
+  void font(Fl_Font face, Fl_Fontsize fsize) {
+    direct->font(face, fsize); 
+    Fl_Graphics_Driver::font(face, fsize);
+  }
+  void text_extents(const char *str, int n, int &dx, int &dy, int &w, int &h) { direct->text_extents(str, n,dx,dy,w,h);}
+  double width(const char *str, int n) {return direct->width(str, n);}
+  double width(unsigned int c) {return direct->width(c);}
+  int height() {return direct->height();}
+  int descent() {return direct->descent();}
+  void rect(int x, int y, int w, int h) { Fl_Xlib_Graphics_Driver::rect(x+offset_x, y+offset_y, w, h); }
+  void rectf(int x, int y, int w, int h) { Fl_Xlib_Graphics_Driver::rectf(x+offset_x, y+offset_y, w, h); }
+  void xyline(int x, int y, int x1) { Fl_Xlib_Graphics_Driver::xyline(x+offset_x, y+offset_y, x1+offset_x); }
+  void xyline(int x, int y, int x1, int y2) { Fl_Xlib_Graphics_Driver::xyline(x+offset_x, y+offset_y, x1+offset_x, y2+offset_y); }
+  void xyline(int x, int y, int x1, int y2, int x3) { Fl_Xlib_Graphics_Driver::xyline(x+offset_x, y+offset_y, x1+offset_x, y2+offset_y, x3+offset_x); }
+  void yxline(int x, int y, int y1) { Fl_Xlib_Graphics_Driver::yxline(x+offset_x, y+offset_y, y1+offset_y); }
+  void yxline(int x, int y, int y1, int x2) { Fl_Xlib_Graphics_Driver::yxline(x+offset_x, y+offset_y, y1+offset_y, x2+offset_x); }
+  void yxline(int x, int y, int y1, int x2, int y3) { Fl_Xlib_Graphics_Driver::yxline(x+offset_x, y+offset_y, y1+offset_y, x2+offset_x, y3+offset_y); }
+  void line(int x, int y, int x1, int y1) { Fl_Xlib_Graphics_Driver::line(x+offset_x, y+offset_y, x1+offset_x, y1+offset_y); }
+  void line(int x, int y, int x1, int y1, int x2, int y2) { Fl_Xlib_Graphics_Driver::line(x+offset_x, y+offset_y, x1+offset_x, y1+offset_y, x2+offset_x, y2+offset_y); }
+  void draw(const char* str, int n, int x, int y) { 
+    fl_graphics_driver = direct;
+    direct->draw(str, n, x+offset_x, y+offset_y); 
+    fl_graphics_driver = this;
+ }
+  void draw(int angle, const char *str, int n, int x, int y) { 
+    fl_graphics_driver = direct;
+    direct->draw(angle, str, n, x+offset_x, y+offset_y); 
+    fl_graphics_driver = this;
+  }
+  void rtl_draw(const char* str, int n, int x, int y) { 
+    fl_graphics_driver = direct;
+    direct->rtl_draw(str, n, x+offset_x, y+offset_y); 
+    fl_graphics_driver = this;
+  }
+  void draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) { 
+    fl_graphics_driver = direct;
+    direct->draw(pxm, XP+offset_x, YP+offset_y, WP,HP,cx,cy); 
+    fl_graphics_driver = this;
+  }
+  void draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) { 
+    fl_graphics_driver = direct;
+    direct->draw(bm, XP+offset_x, YP+offset_y, WP,HP,cx,cy); 
+    fl_graphics_driver = this;
+  }
+  void draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) { 
+    fl_graphics_driver = direct;
+    direct->draw(img, XP+offset_x, YP+offset_y, WP,HP,cx,cy); 
+    fl_graphics_driver = this;
+  }
+  void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0) { 
+    fl_graphics_driver = direct;
+    direct->draw_image(buf, X+offset_x, Y+offset_y, W,H,D,L); 
+    fl_graphics_driver = this;
+  }
+  void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3) { 
+    fl_graphics_driver = direct;
+    direct->draw_image(cb, data, X+offset_x, Y+offset_y, W,H,D); 
+    fl_graphics_driver = this;
+  }
+  void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0) { 
+    fl_graphics_driver = direct;
+    direct->draw_image_mono(buf, X+offset_x, Y+offset_y, W,H,D,L); 
+    fl_graphics_driver = this;
+  }
+  void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1) { 
+    fl_graphics_driver = direct;
+    direct->draw_image_mono(cb, data, X+offset_x, Y+offset_y, W,H,D); 
+    fl_graphics_driver = this;
+  }
+  void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy) { direct->copy_offscreen(x+offset_x, y+offset_y, w, h,pixmap,srcx,srcy); }
+  void push_clip(int x, int y, int w, int h) {
+    fl_graphics_driver = direct;
+    fl_push_clip(x+offset_x, y+offset_y, w, h); 
+    fl_graphics_driver = this;
+  }
+  void pop_clip() {
+    fl_graphics_driver = direct;
+    fl_pop_clip(); 
+    fl_graphics_driver = this;
+  }
+  void push_no_clip() {
+    fl_graphics_driver = direct;
+    fl_push_no_clip(); 
+    fl_graphics_driver = this;
+  };
+  int not_clipped(int x, int y, int w, int h) { return Fl_Xlib_Graphics_Driver::not_clipped(x + offset_x, y + offset_y, w, h); };
+  int clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H) { 
+    int retval = Fl_Xlib_Graphics_Driver::clip_box(x + offset_x, y + offset_y, w,h,X,Y,W,H);
+    X -= offset_x;
+    Y -= offset_y;
+    return retval;
+  }
+  void pie(int x, int y, int w, int h, double a1, double a2) { Fl_Xlib_Graphics_Driver::pie(x+offset_x,y+offset_y,w,h,a1,a2); }
+  void arc(int x, int y, int w, int h, double a1, double a2) { Fl_Xlib_Graphics_Driver::arc(x+offset_x,y+offset_y,w,h,a1,a2); }
+  void polygon(int x0, int y0, int x1, int y1, int x2, int y2) { Fl_Xlib_Graphics_Driver::polygon(x0+offset_x,y0+offset_y,x1+offset_x,y1+offset_y,x2+offset_x,y2+offset_y);}
+  void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
+    Fl_Xlib_Graphics_Driver::polygon(x0+offset_x,y0+offset_y,x1+offset_x,y1+offset_y,x2+offset_x,y2+offset_y,x3+offset_x,y3+offset_y);
+  }
+  void loop(int x0, int y0, int x1, int y1, int x2, int y2) {Fl_Xlib_Graphics_Driver::loop(x0+offset_x,y0+offset_y,x1+offset_x,y1+offset_y,x2+offset_x,y2+offset_y);}
+  void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
+    Fl_Xlib_Graphics_Driver::loop(x0+offset_x,y0+offset_y,x1+offset_x,y1+offset_y,x2+offset_x,y2+offset_y,x3+offset_x,y3+offset_y);
+  }
+  void point(int x, int y) { Fl_Xlib_Graphics_Driver::point(x+offset_x, y+offset_y); }
+};
+
+const char *Fl_translated_Xlib_Graphics_Driver::class_id = "Fl_translated_Xlib_Graphics_Driver";
+
+void Fl_Xlib_Surface::translate(int x, int y) { 
+  ((Fl_translated_Xlib_Graphics_Driver*)driver())->translate_all(x, y); 
+}
+void Fl_Xlib_Surface::untranslate() { 
+  ((Fl_translated_Xlib_Graphics_Driver*)driver())->untranslate_all(); 
+}
+
+Fl_Xlib_Surface::Fl_Xlib_Surface() : Fl_Paged_Device() {
+  driver(new Fl_translated_Xlib_Graphics_Driver((Fl_Xlib_Graphics_Driver*)Fl_Display_Device::display_device()->driver()));
+}
+Fl_Xlib_Surface::~Fl_Xlib_Surface() {
+  delete driver();
+}
+
+const char *Fl_Xlib_Surface::class_id = "Fl_Xlib_Surface";
+
+#endif
Index: src/Fl_Image_Surface.cxx
===================================================================
--- src/Fl_Image_Surface.cxx	(revision 0)
+++ src/Fl_Image_Surface.cxx	(revision 0)
@@ -0,0 +1,132 @@
+#include <FL/Fl_Image_Surface.H>
+#include <FL/Fl_Printer.H>
+#include <FL/Fl.H>
+
+
+const char *Fl_Image_Surface::class_id = "Fl_Image_Surface";
+
+/** The constructor.
+ \param w and \param h give the size in pixels of the resulting image.
+ */
+Fl_Image_Surface::Fl_Image_Surface(int w, int h) : Fl_Surface_Device(NULL) {
+  width = w;
+  height = h;
+  offscreen = fl_create_offscreen(w, h);
+#ifdef __APPLE__
+  helper = new Fl_Quartz_Flipped_Surface(width, height);
+  driver(helper->driver());
+#elif defined(WIN32)
+  helper = new Fl_GDI_Surface();
+  driver(helper->driver());
+#else
+  helper = new Fl_Xlib_Surface();
+  driver(helper->driver());
+#endif
+}
+
+/** The destructor.
+ */
+Fl_Image_Surface::~Fl_Image_Surface() {
+  fl_delete_offscreen(offscreen);
+#ifdef __APPLE__
+  delete (Fl_Quartz_Flipped_Surface*)helper;
+#elif defined(WIN32)
+  delete (Fl_GDI_Surface*)helper;
+#else
+  delete (Fl_Xlib_Surface*)helper;
+#endif
+}
+
+/** Returns the image made of all drawings sent to the Fl_Image_Surface object.
+ The returned object can be safely cast to Fl_RGB_Image* and contains its own copy
+ of the RGB data.
+ */
+Fl_Image* Fl_Image_Surface::image()
+{
+  unsigned char *data;
+#ifdef __APPLE__
+  CGContextFlush(offscreen);
+  data = fl_read_image(NULL, 0, 0, width, height, 0);
+  fl_end_offscreen();
+#elif defined(WIN32)
+  fl_pop_clip(); 
+  data = fl_read_image(NULL, 0, 0, width, height, 0);
+  RestoreDC(fl_gc, _savedc); 
+  DeleteDC(fl_gc); 
+  _ss->set_current(); 
+  fl_window=_sw; 
+  fl_gc = _sgc;
+#else
+  fl_pop_clip(); 
+  data = fl_read_image(NULL, 0, 0, width, height, 0);
+  fl_window = pre_window; 
+  previous->set_current();
+#endif
+  Fl_RGB_Image *image = new Fl_RGB_Image(data, width, height);
+  image->alloc_array = 1;
+  return image;
+}
+
+/** Draws a widget in the image surface
+ 
+ \param widget any FLTK widget (e.g., standard, custom, window, GL view) to draw in the image
+ \param delta_x and \param delta_y give 
+ the position in the image of the top-left corner of the widget
+ */
+void Fl_Image_Surface::draw(Fl_Widget *widget, int delta_x, int delta_y)
+{
+  helper->print_widget(widget, delta_x, delta_y);
+}
+
+
+void Fl_Image_Surface::set_current()
+{
+#if defined(__APPLE__)
+  fl_begin_offscreen(offscreen);
+  fl_pop_clip();
+  Fl_Surface_Device::set_current(); 
+  fl_push_no_clip();
+#elif defined(WIN32)
+  _sgc=fl_gc; 
+  _sw=fl_window;
+  _ss = Fl_Surface_Device::surface(); 
+  Fl_Surface_Device::set_current();
+  fl_gc = fl_makeDC(offscreen); 
+   _savedc = SaveDC(fl_gc); 
+  fl_window=(HWND)offscreen; 
+  fl_push_no_clip();
+#else
+  pre_window = fl_window; 
+  fl_window = offscreen; 
+  previous = Fl_Surface_Device::surface(); 
+  Fl_Surface_Device::set_current();
+  fl_push_no_clip();
+#endif
+}
+
+#if defined(__APPLE__)
+
+Fl_Quartz_Flipped_Surface::Fl_Quartz_Flipped_Surface(int w, int h) : Fl_Quartz_Surface(w, h) {
+}
+
+void Fl_Quartz_Flipped_Surface::translate(int x, int y) {
+  CGContextRestoreGState(fl_gc);
+  CGContextSaveGState(fl_gc);
+  /*CGContextTranslateCTM(fl_gc, 0, height);
+   CGContextScaleCTM(fl_gc, 1.0f, -1.0f);
+   CGContextTranslateCTM(fl_gc, x, y);
+   CGContextScaleCTM(fl_gc, 1.0f, -1.0f);
+   CGContextTranslateCTM(fl_gc, 0, -height);*/
+  CGContextTranslateCTM(fl_gc, x, -y);
+  CGContextSaveGState(fl_gc);
+  CGContextTranslateCTM(fl_gc, 0, height);
+  CGContextScaleCTM(fl_gc, 1.0f, -1.0f);
+}
+
+void Fl_Quartz_Flipped_Surface::untranslate() {
+  CGContextRestoreGState(fl_gc);
+}
+
+const char *Fl_Quartz_Flipped_Surface::class_id = "Fl_Quartz_Flipped_Surface";
+
+#endif // __APPLE__
Index: src/Makefile
===================================================================
--- src/Makefile	(revision 10113)
+++ src/Makefile	(working copy)
@@ -31,6 +31,7 @@
 	Fl_Choice.cxx \
 	Fl_Clock.cxx \
 	Fl_Color_Chooser.cxx \
+	Fl_Copy_Surface.cxx \
 	Fl_Counter.cxx \
 	Fl_Dial.cxx \
 	Fl_Device.cxx \
@@ -43,6 +44,7 @@
 	Fl_Group.cxx \
 	Fl_Help_View.cxx \
 	Fl_Image.cxx \
+	Fl_Image_Surface.cxx \
 	Fl_Input.cxx \
 	Fl_Input_.cxx \
 	Fl_Light_Button.cxx \
Index: src/Fl_x.cxx
===================================================================
--- src/Fl_x.cxx	(revision 10113)
+++ src/Fl_x.cxx	(working copy)
@@ -335,6 +335,7 @@
 Atom fl_XaCompoundText;
 Atom fl_XaUtf8String;
 Atom fl_XaTextUriList;
+Atom fl_XaImageBmp;
 Atom fl_NET_WM_NAME;			// utf8 aware window label
 Atom fl_NET_WM_ICON_NAME;		// utf8 aware window icon name
 Atom fl_NET_SUPPORTING_WM_CHECK;
@@ -641,6 +642,7 @@
   fl_XaCompoundText     = XInternAtom(d, "COMPOUND_TEXT",       0);
   fl_XaUtf8String       = XInternAtom(d, "UTF8_STRING",         0);
   fl_XaTextUriList      = XInternAtom(d, "text/uri-list",       0);
+  fl_XaImageBmp         = XInternAtom(d, "image/bmp",           0);
   fl_NET_WM_NAME        = XInternAtom(d, "_NET_WM_NAME",        0);
   fl_NET_WM_ICON_NAME   = XInternAtom(d, "_NET_WM_ICON_NAME",   0);
   fl_NET_SUPPORTING_WM_CHECK = XInternAtom(d, "_NET_SUPPORTING_WM_CHECK", 0);
@@ -773,6 +775,9 @@
 Fl_Widget *fl_selection_requestor;
 char *fl_selection_buffer[2];
 int fl_selection_length[2];
+#define FL_SELECTION_TEXT 0
+#define FL_SELECTION_IMAGE 1
+int fl_selection_type[2];
 int fl_selection_buffer_length[2];
 char fl_i_own_selection[2] = {0,0};
 
@@ -782,6 +787,8 @@
     // We already have it, do it quickly without window server.
     // Notice that the text is clobbered if set_selection is
     // called in response to FL_PASTE!
+    // However, for now, we only paste text in this function
+    if (fl_selection_type[clipboard] != FL_SELECTION_TEXT) return;
     Fl::e_text = fl_selection_buffer[clipboard];
     Fl::e_length = fl_selection_length[clipboard];
     if (!Fl::e_text) Fl::e_text = (char *)"";
@@ -870,10 +877,81 @@
   fl_selection_buffer[clipboard][len] = 0; // needed for direct paste
   fl_selection_length[clipboard] = len;
   fl_i_own_selection[clipboard] = 1;
+  fl_selection_type[clipboard] = FL_SELECTION_TEXT;
   Atom property = clipboard ? CLIPBOARD : XA_PRIMARY;
   XSetSelectionOwner(fl_display, property, fl_message_window, fl_event_time);
 }
 
+static void write_short(unsigned char **cp,short i){
+  unsigned char *c=*cp;
+  *c++=i&0xFF;i>>=8;
+  *c++=i&0xFF;i>>=8;
+  *cp=c;
+}
+
+static void write_int(unsigned char **cp,int i){
+  unsigned char *c=*cp;
+  *c++=i&0xFF;i>>=8;
+  *c++=i&0xFF;i>>=8;
+  *c++=i&0xFF;i>>=8;
+  *c++=i&0xFF;i>>=8;
+  *cp=c;
+}
+
+static unsigned char *create_bmp(const unsigned char *data, int W, int H, int *return_size){
+  int R=(3*W+3)/4 * 4; // the number of bytes per row, rounded up to multiple of 4
+  int s=H*R;
+  int fs=14+40+s;
+  unsigned char *b=new unsigned char[fs];
+  unsigned char *c=b;
+  // BMP header
+  *c++='B';
+  *c++='M';
+  write_int(&c,fs);
+  write_int(&c,0);
+  write_int(&c,14+40);
+  // DIB header:
+  write_int(&c,40);
+  write_int(&c,W);
+  write_int(&c,H);
+  write_short(&c,1);
+  write_short(&c,24);//bits ber pixel
+  write_int(&c,0);//RGB
+  write_int(&c,s);
+  write_int(&c,0);// horizontal resolution
+  write_int(&c,0);// vertical resolution
+  write_int(&c,0);//number of colors. 0 -> 1<<bits_per_pixel
+  write_int(&c,0);
+  // Pixel data
+  data+=3*W*H;
+  for (int y=0;y<H;++y){
+    data-=3*W;
+    const unsigned char *s=data;
+    unsigned char *p=c;
+    for (int x=0;x<W;++x){
+      *p++=s[2];
+      *p++=s[1];
+      *p++=s[0];
+      s+=3;
+    }
+    c+=R;
+  }
+  *return_size = fs;
+  return b;
+}
+
+void Fl::copy_image(const unsigned char *data, int W, int H, int clipboard){
+  if(!data || W<=0 || H<=0) return;
+  delete[] fl_selection_buffer[clipboard];
+  fl_selection_buffer[clipboard] = (char *) create_bmp(data,W,H,&fl_selection_length[clipboard]);
+  fl_selection_buffer_length[clipboard] = fl_selection_length[clipboard];
+  fl_i_own_selection[clipboard] = 1;
+  fl_selection_type[clipboard] = FL_SELECTION_IMAGE;
+
+  Atom property = clipboard ? CLIPBOARD : XA_PRIMARY;
+  XSetSelectionOwner(fl_display, property, fl_message_window, fl_event_time);
+}
+
 ////////////////////////////////////////////////////////////////
 // Code for tracking clipboard changes:
 
@@ -1242,32 +1320,54 @@
     e.target = fl_xevent->xselectionrequest.target;
     e.time = fl_xevent->xselectionrequest.time;
     e.property = fl_xevent->xselectionrequest.property;
-    if (e.target == TARGETS) {
-      Atom a[3] = {fl_XaUtf8String, XA_STRING, fl_XaText};
-      XChangeProperty(fl_display, e.requestor, e.property,
-                      XA_ATOM, atom_bits, 0, (unsigned char*)a, 3);
-    } else if (/*e.target == XA_STRING &&*/ fl_selection_length[clipboard]) {
-    if (e.target == fl_XaUtf8String ||
-	     e.target == XA_STRING ||
-	     e.target == fl_XaCompoundText ||
-	     e.target == fl_XaText ||
-	     e.target == fl_Xatextplain ||
-	     e.target == fl_Xatextplainutf ||
-	     e.target == fl_Xatextplainutf2) {
-	// clobber the target type, this seems to make some applications
-	// behave that insist on asking for XA_TEXT instead of UTF8_STRING
-	// Does not change XA_STRING as that breaks xclipboard.
-	if (e.target != XA_STRING) e.target = fl_XaUtf8String;
+    if (fl_selection_type[clipboard] == FL_SELECTION_TEXT){
+      if (e.target == TARGETS) {
+	Atom a[3] = {fl_XaUtf8String, XA_STRING, fl_XaText};
 	XChangeProperty(fl_display, e.requestor, e.property,
-			 e.target, 8, 0,
-			 (unsigned char *)fl_selection_buffer[clipboard],
-			 fl_selection_length[clipboard]);
+	                XA_ATOM, atom_bits, 0, (unsigned char*)a, 3);
+      } else {
+	if (/*e.target == XA_STRING &&*/ fl_selection_length[clipboard]) {
+	  if (e.target == fl_XaUtf8String ||
+	      e.target == XA_STRING ||
+	      e.target == fl_XaCompoundText ||
+	      e.target == fl_XaText ||
+	      e.target == fl_Xatextplain ||
+	      e.target == fl_Xatextplainutf ||
+	      e.target == fl_Xatextplainutf2) {
+	    // clobber the target type, this seems to make some applications
+	    // behave that insist on asking for XA_TEXT instead of UTF8_STRING
+	    // Does not change XA_STRING as that breaks xclipboard.
+	    if (e.target != XA_STRING) e.target = fl_XaUtf8String;
+	    XChangeProperty(fl_display, e.requestor, e.property,
+		            e.target, 8, 0,
+		            (unsigned char *)fl_selection_buffer[clipboard],
+		            fl_selection_length[clipboard]);
+	  }
+	} else {
+	  //    char* x = XGetAtomName(fl_display,e.target);
+	  //    fprintf(stderr,"selection request of %s\n",x);
+	  //    XFree(x);
+	  e.property = 0;
+	}
       }
-    } else {
-//    char* x = XGetAtomName(fl_display,e.target);
-//    fprintf(stderr,"selection request of %s\n",x);
-//    XFree(x);
-      e.property = 0;
+    } else { // image in clipboard
+      if (e.target == TARGETS) {
+	Atom a[1] = {fl_XaImageBmp};
+	XChangeProperty(fl_display, e.requestor, e.property,
+	                XA_ATOM, atom_bits, 0, (unsigned char*)a, 1);
+      } else {
+	if (e.target == fl_XaImageBmp && fl_selection_length[clipboard]) {
+	    XChangeProperty(fl_display, e.requestor, e.property,
+		            e.target, 8, 0,
+		            (unsigned char *)fl_selection_buffer[clipboard],
+		            fl_selection_length[clipboard]);
+	} else {
+	  //    char* x = XGetAtomName(fl_display,e.target);
+	  //    fprintf(stderr,"selection request of %s\n",x);
+	  //    XFree(x);
+	  e.property = 0;
+	}
+      }
     }
     XSendEvent(fl_display, e.requestor, 0, 0, (XEvent *)&e);}
     return 1;
Index: FL/Fl.H
===================================================================
--- FL/Fl.H	(revision 10113)
+++ FL/Fl.H	(working copy)
@@ -765,6 +765,9 @@
   clipboard is used for traditional copy/cut/paste operations.
   */
   static void copy(const char* stuff, int len, int destination = 0); // platform dependent
+#if !(defined(__APPLE__) || defined(WIN32))
+  static void copy_image(const unsigned char* data, int W, int H, int destination = 0); // platform dependent
+#endif
   /**
   Pastes the data from the selection buffer (\p source is 0) or the clipboard 
   (\p source is 1) into \p receiver.  
Index: FL/Fl_Copy_Surface.H
===================================================================
--- FL/Fl_Copy_Surface.H	(revision 0)
+++ FL/Fl_Copy_Surface.H	(revision 0)
@@ -0,0 +1,114 @@
+#ifndef Fl_Copy_Surface_H
+#define Fl_Copy_Surface_H
+
+#include <FL/Fl_Paged_Device.H>
+#include <FL/Fl_Printer.H>
+
+#if defined(__APPLE__)
+#include <ApplicationServices/ApplicationServices.h>
+#endif
+
+/** Supports copying of graphical data to the clipboard.
+ 
+ <br> After creation of an Fl_Copy_Surface object, call set_current() on it, and all subsequent graphics requests
+ will be recorded in the clipboard. It's possible to draw widgets (using Fl_Copy_Surface::draw()
+ ) or to use any of the \ref fl_drawings or the \ref fl_attributes.
+ Finally, delete the Fl_Copy_Surface object to load the clipboard with the graphical data.
+ <br> Fl_GL_Window 's can be copied to the clipboard as well. 
+ <br> Usage example:
+ \code
+ Fl_Widget *g = ...; // a widget you want to copy to the clipboard
+ Fl_Copy_Surface *copy_surf = new Fl_Copy_Surface(g->w(), g->h()); // create an Fl_Copy_Surface object
+ copy_surf->set_current(); // direct graphics requests to the clipboard
+ fl_color(FL_WHITE); fl_rectf(0, 0, g->w(), g->h()); // draw a white background
+ copy_surf->draw(g); // draw the g widget in the clipboard
+ delete copy_surf; // after this, the clipboard is loaded
+ Fl_Display_Device::display_device()->set_current();  // direct graphics requests back to the display
+ \endcode
+ Platform details:
+ \li MSWindows: Transparent RGB images copy without transparency.
+ The graphical data is copied to the clipboard as an 'enhanced metafile'.
+ \li Mac OS: Mac OS X 10.4 or higher is necessary. The graphical data is copied to the 
+ clipboard (a.k.a. pasteboard) in 2 'flavors': 
+ 1) in vectorial form as PDF data; 2) in bitmap form as a TIFF image. Applications to which the 
+ clipboard content is pasted can use the flavor that suits them best.
+ \li X11: the graphical data is copied to the clipboard as an image in BMP format.
+*/
+class Fl_Copy_Surface : public Fl_Surface_Device {
+private:
+  int width;
+  int height;
+  Fl_Paged_Device *helper;
+#ifdef __APPLE__
+  CFMutableDataRef pdfdata;
+  CGContextRef oldgc;
+  CGContextRef gc;
+  void prepare_copy_pdf_and_tiff(int w, int h);
+  void complete_copy_pdf_and_tiff();
+  void init_PDF_context(int w, int h);
+  static size_t MyPutBytes(void* info, const void* buffer, size_t count);
+#elif defined(WIN32)
+  HDC oldgc;
+  HDC gc;
+#else // Xlib
+  Fl_Offscreen xid;
+  Window oldwindow;
+  Fl_Surface_Device *_ss;
+#endif
+public:
+  static const char *class_id;
+  const char *class_name() {return class_id;};
+  Fl_Copy_Surface(int w, int h);
+  ~Fl_Copy_Surface();
+  void set_current();
+  void draw(Fl_Widget* widget, int delta_x = 0, int delta_y = 0);
+};
+
+#if defined(__APPLE__)
+
+/* Mac class to reimplement Fl_Paged_Device::printable_rect() */
+class Fl_Quartz_Surface : public Fl_System_Printer {
+protected:
+  int width;
+  int height;
+public:
+  static const char *class_id;
+  const char *class_name() {return class_id;};
+  Fl_Quartz_Surface(int w, int h);
+  virtual int printable_rect(int *w, int *h);
+  virtual ~Fl_Quartz_Surface() {};
+};
+
+#elif defined(WIN32)
+
+/* Win class to implement translate()/untranslate() */
+class Fl_GDI_Surface : public Fl_Paged_Device {
+  int width;
+  int height;
+  int depth;
+  POINT origins[10];
+public:
+  static const char *class_id;
+  const char *class_name() {return class_id;};
+  Fl_GDI_Surface();
+  virtual void translate(int x, int y);
+  virtual void untranslate();
+  virtual ~Fl_GDI_Surface();
+};
+
+#elif !defined(FL_DOXYGEN)
+
+/* Xlib class to implement translate()/untranslate() */
+class Fl_Xlib_Surface : public Fl_Paged_Device {
+public:
+  static const char *class_id;
+  const char *class_name() {return class_id;};
+  Fl_Xlib_Surface();
+  virtual void translate(int x, int y);
+  virtual void untranslate();
+  virtual ~Fl_Xlib_Surface();
+};
+
+#endif
+
+#endif // Fl_Copy_Surface_H
Index: FL/Fl_Image_Surface.H
===================================================================
--- FL/Fl_Image_Surface.H	(revision 0)
+++ FL/Fl_Image_Surface.H	(revision 0)
@@ -0,0 +1,67 @@
+#ifndef Fl_Image_Surface_H
+#define Fl_Image_Surface_H
+
+#include <FL/Fl_Copy_Surface.H>
+#include <FL/Fl_Image.H>
+
+
+/** Directs all graphics requests to an Fl_Image.
+ 
+ After creation of an Fl_Image_Surface object, call set_current() on it, and all subsequent graphics requests
+ will be recorded in the image. It's possible to draw widgets (using Fl_Image_Surface::draw()) 
+ or to use any of the \ref fl_drawings or the \ref fl_attributes.
+ Finally, call image() on the object to obtain a newly allocated Fl_Image object.
+ <br> Fl_GL_Window objects can be drawn in the image as well. 
+ 
+ <br> Usage example:
+ \code
+ Fl_Widget *g = ...; // a widget you want to draw in an image
+ Fl_Image_Surface *img_surf = new Fl_Image_Surface(g->w(), g->h()); // create an Fl_Image_Surface object
+ img_surf->set_current(); // direct graphics requests to the image
+ fl_color(FL_WHITE); fl_rectf(0, 0, g->w(), g->h()); // draw a white background
+ img_surf->draw(g); // draw the g widget in the image
+ Fl_Image* image = img_surf->image(); // get the resulting image
+ delete img_surf; // delete the img_surf object
+ Fl_Display_Device::display_device()->set_current();  // direct graphics requests back to the display
+ \endcode
+*/
+class Fl_Image_Surface : public Fl_Surface_Device {
+private:
+  Fl_Offscreen offscreen;
+  int width;
+  int height;
+  Fl_Paged_Device *helper;
+#ifdef __APPLE__
+#elif defined(WIN32)
+  HDC _sgc; 
+  Window _sw; 
+  Fl_Surface_Device *_ss;
+  int _savedc;
+#else
+  Fl_Surface_Device *previous;
+  Window pre_window;
+#endif
+public:
+  static const char *class_id;
+  const char *class_name() {return class_id;};
+  Fl_Image_Surface(int w, int h);
+  ~Fl_Image_Surface();
+  void set_current();
+  void draw(Fl_Widget*, int delta_x = 0, int delta_y = 0);
+  Fl_Image *image();
+};
+
+#ifdef __APPLE__
+/* Mac class to implement translate()/untranslate() for a flipped bitmap graphics context */
+class Fl_Quartz_Flipped_Surface : public Fl_Quartz_Surface {
+public:
+  static const char *class_id;
+  const char *class_name() {return class_id;};
+  Fl_Quartz_Flipped_Surface(int w, int h);
+  void translate(int x, int y);
+  void untranslate();
+  virtual ~Fl_Quartz_Flipped_Surface() {};
+};
+#endif 
+
+#endif // Fl_Image_Surface_H
Index: test/device.cxx
===================================================================
--- test/device.cxx	(revision 10113)
+++ test/device.cxx	(working copy)
@@ -21,6 +21,7 @@
 
 #include <FL/Fl_Overlay_Window.H>
 #include <FL/Fl_Light_Button.H>
+#include <FL/Fl_Radio_Round_Button.H>
 #include <FL/fl_draw.H>
 #include <FL/Fl_Clock.H>
 #include "pixmaps/porsche.xpm"
@@ -30,9 +31,9 @@
 
 
 #include <FL/Fl_Printer.H>
+#include <FL/Fl_Copy_Surface.H>
+#include <FL/Fl_Image_Surface.H>
 
-//#include "fl_printer_chooser.H"
-
 #include <FL/Fl_File_Chooser.H>
 #include <FL/fl_draw.H>
 
@@ -551,17 +552,47 @@
 }
 
 
-void print(Fl_Widget *, void *w) {
-  Fl_Widget * g = (Fl_Widget *)w;
+Fl_Widget *target;
+const  char *operation;
+
+void copy(Fl_Widget *, void *data) {
+  if (strcmp(operation, "Fl_Image_Surface") == 0) {
+    Fl_Image_Surface *rgb_surf = new Fl_Image_Surface(target->w()+20, target->h()+10);
+    rgb_surf->set_current();
+    fl_color(FL_BLUE);fl_rectf(0,0,1000,1000);
+    rgb_surf->draw(target,10,5);
+    Fl_Image *img = rgb_surf->image();
+    delete rgb_surf;
+    Fl_Display_Device::display_device()->set_current();
+    Fl_Window* g2 = new Fl_Window(img->w(), img->h());
+    Fl_Box *b = new Fl_Box(FL_NO_BOX,0,0,img->w(), img->h(),0);
+    b->image(img);
+    g2->end();
+    g2->show();
+    return;
+  }
   
-  Fl_Printer * p = new Fl_Printer();
-  if (!p->start_job(1)) {
-    p->start_page();
-    p->print_window(g->window());
-    p->end_page();
-    p->end_job();
+  
+  if (strcmp(operation, "Fl_Copy_Surface") == 0) {
+    Fl_Copy_Surface *copy_surf = new Fl_Copy_Surface(target->w()+10, target->h()+20);
+    copy_surf->set_current();
+    fl_color(FL_YELLOW);fl_rectf(0,0,1000,1000);
+    copy_surf->draw(target, 5, 10);
+    delete copy_surf;
+    Fl_Display_Device::display_device()->set_current();  
+    }
+  
+  if (strcmp(operation, "Fl_Printer") == 0) {
+    Fl_Printer * p = new Fl_Printer();
+    if (!p->start_job(1)) {
+      p->start_page();
+      if (target->as_window()) p->print_window(target->as_window());
+      else p->print_widget(target);
+      p->end_page();
+      p->end_job();
+    }
+    delete p;
   }
-  delete p;
 }
 
 /*void print2(Fl_Widget *, void *w) {
@@ -598,6 +629,16 @@
 };
 
 
+void target_cb(Fl_Widget* wid, void *data)
+{
+  target = (Fl_Widget*)data;
+}
+
+void operation_cb(Fl_Widget* wid, void *data)
+{
+  operation = wid->label();
+}
+
 int main(int argc, char ** argv) {
   
   //Fl::scheme("plastic");
@@ -650,7 +691,8 @@
   
   //Fl_Button but7(, 480, 120, 30, "Engraved box");
   //but7.box(FL_ENGRAVED_BOX);
-  { Fl_Group* o = new Fl_Group(360, 495, 120, 40);
+  Fl_Group *group;
+  { Fl_Group* o = new Fl_Group(360, 495, 120, 40); group=o;
     o->box(FL_UP_BOX);
     { Fl_Group* o = new Fl_Group(365, 500, 110, 30);
       o->box(FL_THIN_UP_FRAME);
@@ -673,12 +715,27 @@
   tx.hide();
   
   c2->end();
-  Fl_Button *b4 = new Fl_Button(10,5, 150, 25, "Print");
-  b4->callback(print,c2);
-  /*Fl_Button *b5 = new Fl_Button(165,5, 90, 25, "Print");
-   b5->tooltip("This is a tooltip");
-   b5->callback(print2,c2);*/
   
+  Fl_Radio_Round_Button *rb;
+  Fl_Window *w3 = new Fl_Window(2,5,w2->w()-10,55);
+  w3->box(FL_DOWN_BOX);
+  Fl_Group *g1 = new Fl_Group(w3->x(),w3->y(),w3->w(),w3->h());
+  rb = new Fl_Radio_Round_Button(5,5,150,12, "Fl_Image_Surface"); 
+  rb->set(); rb->callback(operation_cb, NULL); operation = rb->label();
+  rb = new Fl_Radio_Round_Button(5,22,150,12, "Fl_Copy_Surface"); rb->callback(operation_cb, NULL);
+  rb = new Fl_Radio_Round_Button(5,39,150,12, "Fl_Printer"); rb->callback(operation_cb, NULL);
+  g1->end();
+  
+  Fl_Group *g2 = new Fl_Group(w3->x(),w3->y(),w3->w(),w3->h());
+  rb = new Fl_Radio_Round_Button(170,5,150,12, "Window"); 
+  rb->set(); rb->callback(target_cb, w2); target = w2;
+  rb = new Fl_Radio_Round_Button(170,22,150,12, "Sub-window"); rb->callback(target_cb, w3);
+  rb = new Fl_Radio_Round_Button(170,39,150,12, "Group"); rb->callback(target_cb, group);
+  g2->end();
+  Fl_Button *b4 = new Fl_Button(330, (w3->h() - 25)/2, 150, 25, "GO");
+  b4->callback((Fl_Callback*)copy,NULL);
+  w3->end();
+  
   w2->end();
   w2->show(argc, argv);
   
