The R Project SVN R

Rev

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

Rev 36901 Rev 37676
1
/*
1
/*
2
 *  R : A Computer Langage for Statistical Data Analysis
2
 *  R : A Computer Langage for Statistical Data Analysis
3
 *  Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
3
 *  Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
4
 *  Copyright (C) 1998--2005  Robert Gentleman, Ross Ihaka and the
4
 *  Copyright (C) 1998--2005  Robert Gentleman, Ross Ihaka and the
5
 *                            R Development Core Team
5
 *                            R Development Core Team
6
 *
6
 *
7
 *  This program is free software; you can redistribute it and/or modify
7
 *  This program is free software; you can redistribute it and/or modify
8
 *  it under the terms of the GNU General Public License as published by
8
 *  it under the terms of the GNU General Public License as published by
9
 *  the Free Software Foundation; either version 2 of the License, or
9
 *  the Free Software Foundation; either version 2 of the License, or
10
 *  (at your option) any later version.
10
 *  (at your option) any later version.
11
 *
11
 *
12
 *  This program is distributed in the hope that it will be useful,
12
 *  This program is distributed in the hope that it will be useful,
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *  GNU General Public License for more details.
15
 *  GNU General Public License for more details.
16
 *
16
 *
17
 *  You should have received a copy of the GNU General Public License
17
 *  You should have received a copy of the GNU General Public License
18
 *  along with this program; if not, write to the Free Software
18
 *  along with this program; if not, write to the Free Software
19
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
19
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
20
 */
20
 */
21
 
21
 
22
/* TODO
22
/* TODO
23
   - spreadsheet copy and paste?
23
   - spreadsheet copy and paste?
24
 */
24
 */
25
 
25
 
26
/* Use of strchr here is MBCS-safe */
26
/* Use of strchr here is MBCS-safe */
27
 
27
 
28
#ifdef HAVE_CONFIG_H
28
#ifdef HAVE_CONFIG_H
29
#include <config.h>
29
#include <config.h>
30
#endif
30
#endif
31
#include "win-nls.h"
31
#include "win-nls.h"
32
 
32
 
33
#include <wchar.h>
33
#include <wchar.h>
34
#ifdef SUPPORT_MBCS
-
 
35
#include <R_ext/rlocale.h>
34
#include <R_ext/rlocale.h>
36
#endif
-
 
37
 
35
 
38
#include "Defn.h"
36
#include "Defn.h"
39
#include "Print.h"
37
#include "Print.h"
40
 
38
 
41
#include "graphapp/ga.h"
39
#include "graphapp/ga.h"
42
#include "console.h"
40
#include "console.h"
43
#include "consolestructs.h"
41
#include "consolestructs.h"
44
#include "rui.h"
42
#include "rui.h"
45
 
43
 
46
static dataeditor de;
44
static dataeditor de;
47
static ConsoleData p;
45
static ConsoleData p;
48
 
46
 
49
typedef enum {UNKNOWNN, NUMERIC, CHARACTER} CellType;
47
typedef enum {UNKNOWNN, NUMERIC, CHARACTER} CellType;
50
 
48
 
51
static Rboolean R_de_up;
49
static Rboolean R_de_up;
52
 
50
 
53
#ifndef max
51
#ifndef max
54
#define max(a, b) (((a)>(b))?(a):(b))
52
#define max(a, b) (((a)>(b))?(a):(b))
55
#endif
53
#endif
56
#ifndef min
54
#ifndef min
57
#define min(a, b) (((a)<(b))?(a):(b))
55
#define min(a, b) (((a)<(b))?(a):(b))
58
#endif
56
#endif
59
#define BOXW(x) (min(((x<100 && nboxchars==0)?boxw[x]:box_w),WIDTH-boxw[0]-2*bwidth-2))
57
#define BOXW(x) (min(((x<100 && nboxchars==0)?boxw[x]:box_w),WIDTH-boxw[0]-2*bwidth-2))
60
 
58
 
61
#define FIELDWIDTH 10
59
#define FIELDWIDTH 10
62
 
60
 
63
/* Local Function Definitions */
61
/* Local Function Definitions */
64
 
62
 
65
static void advancerect(int);
63
static void advancerect(int);
66
static void bell();
64
static void bell();
67
static void cleararea(int, int, int, int, rgb);
65
static void cleararea(int, int, int, int, rgb);
68
static void clearrect(void);
66
static void clearrect(void);
69
static void closerect(void);
67
static void closerect(void);
70
static void clearwindow(void);
68
static void clearwindow(void);
71
static void de_closewin(void);
69
static void de_closewin(void);
72
static void copyarea(int, int, int, int);
70
static void copyarea(int, int, int, int);
73
static void copyH(int, int, int);
71
static void copyH(int, int, int);
74
static void deredraw(void);
72
static void deredraw(void);
75
static void eventloop(void);
73
static void eventloop(void);
76
static void downlightrect(void);
74
static void downlightrect(void);
77
static void drawwindow(void);
75
static void drawwindow(void);
78
static void drawcol(int);
76
static void drawcol(int);
79
/* static void de_drawline(int, int, int, int);*/
77
/* static void de_drawline(int, int, int, int);*/
80
static void de_drawtext(int, int, char *);
78
static void de_drawtext(int, int, char *);
81
static void drawrectangle(int, int, int, int, int, int);
79
static void drawrectangle(int, int, int, int, int, int);
82
static void drawrow(int);
80
static void drawrow(int);
83
static void find_coords(int, int, int*, int*);
81
static void find_coords(int, int, int*, int*);
84
static void handlechar(char*);
82
static void handlechar(char*);
85
static void highlightrect(void);
83
static void highlightrect(void);
86
static Rboolean initwin(void);
84
static Rboolean initwin(void);
87
static void jumppage(int);
85
static void jumppage(int);
88
static void jumpwin(int, int);
86
static void jumpwin(int, int);
89
static void de_popupmenu(int, int, int);
87
static void de_popupmenu(int, int, int);
90
static void printlabs(void);
88
static void printlabs(void);
91
static void printrect(int, int);
89
static void printrect(int, int);
92
static void printstring(char*, int, int, int, int);
90
static void printstring(char*, int, int, int, int);
93
static void printelt(SEXP, int, int, int);
91
static void printelt(SEXP, int, int, int);
94
static void setcellwidths(void);
92
static void setcellwidths(void);
95
 
93
 
96
static dataeditor newdataeditor();
94
static dataeditor newdataeditor();
97
static void de_copy(control c);
95
static void de_copy(control c);
98
static void de_paste(control c);
96
static void de_paste(control c);
99
static void de_delete(control c);
97
static void de_delete(control c);
100
static menuitem de_mvw;
98
static menuitem de_mvw;
101
 
99
 
102
static SEXP work, names, lens;
100
static SEXP work, names, lens;
103
static PROTECT_INDEX wpi, npi, lpi;
101
static PROTECT_INDEX wpi, npi, lpi;
104
static SEXP ssNA_STRING;
102
static SEXP ssNA_STRING;
105
static double ssNA_REAL;
103
static double ssNA_REAL;
106
 
104
 
107
/* Global variables needed for the graphics */
105
/* Global variables needed for the graphics */
108
 
106
 
109
static int box_w;                       /* width of a box */
107
static int box_w;                       /* width of a box */
110
static int boxw[100];                   /* widths of cells */
108
static int boxw[100];                   /* widths of cells */
111
static int box_h;                       /* height of a box */
109
static int box_h;                       /* height of a box */
112
static int windowWidth;                 /* current width of the window */
110
static int windowWidth;                 /* current width of the window */
113
static int windowHeight;                /* current height of the window */
111
static int windowHeight;                /* current height of the window */
114
static int currentexp;                  /* boolean: whether an cell is active */
112
static int currentexp;                  /* boolean: whether an cell is active */
115
static int crow;                        /* current row */
113
static int crow;                        /* current row */
116
static int ccol;                        /* current column */
114
static int ccol;                        /* current column */
117
static int nwide, nhigh;
115
static int nwide, nhigh;
118
static int colmax, colmin, rowmax, rowmin;
116
static int colmax, colmin, rowmax, rowmin;
119
static int ndecimal;                    /* count decimal points */
117
static int ndecimal;                    /* count decimal points */
120
static int ne;                          /* count exponents */
118
static int ne;                          /* count exponents */
121
static int nneg;			/* indicate whether its a negative */
119
static int nneg;			/* indicate whether its a negative */
122
static int clength;                     /* number of characters currently entered */
120
static int clength;                     /* number of characters currently entered */
123
static char buf[200];
121
static char buf[200];
124
static char *bufp;
122
static char *bufp;
125
static int bwidth;			/* width of the border */
123
static int bwidth;			/* width of the border */
126
static int hwidth;			/* width of header  */
124
static int hwidth;			/* width of header  */
127
static int text_xoffset, text_yoffset;
125
static int text_xoffset, text_yoffset;
128
static field celledit;
126
static field celledit;
129
static Rboolean newcol, CellModified, CellEditable;
127
static Rboolean newcol, CellModified, CellEditable;
130
static int xmaxused, ymaxused;
128
static int xmaxused, ymaxused;
131
static int oldWIDTH=0, oldHEIGHT=0;
129
static int oldWIDTH=0, oldHEIGHT=0;
132
static int nboxchars=0;
130
static int nboxchars=0;
133
static int labdigs=4;
131
static int labdigs=4;
134
static char labform[6];
132
static char labform[6];
135
static int xScrollbarScale=1, yScrollbarScale=1;
133
static int xScrollbarScale=1, yScrollbarScale=1;
136
 
134
 
137
#define WIN32_LEAN_AND_MEAN 1
135
#define WIN32_LEAN_AND_MEAN 1
138
#include <windows.h> /* for Sleep */
136
#include <windows.h> /* for Sleep */
139
 
137
 
140
int mb_char_len(char *buf, int clength, wchar_t *wc); /* from console.c */
138
int mb_char_len(char *buf, int clength, wchar_t *wc); /* from console.c */
141
 
139
 
142
static void moveback()
140
static void moveback()
143
{
141
{
144
    int mb_len;
142
    int mb_len;
145
    wchar_t wc;
143
    wchar_t wc;
146
 
144
 
147
    if (clength > 0) {
145
    if (clength > 0) {
148
	mb_len = mb_char_len(buf, clength-1, &wc);
146
	mb_len = mb_char_len(buf, clength-1, &wc);
149
	clength -= mb_len;
147
	clength -= mb_len;
150
	bufp -= mb_len;
148
	bufp -= mb_len;
151
	printstring(buf, clength, crow, ccol, 1);
149
	printstring(buf, clength, crow, ccol, 1);
152
    } else bell();
150
    } else bell();
153
}
151
}
154
 
152
 
155
 
153
 
156
 /*
154
 /*
157
  Underlying assumptions (for this version R >= 1.8.0)
155
  Underlying assumptions (for this version R >= 1.8.0)
158
 
156
 
159
  The data are stored in a list `work', with unused columns having
157
  The data are stored in a list `work', with unused columns having
160
  NULL entries.  The names for the list are in `names', which should
158
  NULL entries.  The names for the list are in `names', which should
161
  have a name for all displayable columns (up to xmaxused).
159
  have a name for all displayable columns (up to xmaxused).
162
  The *used* lengths of the columns are in `lens': this needs only be
160
  The *used* lengths of the columns are in `lens': this needs only be
163
  set for non-NULL columns.
161
  set for non-NULL columns.
164
 
162
 
165
  If the list was originally length(0), that should work with
163
  If the list was originally length(0), that should work with
166
  0 pre-defined cols.  (It used to have 1 pre-defined numeric column.)
164
  0 pre-defined cols.  (It used to have 1 pre-defined numeric column.)
167
 
165
 
168
  All row and col numbers are 1-based.
166
  All row and col numbers are 1-based.
169
 
167
 
170
  BDR May 2003
168
  BDR May 2003
171
 */
169
 */
172
 
170
 
173
/*
171
/*
174
   ssNewVector is just an interface to allocVector but it lets us
172
   ssNewVector is just an interface to allocVector but it lets us
175
   set the fields to NA. We need to have a special NA for reals and
173
   set the fields to NA. We need to have a special NA for reals and
176
   strings so that we can differentiate between uninitialized elements
174
   strings so that we can differentiate between uninitialized elements
177
   in the vectors and user supplied NA's; hence ssNA_REAL and ssNA_STRING
175
   in the vectors and user supplied NA's; hence ssNA_REAL and ssNA_STRING
178
 */
176
 */
179
 
177
 
180
static SEXP ssNewVector(SEXPTYPE type, int vlen)
178
static SEXP ssNewVector(SEXPTYPE type, int vlen)
181
{
179
{
182
    SEXP tvec;
180
    SEXP tvec;
183
    int j;
181
    int j;
184
 
182
 
185
    tvec = allocVector(type, vlen);
183
    tvec = allocVector(type, vlen);
186
    for (j = 0; j < vlen; j++)
184
    for (j = 0; j < vlen; j++)
187
	if (type == REALSXP)
185
	if (type == REALSXP)
188
	    REAL(tvec)[j] = ssNA_REAL;
186
	    REAL(tvec)[j] = ssNA_REAL;
189
	else if (type == STRSXP)
187
	else if (type == STRSXP)
190
	    SET_STRING_ELT(tvec, j, STRING_ELT(ssNA_STRING, 0));
188
	    SET_STRING_ELT(tvec, j, STRING_ELT(ssNA_STRING, 0));
191
    return (tvec);
189
    return (tvec);
192
}
190
}
193
static void eventloop()
191
static void eventloop()
194
{
192
{
195
    while (R_de_up) {
193
    while (R_de_up) {
196
	/* avoid consuming 100% CPU time here */
194
	/* avoid consuming 100% CPU time here */
197
	Sleep(10);
195
	Sleep(10);
198
	R_ProcessEvents();
196
	R_ProcessEvents();
199
    }
197
    }
200
}
198
}
201
 
199
 
202
static void de_closewin_cend(void *data)
200
static void de_closewin_cend(void *data)
203
{
201
{
204
    de_closewin();
202
    de_closewin();
205
}
203
}
206
 
204
 
