The R Project SVN R

Rev

Rev 27117 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 27117 Rev 27236
1
/*
1
/*
2
 *  R : A Computer Language for Statistical Data Analysis
2
 *  R : A Computer Language for Statistical Data Analysis
3
 *  Copyright (C) 1998-2002   Lyndon Drake
3
 *  Copyright (C) 1998-2002   Lyndon Drake
4
 *                            and the R Development Core Team
4
 *                            and the R Development Core Team
5
 *
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 2 of the License, or
8
 *  the Free Software Foundation; either version 2 of the License, or
9
 *  (at your option) any later version.
9
 *  (at your option) any later version.
10
 *
10
 *
11
 *  This program is distributed in the hope that it will be useful,
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
14
 *  GNU General Public License for more details.
15
 *
15
 *
16
 *  You should have received a copy of the GNU General Public License
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; if not, write to the Free Software
17
 *  along with this program; if not, write to the Free Software
18
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
19
 */
20
 
20
 
21
#ifdef HAVE_CONFIG_H
21
#ifdef HAVE_CONFIG_H
22
# include <config.h>
22
# include <config.h>
23
#endif
23
#endif
24
 
24
 
25
/* Avoid braced-groups warning from -Wall */
25
/* Avoid braced-groups warning from -Wall */
26
#define G_STMT_START do
26
#define G_STMT_START do
27
#define G_STMT_END   while(0)
27
#define G_STMT_END   while(0)
28
 
28
 
29
#include <gnome.h>
29
#include <gnome.h>
30
#include <math.h>
30
#include <math.h>
31
 
31
 
32
#include "Defn.h"
32
#include "Defn.h"
33
#include "Graphics.h"
33
#include "Graphics.h"
34
#include "Rdevices.h"
34
#include "Rdevices.h"
35
#include "devGNOME.h"
35
#include "devGNOME.h"
36
#include "terminal.h"
36
#include "terminal.h"
37
#include "terminal-functions.h"
37
#include "terminal-functions.h"
38
 
38
 
39
#define CURSOR		GDK_CROSSHAIR		/* Default cursor */
39
#define CURSOR		GDK_CROSSHAIR		/* Default cursor */
40
#define MM_PER_INCH	25.4			/* mm -> inch conversion */
40
#define MM_PER_INCH	25.4			/* mm -> inch conversion */
41
 
41
 
42
/* routines from here */
42
/* routines from here */
43
 
43
 
44
/* Device driver actions */
44
/* Device driver actions */
45
static void GNOME_Activate(NewDevDesc *dd);
45
static void GNOME_Activate(NewDevDesc *dd);
46
static void GNOME_Circle(double x, double y, double r,
46
static void GNOME_Circle(double x, double y, double r,
47
		       int col, int fill, double gamma, int lty, double lwd,
47
			 R_GE_gcontext *gc,
48
		       NewDevDesc *dd);
48
			 NewDevDesc *dd);
49
static void GNOME_Clip(double x0, double x1, double y0, double y1, 
49
static void GNOME_Clip(double x0, double x1, double y0, double y1, 
50
		     NewDevDesc *dd);
50
		     NewDevDesc *dd);
51
static void GNOME_Close(NewDevDesc *dd);
51
static void GNOME_Close(NewDevDesc *dd);
52
static void GNOME_Deactivate(NewDevDesc *dd);
52
static void GNOME_Deactivate(NewDevDesc *dd);
53
static void GNOME_Hold(NewDevDesc *dd);
53
static void GNOME_Hold(NewDevDesc *dd);
54
static Rboolean GNOME_Locator(double *x, double *y, NewDevDesc *dd);
54
static Rboolean GNOME_Locator(double *x, double *y, NewDevDesc *dd);
55
static void GNOME_Line(double x1, double y1, double x2, double y2,
55
static void GNOME_Line(double x1, double y1, double x2, double y2,
56
		     int col, double gamma, int lty, double lwd,
56
		       R_GE_gcontext *gc,
57
		     NewDevDesc *dd);
57
		       NewDevDesc *dd);
58
static void GNOME_MetricInfo(int c, int font, double cex, double ps,
58
static void GNOME_MetricInfo(int c,
-
 
59
			     R_GE_gcontext *gc,
59
			      double* ascent, double* descent,
60
			     double* ascent, double* descent,
60
			      double* width, NewDevDesc *dd);
61
			     double* width, NewDevDesc *dd);
61
static void GNOME_Mode(int mode, NewDevDesc *dd);
62
static void GNOME_Mode(int mode, NewDevDesc *dd);
62
static void GNOME_NewPage(int fill, double gamma, NewDevDesc *dd);
63
static void GNOME_NewPage(R_GE_gcontext *gc, NewDevDesc *dd);
63
static void GNOME_Polygon(int n, double *x, double *y, 
64
static void GNOME_Polygon(int n, double *x, double *y, 
64
			int col, int fill, double gamma, int lty, double lwd,
65
			  R_GE_gcontext *gc,
65
			NewDevDesc *dd);
66
			  NewDevDesc *dd);
66
static void GNOME_Polyline(int n, double *x, double *y, 
67
static void GNOME_Polyline(int n, double *x, double *y, 
67
			    int col, double gamma, int lty, double lwd,
68
			   R_GE_gcontext *gc,
68
			    NewDevDesc *dd);
69
			   NewDevDesc *dd);
69
static void GNOME_Rect(double x0, double y0, double x1, double y1,
70
static void GNOME_Rect(double x0, double y0, double x1, double y1,
70
		     int col, int fill, double gamma, int lty, double lwd,
71
		       R_GE_gcontext *gc,
71
		     NewDevDesc *dd);
72
		       NewDevDesc *dd);
72
static void GNOME_Resize(NewDevDesc *dd);
73
static void GNOME_Resize(NewDevDesc *dd);
73
static void GNOME_Size(double *left, double *right,
74
static void GNOME_Size(double *left, double *right,
74
		     double *bottom, double *top,
75
		     double *bottom, double *top,
75
		     NewDevDesc *dd);
76
		     NewDevDesc *dd);
76
static double GNOME_StrWidth(char *str, int font,
77
static double GNOME_StrWidth(char *str, 
-
 
78
			     R_GE_gcontext *gc,
77
			      double cex, double ps, NewDevDesc *dd);
79
			     NewDevDesc *dd);
78
static void GNOME_Text(double x, double y, char *str, 
80
static void GNOME_Text(double x, double y, char *str, 
79
		     double rot, double hadj, 
81
		       double rot, double hadj, 
80
		     int col, double gamma, int font, double cex, double ps,
82
		       R_GE_gcontext *gc,
81
		     NewDevDesc *dd);
83
		       NewDevDesc *dd);
82
static Rboolean GNOME_Open(NewDevDesc*, gnomeDesc*, char*, double, double);
84
static Rboolean GNOME_Open(NewDevDesc*, gnomeDesc*, char*, double, double);
83
 
85
 
84
			/* Pixel Dimensions (Inches) */
86
			/* Pixel Dimensions (Inches) */
85
 
87
 
86
static double pixelWidth(void)
88
static double pixelWidth(void)
87
{
89
{
88
    double width, widthMM;
90
    double width, widthMM;
89
    width = gdk_screen_width();
91
    width = gdk_screen_width();
90
    widthMM = gdk_screen_width_mm();
92
    widthMM = gdk_screen_width_mm();
91
    return ((double)widthMM / (double)width) / MM_PER_INCH;
93
    return ((double)widthMM / (double)width) / MM_PER_INCH;
92
}
94
}
93
 
95
 
94
static double pixelHeight(void)
96
static double pixelHeight(void)
95
{
97
{
96
    double height, heightMM;
98
    double height, heightMM;
97
    height = gdk_screen_height();
99
    height = gdk_screen_height();
98
    heightMM = gdk_screen_height_mm();
100
    heightMM = gdk_screen_height_mm();
99
    return ((double)heightMM / (double)height) / MM_PER_INCH;
101
    return ((double)heightMM / (double)height) / MM_PER_INCH;
100
}
102
}
101
 
103
 
102
/* font stuff */
104
/* font stuff */
103
 
105
 
104
static char *fontname_R6 = "-adobe-helvetica-%s-%s-*-*-*-%d-*-*-*-*-*-*";
106
static char *fontname_R6 = "-adobe-helvetica-%s-%s-*-*-*-%d-*-*-*-*-*-*";
105
static char *symbolname = "-adobe-symbol-*-*-*-*-*-%d-*-*-*-*-*-*";
107
static char *symbolname = "-adobe-symbol-*-*-*-*-*-%d-*-*-*-*-*-*";
106
static char *fixedname = "fixed";
108
static char *fixedname = "fixed";
107
 
109
 
108
static char *slant[] = {"r", "o"};
110
static char *slant[] = {"r", "o"};
109
static char *weight[] = {"medium", "bold"};
111
static char *weight[] = {"medium", "bold"};
110
 
112
 
111
static char *fontname = NULL;
113
static char *fontname = NULL;
112
static GHashTable *font_htab = NULL;
114
static GHashTable *font_htab = NULL;
113
 
115
 
114
static int RDeviceNumber(NewDevDesc *dd)
116
static int RDeviceNumber(NewDevDesc *dd)
115
{
117
{
116
    return devNumber((DevDesc*) dd) + 1;
118
    return devNumber((DevDesc*) dd) + 1;
117
}
119
}
118
 
120
 
119
static GdkFont *RGTKLoadFont(char *font)
121
static GdkFont *RGTKLoadFont(char *font)
120
{
122
{
121
  GdkFont *tmp_font;
123
  GdkFont *tmp_font;
122
  
124
  
123
  g_return_val_if_fail(font_htab, NULL);
125
  g_return_val_if_fail(font_htab, NULL);
124
  tmp_font = g_hash_table_lookup(font_htab, (gpointer) font);
126
  tmp_font = g_hash_table_lookup(font_htab, (gpointer) font);
125
 
127
 
126
  if(!tmp_font)
128
  if(!tmp_font)
127
    {
129
    {
128
      if((tmp_font = gdk_font_load(font)))
130
      if((tmp_font = gdk_font_load(font)))
129
	{
131
	{
130
	  g_hash_table_insert(font_htab, (gpointer) g_strdup(font),
132
	  g_hash_table_insert(font_htab, (gpointer) g_strdup(font),
131
			      (gpointer) tmp_font);
133
			      (gpointer) tmp_font);
132
	}
134
	}
133
    }
135
    }
134
 
136
 
135
  return tmp_font;
137
  return tmp_font;
136
}
138
}
137
 
