The R Project SVN R

Rev

Rev 59261 | Rev 59267 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 59261 Rev 59266
Line 29... Line 29...
29
#include <Colors.h> /* for isNAcol */
29
#include <Colors.h> /* for isNAcol */
30
#include <Print.h>
30
#include <Print.h>
31
 
31
 
32
#define imax2(x, y) ((x < y) ? y : x)
32
#define imax2(x, y) ((x < y) ? y : x)
33
 
33
 
34
static R_INLINE double fmin2(double x, double y)
-
 
35
{
-
 
36
	if (ISNAN(x) || ISNAN(y))
-
 
37
		return x + y;
-
 
38
	return (x < y) ? x : y;
-
 
39
}
-
 
40
 
-
 
41
static R_INLINE double fmax2(double x, double y)
-
 
42
{
-
 
43
	if (ISNAN(x) || ISNAN(y))
-
 
44
		return x + y;
-
 
45
	return (x < y) ? y : x;
-
 
46
}
-
 
47
 
-
 
48
 
-
 
49
/*  P A R A M E T E R	 U T I L I T I E S  */
34
/*  P A R A M E T E R	 U T I L I T I E S  */
50
 
35
 
51
/*
-
 
52
 * Extract specified par from list of inline pars
-
 
53
 */
-
 
54
static SEXP getInlinePar(SEXP s, char *name)
-
 
55
{
-
 
56
    SEXP result = R_NilValue;
-
 
57
    int found = 0;
-
 
58
    if (isList(s) && !found) {
-
 
59
	while (s != R_NilValue) {
-
 
60
	    if (isList(CAR(s))) {
-
 
61
		result = getInlinePar(CAR(s), name);
-
 
62
		if (result)
-
 
63
		    found = 1;
-
 
64
	    } else
-
 
65
		if (TAG(s) != R_NilValue)
-
 
66
		    if (!strcmp(CHAR(PRINTNAME(TAG(s))), name)) {
-
 
67
			result = CAR(s);
-
 
68
			found = 1;
-
 
69
		    }
-
 
70
	    s = CDR(s);
-
 
71
	}
-
 
72
    }
-
 
73
    return result;
-
 
74
}
-
 
75
 
-
 
76
/* dflt used to be used for < 0 values in R < 2.7.0,
-
 
77
   now just used for NULL */
-
 
78
static SEXP FixupPch(SEXP pch, int dflt)
-
 
79
{
-
 
80
    int i, n;
-
 
81
    SEXP ans = R_NilValue;/* -Wall*/
-
 
82
 
-
 
83
    n = length(pch);
-
 
84
    if (n == 0) return ans = ScalarInteger(dflt);
-
 
85
 
-
 
86
    PROTECT(ans = allocVector(INTSXP, n));
-
 
87
    if (isList(pch)) {
-
 
88
	for (i = 0; pch != R_NilValue;	pch = CDR(pch))
-
 
89
	    INTEGER(ans)[i++] = asInteger(CAR(pch));
-
 
90
    }
-
 
91
    else if (isInteger(pch)) {
36
/* used on do_contour, graphics/src */
92
	for (i = 0; i < n; i++)
-
 
93
	    INTEGER(ans)[i] = INTEGER(pch)[i];
-
 
94
    }
-
 
95
    else if (isReal(pch)) {
-
 
96
	for (i = 0; i < n; i++)
-
 
97
	    INTEGER(ans)[i] = R_FINITE(REAL(pch)[i]) ?
-
 
98
		(int) REAL(pch)[i] : NA_INTEGER;
-
 
99
    }
-
 
100
    else if (isString(pch)) {
-
 
101
	for (i = 0; i < n; i++) {
-
 
102
	    /* New in 2.7.0: negative values indicate Unicode points. */
-
 
103
	    INTEGER(ans)[i] = GEstring_to_pch(STRING_ELT(pch, i));
-
 
104
	}
-
 
105
    }
-
 
106
    else if (isLogical(pch)) {/* NA, but not TRUE/FALSE */
-
 
107
	for (i = 0; i < n; i++)
-
 
108
	    if(LOGICAL(pch)[i] == NA_LOGICAL) INTEGER(ans)[i] = NA_INTEGER;
-
 
109
	    else error(_("only NA allowed in logical plotting symbol"));
-
 
110
    }
-
 
111
    else error(_("invalid plotting symbol"));
-
 
112
    UNPROTECT(1);
-
 
113
    return ans;
-
 
114
}
-
 
115
 
-
 
116
attribute_hidden
37
attribute_hidden
117
SEXP FixupLty(SEXP lty, int dflt)
38
SEXP FixupLty(SEXP lty, int dflt)
118
{
39
{
119
    int i, n;
40
    int i, n;
120
    SEXP ans;
41
    SEXP ans;
Line 153... Line 74...
153
	UNPROTECT(1);
74
	UNPROTECT(1);
154
    }
75
    }
155
    return ans;
76
    return ans;
156
}
77
}
157
 
78
 
158
static SEXP FixupFont(SEXP font, int dflt)
-
 
159
{
-
 
160
    int i, k, n;
-
 
161
    SEXP ans = R_NilValue;/* -Wall*/
-
 
162
    n = length(font);
-
 
163
    if (n == 0) {
-
 
164
	ans = ScalarInteger(dflt);
-
 
165
    }
-
 
166
    else if (isLogical(font)) {
-
 
167
	ans = allocVector(INTSXP, n);
-
 
168
	for (i = 0; i < n; i++) {
-
 
169
	    k = LOGICAL(font)[i];
-
 
170
#ifndef Win32
-
 
171
	    if (k < 1 || k > 5) k = NA_INTEGER;
-
 
172
#else
-
 
173
	    if (k < 1 || k > 32) k = NA_INTEGER;
-
 
174
#endif
-
 
175
	    INTEGER(ans)[i] = k;
-
 
176
	}
-
 
177
    }
-
 
178
    else if (isInteger(font)) {
-
 
179
	ans = allocVector(INTSXP, n);
-
 
180
	for (i = 0; i < n; i++) {
-
 
181
	    k = INTEGER(font)[i];
-
 
182
#ifndef Win32
-
 
183
	    if (k < 1 || k > 5) k = NA_INTEGER;
-
 
184
#else
-
 
185
	    if (k < 1 || k > 32) k = NA_INTEGER;
-
 
186
#endif
-
 
187
	    INTEGER(ans)[i] = k;
-
 
188
	}
-
 
189
    }
-
 
190
    else if (isReal(font)) {
-
 
191
	ans = allocVector(INTSXP, n);
-
 
192
	for (i = 0; i < n; i++) {
-
 
193
	    k = (int) REAL(font)[i];
-
 
194
#ifndef Win32
-
 
195
	    if (k < 1 || k > 5) k = NA_INTEGER;
-
 
196
#else
-
 
197
	    if (k < 1 || k > 32) k = NA_INTEGER;
-
 
198
#endif
-
 
199
	    INTEGER(ans)[i] = k;
-
 
200
	}
-
 
201
    }
-
 
202
    else error(_("invalid font specification"));
-
 
203
    return ans;
-
 
204
}
-
 
205
 
79
 
206
SEXP FixupCol(SEXP col, unsigned int dflt)
80
SEXP FixupCol(SEXP col, unsigned int dflt)
207
{
81
{
208
    int i, n;
82
    int i, n;
209
    SEXP ans;
83
    SEXP ans;
Line 225... Line 99...
225
    }
99
    }
226
    UNPROTECT(1);
100
    UNPROTECT(1);
227
    return ans;
101
    return ans;
228
}
102
}
229
 
103
 
230
static SEXP FixupCex(SEXP cex, double dflt)
-
 
231
{
-
 
232
    SEXP ans;
-
 
233
    int i, n;
-
 
234
    n = length(cex);
-
 
235
    if (n == 0) {
-
 
236
	ans = allocVector(REALSXP, 1);
-
 
237
	if (R_FINITE(dflt) && dflt > 0)
-
 
238
	    REAL(ans)[0] = dflt;
-
 
239
	else
-
 
240
	    REAL(ans)[0] = NA_REAL;
-
 
241
    }
-
 
242
    else {
-
 
243
	double c;
-
 
244
	ans = allocVector(REALSXP, n);
-
 
245
	if (isReal(cex))
-
 
246
	    for (i = 0; i < n; i++) {
-
 
247
		c = REAL(cex)[i];
-
 
248
		if (R_FINITE(c) && c > 0)
-
 
249
		    REAL(ans)[i] = c;
-
 
250
		else
-
 
251
		    REAL(ans)[i] = NA_REAL;
-
 
252
	    }
-
 
253
	else if (isInteger(cex) || isLogical(cex))
-
 
254
	    for (i = 0; i < n; i++) {
-
 
255
		c = INTEGER(cex)[i];
-
 
256
		if (c == NA_INTEGER || c <= 0)
-
 
257
		    c = NA_REAL;
-
 
258
		REAL(ans)[i] = c;
-
 
259
	    }
-
 
260
	else
-
 
261
	    error(_("invalid '%s' value"), "cex");
-
 
262
    }
-
 
263
    return ans;
-
 
264
}
-
 
265
 
104
 
266
attribute_hidden
105
attribute_hidden
267
SEXP FixupVFont(SEXP vfont) {
106
SEXP FixupVFont(SEXP vfont) {
268
    SEXP ans = R_NilValue;
107
    SEXP ans = R_NilValue;
269
    if (!isNull(vfont)) {
108
    if (!isNull(vfont)) {
Line 307... Line 146...
307
	UNPROTECT(1);
146
	UNPROTECT(1);
308
    }
147
    }
309
    return ans;
148
    return ans;
310
}
149
}
311
 
150
 
312
/* GetTextArg() : extract from call and possibly set text arguments
-
 
313
 *  ("label", col=, cex=, font=)
-
 
314
 *
-
 
315
 * Main purpose: Treat things like  title(main = list("This Title", font= 4))
-
 
316
 *
-
 
317
 * Called from	do_title()  [only, currently]
-
 
318
 */
-
 
319
static void
-
 
320
GetTextArg(SEXP call, SEXP spec, SEXP *ptxt,
-
 
321
	   rcolor *pcol, double *pcex, int *pfont)
-
 
322
{
-
 
323
    int i, n, font, colspecd;
-
 
324
    rcolor col;
-
 
325
    double cex;
-
 
326
    SEXP txt, nms;
-
 
327
    PROTECT_INDEX pi;
-
 
328
 
-
 
329
    txt	  = R_NilValue;
-
 
330
    cex	  = NA_REAL;
-
 
331
    col	  = R_TRANWHITE;
-
 
332
    colspecd = 0;
-
 
333
    font  = NA_INTEGER;
-
 
334
    /* It doesn't look as if this protection is needed */
-
 
335
    PROTECT_WITH_INDEX(txt, &pi);
-
 
336
 
-
 
337
    switch (TYPEOF(spec)) {
-
 
338
    case LANGSXP:
-
 
339
    case SYMSXP:
-
 
340
	REPROTECT(txt = coerceVector(spec, EXPRSXP), pi);
-
 
341
	break;
-
 
342
    case VECSXP:
-
 
343
	if (length(spec) == 0) {
-
 
344
	    *ptxt = R_NilValue;
-
 
345
	}
-
 
346
	else {
-
 
347
	    nms = getAttrib(spec, R_NamesSymbol);
-
 
348
	    if (nms == R_NilValue){ /* PR#1939 */
-
 
349
	       txt = VECTOR_ELT(spec, 0);
-
 
350
	       if (TYPEOF(txt) == LANGSXP || TYPEOF(txt) == SYMSXP )
-
 
351
		    REPROTECT(txt = coerceVector(txt, EXPRSXP), pi);
-
 
352
	       else if (!isExpression(txt))
-
 
353
		    REPROTECT(txt = coerceVector(txt, STRSXP), pi);
-
 
354
	    } else {
-
 
355
	       n = length(nms);
-
 
356
	       for (i = 0; i < n; i++) {
-
 
357
		if (!strcmp(CHAR(STRING_ELT(nms, i)), "cex")) {
-
 
358
		    cex = asReal(VECTOR_ELT(spec, i));
-
 
359
		}
-
 
360
		else if (!strcmp(CHAR(STRING_ELT(nms, i)), "col")) {
-
 
361
		    SEXP colsxp = VECTOR_ELT(spec, i);
-
 
362
		    if (!isNAcol(colsxp, 0, LENGTH(colsxp))) {
-
 
363
			col = asInteger(FixupCol(colsxp, R_TRANWHITE));
-
 
364
			colspecd = 1;
-
 
365
		    }
-
 
366
		}
-
 
367
		else if (!strcmp(CHAR(STRING_ELT(nms, i)), "font")) {
-
 
368
		    font = asInteger(FixupFont(VECTOR_ELT(spec, i), NA_INTEGER));
-
 
369
		}
-
 
370
		else if (!strcmp(CHAR(STRING_ELT(nms, i)), "")) {
-
 
371
		    txt = VECTOR_ELT(spec, i);
-
 
372
		    if (TYPEOF(txt) == LANGSXP || TYPEOF(txt) == SYMSXP)
-
 
373
			REPROTECT(txt = coerceVector(txt, EXPRSXP), pi);
-
 
374
		    else if (!isExpression(txt))
-
 
375
			REPROTECT(txt = coerceVector(txt, STRSXP), pi);
-
 
376
		}
-
 
377
		else error(_("invalid graphics parameter"));
-
 
378
	       }
-
 
379
	    }
-
 
380
	}
-
 
381
	break;
-
 
382
    case STRSXP:
-
 
383
    case EXPRSXP:
-
 
384
	txt = spec;
-
 
385
	break;
-
 
386
    default:
-
 
387
	REPROTECT(txt = coerceVector(spec, STRSXP), pi);
-
 
388
	break;
-
 
389
    }
-
 
390
    UNPROTECT(1);
-
 
391
    if (txt != R_NilValue) {
-
 
392
	*ptxt = txt;
-
 
393
	if (R_FINITE(cex))	 *pcex	 = cex;
-
 
394
	if (colspecd)	         *pcol	 = col;
-
 
395
	if (font != NA_INTEGER)	 *pfont	 = font;
-
 
396
    }
-
 
397
}/* GetTextArg */
-
 
398
 
-
 
399
 
-
 
400
    /* GRAPHICS FUNCTION ENTRY POINTS */
-
 
401
 
-
 
402
 
-
 
403
SEXP attribute_hidden do_plot_new(SEXP call, SEXP op, SEXP args, SEXP env)
-
 
404
{
-
 
405
    /* plot.new() - create a new plot "frame" */
-
 
406
 
-
 
407
    pGEDevDesc dd;
-
 
408
 
-
 
409
    checkArity(op, args);
-
 
410
 
-
 
411
    dd = GEcurrentDevice();
-
 
412
    /*
-
 
413
     * If user is prompted before new page, user has opportunity
-
 
414
     * to kill current device.  GNewPlot returns (potentially new)
-
 
415
     * current device.
-
 
416
     */
-
 
417
    dd = GNewPlot(GRecording(call, dd));
-
 
418
 
-
 
419
    dpptr(dd)->xlog = gpptr(dd)->xlog = FALSE;
-
 
420
    dpptr(dd)->ylog = gpptr(dd)->ylog = FALSE;
-
 
421
 
-
 
422
    GScale(0.0, 1.0, 1, dd);
-
 
423
    GScale(0.0, 1.0, 2, dd);
-
 
424
    GMapWin2Fig(dd);
-
 
425
    GSetState(1, dd);
-
 
426
 
-
 
427
    if (GRecording(call, dd))
-
 
428
	GErecordGraphicOperation(op, args, dd);
-
 
429
    return R_NilValue;
-
 
430
}
-
 
431
 
-
 
432
 
-
 
433
/*
-
 
434
 *  SYNOPSIS
-
 
435
 *
-
 
436
 *	plot.window(xlim, ylim, log="", asp=NA)
-
 
437
 *
-
 
438
 *  DESCRIPTION
-
 
439
 *
-
 
440
 *	This function sets up the world coordinates for a graphics
-
 
441
 *	window.	 Note that if asp is a finite positive value then
-
 
442
 *	the window is set up so that one data unit in the y direction
-
 
443
 *	is equal in length to one data unit in the x direction divided
-
 
444
 *	by asp.
-
 
445
 *
-
 
446
 *	The special case asp == 1 produces plots where distances
-
 
447
 *	between points are represented accurately on screen.
-
 
448
 *
-
 
449
 *  NOTE
-
 
450
 *
-
 
451
 *	The use of asp can have weird effects when axis is an
-
 
452
 *	interpreted function.  It has to be internal so that the
-
 
453
 *	full computation is captured in the display list.
-
 
454
 */
-
 
455
 
-
 
456
SEXP attribute_hidden do_plot_window(SEXP call, SEXP op, SEXP args, SEXP env)
-
 
457
{
-
 
458
    SEXP xlim, ylim, logarg;
-
 
459
    double asp, xmin, xmax, ymin, ymax;
-
 
460
    Rboolean logscale;
-
 
461
    const char *p;
-
 
462
    SEXP originalArgs = args;
-
 
463
    pGEDevDesc dd = GEcurrentDevice();
-
 
464
 
-
 
465
    if (length(args) < 3)
-
 
466
	error(_("at least 3 arguments required"));
-
 
467
 
-
 
468
    xlim = CAR(args);
-
 
469
    if (!isNumeric(xlim) || LENGTH(xlim) != 2)
-
 
470
	error(_("invalid '%s' value"), "xlim");
-
 
471
    args = CDR(args);
-
 
472
 
-
 
473
    ylim = CAR(args);
-
 
474
    if (!isNumeric(ylim) || LENGTH(ylim) != 2)
-
 
475
	error(_("invalid '%s' value"), "ylim");
-
 
476
    args = CDR(args);
-
 
477
 
-
 
478
    logscale = FALSE;
-
 
479
    logarg = CAR(args);
-
 
480
    if (!isString(logarg))
-
 
481
	error(_("\"log=\" specification must be character"));
-
 
482
    p = CHAR(STRING_ELT(logarg, 0));
-
 
483
    while (*p) {
-
 
484
	switch (*p) {
-
 
485
	case 'x':
-
 
486
	    dpptr(dd)->xlog = gpptr(dd)->xlog = logscale = TRUE;
-
 
487
	    break;
-
 
488
	case 'y':
-
 
489
	    dpptr(dd)->ylog = gpptr(dd)->ylog = logscale = TRUE;
-
 
490
	    break;
-
 
491
	default:
-
 
492
	    error(_("invalid \"log=%s\" specification"), p);
-
 
493
	}
-
 
494
	p++;
-
 
495
    }
-
 
496
    args = CDR(args);
-
 
497
 
-
 
498
    asp = (logscale) ? NA_REAL : asReal(CAR(args));;
-
 
499
    args = CDR(args);
-
 
500
 
-
 
501
    /* This reads [xy]axs and lab, used in GScale */
-
 
502
    GSavePars(dd);
-
 
503
    ProcessInlinePars(args, dd);
-
 
504
 
-
 
505
    if (isInteger(xlim)) {
-
 
506
	if (INTEGER(xlim)[0] == NA_INTEGER || INTEGER(xlim)[1] == NA_INTEGER)
-
 
507
	    error(_("NAs not allowed in 'xlim'"));
-
 
508
	xmin = INTEGER(xlim)[0];
-
 
509
	xmax = INTEGER(xlim)[1];
-
 
510
    }
-
 
511
    else {
-
 
512
	if (!R_FINITE(REAL(xlim)[0]) || !R_FINITE(REAL(xlim)[1]))
-
 
513
	    error(_("need finite 'xlim' values"));
-
 
514
	xmin = REAL(xlim)[0];
-
 
515
	xmax = REAL(xlim)[1];
-
 
516
    }
-
 
517
    if (isInteger(ylim)) {
-
 
518
	if (INTEGER(ylim)[0] == NA_INTEGER || INTEGER(ylim)[1] == NA_INTEGER)
-
 
519
	    error(_("NAs not allowed in 'ylim'"));
-
 
520
	ymin = INTEGER(ylim)[0];
-
 
521
	ymax = INTEGER(ylim)[1];
-
 
522
    }
-
 
523
    else {
-
 
524
	if (!R_FINITE(REAL(ylim)[0]) || !R_FINITE(REAL(ylim)[1]))
-
 
525
	    error(_("need finite 'ylim' values"));
-
 
526
	ymin = REAL(ylim)[0];
-
 
527
	ymax = REAL(ylim)[1];
-
 
528
    }
-
 
529
    if ((dpptr(dd)->xlog && (xmin < 0 || xmax < 0)) ||
-
 
530
       (dpptr(dd)->ylog && (ymin < 0 || ymax < 0)))
-
 
531
	    error(_("Logarithmic axis must have positive limits"));
-
 
532
 
-
 
533
    if (R_FINITE(asp) && asp > 0) {
-
 
534
	double pin1, pin2, scale, xdelta, ydelta, xscale, yscale, xadd, yadd;
-
 
535
	pin1 = GConvertXUnits(1.0, NPC, INCHES, dd);
-
 
536
	pin2 = GConvertYUnits(1.0, NPC, INCHES, dd);
-
 
537
	xdelta = fabs(xmax - xmin) / asp;
-
 
538
	ydelta = fabs(ymax - ymin);
-
 
539
	if(xdelta == 0.0 && ydelta == 0.0) {
-
 
540
	    /* We really do mean zero: small non-zero values work.
-
 
541
	       Mimic the behaviour of GScale for the x axis. */
-
 
542
	    xadd = yadd = ((xmin == 0.0) ? 1 : 0.4) * asp;
-
 
543
	    xadd *= asp;
-
 
544
	} else {
-
 
545
	    xscale = pin1 / xdelta;
-
 
546
	    yscale = pin2 / ydelta;
-
 
547
	    scale = (xscale < yscale) ? xscale : yscale;
-
 
548
	    xadd = .5 * (pin1 / scale - xdelta) * asp;
-
 
549
	    yadd = .5 * (pin2 / scale - ydelta);
-
 
550
	}
-
 
551
	if(xmax < xmin) xadd *= -1;
-
 
552
	if(ymax < ymin) yadd *= -1;
-
 
553
	GScale(xmin - xadd, xmax + xadd, 1, dd);
-
 
554
	GScale(ymin - yadd, ymax + yadd, 2, dd);
-
 
555
    }
-
 
556
    else { /* asp <= 0 or not finite -- includes logscale ! */
-
 
557
	GScale(xmin, xmax, 1, dd);
-
 
558
	GScale(ymin, ymax, 2, dd);
-
 
559
    }
-
 
560
    /* GScale set the [xy]axp parameters */
-
 
561
    GMapWin2Fig(dd);
-
 
562
    GRestorePars(dd);
-
 
563
    /* This has now clobbered the Rf_ggptr settings for coord system */
-
 
564
 
-
 
565
    /* NOTE: the operation is only recorded if there was no "error" */
-
 
566
    if (GRecording(call, dd))
-
 
567
	GErecordGraphicOperation(op, originalArgs, dd);
-
 
568
    return R_NilValue;
-
 
569
}
-
 
570
 
-
 
571
static void GetAxisLimits(double left, double right, Rboolean logflag, double *low, double *high)
-
 
572
{
-
 
573
/*	Called from do_axis()	such as
-
 
574
 *	GetAxisLimits(gpptr(dd)->usr[0], gpptr(dd)->usr[1], &low, &high)
-
 
575
 *
-
 
576
 *	Computes  *low < left, right < *high  (even if left=right)
-
 
577
 */
-
 
578
    double eps;
-
 
579
    if (logflag) {
-
 
580
	left = log(left);
-
 
581
	right = log(right);
-
 
582
    }
-
 
583
    if (left > right) {/* swap */
-
 
584
	eps = left; left = right; right = eps;
-
 
585
    }
-
 
586
    eps = right - left;
-
 
587
    if (eps == 0.)
-
 
588
	eps = 0.5 * FLT_EPSILON;
-
 
589
    else
-
 
590
	eps *= FLT_EPSILON;
-
 
591
    *low = left - eps;
-
 
592
    *high = right + eps;
-
 
593
    
-
 
594
    if (logflag) {
-
 
595
	*low = exp(*low);
-
 
596
	*high = exp(*high);
-
 
597
    }
-
 
598
}
-
 
599
 
-
 
600
 
-
 
601
/* axis(side, at, labels, ...) */
151
/* used in graphics and grid */
602
 
-
 
603
SEXP labelformat(SEXP labels)
-
 