207
SEXP do_dataentry(SEXP call, SEXP op, SEXP args, SEXP rho)
205
SEXP do_dataentry(SEXP call, SEXP op, SEXP args, SEXP rho)
208
{
206
{
209
    SEXP colmodes, tnames, tvec, tvec2, work2;
207
    SEXP colmodes, tnames, tvec, tvec2, work2;
210
    SEXPTYPE type;
208
    SEXPTYPE type;
211
    int i, j, cnt, len, nprotect;
209
    int i, j, cnt, len, nprotect;
212
    RCNTXT cntxt;
210
    RCNTXT cntxt;
213
    char clab[25];
211
    char clab[25];
214
 
212
 
215
    nprotect = 0;/* count the PROTECT()s */
213
    nprotect = 0;/* count the PROTECT()s */
216
    PROTECT_WITH_INDEX(work = duplicate(CAR(args)), &wpi); nprotect++;
214
    PROTECT_WITH_INDEX(work = duplicate(CAR(args)), &wpi); nprotect++;
217
    colmodes = CADR(args);
215
    colmodes = CADR(args);
218
    tnames = getAttrib(work, R_NamesSymbol);
216
    tnames = getAttrib(work, R_NamesSymbol);
219
 
217
 
220
    if (TYPEOF(work) != VECSXP || TYPEOF(colmodes) != VECSXP)
218
    if (TYPEOF(work) != VECSXP || TYPEOF(colmodes) != VECSXP)
221
	errorcall(call, G_("invalid argument"));
219
	errorcall(call, G_("invalid argument"));
222
 
220
 
223
    /* initialize the constants */
221
    /* initialize the constants */
224
 
222
 
225
    bufp = buf;
223
    bufp = buf;
226
    ne = 0;
224
    ne = 0;
227
    currentexp = 0;
225
    currentexp = 0;
228
    nneg = 0;
226
    nneg = 0;
229
    ndecimal = 0;
227
    ndecimal = 0;
230
    clength = 0;
228
    clength = 0;
231
    ccol = 1;
229
    ccol = 1;
232
    crow = 1;
230
    crow = 1;
233
    colmin = 1;
231
    colmin = 1;
234
    rowmin = 1;
232
    rowmin = 1;
235
    ssNA_REAL = -NA_REAL;
233
    ssNA_REAL = -NA_REAL;
236
    tvec = allocVector(REALSXP, 1);
234
    tvec = allocVector(REALSXP, 1);
237
    REAL(tvec)[0] = ssNA_REAL;
235
    REAL(tvec)[0] = ssNA_REAL;
238
    PROTECT(ssNA_STRING = coerceVector(tvec, STRSXP)); nprotect++;
236
    PROTECT(ssNA_STRING = coerceVector(tvec, STRSXP)); nprotect++;
239
    bwidth = 0;
237
    bwidth = 0;
240
    hwidth = 5;
238
    hwidth = 5;
241
 
239
 
242
    /* setup work, names, lens  */
240
    /* setup work, names, lens  */
243
    xmaxused = length(work); ymaxused = 0;
241
    xmaxused = length(work); ymaxused = 0;
244
    PROTECT_WITH_INDEX(lens = allocVector(INTSXP, xmaxused), &lpi);
242
    PROTECT_WITH_INDEX(lens = allocVector(INTSXP, xmaxused), &lpi);
245
    nprotect++;
243
    nprotect++;
246
 
244
 
247
    if (isNull(tnames)) {
245
    if (isNull(tnames)) {
248
	PROTECT_WITH_INDEX(names = allocVector(STRSXP, xmaxused), &npi);
246
	PROTECT_WITH_INDEX(names = allocVector(STRSXP, xmaxused), &npi);
249
	for(i = 0; i < xmaxused; i++) {
247
	for(i = 0; i < xmaxused; i++) {
250
	    sprintf(clab, "var%d", i);
248
	    sprintf(clab, "var%d", i);
251
	    SET_STRING_ELT(names, i, mkChar(clab));
249
	    SET_STRING_ELT(names, i, mkChar(clab));
252
	}
250
	}
253
    } else
251
    } else
254
	PROTECT_WITH_INDEX(names = duplicate(tnames), &npi);
252
	PROTECT_WITH_INDEX(names = duplicate(tnames), &npi);
255
    nprotect++;
253
    nprotect++;
256
    for (i = 0; i < xmaxused; i++) {
254
    for (i = 0; i < xmaxused; i++) {
257
	int len = LENGTH(VECTOR_ELT(work, i));
255
	int len = LENGTH(VECTOR_ELT(work, i));
258
	INTEGER(lens)[i] = len;
256
	INTEGER(lens)[i] = len;
259
	ymaxused = max(len, ymaxused);
257
	ymaxused = max(len, ymaxused);
260
	type = TYPEOF(VECTOR_ELT(work, i));
258
	type = TYPEOF(VECTOR_ELT(work, i));
261
	if (LENGTH(colmodes) > 0 && !isNull(VECTOR_ELT(colmodes, i)))
259
	if (LENGTH(colmodes) > 0 && !isNull(VECTOR_ELT(colmodes, i)))
262
	    type = str2type(CHAR(STRING_ELT(VECTOR_ELT(colmodes, i), 0)));
260
	    type = str2type(CHAR(STRING_ELT(VECTOR_ELT(colmodes, i), 0)));
263
	if (type != STRSXP) type = REALSXP;
261
	if (type != STRSXP) type = REALSXP;
264
	if (isNull(VECTOR_ELT(work, i))) {
262
	if (isNull(VECTOR_ELT(work, i))) {
265
	    if (type == NILSXP) type = REALSXP;
263
	    if (type == NILSXP) type = REALSXP;
266
	    SET_VECTOR_ELT(work, i, ssNewVector(type, 100));
264
	    SET_VECTOR_ELT(work, i, ssNewVector(type, 100));
267
	} else if (!isVector(VECTOR_ELT(work, i)))
265
	} else if (!isVector(VECTOR_ELT(work, i)))
268
	    errorcall(call, G_("invalid type for value"));
266
	    errorcall(call, G_("invalid type for value"));
269
	else {
267
	else {
270
	    if (TYPEOF(VECTOR_ELT(work, i)) != type)
268
	    if (TYPEOF(VECTOR_ELT(work, i)) != type)
271
		SET_VECTOR_ELT(work, i,
269
		SET_VECTOR_ELT(work, i,
272
			       coerceVector(VECTOR_ELT(work, i), type));
270
			       coerceVector(VECTOR_ELT(work, i), type));
273
	}
271
	}
274
    }
272
    }
275
 
273
 
276
    /* scale scrollbars as needed */
274
    /* scale scrollbars as needed */
277
    if (xmaxused > 10000) xScrollbarScale = xmaxused/1000;
275
    if (xmaxused > 10000) xScrollbarScale = xmaxused/1000;
278
    if (ymaxused > 10000) yScrollbarScale = ymaxused/1000;
276
    if (ymaxused > 10000) yScrollbarScale = ymaxused/1000;
279
 
277
 
280
    /* start up the window, more initializing in here */
278
    /* start up the window, more initializing in here */
281
    if (initwin())
279
    if (initwin())
282
	errorcall(call, G_("invalid device"));
280
	errorcall(call, G_("invalid device"));
283
 
281
 
284
    /* set up a context which will close the window if there is an error */
282
    /* set up a context which will close the window if there is an error */
285
    begincontext(&cntxt, CTXT_CCODE, R_NilValue, R_BaseEnv, R_BaseEnv,
283
    begincontext(&cntxt, CTXT_CCODE, R_NilValue, R_BaseEnv, R_BaseEnv,
286
		 R_NilValue, R_NilValue);
284
		 R_NilValue, R_NilValue);
287
    cntxt.cend = &de_closewin_cend;
285
    cntxt.cend = &de_closewin_cend;
288
    cntxt.cenddata = NULL;
286
    cntxt.cenddata = NULL;
289
 
287
 
290
    highlightrect();
288
    highlightrect();
291
 
289
 
292
    eventloop();
290
    eventloop();
293
 
291
 
294
    endcontext(&cntxt);
292
    endcontext(&cntxt);
295
 
293
 
296
    /* drop out unused columns */
294
    /* drop out unused columns */
297
    for(i = 0, cnt = 0; i < xmaxused; i++)
295
    for(i = 0, cnt = 0; i < xmaxused; i++)
298
	if(!isNull(VECTOR_ELT(work, i))) cnt++;
296
	if(!isNull(VECTOR_ELT(work, i))) cnt++;
299
    if (cnt < xmaxused) {
297
    if (cnt < xmaxused) {
300
	PROTECT(work2 = allocVector(VECSXP, cnt)); nprotect++;
298
	PROTECT(work2 = allocVector(VECSXP, cnt)); nprotect++;
301
	for(i = 0, j = 0; i < xmaxused; i++) {
299
	for(i = 0, j = 0; i < xmaxused; i++) {
302
	    if(!isNull(VECTOR_ELT(work, i))) {
300
	    if(!isNull(VECTOR_ELT(work, i))) {
303
		SET_VECTOR_ELT(work2, j, VECTOR_ELT(work, i));
301
		SET_VECTOR_ELT(work2, j, VECTOR_ELT(work, i));
304
		INTEGER(lens)[j] = INTEGER(lens)[i];
302
		INTEGER(lens)[j] = INTEGER(lens)[i];
305
		SET_STRING_ELT(names, j, STRING_ELT(names, i));
303
		SET_STRING_ELT(names, j, STRING_ELT(names, i));
306
		j++;
304
		j++;
307
	    }
305
	    }
308
	}
306
	}
309
	REPROTECT(names = lengthgets(names, cnt), npi);
307
	REPROTECT(names = lengthgets(names, cnt), npi);
310
    } else work2 = work;
308
    } else work2 = work;
311
 
309
 
312
    for (i = 0; i < LENGTH(work2); i++) {
310
    for (i = 0; i < LENGTH(work2); i++) {
313
	len = INTEGER(lens)[i];
311
	len = INTEGER(lens)[i];
314
	tvec = VECTOR_ELT(work2, i);
312
	tvec = VECTOR_ELT(work2, i);
315
	if (LENGTH(tvec) != len) {
313
	if (LENGTH(tvec) != len) {
316
	    tvec2 = ssNewVector(TYPEOF(tvec), len);
314
	    tvec2 = ssNewVector(TYPEOF(tvec), len);
317
	    for (j = 0; j < len; j++) {
315
	    for (j = 0; j < len; j++) {
318
		if (TYPEOF(tvec) == REALSXP) {
316
		if (TYPEOF(tvec) == REALSXP) {
319
		    if (REAL(tvec)[j] != ssNA_REAL)
317
		    if (REAL(tvec)[j] != ssNA_REAL)
320
			REAL(tvec2)[j] = REAL(tvec)[j];
318
			REAL(tvec2)[j] = REAL(tvec)[j];
321
		    else
319
		    else
322
			REAL(tvec2)[j] = NA_REAL;
320
			REAL(tvec2)[j] = NA_REAL;
323
		} else if (TYPEOF(tvec) == STRSXP) {
321
		} else if (TYPEOF(tvec) == STRSXP) {
324
		    if (!streql(CHAR(STRING_ELT(tvec, j)),
322
		    if (!streql(CHAR(STRING_ELT(tvec, j)),
325
				CHAR(STRING_ELT(ssNA_STRING, 0))))
323
				CHAR(STRING_ELT(ssNA_STRING, 0))))
326
			SET_STRING_ELT(tvec2, j, STRING_ELT(tvec, j));
324
			SET_STRING_ELT(tvec2, j, STRING_ELT(tvec, j));
327
		    else
325
		    else
328
			SET_STRING_ELT(tvec2, j, NA_STRING);
326
			SET_STRING_ELT(tvec2, j, NA_STRING);
329
		} else
327
		} else
330
		    error(G_("dataentry: internal memory problem"));
328
		    error(G_("dataentry: internal memory problem"));
331
	    }
329
	    }
332
	    SET_VECTOR_ELT(work2, i, tvec2);
330
	    SET_VECTOR_ELT(work2, i, tvec2);
333
	}
331
	}
334
    }
332
    }
335
 
333
 
336
    setAttrib(work2, R_NamesSymbol, names);
334
    setAttrib(work2, R_NamesSymbol, names);
337
    UNPROTECT(nprotect);
335
    UNPROTECT(nprotect);
338
    return work2;
336
    return work2;
339
}
337
}
340
 
338
 
341
/* Window Drawing Routines */
339
/* Window Drawing Routines */
342
 
340
 
343
static rgb bbg;
341
static rgb bbg;
344
 
342
 
345
static void setcellwidths(void)
343
static void setcellwidths(void)
346
{
344
{
347
    int i, w, dw;
345
    int i, w, dw;
348
 
346
 
349
    windowWidth = w = 2*bwidth + boxw[0] + BOXW(colmin);
347
    windowWidth = w = 2*bwidth + boxw[0] + BOXW(colmin);
350
    nwide = 2;
348
    nwide = 2;
351
    for (i = 2; i < 100; i++) { /* 100 on-screen columns cannot occur */
349
    for (i = 2; i < 100; i++) { /* 100 on-screen columns cannot occur */
352
	dw = BOXW(i + colmin - 1);
350
	dw = BOXW(i + colmin - 1);
353
	if((w += dw) > WIDTH) {
351
	if((w += dw) > WIDTH) {
354
	    nwide = i;
352
	    nwide = i;
355
	    windowWidth = w - dw;
353
	    windowWidth = w - dw;
356
	    break;
354
	    break;
357
	}
355
	}
358
    }
356
    }
359
}
357
}
360
 
358
 
361
 
359
 
362
static void drawwindow(void)
360
static void drawwindow(void)
363
{
361
{
364
    /* might have resized */
362
    /* might have resized */
365
    setcellwidths();
363
    setcellwidths();
366
    nhigh = (HEIGHT - 2 * bwidth - hwidth - 3) / box_h;
364
    nhigh = (HEIGHT - 2 * bwidth - hwidth - 3) / box_h;
367
    windowHeight = nhigh * box_h + 2 * bwidth + hwidth;
365
    windowHeight = nhigh * box_h + 2 * bwidth + hwidth;
368
    oldWIDTH = WIDTH;
366
    oldWIDTH = WIDTH;
369
    oldHEIGHT = HEIGHT;
367
    oldHEIGHT = HEIGHT;
370
 
368
 
371
    clearwindow();
369
    clearwindow();
372
    deredraw();
370
    deredraw();
373
    /* row/col 1 = pos 0 */
371
    /* row/col 1 = pos 0 */
374
    gchangescrollbar(de, VWINSB, (rowmin - 1)/yScrollbarScale,
372
    gchangescrollbar(de, VWINSB, (rowmin - 1)/yScrollbarScale,
375
		     ymaxused/yScrollbarScale,
373
		     ymaxused/yScrollbarScale,
376
		     max(nhigh/yScrollbarScale, 1), 0);
374
		     max(nhigh/yScrollbarScale, 1), 0);
377
    gchangescrollbar(de, HWINSB, (colmin - 1)/xScrollbarScale,
375
    gchangescrollbar(de, HWINSB, (colmin - 1)/xScrollbarScale,
378
		     xmaxused/xScrollbarScale,
376
		     xmaxused/xScrollbarScale,
379
		     max(nwide/xScrollbarScale, 1), 0);
377
		     max(nwide/xScrollbarScale, 1), 0);
380
}
378
}
381
 
379
 
382
static void doHscroll(int oldcol)
380
static void doHscroll(int oldcol)
383
{
381
{
384
    int i, dw;
382
    int i, dw;
385
    int oldnwide = nwide, oldwindowWidth = windowWidth;
383
    int oldnwide = nwide, oldwindowWidth = windowWidth;
386
 
384
 
387
    /* horizontal re-position */
385
    /* horizontal re-position */
388
    setcellwidths();
386
    setcellwidths();
389
    colmax = colmin + (nwide - 2);
387
    colmax = colmin + (nwide - 2);
390
    if (oldcol < colmin) { /* drop oldcol...colmin - 1 */
388
    if (oldcol < colmin) { /* drop oldcol...colmin - 1 */
391
	dw = boxw[0];
389
	dw = boxw[0];
392
	for (i = oldcol; i < colmin; i++) dw += BOXW(i);
390
	for (i = oldcol; i < colmin; i++) dw += BOXW(i);
393
	copyH(dw, boxw[0], oldwindowWidth - dw + 1);
391
	copyH(dw, boxw[0], oldwindowWidth - dw + 1);
394
	dw = oldwindowWidth - BOXW(oldcol) + 1;
392
	dw = oldwindowWidth - BOXW(oldcol) + 1;
395
	cleararea(dw, hwidth, WIDTH-dw, HEIGHT, p->bg);
393
	cleararea(dw, hwidth, WIDTH-dw, HEIGHT, p->bg);
396
	/* oldnwide includes the row labels */
394
	/* oldnwide includes the row labels */
397
	for (i = oldcol+oldnwide-1; i <= colmax; i++) drawcol(i);
395
	for (i = oldcol+oldnwide-1; i <= colmax; i++) drawcol(i);
398
    } else {
396
    } else {
399
	/* move one or more cols left */
397
	/* move one or more cols left */
400
	dw = BOXW(colmin);
398
	dw = BOXW(colmin);
401
	copyH(boxw[0], boxw[0] + dw, windowWidth - dw + 1);
399
	copyH(boxw[0], boxw[0] + dw, windowWidth - dw + 1);
402
	dw = windowWidth + 1;
400
	dw = windowWidth + 1;
403
	cleararea(dw, hwidth, WIDTH-dw, HEIGHT, p->bg);
401
	cleararea(dw, hwidth, WIDTH-dw, HEIGHT, p->bg);
404
	drawcol(colmin);
402
	drawcol(colmin);
405
    }
403
    }
406
    gchangescrollbar(de, HWINSB, (colmin - 1)/xScrollbarScale,
404
    gchangescrollbar(de, HWINSB, (colmin - 1)/xScrollbarScale,
407
		     xmaxused/xScrollbarScale,
405
		     xmaxused/xScrollbarScale,
408
		     max(nwide/xScrollbarScale, 1), 0);
406
		     max(nwide/xScrollbarScale, 1), 0);
409
    highlightrect();
407
    highlightrect();
410
}
408
}
411
 