139
 
138
static gboolean SetBaseFont (gnomeDesc *gd)
140
static gboolean SetBaseFont (gnomeDesc *gd)
139
{
141
{
140
  gd->fontface = 1;
142
  gd->fontface = 1;
141
  gd->fontsize = 12;
143
  gd->fontsize = 12;
142
  gd->usefixed = 0;
144
  gd->usefixed = 0;
143
  
145
  
144
  if (font_htab == NULL)
146
  if (font_htab == NULL)
145
    {
147
    {
146
      font_htab = g_hash_table_new(g_str_hash, g_str_equal);
148
      font_htab = g_hash_table_new(g_str_hash, g_str_equal);
147
    }
149
    }
148
 
150
 
149
  fontname = g_strdup_printf(fontname_R6, weight[0], slant[0], 
151
  fontname = g_strdup_printf(fontname_R6, weight[0], slant[0], 
150
			     gd->fontsize * 10);
152
			     gd->fontsize * 10);
151
  gd->font = RGTKLoadFont(fontname);
153
  gd->font = RGTKLoadFont(fontname);
152
  g_free(fontname);
154
  g_free(fontname);
153
 
155
 
154
  if(gd->font)
156
  if(gd->font)
155
    return TRUE;
157
    return TRUE;
156
 
158
 
157
  gd->usefixed = 1;
159
  gd->usefixed = 1;
158
  gd->font = RGTKLoadFont(fixedname);
160
  gd->font = RGTKLoadFont(fixedname);
159
 
161
 
160
  if(gd->font)
162
  if(gd->font)
161
    return TRUE;
163
    return TRUE;
162
  
164
  
163
  return FALSE;
165
  return FALSE;
164
}
166
}
165
 
167
 
166
#define SMALLEST 8
168
#define SMALLEST 8
167
#define LARGEST 24
169
#define LARGEST 24
168
 
170
 
169
static void SetFont(NewDevDesc *dd, gint face, gint size)
171
static void SetFont(NewDevDesc *dd, gint face, gint size)
170
{
172
{
171
  GdkFont *tmp_font;
173
  GdkFont *tmp_font;
172
  gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
174
  gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
173
 
175
 
174
  if (face < 1 || face > 5)
176
  if (face < 1 || face > 5)
175
    face = 1;
177
    face = 1;
176
  
178
  
177
  size = 2 * size / 2;
179
  size = 2 * size / 2;
178
  if (size < SMALLEST)
180
  if (size < SMALLEST)
179
    size = SMALLEST;
181
    size = SMALLEST;
180
  else if (size > LARGEST)
182
  else if (size > LARGEST)
181
    size = LARGEST;
183
    size = LARGEST;
182
  
184
  
183
  if (!gd->usefixed)
185
  if (!gd->usefixed)
184
    {
186
    {
185
      if (face == 5)
187
      if (face == 5)
186
	fontname = g_strdup_printf(symbolname, 10 * size);
188
	fontname = g_strdup_printf(symbolname, 10 * size);
187
      else
189
      else
188
	fontname = g_strdup_printf(fontname_R6,
190
	fontname = g_strdup_printf(fontname_R6,
189
				   weight[(face-1)%2],
191
				   weight[(face-1)%2],
190
				   slant[((face-1)/2)%2],
192
				   slant[((face-1)/2)%2],
191
				   10 * size);
193
				   10 * size);
192
      
194
      
193
      tmp_font = RGTKLoadFont(fontname);
195
      tmp_font = RGTKLoadFont(fontname);
194
      g_free(fontname);
196
      g_free(fontname);
195
 
197
 
196
      if (tmp_font)
198
      if (tmp_font)
197
	{
199
	{
198
	  gd->font = tmp_font;
200
	  gd->font = tmp_font;
199
	  gd->fontface = face;
201
	  gd->fontface = face;
200
	  gd->fontsize = size;
202
	  gd->fontsize = size;
201
	}
203
	}
202
      else
204
      else
203
	{
205
	{
204
	  error("gdk font at size %d could not be loaded", size);
206
	  error("gdk font at size %d could not be loaded", size);
205
	}
207
	}
206
    }
208
    }
207
}
209
}
208
 
210
 
209
/* Get GNOME color specification from R color  */
211
/* Get GNOME color specification from R color  */
210
static guint32 Color_RGBA(int color)
212
static guint32 Color_RGBA(int color)
211
{
213
{
212
  int red, green, blue, alpha;
214
  int red, green, blue, alpha;
213
  
215
  
214
  red = R_RED(color);
216
  red = R_RED(color);
215
  green = R_GREEN(color);
217
  green = R_GREEN(color);
216
  blue = R_BLUE(color);
218
  blue = R_BLUE(color);
217
  alpha = 255 - R_ALPHA(color);
219
  alpha = 255 - R_ALPHA(color);
218
 
220
 
219
  return GNOME_CANVAS_COLOR_A(red, green, blue, alpha);
221
  return GNOME_CANVAS_COLOR_A(red, green, blue, alpha);
220
}
222
}
221
 
223
 
222
/* line type 
224
/* line type 
223
   fixme: not currently used 
225
   fixme: not currently used 
224
static void SetLineType(NewDevDesc *dd, int newlty, int newlwd)
226
static void SetLineType(NewDevDesc *dd, int newlty, int newlwd)
225
{
227
{
226
  static gchar dashlist[8];
228
  static gchar dashlist[8];
227
  gint i, j;
229
  gint i, j;
228
  gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
230
  gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
229
  
231
  
230
  if (newlty != gd->lty || newlwd != gd->lwd)
232
  if (newlty != gd->lty || newlwd != gd->lwd)
231
    {
233
    {
232
      if (newlty == 0)
234
      if (newlty == 0)
233
	{
235
	{
234
	  if(newlwd <= 1)
236
	  if(newlwd <= 1)
235
	    newlwd = 0;
237
	    newlwd = 0;
236
	  
238
	  
237
	  gdk_gc_set_line_attributes(gd->wgc, newlwd,
239
	  gdk_gc_set_line_attributes(gd->wgc, newlwd,
238
				     GDK_LINE_SOLID,
240
				     GDK_LINE_SOLID,
239
				     GDK_CAP_BUTT,
241
				     GDK_CAP_BUTT,
240
				     GDK_JOIN_ROUND);
242
				     GDK_JOIN_ROUND);
241
	}
243
	}
242
      else
244
      else
243
	{
245
	{
244
	  if (newlwd < 1)
246
	  if (newlwd < 1)
245
	    newlwd = 1;
247
	    newlwd = 1;
246
 
248
 
247
	  for(i = 0; (i < 8) && (newlty != 0); i++) {
249
	  for(i = 0; (i < 8) && (newlty != 0); i++) {
248
	    j = newlty & 15;
250
	    j = newlty & 15;
249
	    if(j == 0) j = 1;
251
	    if(j == 0) j = 1;
250
	    j = j * newlwd;
252
	    j = j * newlwd;
251
	    if(j > 255) j = 255;
253
	    if(j > 255) j = 255;
252
	    dashlist[i] = j;
254
	    dashlist[i] = j;
253
	    newlty = newlty >> 4;
255
	    newlty = newlty >> 4;
254
	  }
256
	  }
255
 
257
 
256
	  // set dashes
258
	  // set dashes
257
	  gdk_gc_set_dashes(gd->wgc, 0, dashlist, i);
259
	  gdk_gc_set_dashes(gd->wgc, 0, dashlist, i);
258
	  gdk_gc_set_line_attributes(gd->wgc, newlwd,
260
	  gdk_gc_set_line_attributes(gd->wgc, newlwd,
259
				     GDK_LINE_ON_OFF_DASH,
261
				     GDK_LINE_ON_OFF_DASH,
260
				     GDK_CAP_BUTT,
262
				     GDK_CAP_BUTT,
261
				     GDK_JOIN_ROUND);
263
				     GDK_JOIN_ROUND);
262
	}
264
	}
263
    }
265
    }
264
}
266
}
265
*/
267
*/
266
 
268
 
267
/* signal functions */
269
/* signal functions */
268
 
270
 
269
static gint configure_event(GtkWidget *widget, GdkEventConfigure *event,
271
static gint configure_event(GtkWidget *widget, GdkEventConfigure *event,
270
			    gpointer data) 
272
			    gpointer data) 
271
{
273
{
272
  NewDevDesc *dd;
274
  NewDevDesc *dd;
273
  gnomeDesc *gd;
275
  gnomeDesc *gd;
274
 
276
 
275
  dd = (NewDevDesc *) data;
277
  dd = (NewDevDesc *) data;
276
  g_return_val_if_fail(dd != NULL, FALSE);
278
  g_return_val_if_fail(dd != NULL, FALSE);
277
 
279
 
278
  gd = (gnomeDesc *) dd->deviceSpecific;
280
  gd = (gnomeDesc *) dd->deviceSpecific;
279
  g_return_val_if_fail(gd != NULL, FALSE);
281
  g_return_val_if_fail(gd != NULL, FALSE);
280
  g_return_val_if_fail(gd->canvas != NULL, FALSE);
282
  g_return_val_if_fail(gd->canvas != NULL, FALSE);
281
  g_return_val_if_fail(GNOME_IS_CANVAS(gd->canvas), FALSE);
283
  g_return_val_if_fail(GNOME_IS_CANVAS(gd->canvas), FALSE);
282
 
284
 
283
  if((gd->windowWidth != gd->canvas->allocation.width) ||
285
  if((gd->windowWidth != gd->canvas->allocation.width) ||
284
     (gd->windowHeight != gd->canvas->allocation.height))
286
     (gd->windowHeight != gd->canvas->allocation.height))
285
    {
287
    {
286
      gd->windowWidth = gd->canvas->allocation.width;
288
      gd->windowWidth = gd->canvas->allocation.width;
287
      gd->windowHeight = gd->canvas->allocation.height;
289
      gd->windowHeight = gd->canvas->allocation.height;
288
      gd->resize = TRUE;
290
      gd->resize = TRUE;
289
    }
291
    }
290
 
292
 
291
  return FALSE;
293
  return FALSE;
292
}
294
}
293
 