604
{
-
 
605
    /* format(labels): i.e. from numbers to strings */
-
 
606
    SEXP ans = R_NilValue;/* -Wall*/
-
 
607
    int i, n, w, d, e, wi, di, ei;
-
 
608
    const char *strp;
-
 
609
    n = length(labels);
-
 
610
    R_print.digits = 7;/* maximally 7 digits -- ``burnt in'';
-
 
611
			  S-PLUS <= 5.x has about 6
-
 
612
			  (but really uses single precision..) */
-
 
613
    switch(TYPEOF(labels)) {
-
 
614
    case LGLSXP:
-
 
615
	PROTECT(ans = allocVector(STRSXP, n));
-
 
616
	for (i = 0; i < n; i++) {
-
 
617
	    strp = EncodeLogical(LOGICAL(labels)[i], 0);
-
 
618
	    SET_STRING_ELT(ans, i, mkChar(strp));
-
 
619
	}
-
 
620
	UNPROTECT(1);
-
 
621
	break;
-
 
622
    case INTSXP:
-
 
623
	PROTECT(ans = allocVector(STRSXP, n));
-
 
624
	for (i = 0; i < n; i++) {
-
 
625
	    strp = EncodeInteger(INTEGER(labels)[i], 0);
-
 
626
	    SET_STRING_ELT(ans, i, mkChar(strp));
-
 
627
	}
-
 
628
	UNPROTECT(1);
-
 
629
	break;
-
 
630
    case REALSXP:
-
 
631
	formatReal(REAL(labels), n, &w, &d, &e, 0);
-
 
632
	PROTECT(ans = allocVector(STRSXP, n));
-
 
633
	for (i = 0; i < n; i++) {
-
 
634
	    strp = EncodeReal(REAL(labels)[i], 0, d, e, OutDec);
-
 
635
	    SET_STRING_ELT(ans, i, mkChar(strp));
-
 
636
	}
-
 
637
	UNPROTECT(1);
-
 
638
	break;
-
 
639
    case CPLXSXP:
-
 
640
	formatComplex(COMPLEX(labels), n, &w, &d, &e, &wi, &di, &ei, 0);
-
 
641
	PROTECT(ans = allocVector(STRSXP, n));
-
 
642
	for (i = 0; i < n; i++) {
-
 
643
	    strp = EncodeComplex(COMPLEX(labels)[i], 0, d, e, 0, di, ei,
-
 
644
				 OutDec);
-
 
645
	    SET_STRING_ELT(ans, i, mkChar(strp));
-
 
646
	}
-
 
647
	UNPROTECT(1);
-
 
648
	break;
-
 
649
    case STRSXP:
-
 
650
	PROTECT(ans = allocVector(STRSXP, n));
-
 
651
	for (i = 0; i < n; i++) {
-
 
652
	    SET_STRING_ELT(ans, i, STRING_ELT(labels, i));
-
 
653
	}
-
 
654
	UNPROTECT(1);
-
 
655
	break;
-
 
656
    default:
-
 
657
	error(_("invalid type for axis labels"));
-
 
658
    }
-
 
659
    return ans;
-
 
660
}
-
 
661
 
-
 
662
SEXP CreateAtVector(double *axp, double *usr, int nint, Rboolean logflag)
152
SEXP CreateAtVector(double *axp, double *usr, int nint, Rboolean logflag)
663
{
153
{
664
/*	Create an  'at = ...' vector for  axis(.) / do_axis,
154
/*	Create an  'at = ...' vector for  axis(.)
665
 *	i.e., the vector of tick mark locations,
155
 *	i.e., the vector of tick mark locations,
666
 *	when none has been specified (= default).
156
 *	when none has been specified (= default).
667
 *
157
 *
668
 *	axp[0:2] = (x1, x2, nInt), where x1..x2 are the extreme tick marks
158
 *	axp[0:2] = (x1, x2, nInt), where x1..x2 are the extreme tick marks
669
 *		   {unless in log case, where nInt \in {1,2,3 ; -1,-2,....}
159
 *		   {unless in log case, where nInt \in {1,2,3 ; -1,-2,....}
Line 824... Line 314...
824
	}
314
	}
825
    } /* linear / log */
315
    } /* linear / log */
826
    return at;
316
    return at;
827
}
317
}
828
 
318
 
829
static double ComputePAdjValue(double padj, int side, int las)
-
 
830
{
-
 
831
    if (!R_FINITE(padj)) {
-
 
832
    switch(las) {
-
 
833
    case 0:/* parallel to axis */
-
 
834
	padj = 0.0; break;
-
 
835
    case 1:/* horizontal */
-
 
836
	switch(side) {
-
 
837
	case 1:
-
 
838
	case 3: padj = 0.0; break;
-
 
839
	case 2:
-
 
840
	case 4: padj = 0.5; break;
-
 
841
	}
-
 
842
	break;
-
 
843
    case 2:/* perpendicular to axis */
-
 
844
	padj = 0.5; break;
-
 
845
    case 3:/* vertical */
-
 
846
	switch(side) {
-
 
847
	case 1:
-
 
848
	case 3: padj = 0.5; break;
-
 
849
	case 2:
-
 
850
	case 4: padj = 0.0; break;
-
 
851
	}
-
 
852
	break;
-
 
853
    }
-
 
854
    }
-
 
855
    return padj;
-
 
856
}
-
 
857
 
-
 
858
static void getxlimits(double *x, pGEDevDesc dd) {
-
 
859
    /*
-
 
860
     * xpd = 0 means clip to current plot region
-
 
861
     * xpd = 1 means clip to current figure region
-
 
862
     * xpd = 2 means clip to device region
-
 
863
     */
-
 
864
    switch (gpptr(dd)->xpd) {
-
 
865
    case 0:
-
 
866
	x[0] = gpptr(dd)->usr[0];
-
 
867
	x[1] = gpptr(dd)->usr[1];
-
 
868
	break;
-
 
869
    case 1:
-
 
870
	x[0] = GConvertX(0, NFC, USER, dd);
-
 
871
	x[1] = GConvertX(1, NFC, USER, dd);
-
 
872
	break;
-
 
873
    case 2:
-
 
874
	x[0] = GConvertX(0, NDC, USER, dd);
-
 
875
	x[1] = GConvertX(1, NDC, USER, dd);
-
 
876
	break;
-
 
877
    }
-
 
878
}
-
 
879
 
-
 
880
static void getylimits(double *y, pGEDevDesc dd) {
-
 
881
    switch (gpptr(dd)->xpd) {
-
 
882
    case 0:
-
 
883
	y[0] = gpptr(dd)->usr[2];
-
 
884
	y[1] = gpptr(dd)->usr[3];
-
 
885
	break;
-
 
886
    case 1:
-
 
887
	y[0] = GConvertY(0, NFC, USER, dd);
-
 
888
	y[1] = GConvertY(1, NFC, USER, dd);
-
 
889
	break;
-
 
890
    case 2:
-
 
891
	y[0] = GConvertY(0, NDC, USER, dd);
-
 
892
	y[1] = GConvertY(1, NDC, USER, dd);
-
 
893
	break;
-
 
894
    }
-
 
895
}
-
 
896
 
-
 
897
SEXP attribute_hidden do_axis(SEXP call, SEXP op, SEXP args, SEXP env)
-
 
898
{
-
 
899
    /* axis(side, at, labels, tick, line, pos,
-
 
900
     	    outer, font, lty, lwd, lwd.ticks, col, col.ticks,
-
 
901
	    hadj, padj, ...)
-
 
902
    */
-
 
903
 
-
 
904
    SEXP at, lab, padj;
-
 
905
    int font, lty, npadj;
-
 
906
    rcolor col, colticks;
-
 
907
    int i, n, nint = 0, ntmp, side, *ind, outer, lineoff = 0;
-
 
908
    int istart, iend, incr;
-
 
909
    Rboolean dolabels, doticks, logflag = FALSE;
-
 
910
    Rboolean create_at;
-
 
911
    double x, y, temp, tnew, tlast;
-
 
912
    double axp[3], usr[2], limits[2];
-
 
913
    double gap, labw, low, high, line, pos, lwd, lwdticks, hadj;
-
 
914
    double axis_base, axis_tick, axis_lab, axis_low, axis_high;
-
 
915
 
-
 
916
    SEXP originalArgs = args, label;
-
 
917
    pGEDevDesc dd = GEcurrentDevice();
-
 
918
 
-
 
919
    /* Arity Check */
-
 
920
    /* This is a builtin function, so it should always have */
-
 
921
    /* the correct arity, but it doesn't hurt to be defensive. */
-
 
922
 
-
 
923
    if (length(args) < 15)
-
 
924
	error(_("too few arguments"));
-
 
925
    GCheckState(dd);
-
 
926
 
-
 
927
    PrintDefaults(); /* prepare for labelformat */
-
 
928
 
-
 
929
    /* Required argument: "side" */
-
 
930
    /* Which side of the plot the axis is to appear on. */
319
/* in Graphics.h, used in contour and in graphics/src */
931
    /* side = 1 | 2 | 3 | 4. */
-
 
932
 
-
 
933
    side = asInteger(CAR(args));
-
 
934
    if (side < 1 || side > 4)
-
 
935
	error(_("invalid axis number %d"), side);
-
 
936
    args = CDR(args);
-
 
937
 
-
 
938
    /* Required argument: "at" */
-
 
939
    /* This gives the tick-label locations. */
-
 
940
    /* Note that these are coerced to the correct type below. */
-
 
941
 
-
 
942
    at = CAR(args); args = CDR(args);
-
 
943
 
-
 
944
    /* Required argument: "labels" */
-
 
945
    /* Labels can be a logical, indicating whether or not */
-
 
946
    /* to label the axis; or it can be a vector of character */
-
 
947
    /* strings or expressions which give the labels explicitly. */
-
 
948
    /* The expressions are used to set mathematical labelling. */
-
 
949
 
-
 
950
    dolabels = TRUE;
-
 
951
    lab = CAR(args);
-
 
952
    if (isLogical(lab) && length(lab) > 0) {
-
 
953
	i = asLogical(lab);
-
 
954
	if (i == 0 || i == NA_LOGICAL)
-
 
955
	    dolabels = FALSE;
-
 
956
	PROTECT(lab = R_NilValue);
-
 
957
    } else if (TYPEOF(lab) == LANGSXP || TYPEOF(lab) == SYMSXP) {
-
 
958
	PROTECT(lab = coerceVector(lab, EXPRSXP));
-
 
959
    } else if (isExpression(lab)) {
-
 
960
	PROTECT(lab);
-
 
961
    } else {
-
 
962
	PROTECT(lab = coerceVector(lab, STRSXP));
-
 
963
    }
-
 
964
    args = CDR(args);
-
 
965
 
-
 
966
    /* Required argument: "tick" */
-
 
967
    /* This indicates whether or not ticks and the axis line */
-
 
968
    /* should be plotted: TRUE => show, FALSE => don't show. */
-
 
969
 
-
 
970
    doticks = asLogical(CAR(args));
-
 
971
    doticks = (doticks == NA_LOGICAL) ? TRUE : (Rboolean) doticks;
-
 
972
    args = CDR(args);
-
 
973
 
-
 
974
    /* Optional argument: "line" */
-
 
975
 
-
 
976
    /* Specifies an offset outward from the plot for the axis.
-
 
977
     * The values in the par value "mgp" are interpreted
-
 
978
     * relative to this value. */
-
 
979
    line = asReal(CAR(args));
-
 
980
    /* defer processing until after in-line pars */
-
 
981
    args = CDR(args);
-
 
982
 
-
 
983
    /* Optional argument: "pos" */
-
 
984
    /* Specifies a user coordinate at which the axis should be drawn. */
-
 
985
    /* This overrides the value of "line".  Again the "mgp" par values */
-
 
986
    /* are interpreted relative to this value. */
-
 
987
 
-
 
988
    pos = asReal(CAR(args));
-
 
989
    /* defer processing until after in-line pars */
-
 
990
    args = CDR(args);
-
 
991
 
-
 
992
    /* Optional argument: "outer" */
-
 
993
    /* Should the axis be drawn in the outer margin. */
-
 
994
    /* This only affects the computation of axis_base. */
-
 
995
 
-
 
996
    outer = asLogical(CAR(args));
-
 
997
    if (outer == NA_LOGICAL || outer == 0)
-
 
998
	outer = NPC;
-
 
999
    else
-
 
1000
	outer = NIC;
-
 
1001
    args = CDR(args);
-
 
1002
 
-
 
1003
    /* Optional argument: "font" */
-
 
1004
    font = asInteger(FixupFont(CAR(args), NA_INTEGER));
-
 
1005
    args = CDR(args);
-
 
1006
 
-
 
1007
    /* Optional argument: "lty" */
-
 
1008
    lty = asInteger(FixupLty(CAR(args), 0));
-
 
1009
    args = CDR(args);
-
 
1010
 
-
 
1011
    /* Optional argument: "lwd" */
-
 
1012
    lwd = asReal(FixupLwd(CAR(args), 1));
-
 
1013
    args = CDR(args);
-
 
1014
    lwdticks = asReal(FixupLwd(CAR(args), 1));
-
 
1015
    args = CDR(args);
-
 
1016
 
-
 
1017
    /* Optional argument: "col" */
-
 
1018
    col = asInteger(FixupCol(CAR(args), gpptr(dd)->fg));
-
 
1019
    args = CDR(args);
-
 
1020
    colticks = asInteger(FixupCol(CAR(args), col));
-
 
1021
    args = CDR(args);
-
 
1022
 
-
 
1023
    /* Optional argument: "hadj" */
-
 
1024
    if (length(CAR(args)) != 1)
-
 
1025
	error(_("'hadj' must be of length one"));
-
 
1026
    hadj = asReal(CAR(args));
-
 
1027
    args = CDR(args);
-
 
1028
 
-
 
1029
    /* Optional argument: "padj" */
-
 
1030
    PROTECT(padj = coerceVector(CAR(args), REALSXP));
-
 
1031
    npadj = length(padj);
-
 
1032
    if (npadj <= 0) error(_("zero length 'padj' specified"));
-
 
1033
 
-
 
1034
    /* Now we process all the remaining inline par values:
-
 
1035
       we need to do it now as x/yaxp are retrieved next.
-
 
1036
       That will set gpptr, so we update that first - do_plotwindow
-
 
1037
       clobbered the gpptr settings. */
-
 
1038
    GSavePars(dd);
-
 
1039
    gpptr(dd)->xaxp[0] = dpptr(dd)->xaxp[0];
-
 
1040
    gpptr(dd)->xaxp[1] = dpptr(dd)->xaxp[1];
-
 
1041
    gpptr(dd)->xaxp[2] = dpptr(dd)->xaxp[2];
-
 
1042
    gpptr(dd)->yaxp[0] = dpptr(dd)->yaxp[0];
-
 
1043
    gpptr(dd)->yaxp[1] = dpptr(dd)->yaxp[1];
-
 
1044
    gpptr(dd)->yaxp[2] = dpptr(dd)->yaxp[2];
-
 
1045
    ProcessInlinePars(args, dd);
-
 
1046
 
-
 
1047
    /* Retrieve relevant "par" values. */
-
 
1048
 
-
 
1049
    switch(side) {
-
 
1050
    case 1:
-
 
1051
    case 3:
-
 
1052
	axp[0] = gpptr(dd)->xaxp[0];
-
 
1053
	axp[1] = gpptr(dd)->xaxp[1];
-
 
1054
	axp[2] = gpptr(dd)->xaxp[2];
-
 
1055
	usr[0] = dpptr(dd)->usr[0];
-
 
1056
	usr[1] = dpptr(dd)->usr[1];
-
 
1057
	logflag = dpptr(dd)->xlog;
-
 
1058
	nint = dpptr(dd)->lab[0];
-
 
1059
	break;
-
 
1060
    case 2:
-
 
1061
    case 4:
-
 
1062
	axp[0] = gpptr(dd)->yaxp[0];
-
 
1063
	axp[1] = gpptr(dd)->yaxp[1];
-
 
1064
	axp[2] = gpptr(dd)->yaxp[2];
-
 
1065
	usr[0] = dpptr(dd)->usr[2];
-
 
1066
	usr[1] = dpptr(dd)->usr[3];
-
 
1067
	logflag = dpptr(dd)->ylog;
-
 
1068
	nint = dpptr(dd)->lab[1];
-
 
1069
	break;
-
 
1070
    }
-
 
1071
 
-
 
1072
    /* Deferred processing */
-
 
1073
    if (!R_FINITE(line)) {
-
 
1074
	/* Except that here mgp values are not relative to themselves */
-
 
1075
	line = gpptr(dd)->mgp[2];
-
 
1076
	lineoff = (int) line;
-
 
1077
    }
-
 
1078
    if (!R_FINITE(pos)) pos = NA_REAL; else lineoff = 0;
-
 
1079
 
-
 
1080
    /* Determine the tickmark positions.  Note that these may fall */
-
 
1081
    /* outside the plot window. We will clip them in the code below. */
-
 
1082
 
-
 
1083
    create_at = isNull(at);
-
 
1084
    if (create_at) {
-
 
1085
	PROTECT(at = CreateAtVector(axp, usr, nint, logflag));
-
 
1086
    }
-
 
1087
    else {
-
 
1088
	if (isReal(at)) PROTECT(at = duplicate(at));
-
 
1089
	else PROTECT(at = coerceVector(at, REALSXP));
-
 
1090
    }
-
 
1091
    n = length(at);
-
 
1092
 
-
 
1093
    /* Check/setup the tick labels.  This can mean using user-specified */
-
 
1094
    /* labels, or encoding the "at" positions as strings. */
-
 
1095
 
-
 
1096
    if (dolabels) {
-
 
1097
	if (length(lab) == 0)
-
 
1098
	    lab = labelformat(at);
320
SEXP labelformat(SEXP labels)
1099
	else {
-
 
1100
	    if (create_at)
-
 
1101
		error(_("'labels' is supplied and not 'at'"));
-
 
1102
	    if (!isExpression(lab)) lab = labelformat(lab);
-
 
1103
	}
-
 
1104
	if (length(at) != length(lab))
-
 
1105
	    error(_("'at' and 'labels' lengths differ, %d != %d"),
-
 
1106
		      length(at), length(lab));
-
 
1107
    }
-
 
1108
    PROTECT(lab);
-
 
1109
 
-
 
1110
    /* Check there are no NA, Inf or -Inf values for tick positions. */
-
 
1111
    /* The code here is long-winded.  Couldn't we just inline things */
-
 
1112
    /* below.  Hmmm - we need the min and max of the finite values ... */
-
 
1113
 
-
 
1114
    ind = (int *) R_alloc(n, sizeof(int));
-
 
1115
    for(i = 0; i < n; i++) ind[i] = i;
-
 
1116
    rsort_with_index(REAL(at), ind, n);
-
 
1117
    ntmp = 0;
-
 
1118
    for(i = 0; i < n; i++) {
-
 
1119
	if(R_FINITE(REAL(at)[i])) ntmp = i+1;
-
 
1120
    }
-
 
1121
    if (n > 0 && ntmp == 0)
-
 
1122
	error(_("no locations are finite"));
-
 
1123
    n = ntmp;
-
 
1124
 
-
 
1125
    /* Ok, all systems are "GO".  Let's get to it. */
-
 
1126
 
-
 
1127
    /* At this point we know the value of "xaxt" and "yaxt",
-
 
1128
     * so we test to see whether the relevant one is "n".
-
 
1129
     * If it is, we just bail out at this point. */
-
 
1130
 
-
 
1131
    if ((n == 0) ||
-
 
1132
        ((side == 1 || side == 3) && gpptr(dd)->xaxt == 'n') ||
-
 
1133
	((side == 2 || side == 4) && gpptr(dd)->yaxt == 'n')) {
-
 
1134
	GRestorePars(dd);
-
 
1135
	UNPROTECT(4);
-
 
1136
	return R_NilValue;
-
 
1137
    }
-
 
1138
 
-
 
1139
 
-
 
1140
    gpptr(dd)->lty = lty;
-
 
1141
    gpptr(dd)->lwd = lwd;
-
 
1142
    gpptr(dd)->adj = R_FINITE(hadj) ? hadj : 0.5;
-
 
1143
    gpptr(dd)->font = (font == NA_INTEGER)? gpptr(dd)->fontaxis : font;
-
 
1144
    gpptr(dd)->cex = gpptr(dd)->cexbase * gpptr(dd)->cexaxis;
-
 
1145
 
-
 
1146
    /* Draw the axis */
-
 
1147
    GMode(1, dd);
-
 
1148
    switch (side) {
-
 
1149
    case 1: /*--- x-axis -- horizontal --- */
-
 
1150
    case 3:
-
 
1151
        /* First set the clipping limits */
-
 
1152
        getxlimits(limits, dd);
-
 
1153
        /* Now override par("xpd") and force clipping to device region. */
-
 
1154
        gpptr(dd)->xpd = 2;
-
 
1155
	GetAxisLimits(limits[0], limits[1], logflag, &low, &high);
-
 
1156
	axis_low  = GConvertX(fmin2(high, fmax2(low, REAL(at)[0])), USER, NFC, dd);
-
 
1157
	axis_high = GConvertX(fmin2(high, fmax2(low, REAL(at)[n-1])), USER, NFC, dd);
-
 
1158
	if (side == 1) {
-
 
1159
	    if (R_FINITE(pos))
-
 
1160
		axis_base = GConvertY(pos, USER, NFC, dd);
-
 
1161
	    else
-
 
1162
		axis_base = GConvertY(0.0, outer, NFC, dd)
-
 
1163
		    - GConvertYUnits(line, LINES, NFC, dd);
-
 
1164
	    if (R_FINITE(gpptr(dd)->tck)) {
-
 
1165
		double len, xu, yu;
-
 
1166
		if(gpptr(dd)->tck > 0.5)
-
 
1167
		    len = GConvertYUnits(gpptr(dd)->tck, NPC, NFC, dd);
-
 
1168
		else {
-
 
1169
		    xu = GConvertXUnits(gpptr(dd)->tck, NPC, INCHES, dd);
-
 
1170
		    yu = GConvertYUnits(gpptr(dd)->tck, NPC, INCHES, dd);
-
 
1171
		    xu = (fabs(xu) < fabs(yu)) ? xu : yu;
-
 
1172
		    len = GConvertYUnits(xu, INCHES, NFC, dd);
-
 
1173
		}
-
 
1174
		axis_tick = axis_base + len;
-
 
1175
 
-
 
1176
	    } else
-
 
1177
		axis_tick = axis_base +
-
 
1178
			GConvertYUnits(gpptr(dd)->tcl, LINES, NFC, dd);
-
 
1179
	}
-
 
1180
	else {
-
 
1181
	    if (R_FINITE(pos))
-
 
1182
		axis_base = GConvertY(pos, USER, NFC, dd);
-
 
1183
	    else
-
 
1184
		axis_base =  GConvertY(1.0, outer, NFC, dd)
-
 
1185
		    + GConvertYUnits(line, LINES, NFC, dd);
-
 
1186
	    if (R_FINITE(gpptr(dd)->tck)) {
-
 
1187
		double len, xu, yu;
-
 
1188
		if(gpptr(dd)->tck > 0.5)
-
 
1189
		    len = GConvertYUnits(gpptr(dd)->tck, NPC, NFC, dd);
-
 
1190
		else {
-
 
1191
		    xu = GConvertXUnits(gpptr(dd)->tck, NPC, INCHES, dd);
-
 
1192
		    yu = GConvertYUnits(gpptr(dd)->tck, NPC, INCHES, dd);
-
 
1193
		    xu = (fabs(xu) < fabs(yu)) ? xu : yu;
-
 
1194
		    len = GConvertYUnits(xu, INCHES, NFC, dd);
-
 
1195
		}
-
 
1196
		axis_tick = axis_base - len;
-
 
1197
	    } else
-
 
1198
		axis_tick = axis_base -
-
 
1199
		    GConvertYUnits(gpptr(dd)->tcl, LINES, NFC, dd);
-
 
1200
	}
-
 
1201
	if (doticks) {
-
 
1202
	    gpptr(dd)->col = col;
-
 
1203
	    if (lwd > 0.0)
-
 
1204
		GLine(axis_low, axis_base, axis_high, axis_base, NFC, dd);
-
 
1205
	    gpptr(dd)->col = colticks;
-
 
1206
	    gpptr(dd)->lwd = lwdticks;
-
 
1207
	    if (lwdticks > 0) {
-
 
1208
		for (i = 0; i < n; i++) {
-
 
1209
		    x = REAL(at)[i];
-
 
1210
		    if (low <= x && x <= high) {
-
 
1211
			x = GConvertX(x, USER, NFC, dd);
-
 
1212
			GLine(x, axis_base, x, axis_tick, NFC, dd);
-
 
1213
		    }
-
 
1214
		}
-
 
1215
	    }
-
 
1216
	}
-
 
1217
	/* Tickmark labels. */
-
 
1218
	gpptr(dd)->col = gpptr(dd)->colaxis;
-
 
1219
	gap = GStrWidth("m", -1, NFC, dd);	/* FIXUP x/y distance */
-
 
1220
	tlast = -1.0;
-
 
1221
	if (!R_FINITE(hadj)) {
-
 
1222
	    if (gpptr(dd)->las == 2 || gpptr(dd)->las == 3) {
-
 
1223
		gpptr(dd)->adj = (side == 1) ? 1 : 0;
-
 
1224
	    }
-
 
1225
	    else gpptr(dd)->adj = 0.5;
-
 
1226
	}
-
 
1227
	if (side == 1) {
-
 
1228
	    axis_lab = - axis_base
-
 
1229
		+ GConvertYUnits(gpptr(dd)->mgp[1]-lineoff, LINES, NFC, dd)
-
 
1230
		+ GConvertY(0.0, NPC, NFC, dd);
-
 
1231
	}
-
 
1232
	else { /* side == 3 */
-
 
1233
	    axis_lab = axis_base
-
 
1234
		+ GConvertYUnits(gpptr(dd)->mgp[1]-lineoff, LINES, NFC, dd)
-
 
1235
		- GConvertY(1.0, NPC, NFC, dd);
-
 
1236
	}
-
 
1237
	axis_lab = GConvertYUnits(axis_lab, NFC, LINES, dd);
-
 
1238
 
-
 
1239
	/* The order of processing is important here. */
-
 
1240
	/* We must ensure that the labels are drawn left-to-right. */
-
 
1241
	/* The logic here is getting way too convoluted. */
-
 
1242
	/* This needs a serious rewrite. */
-
 
1243
 
-
 
1244
	if (gpptr(dd)->usr[0] > gpptr(dd)->usr[1]) {
-
 
1245
	    istart = n - 1;
-
 
1246
	    iend = -1;
-
 
1247
	    incr = -1;
-
 
1248
	}
-
 
1249
	else {
-
 
1250
	    istart = 0;
-
 
1251
	    iend = n;
-
 
1252
	    incr = 1;
-
 
1253
	}
-
 
1254
	for (i = istart; i != iend; i += incr) {
-
 
1255
	    double padjval = REAL(padj)[i%npadj];
-
 
1256
	    padjval = ComputePAdjValue(padjval, side, gpptr(dd)->las);
-
 
1257
	    x = REAL(at)[i];
-
 
1258
	    if (!R_FINITE(x)) continue;
-
 
1259
	    temp = GConvertX(x, USER, NFC, dd);
-
 
1260
	    if (dolabels) {
-
 
1261
		/* Clip tick labels to user coordinates. */
-
 
1262
		if (x > low && x < high) {
-
 
1263
		    if (isExpression(lab)) {
-
 
1264
			GMMathText(VECTOR_ELT(lab, ind[i]), side,
-
 
1265
				   axis_lab, 0, x, gpptr(dd)->las,
-
 
1266
				   padjval, dd);
-
 
1267
		    }
-
 
1268
		    else {
-
 
1269
			label = STRING_ELT(lab, ind[i]);
-
 
1270
			if(label != NA_STRING) {
-
 
1271
			    const char *ss = CHAR(label);
-
 
1272
			    labw = GStrWidth(ss, 0, NFC, dd);
-
 
1273
			    tnew = temp - 0.5 * labw;
-
 
1274
			    /* Check room for perpendicular labels. */
-
 
1275
			    if (gpptr(dd)->las == 2 ||
-
 
1276
				gpptr(dd)->las == 3 ||
-
 
1277
				tnew - tlast >= gap) {
-
 
1278
				GMtext(ss, getCharCE(label),
-
 
1279
				       side, axis_lab, 0, x,
-
 
1280
				       gpptr(dd)->las, padjval, dd);
-
 
1281
				tlast = temp + 0.5 *labw;
-
 
1282
			    }
-
 
1283
			}
-
 
1284
		    }
-
 
1285
		}
-
 
1286
	    }
-
 
1287
	}
-
 
1288
	break;
-
 
1289
 
-
 
1290
    case 2: /*--- y-axis -- vertical --- */
-
 
1291
    case 4:
-
 
1292
        /* First set the clipping limits */
-
 
1293
        getylimits(limits, dd);
-
 
1294
        /* Now override par("xpd") and force clipping to device region. */
-
 
1295
        gpptr(dd)->xpd = 2;
-
 
1296
	GetAxisLimits(limits[0], limits[1], logflag, &low, &high);
-
 
1297
	axis_low = GConvertY(fmin2(high, fmax2(low, REAL(at)[0])), USER, NFC, dd);
-
 
1298
	axis_high = GConvertY(fmin2(high, fmax2(low, REAL(at)[n-1])), USER, NFC, dd);
-
 
1299
	if (side == 2) {
-
 
1300
	    if (R_FINITE(pos))
-
 
1301
		axis_base = GConvertX(pos, USER, NFC, dd);
-
 
1302
	    else
-
 
1303
		axis_base =  GConvertX(0.0, outer, NFC, dd)
-
 
1304
		    - GConvertXUnits(line, LINES, NFC, dd);
-
 
1305
	    if (R_FINITE(gpptr(dd)->tck)) {
-
 
1306
		double len, xu, yu;
-
 
1307
		if(gpptr(dd)->tck > 0.5)
-
 
1308
		    len = GConvertXUnits(gpptr(dd)->tck, NPC, NFC, dd);
-
 
1309
		else {
-
 
1310
		    xu = GConvertXUnits(gpptr(dd)->tck, NPC, INCHES, dd);
-
 
1311
		    yu = GConvertYUnits(gpptr(dd)->tck, NPC, INCHES, dd);
-
 
1312
		    xu = (fabs(xu) < fabs(yu)) ? xu : yu;
-
 
1313
		    len = GConvertXUnits(xu, INCHES, NFC, dd);
-
 
1314
		}
-
 
1315
		axis_tick = axis_base + len;
-
 
1316
	    } else
-
 
1317
		axis_tick = axis_base +
-
 
1318
		    GConvertXUnits(gpptr(dd)->tcl, LINES, NFC, dd);
-
 
1319
	}
-
 
1320
	else {
-
 
1321
	    if (R_FINITE(pos))
-
 
1322
		axis_base = GConvertX(pos, USER, NFC, dd);
-
 
1323
	    else
-
 
1324
		axis_base =  GConvertX(1.0, outer, NFC, dd)
-
 
1325
		    + GConvertXUnits(line, LINES, NFC, dd);
-
 
1326
	    if (R_FINITE(gpptr(dd)->tck)) {
-
 
1327
		double len, xu, yu;
-
 
1328
		if(gpptr(dd)->tck > 0.5)
-
 
1329
		    len = GConvertXUnits(gpptr(dd)->tck, NPC, NFC, dd);
-
 
1330
		else {
-
 
1331
		    xu = GConvertXUnits(gpptr(dd)->tck, NPC, INCHES, dd);
-
 
1332
		    yu = GConvertYUnits(gpptr(dd)->tck, NPC, INCHES, dd);
-
 
1333
		    xu = (fabs(xu) < fabs(yu)) ? xu : yu;
-
 
1334
		    len = GConvertXUnits(xu, INCHES, NFC, dd);
-
 
1335
		}
-
 
1336
		axis_tick = axis_base - len;
-
 
1337
	    } else
-
 
1338
		axis_tick = axis_base -
-
 
1339
		    GConvertXUnits(gpptr(dd)->tcl, LINES, NFC, dd);
-
 
1340
	}
-
 
1341
	if (doticks) {
-
 
1342
	    gpptr(dd)->col = col;
-
 
1343
	    if (lwd > 0.0)
-
 
1344
		GLine(axis_base, axis_low, axis_base, axis_high, NFC, dd);
-
 
1345
	    gpptr(dd)->col = colticks;
-
 
1346
	    gpptr(dd)->lwd = lwdticks;
-
 
1347
	    if (lwdticks > 0) {
-
 
1348
		for (i = 0; i < n; i++) {
-
 
1349
		    y = REAL(at)[i];
-
 
1350
		    if (low <= y && y <= high) {
-
 
1351
			y = GConvertY(y, USER, NFC, dd);
-
 
1352
			GLine(axis_base, y, axis_tick, y, NFC, dd);
-
 
1353
		    }
-
 
1354
		}
-
 
1355
	    }
-
 
1356
	}
-
 
1357
	/* Tickmark labels. */
-
 
1358
	gpptr(dd)->col = gpptr(dd)->colaxis;
-
 
1359
	gap = GStrWidth("m", CE_ANY, INCHES, dd);
-
 
1360
	gap = GConvertYUnits(gap, INCHES, NFC, dd);
-
 
1361
	tlast = -1.0;
-
 
1362
	if (!R_FINITE(hadj)) {
-
 
1363
	    if (gpptr(dd)->las == 1 || gpptr(dd)->las == 2) {
-
 
1364
		gpptr(dd)->adj = (side == 2) ? 1 : 0;
-
 
1365
	    }
-
 
1366
	    else gpptr(dd)->adj = 0.5;
-
 
1367
	}
-
 
1368
	if (side == 2) {
-
 
1369
	    axis_lab = - axis_base
-
 
1370
		+ GConvertXUnits(gpptr(dd)->mgp[1]-lineoff, LINES, NFC, dd)
-
 
1371
		+ GConvertX(0.0, NPC, NFC, dd);
-
 
1372
	}
-
 
1373
	else { /* side == 4 */
-
 
1374
	    axis_lab = axis_base
-
 
1375
		+ GConvertXUnits(gpptr(dd)->mgp[1]-lineoff, LINES, NFC, dd)
-
 
1376
		- GConvertX(1.0, NPC, NFC, dd);
-
 
1377
	}
-
 
1378
	axis_lab = GConvertXUnits(axis_lab, NFC, LINES, dd);
-
 
1379
 
-
 
1380
	/* The order of processing is important here. */
-
 
1381
	/* We must ensure that the labels are drawn left-to-right. */
-
 
1382
	/* The logic here is getting way too convoluted. */
-
 
1383
	/* This needs a serious rewrite. */
-
 
1384
 
-
 
1385
	if (gpptr(dd)->usr[2] > gpptr(dd)->usr[3]) {
-
 
1386
	    istart = n - 1;
-
 
1387
	    iend = -1;
-
 
1388
	    incr = -1;
-
 
1389
	}
-
 
1390
	else {
-
 
1391
	    istart = 0;
-
 
1392
	    iend = n;
-
 
1393
	    incr = 1;
-
 
1394
	}
-
 
1395
	for (i = istart; i != iend; i += incr) {
-
 
1396
	    double padjval = REAL(padj)[i%npadj];
-
 
1397
	    padjval = ComputePAdjValue(padjval, side, gpptr(dd)->las);
-
 
1398
	    y = REAL(at)[i];
-
 
1399
	    if (!R_FINITE(y)) continue;
-
 
1400
	    temp = GConvertY(y, USER, NFC, dd);
-
 
1401
	    if (dolabels) {
-
 
1402
		/* Clip tick labels to user coordinates. */
-
 
1403
		if (y > low && y < high) {
-
 
1404
		    if (isExpression(lab)) {
-
 
1405
			GMMathText(VECTOR_ELT(lab, ind[i]), side,
-
 
1406
				   axis_lab, 0, y, gpptr(dd)->las,
-
 
1407
				   padjval, dd);
-
 
1408
		    }
-
 
1409
		    else {
-
 
1410
			label = STRING_ELT(lab, ind[i]);
-
 
1411
			if(label != NA_STRING) {
-
 
1412
			    const char *ss = CHAR(label);
-
 
1413
			    labw = GStrWidth(ss, getCharCE(label), INCHES, dd);
-
 
1414
			    labw = GConvertYUnits(labw, INCHES, NFC, dd);
-
 
1415
			    tnew = temp - 0.5 * labw;
-
 
1416
			    /* Check room for perpendicular labels. */
-
 
1417
			    if (gpptr(dd)->las == 1 ||
-
 
1418
				gpptr(dd)->las == 2 ||
-
 
1419
				tnew - tlast >= gap) {
-
 
1420
				GMtext(ss, getCharCE(label),
-
 
1421
				       side, axis_lab, 0, y,
-
 
1422
				       gpptr(dd)->las, padjval, dd);
-
 
1423
				tlast = temp + 0.5 *labw;
-
 
1424
			    }
-
 
1425
			}
-
 
1426
		    }
-
 
1427
		}
-
 
1428
	    }
-
 
1429
	}
-
 
1430
	break;
-
 
1431
    } /* end  switch(side, ..) */
-
 
1432
    GMode(0, dd);
-
 
1433
    GRestorePars(dd);
-
 
1434
    /* NOTE: only record operation if no "error"  */
-
 
1435
    if (GRecording(call, dd))
-
 
1436
	GErecordGraphicOperation(op, originalArgs, dd);
-
 
1437
    UNPROTECT(4); /* lab, at, lab, padj again */
-
 
1438
    return at;
-
 
1439
}/* do_axis */
-
 
