blob: e14dd499b921b7daaaa28296c3a165c338221a9d [file] [log] [blame]
/*
* R : A Computer Language for Statistical Data Analysis
* Copyright (C) 2000-2019 The R Core Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, a copy is available at
* https://www.R-project.org/Licenses/
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <Defn.h> /* for checkArity */
#include <Internal.h>
#undef _
#ifdef ENABLE_NLS
#include <libintl.h>
#define _(String) dgettext ("utils", String)
#else
#define _(String) (String)
#endif
#ifdef Win32
# include "Startup.h"
# include "getline/getline.h" /* for gl_load/savehistory */
# include "getline/wc_history.h" /* for wgl_load/savehistory */
SEXP savehistory(SEXP call, SEXP op, SEXP args, SEXP env)
{
SEXP sfile;
args = CDR(args);
sfile = CAR(args);
if (!isString(sfile) || LENGTH(sfile) < 1)
errorcall(call, _("invalid '%s' argument"), "file");
if (CharacterMode == RGui) {
R_setupHistory(); /* re-read the history size */
wgl_savehistoryW(filenameToWchar(STRING_ELT(sfile, 0), 0),
R_HistorySize);
} else if (R_Interactive && CharacterMode == RTerm) {
R_setupHistory(); /* re-read the history size */
gl_savehistory(translateChar(STRING_ELT(sfile, 0)), R_HistorySize);
} else
errorcall(call, _("'savehistory' can only be used in Rgui and Rterm"));
return R_NilValue;
}
SEXP loadhistory(SEXP call, SEXP op, SEXP args, SEXP env)
{
SEXP sfile;
args = CDR(args);
sfile = CAR(args);
if (!isString(sfile) || LENGTH(sfile) < 1)
errorcall(call, _("invalid '%s' argument"), "file");
if (CharacterMode == RGui)
wgl_loadhistoryW(filenameToWchar(STRING_ELT(sfile, 0), 0));
else if (R_Interactive && CharacterMode == RTerm)
gl_loadhistory(translateChar(STRING_ELT(sfile, 0)));
else
errorcall(call, _("'loadhistory' can only be used in Rgui and Rterm"));
return R_NilValue;
}
SEXP addhistory(SEXP call, SEXP op, SEXP args, SEXP env)
{
SEXP stamp;
const void *vmax = vmaxget();
args = CDR(args);
stamp = CAR(args);
if (!isString(stamp))
errorcall(call, _("invalid timestamp"));
if (CharacterMode == RGui) {
for (int i = 0; i < LENGTH(stamp); i++)
wgl_histadd(wtransChar(STRING_ELT(stamp, i)));
} else if (R_Interactive && CharacterMode == RTerm) {
for (int i = 0; i < LENGTH(stamp); i++)
gl_histadd(translateChar(STRING_ELT(stamp, i)));
}
vmaxset(vmax);
return R_NilValue;
}
SEXP Win_dataentry(SEXP args);
SEXP Win_dataviewer(SEXP args);
SEXP dataentry(SEXP call, SEXP op, SEXP args, SEXP rho)
{
return Win_dataentry(CDR(args));
}
SEXP dataviewer(SEXP call, SEXP op, SEXP args, SEXP rho)
{
return Win_dataviewer(CDR(args));
}
SEXP Win_selectlist(SEXP args);
SEXP selectlist(SEXP call, SEXP op, SEXP args, SEXP rho)
{
return Win_selectlist(CDR(args));
}
#else
#define R_INTERFACE_PTRS 1
#include <Rinterface.h>
SEXP loadhistory(SEXP call, SEXP op, SEXP args, SEXP rho)
{
ptr_R_loadhistory(call, op, CDR(args), rho);
return R_NilValue;
}
SEXP savehistory(SEXP call, SEXP op, SEXP args, SEXP rho)
{
ptr_R_savehistory(call, op, CDR(args), rho);
return R_NilValue;
}
SEXP addhistory(SEXP call, SEXP op, SEXP args, SEXP rho)
{
if(ptr_R_addhistory) ptr_R_addhistory(call, op, CDR(args), rho);
return R_NilValue;
}
#ifdef HAVE_X11
#include <Rdynpriv.h>
#include <Rmodules/RX11.h> /* typedefs for the module routine types */
static R_deRoutines de_routines, *de_ptr = &de_routines;
static void R_de_Init(void)
{
static int de_init = 0;
if(de_init > 0) return;
if(de_init < 0) error(_("X11 dataentry cannot be loaded"));
de_init = -1;
if(strcmp(R_GUIType, "none") == 0) {
warning(_("X11 is not available"));
return;
}
int res = R_moduleCdynload("R_de", 1, 1);
if(!res) error(_("X11 dataentry cannot be loaded"));
de_ptr->de = (R_X11DataEntryRoutine)
R_FindSymbol("in_RX11_dataentry", "R_de", NULL);
de_ptr->dv = (R_X11DataViewer)
R_FindSymbol("in_R_X11_dataviewer", "R_de", NULL);
de_init = 1;
return;
}
static SEXP X11_do_dataentry(SEXP call, SEXP op, SEXP args, SEXP rho)
{
R_de_Init();
return (*de_ptr->de)(call, op, args, rho);
}
static SEXP X11_do_dataviewer(SEXP call, SEXP op, SEXP args, SEXP rho)
{
R_de_Init();
return (*de_ptr->dv)(call, op, args, rho);
}
#else /* no X11 */
static SEXP X11_do_dataentry(SEXP call, SEXP op, SEXP args, SEXP rho)
{
error(_("X11 is not available"));
return R_NilValue;
}
static SEXP X11_do_dataviewer(SEXP call, SEXP op, SEXP args, SEXP rho)
{
error(_("X11 is not available"));
return R_NilValue;
}
#endif
SEXP dataentry(SEXP call, SEXP op, SEXP args, SEXP env)
{
args = CDR(args);
if(ptr_do_dataentry) return ptr_do_dataentry(call, op, args, env);
else return X11_do_dataentry(call, op, args, env);
}
SEXP dataviewer(SEXP call, SEXP op, SEXP args, SEXP env)
{
args = CDR(args);
if(ptr_do_dataviewer) return ptr_do_dataviewer(call, op, args, env);
else return X11_do_dataviewer(call, op, args, env);
}
SEXP selectlist(SEXP call, SEXP op, SEXP args, SEXP env)
{
if(ptr_do_selectlist) return ptr_do_selectlist(call, op, CDR(args), env);
return R_NilValue;
}
#endif
SEXP edit(SEXP call, SEXP op, SEXP args, SEXP rho)
{
return do_edit(call, op, CDR(args), rho);
}
SEXP flushconsole(void)
{
R_FlushConsole();
return R_NilValue;
}
SEXP processevents(void)
{
R_ProcessEvents();
return R_NilValue;
}
// formerly in src/main/platform.c
SEXP fileedit(SEXP call, SEXP op, SEXP args, SEXP rho)
{
SEXP fn, ti, ed;
const char **f, **title, *editor;
int i, n;
const void *vmax = vmaxget();
args = CDR(args);
fn = CAR(args); args = CDR(args);
ti = CAR(args); args = CDR(args);
ed = CAR(args);
n = length(fn);
if (!isString(ed) || length(ed) != 1)
error(_("invalid '%s' specification"), "editor");
if (n > 0) {
if (!isString(fn))
error(_("invalid '%s' specification"), "filename");
for (i = 0; i < n; i++)
if (STRING_ELT(fn, i) == NA_STRING)
error(_("'%s' contains missing values"), "filename");
f = (const char**) R_alloc(n, sizeof(char*));
title = (const char**) R_alloc(n, sizeof(char*));
/* FIXME convert to UTF-8 on Windows */
for (i = 0; i < n; i++) {
SEXP el = STRING_ELT(fn, 0);
if (!isNull(el))
#ifdef Win32
f[i] = acopy_string(reEnc(CHAR(el), getCharCE(el), CE_UTF8, 1));
#else
f[i] = acopy_string(translateChar(el));
#endif
else
f[i] = "";
if (!isNull(STRING_ELT(ti, i)))
title[i] = acopy_string(translateChar(STRING_ELT(ti, i)));
else
title[i] = "";
}
}
else { /* open a new file for editing */
n = 1;
f = (const char**) R_alloc(1, sizeof(char*));
f[0] = "";
title = (const char**) R_alloc(1, sizeof(char*));
title[0] = "";
}
SEXP ed0 = STRING_ELT(ed, 0);
#ifdef Win32
editor = acopy_string(reEnc(CHAR(ed0), getCharCE(ed0), CE_UTF8, 1));
#else
editor = acopy_string(translateChar(ed0));
#endif
R_EditFiles(n, f, title, editor);
vmaxset(vmax);
return R_NilValue;
}
#ifdef Win32
SEXP in_loadRconsole(SEXP);
SEXP in_memsize(SEXP);
SEXP in_shortpath(SEXP);
SEXP loadRconsole(SEXP file)
{
return in_loadRconsole(file);
}
SEXP memsize(SEXP size)
{
return in_memsize(size);
}
SEXP shortpath(SEXP paths)
{
return in_shortpath(paths);
}
#endif
/* called from tar() */
SEXP octsize(SEXP size)
{
double s = asReal(size);
SEXP ans = allocVector(RAWSXP, 11);
Rbyte *ra = RAW(ans);
if (!R_FINITE(s) && s >= 0) error("size must be finite and >= 0");
/* We have to be able to do this on a 32-bit system */
for (int i = 0; i < 11; i++) {
double s2 = floor(s/8.);
double t = s - 8.*s2;
s = s2;
ra[10-i] = (Rbyte) (48 + t); // as ASCII
}
return ans;
}