295
 
294
static gint expose_event(GtkWidget *widget, GdkEventExpose *event,
296
static gint expose_event(GtkWidget *widget, GdkEventExpose *event,
295
			 gpointer data)
297
			 gpointer data)
296
{
298
{
297
  NewDevDesc *dd;
299
  NewDevDesc *dd;
298
  gnomeDesc *gd;
300
  gnomeDesc *gd;
299
 
301
 
300
  dd = (NewDevDesc *) data;
302
  dd = (NewDevDesc *) data;
301
  g_return_val_if_fail(dd, FALSE);
303
  g_return_val_if_fail(dd, FALSE);
302
  gd = (gnomeDesc *) dd->deviceSpecific;
304
  gd = (gnomeDesc *) dd->deviceSpecific;
303
 
305
 
304
  if (gd->resize)
306
  if (gd->resize)
305
    {
307
    {
306
      GNOME_Resize(dd); 
308
      GNOME_Resize(dd); 
307
    }
309
    }
308
  
310
  
309
  GEplayDisplayList((GEDevDesc*) GetDevice(devNumber((DevDesc*)dd)));
311
  GEplayDisplayList((GEDevDesc*) GetDevice(devNumber((DevDesc*)dd)));
310
 
312
 
311
  return FALSE;
313
  return FALSE;
312
}
314
}
313
 
315
 
314
static gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) 
316
static gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) 
315
{
317
{
316
    NewDevDesc *dd;
318
    NewDevDesc *dd;
317
    gchar *cmd;
319
    gchar *cmd;
318
 
320
 
319
    dd = (NewDevDesc *) data;
321
    dd = (NewDevDesc *) data;
320
    g_return_val_if_fail(dd != NULL, FALSE);
322
    g_return_val_if_fail(dd != NULL, FALSE);
321
 
323
 
322
    cmd = g_strdup_printf("dev.off(%d)\n", RDeviceNumber(dd));
324
    cmd = g_strdup_printf("dev.off(%d)\n", RDeviceNumber(dd));
323
    R_gtk_terminal_run(cmd);
325
    R_gtk_terminal_run(cmd);
324
    g_free(cmd);
326
    g_free(cmd);
325
 
327
 
326
    return TRUE;
328
    return TRUE;
327
}
329
}
328
 
330
 
329
static void toolbar_activate_cb(GtkWidget *widget, gpointer data) 
331
static void toolbar_activate_cb(GtkWidget *widget, gpointer data) 
330
{
332
{
331
    NewDevDesc *dd;
333
    NewDevDesc *dd;
332
    gchar *cmd;
334
    gchar *cmd;
333
 
335
 
334
    g_return_if_fail(data);
336
    g_return_if_fail(data);
335
    dd = (NewDevDesc *) data;
337
    dd = (NewDevDesc *) data;
336
 
338
 
337
    cmd = g_strdup_printf("dev.set(%d)\n", RDeviceNumber(dd));
339
    cmd = g_strdup_printf("dev.set(%d)\n", RDeviceNumber(dd));
338
    R_gtk_terminal_run(cmd);
340
    R_gtk_terminal_run(cmd);
339
    g_free(cmd);
341
    g_free(cmd);
340
}
342
}
341
 
343
 
342
static void toolbar_close_cb(GtkWidget *widget, gpointer data) 
344
static void toolbar_close_cb(GtkWidget *widget, gpointer data) 
343
{
345
{
344
    NewDevDesc *dd;
346
    NewDevDesc *dd;
345
    gchar *cmd;
347
    gchar *cmd;
346
 
348
 
347
    g_return_if_fail(data);
349
    g_return_if_fail(data);
348
 
350
 
349
    dd = (NewDevDesc *) data;
351
    dd = (NewDevDesc *) data;
350
    cmd = g_strdup_printf("dev.off(%d)\n", RDeviceNumber(dd));
352
    cmd = g_strdup_printf("dev.off(%d)\n", RDeviceNumber(dd));
351
    R_gtk_terminal_run(cmd);
353
    R_gtk_terminal_run(cmd);
352
    g_free(cmd);
354
    g_free(cmd);
353
}
355
}
354
 
356
 
355
static void
357
static void
356
save_ok (GtkWidget *ok_button, gpointer data)
358
save_ok (GtkWidget *ok_button, gpointer data)
357
{
359
{
358
    NewDevDesc *dd;
360
    NewDevDesc *dd;
359
    GtkFileSelection *fsel = GTK_FILE_SELECTION(data);
361
    GtkFileSelection *fsel = GTK_FILE_SELECTION(data);
360
    char *filename = gtk_file_selection_get_filename(fsel);
362
    char *filename = gtk_file_selection_get_filename(fsel);
361
    char *cmd;
363
    char *cmd;
362
 
364
 
363
    if (!filename)
365
    if (!filename)
364
	return;
366
	return;
365
    
367
    
366
    dd = gtk_object_get_user_data(GTK_OBJECT(fsel));
368
    dd = gtk_object_get_user_data(GTK_OBJECT(fsel));
367
    cmd = g_strdup_printf("dev.set(%d)\ndev.print(file=\"%s\")\n",
369
    cmd = g_strdup_printf("dev.set(%d)\ndev.print(file=\"%s\")\n",
368
			  RDeviceNumber(dd), filename);
370
			  RDeviceNumber(dd), filename);
369
    R_gtk_terminal_run(cmd);
371
    R_gtk_terminal_run(cmd);
370
    
372
    
371
    g_free(cmd);
373
    g_free(cmd);
372
    gtk_widget_destroy (GTK_WIDGET(fsel));
374
    gtk_widget_destroy (GTK_WIDGET(fsel));
373
 
375
 
374
}
376
}
375
 
377
 
376
 
378
 
377
static void toolbar_save_as_cb(GtkWidget *widget, gpointer data)
379
static void toolbar_save_as_cb(GtkWidget *widget, gpointer data)
378
{
380
{
379
    NewDevDesc *dd = (NewDevDesc*) data;
381
    NewDevDesc *dd = (NewDevDesc*) data;
380
    gnomeDesc *gd = (gnomeDesc*) dd->deviceSpecific;
382
    gnomeDesc *gd = (gnomeDesc*) dd->deviceSpecific;
381
 
383
 
382
    GtkFileSelection *fsel = 
384
    GtkFileSelection *fsel = 
383
	GTK_FILE_SELECTION(gtk_file_selection_new("Save as PostScript"));
385
	GTK_FILE_SELECTION(gtk_file_selection_new("Save as PostScript"));
384
 
386
 
385
    gtk_object_set_user_data(GTK_OBJECT(fsel), dd);
387
    gtk_object_set_user_data(GTK_OBJECT(fsel), dd);
386
    gtk_file_selection_set_filename(fsel, "Rplots.ps");
388
    gtk_file_selection_set_filename(fsel, "Rplots.ps");
387
  
389
  
388
    gtk_signal_connect(GTK_OBJECT(fsel->ok_button), "clicked",
390
    gtk_signal_connect(GTK_OBJECT(fsel->ok_button), "clicked",
389
		       GTK_SIGNAL_FUNC(save_ok), fsel);
391
		       GTK_SIGNAL_FUNC(save_ok), fsel);
390
    gtk_signal_connect_object(GTK_OBJECT(fsel->cancel_button), "clicked",
392
    gtk_signal_connect_object(GTK_OBJECT(fsel->cancel_button), "clicked",
391
			      GTK_SIGNAL_FUNC(gtk_widget_destroy),
393
			      GTK_SIGNAL_FUNC(gtk_widget_destroy),
392
			      GTK_OBJECT(fsel));
394
			      GTK_OBJECT(fsel));
393
 
395
 
394
 
396
 
395
    gtk_window_position(GTK_WINDOW(fsel), GTK_WIN_POS_MOUSE);
397
    gtk_window_position(GTK_WINDOW(fsel), GTK_WIN_POS_MOUSE);
396
    gtk_window_set_transient_for(GTK_WINDOW(fsel), GTK_WINDOW(gd->window));
398
    gtk_window_set_transient_for(GTK_WINDOW(fsel), GTK_WINDOW(gd->window));
397
    gtk_widget_show(GTK_WIDGET(fsel));
399
    gtk_widget_show(GTK_WIDGET(fsel));
398
}
400
}
399
 
401
 
400
static void toolbar_print_cb (GtkWidget *widget, gpointer data)
402
static void toolbar_print_cb (GtkWidget *widget, gpointer data)
401
{
403
{
402
    NewDevDesc *dd = (NewDevDesc*) data;
404
    NewDevDesc *dd = (NewDevDesc*) data;
403
    gchar *cmd;
405
    gchar *cmd;
404
 
406
 
405
    cmd = g_strdup_printf("dev.set(%d)\ndev.print()",
407
    cmd = g_strdup_printf("dev.set(%d)\ndev.print()",
406
			  RDeviceNumber(dd));
408
			  RDeviceNumber(dd));
407
    R_gtk_terminal_run(cmd);
409
    R_gtk_terminal_run(cmd);
408
    g_free(cmd);
410
    g_free(cmd);
409
}
411
}
410
 
412
 