1440
 
-
 
1441
 
-
 
1442
SEXP attribute_hidden do_plot_xy(SEXP call, SEXP op, SEXP args, SEXP env)
-
 
1443
{
321
{
1444
/*	plot.xy(xy, type, pch, lty, col, bg, cex, lwd, ...)
-
 
1445
 
-
 
1446
 *	plot points or lines of various types
-
 
1447
 */
-
 
1448
    SEXP sxy, sx, sy, pch, cex, col, bg, lty, lwd;
-
 
1449
    double *x, *y, xold, yold, xx, yy, thiscex, thislwd;
-
 
1450
    int i, n, npch, ncex, ncol, nbg, nlwd, type=0, start=0, thispch;
-
 
1451
    rcolor thiscol, thisbg;
-
 
1452
    const void *vmax = NULL /* -Wall */;
-
 
1453
 
-
 
1454
    SEXP originalArgs = args;
-
 
1455
    pGEDevDesc dd = GEcurrentDevice();
-
 
1456
 
-
 
1457
    /* Basic Checks */
-
 
1458
    GCheckState(dd);
-
 
1459
    if (length(args) < 7)
-
 
1460
	error(_("too few arguments"));
-
 
1461
 
-
 
1462
    /* Required Arguments */
322
    /* format(labels): i.e. from numbers to strings */
1463
#define PLOT_XY_DEALING(subname)				\
-
 
1464
    sx = R_NilValue;		/* -Wall */			\
-
 
1465
    sy = R_NilValue;		/* -Wall */			\
323
    SEXP ans = R_NilValue;/* -Wall*/
1466
    sxy = CAR(args);						\
-
 
1467
    if (isNewList(sxy) && length(sxy) >= 2) {			\
-
 
1468
	internalTypeCheck(call, sx = VECTOR_ELT(sxy, 0), REALSXP); \
-
 
1469
	internalTypeCheck(call, sy = VECTOR_ELT(sxy, 1), REALSXP); \
-
 
1470
    }								\
-
 
1471
    else if (isList(sxy) && length(sxy) >= 2) {			\
-
 
1472
	internalTypeCheck(call, sx = CAR(sxy), REALSXP);	\
-
 
1473
	internalTypeCheck(call, sy = CADR(sxy), REALSXP);	\
-
 
1474
    }								\
-
 
1475
    else							\
-
 
1476
	error(_("invalid plotting structure"));	\
-
 
1477
    if (LENGTH(sx) != LENGTH(sy))				\
-
 
1478
	error(_("'x' and 'y' lengths differ in %s()"), subname);\
-
 
1479
    n = LENGTH(sx);						\
-
 
1480
    args = CDR(args)
-
 
1481
 
-
 
1482
    PLOT_XY_DEALING("plot.xy");
-
 
1483
 
-
 
1484
    if (isNull(CAR(args))) type = 'p';
324
    int i, n, w, d, e, wi, di, ei;
1485
    else {
-
 
1486
	if (isString(CAR(args)) && LENGTH(CAR(args)) == 1 &&
-
 
1487
	    LENGTH(pch = STRING_ELT(CAR(args), 0)) >= 1) {
-
 
1488
	    if(LENGTH(pch) > 1)
-
 
1489
		warning(_("plot type '%s' will be truncated to first character"),
-
 
1490
			CHAR(pch));
-
 
1491
	    type = CHAR(pch)[0];
-
 
1492
	}
-
 
1493
	else error(_("invalid plot type"));
-
 
1494
    }
-
 
1495
    args = CDR(args);
325
    const char *strp;
1496
 
-
 
1497
    PROTECT(pch = FixupPch(CAR(args), gpptr(dd)->pch));
-
 
1498
    npch = length(pch);
326
    n = length(labels);
1499
    args = CDR(args);
-
 
1500
 
-
 
1501
    PROTECT(lty = FixupLty(CAR(args), gpptr(dd)->lty));
-
 
1502
    args = CDR(args);
-
 
1503
 
-
 
1504
    /* Default col was NA_INTEGER (0x80000000) which was interpreted
-
 
1505
       as zero (black) or "don't draw" depending on line/rect/circle
-
 
1506
       situation. Now we set the default to zero and don't plot at all
327
    R_print.digits = 7;/* maximally 7 digits -- ``burnt in'';
1507
       if col==NA.
-
 
1508
 
-
 
1509
       FIXME: bg needs similar change, but that requires changes to
-
 
1510
       the specific drivers. */
-
 
1511
 
-
 
1512
    PROTECT(col = FixupCol(CAR(args), 0));		args = CDR(args);
-
 
1513
    ncol = LENGTH(col);
328
			  S-PLUS <= 5.x has about 6
1514
 
-
 
1515
    PROTECT(bg = FixupCol(CAR(args), R_TRANWHITE));	args = CDR(args);
-
 
1516
    nbg = LENGTH(bg);
-
 
1517
 
-
 
1518
    PROTECT(cex = FixupCex(CAR(args), 1.0));		args = CDR(args);
-
 
1519
    ncex = LENGTH(cex);
-
 
1520
 
-
 
1521
    PROTECT(lwd = FixupLwd(CAR(args), gpptr(dd)->lwd)); args = CDR(args);
-
 
1522
    nlwd = LENGTH(lwd);
-
 
1523
 
-
 
1524
    /* Miscellaneous Graphical Parameters */
329
			  (but really uses single precision..) */
1525
    GSavePars(dd);
-
 
1526
    ProcessInlinePars(args, dd);
-
 
1527
 
-
 
1528
    x = REAL(sx);
-
 
1529
    y = REAL(sy);
-
 
1530
 
-
 
1531
    if (INTEGER(lty)[0] != NA_INTEGER)
-
 
1532
	gpptr(dd)->lty = INTEGER(lty)[0];
-
 
1533
    if (R_FINITE( (thislwd = REAL(lwd)[0]) ))
-
 
1534
	gpptr(dd)->lwd = thislwd; /* but do recycle for "p" etc */
-
 
1535
 
-
 
1536
    GMode(1, dd);
-
 
1537
 
-
 
1538
    /* Line drawing :*/
-
 
1539
    switch(type) {
330
    switch(TYPEOF(labels)) {
1540
    case 'l':
-
 
1541
    case 'o':
331
    case LGLSXP:
1542
	/* lines and overplotted lines and points */
332
	PROTECT(ans = allocVector(STRSXP, n));
1543
	gpptr(dd)->col = INTEGER(col)[0];
-
 
1544
	xold = NA_REAL;
-
 
1545
	yold = NA_REAL;
-
 
1546
	for (i = 0; i < n; i++) {
333
	for (i = 0; i < n; i++) {
1547
	    xx = x[i];
-
 
1548
	    yy = y[i];
-
 
1549
	    /* do the conversion now to check for non-finite */
-
 
1550
	    GConvert(&xx, &yy, USER, DEVICE, dd);
334
	    strp = EncodeLogical(LOGICAL(labels)[i], 0);
1551
	    if ((R_FINITE(xx) && R_FINITE(yy)) &&
335
	    SET_STRING_ELT(ans, i, mkChar(strp));
1552
		!(R_FINITE(xold) && R_FINITE(yold)))
-
 
1553
		start = i;
-
 
1554
	    else if ((R_FINITE(xold) && R_FINITE(yold)) &&
-
 
1555
		     !(R_FINITE(xx) && R_FINITE(yy))) {
-
 
1556
		if (i-start > 1)
-
 
1557
		    GPolyline(i-start, x+start, y+start, USER, dd);
-
 
1558
	    }
-
 
1559
	    else if ((R_FINITE(xold) && R_FINITE(yold)) && (i == n-1))
-
 
1560
		GPolyline(n-start, x+start, y+start, USER, dd);
-
 
1561
	    xold = xx;
-
 
1562
	    yold = yy;
-
 
1563
	}
336
	}
-
 
337
	UNPROTECT(1);
1564
	break;
338
	break;
1565
 
-
 
1566
    case 'b':
339
    case INTSXP:
1567
    case 'c': /* broken lines (with points in between if 'b') */
-
 
1568
    {
-
 
1569
	double d, f;
-
 
1570
	d = GConvertYUnits(0.5, CHARS, INCHES, dd);
-
 
1571
	gpptr(dd)->col = INTEGER(col)[0];
-
 
1572
	xold = NA_REAL;
-
 
1573
	yold = NA_REAL;
-
 
1574
	for (i = 0; i < n; i++) {
-
 
1575
	    xx = x[i];
-
 
1576
	    yy = y[i];
-
 
1577
	    GConvert(&xx, &yy, USER, INCHES, dd);
340
	PROTECT(ans = allocVector(STRSXP, n));
1578
	    if (R_FINITE(xold) && R_FINITE(yold) &&
-
 
1579
		R_FINITE(xx) && R_FINITE(yy)) {
-
 
1580
		if ((f = d/hypot(xx-xold, yy-yold)) < 0.5) {
-
 
1581
		    GLine(xold + f * (xx - xold),
-
 
1582
			  yold + f * (yy - yold),
-
 
1583
			  xx + f * (xold - xx),
-
 
1584
			  yy + f * (yold - yy),
-
 
1585
			  INCHES, dd);
-
 
1586
		}
-
 
1587
	    }
-
 
1588
	    xold = xx;
-
 
1589
	    yold = yy;
-
 
1590
	}
-
 
1591
    }
-
 
1592
    break;
-
 
1593
 
-
 
1594
    case 's': /* step function	I */
-
 
1595
    {
-
 
1596
	double *xtemp, *ytemp;
-
 
1597
	int n0 = 0;
-
 
1598
	if(n <= 1000) {
-
 
1599
	    xtemp = (double *) alloca(2*n*sizeof(double));
-
 
1600
	    ytemp = (double *) alloca(2*n*sizeof(double));
-
 
1601
	    R_CheckStack();
-
 
1602
	} else {
-
 
1603
	    vmax = vmaxget();
-
 
1604
	    xtemp = (double *) R_alloc(2*n, sizeof(double));
-
 
1605
	    ytemp = (double *) R_alloc(2*n, sizeof(double));
-
 
1606
	}
-
 
1607
	gpptr(dd)->col = INTEGER(col)[0];
-
 
1608
	xold = NA_REAL;
-
 
1609
	yold = NA_REAL;
-
 
1610
	for (i = 0; i < n; i++) {
341
	for (i = 0; i < n; i++) {
1611
	    xx = x[i];
-
 
1612
	    yy = y[i];
-
 
1613
	    GConvert(&xx, &yy, USER, DEVICE, dd);
342
	    strp = EncodeInteger(INTEGER(labels)[i], 0);
1614
	    if ((R_FINITE(xx) && R_FINITE(yy)) &&
343
	    SET_STRING_ELT(ans, i, mkChar(strp));
1615
		(R_FINITE(xold) && R_FINITE(yold))) {
-
 
1616
		if(n0 == 0) { xtemp[n0] = xold; ytemp[n0++] = yold; }
-
 
1617
		xtemp[n0] = xx; ytemp[n0++] = yold;/* <-only diff 's' <-> 'S' */
-
 
1618
		xtemp[n0] = xx;	ytemp[n0++] = yy;
-
 
1619
	    } else if( (R_FINITE(xold) && R_FINITE(yold)) &&
-
 
1620
		       !(R_FINITE(xx)  && R_FINITE(yy))	  && n0 > 0) {
-
 
1621
		GPolyline(n0, xtemp, ytemp, DEVICE, dd);
-
 
1622
		n0 = 0;
-
 
1623
	    }
-
 
1624
	    xold = xx;
-
 
1625
	    yold = yy;
-
 
1626
	}
-
 
1627
	if(n0 > 0) GPolyline(n0, xtemp, ytemp, DEVICE, dd);
-
 
1628
	if(n > 1000) vmaxset(vmax);
-
 
1629
    }
-
 
1630
    break;
-
 
1631
 
-
 
1632
    case 'S': /* step function	II */
-
 
1633
    {
-
 
1634
	double *xtemp, *ytemp;
-
 
1635
	int n0 = 0;
-
 
1636
	if(n < 1000) {
-
 
1637
	    xtemp = (double *) alloca(2*n*sizeof(double));
-
 
1638
	    ytemp = (double *) alloca(2*n*sizeof(double));
-
 
1639
	    R_CheckStack();
-
 
1640
	} else {
-
 
1641
	    vmax = vmaxget();
-
 
1642
	    xtemp = (double *) R_alloc(2*n, sizeof(double));
-
 
1643
	    ytemp = (double *) R_alloc(2*n, sizeof(double));
-
 
1644
	}
344
	}
1645
	gpptr(dd)->col = INTEGER(col)[0];
345
	UNPROTECT(1);
1646
	xold = NA_REAL;
346
	break;
1647
	yold = NA_REAL;
347
    case REALSXP:
-
 
348
	formatReal(REAL(labels), n, &w, &d, &e, 0);
-
 
349
	PROTECT(ans = allocVector(STRSXP, n));
1648
	for (i = 0; i < n; i++) {
350
	for (i = 0; i < n; i++) {
1649
	    xx = x[i];
-
 
1650
	    yy = y[i];
-
 
1651
	    GConvert(&xx, &yy, USER, DEVICE, dd);
351
	    strp = EncodeReal(REAL(labels)[i], 0, d, e, OutDec);
1652
	    if ((R_FINITE(xx) && R_FINITE(yy)) &&
352
	    SET_STRING_ELT(ans, i, mkChar(strp));
1653
		(R_FINITE(xold) && R_FINITE(yold))) {
-
 
1654
		if(n0 == 0) {xtemp[n0] = xold; ytemp[n0++] = yold;}
-
 
1655
		xtemp[n0] = xold; ytemp[n0++] = yy;
-
 
1656
		xtemp[n0] = xx;	ytemp[n0++] = yy;
-
 
1657
	    } else if( (R_FINITE(xold) && R_FINITE(yold)) &&
-
 
1658
		       !(R_FINITE(xx)  && R_FINITE(yy))	  && n0 > 0) {
-
 
1659
		GPolyline(n0, xtemp, ytemp, DEVICE, dd);
-
 
1660
		n0 = 0;
-
 
1661
	    }
-
 
1662
	    xold = xx;
-
 
1663
	    yold = yy;
-
 
1664
	}
353
	}
1665
	if(n0 > 0) GPolyline(n0, xtemp, ytemp, DEVICE, dd);
-
 
1666
	if(n > 1000) vmaxset(vmax);
354
	UNPROTECT(1);
1667
    }
-
 
1668
    break;
355
	break;
1669
 
-
 
1670
    case 'h': /* h[istogram] (bar plot) */
-
 
1671
	if (gpptr(dd)->ylog)
356
    case CPLXSXP:
1672
	    yold = gpptr(dd)->usr[2];/* DBL_MIN fails.. why ???? */
357
	formatComplex(COMPLEX(labels), n, &w, &d, &e, &wi, &di, &ei, 0);
1673
	else
-
 
1674
	    yold = 0.0;
-
 
1675
	yold = GConvertY(yold, USER, DEVICE, dd);
358
	PROTECT(ans = allocVector(STRSXP, n));
1676
	for (i = 0; i < n; i++) {
359
	for (i = 0; i < n; i++) {
1677
	    xx = x[i];
-
 
1678
	    yy = y[i];
-
 
1679
	    GConvert(&xx, &yy, USER, DEVICE, dd);
-
 
1680
	    if (R_FINITE(xx) && R_FINITE(yy)
-
 
1681
		&& !R_TRANSPARENT(thiscol = INTEGER(col)[i % ncol])) {
360
	    strp = EncodeComplex(COMPLEX(labels)[i], 0, d, e, 0, di, ei,
1682
		gpptr(dd)->col = thiscol;
361
				 OutDec);
1683
		GLine(xx, yold, xx, yy, DEVICE, dd);
362
	    SET_STRING_ELT(ans, i, mkChar(strp));
1684
	    }
-
 
1685
	}
363
	}
-
 
364
	UNPROTECT(1);
1686
	break;
365
	break;
1687
 
-
 
1688
    case 'p':
366
    case STRSXP:
1689
    case 'n': /* nothing here */
-
 
1690
	break;
-
 
1691
 
-
 
1692
    default:/* OTHERWISE */
-
 
1693
	error(_("invalid plot type '%c'"), type);
367
	PROTECT(ans = allocVector(STRSXP, n));
1694
 
-
 
1695
    } /* End {switch(type)} - for lines */
-
 
1696
 
-
 
1697
    /* Points : */
-
 
1698
    if (type == 'p' || type == 'b' || type == 'o') {
-
 
1699
	for (i = 0; i < n; i++) {
368
	for (i = 0; i < n; i++) {
1700
	    xx = x[i];
-
 
1701
	    yy = y[i];
-
 
1702
	    GConvert(&xx, &yy, USER, DEVICE, dd);
-
 
1703
	    if (R_FINITE(xx) && R_FINITE(yy)) {
-
 
1704
		if (R_FINITE( (thiscex = REAL(cex)[i % ncex]) ) &&
-
 
1705
		    (thispch = INTEGER(pch)[i % npch]) != NA_INTEGER) {
-
 
1706
		    /* FIXME: should this skip 0-sized symbols? */
-
 
1707
		    thiscol = INTEGER(col)[i % ncol];
-
 
1708
		    thisbg = INTEGER(bg)[i % nbg];
-
 
1709
		    if (!(R_TRANSPARENT(thiscol) &&
-
 
1710
			  R_TRANSPARENT(thisbg))) {
-
 
1711
			gpptr(dd)->cex = thiscex * gpptr(dd)->cexbase;
-
 
1712
			gpptr(dd)->col = thiscol;
-
 
1713
			if(nlwd > 1 &&
-
 
1714
			   R_FINITE((thislwd = REAL(lwd)[i % nlwd])))
-
 
1715
			    gpptr(dd)->lwd = thislwd;
-
 
1716
			gpptr(dd)->bg = thisbg;
-
 
1717
			GSymbol(xx, yy, DEVICE, thispch, dd);
-
 
1718
		    }
-
 
1719
		}
-
 
1720
	    }
-
 
1721
	}
-
 
1722
    }
-
 
1723
    GMode(0, dd);
-
 
1724
    GRestorePars(dd);
-
 
1725
    UNPROTECT(6);
-
 
1726
    /* NOTE: only record operation if no "error"  */
-
 
1727
    if (GRecording(call, dd))
-
 
1728
	GErecordGraphicOperation(op, originalArgs, dd);
-
 
1729
    return R_NilValue;
-
 
1730
}/* do_plot_xy */
-
 
1731
 
-
 
1732
/* Checks for ... , x0, y0, x1, y1 ... */
-
 
1733
 
-
 
1734
static void xypoints(SEXP call, SEXP args, int *n)
-
 
1735
{
-
 
1736
    int k=0,/* -Wall */ kmin;
-
 
1737
 
-
 
1738
    if (!isNumeric(CAR(args)))
-
 
1739
	error(_("invalid first argument"));
-
 
1740
    SETCAR(args, coerceVector(CAR(args), REALSXP));
-
 
1741
    k = LENGTH(CAR(args));
-
 
1742
    *n = k; kmin = k;
-
 
1743
    args = CDR(args);
-
 
1744
 
-
 
1745
    if (!isNumeric(CAR(args)))
-
 
1746
	error(_("invalid second argument"));
-
 
1747
    k = LENGTH(CAR(args));
-
 
1748
    SETCAR(args, coerceVector(CAR(args), REALSXP));
-
 
1749
    if (k > *n) *n = k;
-
 
1750
    if (k < kmin) kmin = k;
-
 
1751
    args = CDR(args);
-
 
1752
 
-
 
1753
    if (!isNumeric(CAR(args)))
-
 
1754
	error(_("invalid third argument"));
-
 
1755
    SETCAR(args, coerceVector(CAR(args), REALSXP));
-
 
1756
    k = LENGTH(CAR(args));
-
 
1757
    if (k > *n) *n = k;
-
 
1758
    if (k < kmin) kmin = k;
-
 
1759
    args = CDR(args);
-
 
1760
 
-
 
1761
    if (!isNumeric(CAR(args)))
-
 
1762
	error(_("invalid fourth argument"));
-
 
1763
    SETCAR(args, coerceVector(CAR(args), REALSXP));
-
 
1764
    k = LENGTH(CAR(args));
-
 
1765
    if (k > *n) *n = k;
-
 
1766
    if (k < kmin) kmin = k;
-
 
1767
    args = CDR(args);
-
 
1768
 
-
 
1769
    if (*n > 0 && kmin == 0)
-
 
1770
	error(_("cannot mix zero-length and non-zero-length coordinates"));
-
 
1771
}
-
 
1772
 
-
 
1773
 
-
 
1774
SEXP attribute_hidden do_segments(SEXP call, SEXP op, SEXP args, SEXP env)
-
 
1775
{
-
 
1776
    /* segments(x0, y0, x1, y1, col, lty, lwd, ...) */
-
 
1777
    SEXP sx0, sx1, sy0, sy1, col, lty, lwd;
-
 
1778
    double *x0, *x1, *y0, *y1;
-
 
1779
    double xx[2], yy[2];
-
 
1780
    int nx0, nx1, ny0, ny1, i, n, ncol, nlty, nlwd;
-
 
1781
    SEXP originalArgs = args;
-
 
1782
    pGEDevDesc dd = GEcurrentDevice();
-
 
1783
 
-
 
1784
    if (length(args) < 4) error(_("too few arguments"));
-
 
1785
    GCheckState(dd);
-
 
1786
 
-
 
1787
    xypoints(call, args, &n);
-
 
1788
    if(n == 0) return R_NilValue;
-
 
1789
 
-
 
1790
    sx0 = CAR(args); nx0 = length(sx0); args = CDR(args);
-
 
1791
    sy0 = CAR(args); ny0 = length(sy0); args = CDR(args);
-
 
1792
    sx1 = CAR(args); nx1 = length(sx1); args = CDR(args);
-
 
1793
    sy1 = CAR(args); ny1 = length(sy1); args = CDR(args);
-
 
1794
 
-
 
1795
    PROTECT(col = FixupCol(CAR(args), R_TRANWHITE));
-
 
1796
    ncol = LENGTH(col); args = CDR(args);
-
 
1797
 
-
 
1798
    PROTECT(lty = FixupLty(CAR(args), gpptr(dd)->lty));
-
 
1799
    nlty = length(lty); args = CDR(args);
-
 
1800
 
-
 
1801
    PROTECT(lwd = FixupLwd(CAR(args), gpptr(dd)->lwd));
-
 
1802
    nlwd = length(lwd); args = CDR(args);
-
 
1803
 
-
 
1804
    GSavePars(dd);
-
 
1805
    ProcessInlinePars(args, dd);
-
 
1806
 
-
 
1807
    x0 = REAL(sx0);
-
 
1808
    y0 = REAL(sy0);
-
 
1809
    x1 = REAL(sx1);
-
 
1810
    y1 = REAL(sy1);
-
 
1811
 
-
 
1812
    GMode(1, dd);
-
 
1813
    for (i = 0; i < n; i++) {
-
 
1814
	xx[0] = x0[i%nx0];
-
 
1815
	yy[0] = y0[i%ny0];
-
 
1816
	xx[1] = x1[i%nx1];
-
 
1817
	yy[1] = y1[i%ny1];
-
 
1818
	GConvert(xx, yy, USER, DEVICE, dd);
-
 
1819
	GConvert(xx+1, yy+1, USER, DEVICE, dd);
-
 
1820
	if (R_FINITE(xx[0]) && R_FINITE(yy[0]) &&
-
 
1821
	    R_FINITE(xx[1]) && R_FINITE(yy[1]))
369
	    SET_STRING_ELT(ans, i, STRING_ELT(labels, i));
1822
	{
-
 
1823
	    int thiscol = INTEGER(col)[i % ncol];
-
 
1824
	    if(!R_TRANSPARENT(thiscol)) {
-
 
1825
		gpptr(dd)->col = thiscol;
-
 
1826
		gpptr(dd)->lty = INTEGER(lty)[i % nlty];
-
 
1827
		gpptr(dd)->lwd = REAL(lwd)[i % nlwd];
-
 
1828
		GLine(xx[0], yy[0], xx[1], yy[1], DEVICE, dd);
-
 
1829
	    }
-
 
1830
	}
370
	}
-
 
371
	UNPROTECT(1);
-
 
372
	break;
-
 
373
    default:
-
 
374
	error(_("invalid type for axis labels"));
1831
    }
375
    }
1832
    GMode(0, dd);
-
 
1833
    GRestorePars(dd);
-
 
1834
 
-
 
1835
    UNPROTECT(3);
-
 
1836
    /* NOTE: only record operation if no "error"  */
-
 
1837
    if (GRecording(call, dd))
-
 
1838
	GErecordGraphicOperation(op, originalArgs, dd);
-
 
1839
    return R_NilValue;
376
    return ans;
1840
}
377
}
1841
 