409
 
412
/* find_coords finds the coordinates of the upper left corner of the
410
/* find_coords finds the coordinates of the upper left corner of the
413
   given cell on the screen: row and col are on-screen coords */
411
   given cell on the screen: row and col are on-screen coords */
414
 
412
 
415
static void find_coords(int row, int col, int *xcoord, int *ycoord)
413
static void find_coords(int row, int col, int *xcoord, int *ycoord)
416
{
414
{
417
    int i, w;
415
    int i, w;
418
    w = bwidth;
416
    w = bwidth;
419
    if (col > 0) w += boxw[0];
417
    if (col > 0) w += boxw[0];
420
    for(i = 1; i < col; i ++) w += BOXW(i + colmin - 1);
418
    for(i = 1; i < col; i ++) w += BOXW(i + colmin - 1);
421
    *xcoord = w;
419
    *xcoord = w;
422
    *ycoord = bwidth + hwidth + box_h * row;
420
    *ycoord = bwidth + hwidth + box_h * row;
423
}
421
}
424
 
422
 
425
/* draw the window with the top left box at column wcol and row wrow */
423
/* draw the window with the top left box at column wcol and row wrow */
426
 
424
 
427
static void jumpwin(int wcol, int wrow)
425
static void jumpwin(int wcol, int wrow)
428
{
426
{
429
    if (wcol < 0 || wrow < 0) {
427
    if (wcol < 0 || wrow < 0) {
430
	bell();
428
	bell();
431
	return;
429
	return;
432
    }
430
    }
433
    closerect();
431
    closerect();
434
    if (colmin != wcol || rowmin != wrow) {
432
    if (colmin != wcol || rowmin != wrow) {
435
	colmin = wcol;
433
	colmin = wcol;
436
	rowmin = wrow;
434
	rowmin = wrow;
437
	deredraw();
435
	deredraw();
438
    } else highlightrect();
436
    } else highlightrect();
439
}
437
}
440
 
438
 
441
static void advancerect(int which)
439
static void advancerect(int which)
442
{
440
{
443
 
441
 
444
    /* if we are in the header, changing a name then only down is
442
    /* if we are in the header, changing a name then only down is
445
       allowed */
443
       allowed */
446
    if (crow < 1 && which != DOWN) {
444
    if (crow < 1 && which != DOWN) {
447
	bell();
445
	bell();
448
	return;
446
	return;
449
    }
447
    }
450
 
448
 
451
    closerect();
449
    closerect();
452
 
450
 
453
    switch (which) {
451
    switch (which) {
454
    case UP:
452
    case UP:
455
	if (crow == 1) {
453
	if (crow == 1) {
456
	    if (rowmin == 1)
454
	    if (rowmin == 1)
457
		bell();
455
		bell();
458
	    else
456
	    else
459
		jumppage(UP);
457
		jumppage(UP);
460
	} else
458
	} else
461
	    crow--;
459
	    crow--;
462
	break;
460
	break;
463
    case DOWN:
461
    case DOWN:
464
	if (crow == (nhigh - 1))
462
	if (crow == (nhigh - 1))
465
	    jumppage(DOWN);
463
	    jumppage(DOWN);
466
	else
464
	else
467
	    crow++;
465
	    crow++;
468
	break;
466
	break;
469
    case RIGHT:
467
    case RIGHT:
470
	if (ccol == (nwide - 1))
468
	if (ccol == (nwide - 1))
471
	    jumppage(RIGHT);
469
	    jumppage(RIGHT);
472
	else
470
	else
473
	    ccol++;
471
	    ccol++;
474
	break;
472
	break;
475
    case LEFT:
473
    case LEFT:
476
	if (ccol == 1) {
474
	if (ccol == 1) {
477
	    if (colmin == 1)
475
	    if (colmin == 1)
478
		bell();
476
		bell();
479
	    else
477
	    else
480
		jumppage(LEFT);
478
		jumppage(LEFT);
481
	} else
479
	} else
482
	    ccol--;
480
	    ccol--;
483
	break;
481
	break;
484
    default:
482
    default:
485
	UNIMPLEMENTED("advancerect");
483
	UNIMPLEMENTED("advancerect");
486
    }
484
    }
487
 
485
 
488
    highlightrect();
486
    highlightrect();
489
}
487
}
490
 
488
 
491
static char *get_col_name(int col)
489
static char *get_col_name(int col)
492
{
490
{
493
    static char clab[25];
491
    static char clab[25];
494
    if (col <= xmaxused) {
492
    if (col <= xmaxused) {
495
	/* don't use NA labels */
493
	/* don't use NA labels */
496
	SEXP tmp = STRING_ELT(names, col - 1);
494
	SEXP tmp = STRING_ELT(names, col - 1);
497
	if(tmp != NA_STRING) return(CHAR(tmp));
495
	if(tmp != NA_STRING) return(CHAR(tmp));
498
    }
496
    }
499
    sprintf(clab, "var%d", col);
497
    sprintf(clab, "var%d", col);
500
    return clab;
498
    return clab;
501
}
499
}
502
 
500
 
503
static int get_col_width(int col)
501
static int get_col_width(int col)
504
{
502
{
505
    int i, w = 0, w1, fw = FIELDWIDTH;
503
    int i, w = 0, w1, fw = FIELDWIDTH;
506
    char *strp;
504
    char *strp;
507
    SEXP tmp, lab;
505
    SEXP tmp, lab;
508
 
506
 
509
    if (nboxchars > 0) return nboxchars;
507
    if (nboxchars > 0) return nboxchars;
510
    if (col <= xmaxused) {
508
    if (col <= xmaxused) {
511
	tmp = VECTOR_ELT(work, col - 1);
509
	tmp = VECTOR_ELT(work, col - 1);
512
	if (isNull(tmp)) return fw;
510
	if (isNull(tmp)) return fw;
513
	/* don't use NA labels */
511
	/* don't use NA labels */
514
	lab = STRING_ELT(names, col - 1);
512
	lab = STRING_ELT(names, col - 1);
515
	if(lab != NA_STRING) w = strlen(CHAR(lab)); else w = fw;
513
	if(lab != NA_STRING) w = strlen(CHAR(lab)); else w = fw;
516
	PrintDefaults(R_NilValue);
514
	PrintDefaults(R_NilValue);
517
	for (i = 0; i < INTEGER(lens)[col - 1]; i++) {
515
	for (i = 0; i < INTEGER(lens)[col - 1]; i++) {
518
	    strp = EncodeElement(tmp, i, 0, '.');
516
	    strp = EncodeElement(tmp, i, 0, '.');
519
	    w1 = strlen(strp);
517
	    w1 = strlen(strp);
520
	    if (w1 > w) w = w1;
518
	    if (w1 > w) w = w1;
521
	}
519
	}
522
	if(w < 5) w = 5;
520
	if(w < 5) w = 5;
523
	if(w < 8) w++;
521
	if(w < 8) w++;
524
	if(w > 50) w = 50;
522
	if(w > 50) w = 50;
525
	return w;
523
	return w;
526
    }
524
    }
527
    return fw;
525
    return fw;
528
}
526
}
529
 
527
 
530
static CellType get_col_type(int col)
528
static CellType get_col_type(int col)
531
{
529
{
532
    SEXP tmp;
530
    SEXP tmp;
533
    CellType res = UNKNOWNN;
531
    CellType res = UNKNOWNN;
534
 
532
 
535
    if (col <= xmaxused) {
533
    if (col <= xmaxused) {
536
	tmp = VECTOR_ELT(work, col - 1);
534
	tmp = VECTOR_ELT(work, col - 1);
537
	if(TYPEOF(tmp) == REALSXP) res = NUMERIC;
535
	if(TYPEOF(tmp) == REALSXP) res = NUMERIC;
538
	if(TYPEOF(tmp) == STRSXP) res = CHARACTER;
536
	if(TYPEOF(tmp) == STRSXP) res = CHARACTER;
539
    }
537
    }
540
    return res;
538
    return res;
541
}
539
}
542
 
540
 
543
 
541
 
544
/* whichcol is absolute col no, col is position on screen */
542
/* whichcol is absolute col no, col is position on screen */
545
static void drawcol(int whichcol)
543
static void drawcol(int whichcol)
546
{
544
{
547
    int i, src_x, src_y, len, col = whichcol - colmin + 1, bw = BOXW(whichcol);
545
    int i, src_x, src_y, len, col = whichcol - colmin + 1, bw = BOXW(whichcol);
548
    char *clab;
546
    char *clab;
549
    SEXP tmp;
547
    SEXP tmp;
550
 
548
 
551
    find_coords(0, col, &src_x, &src_y);
549
    find_coords(0, col, &src_x, &src_y);
552
    cleararea(src_x, src_y, bw, windowHeight, p->bg);
550
    cleararea(src_x, src_y, bw, windowHeight, p->bg);
553
    cleararea(src_x, src_y, bw, box_h, bbg);
551
    cleararea(src_x, src_y, bw, box_h, bbg);
554
    for (i = 0; i < nhigh; i++)
552
    for (i = 0; i < nhigh; i++)
555
	drawrectangle(src_x, hwidth + i * box_h, bw, box_h, 1, 1);
553
	drawrectangle(src_x, hwidth + i * box_h, bw, box_h, 1, 1);
556
 
554
 
557
    /* now fill it in if it is active */
555
    /* now fill it in if it is active */
558
    clab = get_col_name(whichcol);
556
    clab = get_col_name(whichcol);
559
    printstring(clab, strlen(clab), 0, col, 0);
557
    printstring(clab, strlen(clab), 0, col, 0);
560
 
558
 
561
   if (xmaxused >= whichcol) {
559
   if (xmaxused >= whichcol) {
562
	tmp = VECTOR_ELT(work, whichcol - 1);
560
	tmp = VECTOR_ELT(work, whichcol - 1);
563
	if (!isNull(tmp)) {
561
	if (!isNull(tmp)) {
564
	    len = min(rowmax, INTEGER(lens)[whichcol - 1]);
562
	    len = min(rowmax, INTEGER(lens)[whichcol - 1]);
565
	    for (i = (rowmin - 1); i < len; i++)
563
	    for (i = (rowmin - 1); i < len; i++)
566
		printelt(tmp, i, i - rowmin + 2, col);
564
		printelt(tmp, i, i - rowmin + 2, col);
567
	}
565
	}
568
    }
566
    }
569
}
567
}
570
 
568
 
571
 
569
 
572
/* whichrow is absolute row no */
570
/* whichrow is absolute row no */
573
static void drawrow(int whichrow)
571
static void drawrow(int whichrow)
574
{
572
{
575
    int i, src_x, src_y, row = whichrow - rowmin + 1, w;
573
    int i, src_x, src_y, row = whichrow - rowmin + 1, w;
576
    char rlab[15];
574
    char rlab[15];
577
    SEXP tvec;
575
    SEXP tvec;
578
 
576
 
579
    find_coords(row, 0, &src_x, &src_y);
577
    find_coords(row, 0, &src_x, &src_y);
580
    cleararea(src_x, src_y, windowWidth, box_h, (whichrow > 0)?p->bg:bbg);
578
    cleararea(src_x, src_y, windowWidth, box_h, (whichrow > 0)?p->bg:bbg);
581
    drawrectangle(src_x, src_y, boxw[0], box_h, 1, 1);
579
    drawrectangle(src_x, src_y, boxw[0], box_h, 1, 1);
582
 
580
 
583
    sprintf(rlab, labform, whichrow);
581
    sprintf(rlab, labform, whichrow);
584
    printstring(rlab, strlen(rlab), row, 0, 0);
582
    printstring(rlab, strlen(rlab), row, 0, 0);
585
 
583
 
586
    w = bwidth + boxw[0];
584
    w = bwidth + boxw[0];
587
    for (i = colmin; i <= colmax; i++) {
585
    for (i = colmin; i <= colmax; i++) {
588
	drawrectangle(w, src_y, BOXW(i), box_h, 1, 1);
586
	drawrectangle(w, src_y, BOXW(i), box_h, 1, 1);
589
	w += BOXW(i);
587
	w += BOXW(i);
590
    }
588
    }
591
 
589
 
592
    for (i = colmin; i <= colmax; i++) {
590
    for (i = colmin; i <= colmax; i++) {
593
	if (i > xmaxused) break;
591
	if (i > xmaxused) break;
594
	if (!isNull(tvec = VECTOR_ELT(work, i - 1)))
592
	if (!isNull(tvec = VECTOR_ELT(work, i - 1)))
595
	    if (whichrow <= INTEGER(lens)[i - 1])
593
	    if (whichrow <= INTEGER(lens)[i - 1])
596
		printelt(tvec, whichrow - 1, row, i - colmin + 1);
594
		printelt(tvec, whichrow - 1, row, i - colmin + 1);
597
    }
595
    }
598
}
596
}
599
 
597
 
600
/* printelt: print the correct value from vector[vrow] into the
598
/* printelt: print the correct value from vector[vrow] into the
601
   spreadsheet in row ssrow and col sscol */
599
   spreadsheet in row ssrow and col sscol */
602
 
600
 
603
/* WARNING: This has no check that you're not beyond the end of the
601
/* WARNING: This has no check that you're not beyond the end of the
604
   vector. Caller must check. */
602
   vector. Caller must check. */
605
 
603
 
606
static void printelt(SEXP invec, int vrow, int ssrow, int sscol)
604
static void printelt(SEXP invec, int vrow, int ssrow, int sscol)
607
{
605
{
608
    char *strp;
606
    char *strp;
609
    PrintDefaults(R_NilValue);
607
    PrintDefaults(R_NilValue);
610
    if (TYPEOF(invec) == REALSXP) {
608
    if (TYPEOF(invec) == REALSXP) {
611
	if (REAL(invec)[vrow] != ssNA_REAL) {
609
	if (REAL(invec)[vrow] != ssNA_REAL) {
612
	    strp = EncodeElement(invec, vrow, 0, '.');
610
	    strp = EncodeElement(invec, vrow, 0, '.');
613
	    printstring(strp, strlen(strp), ssrow, sscol, 0);
611
	    printstring(strp, strlen(strp), ssrow, sscol, 0);
614
	}
612
	}
615
    }
613
    }
616
    else if (TYPEOF(invec) == STRSXP) {
614
    else if (TYPEOF(invec) == STRSXP) {
617
	if (!streql(CHAR(STRING_ELT(invec, vrow)),
615
	if (!streql(CHAR(STRING_ELT(invec, vrow)),
618
		    CHAR(STRING_ELT(ssNA_STRING, 0)))) {
616
		    CHAR(STRING_ELT(ssNA_STRING, 0)))) {
619
	    strp = EncodeElement(invec, vrow, 0, '.');
617
	    strp = EncodeElement(invec, vrow, 0, '.');
620
	    printstring(strp, strlen(strp), ssrow, sscol, 0);
618
	    printstring(strp, strlen(strp), ssrow, sscol, 0);
621
	}
619
	}
622
    }
620
    }
623
    else
621
    else
624
	error(G_("dataentry: internal memory error"));
622
	error(G_("dataentry: internal memory error"));
625
}
623
}
626
 