411
static GnomeUIInfo graphics_toolbar[] =
413
static GnomeUIInfo graphics_toolbar[] =
412
{
414
{
413
    { GNOME_APP_UI_ITEM, "Activate", "Make this window the current device",
415
    { GNOME_APP_UI_ITEM, "Activate", "Make this window the current device",
414
      (gpointer) toolbar_activate_cb, NULL, NULL, GNOME_APP_PIXMAP_STOCK,
416
      (gpointer) toolbar_activate_cb, NULL, NULL, GNOME_APP_PIXMAP_STOCK,
415
      GNOME_STOCK_PIXMAP_JUMP_TO, 0, (GdkModifierType) 0, NULL },
417
      GNOME_STOCK_PIXMAP_JUMP_TO, 0, (GdkModifierType) 0, NULL },
416
    GNOMEUIINFO_SEPARATOR,
418
    GNOMEUIINFO_SEPARATOR,
417
    { GNOME_APP_UI_ITEM, "Save As", "Save as a PostScript file", 
419
    { GNOME_APP_UI_ITEM, "Save As", "Save as a PostScript file", 
418
      (gpointer) toolbar_save_as_cb, NULL, NULL, 
420
      (gpointer) toolbar_save_as_cb, NULL, NULL, 
419
      GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_SAVE_AS, 0, 
421
      GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_SAVE_AS, 0, 
420
      (GdkModifierType) 0, NULL },
422
      (GdkModifierType) 0, NULL },
421
    { GNOME_APP_UI_ITEM, "Print", "Print graphics", 
423
    { GNOME_APP_UI_ITEM, "Print", "Print graphics", 
422
      (gpointer) toolbar_print_cb, NULL, NULL, 
424
      (gpointer) toolbar_print_cb, NULL, NULL, 
423
      GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_PRINT, 0, 
425
      GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_PRINT, 0, 
424
      (GdkModifierType) 0, NULL },
426
      (GdkModifierType) 0, NULL },
425
    GNOMEUIINFO_SEPARATOR,
427
    GNOMEUIINFO_SEPARATOR,
426
    { GNOME_APP_UI_ITEM, "Close", "Close this graphics device",
428
    { GNOME_APP_UI_ITEM, "Close", "Close this graphics device",
427
      (gpointer) toolbar_close_cb, NULL, NULL,
429
      (gpointer) toolbar_close_cb, NULL, NULL,
428
      GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_CLOSE, 0, 
430
      GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_CLOSE, 0, 
429
      (GdkModifierType) 0, NULL },
431
      (GdkModifierType) 0, NULL },
430
    GNOMEUIINFO_END
432
    GNOMEUIINFO_END
431
};
433
};
432
 
434
 
433
static void GNOME_NewPage(int fill, double gamma, NewDevDesc *dd)
435
static void GNOME_NewPage(R_GE_gcontext *gc,
-
 
436
			  NewDevDesc *dd)
434
{
437
{
435
  GnomeCanvasItem *group;
438
  GnomeCanvasItem *group;
436
  gnomeDesc *gd = (gnomeDesc*) dd->deviceSpecific;
439
  gnomeDesc *gd = (gnomeDesc*) dd->deviceSpecific;
437
 
440
 
438
  g_return_if_fail(gd->canvas);
441
  g_return_if_fail(gd->canvas);
439
 
442
 
440
  if (gd->group)
443
  if (gd->group)
441
    {
444
    {
442
      gtk_object_destroy(GTK_OBJECT(gd->group));
445
      gtk_object_destroy(GTK_OBJECT(gd->group));
443
      gd->plotarea = NULL;
446
      gd->plotarea = NULL;
444
    }
447
    }
445
  
448
  
446
  /* create group for plotting objects */
449
  /* create group for plotting objects */
447
  group = gnome_canvas_item_new (gnome_canvas_root(GNOME_CANVAS(gd->canvas)),
450
  group = gnome_canvas_item_new (gnome_canvas_root(GNOME_CANVAS(gd->canvas)),
448
				 gnome_canvas_group_get_type(),
451
				 gnome_canvas_group_get_type(),
449
				 "x", (double) 0.0,
452
				 "x", (double) 0.0,
450
				 "y", (double) 0.0,
453
				 "y", (double) 0.0,
451
				 NULL);
454
				 NULL);
452
  gd->group = GNOME_CANVAS_GROUP(group);
455
  gd->group = GNOME_CANVAS_GROUP(group);
453
  
456
  
454
  /* create plotting area */
457
  /* create plotting area */
455
  gd->plotarea = 
458
  gd->plotarea = 
456
    gnome_canvas_item_new (gd->group,
459
    gnome_canvas_item_new (gd->group,
457
			   gnome_canvas_rect_get_type(),
460
			   gnome_canvas_rect_get_type(),
458
			   "x1", (double) 0.0,
461
			   "x1", (double) 0.0,
459
			   "y1", (double) 0.0,
462
			   "y1", (double) 0.0,
460
			   "x2", (double) gd->windowWidth,
463
			   "x2", (double) gd->windowWidth,
461
			   "y2", (double) gd->windowHeight,
464
			   "y2", (double) gd->windowHeight,
462
			   NULL);
465
			   NULL);
463
 
466
 
464
  if (R_OPAQUE(fill))
467
  if (R_OPAQUE(gc->fill))
465
    {
468
    {
466
      gnome_canvas_item_set(gd->plotarea,
469
      gnome_canvas_item_set(gd->plotarea,
467
			    "fill_color_rgba", Color_RGBA(fill),
470
			    "fill_color_rgba", Color_RGBA(gc->fill),
468
			    NULL);
471
			    NULL);
469
    }
472
    }
470
  else
473
  else
471
    {
474
    {
472
      gnome_canvas_item_set(gd->plotarea,
475
      gnome_canvas_item_set(gd->plotarea,
473
			    "fill_color", "white",
476
			    "fill_color", "white",
474
			    NULL);
477
			    NULL);
475
    }
478
    }
476
}
479
}
477
 
480
 
478
/* create window etc */
481
/* create window etc */
479
static Rboolean
482
static Rboolean
480
GNOME_Open(NewDevDesc *dd, gnomeDesc *gd, char *dsp, double w, double h)
483
GNOME_Open(NewDevDesc *dd, gnomeDesc *gd, char *dsp, double w, double h)
481
{
484
{
482
    gint iw, ih;
485
    gint iw, ih;
-
 
486
    R_GE_gcontext gc;
483
 
487
 
484
    /*gdk_rgb_set_install(TRUE); */
488
    /*gdk_rgb_set_install(TRUE); */
485
    /* gdk_rgb_set_verbose(TRUE);*/
489
    /* gdk_rgb_set_verbose(TRUE);*/
486
    gdk_rgb_init();
490
    gdk_rgb_init();
487
    gtk_widget_push_visual(gdk_rgb_get_visual());
491
    gtk_widget_push_visual(gdk_rgb_get_visual());
488
    gtk_widget_push_colormap(gdk_rgb_get_cmap());
492
    gtk_widget_push_colormap(gdk_rgb_get_cmap());
489
 
493
 
490
    /* initialise pointers */
494
    /* initialise pointers */
491
    gd->canvas = NULL;
495
    gd->canvas = NULL;
492
    gd->group = NULL;
496
    gd->group = NULL;
493
    gd->plotarea = NULL;
497
    gd->plotarea = NULL;
494
 
498
 
495
    if(!SetBaseFont(gd))
499
    if(!SetBaseFont(gd))
496
      {
500
      {
497
	Rprintf("can't find X11 font\n");
501
	Rprintf("can't find X11 font\n");
498
	return FALSE;
502
	return FALSE;
499
      }
503
      }
500
 
504
 
501
    /* create window etc */
505
    /* create window etc */
502
    gd->windowWidth = iw = w / pixelWidth();
506
    gd->windowWidth = iw = w / pixelWidth();
503
    gd->windowHeight = ih = h / pixelHeight();
507
    gd->windowHeight = ih = h / pixelHeight();
504
 
508
 
505
    gd->window = gnome_app_new("R.gnome.graphics", "R Graphics");
509
    gd->window = gnome_app_new("R.gnome.graphics", "R Graphics");
506
 
510
 
507
    gtk_window_set_policy(GTK_WINDOW(gd->window), TRUE, TRUE, FALSE);
511
    gtk_window_set_policy(GTK_WINDOW(gd->window), TRUE, TRUE, FALSE);
508
    gtk_widget_realize(gd->window);
512
    gtk_widget_realize(gd->window);
509
 
513
 
510
    /* create toolbar */
514
    /* create toolbar */
511
    gnome_app_create_toolbar_with_data(GNOME_APP(gd->window), graphics_toolbar,
515
    gnome_app_create_toolbar_with_data(GNOME_APP(gd->window), graphics_toolbar,
512
				       (gpointer) dd);
516
				       (gpointer) dd);
513
 
517
 
514
    /* create canvas */
518
    /* create canvas */
515
    gd->canvas = gnome_canvas_new_aa();
519
    gd->canvas = gnome_canvas_new_aa();
516
    gtk_widget_set_usize(gd->canvas, iw, ih);
520
    gtk_widget_set_usize(gd->canvas, iw, ih);
517
    gnome_canvas_set_scroll_region(GNOME_CANVAS(gd->canvas), 0, 0, iw, ih);
521
    gnome_canvas_set_scroll_region(GNOME_CANVAS(gd->canvas), 0, 0, iw, ih);
518
 
522
 
519
    /* create new plot area on canvas */
523
    /* create new plot area on canvas */
520
    /* FIXME: We should have a canvas color argument */
524
    /* FIXME: We should have a canvas color argument */
521
    /* gamma is defaulted to 1 here */
525
    /* gamma is defaulted to 1 here */
-
 
526
    /* 
-
 
527
     * WARNING: Many graphical parameters are unset - if GNOME_NewPage
-
 
528
     * starts to make use of more than fill and gamma then more 
-
 
529
     * parameters need setting here.
-
 
530
     */
522
    GNOME_NewPage(R_RGB(255,255,255), 1, dd);
531
    gc.fill = R_RGB(255,255,255);
-
 
532
    gc.gamma = 1;
-
 
533
    GNOME_NewPage(&gc, dd);
523
 
534
 
524
    /* place and realize the canvas */
535
    /* place and realize the canvas */
525
    gnome_app_set_contents(GNOME_APP(gd->window), gd->canvas);
536
    gnome_app_set_contents(GNOME_APP(gd->window), gd->canvas);
526
    gtk_widget_realize(gd->canvas);
537
    gtk_widget_realize(gd->canvas);
527
 
538
 
528
    /* same as XSynch() */
539
    /* same as XSynch() */
529
    gdk_flush();
540
    gdk_flush();
530
 
541
 
531
    /* set the cursor */
542
    /* set the cursor */
532
    gd->gcursor = gdk_cursor_new(GDK_CROSSHAIR);
543
    gd->gcursor = gdk_cursor_new(GDK_CROSSHAIR);
533
    gdk_window_set_cursor(gd->canvas->window, gd->gcursor);
544
    gdk_window_set_cursor(gd->canvas->window, gd->gcursor);
534
    
545
    
535
    /* connect to delete signal handler, etc */
546
    /* connect to delete signal handler, etc */
536
    gtk_signal_connect(GTK_OBJECT(gd->window), "configure_event",
547
    gtk_signal_connect(GTK_OBJECT(gd->window), "configure_event",
537
		       (GtkSignalFunc) configure_event, (gpointer) dd);
548
		       (GtkSignalFunc) configure_event, (gpointer) dd);
538
    gtk_signal_connect(GTK_OBJECT(gd->canvas), "expose_event",
549
    gtk_signal_connect(GTK_OBJECT(gd->canvas), "expose_event",
539
		       (GtkSignalFunc) expose_event, (gpointer) dd);
550
		       (GtkSignalFunc) expose_event, (gpointer) dd);
540
    gtk_signal_connect(GTK_OBJECT(gd->window), "delete_event",
551
    gtk_signal_connect(GTK_OBJECT(gd->window), "delete_event",
541
		       (GtkSignalFunc) delete_event, (gpointer) dd);
552
		       (GtkSignalFunc) delete_event, (gpointer) dd);
542
 
553
 
543
    /* show everything */
554
    /* show everything */
544
    gtk_widget_show_all(gd->window);
555
    gtk_widget_show_all(gd->window);
545
 
556
 
546
    /* let other widgets use the default settings */
557
    /* let other widgets use the default settings */
547
    gtk_widget_pop_visual();
558
    gtk_widget_pop_visual();
548
    gtk_widget_pop_colormap();
559
    gtk_widget_pop_colormap();
549
 
560
 
550
    /* we made it! */
561
    /* we made it! */
551
    return TRUE;
562
    return TRUE;
552
}
563
}
553
 