378
 
1842
 
379
 
1843
SEXP attribute_hidden do_rect(SEXP call, SEXP op, SEXP args, SEXP env)
-
 
1844
{
-
 
1845
    /* rect(xl, yb, xr, yt, col, border, lty, ...) */
380
    /* GRAPHICS FUNCTION ENTRY POINTS */
1846
    SEXP sxl, sxr, syb, syt, col, lty, lwd, border;
-
 
1847
    double *xl, *xr, *yb, *yt, x0, y0, x1, y1;
-
 
1848
    int i, n, nxl, nxr, nyb, nyt, ncol, nlty, nlwd, nborder;
-
 
1849
    SEXP originalArgs = args;
-
 
1850
    pGEDevDesc dd = GEcurrentDevice();
-
 
1851
 
-
 
1852
    if (length(args) < 4) error(_("too few arguments"));
-
 
1853
    GCheckState(dd);
-
 
1854
 
-
 
1855
    xypoints(call, args, &n);
-
 
1856
    if(n == 0) return R_NilValue;
-
 
1857
 
-
 
1858
    sxl = CAR(args); nxl = length(sxl); args = CDR(args);/* x_left */
-
 
1859
    syb = CAR(args); nyb = length(syb); args = CDR(args);/* y_bottom */
-
 
1860
    sxr = CAR(args); nxr = length(sxr); args = CDR(args);/* x_right */
-
 
1861
    syt = CAR(args); nyt = length(syt); args = CDR(args);/* y_top */
-
 
1862
 
-
 
1863
    PROTECT(col = FixupCol(CAR(args), R_TRANWHITE));
-
 
1864
    ncol = LENGTH(col);
-
 
1865
    args = CDR(args);
-
 
1866
 
-
 
1867
    PROTECT(border =  FixupCol(CAR(args), gpptr(dd)->fg));
-
 
1868
    nborder = LENGTH(border);
-
 
1869
    args = CDR(args);
-
 
1870
 
-
 
1871
    PROTECT(lty = FixupLty(CAR(args), gpptr(dd)->lty));
-
 
1872
    nlty = length(lty);
-
 
1873
    args = CDR(args);
-
 
1874
 
-
 
1875
    PROTECT(lwd = FixupLwd(CAR(args), gpptr(dd)->lwd));
-
 
1876
    nlwd = length(lwd);
-
 
1877
    args = CDR(args);
-
 
1878
 
-
 
1879
    GSavePars(dd);
-
 
1880
    ProcessInlinePars(args, dd);
-
 
1881
 
-
 
1882
    xl = REAL(sxl);
-
 
1883
    xr = REAL(sxr);
-
 
1884
    yb = REAL(syb);
-
 
1885
    yt = REAL(syt);
-
 
1886
 
-
 
1887
    GMode(1, dd);
-
 
1888
    for (i = 0; i < n; i++) {
-
 
1889
	if (nlty && INTEGER(lty)[i % nlty] != NA_INTEGER)
-
 
1890
	    gpptr(dd)->lty = INTEGER(lty)[i % nlty];
-
 
1891
	else
-
 
1892
	    gpptr(dd)->lty = dpptr(dd)->lty;
-
 
1893
	if (nlwd && REAL(lwd)[i % nlwd] != NA_REAL)
-
 
1894
	    gpptr(dd)->lwd = REAL(lwd)[i % nlwd];
-
 
1895
	else
-
 
1896
	    gpptr(dd)->lwd = dpptr(dd)->lwd;
-
 
1897
	x0 = xl[i%nxl];
-
 
1898
	y0 = yb[i%nyb];
-
 
1899
	x1 = xr[i%nxr];
-
 
1900
	y1 = yt[i%nyt];
-
 
1901
	GConvert(&x0, &y0, USER, DEVICE, dd);
-
 
1902
	GConvert(&x1, &y1, USER, DEVICE, dd);
-
 
1903
	if (R_FINITE(x0) && R_FINITE(y0) && R_FINITE(x1) && R_FINITE(y1))
-
 
1904
	    GRect(x0, y0, x1, y1, DEVICE, INTEGER(col)[i % ncol],
-
 
1905
		  INTEGER(border)[i % nborder], dd);
-
 
1906
    }
-
 
1907
    GMode(0, dd);
-
 
1908
 
381
 
1909
    GRestorePars(dd);
-
 
1910
    UNPROTECT(4);
-
 
1911
    /* NOTE: only record operation if no "error"  */
-
 
1912
    if (GRecording(call, dd))
-
 
1913
	GErecordGraphicOperation(op, originalArgs, dd);
-
 
1914
    return R_NilValue;
-
 
1915
}
-
 
1916
 
382
 