624
 
627
 
625
 
628
static void drawelt(int whichrow, int whichcol)
626
static void drawelt(int whichrow, int whichcol)
629
{
627
{
630
    int i;
628
    int i;
631
    char *clab;
629
    char *clab;
632
    SEXP tmp;
630
    SEXP tmp;
633
 
631
 
634
    if (whichrow == 0) {
632
    if (whichrow == 0) {
635
	clab = get_col_name(whichcol + colmin - 1);
633
	clab = get_col_name(whichcol + colmin - 1);
636
	printstring(clab, strlen(clab), 0, whichcol, 0);
634
	printstring(clab, strlen(clab), 0, whichcol, 0);
637
    } else {
635
    } else {
638
	if (xmaxused >= whichcol + colmin - 1) {
636
	if (xmaxused >= whichcol + colmin - 1) {
639
	    tmp = VECTOR_ELT(work, whichcol + colmin - 2);
637
	    tmp = VECTOR_ELT(work, whichcol + colmin - 2);
640
	    if (!isNull(tmp) && (i = rowmin + whichrow - 2) <
638
	    if (!isNull(tmp) && (i = rowmin + whichrow - 2) <
641
		INTEGER(lens)[whichcol + colmin - 2] )
639
		INTEGER(lens)[whichcol + colmin - 2] )
642
		printelt(tmp, i, whichrow, whichcol);
640
		printelt(tmp, i, whichrow, whichcol);
643
	} else
641
	} else
644
	    printstring("", 0, whichrow,  whichcol, 0);
642
	    printstring("", 0, whichrow,  whichcol, 0);
645
    }
643
    }
646
}
644
}
647
 
645
 
648
static void jumppage(int dir)
646
static void jumppage(int dir)
649
{
647
{
650
    int i, w, oldcol, wcol;
648
    int i, w, oldcol, wcol;
651
 
649
 
652
    switch (dir) {
650
    switch (dir) {
653
    case UP:
651
    case UP:
654
	rowmin--;
652
	rowmin--;
655
	rowmax--;
653
	rowmax--;
656
	copyarea(0, hwidth + box_h, 0, hwidth + 2 * box_h);
654
	copyarea(0, hwidth + box_h, 0, hwidth + 2 * box_h);
657
	drawrow(rowmin);
655
	drawrow(rowmin);
658
	gchangescrollbar(de, VWINSB, (rowmin - 1)/yScrollbarScale,
656
	gchangescrollbar(de, VWINSB, (rowmin - 1)/yScrollbarScale,
659
			 ymaxused/yScrollbarScale,
657
			 ymaxused/yScrollbarScale,
660
			 max(nhigh/yScrollbarScale, 1), 0);
658
			 max(nhigh/yScrollbarScale, 1), 0);
661
	break;
659
	break;
662
    case DOWN:
660
    case DOWN:
663
	if (rowmax >= 65535) return;
661
	if (rowmax >= 65535) return;
664
	rowmin++;
662
	rowmin++;
665
	rowmax++;
663
	rowmax++;
666
	copyarea(0, hwidth + 2 * box_h, 0, hwidth + box_h);
664
	copyarea(0, hwidth + 2 * box_h, 0, hwidth + box_h);
667
	drawrow(rowmax);
665
	drawrow(rowmax);
668
	gchangescrollbar(de, VWINSB, (rowmin - 1)/yScrollbarScale,
666
	gchangescrollbar(de, VWINSB, (rowmin - 1)/yScrollbarScale,
669
			 ymaxused/yScrollbarScale,
667
			 ymaxused/yScrollbarScale,
670
			 max(nhigh/yScrollbarScale, 1), 0);
668
			 max(nhigh/yScrollbarScale, 1), 0);
671
	break;
669
	break;
672
    case LEFT:
670
    case LEFT:
673
	colmin--;
671
	colmin--;
674
	doHscroll(colmin+1);
672
	doHscroll(colmin+1);
675
	break;
673
	break;
676
    case RIGHT:
674
    case RIGHT:
677
	oldcol = colmin;
675
	oldcol = colmin;
678
	wcol = colmin + ccol + 1; /* column to be selected */
676
	wcol = colmin + ccol + 1; /* column to be selected */
679
        /* There may not be room to fit the next column in */
677
        /* There may not be room to fit the next column in */
680
	w = WIDTH - boxw[0] - BOXW(colmax + 1);
678
	w = WIDTH - boxw[0] - BOXW(colmax + 1);
681
	for (i = colmax; i >= oldcol; i--) {
679
	for (i = colmax; i >= oldcol; i--) {
682
	    w -= BOXW(i);
680
	    w -= BOXW(i);
683
	    if(w < 0) {
681
	    if(w < 0) {
684
		colmin = i + 1;
682
		colmin = i + 1;
685
		break;
683
		break;
686
	    }
684
	    }
687
	}
685
	}
688
	ccol = wcol - colmin;
686
	ccol = wcol - colmin;
689
	doHscroll(oldcol);
687
	doHscroll(oldcol);
690
	break;
688
	break;
691
    }
689
    }
692
}
690
}
693
/* draw a rectangle, used to highlight/downlight the current box */
691
/* draw a rectangle, used to highlight/downlight the current box */
694
 
692
 
695
static void printrect(int lwd, int fore)
693
static void printrect(int lwd, int fore)
696
{
694
{
697
    int x, y;
695
    int x, y;
698
    find_coords(crow, ccol, &x, &y);
696
    find_coords(crow, ccol, &x, &y);
699
    drawrectangle(x + lwd - 1, y + lwd - 1,
697
    drawrectangle(x + lwd - 1, y + lwd - 1,
700
		  BOXW(ccol+colmin-1) - lwd + 1,
698
		  BOXW(ccol+colmin-1) - lwd + 1,
701
		  box_h - lwd + 1, lwd, fore);
699
		  box_h - lwd + 1, lwd, fore);
702
}
700
}
703
 
701
 
704
static void downlightrect(void)
702
static void downlightrect(void)
705
{
703
{
706
    printrect(2, 0);
704
    printrect(2, 0);
707
    printrect(1, 1);
705
    printrect(1, 1);
708
}
706
}
709
 
707
 
710
static void highlightrect(void)
708
static void highlightrect(void)
711
{
709
{
712
    printrect(2, 1);
710
    printrect(2, 1);
713
}
711
}
714
 
712
 
715
 
713
 
716
static void getccol()
714
static void getccol()
717
{
715
{
718
    SEXP tmp, tmp2;
716
    SEXP tmp, tmp2;
719
    int i, len, newlen, wcol, wrow;
717
    int i, len, newlen, wcol, wrow;
720
    SEXPTYPE type;
718
    SEXPTYPE type;
721
    char clab[25];
719
    char clab[25];
722
 
720
 
723
    wcol = ccol + colmin - 1;
721
    wcol = ccol + colmin - 1;
724
    wrow = crow + rowmin - 1;
722
    wrow = crow + rowmin - 1;
725
    if (wcol > xmaxused) {
723
    if (wcol > xmaxused) {
726
	/* extend work, names and lens */
724
	/* extend work, names and lens */
727
	REPROTECT(work = lengthgets(work, wcol), wpi);
725
	REPROTECT(work = lengthgets(work, wcol), wpi);
728
	REPROTECT(names = lengthgets(names, wcol), npi);
726
	REPROTECT(names = lengthgets(names, wcol), npi);
729
	for (i = xmaxused; i < wcol; i++) {
727
	for (i = xmaxused; i < wcol; i++) {
730
	    sprintf(clab, "var%d", i + 1);
728
	    sprintf(clab, "var%d", i + 1);
731
	    SET_STRING_ELT(names, i, mkChar(clab));
729
	    SET_STRING_ELT(names, i, mkChar(clab));
732
	}
730
	}
733
	REPROTECT(lens = lengthgets(lens, wcol), lpi);
731
	REPROTECT(lens = lengthgets(lens, wcol), lpi);
734
	xmaxused = wcol;
732
	xmaxused = wcol;
735
    }
733
    }
736
    newcol = FALSE;
734
    newcol = FALSE;
737
    if (isNull(VECTOR_ELT(work, wcol - 1))) {
735
    if (isNull(VECTOR_ELT(work, wcol - 1))) {
738
	newcol = TRUE;
736
	newcol = TRUE;
739
	SET_VECTOR_ELT(work, wcol - 1, ssNewVector(REALSXP, max(100, wrow)));
737
	SET_VECTOR_ELT(work, wcol - 1, ssNewVector(REALSXP, max(100, wrow)));
740
	INTEGER(lens)[wcol - 1] = 0;
738
	INTEGER(lens)[wcol - 1] = 0;
741
    }
739
    }
742
    if (!isVector(tmp = VECTOR_ELT(work, wcol - 1)))
740
    if (!isVector(tmp = VECTOR_ELT(work, wcol - 1)))
743
	error(G_("internal type error in dataentry"));
741
	error(G_("internal type error in dataentry"));
744
    len = INTEGER(lens)[wcol - 1];
742
    len = INTEGER(lens)[wcol - 1];
745
    type = TYPEOF(tmp);
743
    type = TYPEOF(tmp);
746
    if (len < wrow) {
744
    if (len < wrow) {
747
	for (newlen = max(len * 2, 10) ; newlen < wrow ; newlen *= 2)
745
	for (newlen = max(len * 2, 10) ; newlen < wrow ; newlen *= 2)
748
	    ;
746
	    ;
749
	tmp2 = ssNewVector(type, newlen);
747
	tmp2 = ssNewVector(type, newlen);
750
	for (i = 0; i < len; i++)
748
	for (i = 0; i < len; i++)
751
	    if (type == REALSXP)
749
	    if (type == REALSXP)
752
		REAL(tmp2)[i] = REAL(tmp)[i];
750
		REAL(tmp2)[i] = REAL(tmp)[i];
753
	    else if (type == STRSXP)
751
	    else if (type == STRSXP)
754
		SET_STRING_ELT(tmp2, i, STRING_ELT(tmp, i));
752
		SET_STRING_ELT(tmp2, i, STRING_ELT(tmp, i));
755
	    else
753
	    else
756
		error(G_("internal type error in dataentry"));
754
		error(G_("internal type error in dataentry"));
757
	SET_VECTOR_ELT(work, wcol - 1, tmp2);
755
	SET_VECTOR_ELT(work, wcol - 1, tmp2);
758
    }
756
    }
759
}
757
}
760
 
758
 
761
/* close up the entry to a cell, put the value that has been entered
759
/* close up the entry to a cell, put the value that has been entered
762
   into the correct place and as the correct type */
760
   into the correct place and as the correct type */
763
 
761
 
764
static void closerect(void)
762
static void closerect(void)
765
{
763
{
766
    SEXP cvec;
764
    SEXP cvec;
767
    int wcol = ccol + colmin - 1, wrow = rowmin + crow - 1, wrow0;
765
    int wcol = ccol + colmin - 1, wrow = rowmin + crow - 1, wrow0;
768
 
766
 
769
    *bufp = '\0';
767
    *bufp = '\0';
770
 
768
 
771
    if (CellModified || CellEditable) {
769
    if (CellModified || CellEditable) {
772
	if (CellEditable) {
770
	if (CellEditable) {
773
	    strcpy(buf, gettext(celledit));
771
	    strcpy(buf, gettext(celledit));
774
	    clength = strlen(buf);
772
	    clength = strlen(buf);
775
	    hide(celledit);
773
	    hide(celledit);
776
	    del(celledit);
774
	    del(celledit);
777
	}
775
	}
778
	getccol();
776
	getccol();
779
	cvec = VECTOR_ELT(work, wcol - 1);
777
	cvec = VECTOR_ELT(work, wcol - 1);
780
	wrow0 = INTEGER(lens)[wcol - 1];
778
	wrow0 = INTEGER(lens)[wcol - 1];
781
	if (wrow > wrow0) INTEGER(lens)[wcol - 1] = wrow;
779
	if (wrow > wrow0) INTEGER(lens)[wcol - 1] = wrow;
782
	ymaxused = max(ymaxused, wrow);
780
	ymaxused = max(ymaxused, wrow);
783
	if (clength != 0) {
781
	if (clength != 0) {
784
	    /* do it this way to ensure NA, Inf, ...  can get set */
782
	    /* do it this way to ensure NA, Inf, ...  can get set */
785
	    char *endp;
783
	    char *endp;
786
	    double new = R_strtod(buf, &endp);
784
	    double new = R_strtod(buf, &endp);
787
	    int warn = !isBlankString(endp);
785
	    int warn = !isBlankString(endp);
788
	    if (TYPEOF(cvec) == STRSXP)
786
	    if (TYPEOF(cvec) == STRSXP)
789
		SET_STRING_ELT(cvec, wrow - 1, mkChar(buf));
787
		SET_STRING_ELT(cvec, wrow - 1, mkChar(buf));
790
	    else
788
	    else
791
		REAL(cvec)[wrow - 1] = new;
789
		REAL(cvec)[wrow - 1] = new;
792
	    if (newcol & warn) {
790
	    if (newcol & warn) {
793
		/* change mode to character */
791
		/* change mode to character */
794
		SET_VECTOR_ELT(work, wcol - 1, coerceVector(cvec, STRSXP));
792
		SET_VECTOR_ELT(work, wcol - 1, coerceVector(cvec, STRSXP));
795
		SET_STRING_ELT(VECTOR_ELT(work, wcol - 1), wrow - 1,
793
		SET_STRING_ELT(VECTOR_ELT(work, wcol - 1), wrow - 1,
796
			       mkChar(buf));
794
			       mkChar(buf));
797
	    }
795
	    }
798
	} else {
796
	} else {
799
	    if (TYPEOF(cvec) == STRSXP)
797
	    if (TYPEOF(cvec) == STRSXP)
800
		SET_STRING_ELT(cvec, wrow - 1, NA_STRING);
798
		SET_STRING_ELT(cvec, wrow - 1, NA_STRING);
801
	    else
799
	    else
802
		REAL(cvec)[wrow - 1] = NA_REAL;
800
		REAL(cvec)[wrow - 1] = NA_REAL;
803
	}
801
	}
804
	drawelt(crow, ccol);  /* to get the cell scrolling right */
802
	drawelt(crow, ccol);  /* to get the cell scrolling right */
805
	if(wrow > wrow0) drawcol(wcol); /* to fill in NAs */
803
	if(wrow > wrow0) drawcol(wcol); /* to fill in NAs */
806
    }
804
    }
807
    CellEditable = CellModified = FALSE;
805
    CellEditable = CellModified = FALSE;
808
 
806
 
809
    downlightrect();
807
    downlightrect();
810
    gsetcursor(de, ArrowCursor);
808
    gsetcursor(de, ArrowCursor);
811
 
809
 
812
    ndecimal = 0;
810
    ndecimal = 0;
813
    nneg = 0;
811
    nneg = 0;
814
    ne = 0;
812
    ne = 0;
815
    currentexp = 0;
813
    currentexp = 0;
816
    clength = 0;
814
    clength = 0;
817
    bufp = buf;
815
    bufp = buf;
818
}
816
}
819
 
817
 
820
/* print a null terminated string, check to see if it is longer than
818
/* print a null terminated string, check to see if it is longer than
821
   the print area and print it, left adjusted if necessary; clear the
819
   the print area and print it, left adjusted if necessary; clear the
822
   area of previous text; */
820
   area of previous text; */
823
 
821
 
824
/* This version will only display 200 chars, but the maximum col width
822
/* This version will only display 200 chars, but the maximum col width
825
   will not allow that many */
823
   will not allow that many */