564
 
554
static double GNOME_StrWidth(char *str, int font,
565
static double GNOME_StrWidth(char *str, 
-
 
566
			     R_GE_gcontext *gc,
555
			      double cex, double ps, NewDevDesc *dd)
567
			     NewDevDesc *dd)
556
{
568
{
557
  int size;
569
  int size;
558
  gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
570
  gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
559
 
571
 
560
  size = cex * ps + 0.5;
572
  size = gc->cex * gc->ps + 0.5;
561
  SetFont(dd, font, size);
573
  SetFont(dd, gc->fontface, size);
562
 
574
 
563
  return (double) gdk_string_width(gd->font, str);
575
  return (double) gdk_string_width(gd->font, str);
564
}
576
}
565
 
577
 
566
static void GNOME_MetricInfo(int c, int font, double cex, double ps,
578
static void GNOME_MetricInfo(int c, 
-
 
579
			     R_GE_gcontext *gc,
567
			      double* ascent, double* descent,
580
			     double* ascent, double* descent,
568
			      double* width, NewDevDesc *dd)
581
			     double* width, NewDevDesc *dd)
569
{
582
{
570
  gint size;
583
  gint size;
571
  gint lbearing, rbearing, iascent, idescent, iwidth;
584
  gint lbearing, rbearing, iascent, idescent, iwidth;
572
  gint maxwidth;
585
  gint maxwidth;
573
  gchar tmp[2];
586
  gchar tmp[2];
574
  gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
587
  gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
575
 
588
 
576
  size = cex * ps + 0.5;
589
  size = gc->cex * gc->ps + 0.5;
577
  SetFont(dd, font, size);
590
  SetFont(dd, gc->fontface, size);
578
 
591
 
579
  if(c == 0) {
592
  if(c == 0) {
580
    maxwidth = 0;
593
    maxwidth = 0;
581
 
594
 
582
    for(c = 0; c <= 255; c++) {
595
    for(c = 0; c <= 255; c++) {
583
      g_snprintf(tmp, 2, "%c", (gchar) c);
596
      g_snprintf(tmp, 2, "%c", (gchar) c);
584
      iwidth = gdk_string_width(gd->font, tmp);
597
      iwidth = gdk_string_width(gd->font, tmp);
585
      if (iwidth > maxwidth)
598
      if (iwidth > maxwidth)
586
	maxwidth = iwidth;
599
	maxwidth = iwidth;
587
    }
600
    }
588
 
601
 
589
    *ascent = (double) gd->font->ascent;
602
    *ascent = (double) gd->font->ascent;
590
    *descent = (double) gd->font->descent;
603
    *descent = (double) gd->font->descent;
591
    *width = (double) maxwidth;
604
    *width = (double) maxwidth;
592
  }
605
  }
593
  else {
606
  else {
594
    g_snprintf(tmp, 2, "%c", (gchar) c);
607
    g_snprintf(tmp, 2, "%c", (gchar) c);
595
    gdk_string_extents(gd->font, tmp,
608
    gdk_string_extents(gd->font, tmp,
596
		       &lbearing, &rbearing,
609
		       &lbearing, &rbearing,
597
		       &iwidth, &iascent, &idescent);
610
		       &iwidth, &iascent, &idescent);
598
 
611
 
599
    *ascent = (double) iascent;
612
    *ascent = (double) iascent;
600
    *descent = (double) idescent;
613
    *descent = (double) idescent;
601
    *width = (double) (lbearing+rbearing);
614
    *width = (double) (lbearing+rbearing);
602
  }
615
  }
603
}
616
}
604
 
617
 
605
static void GNOME_Resize(NewDevDesc *dd)
618
static void GNOME_Resize(NewDevDesc *dd)
606
{
619
{
607
  gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
620
  gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
608
 
621
 
609
  if (gd->resize) {
622
  if (gd->resize) {
610
    dd->left = 0.0;
623
    dd->left = 0.0;
611
    dd->right =  gd->windowWidth;
624
    dd->right =  gd->windowWidth;
612
    dd->bottom = gd->windowHeight;
625
    dd->bottom = gd->windowHeight;
613
    dd->top = 0.0;
626
    dd->top = 0.0;
614
    gd->resize = FALSE;
627
    gd->resize = FALSE;
615
 
628
 
616
    gtk_widget_set_usize(gd->canvas, gd->windowWidth, gd->windowHeight);
629
    gtk_widget_set_usize(gd->canvas, gd->windowWidth, gd->windowHeight);
617
    gnome_canvas_set_scroll_region(GNOME_CANVAS(gd->canvas), 0, 0,
630
    gnome_canvas_set_scroll_region(GNOME_CANVAS(gd->canvas), 0, 0,
618
				   gd->windowWidth, gd->windowHeight);
631
				   gd->windowWidth, gd->windowHeight);
619
    gnome_canvas_item_set(gd->plotarea,
632
    gnome_canvas_item_set(gd->plotarea,
620
			  "x2", (double) gd->windowWidth,
633
			  "x2", (double) gd->windowWidth,
621
			  "y2", (double) gd->windowHeight,
634
			  "y2", (double) gd->windowHeight,
622
			  NULL);
635
			  NULL);
623
  }
636
  }
624
}
637
}
625
 
638
 
626
static void GNOME_Clip(double x0, double x1, double y0, double y1, NewDevDesc *dd)
639
static void GNOME_Clip(double x0, double x1, double y0, double y1, NewDevDesc *dd)
627
{
640
{
628
  /* 
641
  /* 
629
     Clipping is theoretically possible: there is an implementation of
642
     Clipping is theoretically possible: there is an implementation of
630
     it in gnome-print-preview, which has a class called clipped-group. As
643
     it in gnome-print-preview, which has a class called clipped-group. As
631
     the name suggests, this is a canvas group which defines a
644
     the name suggests, this is a canvas group which defines a
632
     clipping path for the items it contains.  The notes say that this
645
     clipping path for the items it contains.  The notes say that this
633
     will be folded into the standard GnomeCanvasGroup, so I'm waiting
646
     will be folded into the standard GnomeCanvasGroup, so I'm waiting
634
     for this to happen instead of duplicating it here. MTP 6/9/2001
647
     for this to happen instead of duplicating it here. MTP 6/9/2001
635
  */
648
  */
636
}
649
}
637
 
650
 
638
static void GNOME_Size(double *left, double *right,
651
static void GNOME_Size(double *left, double *right,
639
		     double *bottom, double *top,
652
		     double *bottom, double *top,
640
		     NewDevDesc *dd)
653
		     NewDevDesc *dd)
641
{
654
{
642
    gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
655
    gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
643
 
656
 
644
    *left = 0.0;
657
    *left = 0.0;
645
    *right =  gd->windowWidth;
658
    *right =  gd->windowWidth;
646
    *bottom = gd->windowHeight;
659
    *bottom = gd->windowHeight;
647
    *top = 0.0;
660
    *top = 0.0;
648
}
661
}
649
 
662
 
650
 
663
 
651
/* kill off the window etc */
664
/* kill off the window etc */
652
static void GNOME_Close(NewDevDesc *dd)
665
static void GNOME_Close(NewDevDesc *dd)
653
{
666
{
654
    gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
667
    gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
655
 
668
 
656
    gtk_widget_destroy(gd->window);
669
    gtk_widget_destroy(gd->window);
657
 
670
 
658
    free(gd);
671
    free(gd);
659
}
672
}
660
 
673
 
661
#define title_text_inactive "R graphics device %d"
674
#define title_text_inactive "R graphics device %d"
662
#define title_text_active "R graphics device %d - Active"
675
#define title_text_active "R graphics device %d - Active"
663
 
676
 