1917
SEXP attribute_hidden do_path(SEXP call, SEXP op, SEXP args, SEXP env)
383
SEXP attribute_hidden do_plot_new(SEXP call, SEXP op, SEXP args, SEXP env)
1918
{
384
{
1919
    /* path(x, y, col, border, lty, ...) */
385
    /* plot.new() - create a new plot "frame" */
1920
    SEXP sx, sy, nper, rule, col, border, lty;
-
 
1921
    int i, nx, npoly;
-
 
1922
    double *xx, *yy;
-
 
1923
    const void *vmax = NULL /* -Wall */;
-
 
1924
 
-
 
1925
    SEXP originalArgs = args;
-
 
1926
    pGEDevDesc dd = GEcurrentDevice();
-
 
1927
 
-
 
1928
    GCheckState(dd);
-
 
1929
 
-
 
1930
    if (length(args) < 2) error(_("too few arguments"));
-
 
1931
    /* (x,y) is checked in R via xy.coords() ; no need here : */
-
 
1932
    sx = SETCAR(args, coerceVector(CAR(args), REALSXP));  args = CDR(args);
-
 
1933
    sy = SETCAR(args, coerceVector(CAR(args), REALSXP));  args = CDR(args);
-
 
1934
    nx = LENGTH(sx);
-
 
1935
 
-
 
1936
    PROTECT(nper = CAR(args)); args = CDR(args);
-
 
1937
    npoly = LENGTH(nper);
-
 
1938
 
-
 
1939
    PROTECT(rule = CAR(args)); args = CDR(args);
-
 
1940
 
-
 
1941
    PROTECT(col = FixupCol(CAR(args), R_TRANWHITE));	args = CDR(args);
-
 
1942
    PROTECT(border = FixupCol(CAR(args), gpptr(dd)->fg)); args = CDR(args);
-
 
1943
    PROTECT(lty = FixupLty(CAR(args), gpptr(dd)->lty)); args = CDR(args);
-
 
1944
 
-
 
1945
    GSavePars(dd);
-
 
1946
    ProcessInlinePars(args, dd);
-
 
1947
 
386
 
1948
    GMode(1, dd);
387
    pGEDevDesc dd;
1949
 
388
 
1950
    vmax = vmaxget();
389
    checkArity(op, args);
1951
 
390
 
-
 
391
    dd = GEcurrentDevice();
1952
    /*
392
    /*
1953
     * Work in device coordinates because that is what the
393
     * If user is prompted before new page, user has opportunity
-
 
394
     * to kill current device.  GNewPlot returns (potentially new)
1954
     * graphics engine needs.
395
     * current device.
1955
     */
396
     */
1956
    xx = (double*) R_alloc(nx, sizeof(double));
-
 
1957
    yy = (double*) R_alloc(nx, sizeof(double));
-
 
1958
    if (!xx || !yy)
-
 
1959
	error(_("unable to allocate memory (in GPath)"));
-
 
1960
    for (i=0; i<nx; i++) {
-
 
1961
        xx[i] = REAL(sx)[i];
-
 
1962
        yy[i] = REAL(sy)[i];
-
 
1963
        GConvert(&(xx[i]), &(yy[i]), USER, DEVICE, dd);
-
 
1964
        if (!(R_FINITE(xx[i]) && R_FINITE(yy[i])))
-
 
1965
            error(_("invalid x or y (in GPath)"));
-
 
1966
    }
-
 
1967
 
-
 
1968
    if (INTEGER(lty)[0] == NA_INTEGER)
-
 
1969
	gpptr(dd)->lty = dpptr(dd)->lty;
-
 
1970
    else
-
 
1971
	gpptr(dd)->lty = INTEGER(lty)[0];
-
 
1972
 
-
 
1973
    GPath(xx, yy, npoly, INTEGER(nper), INTEGER(rule)[0] == 1,
-
 
1974
          INTEGER(col)[0], INTEGER(border)[0], dd);
-
 
1975
 
-
 
1976
    GMode(0, dd);
-
 
1977
 
-
 
1978
    GRestorePars(dd);
-
 
1979
    UNPROTECT(5);
-
 
1980
    /* NOTE: only record operation if no "error"  */
-
 
1981
    if (GRecording(call, dd))
-
 
1982
	GErecordGraphicOperation(op, originalArgs, dd);
-
 
1983
 
-
 
1984
    vmaxset(vmax);
-
 
1985
    return R_NilValue;
-
 
1986
}
-
 
1987
 
-
 
1988
SEXP attribute_hidden do_raster(SEXP call, SEXP op, SEXP args, SEXP env)
-
 
1989
{
-
 
1990
    /* raster(image, xl, yb, xr, yt, angle, interpolate, ...) */
-
 
1991
    const void *vmax;
-
 
1992
    unsigned int *image;
-
 
1993
    SEXP raster, dim, sxl, sxr, syb, syt, angle, interpolate;
-
 
1994
    double *xl, *xr, *yb, *yt, x0, y0, x1, y1;
-
 
1995
    int i, n, nxl, nxr, nyb, nyt;
-
 
1996
    SEXP originalArgs = args;
-
 
1997
    pGEDevDesc dd = GEcurrentDevice();
-
 
1998
 
-
 
1999
    if (length(args) < 7) error(_("too few arguments"));
-
 
2000
    GCheckState(dd);
-
 
2001
 
-
 
2002
    raster = CAR(args); args = CDR(args);
-
 
2003
    n = LENGTH(raster);
-
 
2004
    dim = getAttrib(raster, R_DimSymbol);
-
 
2005
 
-
 
2006
    vmax = vmaxget();
-
 
2007
    /* raster is rather inefficient so allow a native representation as
-
 
2008
       an integer array which requires no conversion */
-
 
2009
    if (inherits(raster, "nativeRaster") && isInteger(raster))
-
 
2010
	image = (unsigned int*) INTEGER(raster);
-
 
2011
    else {
-
 
2012
	image = (unsigned int*) R_alloc(n, sizeof(unsigned int));
-
 
2013
	for (i=0; i<n; i++)
-
 
2014
	    image[i] = RGBpar3(raster, i, R_TRANWHITE);
-
 
2015
    }
-
 
2016
 
-
 
2017
    xypoints(call, args, &n);
-
 
2018
    if(n == 0) return R_NilValue;
-
 
2019
 
-
 
2020
    sxl = CAR(args); nxl = length(sxl); args = CDR(args);/* x_left */
-
 
2021
    syb = CAR(args); nyb = length(syb); args = CDR(args);/* y_bottom */
-
 
2022
    sxr = CAR(args); nxr = length(sxr); args = CDR(args);/* x_right */
-
 
2023
    syt = CAR(args); nyt = length(syt); args = CDR(args);/* y_top */
-
 
2024
 
-
 
2025
    angle = CAR(args); args = CDR(args);
-
 
2026
    interpolate = CAR(args); args = CDR(args);
-
 
2027
 
-
 
2028
    GSavePars(dd);
-
 
2029
    ProcessInlinePars(args, dd);
-
 
2030
 
-
 
2031
    xl = REAL(sxl);
-
 
2032
    xr = REAL(sxr);
-
 
2033
    yb = REAL(syb);
-
 
2034
    yt = REAL(syt);
-
 
2035
 
-
 
2036
    GMode(1, dd);
-
 
2037
    for (i = 0; i < n; i++) {
-
 
2038
	x0 = xl[i%nxl];
-
 
2039
	y0 = yb[i%nyb];
-
 
2040
	x1 = xr[i%nxr];
-
 
2041
	y1 = yt[i%nyt];
-
 
2042
	GConvert(&x0, &y0, USER, DEVICE, dd);
-
 
2043
	GConvert(&x1, &y1, USER, DEVICE, dd);
-
 
2044
	if (R_FINITE(x0) && R_FINITE(y0) && R_FINITE(x1) && R_FINITE(y1))
-
 
2045
           GRaster(image, INTEGER(dim)[1], INTEGER(dim)[0],
-
 
2046
                   x0, y0, x1 - x0, y1 - y0,
-
 
2047
                   REAL(angle)[i % LENGTH(angle)],
-
 
2048
                   LOGICAL(interpolate)[i % LENGTH(interpolate)], dd);
-
 
2049
    }
-
 
2050
    GMode(0, dd);
-
 
2051
 
-
 
2052
    GRestorePars(dd);
-
 
2053
    /* NOTE: only record operation if no "error"  */
-
 
2054
    if (GRecording(call, dd))
-
 
2055
	GErecordGraphicOperation(op, originalArgs, dd);
-
 
2056
 
-
 
2057
    vmaxset(vmax);
-
 
2058
    return R_NilValue;
-
 
2059
}
-
 
2060
 
-
 
2061
 
-
 
2062
SEXP attribute_hidden do_arrows(SEXP call, SEXP op, SEXP args, SEXP env)
-
 
2063
{
-
 
2064
    /* arrows(x0, y0, x1, y1, length, angle, code, col, lty, lwd, ...) */
-
 
2065
    SEXP sx0, sx1, sy0, sy1, col, lty, lwd;
-
 
2066
    double *x0, *x1, *y0, *y1;
-
 
2067
    double xx0, yy0, xx1, yy1;
-
 
2068
    double hlength, angle;
-
 
2069
    int code;
-
 
2070
    int nx0, nx1, ny0, ny1, i, n, ncol, nlty, nlwd;
-
 
2071
    rcolor thiscol;
-
 
2072
    SEXP originalArgs = args;
-
 
2073
    pGEDevDesc dd = GEcurrentDevice();
-
 
2074
 
-
 
2075
    if (length(args) < 4) error(_("too few arguments"));
-
 
2076
    GCheckState(dd);
-
 
2077
 
-
 
2078
    xypoints(call, args, &n);
-
 
2079
    if(n == 0) return R_NilValue;
-
 
2080
 
-
 
2081
    sx0 = CAR(args); nx0 = length(sx0); args = CDR(args);
-
 
2082
    sy0 = CAR(args); ny0 = length(sy0); args = CDR(args);
-
 
2083
    sx1 = CAR(args); nx1 = length(sx1); args = CDR(args);
-
 
2084
    sy1 = CAR(args); ny1 = length(sy1); args = CDR(args);
-
 
2085
 
-
 
2086
    hlength = asReal(CAR(args));
-
 
2087
    if (!R_FINITE(hlength) || hlength < 0)
-
 
2088
	error(_("invalid arrow head length"));
-
 
2089
    args = CDR(args);
-
 
2090
 
-
 
2091
    angle = asReal(CAR(args));
-
 
2092
    if (!R_FINITE(angle))
-
 
2093
	error(_("invalid arrow head angle"));
-
 
2094
    args = CDR(args);
-
 
2095
 
-
 
2096
    code = asInteger(CAR(args));
-
 
2097
    if (code == NA_INTEGER || code < 0 || code > 3)
-
 
2098
	error(_("invalid arrow head specification"));
-
 
2099
    args = CDR(args);
-
 
2100
 
-
 
2101
    PROTECT(col = FixupCol(CAR(args), R_TRANWHITE));
-
 
2102
    ncol = LENGTH(col);
-
 
2103
    args = CDR(args);
-
 
2104
 
-
 
2105
    PROTECT(lty = FixupLty(CAR(args), gpptr(dd)->lty));
-
 
2106
    nlty = length(lty);
-
 
2107
    args = CDR(args);
-
 
2108
 
-
 
2109
    PROTECT(lwd = FixupLwd(CAR(args), gpptr(dd)->lwd));
-
 
2110
    nlwd = length(lwd);
-
 
2111
    args = CDR(args);
-
 
2112
 
-
 
2113
    GSavePars(dd);
-
 
2114
    ProcessInlinePars(args, dd);
-
 
2115
 
-
 
2116
    x0 = REAL(sx0);
-
 
2117
    y0 = REAL(sy0);
-
 
2118
    x1 = REAL(sx1);
-
 
2119
    y1 = REAL(sy1);
-
 
2120
 
-
 
2121
    GMode(1, dd);
-
 
2122
    for (i = 0; i < n; i++) {
-
 
2123
	xx0 = x0[i%nx0];
-
 
2124
	yy0 = y0[i%ny0];
-
 
2125
	xx1 = x1[i%nx1];
-
 
2126
	yy1 = y1[i%ny1];
-
 
2127
	GConvert(&xx0, &yy0, USER, DEVICE, dd);
-
 
2128
	GConvert(&xx1, &yy1, USER, DEVICE, dd);
-
 
2129
	if (R_FINITE(xx0) && R_FINITE(yy0) && R_FINITE(xx1) && R_FINITE(yy1)
-
 
2130
	    && !R_TRANSPARENT(thiscol = INTEGER(col)[i % ncol])) {
-
 
2131
	    gpptr(dd)->col = thiscol;
-
 
2132
	    gpptr(dd)->lty = INTEGER(lty)[i % nlty];
-
 
2133
	    gpptr(dd)->lwd = REAL(lwd)[i % nlwd];
-
 
2134
	    GArrow(xx0, yy0, xx1, yy1, DEVICE,
-
 
2135
		   hlength, angle, code, dd);
-
 
2136
	}
-
 
2137
    }
-
 
2138
    GMode(0, dd);
-
 
2139
    GRestorePars(dd);
-
 
2140
 
-
 
2141
    UNPROTECT(3);
-
 
2142
    /* NOTE: only record operation if no "error"  */
-
 
2143
    if (GRecording(call, dd))
-
 
2144
	GErecordGraphicOperation(op, originalArgs, dd);
-
 
2145
    return R_NilValue;
-
 
2146
}
-
 
2147
 
-
 
2148
 
-
 
2149
static void drawPolygon(int n, double *x, double *y,
-
 
2150
			int lty, int fill, int border, pGEDevDesc dd)
-
 
2151
{
-
 
2152
    if (lty == NA_INTEGER)
-
 
2153
	gpptr(dd)->lty = dpptr(dd)->lty;
-
 
2154
    else
-
 
2155
	gpptr(dd)->lty = lty;
-
 
2156
    GPolygon(n, x, y, USER, fill, border, dd);
-
 
2157
}
-
 
2158
 
-
 
2159
SEXP attribute_hidden do_polygon(SEXP call, SEXP op, SEXP args, SEXP env)
-
 
2160
{
-
 
2161
    /* polygon(x, y, col, border, lty, ...) */
-
 
2162
    SEXP sx, sy, col, border, lty;
-
 
2163
    int nx;
-
 
2164
    int ncol, nborder, nlty, i, start=0;
-
 
2165
    int num = 0;
-
 
2166
    double *x, *y, xx, yy, xold, yold;
-
 
2167
 
-
 
2168
    SEXP originalArgs = args;
-
 
2169
    pGEDevDesc dd = GEcurrentDevice();
-
 
2170
 
-
 
2171
    GCheckState(dd);
-
 
2172
 
-
 
2173
    if (length(args) < 2) error(_("too few arguments"));
-
 
2174
    /* (x,y) is checked in R via xy.coords() ; no need here : */
-
 
2175
    sx = SETCAR(args, coerceVector(CAR(args), REALSXP));  args = CDR(args);
-
 
2176
    sy = SETCAR(args, coerceVector(CAR(args), REALSXP));  args = CDR(args);
-
 
2177
    nx = LENGTH(sx);
-
 
2178
 
-
 
2179
    PROTECT(col = FixupCol(CAR(args), R_TRANWHITE));	args = CDR(args);
-
 
2180
    ncol = LENGTH(col);
-
 
2181
 
-
 
2182
    PROTECT(border = FixupCol(CAR(args), gpptr(dd)->fg)); args = CDR(args);
-
 
2183
    nborder = LENGTH(border);
-
 
2184
 
-
 
2185
    PROTECT(lty = FixupLty(CAR(args), gpptr(dd)->lty)); args = CDR(args);
-
 
2186
    nlty = length(lty);
-
 
2187
 
-
 
2188
    GSavePars(dd);
-
 
2189
    ProcessInlinePars(args, dd);
-
 
2190
 
-
 
2191
    GMode(1, dd);
-
 
2192
 
-
 
2193
    x = REAL(sx);
-
 
2194
    y = REAL(sy);
-
 
2195
    xold = NA_REAL;
-
 
2196
    yold = NA_REAL;
-
 
2197
    for (i = 0; i < nx; i++) {
-
 
2198
	xx = x[i];
-
 
2199
	yy = y[i];
-
 
2200
	GConvert(&xx, &yy, USER, DEVICE, dd);
-
 
2201
	if ((R_FINITE(xx) && R_FINITE(yy)) &&
-
 
2202
	    !(R_FINITE(xold) && R_FINITE(yold)))
-
 
2203
	    start = i; /* first point of current segment */
-
 
2204
	else if ((R_FINITE(xold) && R_FINITE(yold)) &&
-
 
2205
		 !(R_FINITE(xx) && R_FINITE(yy))) {
-
 
2206
	    if (i-start > 1) {
-
 
2207
		drawPolygon(i-start, x+start, y+start,
-
 
2208
			    INTEGER(lty)[num%nlty],
-
 
2209
			    INTEGER(col)[num%ncol],
-
 
2210
			    INTEGER(border)[num%nborder], dd);
-
 
2211
		num++;
-
 
2212
	    }
-
 
2213
	}
-
 
2214
	else if ((R_FINITE(xold) && R_FINITE(yold)) && (i == nx-1)) { /* last */
-
 
2215
	    drawPolygon(nx-start, x+start, y+start,
-
 
2216
			INTEGER(lty)[num%nlty],
-
 
2217
			INTEGER(col)[num%ncol],
-
 
2218
			INTEGER(border)[num%nborder], dd);
-
 
2219
	    num++;
-
 
2220
	}
-
 
2221
	xold = xx;
-
 
2222
	yold = yy;
-
 
2223
    }
-
 
2224
 
-
 
2225
    GMode(0, dd);
-
 
2226
 
-
 
2227
    GRestorePars(dd);
-
 
2228
    UNPROTECT(3);
-
 
2229
    /* NOTE: only record operation if no "error"  */
-
 
2230
    if (GRecording(call, dd))
-
 
2231
	GErecordGraphicOperation(op, originalArgs, dd);
-
 
2232
    return R_NilValue;
-
 
2233
}
-
 
2234
 
-
 
2235
SEXP attribute_hidden do_text(SEXP call, SEXP op, SEXP args, SEXP env)
-
 
2236
{
-
 
2237
/* text(xy, labels, adj, pos, offset,
-
 
2238
 *	vfont, cex, col, font, ...)
-
 
2239
 */
-
 
2240
    SEXP sx, sy, sxy, txt, adj, pos, cex, col, rawcol, font, vfont;
-
 
2241
    int i, n, npos, ncex, ncol, nfont, ntxt;
-
 
2242
    double adjx = 0, adjy = 0, offset = 0.5;
-
 
2243
    double *x, *y;
-
 
2244
    double xx, yy;
-
 
2245
    Rboolean vectorFonts = FALSE;
-
 
2246
    SEXP string, originalArgs = args;
-
 
2247
    pGEDevDesc dd = GEcurrentDevice();
-
 
2248
 
-
 
2249
    GCheckState(dd);
-
 
2250
 
-
 
2251
    if (length(args) < 3) error(_("too few arguments"));
-
 
2252
 
-
 
2253
    PLOT_XY_DEALING("text");
-
 
2254
 
-
 
2255
    /* labels */
-
 
2256
    txt = CAR(args);
-
 
2257
    if (isSymbol(txt) || isLanguage(txt))
-
 
2258
	txt = coerceVector(txt, EXPRSXP);
-
 
2259
    else if (!isExpression(txt))
-
 
2260
	txt = coerceVector(txt, STRSXP);
-
 
2261
    PROTECT(txt);
-
 
2262
    if (length(txt) <= 0)
-
 
2263
	error(_("zero length 'labels'"));
-
 
2264
    args = CDR(args);
-
 
2265
 
-
 
2266
    PROTECT(adj = CAR(args));
-
 
2267
    if (isNull(adj) || (isNumeric(adj) && length(adj) == 0)) {
-
 
2268
	adjx = gpptr(dd)->adj;
-
 
2269
	adjy = NA_REAL;
-
 
2270
    }
-
 
2271
    else if (isReal(adj)) {
-
 
2272
	if (LENGTH(adj) == 1) {
-
 
2273
	    adjx = REAL(adj)[0];
-
 
2274
	    adjy = NA_REAL;
-
 
2275
	}
-
 
2276
	else {
-
 
2277
	    adjx = REAL(adj)[0];
-
 
2278
	    adjy = REAL(adj)[1];
-
 
2279
	}
-
 
2280
    }
-
 
2281
    else if (isInteger(adj)) {
-
 
2282
	if (LENGTH(adj) == 1) {
-
 
2283
	    adjx = INTEGER(adj)[0];
-
 
2284
	    adjy = NA_REAL;
-
 
2285
	}
-
 
2286
	else {
-
 
2287
	    adjx = INTEGER(adj)[0];
-
 
2288
	    adjy = INTEGER(adj)[1];
-
 
2289
	}
-
 
2290
    }
-
 
2291
    else error(_("invalid '%s' value"), "adj");
-
 
2292
    args = CDR(args);
-
 
2293
 
-
 
2294
    PROTECT(pos = coerceVector(CAR(args), INTSXP));
-
 
2295
    npos = length(pos);
-
 
2296
    for (i = 0; i < npos; i++)
-
 
2297
	if (INTEGER(pos)[i] < 1 || INTEGER(pos)[i] > 4)
-
 
2298
	    error(_("invalid '%s' value"), "pos");
-
 
2299
    args = CDR(args);
-
 
2300
 
-
 
2301
    offset = GConvertXUnits(asReal(CAR(args)), CHARS, INCHES, dd);
-
 
2302
    args = CDR(args);
-
 
2303
 
-
 
2304
    PROTECT(vfont = FixupVFont(CAR(args)));
-
 
2305
    args = CDR(args);
-
 
2306
 
-
 
2307
    PROTECT(cex = FixupCex(CAR(args), 1.0));
-
 
2308
    ncex = LENGTH(cex);
-
 
2309
    args = CDR(args);
-
 
2310
 
-
 
2311
    rawcol = CAR(args);
-
 
2312
    PROTECT(col = FixupCol(rawcol, R_TRANWHITE));
-
 
2313
    ncol = LENGTH(col);
-
 
2314
    args = CDR(args);
-
 
2315
 
-
 
2316
    PROTECT(font = FixupFont(CAR(args), NA_INTEGER));
-
 
2317
    nfont = LENGTH(font);
-
 
2318
    args = CDR(args);
-
 
2319
 
-
 
2320
    x = REAL(sx);
-
 
2321
    y = REAL(sy);
-
 
2322
    /* n = LENGTH(sx) = LENGTH(sy) */
-
 
2323
    ntxt = LENGTH(txt);
-
 
2324
 
-
 
2325
    GSavePars(dd);
-
 
2326
    ProcessInlinePars(args, dd);
-
 
2327
 
-
 
2328
    /* Done here so 'vfont' trumps inline 'family' */
-
 
2329
    if (!isNull(vfont) && !isExpression(txt)) {
-
 
2330
	strncpy(gpptr(dd)->family, "Her ", 201);
-
 
2331
	gpptr(dd)->family[3] = (char) INTEGER(vfont)[0];
-
 
2332
	vectorFonts = TRUE;
-
 
2333
    }
-
 
2334
 
-
 
2335
    GMode(1, dd);
-
 
2336
    if (n == 0 && ntxt > 0)
-
 
2337
	error(_("no coordinates were supplied"));
-
 
2338
    for (i = 0; i < imax2(n,ntxt); i++) {
-
 
2339
	xx = x[i % n];
-
 
2340
	yy = y[i % n];
-
 
2341
	GConvert(&xx, &yy, USER, INCHES, dd);
-
 
2342
	if (R_FINITE(xx) && R_FINITE(yy)) {
-
 
2343
	    if (ncol && !isNAcol(rawcol, i, ncol))
-
 
2344
		gpptr(dd)->col = INTEGER(col)[i % ncol];
-
 
2345
	    else
-
 
2346
		gpptr(dd)->col = dpptr(dd)->col;
-
 
2347
	    if (ncex && R_FINITE(REAL(cex)[i%ncex]))
-
 
2348
		gpptr(dd)->cex = gpptr(dd)->cexbase * REAL(cex)[i % ncex];
-
 
2349
	    else
-
 
2350
		gpptr(dd)->cex = gpptr(dd)->cexbase;
-
 
2351
 
-
 
2352
	    if (vectorFonts) gpptr(dd)->font = INTEGER(vfont)[1];
-
 
2353
	    else if (nfont && INTEGER(font)[i % nfont] != NA_INTEGER)
-
 
2354
		gpptr(dd)->font = INTEGER(font)[i % nfont];
-
 
2355
	    else
-
 
2356
		gpptr(dd)->font = dpptr(dd)->font;
-
 
2357
 
-
 
2358
	    if (npos > 0) {
-
 
2359
		switch(INTEGER(pos)[i % npos]) {
-
 
2360
		case 1:
-
 
2361
		    yy = yy - offset;
-
 
2362
		    adjx = 0.5;
-
 
2363
		    adjy = 1 - (0.5 - dd->dev->yCharOffset);
-
 
2364
		    break;
-
 
2365
		case 2:
-
 
2366
		    xx = xx - offset;
-
 
2367
		    adjx = 1;
-
 
2368
		    adjy = dd->dev->yCharOffset;
-
 
2369
		    break;
-
 
2370
		case 3:
-
 
2371
		    yy = yy + offset;
-
 
2372
		    adjx = 0.5;
-
 
2373
		    adjy = 0;
-
 
2374
		    break;
-
 
2375
		case 4:
-
 
2376
		    xx = xx + offset;
-
 
2377
		    adjx = 0;
-
 
2378
		    adjy = dd->dev->yCharOffset;
-
 
2379
		    break;
-
 
2380
		}
-
 
2381
	    }
-
 
2382
	    if (isExpression(txt)) {
-
 
2383
		GMathText(xx, yy, INCHES, VECTOR_ELT(txt, i % ntxt),
-
 
2384
			  adjx, adjy, gpptr(dd)->srt, dd);
-
 
2385
	    } else {
-
 
2386
		string = STRING_ELT(txt, i % ntxt);
-
 
2387
		if(string != NA_STRING)
-
 
2388
		    GText(xx, yy, INCHES, CHAR(string), getCharCE(string),
-
 
2389
			  adjx, adjy, gpptr(dd)->srt, dd);
-
 
2390
	    }
-
 
2391
	}
-
 
2392
    }
-
 
2393
    GMode(0, dd);
-
 
2394
 
-
 
2395
    GRestorePars(dd);
-
 
2396
    UNPROTECT(7);
-
 
2397
    /* NOTE: only record operation if no "error"  */
-
 
2398
    if (GRecording(call, dd))
-
 
2399
	GErecordGraphicOperation(op, originalArgs, dd);
-
 
2400
    return R_NilValue;
-
 
2401
}
-
 
2402
 
-
 
2403
static double ComputeAdjValue(double adj, int side, int las)
-
 
2404
{
-
 
2405
    if (!R_FINITE(adj)) {
-
 
2406
	switch(las) {
-
 
2407
	case 0:/* parallel to axis */
-
 
2408
	    adj = 0.5; break;
-
 
2409
	case 1:/* horizontal */
-
 
2410
	    switch(side) {
-
 
2411
	    case 1:
-
 
2412
	    case 3: adj = 0.5; break;
-
 
2413
	    case 2: adj = 1.0; break;
-
 
2414
	    case 4: adj = 0.0; break;
-
 
2415
	    }
-
 
2416
	    break;
-
 
2417
	case 2:/* perpendicular to axis */
-
 
2418
	    switch(side) {
-
 
2419
	    case 1:
-
 
2420
	    case 2: adj = 1.0; break;
-
 
2421
	    case 3:
-
 
2422
	    case 4: adj = 0.0; break;
-
 
2423
	    }
-
 
2424
	    break;
-
 
2425
	case 3:/* vertical */
-
 
2426
	    switch(side) {
-
 
2427
	    case 1: adj = 1.0; break;
-
 
2428
	    case 3: adj = 0.0; break;
-
 
2429
	    case 2:
-
 
2430
	    case 4: adj = 0.5; break;
-
 
2431
	    }
-
 
2432
	    break;
-
 
2433
	}
-
 
2434
    }
-
 
2435
    return adj;
-
 
2436
}
-
 
2437
 
-
 
2438
static double ComputeAtValueFromAdj(double adj, int side, int outer,
-
 
2439
				    pGEDevDesc dd)
-
 
2440
{
-
 
2441
    double at = 0;		/* -Wall */
-
 
2442
    switch(side % 2) {
-
 
2443
    case 0:
-
 
2444
	at  = outer ? adj : yNPCtoUsr(adj, dd);
-
 
2445
	break;
-
 
2446
    case 1:
-
 
2447
	at = outer ? adj : xNPCtoUsr(adj, dd);
-
 
2448
	break;
-
 
2449
    }
-
 
2450
    return at;
-
 
2451
}
-
 
2452
 
-
 
2453
static double ComputeAtValue(double at, double adj,
-
 
2454
			     int side, int las, int outer,
-
 
2455
			     pGEDevDesc dd)
-
 
2456
{
-
 
2457
    if (!R_FINITE(at)) {
-
 
2458
	/* If the text is parallel to the axis, use "adj" for "at"
-
 
2459
	 * Otherwise, centre the text
-
 
2460
	 */
-
 
2461
	switch(las) {
-
 
2462
	case 0:/* parallel to axis */
-
 
2463
	    at = ComputeAtValueFromAdj(adj, side, outer, dd);
-
 
2464
	    break;
-
 
2465
	case 1:/* horizontal */
-
 
2466
	    switch(side) {
-
 
2467
	    case 1:
-
 
2468
	    case 3:
-
 
2469
		at = ComputeAtValueFromAdj(adj, side, outer, dd);
-
 
2470
		break;
-
 
2471
	    case 2:
-
 
2472
	    case 4:
-
 
2473
		at = outer ? 0.5 : yNPCtoUsr(0.5, dd);
-
 
2474
		break;
-
 
2475
	    }
-
 
2476
	    break;
-
 
2477
	case 2:/* perpendicular to axis */
-
 
2478
	    switch(side) {
-
 
2479
	    case 1:
-
 
2480
	    case 3:
-
 
2481
		at = outer ? 0.5 : xNPCtoUsr(0.5, dd);
-
 
2482
		break;
-
 
2483
	    case 2:
-
 
2484
	    case 4:
-
 
2485
		at = outer ? 0.5 : yNPCtoUsr(0.5, dd);
-
 
2486
		break;
-
 
2487
	    }
-
 
2488
	    break;
-
 
2489
	case 3:/* vertical */
-
 
2490
	    switch(side) {
-
 
2491
	    case 1:
-
 
2492
	    case 3:
-
 
2493
		at = outer ? 0.5 : xNPCtoUsr(0.5, dd);
-
 
2494
		break;
-
 
2495
	    case 2:
-
 
2496
	    case 4:
-
 
2497
		at = ComputeAtValueFromAdj(adj, side, outer, dd);
-
 
2498
		break;
-
 
2499
	    }
-
 
2500
	    break;
-
 
2501
	}
-
 
2502
    }
-
 
2503
    return at;
-
 
2504
}
-
 
2505
 
-
 
2506
/* mtext(text,
-
 
2507
	 side = 3,
-
 
2508
	 line = 0,
-
 
2509
	 outer = TRUE,
-
 
2510
	 at = NA,
-
 
2511
	 adj = NA,
-
 
2512
	 padj = NA,
-
 
2513
	 cex = NA,
-
 
2514
	 col = NA,
-
 
2515
	 font = NA,
-
 
2516
	 ...) */
-
 
2517
 
-
 
2518
SEXP attribute_hidden do_mtext(SEXP call, SEXP op, SEXP args, SEXP env)
-
 
2519
{
-
 
2520
    SEXP text, side, line, outer, at, adj, padj, cex, col, font, string;
-
 
2521
    SEXP rawcol;
-
 
2522
    int ntext, nside, nline, nouter, nat, nadj, npadj, ncex, ncol, nfont;
-
 
2523
    Rboolean dirtyplot = FALSE, gpnewsave = FALSE, dpnewsave = FALSE;
-
 
2524
    int i, n, fontsave, colsave;
-
 
2525
    double cexsave;
-
 
2526
    SEXP originalArgs = args;
-
 
2527
    pGEDevDesc dd = GEcurrentDevice();
-
 
2528
 
-
 
2529
    GCheckState(dd);
-
 
2530
 
-
 
2531
    if (length(args) < 9)
-
 
2532
	error(_("too few arguments"));
-
 
2533
 
-
 
2534
    /* Arg1 : text= */
-
 
2535
    text = CAR(args);
-
 
2536
    if (isSymbol(text) || isLanguage(text))
-
 
2537
	text = coerceVector(text, EXPRSXP);
-
 
2538
    else if (!isExpression(text))
-
 
2539
	text = coerceVector(text, STRSXP);
-
 
2540
    PROTECT(text);
-
 
2541
    n = ntext = length(text);
-
 
2542
    if (ntext <= 0)
-
 
2543
	error(_("zero length 'text' specified"));
-
 
2544
    args = CDR(args);
-
 
2545
 
-
 
2546
    /* Arg2 : side= */
-
 
2547
    PROTECT(side = coerceVector(CAR(args), INTSXP));
-
 
2548
    nside = length(side);
-
 
2549
    if (nside <= 0) error(_("zero length 'side' specified"));
-
 
2550
    if (n < nside) n = nside;
-
 
2551
    args = CDR(args);
-
 
2552
 
-
 
2553
    /* Arg3 : line= */
-
 
2554
    PROTECT(line = coerceVector(CAR(args), REALSXP));
-
 
2555
    nline = length(line);
-
 
2556
    if (nline <= 0) error(_("zero length 'line' specified"));
-
 
2557
    if (n < nline) n = nline;
-
 
2558
    args = CDR(args);
-
 
2559
 
-
 
2560
    /* Arg4 : outer= */
-
 
2561
    /* outer == NA => outer <- 0 */
-
 
2562
    PROTECT(outer = coerceVector(CAR(args), INTSXP));
-
 
2563
    nouter = length(outer);
-
 
2564
    if (nouter <= 0) error(_("zero length 'outer' specified"));
-
 
2565
    if (n < nouter) n = nouter;
-
 
2566
    args = CDR(args);
-
 
2567
 
-
 
2568
    /* Arg5 : at= */
-
 
2569
    PROTECT(at = coerceVector(CAR(args), REALSXP));
-
 
2570
    nat = length(at);
-
 
2571
    if (nat <= 0) error(_("zero length 'at' specified"));
-
 
2572
    if (n < nat) n = nat;
-
 
2573
    args = CDR(args);
-
 
2574
 
-
 
2575
    /* Arg6 : adj= */
-
 
2576
    PROTECT(adj = coerceVector(CAR(args), REALSXP));
-
 
2577
    nadj = length(adj);
-
 
2578
    if (nadj <= 0) error(_("zero length 'adj' specified"));
-
 
2579
    if (n < nadj) n = nadj;
-
 
2580
    args = CDR(args);
-
 
2581
 
-
 
2582
    /* Arg7 : padj= */
-
 
2583
    PROTECT(padj = coerceVector(CAR(args), REALSXP));
-
 
2584
    npadj = length(padj);
-
 
2585
    if (npadj <= 0) error(_("zero length 'padj' specified"));
-
 
2586
    if (n < npadj) n = npadj;
-
 
2587
    args = CDR(args);
-
 
2588
 
-
 
2589
    /* Arg8 : cex */
-
 
2590
    PROTECT(cex = FixupCex(CAR(args), 1.0));
-
 
2591
    ncex = length(cex);
-
 
2592
    if (ncex <= 0) error(_("zero length 'cex' specified"));
-
 
2593
    if (n < ncex) n = ncex;
-
 
2594
    args = CDR(args);
-
 
2595
 
-
 
2596
    /* Arg9 : col */
-
 
2597
    rawcol = CAR(args);
-
 
2598
    PROTECT(col = FixupCol(rawcol, R_TRANWHITE));
-
 
2599
    ncol = length(col);
-
 
2600
    if (ncol <= 0) error(_("zero length 'col' specified"));
-
 
2601
    if (n < ncol) n = ncol;
-
 
2602
    args = CDR(args);
-
 
2603
 
-
 
2604
    /* Arg10 : font */
-
 
2605
    PROTECT(font = FixupFont(CAR(args), NA_INTEGER));
-
 
2606
    nfont = length(font);
-
 
2607
    if (nfont <= 0) error(_("zero length 'font' specified"));
-
 
2608
    if (n < nfont) n = nfont;
-
 
2609
    args = CDR(args);
-
 
2610
 
-
 
2611
    GSavePars(dd);
-
 
2612
    ProcessInlinePars(args, dd);
-
 
2613
 
-
 
2614
    /* If we only scribble in the outer margins, */
-
 
2615
    /* we don't want to mark the plot as dirty. */
-
 
2616
 
-
 
2617
    dirtyplot = FALSE;
-
 
2618
    gpnewsave = gpptr(dd)->new;
-
 
2619
    dpnewsave = dpptr(dd)->new;
-
 
2620
    cexsave = gpptr(dd)->cex;
-
 
2621
    fontsave = gpptr(dd)->font;
-
 
2622
    colsave = gpptr(dd)->col;
-
 
2623
 
-
 
2624
    /* override par("xpd") and force clipping to figure region
-
 
2625
       NOTE: don't override to _reduce_ clipping region */
-
 
2626
    if (gpptr(dd)->xpd < 1)
-
 
2627
	gpptr(dd)->xpd = 1;
-
 
2628
 
-
 
2629
    if (outer) {
-
 
2630
	gpnewsave = gpptr(dd)->new;
-
 
2631
	dpnewsave = dpptr(dd)->new;
-
 
2632
	/* override par("xpd") and force clipping to device region */
-
 
2633
	gpptr(dd)->xpd = 2;
-
 
2634
    }
-
 
2635
    GMode(1, dd);
-
 
2636
 
-
 
2637
    for (i = 0; i < n; i++) {
-
 
2638
	double atval = REAL(at)[i%nat];
-
 
2639
	double adjval = REAL(adj)[i%nadj];
-
 
2640
	double padjval = REAL(padj)[i%npadj];
-
 
2641
	double cexval = REAL(cex)[i%ncex];
-
 
2642
	double lineval = REAL(line)[i%nline];
-
 
2643
	int outerval = INTEGER(outer)[i%nouter];
-
 
2644
	int sideval = INTEGER(side)[i%nside];
-
 
2645
	int fontval = INTEGER(font)[i%nfont];
-
 
2646
	int colval = INTEGER(col)[i%ncol];
-
 
2647
 
-
 
2648
	if (outerval == NA_INTEGER) outerval = 0;
-
 
2649
	/* Note : we ignore any shrinking produced */
-
 
2650
	/* by mfrow / mfcol specs here.	 I.e. don't */
-
 
2651
	/* gpptr(dd)->cexbase. */
-
 
2652
	if (R_FINITE(cexval)) gpptr(dd)->cex = cexval;
-
 
2653
	else cexval = cexsave;
-
 
2654
	gpptr(dd)->font = (fontval == NA_INTEGER) ? fontsave : fontval;
-
 
2655
	if (isNAcol(rawcol, i, ncol))
-
 
2656
	    gpptr(dd)->col = colsave;
-
 
2657
	else
-
 
2658
	    gpptr(dd)->col = colval;
-
 
2659
	gpptr(dd)->adj = ComputeAdjValue(adjval, sideval, gpptr(dd)->las);
-
 
2660
	padjval = ComputePAdjValue(padjval, sideval, gpptr(dd)->las);
-
 
2661
	atval = ComputeAtValue(atval, gpptr(dd)->adj, sideval, gpptr(dd)->las,
-
 
2662
			       outerval, dd);
-
 
2663
 
-
 
2664
	if (isExpression(text))
-
 
2665
	    GMMathText(VECTOR_ELT(text, i%ntext),
-
 
2666
		       sideval, lineval, outerval, atval, gpptr(dd)->las,
-
 
2667
		       padjval, dd);
-
 
2668
	else {
-
 
2669
	    string = STRING_ELT(text, i%ntext);
-
 
2670
	    if(string != NA_STRING)
-
 
2671
		GMtext(CHAR(string), getCharCE(string), sideval, lineval,
-
 
2672
		       outerval, atval, gpptr(dd)->las, padjval, dd);
-
 
2673
	}
-
 
2674
 
-
 
2675
	if (outerval == 0) dirtyplot = TRUE;
-
 
2676
    }
-
 
2677
    GMode(0, dd);
-
 
2678
 
-
 
2679
    GRestorePars(dd);
-
 
2680
    if (!dirtyplot) {
-
 
2681
	gpptr(dd)->new = gpnewsave;
-
 
2682
	dpptr(dd)->new = dpnewsave;
-
 
2683
    }
-
 
2684
    UNPROTECT(10);
-
 
2685
 
-
 
2686
    /* NOTE: only record operation if no "error"  */
-
 
2687
    if (GRecording(call, dd))
-
 
2688
	GErecordGraphicOperation(op, originalArgs, dd);
-
 
2689
    return R_NilValue;
-
 
2690
}/* do_mtext */
-
 
2691
 
-
 
2692
 
-
 
2693
SEXP attribute_hidden do_title(SEXP call, SEXP op, SEXP args, SEXP env)
-
 
2694
{
-
 
2695
/* Annotation for plots :
-
 
2696
 
-
 
2697
   title(main, sub, xlab, ylab,
-
 
2698
	 line, outer,
-
 
2699
	 ...) */
-
 
2700
 
-
 
2701
    SEXP Main, xlab, ylab, sub, string;
-
 
2702
    double adj, adjy, cex, offset, line, hpos, vpos;
-
 
2703
    int i, n, font, outer, where;
-
 
2704
    rcolor col;
-
 
2705
    SEXP originalArgs = args;
-
 
2706
    pGEDevDesc dd = GEcurrentDevice();
-
 
2707
 
-
 
2708
    GCheckState(dd);
-
 
2709
 
-
 
2710
    if (length(args) < 6) error(_("too few arguments"));
-
 
2711
 
-
 
2712
    Main = sub = xlab = ylab = R_NilValue;
-
 
2713
 
-
 
2714
    if (CAR(args) != R_NilValue && LENGTH(CAR(args)) > 0)
-
 
2715
	Main = CAR(args);
-
 
2716
    args = CDR(args);
-
 
2717
 
-
 
2718
    if (CAR(args) != R_NilValue && LENGTH(CAR(args)) > 0)
-
 
2719
	sub = CAR(args);
-
 
2720
    args = CDR(args);
-
 
2721
 
-
 
2722
    if (CAR(args) != R_NilValue && LENGTH(CAR(args)) > 0)
-
 
2723
	xlab = CAR(args);
-
 
2724
    args = CDR(args);
-
 
2725
 
-
 
2726
    if (CAR(args) != R_NilValue && LENGTH(CAR(args)) > 0)
-
 
2727
	ylab = CAR(args);
-
 
2728
    args = CDR(args);
-
 
2729
 
-
 
2730
    line = asReal(CAR(args));
-
 
2731
    args = CDR(args);
-
 
2732
 
-
 
2733
    outer = asLogical(CAR(args));
-
 
2734
    if (outer == NA_LOGICAL) outer = 0;
-
 
2735
    args = CDR(args);
-
 
2736
 
-
 
2737
    GSavePars(dd);
-
 
2738
    ProcessInlinePars(args, dd);
-
 
2739
 
-
 
2740
    /* override par("xpd") and force clipping to figure region
-
 
2741
       NOTE: don't override to _reduce_ clipping region */
-
 
2742
    if (gpptr(dd)->xpd < 1)
-
 
2743
	gpptr(dd)->xpd = 1;
-
 
2744
    if (outer)
-
 
2745
	gpptr(dd)->xpd = 2;
-
 
2746
    adj = gpptr(dd)->adj;
-
 
2747
 
-
 
2748
    GMode(1, dd);
-
 
2749
    if (Main != R_NilValue) {
-
 
2750
	cex = gpptr(dd)->cexmain;
-
 
2751
	col = gpptr(dd)->colmain;
-
 
2752
	font = gpptr(dd)->fontmain;
-
 
2753
	/* GetTextArg may coerce, so protect the result */
-
 
2754
	GetTextArg(call, Main, &Main, &col, &cex, &font);
-
 
2755
	PROTECT(Main);
-
 
2756
	gpptr(dd)->col = col;
-
 
2757
	gpptr(dd)->cex = gpptr(dd)->cexbase * cex;
-
 
2758
	gpptr(dd)->font = font;
-
 
2759
	if (outer) {
-
 
2760
	    if (R_FINITE(line)) {
-
 
2761
		vpos = line;
-
 
2762
		adjy = 0;
-
 
2763
	    }
-
 
2764
	    else {
-
 
2765
		vpos = 0.5 * gpptr(dd)->oma[2];
-
 
2766
		adjy = 0.5;
-
 
2767
	    }
-
 
2768
	    hpos = adj;
-
 
2769
	    where = OMA3;
-
 
2770
	}
-
 
2771
	else {
-
 
2772
	    if (R_FINITE(line)) {
-
 
2773
		vpos = line;
-
 
2774
		adjy = 0;
-
 
2775
	    }
-
 
2776
	    else {
-
 
2777
		vpos = 0.5 * gpptr(dd)->mar[2];
-
 
2778
		adjy = 0.5;
-
 
2779
	    }
-
 
2780
	    hpos = GConvertX(adj, NPC, USER, dd);
-
 
2781
	    where = MAR3;
-
 
2782
	}
-
 
2783
	if (isExpression(Main)) {
-
 
2784
	    GMathText(hpos, vpos, where, VECTOR_ELT(Main, 0),
-
 
2785
		      adj, 0.5, 0.0, dd);
-
 
2786
	}
-
 
2787
	else {
-
 
2788
	  n = length(Main);
-
 
2789
	  offset = 0.5 * (n - 1) + vpos;
-
 
2790
	  for (i = 0; i < n; i++) {
-
 
2791
		string = STRING_ELT(Main, i);
-
 
2792
		if(string != NA_STRING)
-
 
2793
		    GText(hpos, offset - i, where, CHAR(string), getCharCE(string),
-
 
2794
			  adj, adjy, 0.0, dd);
-
 
2795
	  }
-
 
2796
	}
-
 
2797
	UNPROTECT(1);
-
 
2798
    }
-
 
2799
    if (sub != R_NilValue) {
-
 
2800
	cex = gpptr(dd)->cexsub;
-
 
2801
	col = gpptr(dd)->colsub;
-
 
2802
	font = gpptr(dd)->fontsub;
-
 
2803
	/* GetTextArg may coerce, so protect the result */
-
 
2804
	GetTextArg(call, sub, &sub, &col, &cex, &font);
-
 
2805
	PROTECT(sub);
-
 
2806
	gpptr(dd)->col = col;
-
 
2807
	gpptr(dd)->cex = gpptr(dd)->cexbase * cex;
-
 
2808
	gpptr(dd)->font = font;
-
 
2809
	if (R_FINITE(line))
-
 
2810
	    vpos = line;
-
 
2811
	else
-
 
2812
	    vpos = gpptr(dd)->mgp[0] + 1;
-
 
2813
	if (outer) {
-
 
2814
	    hpos = adj;
-
 
2815
	    where = 1;
-
 
2816
	}
-
 
2817
	else {
-
 
2818
	    hpos = GConvertX(adj, NPC, USER, dd);
-
 
2819
	    where = 0;
-
 
2820
	}
-
 
2821
	if (isExpression(sub))
-
 
2822
	    GMMathText(VECTOR_ELT(sub, 0), 1, vpos, where,
-
 
2823
		       hpos, 0, 0.0, dd);
-
 
2824
	else {
-
 
2825
	    n = length(sub);
-
 
2826
	    for (i = 0; i < n; i++) {
-
 
2827
		string = STRING_ELT(sub, i);
-
 
2828
		if(string != NA_STRING)
-
 
2829
		    GMtext(CHAR(string), getCharCE(string), 1, vpos, where,
-
 
2830
			   hpos, 0, 0.0, dd);
-
 
2831
	    }
-
 
2832
	}
-
 
2833
	UNPROTECT(1);
-
 
2834
    }
-
 
2835
    if (xlab != R_NilValue) {
-
 
2836
	cex = gpptr(dd)->cexlab;
-
 
2837
	col = gpptr(dd)->collab;
-
 
2838
	font = gpptr(dd)->fontlab;
-
 
2839
	/* GetTextArg may coerce, so protect the result */
-
 
2840
	GetTextArg(call, xlab, &xlab, &col, &cex, &font);
-
 
2841
	PROTECT(xlab);
-
 
2842
	gpptr(dd)->cex = gpptr(dd)->cexbase * cex;
-
 
2843
	gpptr(dd)->col = col;
-
 
2844
	gpptr(dd)->font = font;
-
 
2845
	if (R_FINITE(line))
-
 
2846
	    vpos = line;
-
 
2847
	else
-
 
2848
	    vpos = gpptr(dd)->mgp[0];
-
 
2849
	if (outer) {
-
 
2850
	    hpos = adj;
-
 
2851
	    where = 1;
-
 
2852
	}
-
 
2853
	else {
-
 
2854
	    hpos = GConvertX(adj, NPC, USER, dd);
-
 
2855
	    where = 0;
-
 
2856
	}
-
 
2857
	if (isExpression(xlab))
-
 
2858
	    GMMathText(VECTOR_ELT(xlab, 0), 1, vpos, where,
-
 
2859
		       hpos, 0, 0.0, dd);
-
 
2860
	else {
-
 
2861
	    n = length(xlab);
-
 
2862
	    for (i = 0; i < n; i++) {
-
 
2863
		string = STRING_ELT(xlab, i);
-
 
2864
		if(string != NA_STRING)
-
 
2865
		    GMtext(CHAR(string), getCharCE(string), 1, vpos + i,
-
 
2866
			   where, hpos, 0, 0.0, dd);
-
 
2867
	    }
-
 
2868
	}
-
 
2869
	UNPROTECT(1);
-
 
2870
    }
-
 
2871
    if (ylab != R_NilValue) {
-
 
2872
	cex = gpptr(dd)->cexlab;
-
 
2873
	col = gpptr(dd)->collab;
-
 
2874
	font = gpptr(dd)->fontlab;
-
 
2875
	/* GetTextArg may coerce, so protect the result */
-
 
2876
	GetTextArg(call, ylab, &ylab, &col, &cex, &font);
-
 
2877
	PROTECT(ylab);
-
 
2878
	gpptr(dd)->cex = gpptr(dd)->cexbase * cex;
-
 
2879
	gpptr(dd)->col = col;
-
 
2880
	gpptr(dd)->font = font;
-
 
2881
	if (R_FINITE(line))
-
 
2882
	    vpos = line;
-
 
2883
	else
-
 
2884
	    vpos = gpptr(dd)->mgp[0];
-
 
2885
	if (outer) {
-
 
2886
	    hpos = adj;
-
 
2887
	    where = 1;
-
 
2888
	}
-
 
2889
	else {
-
 
2890
	    hpos = GConvertY(adj, NPC, USER, dd);
-
 
2891
	    where = 0;
-
 
2892
	}
-
 
2893
	if (isExpression(ylab))
-
 
2894
	    GMMathText(VECTOR_ELT(ylab, 0), 2, vpos, where,
-
 
2895
		       hpos, 0, 0.0, dd);
-
 
2896
	else {
-
 
2897
	    n = length(ylab);
-
 
2898
	    for (i = 0; i < n; i++) {
-
 
2899
		string = STRING_ELT(ylab, i);
-
 
2900
		if(string != NA_STRING)
-
 
2901
		    GMtext(CHAR(string), getCharCE(string), 2, vpos - i,
-
 
2902
			   where, hpos, 0, 0.0, dd);
-
 
2903
	    }
-
 
2904
	}
-
 
2905
	UNPROTECT(1);
-
 
2906
    }
-
 
2907
    GMode(0, dd);
-
 
2908
    GRestorePars(dd);
-
 
2909
    /* NOTE: only record operation if no "error"  */
-
 
2910
    if (GRecording(call, dd))
-
 
2911
	GErecordGraphicOperation(op, originalArgs, dd);
-
 
2912
    return R_NilValue;
-
 
2913
}/* do_title */
-
 
2914
 
-
 
2915
 
-
 
2916
/*  abline(a, b, h, v, col, lty, lwd, ...)
-
 
2917
    draw lines in intercept/slope form.	 */
-
 
2918
 
-
 
2919
SEXP attribute_hidden do_abline(SEXP call, SEXP op, SEXP args, SEXP env)
-
 
2920
{
-
 
2921
    SEXP a, b, h, v, untf, col, lty, lwd;
-
 
2922
    int i, ncol, nlines, nlty, nlwd, lstart, lstop;
-
 
2923
    double aa, bb, x[2], y[2]={0.,0.} /* -Wall */;
-
 
2924
    SEXP originalArgs = args;
-
 
2925
    pGEDevDesc dd = GEcurrentDevice();
-
 
2926
 
-
 
2927
    GCheckState(dd);
-
 
2928
 
-
 
2929
    if (length(args) < 5) error(_("too few arguments"));
-
 
2930
 
-
 
2931
    if ((a = CAR(args)) != R_NilValue)
-
 
2932
	SETCAR(args, a = coerceVector(a, REALSXP));
-
 
2933
    args = CDR(args);
-
 
2934
 
-
 
2935
    if ((b = CAR(args)) != R_NilValue)
-
 
2936
	SETCAR(args, b = coerceVector(b, REALSXP));
-
 
2937
    args = CDR(args);
-
 
2938
 
-
 
2939
    if ((h = CAR(args)) != R_NilValue)
-
 
2940
	SETCAR(args, h = coerceVector(h, REALSXP));
-
 
2941
    args = CDR(args);
-
 
2942
 
-
 
2943
    if ((v = CAR(args)) != R_NilValue)
-
 
2944
	SETCAR(args, v = coerceVector(v, REALSXP));
-
 
2945
    args = CDR(args);
-
 
2946
 
-
 
2947
    if ((untf = CAR(args)) != R_NilValue)
-
 
2948
	SETCAR(args, untf = coerceVector(untf, LGLSXP));
-
 
2949
    args = CDR(args);
-
 
2950
 
-
 
2951
 
-
 
2952
    PROTECT(col = FixupCol(CAR(args), R_TRANWHITE));	args = CDR(args);
-
 
2953
    ncol = LENGTH(col);
-
 
2954
 
-
 
2955
    PROTECT(lty = FixupLty(CAR(args), gpptr(dd)->lty)); args = CDR(args);
-
 
2956
    nlty = length(lty);
-
 
2957
 
-
 
2958
    PROTECT(lwd = FixupLwd(CAR(args), gpptr(dd)->lwd)); args = CDR(args);
-
 
2959
    nlwd = length(lwd);
-
 
2960
 
-
 
2961
    GSavePars(dd);
-
 
2962
 
-
 
2963
    ProcessInlinePars(args, dd);
-
 
2964
 
-
 
2965
    nlines = 0;
-
 
2966
 
-
 
2967
    if (a != R_NilValue) {  /* case where a ans b are supplied */
-
 
2968
	if (b == R_NilValue) {
-
 
2969
	    if (LENGTH(a) != 2)
-
 
2970
		error(_("invalid a=, b= specification"));
-
 
2971
	    aa = REAL(a)[0];
-
 
2972
	    bb = REAL(a)[1];
-
 
2973
	}
-
 
2974
	else {
-
 
2975
	    aa = asReal(a);
-
 
2976
	    bb = asReal(b);
-
 
2977
	}
-
 
2978
	if (!R_FINITE(aa) || !R_FINITE(bb))
-
 
2979
	    error(_("'a' and 'b' must be finite"));
-
 
2980
	gpptr(dd)->col = INTEGER(col)[0];
-
 
2981
	gpptr(dd)->lwd = REAL(lwd)[0];
-
 
2982
	if (nlty && INTEGER(lty)[0] != NA_INTEGER)
-
 
2983
	    gpptr(dd)->lty = INTEGER(lty)[0];
-
 
2984
	else
-
 
2985
	    gpptr(dd)->lty = dpptr(dd)->lty;
-
 
2986
	GMode(1, dd);
-
 
2987
 
-
 
2988
	/* FIXME?
-
 
2989
	 * Seems like the logic here is just draw from xmin to xmax
-
 
2990
	 * and you're guaranteed to draw at least from ymin to ymax
-
 
2991
	 * This MAY cause a problem at some stage when the line being
-
 
2992
	 * drawn is VERY steep -- and the problem is worse now that
-
 
2993
	 * abline will potentially draw to the extents of the device
-
 
2994
	 * (when xpd = NA).  NOTE that R's internal clipping protects the
-
 
2995
	 * device drivers from stupidly large numbers, BUT there is
-
 
2996
	 * still a risk that we could produce a number which is too
-
 
2997
	 * big for the computer's brain.
-
 
2998
	 * Paul.
-
 
2999
	 *
-
 
3000
	 * The problem is worse -- you could get NaN, which at least the
-
 
3001
	 * X11 device coerces to -2^31 <TSL>
-
 
3002
	 */
-
 
3003
	getxlimits(x, dd);/* -> (x[0], x[1]) */
-
 
3004
	if (R_FINITE(gpptr(dd)->lwd)) {
-
 
3005
	    Rboolean xlog = gpptr(dd)->xlog, ylog = gpptr(dd)->ylog;
-
 
3006
	    if (LOGICAL(untf)[0] && (xlog || ylog)) {
-
 
3007
#define NS 100
-
 
3008
		/* Plot curve, linear on original scales */
-
 
3009
		double xx[NS+1], yy[NS+1];
-
 
3010
		if(xlog) {
-
 
3011
		    /* x_i should be equidistant in log-scale, i.e., equi-ratio */
-
 
3012
		    double x_f = x[1] / DBL_MAX;
-
 
3013
		    xx[0] = x[0] = fmax2(x[0], 1.01 *x_f); /* > 0 */
-
 
3014
		    x_f = pow(x[1]/x[0], 1./NS);
-
 
3015
		    for (i = 1; i < NS; i++)
-
 
3016
			xx[i] = xx[i-1] * x_f;
-
 
3017
		} else {
-
 
3018
		    double xstep = (x[1] - x[0])/NS;
-
 
3019
		    for (i = 0; i < NS; i++)
-
 
3020
			xx[i] = x[0] + i*xstep;
-
 
3021
		}
-
 
3022
		xx[NS] = x[1];
-
 
3023
		for (i = 0; i <= NS; i++)
-
 
3024
		    yy[i] = aa + xx[i] * bb;
-
 
3025
 
-
 
3026
		/* now get rid of -ve values */
-
 
3027
		lstart = 0;lstop = NS;
-
 
3028
		if (xlog) {
-
 
3029
		    for(; xx[lstart] <= 0 && lstart < NS+1; lstart++);
-
 
3030
		    for(; xx[lstop] <= 0 && lstop > 0; lstop--);
-
 
3031
		}
-
 
3032
		if (ylog) {
-
 
3033
		    for(; yy[lstart] <= 0 && lstart < NS+1; lstart++);
-
 
3034
		    for(; yy[lstop] <= 0 && lstop > 0; lstop--);
-
 
3035
		}
-
 
3036
 
-
 
3037
		GPolyline(lstop-lstart+1, xx+lstart, yy+lstart, USER, dd);
-
 
3038
#undef NS
-
 
3039
	    } else { /* non-log plots, possibly with log scales */
-
 
3040
 
-
 
3041
		y[0] = aa + (xlog ? log10(x[0]) : x[0]) * bb;
-
 
3042
		y[1] = aa + (xlog ? log10(x[1]) : x[1]) * bb;
-
 
3043
		if (ylog) {
-
 
3044
		    y[0] = pow(10., y[0]);
-
 
3045
		    y[1] = pow(10., y[1]);
-
 
3046
		}
-
 
3047
 
-
 
3048
		GLine(x[0], y[0], x[1], y[1], USER, dd);
-
 
3049
	    }
-
 
3050
	}
-
 
3051
	GMode(0, dd);
-
 
3052
	nlines++;
-
 
3053
    }
-
 
3054
    if (h != R_NilValue) { /* horizontal liee */
-
 
3055
	GMode(1, dd);
-
 
3056
	for (i = 0; i < LENGTH(h); i++) {
-
 
3057
	    gpptr(dd)->col = INTEGER(col)[nlines % ncol];
-
 
3058
	    if (nlty && INTEGER(lty)[nlines % nlty] != NA_INTEGER)
-
 
3059
		gpptr(dd)->lty = INTEGER(lty)[nlines % nlty];
-
 
3060
	    else
-
 
3061
		gpptr(dd)->lty = dpptr(dd)->lty;
-
 
3062
	    gpptr(dd)->lwd = REAL(lwd)[nlines % nlwd];
-
 
3063
	    aa = REAL(h)[i];
-
 
3064
	    if (R_FINITE(aa) && R_FINITE(gpptr(dd)->lwd)) {
-
 
3065
		getxlimits(x, dd);
-
 
3066
		y[0] = aa;
-
 
3067
		y[1] = aa;
-
 
3068
		GLine(x[0], y[0], x[1], y[1], USER, dd);
-
 
3069
	    }
-
 
3070
	    nlines++;
-
 
3071
	}
-
 
3072
	GMode(0, dd);
-
 
3073
    }
-
 
3074
    if (v != R_NilValue) { /* vertical line */
-
 
3075
	GMode(1, dd);
-
 
3076
	for (i = 0; i < LENGTH(v); i++) {
-
 
3077
	    gpptr(dd)->col = INTEGER(col)[nlines % ncol];
-
 
3078
	    if (nlty && INTEGER(lty)[nlines % nlty] != NA_INTEGER)
-
 
3079
		gpptr(dd)->lty = INTEGER(lty)[nlines % nlty];
-
 
3080
	    else
-
 
3081
		gpptr(dd)->lty = dpptr(dd)->lty;
-
 
3082
	    gpptr(dd)->lwd = REAL(lwd)[nlines % nlwd];
-
 
3083
	    aa = REAL(v)[i];
-
 
3084
	    if (R_FINITE(aa) && R_FINITE(gpptr(dd)->lwd)) {
-
 
3085
		getylimits(y, dd);
-
 
3086
		x[0] = aa;
-
 
3087
		x[1] = aa;
-
 
3088
		GLine(x[0], y[0], x[1], y[1], USER, dd);
-
 
3089
	    }
-
 
3090
	    nlines++;
-
 
3091
	}
-
 
3092
	GMode(0, dd);
-
 
3093
    }
-
 
3094
    UNPROTECT(3);
-
 
3095
    GRestorePars(dd);
-
 
3096
    /* NOTE: only record operation if no "error"  */
-
 
3097
    if (GRecording(call, dd))
397
    dd = GNewPlot(GRecording(call, dd));
3098
	GErecordGraphicOperation(op, originalArgs, dd);
-
 
3099
    return R_NilValue;
-
 
3100
} /* do_abline */
-
 
3101
 
398
 
-
 
399
    dpptr(dd)->xlog = gpptr(dd)->xlog = FALSE;
-
 
400
    dpptr(dd)->ylog = gpptr(dd)->ylog = FALSE;
3102
 
401
 
3103
SEXP attribute_hidden do_box(SEXP call, SEXP op, SEXP args, SEXP env)
-
 
3104
{
-
 
3105
/*     box(which="plot", lty="solid", ...)
-
 
3106
       --- which is coded, 1 = plot, 2 = figure, 3 = inner, 4 = outer.
-
 
3107
*/
-
 
3108
    int which, col;
402
    GScale(0.0, 1.0, 1, dd);
3109
    SEXP colsxp, fgsxp;
403
    GScale(0.0, 1.0, 2, dd);
3110
    SEXP originalArgs = args;
404
    GMapWin2Fig(dd);
3111
    pGEDevDesc dd = GEcurrentDevice();
405
    GSetState(1, dd);
3112
 
406
 
3113
    GCheckState(dd);
-
 
3114
    GSavePars(dd);
-
 
3115
    which = asInteger(CAR(args)); args = CDR(args);
-
 
3116
    if (which < 1 || which > 4)
-
 
3117
	error(_("invalid '%s' argument"), "which");
-
 
3118
    /*
-
 
3119
     * If specified non-NA col then use that, else ...
-
 
3120
     *
-
 
3121
     * if specified non-NA fg then use that, else ...
-
 
3122
     *
-
 
3123
     * else use par("col")
-
 
3124
     */
-
 
3125
    col= gpptr(dd)->col;
-
 
3126
    ProcessInlinePars(args, dd);
-
 
3127
    colsxp = getInlinePar(args, "col");
-
 
3128
    if (isNAcol(colsxp, 0, 1)) {
-
 
3129
	fgsxp = getInlinePar(args, "fg");
-
 
3130
	if (isNAcol(fgsxp, 0, 1))
-
 
3131
	    gpptr(dd)->col = col;
-
 
3132
	else
-
 
3133
	    gpptr(dd)->col = gpptr(dd)->fg;
-
 
3134
    }
-
 
3135
    /* override par("xpd") and force clipping to device region */
-
 
3136
    gpptr(dd)->xpd = 2;
-
 
3137
    GMode(1, dd);
-
 
3138
    GBox(which, dd);
-
 
3139
    GMode(0, dd);
-
 
3140
    GRestorePars(dd);
-
 
3141
    /* NOTE: only record operation if no "error"  */
-
 
3142
    if (GRecording(call, dd))
407
    if (GRecording(call, dd))
3143
	GErecordGraphicOperation(op, originalArgs, dd);
408
	GErecordGraphicOperation(op, args, dd);
3144
    return R_NilValue;
409
    return R_NilValue;
3145
}
410
}
3146
 