826
static void printstring(char *ibuf, int buflen, int row, int col, int left)
824
static void printstring(char *ibuf, int buflen, int row, int col, int left)
827
{
825
{
828
    int x_pos, y_pos, bw, fw, bufw;
826
    int x_pos, y_pos, bw, fw, bufw;
829
    char buf[201];
827
    char buf[201];
830
 
828
 
831
    find_coords(row, col, &x_pos, &y_pos);
829
    find_coords(row, col, &x_pos, &y_pos);
832
    if (col == 0) bw = boxw[0]; else bw = BOXW(col+colmin-1);
830
    if (col == 0) bw = boxw[0]; else bw = BOXW(col+colmin-1);
833
    cleararea(x_pos + 1, y_pos + 1, bw - 1, box_h - 1,
831
    cleararea(x_pos + 1, y_pos + 1, bw - 1, box_h - 1,
834
	      (row==0 || col==0) ? bbg:p->bg);
832
	      (row==0 || col==0) ? bbg:p->bg);
835
    fw = min(200, (bw - 8)/FW);
833
    fw = min(200, (bw - 8)/FW);
836
    bufw = min(fw, buflen);
834
    bufw = min(fw, buflen);
837
    strncpy(buf, ibuf, bufw);
835
    strncpy(buf, ibuf, bufw);
838
    buf[bufw] = '\0';
836
    buf[bufw] = '\0';
839
    if (buflen > fw) {
837
    if (buflen > fw) {
840
	if(left) {
838
	if(left) {
841
	    strncpy(buf, ibuf + buflen - fw, fw);
839
	    strncpy(buf, ibuf + buflen - fw, fw);
842
	    buf[fw] = '\0';
840
	    buf[fw] = '\0';
843
	    *buf = '<';
841
	    *buf = '<';
844
	} else {
842
	} else {
845
	    *(buf + fw - 1) = '>';
843
	    *(buf + fw - 1) = '>';
846
	    *(buf + fw) = '\0';
844
	    *(buf + fw) = '\0';
847
	}
845
	}
848
    }
846
    }
849
    de_drawtext(x_pos + text_xoffset, y_pos - text_yoffset, buf);
847
    de_drawtext(x_pos + text_xoffset, y_pos - text_yoffset, buf);
850
}
848
}
851
 
849
 
852
static void clearrect(void)
850
static void clearrect(void)
853
{
851
{
854
    int x_pos, y_pos;
852
    int x_pos, y_pos;
855
 
853
 
856
    find_coords(crow, ccol, &x_pos, &y_pos);
854
    find_coords(crow, ccol, &x_pos, &y_pos);
857
    cleararea(x_pos, y_pos, BOXW(ccol+colmin-1), box_h, p->bg);
855
    cleararea(x_pos, y_pos, BOXW(ccol+colmin-1), box_h, p->bg);
858
}
856
}
859
 
857
 
860
/* handlechar has to be able to parse decimal numbers and strings,
858
/* handlechar has to be able to parse decimal numbers and strings,
861
   depending on the current column type, only printing characters
859
   depending on the current column type, only printing characters
862
   should get this far */
860
   should get this far */
863
 
861
 
864
/* --- Not true! E.g. ESC ends up in here... */
862
/* --- Not true! E.g. ESC ends up in here... */
865
 
863
 
866
static void handlechar(char *text)
864
static void handlechar(char *text)
867
{
865
{
868
    int c = text[0];
866
    int c = text[0];
869
 
867
 
870
    if ( c == '\033' ) {
868
    if ( c == '\033' ) {
871
	CellModified = FALSE;
869
	CellModified = FALSE;
872
	clength = 0;
870
	clength = 0;
873
	drawelt(crow, ccol);
871
	drawelt(crow, ccol);
874
	gsetcursor(de, ArrowCursor);
872
	gsetcursor(de, ArrowCursor);
875
	return;
873
	return;
876
    } else {
874
    } else {
877
	CellModified = TRUE;
875
	CellModified = TRUE;
878
	gsetcursor(de, TextCursor);
876
	gsetcursor(de, TextCursor);
879
    }
877
    }
880
 
878
 
881
    if (clength == 0) {
879
    if (clength == 0) {
882
	switch(get_col_type(ccol + colmin - 1)) {
880
	switch(get_col_type(ccol + colmin - 1)) {
883
	case NUMERIC:
881
	case NUMERIC:
884
	    currentexp = 1;
882
	    currentexp = 1;
885
	    break;
883
	    break;
886
	default:
884
	default:
887
	    currentexp = 2;
885
	    currentexp = 2;
888
	}
886
	}
889
	clearrect();
887
	clearrect();
890
	highlightrect();
888
	highlightrect();
891
    }
889
    }
892
 
890
 
893
    if (currentexp == 1)	/* we are parsing a number */
891
    if (currentexp == 1)	/* we are parsing a number */
894
	switch (c) {
892
	switch (c) {
895
	case '-':
893
	case '-':
896
	    if (nneg == 0)
894
	    if (nneg == 0)
897
		nneg++;
895
		nneg++;
898
	    else
896
	    else
899
		goto donehc;
897
		goto donehc;
900
	    break;
898
	    break;
901
	case '.':
899
	case '.':
902
	    if (ndecimal == 0)
900
	    if (ndecimal == 0)
903
		ndecimal++;
901
		ndecimal++;
904
	    else
902
	    else
905
		goto donehc;
903
		goto donehc;
906
	    break;
904
	    break;
907
	case 'e':
905
	case 'e':
908
	case 'E':
906
	case 'E':
909
	    if (ne == 0) {
907
	    if (ne == 0) {
910
		nneg = ndecimal = 0;	/* might have decimal in exponent */
908
		nneg = ndecimal = 0;	/* might have decimal in exponent */
911
		ne++;
909
		ne++;
912
	    }
910
	    }
913
	    else
911
	    else
914
		goto donehc;
912
		goto donehc;
915
	    break;
913
	    break;
916
	default:
914
	default:
917
	    if (!isdigit((int)text[0]))
915
	    if (!isdigit((int)text[0]))
918
		goto donehc;
916
		goto donehc;
919
	    break;
917
	    break;
920
	}
918
	}
921
 
919
 
922
    if (clength++ > 199) {
920
    if (clength++ > 199) {
923
	warning(G_("dataentry: expression too long"));
921
	warning(G_("dataentry: expression too long"));
924
	clength--;
922
	clength--;
925
	goto donehc;
923
	goto donehc;
926
    }
924
    }
927
 
925
 
928
    *bufp++ = text[0];
926
    *bufp++ = text[0];
929
    printstring(buf, clength, crow, ccol, 1);
927
    printstring(buf, clength, crow, ccol, 1);
930
    return;
928
    return;
931
 
929
 
932
 donehc:
930
 donehc:
933
    bell();
931
    bell();
934
}
932
}
935
 
933
 
936
static void printlabs(void)
934
static void printlabs(void)
937
{
935
{
938
    char clab[15], *p;
936
    char clab[15], *p;
939
    int i;
937
    int i;
940
 
938
 
941
    for (i = colmin; i <= colmax; i++) {
939
    for (i = colmin; i <= colmax; i++) {
942
	p = get_col_name(i);
940
	p = get_col_name(i);
943
	printstring(p, strlen(p), 0, i - colmin + 1, 0);
941
	printstring(p, strlen(p), 0, i - colmin + 1, 0);
944
    }
942
    }
945
    for (i = rowmin; i <= rowmax; i++) {
943
    for (i = rowmin; i <= rowmax; i++) {
946
	sprintf(clab, labform, i);
944
	sprintf(clab, labform, i);
947
	printstring(clab, strlen(clab), i - rowmin + 1, 0, 0);
945
	printstring(clab, strlen(clab), i - rowmin + 1, 0, 0);
948
    }
946
    }
949
}
947
}
950
 
948
 
951
              /* ================ GraphApp-specific ================ */
949
              /* ================ GraphApp-specific ================ */
952
 
950
 
953
static void bell(void)
951
static void bell(void)
954
{
952
{
955
    gabeep();
953
    gabeep();
956
}
954
}
957
 
955
 
958
static void cleararea(int xpos, int ypos, int width, int height, rgb col)
956
static void cleararea(int xpos, int ypos, int width, int height, rgb col)
959
{
957
{
960
    gfillrect(de, col, rect(xpos, ypos, width, height));
958
    gfillrect(de, col, rect(xpos, ypos, width, height));
961
}
959
}
962
 
960
 
963
static void clearwindow(void)
961
static void clearwindow(void)
964
{
962
{
965
    gfillrect(de, p->bg, rect(0, 0, WIDTH, HEIGHT));
963
    gfillrect(de, p->bg, rect(0, 0, WIDTH, HEIGHT));
966
}
964
}
967
 
965
 
968
 
966
 
969
static void drawrectangle(int xpos, int ypos, int width, int height,
967
static void drawrectangle(int xpos, int ypos, int width, int height,
970
			  int lwd, int fore)
968
			  int lwd, int fore)
971
{
969
{
972
    /* only used on screen, so always fast */
970
    /* only used on screen, so always fast */
973
    gdrawrect(de, lwd, 0, (fore==1)? p->ufg: p->bg,
971
    gdrawrect(de, lwd, 0, (fore==1)? p->ufg: p->bg,
974
	      rect(xpos, ypos, width, height), 1, PS_ENDCAP_SQUARE, 
972
	      rect(xpos, ypos, width, height), 1, PS_ENDCAP_SQUARE, 
975
	      PS_JOIN_BEVEL, 10);
973
	      PS_JOIN_BEVEL, 10);
976
}
974
}
977
 
975
 
978
static void de_drawtext(int xpos, int ypos, char *text)
976
static void de_drawtext(int xpos, int ypos, char *text)
979
{
977
{
980
    gdrawstr(de, p->f, p->fg, pt(xpos, ypos), text);
978
    gdrawstr(de, p->f, p->fg, pt(xpos, ypos), text);
981
}
979
}
982
 
980
 
983
/* Keypress callbacks */
981
/* Keypress callbacks */
984
 
982
 
985
static void de_normalkeyin(control c, int k)
983
static void de_normalkeyin(control c, int k)
986
{
984
{
987
    int i, st;
985
    int i, st;
988
    char text[1];
986
    char text[1];
989
 
987
 
990
    st = ggetkeystate();
988
    st = ggetkeystate();
991
    if ((p->chbrk) && (k == p->chbrk) &&
989
    if ((p->chbrk) && (k == p->chbrk) &&
992
	((!p->modbrk) || ((p->modbrk) && (st == p->modbrk)))) {
990
	((!p->modbrk) || ((p->modbrk) && (st == p->modbrk)))) {
993
	p->fbrk(c);
991
	p->fbrk(c);
994
	return;
992
	return;
995
    }
993
    }
996
    if (st & CtrlKey) {
994
    if (st & CtrlKey) {
997
	switch (k + 'A' - 1) {
995
	switch (k + 'A' - 1) {
998
	case 'B':
996
	case 'B':
999
	    i = rowmin - nhigh + 2;
997
	    i = rowmin - nhigh + 2;
1000
	    jumpwin(colmin, max(i, 1));
998
	    jumpwin(colmin, max(i, 1));
1001
	    break;
999
	    break;
1002
	case 'F':
1000
	case 'F':
1003
	    jumpwin(colmin, rowmax);
1001
	    jumpwin(colmin, rowmax);
1004
	    break;
1002
	    break;
1005
	case 'H':
1003
	case 'H':
1006
	    moveback();
1004
	    moveback();
1007
	    break;
1005
	    break;
1008
	case 'I':
1006
	case 'I':
1009
	    if (st & ShiftKey) advancerect(LEFT);
1007
	    if (st & ShiftKey) advancerect(LEFT);
1010
	    else advancerect(RIGHT);
1008
	    else advancerect(RIGHT);
1011
	    break;
1009
	    break;
1012
	case 'N':
1010
	case 'N':
1013
	case 'J':
1011
	case 'J':
1014
	    advancerect(DOWN);
1012
	    advancerect(DOWN);
1015
	    break;
1013
	    break;
1016
	case 'C':
1014
	case 'C':
1017
	    de_copy(de);
1015
	    de_copy(de);
1018
	    break;
1016
	    break;
1019
	case 'V':
1017
	case 'V':
1020
	    de_paste(de);
1018
	    de_paste(de);
1021
	    break;
1019
	    break;
1022
	case 'L':
1020
	case 'L':
1023
	    for (i = colmin; i < colmax; i++)
1021
	    for (i = colmin; i < colmax; i++)
1024
		if (i < 100) boxw[i] = get_col_width(i)*FW + 8;
1022
		if (i < 100) boxw[i] = get_col_width(i)*FW + 8;
1025
	    drawwindow();
1023
	    drawwindow();
1026
	    break;
1024
	    break;
1027
	default:
1025
	default:
1028
	    bell();
1026
	    bell();
1029
	}
1027
	}
1030
    } else if(k == '\b') {
1028
    } else if(k == '\b') {
1031
	moveback();
1029
	moveback();
1032
    } else if(k == '\n' || k == '\r') {
1030
    } else if(k == '\n' || k == '\r') {
1033
	    advancerect(DOWN);
1031
	    advancerect(DOWN);
1034
    } else if(k == '\t') {
1032
    } else if(k == '\t') {
1035
	if (st & ShiftKey) advancerect(LEFT);
1033
	if (st & ShiftKey) advancerect(LEFT);
1036
	else advancerect(RIGHT);
1034
	else advancerect(RIGHT);
1037
    } else {
1035
    } else {
1038
	text[0] = k;
1036
	text[0] = k;
1039
	handlechar(text);
1037
	handlechar(text);
1040
    }
1038
    }
1041
 
1039
 
1042
}
1040
}
1043
 
1041
 
1044
static void de_ctrlkeyin(control c, int key)
1042
static void de_ctrlkeyin(control c, int key)
1045
{
1043
{
1046
    int st, i;
1044
    int st, i;
1047
 
1045
 
1048
    st = ggetkeystate();
1046
    st = ggetkeystate();
1049
    if ((p->chbrk) && (key == p->chbrk) &&
1047
    if ((p->chbrk) && (key == p->chbrk) &&
1050
	((!p->modbrk) || ((p->modbrk) && (st == p->modbrk)))) {
1048
	((!p->modbrk) || ((p->modbrk) && (st == p->modbrk)))) {
1051
	p->fbrk(c);
1049
	p->fbrk(c);
1052
	return;
1050
	return;
1053
    }
1051
    }
1054
    switch (key) {
1052
    switch (key) {
1055
    case HOME:
1053
    case HOME:
1056
	jumpwin(1, 1);
1054
	jumpwin(1, 1);
1057
	downlightrect();
1055
	downlightrect();
1058
	crow = ccol = 1;
1056
	crow = ccol = 1;
1059
	highlightrect();
1057
	highlightrect();
1060
	break;
1058
	break;
1061
    case END:
1059
    case END:
1062
	i = ymaxused - nhigh + 2;
1060
	i = ymaxused - nhigh + 2;
1063
	jumpwin(xmaxused, max(i, 1));
1061
	jumpwin(xmaxused, max(i, 1));
1064
	downlightrect();
1062
	downlightrect();
1065
	crow = ymaxused - rowmin + 1;
1063
	crow = ymaxused - rowmin + 1;
1066
	ccol = 1;
1064
	ccol = 1;
1067
	highlightrect();
1065
	highlightrect();
1068
	break;
1066
	break;
1069
    case PGUP:
1067
    case PGUP:
1070
	i = rowmin - nhigh + 2;
1068
	i = rowmin - nhigh + 2;
1071
	jumpwin(colmin, max(i, 1));
1069
	jumpwin(colmin, max(i, 1));
1072
	break;
1070
	break;
1073
    case PGDN:
1071
    case PGDN:
1074
	jumpwin(colmin, rowmax);
1072
	jumpwin(colmin, rowmax);
1075
	break;
1073
	break;
1076
    case LEFT:
1074
    case LEFT:
1077
	advancerect(LEFT);
1075
	advancerect(LEFT);
1078
	break;
1076
	break;
1079
    case RIGHT:
1077
    case RIGHT:
1080
	advancerect(RIGHT);
1078
	advancerect(RIGHT);
1081
	break;
1079
	break;
1082
    case UP:
1080
    case UP:
1083
	advancerect(UP);
1081
	advancerect(UP);
1084
	break;
1082
	break;
1085
    case DOWN:
1083
    case DOWN:
1086
	advancerect(DOWN);
1084
	advancerect(DOWN);
1087
	break;
1085
	break;
1088
    case DEL:
1086
    case DEL:
1089
	moveback();
1087
	moveback();
1090
	break;
1088
	break;
1091
     case ENTER:
1089
     case ENTER:
1092
	 advancerect(DOWN);
1090
	 advancerect(DOWN);
1093
	 break;
1091
	 break;
1094
    default:
1092
    default:
1095
	;
1093
	;
1096
    }
1094
    }
1097
}
1095
}
1098
 