664
static void GNOME_Activate(NewDevDesc *dd)
677
static void GNOME_Activate(NewDevDesc *dd)
665
{
678
{
666
    gnomeDesc *gd;
679
    gnomeDesc *gd;
667
    gint devnum, numdigits;
680
    gint devnum, numdigits;
668
    gchar *title_text;
681
    gchar *title_text;
669
    gint text_len;
682
    gint text_len;
670
 
683
 
671
    text_len = strlen(title_text_active);
684
    text_len = strlen(title_text_active);
672
 
685
 
673
    gd = (gnomeDesc *) dd->deviceSpecific;
686
    gd = (gnomeDesc *) dd->deviceSpecific;
674
 
687
 
675
    g_return_if_fail(gd != NULL);
688
    g_return_if_fail(gd != NULL);
676
 
689
 
677
    devnum = devNumber((DevDesc*)dd);
690
    devnum = devNumber((DevDesc*)dd);
678
    devnum++;
691
    devnum++;
679
    numdigits = floor(R_Log10(devnum)) + 1;
692
    numdigits = floor(R_Log10(devnum)) + 1;
680
    title_text = g_malloc(text_len + numdigits + 1);
693
    title_text = g_malloc(text_len + numdigits + 1);
681
 
694
 
682
    g_return_if_fail(title_text != NULL);
695
    g_return_if_fail(title_text != NULL);
683
 
696
 
684
    g_snprintf(title_text, text_len + numdigits + 1, title_text_active, devnum);
697
    g_snprintf(title_text, text_len + numdigits + 1, title_text_active, devnum);
685
    *(title_text + text_len + numdigits) = '\0';
698
    *(title_text + text_len + numdigits) = '\0';
686
 
699
 
687
    gtk_window_set_title(GTK_WINDOW(gd->window), title_text);
700
    gtk_window_set_title(GTK_WINDOW(gd->window), title_text);
688
 
701
 
689
    g_free(title_text);
702
    g_free(title_text);
690
}
703
}
691
 
704
 
692
static void GNOME_Deactivate(NewDevDesc *dd)
705
static void GNOME_Deactivate(NewDevDesc *dd)
693
{
706
{
694
    gnomeDesc *gd;
707
    gnomeDesc *gd;
695
    gint devnum, numdigits;
708
    gint devnum, numdigits;
696
    gchar *title_text;
709
    gchar *title_text;
697
    gint text_len;
710
    gint text_len;
698
 
711
 
699
    text_len = strlen(title_text_inactive);
712
    text_len = strlen(title_text_inactive);
700
 
713
 
701
    gd = (gnomeDesc *) dd->deviceSpecific;
714
    gd = (gnomeDesc *) dd->deviceSpecific;
702
 
715
 
703
    g_return_if_fail(gd != NULL);
716
    g_return_if_fail(gd != NULL);
704
 
717
 
705
    devnum = devNumber((DevDesc*)dd);
718
    devnum = devNumber((DevDesc*)dd);
706
    devnum++;
719
    devnum++;
707
    numdigits = floor(R_Log10(devnum)) + 1;
720
    numdigits = floor(R_Log10(devnum)) + 1;
708
    title_text = g_malloc(text_len + numdigits + 1);
721
    title_text = g_malloc(text_len + numdigits + 1);
709
 
722
 
710
    g_return_if_fail(title_text != NULL);
723
    g_return_if_fail(title_text != NULL);
711
 
724
 
712
    g_snprintf(title_text, text_len + numdigits + 1, title_text_inactive, devnum);
725
    g_snprintf(title_text, text_len + numdigits + 1, title_text_inactive, devnum);
713
    *(title_text + text_len + numdigits) = '\0';
726
    *(title_text + text_len + numdigits) = '\0';
714
 
727
 
715
    gtk_window_set_title(GTK_WINDOW(gd->window), title_text);
728
    gtk_window_set_title(GTK_WINDOW(gd->window), title_text);
716
 
729
 
717
    g_free(title_text);
730
    g_free(title_text);
718
}
731
}
719
 
732
 
720
/* drawing stuff */
733
/* drawing stuff */
721
 
734
 
722
static void GNOME_Rect(double x0, double y0, double x1, double y1,
735
static void GNOME_Rect(double x0, double y0, double x1, double y1,
723
		     int col, int fill, double gamma, int lty, double lwd,
736
		       R_GE_gcontext *gc,
724
		     NewDevDesc *dd)
737
		       NewDevDesc *dd)
725
{
738
{
726
    double tmp;
739
    double tmp;
727
    gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
740
    gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
728
    GnomeCanvasItem *item;
741
    GnomeCanvasItem *item;
729
 
742
 
730
    if(x0 > x1) {
743
    if(x0 > x1) {
731
	tmp = x0;
744
	tmp = x0;
732
	x0 = x1;
745
	x0 = x1;
733
	x1 = tmp;
746
	x1 = tmp;
734
    }
747
    }
735
    if(y0 > y1) {
748
    if(y0 > y1) {
736
	tmp = y0;
749
	tmp = y0;
737
	y0 = y1;
750
	y0 = y1;
738
	y1 = tmp;
751
	y1 = tmp;
739
    }
752
    }
740
 
753
 
741
    item = gnome_canvas_item_new(gd->group,
754
    item = gnome_canvas_item_new(gd->group,
742
				 gnome_canvas_rect_get_type(),
755
				 gnome_canvas_rect_get_type(),
743
				 "x1", x0,
756
				 "x1", x0,
744
				 "y1", y0,
757
				 "y1", y0,
745
				 "x2", x1,
758
				 "x2", x1,
746
				 "y2", y1,
759
				 "y2", y1,
747
				 "width_units", (double) lwd,
760
				 "width_units", (double) gc->lwd,
748
				 NULL);
761
				 NULL);
749
 
762
 
750
    if(fill != NA_INTEGER) {
763
    if(gc->fill != NA_INTEGER) {
751
	gnome_canvas_item_set(item,
764
	gnome_canvas_item_set(item,
752
			      "fill_color_rgba", Color_RGBA(fill),
765
			      "fill_color_rgba", Color_RGBA(gc->fill),
753
			      NULL);
766
			      NULL);
754
    }
767
    }
755
    if(col != NA_INTEGER) {
768
    if(gc->col != NA_INTEGER) {
756
	gnome_canvas_item_set(item,
769
	gnome_canvas_item_set(item,
757
			      "outline_color_rgba", Color_RGBA(col),
770
			      "outline_color_rgba", Color_RGBA(gc->col),
758
			      NULL);
771
			      NULL);
759
    }
772
    }
760
}
773
}
761
 
774
 
762
static void GNOME_Circle(double x, double y, double r,
775
static void GNOME_Circle(double x, double y, double r,
763
		       int col, int fill, double gamma, int lty, double lwd,
776
			 R_GE_gcontext *gc,
764
		       NewDevDesc *dd)
777
			 NewDevDesc *dd)
765
{
778
{
766
    double x1, y1, x2, y2;
779
    double x1, y1, x2, y2;
767
    gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
780
    gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
768
    GnomeCanvasItem *item;
781
    GnomeCanvasItem *item;
769
 
782
 
770
    x1 = x - r;  y1 = y - r;
783
    x1 = x - r;  y1 = y - r;
771
    x2 = x + r;  y2 = y + r;
784
    x2 = x + r;  y2 = y + r;
772
 
785
 
773
    item = gnome_canvas_item_new(gd->group,
786
    item = gnome_canvas_item_new(gd->group,
774
				 gnome_canvas_ellipse_get_type(),
787
				 gnome_canvas_ellipse_get_type(),
775
				 "x1", x1,
788
				 "x1", x1,
776
				 "y1", y1,
789
				 "y1", y1,
777
				 "x2", x2,
790
				 "x2", x2,
778
				 "y2", y2,
791
				 "y2", y2,
779
				 "width_units", (double) lwd,
792
				 "width_units", (double) gc->lwd,
780
				 NULL);
793
				 NULL);
781
 
794
 
782
    if(fill != NA_INTEGER) {
795
    if(gc->fill != NA_INTEGER) {
783
	gnome_canvas_item_set(item,
796
	gnome_canvas_item_set(item,
784
			      "fill_color_rgba", Color_RGBA(fill),
797
			      "fill_color_rgba", Color_RGBA(gc->fill),
785
			      NULL);
798
			      NULL);
786
    }
799
    }
787
    if(col != NA_INTEGER) {
800
    if(gc->col != NA_INTEGER) {
788
	gnome_canvas_item_set(item,
801
	gnome_canvas_item_set(item,
789
			      "outline_color_rgba", Color_RGBA(col),
802
			      "outline_color_rgba", Color_RGBA(gc->col),
790
			      NULL);
803
			      NULL);
791
    }
804
    }
792
}
805
}
793
 
806
 
794
static void GNOME_Line(double x1, double y1, double x2, double y2,
807
static void GNOME_Line(double x1, double y1, double x2, double y2,
795
		     int col, double gamma, int lty, double lwd,
808
		       R_GE_gcontext *gc,
796
		     NewDevDesc *dd)
809
		       NewDevDesc *dd)