411
 
3147
static void drawPointsLines(double xp, double yp, double xold, double yold,
412
static void drawPointsLines(double xp, double yp, double xold, double yold,
3148
			    char type, int first, pGEDevDesc dd)
413
			    char type, int first, pGEDevDesc dd)
Line 3151... Line 416...
3151
	GSymbol(xp, yp, DEVICE, gpptr(dd)->pch, dd);
416
	GSymbol(xp, yp, DEVICE, gpptr(dd)->pch, dd);
3152
    if ((type == 'l' || type == 'o') && !first)
417
    if ((type == 'l' || type == 'o') && !first)
3153
	GLine(xold, yold, xp, yp, DEVICE, dd);
418
	GLine(xold, yold, xp, yp, DEVICE, dd);
3154
}
419
}
3155
 
420
 
-
 
421
 
3156
SEXP attribute_hidden do_locator(SEXP call, SEXP op, SEXP args, SEXP env)
422
SEXP attribute_hidden do_locator(SEXP call, SEXP op, SEXP args, SEXP env)
3157
{
423
{
3158
    SEXP x, y, nobs, ans, saveans, stype = R_NilValue;
424
    SEXP x, y, nobs, ans, saveans, stype = R_NilValue;
3159
    int i, n;
425
    int i, n;
3160
    char type = 'p';
426
    char type = 'p';
Line 3460... Line 726...
3460
 
726
 
3461
	R_Visible = TRUE;
727
	R_Visible = TRUE;
3462
	return ans;
728
	return ans;
3463
    }
729
    }