1096
 
1099
/* mouse callbacks */
1097
/* mouse callbacks */
1100
 
1098
 
1101
static char *get_cell_text(void)
1099
static char *get_cell_text(void)
1102
{
1100
{
1103
    int  wrow = rowmin + crow - 2, wcol = colmin + ccol - 1;
1101
    int  wrow = rowmin + crow - 2, wcol = colmin + ccol - 1;
1104
    char *prev = "";
1102
    char *prev = "";
1105
    SEXP tvec;
1103
    SEXP tvec;
1106
 
1104
 
1107
    if (wcol <= xmaxused) {
1105
    if (wcol <= xmaxused) {
1108
	tvec = VECTOR_ELT(work, wcol - 1);
1106
	tvec = VECTOR_ELT(work, wcol - 1);
1109
	if (!isNull(tvec) && wrow < INTEGER(lens)[wcol - 1]) {
1107
	if (!isNull(tvec) && wrow < INTEGER(lens)[wcol - 1]) {
1110
	    PrintDefaults(R_NilValue);
1108
	    PrintDefaults(R_NilValue);
1111
	    if (TYPEOF(tvec) == REALSXP) {
1109
	    if (TYPEOF(tvec) == REALSXP) {
1112
		if (REAL(tvec)[wrow] != ssNA_REAL)
1110
		if (REAL(tvec)[wrow] != ssNA_REAL)
1113
		    prev = EncodeElement(tvec, wrow, 0, '.');
1111
		    prev = EncodeElement(tvec, wrow, 0, '.');
1114
	    } else if (TYPEOF(tvec) == STRSXP) {
1112
	    } else if (TYPEOF(tvec) == STRSXP) {
1115
		if (!streql(CHAR(STRING_ELT(tvec, wrow)),
1113
		if (!streql(CHAR(STRING_ELT(tvec, wrow)),
1116
			    CHAR(STRING_ELT(ssNA_STRING, 0))))
1114
			    CHAR(STRING_ELT(ssNA_STRING, 0))))
1117
		    prev = EncodeElement(tvec, wrow, 0, '.');
1115
		    prev = EncodeElement(tvec, wrow, 0, '.');
1118
	    } else error(G_("dataentry: internal memory error"));
1116
	    } else error(G_("dataentry: internal memory error"));
1119
	}
1117
	}
1120
    }
1118
    }
1121
    return prev;
1119
    return prev;
1122
}
1120
}
1123
 
1121
 
1124
static int online, clickline;
1122
static int online, clickline;
1125
 
1123
 
1126
static void de_mousedown(control c, int buttons, point xy)
1124
static void de_mousedown(control c, int buttons, point xy)
1127
{
1125
{
1128
    int xw, yw, wcol=0, wrow, i, w;
1126
    int xw, yw, wcol=0, wrow, i, w;
1129
 
1127
 
1130
    if (buttons & LeftButton) {
1128
    if (buttons & LeftButton) {
1131
	xw = xy.x;
1129
	xw = xy.x;
1132
	yw = xy.y;
1130
	yw = xy.y;
1133
 
1131
 
1134
	closerect();
1132
	closerect();
1135
 
1133
 
1136
	/* check to see if the click was in the header */
1134
	/* check to see if the click was in the header */
1137
 
1135
 
1138
	if (yw < hwidth + bwidth) {
1136
	if (yw < hwidth + bwidth) {
1139
	    /* too high */
1137
	    /* too high */
1140
	    return;
1138
	    return;
1141
	}
1139
	}
1142
	/* translate to box coordinates */
1140
	/* translate to box coordinates */
1143
 
1141
 
1144
	wrow = (yw - bwidth - hwidth) / box_h;
1142
	wrow = (yw - bwidth - hwidth) / box_h;
1145
 
1143
 
1146
	/* see if it is in the row labels */
1144
	/* see if it is in the row labels */
1147
	if (xw < bwidth + boxw[0]) {
1145
	if (xw < bwidth + boxw[0]) {
1148
	    bell();
1146
	    bell();
1149
	    highlightrect();
1147
	    highlightrect();
1150
	    return;
1148
	    return;
1151
	}
1149
	}
1152
	w = bwidth + boxw[0];
1150
	w = bwidth + boxw[0];
1153
	for (i = 1; i <= nwide; i++)
1151
	for (i = 1; i <= nwide; i++)
1154
	    if((w += BOXW(i+colmin-1)) > xw) {
1152
	    if((w += BOXW(i+colmin-1)) > xw) {
1155
		wcol = i;
1153
		wcol = i;
1156
		break;
1154
		break;
1157
	}
1155
	}
1158
 
1156
 
1159
	/* see if we selected a line */
1157
	/* see if we selected a line */
1160
	w = bwidth;
1158
	w = bwidth;
1161
	online = 0;
1159
	online = 0;
1162
	for (i = 0; i <= nwide; i++) {
1160
	for (i = 0; i <= nwide; i++) {
1163
	    if(i == 0) w += boxw[0]; else w += BOXW(i+colmin-1);
1161
	    if(i == 0) w += boxw[0]; else w += BOXW(i+colmin-1);
1164
	    if (abs(w - xw) <= 2) {
1162
	    if (abs(w - xw) <= 2) {
1165
		online = 1;
1163
		online = 1;
1166
		clickline = i; /* between cols i and i+1 */
1164
		clickline = i; /* between cols i and i+1 */
1167
		highlightrect();
1165
		highlightrect();
1168
		gsetcursor(de, HandCursor);
1166
		gsetcursor(de, HandCursor);
1169
		return;
1167
		return;
1170
	    }
1168
	    }
1171
	}
1169
	}
1172
 
1170
 
1173
	/* next check to see if it is in the column labels */
1171
	/* next check to see if it is in the column labels */
1174
 
1172
 
1175
	if (yw < hwidth + bwidth + box_h) {
1173
	if (yw < hwidth + bwidth + box_h) {
1176
	    if (xw > bwidth + boxw[0]) {
1174
	    if (xw > bwidth + boxw[0]) {
1177
		highlightrect();
1175
		highlightrect();
1178
		de_popupmenu(xw, yw, wcol);
1176
		de_popupmenu(xw, yw, wcol);
1179
		return;
1177
		return;
1180
	    } else {
1178
	    } else {
1181
		/* in 0th column */
1179
		/* in 0th column */
1182
		highlightrect();
1180
		highlightrect();
1183
		bell();
1181
		bell();
1184
	    }
1182
	    }
1185
	} else if (wrow > nhigh - 1 || wcol > nwide - 1) {
1183
	} else if (wrow > nhigh - 1 || wcol > nwide - 1) {
1186
		/* off the grid */
1184
		/* off the grid */
1187
		highlightrect();
1185
		highlightrect();
1188
		bell();
1186
		bell();
1189
		return;
1187
		return;
1190
	} else if (buttons & DblClick) {
1188
	} else if (buttons & DblClick) {
1191
	    int x, y, bw;
1189
	    int x, y, bw;
1192
	    char *prev;
1190
	    char *prev;
1193
	    rect rr;
1191
	    rect rr;
1194
 
1192
 
1195
	    ccol = wcol;
1193
	    ccol = wcol;
1196
	    crow = wrow;
1194
	    crow = wrow;
1197
	    highlightrect();
1195
	    highlightrect();
1198
	    find_coords(crow, ccol, &x, &y);
1196
	    find_coords(crow, ccol, &x, &y);
1199
	    bw = BOXW(ccol + colmin - 1);
1197
	    bw = BOXW(ccol + colmin - 1);
1200
	    rr = rect(x + text_xoffset, y - text_yoffset - 1,
1198
	    rr = rect(x + text_xoffset, y - text_yoffset - 1,
1201
		      bw - text_xoffset - 2,
1199
		      bw - text_xoffset - 2,
1202
		      box_h - text_yoffset - 2);
1200
		      box_h - text_yoffset - 2);
1203
	    prev = get_cell_text();
1201
	    prev = get_cell_text();
1204
	    if (strlen(prev) * FW > bw)
1202
	    if (strlen(prev) * FW > bw)
1205
		rr.width = (strlen(prev) + 2) * FW;
1203
		rr.width = (strlen(prev) + 2) * FW;
1206
	    addto(de);
1204
	    addto(de);
1207
	    celledit = newfield_no_border(prev, rr);
1205
	    celledit = newfield_no_border(prev, rr);
1208
	    setbackground(celledit, p->bg);
1206
	    setbackground(celledit, p->bg);
1209
	    setforeground(celledit, p->ufg);
1207
	    setforeground(celledit, p->ufg);
1210
	    settextfont(celledit, p->f);
1208
	    settextfont(celledit, p->f);
1211
	    show(celledit);
1209
	    show(celledit);
1212
	    CellEditable = TRUE;
1210
	    CellEditable = TRUE;
1213
	} else if (buttons & LeftButton) {
1211
	} else if (buttons & LeftButton) {
1214
	    ccol = wcol;
1212
	    ccol = wcol;
1215
	    crow = wrow;
1213
	    crow = wrow;
1216
	}
1214
	}
1217
	highlightrect();
1215
	highlightrect();
1218
	return;
1216
	return;
1219
    }
1217
    }
1220
}
1218
}
1221
 
1219
 
1222
static void de_mouseup(control c, int buttons, point xy)
1220
static void de_mouseup(control c, int buttons, point xy)
1223
{
1221
{
1224
    int xw, bw, i, w;
1222
    int xw, bw, i, w;
1225
 
1223
 
1226
    if (online) {
1224
    if (online) {
1227
	xw = xy.x;
1225
	xw = xy.x;
1228
	w = bwidth + boxw[0];
1226
	w = bwidth + boxw[0];
1229
	for(i = 1; i < clickline; i++) w+= BOXW(i+colmin-1);
1227
	for(i = 1; i < clickline; i++) w+= BOXW(i+colmin-1);
1230
	bw = xw - w;
1228
	bw = xw - w;
1231
	if (bw < FW*4 + 8) bw = FW*4 + 8;
1229
	if (bw < FW*4 + 8) bw = FW*4 + 8;
1232
	if (bw > FW*50) bw = FW*50;
1230
	if (bw > FW*50) bw = FW*50;
1233
	if(clickline < 100) boxw[clickline] = bw;
1231
	if(clickline < 100) boxw[clickline] = bw;
1234
	gsetcursor(de, ArrowCursor);
1232
	gsetcursor(de, ArrowCursor);
1235
	deredraw();
1233
	deredraw();
1236
    }
1234
    }
1237
}
1235
}
1238
 
1236
 
1239
static void de_redraw(control c, rect r)
1237
static void de_redraw(control c, rect r)
1240
{
1238
{
1241
    if (WIDTH != oldWIDTH || HEIGHT != oldHEIGHT) drawwindow();
1239
    if (WIDTH != oldWIDTH || HEIGHT != oldHEIGHT) drawwindow();
1242
    else deredraw();
1240
    else deredraw();
1243
}
1241
}
1244
 
1242
 
1245
static void deredraw(void)
1243
static void deredraw(void)
1246
{
1244
{
1247
    int i;
1245
    int i;
1248
 
1246
 
1249
    setcellwidths();
1247
    setcellwidths();
1250
 
1248
 
1251
    if(hwidth > 0) gfillrect(de, bbg, rect(0, 0, WIDTH, hwidth));
1249
    if(hwidth > 0) gfillrect(de, bbg, rect(0, 0, WIDTH, hwidth));
1252
    gfillrect(de, bbg, rect(0, 0, boxw[0], windowHeight));
1250
    gfillrect(de, bbg, rect(0, 0, boxw[0], windowHeight));
1253
 
1251
 
1254
    for (i = 1; i < nhigh; i++)
1252
    for (i = 1; i < nhigh; i++)
1255
	drawrectangle(0, hwidth + i * box_h, boxw[0], box_h, 1, 1);
1253
	drawrectangle(0, hwidth + i * box_h, boxw[0], box_h, 1, 1);
1256
    colmax = colmin + (nwide - 2);
1254
    colmax = colmin + (nwide - 2);
1257
    rowmax = rowmin + (nhigh - 2);
1255
    rowmax = rowmin + (nhigh - 2);
1258
    printlabs();
1256
    printlabs();
1259
    /* if (!isNull(work) I don't think it can be null */
1257
    /* if (!isNull(work) I don't think it can be null */
1260
    for (i = colmin; i <= colmax; i++) drawcol(i);
1258
    for (i = colmin; i <= colmax; i++) drawcol(i);
1261
    gfillrect(de, p->bg, rect(windowWidth+1, hwidth, WIDTH-windowWidth-1,
1259
    gfillrect(de, p->bg, rect(windowWidth+1, hwidth, WIDTH-windowWidth-1,
1262
			      HEIGHT - hwidth));
1260
			      HEIGHT - hwidth));
1263
    highlightrect();
1261
    highlightrect();
1264
}
1262
}
1265
 
1263
 
1266
static void de_closewin(void)
1264
static void de_closewin(void)
1267
{
1265
{
1268
    closerect();
1266
    closerect();
1269
    hide(de);
1267
    hide(de);
1270
    del(de);
1268
    del(de);
1271
}
1269
}
1272
 
1270
 
1273
static void copyarea(int src_x, int src_y, int dest_x, int dest_y)
1271
static void copyarea(int src_x, int src_y, int dest_x, int dest_y)
1274
{
1272
{
1275
    int mx = max(src_x, dest_x), my = max(src_y, dest_y);
1273
    int mx = max(src_x, dest_x), my = max(src_y, dest_y);
1276
    copyrect(de, pt(dest_x, dest_y),
1274
    copyrect(de, pt(dest_x, dest_y),
1277
	     rect(src_x, src_y, windowWidth - mx, windowHeight - my));
1275
	     rect(src_x, src_y, windowWidth - mx, windowHeight - my));
1278
}
1276
}
1279
 
1277
 
1280
static void copyH(int src_x, int dest_x, int width)
1278
static void copyH(int src_x, int dest_x, int width)
1281
{
1279
{
1282
    copyrect(de, pt(dest_x, hwidth),
1280
    copyrect(de, pt(dest_x, hwidth),
1283
	     rect(src_x, hwidth, width, windowHeight - hwidth));
1281
	     rect(src_x, hwidth, width, windowHeight - hwidth));
1284
}
1282
}
1285
 
1283
 