797
{
810
{
798
    GnomeCanvasPoints *points;
811
    GnomeCanvasPoints *points;
799
    gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
812
    gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
800
    GnomeCanvasItem *item;
813
    GnomeCanvasItem *item;
801
 
814
 
802
    points = gnome_canvas_points_new(2);
815
    points = gnome_canvas_points_new(2);
803
    points->coords[0] = x1;
816
    points->coords[0] = x1;
804
    points->coords[1] = y1;
817
    points->coords[1] = y1;
805
    points->coords[2] = x2;
818
    points->coords[2] = x2;
806
    points->coords[3] = y2;
819
    points->coords[3] = y2;
807
 
820
 
808
    item = gnome_canvas_item_new(gd->group,
821
    item = gnome_canvas_item_new(gd->group,
809
				 gnome_canvas_line_get_type(),
822
				 gnome_canvas_line_get_type(),
810
				 "points", points,
823
				 "points", points,
811
				 "width_units", (double) lwd,
824
				 "width_units", (double) gc->lwd,
812
				 NULL);
825
				 NULL);
813
 
826
 
814
    if(col != NA_INTEGER) {
827
    if(gc->col != NA_INTEGER) {
815
	if(lty != 0) {
828
	if(gc->lty != 0) {
816
	    /*SetLineType(GNOME_CANVAS_LINE(item)->gc, lty, lwd);*/
829
	    /*SetLineType(GNOME_CANVAS_LINE(item)->gc, lty, lwd);*/
817
	    gnome_canvas_item_set(item,
830
	    gnome_canvas_item_set(item,
818
				  "line_style", GDK_LINE_ON_OFF_DASH,
831
				  "line_style", GDK_LINE_ON_OFF_DASH,
819
				  NULL);
832
				  NULL);
820
	}
833
	}
821
	gnome_canvas_item_set(item,
834
	gnome_canvas_item_set(item,
822
			      "fill_color_rgba", Color_RGBA(col),
835
			      "fill_color_rgba", Color_RGBA(gc->col),
823
			      NULL);
836
			      NULL);
824
    }
837
    }
825
 
838
 
826
    gnome_canvas_points_free(points);
839
    gnome_canvas_points_free(points);
827
}
840
}
828
 
841
 
829
static void GNOME_Polyline(int n, double *x, double *y, 
842
static void GNOME_Polyline(int n, double *x, double *y, 
830
			    int col, double gamma, int lty, double lwd,
843
			   R_GE_gcontext *gc,
831
			    NewDevDesc *dd)
844
			   NewDevDesc *dd)
832
{
845
{
833
    int i;
846
    int i;
834
    GnomeCanvasPoints *points;
847
    GnomeCanvasPoints *points;
835
    gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
848
    gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
836
    GnomeCanvasItem *item;
849
    GnomeCanvasItem *item;
837
 
850
 
838
    points = gnome_canvas_points_new(n);
851
    points = gnome_canvas_points_new(n);
839
 
852
 
840
    for(i = 0; i < n; i++) {
853
    for(i = 0; i < n; i++) {
841
	points->coords[i * 2] = x[i];
854
	points->coords[i * 2] = x[i];
842
	points->coords[i * 2 + 1] = y[i];
855
	points->coords[i * 2 + 1] = y[i];
843
    }
856
    }
844
 
857
 
845
    item = gnome_canvas_item_new(gd->group,
858
    item = gnome_canvas_item_new(gd->group,
846
				 gnome_canvas_line_get_type(),
859
				 gnome_canvas_line_get_type(),
847
				 "points", points,
860
				 "points", points,
848
				 "width_units", (double) lwd,
861
				 "width_units", (double) gc->lwd,
849
				 NULL);
862
				 NULL);
850
 
863
 
851
    if(col != NA_INTEGER) {
864
    if(gc->col != NA_INTEGER) {
852
	if(lty != 0) {
865
	if(gc->lty != 0) {
853
	  /*
866
	  /*
854
	    SetLineType(&stipple, lty, lwd);
867
	    SetLineType(&stipple, lty, lwd);
855
	    gnome_canvas_item_set(item,
868
	    gnome_canvas_item_set(item,
856
				  "fill_stipple", &stipple,
869
				  "fill_stipple", &stipple,
857
				  NULL);
870
				  NULL);
858
	    */
871
	    */
859
	    gnome_canvas_item_set(item,
872
	    gnome_canvas_item_set(item,
860
				  "line_style", GDK_LINE_ON_OFF_DASH,
873
				  "line_style", GDK_LINE_ON_OFF_DASH,
861
				  NULL);
874
				  NULL);
862
	}
875
	}
863
	gnome_canvas_item_set(item,
876
	gnome_canvas_item_set(item,
864
			      "fill_color_rgba", Color_RGBA(col),
877
			      "fill_color_rgba", Color_RGBA(gc->col),
865
			      NULL);
878
			      NULL);
866
    }
879
    }
867
 
880
 
868
    gnome_canvas_points_free(points);
881
    gnome_canvas_points_free(points);
869
}
882
}
870
 
883
 
871
static void GNOME_Polygon(int n, double *x, double *y, 
884
static void GNOME_Polygon(int n, double *x, double *y, 
872
			int col, int fill, double gamma, int lty, double lwd,
885
			  R_GE_gcontext *gc,
873
			NewDevDesc *dd)
886
			  NewDevDesc *dd)
874
{
887
{
875
    int i;
888
    int i;
876
    GnomeCanvasPoints *points;
889
    GnomeCanvasPoints *points;
877
    gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
890
    gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
878
    GnomeCanvasItem *item;
891
    GnomeCanvasItem *item;
879
 
892
 
880
    points = gnome_canvas_points_new(n);
893
    points = gnome_canvas_points_new(n);
881
 
894
 
882
    for(i = 0; i < n; i++) {
895
    for(i = 0; i < n; i++) {
883
	points->coords[i * 2] = floor(x[i]);
896
	points->coords[i * 2] = floor(x[i]);
884
	points->coords[i * 2 + 1] = floor(y[i]);
897
	points->coords[i * 2 + 1] = floor(y[i]);
885
    }
898
    }
886
 
899
 
887
    item = gnome_canvas_item_new(gd->group,
900
    item = gnome_canvas_item_new(gd->group,
888
				 gnome_canvas_polygon_get_type(),
901
				 gnome_canvas_polygon_get_type(),
889
				 "points", points,
902
				 "points", points,
890
				 "width_units", (double) 2,
903
				 "width_units", (double) 2,
891
				 NULL);
904
				 NULL);
892
 
905
 
893
    if(fill != NA_INTEGER) {
906
    if(gc->fill != NA_INTEGER) {
894
	gnome_canvas_item_set(item,
907
	gnome_canvas_item_set(item,
895
			      "fill_color_rgba", Color_RGBA(fill),
908
			      "fill_color_rgba", Color_RGBA(gc->fill),
896
			      NULL);
909
			      NULL);
897
    }
910
    }
898
    if(col != NA_INTEGER) {
911
    if(gc->col != NA_INTEGER) {
899
	gnome_canvas_item_set(item,
912
	gnome_canvas_item_set(item,
900
			      "outline_color_rgba", Color_RGBA(col),
913
			      "outline_color_rgba", Color_RGBA(gc->col),
901
			      NULL);
914
			      NULL);
902
    }
915
    }
903
 
916
 
904
    gnome_canvas_points_free(points);
917
    gnome_canvas_points_free(points);
905
}
918
}
906
 
919
 
907
static void GNOME_Text(double x, double y, char *str, 
920
static void GNOME_Text(double x, double y, char *str, 
908
		     double rot, double hadj, 
921
		       double rot, double hadj, 
909
		     int col, double gamma, int font, double cex, double ps,
922
		       R_GE_gcontext *gc,
910
		     NewDevDesc *dd)
923
		       NewDevDesc *dd)
911
{
924
{
912
  double affine[6] = {1, 0, 0, 1, 0, 0};
925
  double affine[6] = {1, 0, 0, 1, 0, 0};
913
  double rrot = DEG2RAD * rot;
926
  double rrot = DEG2RAD * rot;
914
  GnomeCanvasItem *item;
927
  GnomeCanvasItem *item;
915
  gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
928
  gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
916
  int size;
929
  int size;
917
 
930
 
918
  size = cex * ps + 0.5;
931
  size = gc->cex * gc->ps + 0.5;
919
  SetFont(dd, font, size);
932
  SetFont(dd, gc->fontface, size);
920
  
933
  
921
  if (rot != 0)
934
  if (rot != 0)
922
    {
935
    {
923
      affine[0] = affine[3] = cos(rrot);
936
      affine[0] = affine[3] = cos(rrot);
924
      affine[1] = -sin(rrot);
937
      affine[1] = -sin(rrot);
925
      affine[2] = -affine[1];
938
      affine[2] = -affine[1];
926
      affine[4] = x;
939
      affine[4] = x;
927
      affine[5] = y;
940
      affine[5] = y;
928
      x = y = 0.0;
941
      x = y = 0.0;
929
    }
942
    }
930
 
943
 
931
  item = gnome_canvas_item_new (gd->group,
944
  item = gnome_canvas_item_new (gd->group,
932
				gnome_canvas_text_get_type(),
945
				gnome_canvas_text_get_type(),
933
				"text", str,
946
				"text", str,
934
				"anchor", GTK_ANCHOR_SOUTH_WEST,
947
				"anchor", GTK_ANCHOR_SOUTH_WEST,
935
				"x", x,
948
				"x", x,
936
				"y", y,
949
				"y", y,
937
				"font_gdk", gd->font,
950
				"font_gdk", gd->font,
938
				"fill_color_rgba", Color_RGBA(col),
951
				"fill_color_rgba", Color_RGBA(gc->col),
939
				NULL);
952
				NULL);
940
 
953
 
941
  if (rot != 0)
954
  if (rot != 0)
942
    gnome_canvas_item_affine_relative (item, affine);
955
    gnome_canvas_item_affine_relative (item, affine);
943
}
956
}
944
 
957
 
945
/* locator */
958
/* locator */
946
 
959
 
947
static gint locator_cb (GtkWidget * canvas, GdkEventButton * event,
960
static gint locator_cb (GtkWidget * canvas, GdkEventButton * event,
948
			gpointer data)
961
			gpointer data)
949
{
962
{
950
  GdkEventButton *info = (GdkEventButton*) data;
963
  GdkEventButton *info = (GdkEventButton*) data;
951
  
964
  
952
  *info = *event;
965
  *info = *event;
953
  gtk_main_quit();
966
  gtk_main_quit();
954
 
967
 
955
  return FALSE;
968
  return FALSE;
956
}
969
}
957
 
970
 