3464
}
730
}
3465
 
-
 
3466
/* strheight(str, units, cex, font, vfont, ...)  ||  strwidth() */
-
 
3467
#define DO_STR_DIM(KIND)						\
-
 
3468
{									\
-
 
3469
    SEXP ans, str, ch, font, vfont;					\
-
 
3470
    int i, n, units;							\
-
 
3471
    double cex, cexsave;						\
-
 
3472
    pGEDevDesc dd = GEcurrentDevice();					\
-
 
3473
									\
-
 
3474
    if (length(args) < 5) error(_("too few arguments"));		\
-
 
3475
    /* GCheckState(dd); */						\
-
 
3476
									\
-
 
3477
    str = CAR(args);							\
-
 
3478
    if (isSymbol(str) || isLanguage(str))				\
-
 
3479
	str = coerceVector(str, EXPRSXP);				\
-
 
3480
    else if (!isExpression(str))					\
-
 
3481
	str = coerceVector(str, STRSXP);				\
-
 
3482
    PROTECT(str);							\
-
 
3483
    args = CDR(args);							\
-
 
3484
									\
-
 
3485
    if ((units = asInteger(CAR(args))) == NA_INTEGER || units < 0)	\
-
 
3486
	error(_("invalid units"));					\
-
 
3487
    if(units == 1)  GCheckState(dd); \
-
 
3488
    args = CDR(args);							\
-
 
3489
									\
-
 
3490
    if (isNull(CAR(args)))						\
-
 
3491
	cex = gpptr(dd)->cex;						\
-
 
3492
    else if (!R_FINITE((cex = asReal(CAR(args)))) || cex <= 0.0)	\
-
 
3493
	error(_("invalid '%s' value"), "cex");				\
-
 
3494
    args = CDR(args);							\
-
 
3495
    PROTECT(font = FixupFont(CAR(args), NA_INTEGER)); args = CDR(args); \
-
 
3496
    PROTECT(vfont = FixupVFont(CAR(args))); args = CDR(args);		\
-
 
3497
    GSavePars(dd);							\
-
 
3498
    ProcessInlinePars(args, dd);					\
-
 
3499
									\
-
 
3500
    /* 'vfont' trumps inline 'family' */				\
-
 
3501
    if (!isNull(vfont) && !isExpression(str)) {				\
-
 
3502
	strncpy(gpptr(dd)->family, "Her ", 201);			\
-
 
3503
	gpptr(dd)->family[3] = (char)INTEGER(vfont)[0];			\
-
 
3504
	gpptr(dd)->font = INTEGER(vfont)[1];				\
-
 
3505
    } else gpptr(dd)->font = INTEGER(font)[0];				\
-
 
3506
									\
-
 
3507
    n = LENGTH(str);							\
-
 
3508
    PROTECT(ans = allocVector(REALSXP, n));				\
-
 
3509
    cexsave = gpptr(dd)->cex;						\
-
 
3510
    gpptr(dd)->cex = cex * gpptr(dd)->cexbase;				\
-
 
3511
    for (i = 0; i < n; i++)						\
-
 
3512
	if (isExpression(str))						\
-
 
3513
	    REAL(ans)[i] = GExpression ## KIND(VECTOR_ELT(str, i),	\
-
 
3514
					     GMapUnits(units), dd);	\
-
 
3515
	else {								\
-
 
3516
	    ch = STRING_ELT(str, i);					\
-
 
3517
	    REAL(ans)[i] = (ch == NA_STRING) ? 0.0 :			\
-
 
3518
		GStr ## KIND(CHAR(ch), getCharCE(ch), GMapUnits(units), dd);		\
-
 
3519
	}								\
-
 
3520
    gpptr(dd)->cex = cexsave;						\
-
 
3521
    GRestorePars(dd);							\
-
 
3522
    UNPROTECT(4);							\
-
 
3523
    return ans;								\
-
 
3524
}
-
 
3525
 
-
 
3526
SEXP attribute_hidden do_strheight(SEXP call, SEXP op, SEXP args, SEXP env)
-
 
3527
DO_STR_DIM(Height)
-
 
3528
 
-
 
3529
SEXP attribute_hidden do_strwidth (SEXP call, SEXP op, SEXP args, SEXP env)
-
 
3530
DO_STR_DIM(Width)
-
 
3531
 
-
 
3532
#undef DO_STR_DIM
-
 
3533
 
-
 
3534
 
-
 
3535
static int *dnd_lptr;
-
 
3536
static int *dnd_rptr;
-
 
3537
static double *dnd_hght;
-
 
3538
static double *dnd_xpos;
-
 
3539
static double dnd_hang;
-
 
3540
static double dnd_offset;
-
 
3541
 
-
 
3542
static void drawdend(int node, double *x, double *y, SEXP dnd_llabels,
-
 
3543
		     pGEDevDesc dd)
-
 
3544
{
-
 
3545
/* Recursive function for 'hclust' dendrogram drawing:
-
 
3546
 * Do left + Do right + Do myself
-
 
3547
 * "do" : 1) label leafs (if there are) and __
-
 
3548
 *        2) find coordinates to draw the  | |
-
 
3549
 *        3) return (*x,*y) of "my anchor"
-
 
3550
 */
-
 
3551
    double xl, xr, yl, yr;
-
 
3552
    double xx[4], yy[4];
-
 
3553
    int k;
-
 
3554
 
-
 
3555
    *y = dnd_hght[node-1];
-
 
3556
    /* left part  */
-
 
3557
    k = dnd_lptr[node-1];
-
 
3558
    if (k > 0) drawdend(k, &xl, &yl, dnd_llabels, dd);
-
 
3559
    else {
-
 
3560
	xl = dnd_xpos[-k-1];
-
 
3561
	yl = (dnd_hang >= 0) ? *y - dnd_hang : 0;
-
 
3562
	if(STRING_ELT(dnd_llabels, -k-1) != NA_STRING)
-
 
3563
	    GText(xl, yl-dnd_offset, USER,
-
 
3564
		  CHAR(STRING_ELT(dnd_llabels, -k-1)),
-
 
3565
		  getCharCE(STRING_ELT(dnd_llabels, -k-1)),
-
 
3566
		  1.0, 0.3, 90.0, dd);
-
 
3567
    }
-
 
3568
    /* right part */
-
 
3569
    k = dnd_rptr[node-1];
-
 
3570
    if (k > 0) drawdend(k, &xr, &yr, dnd_llabels, dd);
-
 
3571
    else {
-
 
3572
	xr = dnd_xpos[-k-1];
-
 
3573
	yr = (dnd_hang >= 0) ? *y - dnd_hang : 0;
-
 
3574
	if(STRING_ELT(dnd_llabels, -k-1) != NA_STRING)
-
 
3575
	    GText(xr, yr-dnd_offset, USER,
-
 
3576
		  CHAR(STRING_ELT(dnd_llabels, -k-1)),
-
 
3577
		  getCharCE(STRING_ELT(dnd_llabels, -k-1)),
-
 
3578
		  1.0, 0.3, 90.0, dd);
-
 
3579
    }
-
 
3580
    xx[0] = xl; yy[0] = yl;
-
 
3581
    xx[1] = xl; yy[1] = *y;
-
 
3582
    xx[2] = xr; yy[2] = *y;
-
 
3583
    xx[3] = xr; yy[3] = yr;
-
 
3584
    GPolyline(4, xx, yy, USER, dd);
-
 
3585
    *x = 0.5 * (xl + xr);
-
 
3586
}
-
 
3587
 
-
 
3588
 
-
 
3589
SEXP attribute_hidden do_dend(SEXP call, SEXP op, SEXP args, SEXP env)
-
 
3590
{
-
 
3591
    double x, y;
-
 
3592
    int n;
-
 
3593
 
-
 
3594
    SEXP originalArgs, dnd_llabels, xpos;
-
 
3595
    pGEDevDesc dd;
-
 
3596
 
-
 
3597
    dd = GEcurrentDevice();
-
 
3598
    GCheckState(dd);
-
 
3599
 
-
 
3600
    originalArgs = args;
-
 
3601
    if (length(args) < 6)
-
 
3602
	error(_("too few arguments"));
-
 
3603
 
-
 
3604
    /* n */
-
 
3605
    n = asInteger(CAR(args));
-
 
3606
    if (n == NA_INTEGER || n < 2)
-
 
3607
	goto badargs;
-
 
3608
    args = CDR(args);
-
 
3609
 
-
 
3610
    /* merge */
-
 
3611
    if (TYPEOF(CAR(args)) != INTSXP || length(CAR(args)) != 2*n)
-
 
3612
	goto badargs;
-
 
3613
    dnd_lptr = &(INTEGER(CAR(args))[0]);
-
 
3614
    dnd_rptr = &(INTEGER(CAR(args))[n]);
-
 
3615
    args = CDR(args);
-
 
3616
 
-
 
3617
    /* height */
-
 
3618
    if (TYPEOF(CAR(args)) != REALSXP || length(CAR(args)) != n)
-
 
3619
	goto badargs;
-
 
3620
    dnd_hght = REAL(CAR(args));
-
 
3621
    args = CDR(args);
-
 
3622
 
-
 
3623
    /* ord = order(x$order) */
-
 
3624
    if (length(CAR(args)) != n+1)
-
 
3625
	goto badargs;
-
 
3626
    PROTECT(xpos = coerceVector(CAR(args), REALSXP));
-
 
3627
    dnd_xpos = REAL(xpos);
-
 
3628
    args = CDR(args);
-
 
3629
 
-
 
3630
    /* hang */
-
 
3631
    dnd_hang = asReal(CAR(args));
-
 
3632
    if (!R_FINITE(dnd_hang))
-
 
3633
	goto badargs;
-
 
3634
    dnd_hang = dnd_hang * (dnd_hght[n-1] - dnd_hght[0]);
-
 
3635
    args = CDR(args);
-
 
3636
 
-
 
3637
    /* labels */
-
 
3638
    if (TYPEOF(CAR(args)) != STRSXP || length(CAR(args)) != n+1)
-
 
3639
	goto badargs;
-
 
3640
    dnd_llabels = CAR(args);
-
 
3641
    args = CDR(args);
-
 
3642
 
-
 
3643
    GSavePars(dd);
-
 
3644
    ProcessInlinePars(args, dd);
-
 
3645
    gpptr(dd)->cex = gpptr(dd)->cexbase * gpptr(dd)->cex;
-
 
3646
    dnd_offset = GConvertYUnits(GStrWidth("m", CE_ANY, INCHES, dd), INCHES,
-
 
3647
				USER, dd);
-
 
3648
 
-
 
3649
    /* override par("xpd") and force clipping to figure region
-
 
3650
       NOTE: don't override to _reduce_ clipping region */
-
 
3651
    if (gpptr(dd)->xpd < 1)
-
 
3652
	gpptr(dd)->xpd = 1;
-
 
3653
 
-
 
3654
    GMode(1, dd);
-
 
3655
    drawdend(n, &x, &y, dnd_llabels, dd);
-
 
3656
    GMode(0, dd);
-
 
3657
    GRestorePars(dd);
-
 
3658
    /* NOTE: only record operation if no "error"  */
-
 
3659
    if (GRecording(call, dd))
-
 
3660
	GErecordGraphicOperation(op, originalArgs, dd);
-
 
3661
    UNPROTECT(1);
-
 
3662
    return R_NilValue;
-
 
3663
 
-
 
3664
  badargs:
-
 
3665
    error(_("invalid dendrogram input"));
-
 
3666
    return R_NilValue;/* never used; to keep -Wall happy */
-
 
3667
}
-
 
3668
 
-
 
3669
SEXP attribute_hidden do_dendwindow(SEXP call, SEXP op, SEXP args, SEXP env)
-
 
3670
{
-
 
3671
    int i, imax, n;
-
 
3672
    double pin, *ll, tmp, yval, *y, ymin, ymax, yrange, m;
-
 
3673
    SEXP originalArgs, merge, height, llabels, str;
-
 
3674
    const void *vmax;
-
 
3675
    pGEDevDesc dd;
-
 
3676
 
-
 
3677
    dd = GEcurrentDevice();
-
 
3678
    GCheckState(dd);
-
 
3679
    originalArgs = args;
-
 
3680
    if (length(args) < 5)
-
 
3681
	error(_("too few arguments"));
-
 
3682
    n = asInteger(CAR(args));
-
 
3683
    if (n == NA_INTEGER || n < 2)
-
 
3684
	goto badargs;
-
 
3685
    args = CDR(args);
-
 
3686
    if (TYPEOF(CAR(args)) != INTSXP || length(CAR(args)) != 2 * n)
-
 
3687
	goto badargs;
-
 
3688
    merge = CAR(args);
-
 
3689
 
-
 
3690
    args = CDR(args);
-
 
3691
    if (TYPEOF(CAR(args)) != REALSXP || length(CAR(args)) != n)
-
 
3692
	goto badargs;
-
 
3693
    height = CAR(args);
-
 
3694
 
-
 
3695
    args = CDR(args);
-
 
3696
    dnd_hang = asReal(CAR(args));
-
 
3697
    if (!R_FINITE(dnd_hang))
-
 
3698
	goto badargs;
-
 
3699
 
-
 
3700
    args = CDR(args);
-
 
3701
    if (TYPEOF(CAR(args)) != STRSXP || length(CAR(args)) != n + 1)
-
 
3702
	goto badargs;
-
 
3703
    llabels = CAR(args);
-
 
3704
 
-
 
3705
    args = CDR(args);
-
 
3706
    GSavePars(dd);
-
 
3707
    ProcessInlinePars(args, dd);
-
 
3708
    gpptr(dd)->cex = gpptr(dd)->cexbase * gpptr(dd)->cex;
-
 
3709
    dnd_offset = GStrWidth("m", CE_ANY, INCHES, dd);
-
 
3710
    vmax = vmaxget();
-
 
3711
    /* n is the number of merges, so the points are labelled 1 ... n+1 */
-
 
3712
    y =  (double*)R_alloc(n+1, sizeof(double));
-
 
3713
    ll = (double*)R_alloc(n+1, sizeof(double));
-
 
3714
    dnd_lptr = &(INTEGER(merge)[0]);
-
 
3715
    dnd_rptr = &(INTEGER(merge)[n]);
-
 
3716
    ymax = ymin = REAL(height)[0];
-
 
3717
    for (i = 1; i < n; i++) {
-
 
3718
	m = REAL(height)[i];
-
 
3719
	if (m > ymax)
-
 
3720
	    ymax = m;
-
 
3721
	else if (m < ymin)
-
 
3722
	    ymin = m;
-
 
3723
    }
-
 
3724
    pin = gpptr(dd)->pin[1];
-
 
3725
    for (i = 0; i <= n; i++) {
-
 
3726
	str = STRING_ELT(llabels, i);
-
 
3727
	ll[i] = (str == NA_STRING) ? 0.0 :
-
 
3728
	    GStrWidth(CHAR(str), getCharCE(str), INCHES, dd) + dnd_offset;
-
 
3729
    }
-
 
3730
 
-
 
3731
    imax = -1; yval = -DBL_MAX;
-
 
3732
    if (dnd_hang >= 0) {
-
 
3733
	ymin = ymax - (1 + dnd_hang) * (ymax - ymin);
-
 
3734
	yrange = ymax - ymin;
-
 
3735
	/* determine leaf heights */
-
 
3736
	for (i = 0; i < n; i++) {
-
 
3737
	    if (dnd_lptr[i] < 0)
-
 
3738
		y[-dnd_lptr[i] - 1] = REAL(height)[i];
-
 
3739
	    if (dnd_rptr[i] < 0)
-
 
3740
		y[-dnd_rptr[i] - 1] = REAL(height)[i];
-
 
3741
	}
-
 
3742
	/* determine the most extreme label depth */
-
 
3743
	/* assuming that we are using the full plot */
-
 
3744
	/* window for the tree itself */
-
 
3745
	for (i = 0; i <= n; i++) {
-
 
3746
	    tmp = ((ymax - y[i]) / yrange) * pin + ll[i];
-
 
3747
	    if (tmp > yval) {
-
 
3748
		yval = tmp;
-
 
3749
		imax = i;
-
 
3750
	    }
-
 
3751
	}
-
 
3752
    }
-
 
3753
    else {
-
 
3754
	yrange = ymax;
-
 
3755
	for (i = 0; i <= n; i++) {
-
 
3756
	    tmp = pin + ll[i];
-
 
3757
	    if (tmp > yval) {
-
 
3758
		yval = tmp;
-
 
3759
		imax = i;
-
 
3760
	    }
-
 
3761
	}
-
 
3762
    }
-
 
3763
    /* now determine how much to scale */
-
 
3764
    ymin = ymax - (pin/(pin - ll[imax])) * yrange;
-
 
3765
    GScale(1.0, n+1.0, 1 /* x */, dd);
-
 
3766
    GScale(ymin, ymax, 2 /* y */, dd);
-
 
3767
    GMapWin2Fig(dd);
-
 
3768
    GRestorePars(dd);
-
 
3769
    /* NOTE: only record operation if no "error"  */
-
 
3770
    if (GRecording(call, dd))
-
 
3771
	GErecordGraphicOperation(op, originalArgs, dd);
-
 
3772
    vmaxset(vmax);
-
 
3773
    return R_NilValue;
-
 
3774
  badargs:
-
 
3775
    error(_("invalid dendrogram input"));
-
 
3776
    return R_NilValue;/* never used; to keep -Wall happy */
-
 
3777
}
-
 
3778
 
-
 
3779
 
-
 
3780
SEXP attribute_hidden do_erase(SEXP call, SEXP op, SEXP args, SEXP env)
-
 
3781
{
-
 
3782
    SEXP col;
-
 
3783
    pGEDevDesc dd = GEcurrentDevice();
-
 
3784
    checkArity(op, args);
-
 
3785
    PROTECT(col = FixupCol(CAR(args), R_TRANWHITE));
-
 
3786
    GSavePars(dd);
-
 
3787
    GMode(1, dd);
-
 
3788
    GRect(0.0, 0.0, 1.0, 1.0, NDC, INTEGER(col)[0], R_TRANWHITE, dd);
-
 
3789
    GMode(0, dd);
-
 
3790
    GRestorePars(dd);
-
 
3791
    UNPROTECT(1);
-
 
3792
    return R_NilValue;
-
 
3793
}
-
 
3794
 
-
 
3795
/* symbols(..) in ../library/base/R/symbols.R  : */
-
 
3796
 
-
 
3797
/* utility just computing range() */
-
 
3798
static Rboolean SymbolRange(double *x, int n, double *xmax, double *xmin)
-
 
3799
{
-
 
3800
    int i;
-
 
3801
    *xmax = -DBL_MAX;
-
 
3802
    *xmin =  DBL_MAX;
-
 
3803
    for(i = 0; i < n; i++)
-
 
3804
	if (R_FINITE(x[i])) {
-
 
3805
	    if (*xmax < x[i]) *xmax = x[i];
-
 
3806
	    if (*xmin > x[i]) *xmin = x[i];
-
 
3807
	}
-
 
3808
    return(*xmax >= *xmin && *xmin >= 0);
-
 
3809
}
-
 
3810
 
-
 
3811
static void CheckSymbolPar(SEXP call, SEXP p, int *nr, int *nc)
-
 
3812
{
-
 
3813
    SEXP dim = getAttrib(p, R_DimSymbol);
-
 
3814
    switch(length(dim)) {
-
 
3815
    case 0:
-
 
3816
	*nr = LENGTH(p);
-
 
3817
	*nc = 1;
-
 
3818
	break;
-
 
3819
    case 1:
-
 
3820
	*nr = INTEGER(dim)[0];
-
 
3821
	*nc = 1;
-
 
3822
	break;
-
 
3823
    case 2:
-
 
3824
	*nr = INTEGER(dim)[0];
-
 
3825
	*nc = INTEGER(dim)[1];
-
 
3826
	break;
-
 
3827
    default:
-
 
3828
	*nr = 0;
-
 
3829
	*nc = 0;
-
 
3830
    }
-
 
3831
    if (*nr == 0 || *nc == 0)
-
 
3832
	error(_("invalid symbol parameter vector"));
-
 
3833
}
-
 
3834
 
-
 
3835
/* Internal  symbols(x, y, type, data, inches, bg, fg, ...) */
-
 
3836
SEXP attribute_hidden do_symbols(SEXP call, SEXP op, SEXP args, SEXP env)
-
 