1286
static Rboolean initwin(void)
1284
static Rboolean initwin(void)
1287
{
1285
{
1288
    int i;
1286
    int i;
1289
    rect r;
1287
    rect r;
1290
 
1288
 
1291
    de = newdataeditor();
1289
    de = newdataeditor();
1292
    if(!de) return TRUE;
1290
    if(!de) return TRUE;
1293
    p = getdata(de);
1291
    p = getdata(de);
1294
 
1292
 
1295
    nboxchars = asInteger(GetOption(install("de.cellwidth"), R_GlobalEnv));
1293
    nboxchars = asInteger(GetOption(install("de.cellwidth"), R_GlobalEnv));
1296
    if (nboxchars == NA_INTEGER || nboxchars < 0) nboxchars = 0;
1294
    if (nboxchars == NA_INTEGER || nboxchars < 0) nboxchars = 0;
1297
    if (nboxchars > 0) check(de_mvw);
1295
    if (nboxchars > 0) check(de_mvw);
1298
    box_w = ((nboxchars >0)?nboxchars:FIELDWIDTH)*FW + 8;
1296
    box_w = ((nboxchars >0)?nboxchars:FIELDWIDTH)*FW + 8;
1299
    /* this used to presume 4 chars sufficed for row numbering */
1297
    /* this used to presume 4 chars sufficed for row numbering */
1300
    labdigs = max(3, 1+floor(log10((double)ymaxused)));
1298
    labdigs = max(3, 1+floor(log10((double)ymaxused)));
1301
    boxw[0] = (1+labdigs)*FW + 8;
1299
    boxw[0] = (1+labdigs)*FW + 8;
1302
    sprintf(labform, "%%%dd", labdigs);
1300
    sprintf(labform, "%%%dd", labdigs);
1303
    for(i = 1; i < 100; i++) boxw[i] = get_col_width(i)*FW + 8;
1301
    for(i = 1; i < 100; i++) boxw[i] = get_col_width(i)*FW + 8;
1304
    box_h = FH + 4;
1302
    box_h = FH + 4;
1305
    text_xoffset = 5;
1303
    text_xoffset = 5;
1306
    text_yoffset = -3;
1304
    text_yoffset = -3;
1307
    setcellwidths();
1305
    setcellwidths();
1308
    nhigh = (HEIGHT - 2 * bwidth - hwidth - 3) / box_h;
1306
    nhigh = (HEIGHT - 2 * bwidth - hwidth - 3) / box_h;
1309
    windowHeight = nhigh * box_h + 2 * bwidth + hwidth;
1307
    windowHeight = nhigh * box_h + 2 * bwidth + hwidth;
1310
    r = getrect(de);
1308
    r = getrect(de);
1311
    r.width = windowWidth + 3;
1309
    r.width = windowWidth + 3;
1312
    r.height = windowHeight + 3;
1310
    r.height = windowHeight + 3;
1313
    resize(de, r);
1311
    resize(de, r);
1314
 
1312
 
1315
    CellModified = CellEditable = FALSE;
1313
    CellModified = CellEditable = FALSE;
1316
    bbg = dialog_bg();
1314
    bbg = dialog_bg();
1317
    /* set the active cell to be the upper left one */
1315
    /* set the active cell to be the upper left one */
1318
    crow = 1;
1316
    crow = 1;
1319
    ccol = 1;
1317
    ccol = 1;
1320
    /* drawwindow(); done as repaint but
1318
    /* drawwindow(); done as repaint but
1321
       decide if we need scrollbars here to avoid flashing*/
1319
       decide if we need scrollbars here to avoid flashing*/
1322
    nhigh = (HEIGHT - 2 * bwidth - hwidth) / box_h;
1320
    nhigh = (HEIGHT - 2 * bwidth - hwidth) / box_h;
1323
    gchangescrollbar(de, VWINSB, 0, ymaxused/yScrollbarScale,
1321
    gchangescrollbar(de, VWINSB, 0, ymaxused/yScrollbarScale,
1324
		     max(nhigh/yScrollbarScale, 1), 0);
1322
		     max(nhigh/yScrollbarScale, 1), 0);
1325
    setcellwidths();
1323
    setcellwidths();
1326
    gchangescrollbar(de, HWINSB, 0, xmaxused/xScrollbarScale,
1324
    gchangescrollbar(de, HWINSB, 0, xmaxused/xScrollbarScale,
1327
		     max(nwide/xScrollbarScale, 1), 0);
1325
		     max(nwide/xScrollbarScale, 1), 0);
1328
    show(de);
1326
    show(de);
1329
    show(de); /* a precaution, as PD reports transparent windows */
1327
    show(de); /* a precaution, as PD reports transparent windows */
1330
    BringToTop(de, 0);
1328
    BringToTop(de, 0);
1331
    R_de_up = TRUE;
1329
    R_de_up = TRUE;
1332
    return FALSE;
1330
    return FALSE;
1333
}
1331
}
1334
 
1332
 
1335
/* Menus */
1333
/* Menus */
1336
 
1334
 
1337
static window wconf, devw;
1335
static window wconf, devw;
1338
static radiobutton rb_num, rb_char;
1336
static radiobutton rb_num, rb_char;
1339
static label lwhat, lrb;
1337
static label lwhat, lrb;
1340
static field varname;
1338
static field varname;
1341
static int isnumeric, popupcol;
1339
static int isnumeric, popupcol;
1342
 
1340
 
1343
static void popupclose(control c)
1341
static void popupclose(control c)
1344
{
1342
{
1345
    SEXP tvec;
1343
    SEXP tvec;
1346
    char buf[30], clab[25];
1344
    char buf[30], clab[25];
1347
    int i;
1345
    int i;
1348
 
1346
 
1349
    strcpy(buf, gettext(varname));
1347
    strcpy(buf, gettext(varname));
1350
    if(!strlen(buf)) {
1348
    if(!strlen(buf)) {
1351
	askok(G_("column names cannot be blank"));
1349
	askok(G_("column names cannot be blank"));
1352
	return;
1350
	return;
1353
    }
1351
    }
1354
    if (popupcol > xmaxused) {
1352
    if (popupcol > xmaxused) {
1355
	/* extend work, names and lens */
1353
	/* extend work, names and lens */
1356
	REPROTECT(work = lengthgets(work, popupcol), wpi);
1354
	REPROTECT(work = lengthgets(work, popupcol), wpi);
1357
	REPROTECT(names = lengthgets(names, popupcol), npi);
1355
	REPROTECT(names = lengthgets(names, popupcol), npi);
1358
	/* Last col name is set later */
1356
	/* Last col name is set later */
1359
	for (i = xmaxused+1; i < popupcol - 1; i++) {
1357
	for (i = xmaxused+1; i < popupcol - 1; i++) {
1360
	    sprintf(clab, "var%d", i + 1);
1358
	    sprintf(clab, "var%d", i + 1);
1361
	    SET_STRING_ELT(names, i, mkChar(clab));
1359
	    SET_STRING_ELT(names, i, mkChar(clab));
1362
	}
1360
	}
1363
	REPROTECT(lens = lengthgets(lens, popupcol), lpi);
1361
	REPROTECT(lens = lengthgets(lens, popupcol), lpi);
1364
	xmaxused = popupcol;
1362
	xmaxused = popupcol;
1365
    }
1363
    }
1366
    tvec = VECTOR_ELT(work, popupcol - 1);
1364
    tvec = VECTOR_ELT(work, popupcol - 1);
1367
    if(ischecked(rb_num) && !isnumeric) {
1365
    if(ischecked(rb_num) && !isnumeric) {
1368
	if (isNull(tvec))
1366
	if (isNull(tvec))
1369
	    SET_VECTOR_ELT(work, popupcol - 1, ssNewVector(REALSXP, 100));
1367
	    SET_VECTOR_ELT(work, popupcol - 1, ssNewVector(REALSXP, 100));
1370
	else
1368
	else
1371
	    SET_VECTOR_ELT(work, popupcol - 1, coerceVector(tvec, REALSXP));
1369
	    SET_VECTOR_ELT(work, popupcol - 1, coerceVector(tvec, REALSXP));
1372
    } else if(ischecked(rb_char) && isnumeric) {
1370
    } else if(ischecked(rb_char) && isnumeric) {
1373
	if (isNull(tvec))
1371
	if (isNull(tvec))
1374
	    SET_VECTOR_ELT(work, popupcol - 1, ssNewVector(STRSXP, 100));
1372
	    SET_VECTOR_ELT(work, popupcol - 1, ssNewVector(STRSXP, 100));
1375
	else
1373
	else
1376
	    SET_VECTOR_ELT(work, popupcol - 1, coerceVector(tvec, STRSXP));
1374
	    SET_VECTOR_ELT(work, popupcol - 1, coerceVector(tvec, STRSXP));
1377
    }
1375
    }
1378
    SET_STRING_ELT(names, popupcol - 1, mkChar(buf));
1376
    SET_STRING_ELT(names, popupcol - 1, mkChar(buf));
1379
    hide(wconf);
1377
    hide(wconf);
1380
    del(wconf);
1378
    del(wconf);
1381
}
1379
}
1382
 
1380
 
1383
static void nm_hit_key(window w, int key)
1381
static void nm_hit_key(window w, int key)
1384
{
1382
{
1385
    if(key == '\n') popupclose(wconf);
1383
    if(key == '\n') popupclose(wconf);
1386
}
1384
}
1387
 
1385
 
1388
static void de_popupmenu(int x_pos, int y_pos, int col)
1386
static void de_popupmenu(int x_pos, int y_pos, int col)
1389
{
1387
{
1390
    char *blah;
1388
    char *blah;
1391
    rect r = screen_coords(de);
1389
    rect r = screen_coords(de);
1392
 
1390
 
1393
    popupcol = colmin + col - 1;
1391
    popupcol = colmin + col - 1;
1394
    blah = get_col_name(popupcol);
1392
    blah = get_col_name(popupcol);
1395
    wconf = newwindow(G_("Variable editor"),
1393
    wconf = newwindow(G_("Variable editor"),
1396
		      rect(x_pos + r.x-150, y_pos + r.y-50, 300, 100),
1394
		      rect(x_pos + r.x-150, y_pos + r.y-50, 300, 100),
1397
		      Titlebar | Closebox | Modal);
1395
		      Titlebar | Closebox | Modal);
1398
    setclose(wconf, popupclose);
1396
    setclose(wconf, popupclose);
1399
    setbackground(wconf, bbg);
1397
    setbackground(wconf, bbg);
1400
    lwhat = newlabel(G_("variable name"), rect(10, 22, 90, 20), AlignLeft);
1398
    lwhat = newlabel(G_("variable name"), rect(10, 22, 90, 20), AlignLeft);
1401
    varname = newfield(blah, rect(100, 20, 120, 20));
1399
    varname = newfield(blah, rect(100, 20, 120, 20));
1402
    lrb = newlabel(G_("type"), rect(50, 62, 50, 20), AlignLeft);
1400
    lrb = newlabel(G_("type"), rect(50, 62, 50, 20), AlignLeft);
1403
    rb_num = newradiobutton("numeric", rect(100, 60 , 80, 20), NULL);
1401
    rb_num = newradiobutton("numeric", rect(100, 60 , 80, 20), NULL);
1404
    rb_char = newradiobutton("character", rect(180, 60 , 80, 20), NULL);
1402
    rb_char = newradiobutton("character", rect(180, 60 , 80, 20), NULL);
1405
    isnumeric = (get_col_type(popupcol) == NUMERIC);
1403
    isnumeric = (get_col_type(popupcol) == NUMERIC);
1406
    if (isnumeric) check(rb_num); else check(rb_char);
1404
    if (isnumeric) check(rb_num); else check(rb_char);
1407
    setkeydown(wconf, nm_hit_key);
1405
    setkeydown(wconf, nm_hit_key);
1408
    show(wconf);
1406
    show(wconf);
1409
}
1407
}
1410
 
1408
 
1411
static void de_copy(control c)
1409
static void de_copy(control c)
1412
{
1410
{
1413
    copystringtoclipboard(get_cell_text());
1411
    copystringtoclipboard(get_cell_text());
1414
}
1412
}
1415
 
1413
 
1416
static void de_paste(control c)
1414
static void de_paste(control c)
1417
{
1415
{
1418
    char *p;
1416
    char *p;
1419
 
1417
 
1420
    closerect();
1418
    closerect();
1421
    if ( clipboardhastext() &&
1419
    if ( clipboardhastext() &&
1422
	 !getstringfromclipboard(buf, 1999) ) {
1420
	 !getstringfromclipboard(buf, 1999) ) {
1423
	/* set current cell to first line of clipboard */
1421
	/* set current cell to first line of clipboard */
1424
	CellModified = TRUE;
1422
	CellModified = TRUE;
1425
	if ((p = strchr(buf, '\n'))) *p = '\0';
1423
	if ((p = strchr(buf, '\n'))) *p = '\0';
1426
	clength = strlen(buf);
1424
	clength = strlen(buf);
1427
	bufp = buf + clength;
1425
	bufp = buf + clength;
1428
	closerect();
1426
	closerect();
1429
    }
1427
    }
1430
    highlightrect();
1428
    highlightrect();
1431
}
1429
}
1432
 
1430
 
1433
static void de_delete(control c)
1431
static void de_delete(control c)
1434
{
1432
{
1435
    CellModified = TRUE;
1433
    CellModified = TRUE;
1436
    buf[0] = '\0';
1434
    buf[0] = '\0';
1437
    clength = -1;
1435
    clength = -1;
1438
    bufp = buf + clength;
1436
    bufp = buf + clength;
1439
    closerect();
1437
    closerect();
1440
    highlightrect();
1438
    highlightrect();
1441
}
1439
}
1442
 
1440
 
1443
static void de_autosize(control c)
1441
static void de_autosize(control c)
1444
{
1442
{
1445
    int col = ccol + colmin - 1;
1443
    int col = ccol + colmin - 1;
1446
 
1444
 
1447
    closerect();
1445
    closerect();
1448
    if(col < 100) {
1446
    if(col < 100) {
1449
	boxw[col] = get_col_width(col)*FW + 8;
1447
	boxw[col] = get_col_width(col)*FW + 8;
1450
	deredraw();
1448
	deredraw();
1451
    }
1449
    }
1452
}
1450
}
1453
 
1451
 
1454
static void de_stayontop(control c)
1452
static void de_stayontop(control c)
1455
{
1453
{
1456
    BringToTop(de, 2);
1454
    BringToTop(de, 2);
1457
}
1455
}
1458
 
1456
 
1459
static void de_sbf(control c, int pos)
1457
static void de_sbf(control c, int pos)
1460
{
1458
{
1461
    if (pos < 0) { /* horizontal */
1459
    if (pos < 0) { /* horizontal */
1462
	colmin = 1 + (-pos*xScrollbarScale - 1);
1460
	colmin = 1 + (-pos*xScrollbarScale - 1);
1463
    } else {
1461
    } else {
1464
	rowmin = 1 + pos*yScrollbarScale;
1462
	rowmin = 1 + pos*yScrollbarScale;
1465
	if(rowmin > ymaxused - nhigh + 2) rowmin = max(1,ymaxused - nhigh + 2);
1463
	if(rowmin > ymaxused - nhigh + 2) rowmin = max(1,ymaxused - nhigh + 2);
1466
    }
1464
    }
1467
    drawwindow();
1465
    drawwindow();
1468
}
1466
}
1469
 
1467
 
1470
static checkbox varwidths;
1468
static checkbox varwidths;
1471
 
1469
 
1472
static void vw_close(control c)
1470
static void vw_close(control c)
1473
{
1471
{
1474
    int x;
1472
    int x;
1475
    if (ischecked(varwidths)) x = 0;
1473
    if (ischecked(varwidths)) x = 0;
1476
    else x = atoi(gettext(varname)); /* 0 if error */
1474
    else x = atoi(gettext(varname)); /* 0 if error */
1477
    x = min(x, 50);
1475
    x = min(x, 50);
1478
    if (x != nboxchars) {
1476
    if (x != nboxchars) {
1479
	nboxchars = x;
1477
	nboxchars = x;
1480
	box_w = ((nboxchars >0)?nboxchars:FIELDWIDTH)*FW + 8;
1478
	box_w = ((nboxchars >0)?nboxchars:FIELDWIDTH)*FW + 8;
1481
	deredraw();
1479
	deredraw();
1482
    }
1480
    }
1483
    hide(devw);
1481
    hide(devw);
1484
    del(devw);
1482
    del(devw);
1485
    if (nboxchars > 0) check(de_mvw);
1483
    if (nboxchars > 0) check(de_mvw);
1486
    else uncheck(de_mvw);
1484
    else uncheck(de_mvw);
1487
    addto(de);
1485
    addto(de);
1488
}
1486
}
1489
 