958
static Rboolean GNOME_Locator(double *x, double *y, NewDevDesc *dd)
971
static Rboolean GNOME_Locator(double *x, double *y, NewDevDesc *dd)
959
{
972
{
960
  gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
973
  gnomeDesc *gd = (gnomeDesc *) dd->deviceSpecific;
961
  GdkEventButton info;
974
  GdkEventButton info;
962
  guint handler_id;
975
  guint handler_id;
963
 
976
 
964
  /* Flush any pending events */
977
  /* Flush any pending events */
965
  while (gtk_events_pending())
978
  while (gtk_events_pending())
966
    gtk_main_iteration();
979
    gtk_main_iteration();
967
 
980
 
968
  /* connect signal */
981
  /* connect signal */
969
  handler_id = gtk_signal_connect (GTK_OBJECT (gd->canvas),
982
  handler_id = gtk_signal_connect (GTK_OBJECT (gd->canvas),
970
				   "button-press-event",
983
				   "button-press-event",
971
				   GTK_SIGNAL_FUNC (locator_cb), &info);
984
				   GTK_SIGNAL_FUNC (locator_cb), &info);
972
 
985
 
973
  /* run the handler */
986
  /* run the handler */
974
  gtk_main();
987
  gtk_main();
975
 
988
 
976
  *x = (double) info.x;
989
  *x = (double) info.x;
977
  *y = (double) info.y;
990
  *y = (double) info.y;
978
 
991
 
979
  /* clean up */
992
  /* clean up */
980
  gtk_signal_disconnect(GTK_OBJECT(gd->canvas), handler_id);
993
  gtk_signal_disconnect(GTK_OBJECT(gd->canvas), handler_id);
981
 
994
 
982
  if (info.button == 1)
995
  if (info.button == 1)
983
    {
996
    {
984
      gdk_beep();
997
      gdk_beep();
985
      return TRUE;
998
      return TRUE;
986
    }
999
    }
987
  else
1000
  else
988
    return FALSE;
1001
    return FALSE;
989
}
1002
}
990
 
1003
 
991
/* useless stuff */
1004
/* useless stuff */
992
 
1005
 
993
static void GNOME_Mode(gint mode, NewDevDesc *dd)
1006
static void GNOME_Mode(gint mode, NewDevDesc *dd)
994
{
1007
{
995
}
1008
}
996
 
1009
 
997
static void GNOME_Hold(NewDevDesc *dd)
1010
static void GNOME_Hold(NewDevDesc *dd)
998
{
1011
{
999
}
1012
}
1000
 
1013
 
1001
 
1014
 
1002
/* Device driver entry point */
1015
/* Device driver entry point */
1003
Rboolean GnomeDeviceDriver(DevDesc *odd, char *display, 
1016
Rboolean GnomeDeviceDriver(DevDesc *odd, char *display, 
1004
			   double width, double height, double pointsize)
1017
			   double width, double height, double pointsize)
1005
{
1018
{
1006
    int ps;
1019
    int ps;
1007
    gnomeDesc *gd;
1020
    gnomeDesc *gd;
1008
    NewDevDesc *dd;
1021
    NewDevDesc *dd;
1009
 
1022
 
1010
    if(!(gd = (gnomeDesc *) malloc(sizeof(gnomeDesc))))
1023
    if(!(gd = (gnomeDesc *) malloc(sizeof(gnomeDesc))))
1011
	return FALSE;
1024
	return FALSE;
1012
 
1025
 
1013
    dd = (NewDevDesc*) odd;  
1026
    dd = (NewDevDesc*) odd;  
1014
    dd->deviceSpecific = (void *) gd;
1027
    dd->deviceSpecific = (void *) gd;
1015
 
1028
 
1016
    /* FIXME: font loading */
1029
    /* FIXME: font loading */
1017
    ps = pointsize;
1030
    ps = pointsize;
1018
    if(ps < 6 || ps > 24) ps = 12;
1031
    if(ps < 6 || ps > 24) ps = 12;
1019
    ps = 2 * (ps / 2);
1032
    ps = 2 * (ps / 2);
1020
    gd->fontface = -1;
1033
    gd->fontface = -1;
1021
    gd->fontsize = -1;
1034
    gd->fontsize = -1;
1022
    
1035
    
1023
    dd->startfont = 1; 
1036
    dd->startfont = 1; 
1024
    dd->startps = ps;
1037
    dd->startps = ps;
1025
    dd->startcol = 0;
1038
    dd->startcol = 0;
1026
    dd->startfill = NA_INTEGER;
1039
    dd->startfill = NA_INTEGER;
1027
    dd->startlty = LTY_SOLID; 
1040
    dd->startlty = LTY_SOLID; 
1028
    dd->startgamma = 1;
1041
    dd->startgamma = 1;
1029
 
1042
 
1030
    /* device driver start */
1043
    /* device driver start */
1031
    if(!GNOME_Open(dd, gd, display, width, height)) {
1044
    if(!GNOME_Open(dd, gd, display, width, height)) {
1032
	free(gd);
1045
	free(gd);
1033
	return FALSE;
1046
	return FALSE;
1034
    }
1047
    }
1035
 
1048
 
1036
    dd->newDevStruct = 1;
1049
    dd->newDevStruct = 1;
1037
 
1050
 
1038
    /* setup data structure */
1051
    /* setup data structure */
1039
    dd->open = GNOME_Open;
1052
    dd->open = GNOME_Open;
1040
    dd->close = GNOME_Close;
1053
    dd->close = GNOME_Close;
1041
    dd->activate = GNOME_Activate;
1054
    dd->activate = GNOME_Activate;
1042
    dd->deactivate = GNOME_Deactivate;
1055
    dd->deactivate = GNOME_Deactivate;
1043
    dd->size = GNOME_Size;
1056
    dd->size = GNOME_Size;
1044
    dd->newPage = GNOME_NewPage;
1057
    dd->newPage = GNOME_NewPage;
1045
    dd->clip = GNOME_Clip;
1058
    dd->clip = GNOME_Clip;
1046
    dd->strWidth = GNOME_StrWidth;
1059
    dd->strWidth = GNOME_StrWidth;
1047
    dd->text = GNOME_Text;
1060
    dd->text = GNOME_Text;
1048
    dd->rect = GNOME_Rect;
1061
    dd->rect = GNOME_Rect;
1049
    dd->circle = GNOME_Circle;
1062
    dd->circle = GNOME_Circle;
1050
    dd->line = GNOME_Line;
1063
    dd->line = GNOME_Line;
1051
    dd->polyline = GNOME_Polyline;
1064
    dd->polyline = GNOME_Polyline;
1052
    dd->polygon = GNOME_Polygon;
1065
    dd->polygon = GNOME_Polygon;
1053
    dd->locator = GNOME_Locator;
1066
    dd->locator = GNOME_Locator;
1054
    dd->mode = GNOME_Mode;
1067
    dd->mode = GNOME_Mode;
1055
    dd->hold = GNOME_Hold;
1068
    dd->hold = GNOME_Hold;
1056
    dd->metricInfo = GNOME_MetricInfo;
1069
    dd->metricInfo = GNOME_MetricInfo;
1057
 
1070
 
1058
    dd->left = 0;
1071
    dd->left = 0;
1059
    dd->right = gd->windowWidth;
1072
    dd->right = gd->windowWidth;
1060
    dd->bottom = gd->windowHeight;
1073
    dd->bottom = gd->windowHeight;
1061
    dd->top = 0;
1074
    dd->top = 0;
1062
 
1075
 
1063
    /* FIXME: nominal character sizes */
1076
    /* FIXME: nominal character sizes */
1064
    dd->cra[0] = 10;
1077
    dd->cra[0] = 10;
1065
    dd->cra[1] = 10;
1078
    dd->cra[1] = 10;
1066
 
1079
 
1067
    /* FIXME: character addressing offsets */
1080
    /* FIXME: character addressing offsets */
1068
    dd->xCharOffset = 0.4900;
1081
    dd->xCharOffset = 0.4900;
1069
    dd->yCharOffset = 0.3333;
1082
    dd->yCharOffset = 0.3333;
1070
    dd->yLineBias = 0.1;
1083
    dd->yLineBias = 0.1;
1071
 
1084
 
1072
    /* inches per raster unit */
1085
    /* inches per raster unit */
1073
    dd->ipr[0] = pixelWidth();
1086
    dd->ipr[0] = pixelWidth();
1074
    dd->ipr[1] = pixelHeight();
1087
    dd->ipr[1] = pixelHeight();
1075
 
1088
 
1076
    /* device capabilities */
1089
    /* device capabilities */
1077
    dd->canResizePlot= TRUE;
1090
    dd->canResizePlot= TRUE;
1078
    dd->canChangeFont= FALSE; /* FIXME: surely this is possible */
1091
    dd->canChangeFont= FALSE; /* FIXME: surely this is possible */
1079
    dd->canRotateText= TRUE;
1092
    dd->canRotateText= TRUE;
1080
    dd->canResizeText= TRUE;
1093
    dd->canResizeText= TRUE;
1081
    dd->canClip = FALSE;/* FIXME: really? */
1094
    dd->canClip = FALSE;/* FIXME: really? */
1082
    dd->canHAdj = 0;/* not better? {0, 0.5, 1} */
1095
    dd->canHAdj = 0;/* not better? {0, 0.5, 1} */
1083
    dd->canChangeGamma = FALSE;
1096
    dd->canChangeGamma = FALSE;
1084
 
1097
 
1085
    /* x11 device description stuff */
1098
    /* x11 device description stuff */
1086
    gd->cex = 1.0;
1099
    gd->cex = 1.0;
1087
    gd->srt = 0.0;
1100
    gd->srt = 0.0;
1088
    gd->resize = FALSE;
1101
    gd->resize = FALSE;
1089
 
1102
 
1090
    dd->displayListOn = TRUE;
1103
    dd->displayListOn = TRUE;
1091
 
1104
 
1092
    /* finish */
1105
    /* finish */
1093
    return TRUE;
1106
    return TRUE;
1094
}
1107
}
1095
 
1108
 
1096
 
1109
 
1097
 
1110
 
1098
 
1111
 
1099
 
1112
 
1100
 
1113
 
1101
 
1114
 
1102
 
1115
 
1103
 
1116
 
1104
 
1117
 
1105
 
1118
 
1106
 
1119
 
1107
 
1120
 
1108
 
1121
 
1109
 
1122
 
1110
 
1123
 
1111
 
1124
 
1112
 
1125
 
1113
 
1126