3837
{
-
 
3838
    SEXP x, y, p, fg, bg;
-
 
3839
    int i, j, nr, nc, nbg, nfg, type;
-
 
3840
    double pmax, pmin, inches, rx, ry;
-
 
3841
    double xx, yy, p0, p1, p2, p3, p4;
-
 
3842
    double *pp, *xp, *yp;
-
 
3843
    const void *vmax;
-
 
3844
 
-
 
3845
    SEXP originalArgs = args;
-
 
3846
    pGEDevDesc dd = GEcurrentDevice();
-
 
3847
    GCheckState(dd);
-
 
3848
 
-
 
3849
    if (length(args) < 7)
-
 
3850
	error(_("too few arguments"));
-
 
3851
 
-
 
3852
    PROTECT(x = coerceVector(CAR(args), REALSXP)); args = CDR(args);
-
 
3853
    PROTECT(y = coerceVector(CAR(args), REALSXP)); args = CDR(args);
-
 
3854
    if (!isNumeric(x) || !isNumeric(y) || length(x) <= 0 || LENGTH(x) <= 0)
-
 
3855
	error(_("invalid symbol coordinates"));
-
 
3856
 
-
 
3857
    type = asInteger(CAR(args)); args = CDR(args);
-
 
3858
 
-
 
3859
    /* data: */
-
 
3860
    p = PROTECT(coerceVector(CAR(args), REALSXP)); args = CDR(args);
-
 
3861
    CheckSymbolPar(call, p, &nr, &nc);
-
 
3862
    if (LENGTH(x) != nr || LENGTH(y) != nr)
-
 
3863
	error(_("x/y/parameter length mismatch"));
-
 
3864
 
-
 
3865
    inches = asReal(CAR(args)); args = CDR(args);
-
 
3866
    if (!R_FINITE(inches) || inches < 0)
-
 
3867
	inches = 0;
-
 
3868
 
-
 
3869
    PROTECT(bg = FixupCol(CAR(args), R_TRANWHITE)); args = CDR(args);
-
 
3870
    nbg = LENGTH(bg);
-
 
3871
 
-
 
3872
    PROTECT(fg = FixupCol(CAR(args), R_TRANWHITE)); args = CDR(args);
-
 
3873
    nfg = LENGTH(fg);
-
 
3874
 
-
 
3875
    GSavePars(dd);
-
 
3876
    ProcessInlinePars(args, dd);
-
 
3877
 
-
 
3878
    GMode(1, dd);
-
 
3879
    switch (type) {
-
 
3880
    case 1: /* circles */
-
 
3881
	if (nc != 1)
-
 
3882
	    error(_("invalid circles data"));
-
 
3883
	if (!SymbolRange(REAL(p), nr, &pmax, &pmin))
-
 
3884
	    error(_("invalid symbol parameter"));
-
 
3885
	for (i = 0; i < nr; i++) {
-
 
3886
	    if (R_FINITE(REAL(x)[i]) && R_FINITE(REAL(y)[i]) &&
-
 
3887
		R_FINITE(REAL(p)[i])) {
-
 
3888
		rx = REAL(p)[i];
-
 
3889
		/* For GCircle the radius is always in INCHES */
-
 
3890
		if (inches > 0)
-
 
3891
		    rx *= inches / pmax;
-
 
3892
		else
-
 
3893
		    rx = GConvertXUnits(rx, USER, INCHES, dd);
-
 
3894
		/* GCircle sets radius zero to one pixel, but does
-
 
3895
		   not change very small non-zero radii */
-
 
3896
		GCircle(REAL(x)[i], REAL(y)[i],	USER, rx,
-
 
3897
			INTEGER(bg)[i%nbg], INTEGER(fg)[i%nfg],	dd);
-
 
3898
	    }
-
 
3899
	}
-
 
3900
	break;
-
 
3901
    case 2: /* squares */
-
 
3902
	if(nc != 1)
-
 
3903
	    error(_("invalid squares data"));
-
 
3904
	if(!SymbolRange(REAL(p), nr, &pmax, &pmin))
-
 
3905
	    error(_("invalid symbol parameter"));
-
 
3906
	for (i = 0; i < nr; i++) {
-
 
3907
	    if (R_FINITE(REAL(x)[i]) && R_FINITE(REAL(y)[i]) &&
-
 
3908
		R_FINITE(REAL(p)[i])) {
-
 
3909
		p0 = REAL(p)[i];
-
 
3910
		xx = REAL(x)[i];
-
 
3911
		yy = REAL(y)[i];
-
 
3912
		GConvert(&xx, &yy, USER, DEVICE, dd);
-
 
3913
		if (inches > 0) {
-
 
3914
		    p0 *= inches / pmax;
-
 
3915
		    rx = GConvertXUnits(0.5 * p0, INCHES, DEVICE, dd);
-
 
3916
		}
-
 
3917
		else {
-
 
3918
		    rx = GConvertXUnits(0.5 * p0, USER, DEVICE, dd);
-
 
3919
		}
-
 
3920
		/* FIXME: should this skip 0-sized symbols? */
-
 
3921
		GRect(xx - rx, yy - rx, xx + rx, yy + rx, DEVICE,
-
 
3922
		      INTEGER(bg)[i%nbg], INTEGER(fg)[i%nfg], dd);
-
 
3923
	    }
-
 
3924
	}
-
 
3925
	break;
-
 
3926
    case 3: /* rectangles */
-
 
3927
	if (nc != 2)
-
 
3928
	    error(_("invalid rectangles data (need 2 columns)"));
-
 
3929
	if (!SymbolRange(REAL(p), 2 * nr, &pmax, &pmin))
-
 
3930
	    error(_("invalid symbol parameter"));
-
 
3931
	for (i = 0; i < nr; i++) {
-
 
3932
	    if (R_FINITE(REAL(x)[i]) && R_FINITE(REAL(y)[i]) &&
-
 
3933
		R_FINITE(REAL(p)[i]) && R_FINITE(REAL(p)[i+nr])) {
-
 
3934
		xx = REAL(x)[i];
-
 
3935
		yy = REAL(y)[i];
-
 
3936
		GConvert(&xx, &yy, USER, DEVICE, dd);
-
 
3937
		p0 = REAL(p)[i];
-
 
3938
		p1 = REAL(p)[i+nr];
-
 
3939
		if (inches > 0) {
-
 
3940
		    p0 *= inches / pmax;
-
 
3941
		    p1 *= inches / pmax;
-
 
3942
		    rx = GConvertXUnits(0.5 * p0, INCHES, DEVICE, dd);
-
 
3943
		    ry = GConvertYUnits(0.5 * p1, INCHES, DEVICE, dd);
-
 
3944
		}
-
 
3945
		else {
-
 
3946
		    rx = GConvertXUnits(0.5 * p0, USER, DEVICE, dd);
-
 
3947
		    ry = GConvertYUnits(0.5 * p1, USER, DEVICE, dd);
-
 
3948
		}
-
 
3949
		/* FIXME: should this skip 0-sized symbols? */
-
 
3950
		GRect(xx - rx, yy - ry, xx + rx, yy + ry, DEVICE,
-
 
3951
		      INTEGER(bg)[i%nbg], INTEGER(fg)[i%nfg], dd);
-
 
3952
 
-
 
3953
	    }
-
 
3954
	}
-
 
3955
	break;
-
 
3956
    case 4: /* stars */
-
 
3957
	if (nc < 3)
-
 
3958
	    error(_("invalid stars data"));
-
 
3959
	if (!SymbolRange(REAL(p), nc * nr, &pmax, &pmin))
-
 
3960
	    error(_("invalid symbol parameter"));
-
 
3961
	vmax = vmaxget();
-
 
3962
	pp = (double*)R_alloc(nc, sizeof(double));
-
 
3963
	xp = (double*)R_alloc(nc, sizeof(double));
-
 
3964
	yp = (double*)R_alloc(nc, sizeof(double));
-
 
3965
	p1 = 2.0 * M_PI / nc;
-
 
3966
	for (i = 0; i < nr; i++) {
-
 
3967
	    xx = REAL(x)[i];
-
 
3968
	    yy = REAL(y)[i];
-
 
3969
	    if (R_FINITE(xx) && R_FINITE(yy)) {
-
 
3970
		GConvert(&xx, &yy, USER, NDC, dd);
-
 
3971
		if (inches > 0) {
-
 
3972
		    for(j = 0; j < nc; j++) {
-
 
3973
			p0 = REAL(p)[i + j * nr];
-
 
3974
			if (!R_FINITE(p0)) p0 = 0;
-
 
3975
			pp[j] = (p0 / pmax) * inches;
-
 
3976
		    }
-
 
3977
		}
-
 
3978
		else {
-
 
3979
		    for(j = 0; j < nc; j++) {
-
 
3980
			p0 = REAL(p)[i + j * nr];
-
 
3981
			if (!R_FINITE(p0)) p0 = 0;
-
 
3982
			pp[j] =	 GConvertXUnits(p0, USER, INCHES, dd);
-
 
3983
		    }
-
 
3984
		}
-
 
3985
		/* FIXME: should this skip 0-sized symbols? */
-
 
3986
		for(j = 0; j < nc; j++) {
-
 
3987
		    xp[j] = GConvertXUnits(pp[j] * cos(j * p1),
-
 
3988
					   INCHES, NDC, dd) + xx;
-
 
3989
		    yp[j] = GConvertYUnits(pp[j] * sin(j * p1),
-
 
3990
					   INCHES, NDC, dd) + yy;
-
 
3991
		}
-
 
3992
		GPolygon(nc, xp, yp, NDC,
-
 
3993
			 INTEGER(bg)[i%nbg], INTEGER(fg)[i%nfg], dd);
-
 
3994
	    }
-
 
3995
	}
-
 
3996
	vmaxset(vmax);
-
 
3997
	break;
-
 
3998
    case 5: /* thermometers */
-
 
3999
	if (nc != 3 && nc != 4)
-
 
4000
	    error(_("invalid thermometers data (need 3 or 4 columns)"));
-
 
4001
	SymbolRange(REAL(p)+2*nr/* <-- pointer arith*/, nr, &pmax, &pmin);
-
 
4002
	if (pmax < pmin)
-
 
4003
	    error(_("invalid thermometers[,%s]"),
-
 
4004
		      (nc == 4)? "3:4" : "3");
-
 
4005
	if (pmin < 0. || pmax > 1.) /* S-PLUS has an error here */
-
 
4006
	    warning(_("thermometers[,%s] not in [0,1] -- may look funny"),
-
 
4007
		    (nc == 4)? "3:4" : "3");
-
 
4008
	if (!SymbolRange(REAL(p), 2 * nr, &pmax, &pmin))
-
 
4009
	    error(_("invalid thermometers[,1:2]"));
-
 
4010
	for (i = 0; i < nr; i++) {
-
 
4011
	    xx = REAL(x)[i];
-
 
4012
	    yy = REAL(y)[i];
-
 
4013
	    if (R_FINITE(xx) && R_FINITE(yy)) {
-
 
4014
		p0 = REAL(p)[i];
-
 
4015
		p1 = REAL(p)[i + nr];
-
 
4016
		p2 = REAL(p)[i + 2 * nr];
-
 
4017
		p3 = (nc == 4)? REAL(p)[i + 3 * nr] : 0.;
-
 
4018
		if (R_FINITE(p0) && R_FINITE(p1) &&
-
 
4019
		    R_FINITE(p2) && R_FINITE(p3)) {
-
 
4020
		    if (p2 < 0) p2 = 0; else if (p2 > 1) p2 = 1;
-
 
4021
		    if (p3 < 0) p3 = 0; else if (p3 > 1) p3 = 1;
-
 
4022
		    GConvert(&xx, &yy, USER, NDC, dd);
-
 
4023
		    if (inches > 0) {
-
 
4024
			p0 *= inches / pmax;
-
 
4025
			p1 *= inches / pmax;
-
 
4026
			rx = GConvertXUnits(0.5 * p0, INCHES, NDC, dd);
-
 
4027
			ry = GConvertYUnits(0.5 * p1, INCHES, NDC, dd);
-
 
4028
		    }
-
 
4029
		    else {
-
 
4030
			rx = GConvertXUnits(0.5 * p0, USER, NDC, dd);
-
 
4031
			ry = GConvertYUnits(0.5 * p1, USER, NDC, dd);
-
 
4032
		    }
-
 
4033
		    GRect(xx - rx, yy - ry, xx + rx, yy + ry, NDC,
-
 
4034
			  INTEGER(bg)[i%nbg], INTEGER(fg)[i%nfg], dd);
-
 
4035
		    GRect(xx - rx,  yy - (1 - 2 * p2) * ry,
-
 
4036
			  xx + rx,  yy - (1 - 2 * p3) * ry,
-
 
4037
			  NDC,
-
 
4038
			  INTEGER(fg)[i%nfg], INTEGER(fg)[i%nfg], dd);
-
 
4039
		    GLine(xx - rx, yy, xx - 1.5 * rx, yy, NDC, dd);
-
 
4040
		    GLine(xx + rx, yy, xx + 1.5 * rx, yy, NDC, dd);
-
 
4041
 
-
 
4042
		}
-
 
4043
	    }
-
 
4044
	}
-
 
4045
	break;
-
 
4046
    case 6: /* boxplots (wid, hei, loWhsk, upWhsk, medProp) */
-
 
4047
	if (nc != 5)
-
 
4048
	    error(_("invalid boxplots data (need 5 columns)"));
-
 
4049
	pmax = -DBL_MAX;
-
 
4050
	pmin =	DBL_MAX;
-
 
4051
	for(i = 0; i < nr; i++) {
-
 
4052
	    p4 = REAL(p)[i + 4 * nr];	/* median proport. in [0,1] */
-
 
4053
	    if (pmax < p4) pmax = p4;
-
 
4054
	    if (pmin > p4) pmin = p4;
-
 
4055
	}
-
 
4056
	if (pmin < 0. || pmax > 1.) /* S-PLUS has an error here */
-
 
4057
	    warning(_("boxplots[,5] outside [0,1] -- may look funny"));
-
 
4058
	if (!SymbolRange(REAL(p), 4 * nr, &pmax, &pmin))
-
 
4059
	    error(_("invalid boxplots[, 1:4]"));
-
 
4060
	for (i = 0; i < nr; i++) {
-
 
4061
	    xx = REAL(x)[i];
-
 
4062
	    yy = REAL(y)[i];
-
 
4063
	    if (R_FINITE(xx) && R_FINITE(yy)) {
-
 
4064
		p0 = REAL(p)[i];	/* width */
-
 
4065
		p1 = REAL(p)[i + nr];	/* height */
-
 
4066
		p2 = REAL(p)[i + 2 * nr];/* lower whisker */
-
 
4067
		p3 = REAL(p)[i + 3 * nr];/* upper whisker */
-
 
4068
		p4 = REAL(p)[i + 4 * nr];/* median proport. in [0,1] */
-
 
4069
		if (R_FINITE(p0) && R_FINITE(p1) &&
-
 
4070
		    R_FINITE(p2) && R_FINITE(p3) && R_FINITE(p4)) {
-
 
4071
		    GConvert(&xx, &yy, USER, NDC, dd);
-
 
4072
		    if (inches > 0) {
-
 
4073
			p0 *= inches / pmax;
-
 
4074
			p1 *= inches / pmax;
-
 
4075
			p2 *= inches / pmax;
-
 
4076
			p3 *= inches / pmax;
-
 
4077
			p0 = GConvertXUnits(p0, INCHES, NDC, dd);
-
 
4078
			p1 = GConvertYUnits(p1, INCHES, NDC, dd);
-
 
4079
			p2 = GConvertYUnits(p2, INCHES, NDC, dd);
-
 
4080
			p3 = GConvertYUnits(p3, INCHES, NDC, dd);
-
 
4081
		    }
-
 
4082
		    else {
-
 
4083
			p0 = GConvertXUnits(p0, USER, NDC, dd);
-
 
4084
			p1 = GConvertYUnits(p1, USER, NDC, dd);
-
 
4085
			p2 = GConvertYUnits(p2, USER, NDC, dd);
-
 
4086
			p3 = GConvertYUnits(p3, USER, NDC, dd);
-
 
4087
		    }
-
 
4088
		    rx = 0.5 * p0;
-
 
4089
		    ry = 0.5 * p1;
-
 
4090
		    p4 = (1 - p4) * (yy - ry) + p4 * (yy + ry);
-
 
4091
		    /* Box */
-
 
4092
		    GRect(xx - rx, yy - ry, xx + rx, yy + ry, NDC,
-
 
4093
			  INTEGER(bg)[i%nbg], INTEGER(fg)[i%nfg], dd);
-
 
4094
		    /* Median */
-
 
4095
		    GLine(xx - rx, p4, xx + rx, p4, NDC, dd);
-
 
4096
		    /* Lower Whisker */
-
 
4097
		    GLine(xx, yy - ry, xx, yy - ry - p2, NDC, dd);
-
 
4098
		    /* Upper Whisker */
-
 
4099
		    GLine(xx, yy + ry, xx, yy + ry + p3, NDC, dd);
-
 
4100
		}
-
 
4101
	    }
-
 
4102
	}
-
 
4103
	break;
-
 
4104
    default:
-
 
4105
	error(_("invalid symbol type"));
-
 
4106
    }
-
 
4107
    GMode(0, dd);
-
 
4108
    GRestorePars(dd);
-
 
4109
    if (GRecording(call, dd))
-
 
4110
	GErecordGraphicOperation(op, originalArgs, dd);
-
 
4111
    UNPROTECT(5);
-
 
4112
    return R_NilValue;
-
 
4113
}
-
 
4114
 
-
 
4115
SEXP attribute_hidden do_xspline(SEXP call, SEXP op, SEXP args, SEXP env)
-
 
4116
{
-
 
4117
    SEXP sx, sy, ss, col, border, res, ans = R_NilValue;
-
 
4118
    int i, nx;
-
 
4119
    int ncol, nborder;
-
 
4120
    double *x, *y;
-
 
4121
    Rboolean open, repEnds, draw;
-
 
4122
    double *xx;
-
 
4123
    double *yy;
-
 
4124
    const void *vmaxsave;
-
 
4125
    R_GE_gcontext gc;
-
 
4126
 
-
 
4127
    SEXP originalArgs = args;
-
 
4128
    pGEDevDesc dd = GEcurrentDevice();
-
 
4129
 
-
 
4130
    GCheckState(dd);
-
 
4131
 
-
 
4132
    if (length(args) < 6) error(_("too few arguments"));
-
 
4133
    /* (x,y) is checked in R via xy.coords() ; no need here : */
-
 
4134
    sx = SETCAR(args, coerceVector(CAR(args), REALSXP));  args = CDR(args);
-
 
4135
    sy = SETCAR(args, coerceVector(CAR(args), REALSXP));  args = CDR(args);
-
 
4136
    nx = LENGTH(sx);
-
 
4137
    ss = SETCAR(args, coerceVector(CAR(args), REALSXP));  args = CDR(args);
-
 
4138
    open = asLogical(CAR(args)); args = CDR(args);
-
 
4139
    repEnds = asLogical(CAR(args)); args = CDR(args);
-
 
4140
    draw = asLogical(CAR(args)); args = CDR(args);
-
 
4141
 
-
 
4142
    PROTECT(col = FixupCol(CAR(args), R_TRANWHITE));	args = CDR(args);
-
 
4143
    ncol = LENGTH(col);
-
 
4144
    if(ncol < 1)
-
 
4145
	error(_("incorrect length for '%s' argument"), "col");
-
 
4146
    if(ncol > 1)
-
 
4147
	warning(_("incorrect length for '%s' argument"), "col");
-
 
4148
 
-
 
4149
    PROTECT(border = FixupCol(CAR(args), gpptr(dd)->fg)); args = CDR(args);
-
 
4150
    nborder = LENGTH(border);
-
 
4151
    if(nborder < 1)
-
 
4152
	error(_("incorrect length for '%s' argument"), "border");
-
 
4153
    if(nborder > 1)
-
 
4154
	warning(_("incorrect length for '%s' argument"), "border");
-
 
4155
 
-
 
4156
    GSavePars(dd);
-
 
4157
    ProcessInlinePars(args, dd);
-
 
4158
    /* Paul 2008-12-05
-
 
4159
     * Convert GP to gcontext AFTER ProcessInlinePars
-
 
4160
     */
-
 
4161
    gcontextFromGP(&gc, dd);
-
 
4162
 
-
 
4163
    GMode(1, dd);
-
 
4164
 
-
 
4165
    x = REAL(sx);
-
 
4166
    y = REAL(sy);
-
 
4167
    vmaxsave = vmaxget();
-
 
4168
    xx = (double *) R_alloc(nx, sizeof(double));
-
 
4169
    yy = (double *) R_alloc(nx, sizeof(double));
-
 
4170
    if (!xx || !yy)
-
 
4171
	error(_("unable to allocate memory (in do_xspline)"));
-
 
4172
    for (i = 0; i < nx; i++) {
-
 
4173
	xx[i] = x[i];
-
 
4174
	yy[i] = y[i];
-
 
4175
	GConvert(&(xx[i]), &(yy[i]), USER, DEVICE, dd);
-
 
4176
    }
-
 
4177
    GClip(dd);
-
 
4178
    gc.col = INTEGER(border)[0];
-
 
4179
    gc.fill = INTEGER(col)[0];
-
 
4180
    res = GEXspline(nx, xx, yy, REAL(ss), open, repEnds, draw, &gc, dd);
-
 
4181
    vmaxset(vmaxsave);
-
 
4182
    UNPROTECT(2);
-
 
4183
 
-
 
4184
    if(!draw) {
-
 
4185
	SEXP nm, tmpx, tmpy;
-
 
4186
	double *xx, *yy, *x0, *y0;
-
 
4187
	PROTECT(ans = res);
-
 
4188
	PROTECT(nm = allocVector(STRSXP, 2));
-
 
4189
	SET_STRING_ELT(nm, 0, mkChar("x"));
-
 
4190
	SET_STRING_ELT(nm, 1, mkChar("y"));
-
 
4191
	setAttrib(ans, R_NamesSymbol, nm);
-
 
4192
	nx = LENGTH(VECTOR_ELT(ans, 0));
-
 
4193
	x0 = REAL(VECTOR_ELT(ans, 0));
-
 
4194
	y0 = REAL(VECTOR_ELT(ans, 1));
-
 
4195
	PROTECT(tmpx = allocVector(REALSXP, nx));
-
 
4196
	PROTECT(tmpy = allocVector(REALSXP, nx));
-
 
4197
	xx = REAL(tmpx);
-
 
4198
	yy = REAL(tmpy);
-
 
4199
	for (i = 0; i < nx; i++) {
-
 
4200
	    xx[i] = x0[i];
-
 
4201
	    yy[i] = y0[i];
-
 
4202
	    GConvert(&(xx[i]), &(yy[i]), DEVICE, USER, dd);
-
 
4203
	}
-
 
4204
	SET_VECTOR_ELT(ans, 0, tmpx);
-
 
4205
	SET_VECTOR_ELT(ans, 1, tmpy);
-
 
4206
	UNPROTECT(4);
-
 
4207
    }
-
 
4208
 
-
 
4209
    GMode(0, dd);
-
 
4210
    GRestorePars(dd);
-
 
4211
    /* NOTE: only record operation if no "error"  */
-
 
4212
    if (GRecording(call, dd))
-
 
4213
	GErecordGraphicOperation(op, originalArgs, dd);
-
 
4214
    return ans;
-
 
4215
}
-
 
4216
 
-
 
4217
/* clip(x1, x2, y1, y2) */
-
 
4218
SEXP attribute_hidden do_clip(SEXP call, SEXP op, SEXP args, SEXP env)
-
 
4219
{
-
 
4220
    SEXP ans = R_NilValue;
-
 
4221
    double x1, x2, y1, y2;
-
 
4222
    SEXP originalArgs = args;
-
 
4223
    pGEDevDesc dd = GEcurrentDevice();
-
 
4224
 
-
 
4225
    checkArity(op, args);
-
 
4226
    x1 = asReal(CAR(args));
-
 
4227
    if(!R_FINITE(x1)) error("invalid '%s' argument", "x1");
-
 
4228
    args = CDR(args);
-
 
4229
    x2 = asReal(CAR(args));
-
 
4230
    if(!R_FINITE(x2)) error("invalid '%s' argument", "x2");
-
 
4231
    args = CDR(args);
-
 
4232
    y1 = asReal(CAR(args));
-
 
4233
    if(!R_FINITE(y1)) error("invalid '%s' argument", "y1");
-
 
4234
    args = CDR(args);
-
 
4235
    y2 = asReal(CAR(args));
-
 
4236
    if(!R_FINITE(y2)) error("invalid '%s' argument", "y2");
-
 
4237
 
-
 
4238
    GConvert(&x1, &y1, USER, DEVICE, dd);
-
 
4239
    GConvert(&x2, &y2, USER, DEVICE, dd);
-
 
4240
    GESetClip(x1, y1, x2, y2, dd);
-
 
4241
    /* avoid GClip resetting this */
-
 
4242
    gpptr(dd)->oldxpd = gpptr(dd)->xpd;
-
 
4243
 
-
 
4244
    /* NOTE: only record operation if no "error"  */
-
 
4245
    if (GRecording(call, dd))
-
 
4246
	GErecordGraphicOperation(op, originalArgs, dd);
-
 
4247
    return ans;
-
 
4248
}
-
 
4249
 
-
 
4250
/* convert[XY](x, from to) */
-
 
4251
SEXP attribute_hidden do_convertXY(SEXP call, SEXP op, SEXP args, SEXP env)
-
 
4252
{
-
 
4253
    SEXP ans = R_NilValue, x;
-
 
4254
    int from, to, i, n;
-
 
4255
    double *rx;
-
 
4256
    pGEDevDesc gdd = GEcurrentDevice();
-
 
4257
 
-
 
4258
    checkArity(op, args);
-
 
4259
    x = CAR(args);
-
 
4260
    if (TYPEOF(x) != REALSXP) error(_("invalid '%s' argument"), "x");
-
 
4261
    n = LENGTH(x);
-
 
4262
    from = asInteger(CADR(args));
-
 
4263
    if (from == NA_INTEGER || from <= 0 || from > 17 )
-
 
4264
	error(_("invalid '%s' argument"), "from");
-
 
4265
    to = asInteger(CADDR(args));
-
 
4266
    if (to == NA_INTEGER || to <= 0 || to > 17 )
-
 
4267
	error(_("invalid '%s' argument"), "to");
-
 
4268
    from--; to--;
-
 
4269
 
-
 
4270
    PROTECT(ans = duplicate(x));
-
 
4271
    rx = REAL(ans);
-
 
4272
    if (PRIMVAL(op) == 1)
-
 
4273
	for (i = 0; i < n; i++) rx[i] = GConvertY(rx[i], from, to, gdd);
-
 
4274
    else
-
 
4275
	for (i = 0; i < n; i++) rx[i] = GConvertX(rx[i], from, to, gdd);
-
 
4276
    UNPROTECT(1);
-
 
4277
 
-
 
4278
    return ans;
-
 
4279
}
-