1487
 
1490
static void vw_hit_key(window w, int key)
1488
static void vw_hit_key(window w, int key)
1491
{
1489
{
1492
    if(key == '\n') vw_close(w);
1490
    if(key == '\n') vw_close(w);
1493
}
1491
}
1494
 
1492
 
1495
static void vw_callback(control c)
1493
static void vw_callback(control c)
1496
{
1494
{
1497
    if (ischecked(varwidths)) disable(varname);
1495
    if (ischecked(varwidths)) disable(varname);
1498
    else enable(varname);
1496
    else enable(varname);
1499
}
1497
}
1500
 
1498
 
1501
 
1499
 
1502
static void de_popup_vw(void)
1500
static void de_popup_vw(void)
1503
{
1501
{
1504
    char blah[25];
1502
    char blah[25];
1505
 
1503
 
1506
    devw = newwindow(G_("Cell width(s)"),
1504
    devw = newwindow(G_("Cell width(s)"),
1507
		      rect(0, 0, 250, 60),
1505
		      rect(0, 0, 250, 60),
1508
		      Titlebar | Centered | Closebox | Modal);
1506
		      Titlebar | Centered | Closebox | Modal);
1509
    setclose(devw, vw_close);
1507
    setclose(devw, vw_close);
1510
    setbackground(devw, bbg);
1508
    setbackground(devw, bbg);
1511
    lwhat = newlabel(G_("Cell width"), rect(10, 20, 70, 20), AlignLeft);
1509
    lwhat = newlabel(G_("Cell width"), rect(10, 20, 70, 20), AlignLeft);
1512
    sprintf(blah, "%d", nboxchars);
1510
    sprintf(blah, "%d", nboxchars);
1513
    varname = newfield(blah, rect(80, 20, 40, 20));
1511
    varname = newfield(blah, rect(80, 20, 40, 20));
1514
    varwidths = newcheckbox(G_("variable"), rect(150, 20, 80, 20), vw_callback);
1512
    varwidths = newcheckbox(G_("variable"), rect(150, 20, 80, 20), vw_callback);
1515
    if (nboxchars == 0) {
1513
    if (nboxchars == 0) {
1516
	check(varwidths);
1514
	check(varwidths);
1517
	disable(varname);
1515
	disable(varname);
1518
    }
1516
    }
1519
    setkeydown(devw, vw_hit_key);
1517
    setkeydown(devw, vw_hit_key);
1520
    show(devw);
1518
    show(devw);
1521
}
1519
}
1522
 
1520
 
1523
static void menudecellwidth(control m)
1521
static void menudecellwidth(control m)
1524
{
1522
{
1525
    de_popup_vw();
1523
    de_popup_vw();
1526
}
1524
}
1527
 
1525
 
1528
static void deldataeditor(control m)
1526
static void deldataeditor(control m)
1529
{
1527
{
1530
    freeConsoleData(getdata(m));
1528
    freeConsoleData(getdata(m));
1531
}
1529
}
1532
 
1530
 
1533
static void declose(control m)
1531
static void declose(control m)
1534
{
1532
{
1535
    de_closewin();
1533
    de_closewin();
1536
    show(RConsole);
1534
    show(RConsole);
1537
    R_de_up = FALSE;
1535
    R_de_up = FALSE;
1538
}
1536
}
1539
 
1537
 
1540
static void deresize(console c, rect r)
1538
static void deresize(console c, rect r)
1541
{
1539
{
1542
    if (((WIDTH  == r.width) &&
1540
    if (((WIDTH  == r.width) &&
1543
	 (HEIGHT == r.height)) ||
1541
	 (HEIGHT == r.height)) ||
1544
	(r.width == 0) || (r.height == 0) ) /* minimize */
1542
	(r.width == 0) || (r.height == 0) ) /* minimize */
1545
        return;;
1543
        return;;
1546
    WIDTH = r.width;
1544
    WIDTH = r.width;
1547
    HEIGHT = r.height;
1545
    HEIGHT = r.height;
1548
}
1546
}
1549
 
1547
 
1550
 
1548
 
1551
static void menudehelp(control m)
1549
static void menudehelp(control m)
1552
{
1550
{
1553
    char s[] = GN_("Navigation.\n  Keyboard: cursor keys move selection\n\tTab move right, Shift+Tab moves left\n\tPgDn or Ctrl+F: move down one screenful\n\tPgUp or Ctrl+B: move up one screenful\n\tHome: move to (1,1) cell\n\tEnd: show last rows of last column.\n   Mouse: left-click in a cell, use the scrollbar(s).\n\nEditing.\n  Type in the currently hightlighted cell\n  Double-click in a cell for an editable field\n\nMisc.\n  Ctrl-L redraws the screen, auto-resizing the columns\n  Ctrl-C copies selected cell\n  Ctrl-V pastes to selected cell\n  Right-click menu for copy, paste, autosize currently selected column\n\n");
1551
    char s[] = GN_("Navigation.\n  Keyboard: cursor keys move selection\n\tTab move right, Shift+Tab moves left\n\tPgDn or Ctrl+F: move down one screenful\n\tPgUp or Ctrl+B: move up one screenful\n\tHome: move to (1,1) cell\n\tEnd: show last rows of last column.\n   Mouse: left-click in a cell, use the scrollbar(s).\n\nEditing.\n  Type in the currently hightlighted cell\n  Double-click in a cell for an editable field\n\nMisc.\n  Ctrl-L redraws the screen, auto-resizing the columns\n  Ctrl-C copies selected cell\n  Ctrl-V pastes to selected cell\n  Right-click menu for copy, paste, autosize currently selected column\n\n");
1554
    askok(G_(s));
1552
    askok(G_(s));
1555
}
1553
}
1556
 
1554
 
1557
 
1555
 
1558
static MenuItem DePopup[28] = {
1556
static MenuItem DePopup[28] = {
1559
    {GN_("Help"), menudehelp, 0},
1557
    {GN_("Help"), menudehelp, 0},
1560
    {"-", 0, 0},
1558
    {"-", 0, 0},
1561
    {GN_("Copy selected cell"), de_copy, 0},
1559
    {GN_("Copy selected cell"), de_copy, 0},
1562
    {GN_("Paste to selected cell"), de_paste, 0},
1560
    {GN_("Paste to selected cell"), de_paste, 0},
1563
    {GN_("Autosize column"), de_autosize, 0},
1561
    {GN_("Autosize column"), de_autosize, 0},
1564
    {"-", 0, 0},
1562
    {"-", 0, 0},
1565
    {GN_("Stay on top"), de_stayontop, 0},
1563
    {GN_("Stay on top"), de_stayontop, 0},
1566
    {"-", 0, 0},
1564
    {"-", 0, 0},
1567
    {GN_("Close"), declose, 0},
1565
    {GN_("Close"), declose, 0},
1568
    LASTMENUITEM
1566
    LASTMENUITEM
1569
};
1567
};
1570
 
1568
 
1571
static void demenuact(control m)
1569
static void demenuact(control m)
1572
{
1570
{
1573
    /* use this to customize the menu */
1571
    /* use this to customize the menu */
1574
}
1572
}
1575
 
1573
 
1576
static void depopupact(control m)
1574
static void depopupact(control m)
1577
{
1575
{
1578
    /* use this to customize the menu */
1576
    /* use this to customize the menu */
1579
    if (ismdi())
1577
    if (ismdi())
1580
    	disable(DePopup[6].m);
1578
    	disable(DePopup[6].m);
1581
    else {
1579
    else {
1582
    	if (isTopmost(de))
1580
    	if (isTopmost(de))
1583
    	    check(DePopup[6].m);
1581
    	    check(DePopup[6].m);
1584
    	else
1582
    	else
1585
    	    uncheck(DePopup[6].m);
1583
    	    uncheck(DePopup[6].m);
1586
    }
1584
    }
1587
}
1585
}
1588
 
1586
 
1589
 
1587
 
1590
#define MCHECK(a) if (!(a)) {del(c);return NULL;}
1588
#define MCHECK(a) if (!(a)) {del(c);return NULL;}
1591
 
1589
 
1592
RECT *RgetMDIsize(); /* in rui.c */
1590
RECT *RgetMDIsize(); /* in rui.c */
1593
 
1591
 
1594
static dataeditor newdataeditor(void)
1592
static dataeditor newdataeditor(void)
1595
{
1593
{
1596
    ConsoleData p;
1594
    ConsoleData p;
1597
    int w, h, x, y;
1595
    int w, h, x, y;
1598
    dataeditor c;
1596
    dataeditor c;
1599
    menuitem m;
1597
    menuitem m;
1600
 
1598
 
1601
    p = newconsoledata((consolefn) ? consolefn : FixedFont,
1599
    p = newconsoledata((consolefn) ? consolefn : FixedFont,
1602
		       pagerrow, pagercol, 0, 0,
1600
		       pagerrow, pagercol, 0, 0,
1603
		       consolefg, consoleuser, consolebg,
1601
		       consolefg, consoleuser, consolebg,
1604
		       DATAEDITOR);
1602
		       DATAEDITOR);
1605
    if (!p) return NULL;
1603
    if (!p) return NULL;
1606
 
1604
 
1607
    w = WIDTH ;
1605
    w = WIDTH ;
1608
    h = HEIGHT;
1606
    h = HEIGHT;
1609
    if (ismdi()) {
1607
    if (ismdi()) {
1610
	RECT *pR = RgetMDIsize();
1608
	RECT *pR = RgetMDIsize();
1611
	x = (pR->right - w) / 3; x = x > 20 ? x:20;
1609
	x = (pR->right - w) / 3; x = x > 20 ? x:20;
1612
	y = (pR->bottom - h) / 3; y = y > 20 ? y:20;
1610
	y = (pR->bottom - h) / 3; y = y > 20 ? y:20;
1613
    } else {
1611
    } else {
1614
	x = (devicewidth(NULL) - w) / 3;
1612
	x = (devicewidth(NULL) - w) / 3;
1615
	y = (deviceheight(NULL) - h) / 3 ;
1613
	y = (deviceheight(NULL) - h) / 3 ;
1616
    }
1614
    }
1617
    c = (dataeditor) newwindow(G_("Data Editor"), rect(x, y, w, h),
1615
    c = (dataeditor) newwindow(G_("Data Editor"), rect(x, y, w, h),
1618
			       Document | StandardWindow | Menubar |
1616
			       Document | StandardWindow | Menubar |
1619
			       VScrollbar | HScrollbar | TrackMouse);
1617
			       VScrollbar | HScrollbar | TrackMouse);
1620
    if (!c) {
1618
    if (!c) {
1621
         freeConsoleData(p);
1619
         freeConsoleData(p);
1622
         return NULL;
1620
         return NULL;
1623
    }
1621
    }
1624
    setdata(c, p);
1622
    setdata(c, p);
1625
    if(h == 0) HEIGHT = getheight(c);
1623
    if(h == 0) HEIGHT = getheight(c);
1626
    if(w == 0) WIDTH  = getwidth(c);
1624
    if(w == 0) WIDTH  = getwidth(c);
1627
    COLS = WIDTH / FW - 1;
1625
    COLS = WIDTH / FW - 1;
1628
    ROWS = HEIGHT / FH - 1;
1626
    ROWS = HEIGHT / FH - 1;
1629
    BORDERX = (WIDTH - COLS*FW) / 2;
1627
    BORDERX = (WIDTH - COLS*FW) / 2;
1630
    BORDERY = (HEIGHT - ROWS*FH) / 2;
1628
    BORDERY = (HEIGHT - ROWS*FH) / 2;
1631
    gsetcursor(c, ArrowCursor);
1629
    gsetcursor(c, ArrowCursor);
1632
    setbackground(c, consolebg);
1630
    setbackground(c, consolebg);
1633
    if (ismdi() && (RguiMDI & RW_TOOLBAR)) {
1631
    if (ismdi() && (RguiMDI & RW_TOOLBAR)) {
1634
	/* blank toolbar to stop windows jumping around */
1632
	/* blank toolbar to stop windows jumping around */
1635
        int btsize = 24;
1633
        int btsize = 24;
1636
        control tb;
1634
        control tb;
1637
        addto(c);
1635
        addto(c);
1638
        MCHECK(tb = newtoolbar(btsize + 4));
1636
        MCHECK(tb = newtoolbar(btsize + 4));
1639
	gsetcursor(tb, ArrowCursor);
1637
	gsetcursor(tb, ArrowCursor);
1640
    }
1638
    }
1641
    MCHECK(gpopup(depopupact, DePopup));
1639
    MCHECK(gpopup(depopupact, DePopup));
1642
    MCHECK(m = newmenubar(demenuact));
1640
    MCHECK(m = newmenubar(demenuact));
1643
    MCHECK(newmenu(G_("File")));
1641
    MCHECK(newmenu(G_("File")));
1644
/*    MCHECK(m = newmenuitem("-", 0, NULL));*/
1642
/*    MCHECK(m = newmenuitem("-", 0, NULL));*/
1645
    MCHECK(m = newmenuitem(G_("Close"), 0, declose));
1643
    MCHECK(m = newmenuitem(G_("Close"), 0, declose));
1646
    newmdimenu();
1644
    newmdimenu();
1647
    MCHECK(newmenu(G_("Edit")));
1645
    MCHECK(newmenu(G_("Edit")));
1648
    MCHECK(m = newmenuitem(G_("Copy  \tCTRL+C"), 0, de_copy));
1646
    MCHECK(m = newmenuitem(G_("Copy  \tCTRL+C"), 0, de_copy));
1649
    MCHECK(m = newmenuitem(G_("Paste \tCTRL+V"), 0, de_paste));
1647
    MCHECK(m = newmenuitem(G_("Paste \tCTRL+V"), 0, de_paste));
1650
    MCHECK(m = newmenuitem(G_("Delete\tDEL"), 0, de_delete));
1648
    MCHECK(m = newmenuitem(G_("Delete\tDEL"), 0, de_delete));
1651
    MCHECK(m = newmenuitem("-", 0, NULL));
1649
    MCHECK(m = newmenuitem("-", 0, NULL));
1652
    MCHECK(de_mvw = newmenuitem(G_("Cell widths ..."), 0, menudecellwidth));
1650
    MCHECK(de_mvw = newmenuitem(G_("Cell widths ..."), 0, menudecellwidth));
1653
    MCHECK(m = newmenu(G_("Help")));
1651
    MCHECK(m = newmenu(G_("Help")));
1654
    MCHECK(newmenuitem(G_("Data editor"), 0, menudehelp));
1652
    MCHECK(newmenuitem(G_("Data editor"), 0, menudehelp));
1655
 
1653
 
1656
    setdata(c, p);
1654
    setdata(c, p);
1657
    setresize(c, deresize);
1655
    setresize(c, deresize);
1658
    setredraw(c, de_redraw);
1656
    setredraw(c, de_redraw);
1659
    setdel(c, deldataeditor);
1657
    setdel(c, deldataeditor);
1660
    setclose(c, declose);
1658
    setclose(c, declose);
1661
    sethit(c, de_sbf);
1659
    sethit(c, de_sbf);
1662
    setkeyaction(c, de_ctrlkeyin);
1660
    setkeyaction(c, de_ctrlkeyin);
1663
    setkeydown(c, de_normalkeyin);
1661
    setkeydown(c, de_normalkeyin);
1664
    setmousedown(c, de_mousedown);
1662
    setmousedown(c, de_mousedown);
1665
    setmouseup(c, de_mouseup);
1663
    setmouseup(c, de_mouseup);
1666
    return(c);
1664
    return(c);
1667
}
1665
}