The R Project SVN R

Rev

Rev 79226 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 79226 Rev 83796
Line 1... Line 1...
1
/*
1
/*
2
 *  R : A Computer Language for Statistical Data Analysis
2
 *  R : A Computer Language for Statistical Data Analysis
3
 *  Copyright (C) 1999-2020  The R Core Team
3
 *  Copyright (C) 1999-2023  The R Core Team
4
 *
4
 *
5
 *  This program is free software; you can redistribute it and/or modify
5
 *  This program is free software; you can redistribute it and/or modify
6
 *  it under the terms of the GNU General Public License as published by
6
 *  it under the terms of the GNU General Public License as published by
7
 *  the Free Software Foundation; either version 2 of the License, or
7
 *  the Free Software Foundation; either version 2 of the License, or
8
 *  (at your option) any later version.
8
 *  (at your option) any later version.
Line 53... Line 53...
53
/* Pointers to currently open editors */
53
/* Pointers to currently open editors */
54
static editor REditors[MAXNEDITORS];
54
static editor REditors[MAXNEDITORS];
55
static int neditors  = 0;
55
static int neditors  = 0;
56
static Rboolean fix_editor_up = FALSE;
56
static Rboolean fix_editor_up = FALSE;
57
 
57
 
58
static EditorData neweditordata (int file, const char *filename)
58
static EditorData neweditordata (int file)
59
{
59
{
60
    EditorData p;
60
    EditorData p;
61
    p = (EditorData) malloc(sizeof(struct structEditorData));
61
    p = (EditorData) malloc(sizeof(struct structEditorData));
62
    p->file = file;
62
    p->file = file;
63
    /* need space for terminator, and to copy it */
-
 
64
    p->filename = (char *) malloc((MAX_PATH+1)*sizeof(char));
-
 
65
    if (filename)
63
    p->filename = NULL;
66
	strncpy(p->filename, filename, MAX_PATH+1);
-
 
67
    p->title = (char *) malloc((EDITORMAXTITLE + 1)*sizeof(char));
64
    p->title = (char *) malloc((EDITORMAXTITLE + 1)*sizeof(char));
68
    p->title[EDITORMAXTITLE] = p->title[0] = '\0';
65
    p->title[EDITORMAXTITLE] = p->title[0] = '\0';
69
    return p;
66
    return p;
70
}
67
}
71
 
68
 
72
void deleditordata(EditorData p)
69
void deleditordata(EditorData p)
73
{
70
{
74
    if (p->stealconsole)
71
    if (p->stealconsole)
75
	fix_editor_up = FALSE;
72
	fix_editor_up = FALSE;
-
 
73
    if (p->filename)
76
    free(p->filename);
74
	free(p->filename);
77
    free(p->title);
75
    free(p->title);
78
    free(p->hmenu);
76
    free(p->hmenu);
79
    free(p->pmenu);
77
    free(p->pmenu);
80
    free(p);
78
    free(p);
81
}
79
}
Line 95... Line 93...
95
    settext(c, wtitle);
93
    settext(c, wtitle);
96
}
94
}
97
 
95
 
98
/*** FILE MANAGEMENT FUNCTIONS ***/
96
/*** FILE MANAGEMENT FUNCTIONS ***/
99
 
97
 
-
 
98
/* FIXME: simplify this once UTF-8 is the only supported native encoding. */
-
 
99
 
-
 
100
static wchar_t* utf8_to_wchar(const char *src)
-
 
101
{
-
 
102
    size_t needed = Rf_utf8towcs(NULL, src, 0);
-
 
103
    wchar_t *res = (wchar_t  *)malloc((needed + 1)*sizeof(wchar_t));
-
 
104
    if (res)
-
 
105
	Rf_utf8towcs(res, src, needed + 1);
-
 
106
    return res;
-
 
107
}
-
 
108
	
-
 
109
static char* utf8_to_native(const char *src)
-
 
110
{
-
 
111
    /* a defensive guess, reEnc2 would throw error if not enough */
-
 
112
    size_t needed = strlen(src) * 4;
-
 
113
    char *res = (char *)malloc(needed + 1);
-
 
114
    if (res)
-
 
115
	reEnc2(src, res, needed + 1, CE_UTF8, CE_NATIVE, 3);
-
 
116
    return res;
-
 
117
}	
-
 
118
 
-
 
119
static char* native_to_utf8(const char *src)
-
 
120
{
-
 
121
    /* a defensive guess, reEnc2 would throw error if not enough */
-
 
122
    size_t needed = strlen(src) * 4;
-
 
123
    char *res = (char *)malloc(needed + 1);
-
 
124
    if (res)
-
 
125
	reEnc2(src, res, needed + 1, CE_NATIVE, CE_UTF8, 3);
-
 
126
    return res;
-
 
127
}	
-
 
128
 
-
 
129
static char* wchar_to_utf8(const wchar_t *src)
-
 
130
{
-
 
131
    size_t needed = Rf_wcstoutf8(NULL, src, INT_MAX);
-
 
132
    char *res = (char *)malloc(needed + 1);
-
 
133
    if (res)
-
 
134
	Rf_wcstoutf8(res, src, needed + 1);
-
 
135
    return res;
-
 
136
}
-
 
137
 
100
FILE *R_wfopen(const wchar_t *filename, const wchar_t *mode);
138
FILE *R_wfopen(const wchar_t *filename, const wchar_t *mode);
101
 
139
 
-
 
140
#define MSGSIZE 512
-
 
141
 
102
static void editor_load_file(editor c, const char *name, int enc)
142
static void editor_load_file(editor c, const char *name, int enc)
103
{
143
{
104
    textbox t = getdata(c);
144
    textbox t = getdata(c);
105
    EditorData p = getdata(t);
145
    EditorData p = getdata(t);
106
    FILE *f;
146
    FILE *f;
107
    char *buffer = NULL, tmp[MAX_PATH+50], tname[MAX_PATH+1];
147
    char *buffer = NULL, tmp[MSGSIZE];
108
    const char *sname;
148
    const char *sname;
109
    long num = 1, bufsize;
149
    long num = 1, bufsize;
110
 
150
 
111
    if(enc == CE_UTF8) {
151
    if(enc == CE_UTF8) {
112
	wchar_t wname[MAX_PATH+1];
152
	wchar_t *wname = utf8_to_wchar(name);
113
	Rf_utf8towcs(wname, name, MAX_PATH+1);
-
 
114
	f = R_wfopen(wname, L"r");
153
	f = R_wfopen(wname, L"r");
115
	reEnc2(name, tname, MAX_PATH+1, CE_UTF8, CE_NATIVE, 3);
154
	free(wname);
116
	sname = tname;
155
	sname = utf8_to_native(name);
117
    } else {
156
    } else {
118
	f = R_fopen(name, "r");
157
	f = R_fopen(name, "r");
119
	sname = name;
158
	sname = name;
120
    }
159
    }
121
    if (f == NULL) {
160
    if (f == NULL) {
122
	snprintf(tmp, MAX_PATH+50, 
161
	snprintf(tmp, MSGSIZE, 
123
		 G_("unable to open file %s for reading"), sname);
162
		 G_("unable to open file %s for reading"), sname);
124
	R_ShowMessage(tmp);
163
	R_ShowMessage(tmp);
-
 
164
	if (enc == CE_UTF8)
-
 
165
	    free((char *)sname); 
125
	return;
166
	return;
126
    }
167
    }
127
    p->file = 1;
168
    p->file = 1;
-
 
169
    if (p->filename)
-
 
170
	free(p->filename);
-
 
171
    if (enc == CE_UTF8) {
-
 
172
	p->filename = (char *) malloc(strlen(name) + 1);
128
    strncpy(p->filename, name, MAX_PATH+1);
173
	strcpy(p->filename, name);
-
 
174
    } else
-
 
175
	p->filename = native_to_utf8(name);
-
 
176
 
129
    bufsize = 0;
177
    bufsize = 0;
130
    while (num > 0) {
178
    while (num > 0) {
131
	buffer = realloc(buffer, bufsize + 3000 + 1);
179
	buffer = realloc(buffer, bufsize + 3000 + 1);
132
	num = fread(buffer + bufsize, 1, 3000 - 1, f);
180
	num = fread(buffer + bufsize, 1, 3000 - 1, f);
133
	if (num >= 0) {
181
	if (num >= 0) {
134
	    bufsize += num;
182
	    bufsize += num;
135
	    buffer[bufsize] = '\0';
183
	    buffer[bufsize] = '\0';
136
	}
184
	}
137
	else {
185
	else {
138
	    snprintf(tmp, MAX_PATH+50, 
186
	    snprintf(tmp, MSGSIZE,
139
		     G_("Could not read from file '%s'"), sname);
187
		     G_("Could not read from file '%s'"), sname);
140
	    askok(tmp);
188
	    askok(tmp);
141
	}
189
	}
142
    }
190
    }
143
    setlimittext(t, 2 * strlen(buffer));
191
    setlimittext(t, 2 * strlen(buffer));
144
    settext(t, buffer);
192
    settext(t, buffer);
145
    gsetmodified(t, 0);
193
    gsetmodified(t, 0);
146
    free(buffer);
194
    free(buffer);
147
    fclose(f);
195
    fclose(f);
-
 
196
    if (enc == CE_UTF8)
-
 
197
	free((char *)sname); 
148
}
198
}
149
 
199
 
150
static void editor_save_file(editor c, const char *name, int enc)
200
static void editor_save_file(editor c, const char *name, int enc)
151
{
201
{
152
    textbox t = getdata(c);
202
    textbox t = getdata(c);
153
    FILE *f;
203
    FILE *f;
154
    char buf[MAX_PATH+30], tname[MAX_PATH+1];
204
    char buf[MSGSIZE];
155
    const char *sname;
205
    const char *sname;
156
 
206
 
157
    if (name == NULL)
207
    if (name == NULL)
158
	return;
208
	return;
159
    else {
209
    else {
160
	if(enc == CE_UTF8) {
210
	if(enc == CE_UTF8) {
161
	    wchar_t wname[MAX_PATH+1];
211
	    wchar_t *wname = utf8_to_wchar(name);
162
	    Rf_utf8towcs(wname, name, MAX_PATH+1);
-
 
163
	    reEnc2(name, tname, MAX_PATH+1, CE_UTF8, CE_NATIVE, 3);
-
 
164
	    sname = tname;
-
 
165
	    f = R_wfopen(wname, L"w");
212
	    f = R_wfopen(wname, L"w");
-
 
213
	    free(wname);
-
 
214
	    sname = utf8_to_native(name);
166
	} else {
215
	} else {
167
	    sname = name;
216
	    sname = name;
168
	    f = R_fopen(sname, "w");
217
	    f = R_fopen(sname, "w");
169
	}
218
	}
170
	if (f == NULL) {
219
	if (f == NULL) {
171
	    snprintf(buf, MAX_PATH+30, G_("Could not save file '%s'"), sname);
220
	    snprintf(buf, MSGSIZE, G_("Could not save file '%s'"), sname);
172
	    askok(buf);
221
	    askok(buf);
-
 
222
	    if (enc == CE_UTF8)
-
 
223
		free((char *)sname);
173
	    return;
224
	    return;
174
	}
225
	}
175
	fprintf(f, "%s", gettext(t));
226
	fprintf(f, "%s", gettext(t));
176
	fclose(f);
227
	fclose(f);
-
 
228
	if (enc == CE_UTF8)
-
 
229
	    free((char *)sname);
177
    }
230
    }
178
}
231
}
179
 
232
 
180
static void editorsaveas(editor c)
233
static void editorsaveas(editor c)
181
{
234
{
Line 184... Line 237...
184
    wchar_t *wname;
237
    wchar_t *wname;
185
 
238
 
186
    setuserfilterW(L"R files (*.R)\0*.R\0S files (*.q, *.ssc, *.S)\0*.q;*.ssc;*.S\0All files (*.*)\0*.*\0\0");
239
    setuserfilterW(L"R files (*.R)\0*.R\0S files (*.q, *.ssc, *.S)\0*.q;*.ssc;*.S\0All files (*.*)\0*.*\0\0");
187
    wname = askfilesaveW(G_("Save script as"), "");
240
    wname = askfilesaveW(G_("Save script as"), "");
188
    if (wname) {
241
    if (wname) {
189
	char name[4*MAX_PATH+1];
-
 
190
	wcstoutf8(name, wname, sizeof(name));
242
	char *name = wchar_to_utf8(wname);
191
	/* now check if it has an extension */
-
 
192
	char *q = strchr(name, '.');
243
	char *q = strchr(name, '.');
-
 
244
	if(!q) {
-
 
245
	    char *tmp = (char *)malloc(strlen(name) + 2 + 1);
-
 
246
	    if (tmp) {
-
 
247
		strcpy(tmp, name);
193
	if(!q) strncat(name, ".R", 4*MAX_PATH);
248
		strcat(tmp, ".R");
-
 
249
		free(name);
-
 
250
		name = tmp;
-
 
251
	    }
-
 
252
	}
194
	editor_save_file(c, name, CE_UTF8);
253
	editor_save_file(c, name, CE_UTF8);
195
	p->file = 1;
254
	p->file = 1;
196
	reEnc2(name, p->filename, MAX_PATH+1, CE_UTF8, CE_NATIVE, 3);
255
	p->filename = name; /* keeps name */
197
	gsetmodified(t, 0);
256
	gsetmodified(t, 0);
-
 
257
	char *sname = utf8_to_native(name);
198
	editor_set_title(c, p->filename);
258
	editor_set_title(c, sname);
-
 
259
	free(sname);
199
    }
260
    }
200
    show(c);
261
    show(c);
201
}
262
}
202
 
263
 
203
static void menueditorsaveas(control m)
264
static void menueditorsaveas(control m)
Line 370... Line 431...
370
}
431
}
371
 
432
 
372
static void editoropen(const char *default_name)
433
static void editoropen(const char *default_name)
373
{
434
{
374
    wchar_t *wname;
435
    wchar_t *wname;
375
    char name[4*MAX_PATH + 1], title[4*MAX_PATH];
-
 
376
 
436
 
377
    int i; textbox t; EditorData p;
437
    int i; textbox t; EditorData p;
378
    setuserfilterW(L"R files (*.R)\0*.R\0S files (*.q, *.ssc, *.S)\0*.q;*.ssc;*.S\0All files (*.*)\0*.*\0\0");
438
    setuserfilterW(L"R files (*.R)\0*.R\0S files (*.q, *.ssc, *.S)\0*.q;*.ssc;*.S\0All files (*.*)\0*.*\0\0");
379
    wname = askfilenameW(G_("Open script"), default_name); /* returns NULL if open dialog cancelled */
439
    wname = askfilenameW(G_("Open script"), default_name); /* returns NULL if open dialog cancelled */
380
    if (wname) {
440
    if (wname) {
381
	wcstoutf8(name, wname, sizeof(name));
441
	char *name = wchar_to_utf8(wname);
382
	/* check if file is already open in an editor. If so, close and open again */
442
	/* check if file is already open in an editor. If so, close and open again */
383
	for (i = 0; i < neditors; ++i) {
443
	for (i = 0; i < neditors; ++i) {
384
	    t = getdata(REditors[i]);
444
	    t = getdata(REditors[i]);
385
	    p = getdata(t);
445
	    p = getdata(t);
386
	    if (!strcmp (name, p->filename)) {
446
	    if (p->filename && !strcmp (name, p->filename)) {
387
		editorclose(REditors[i]);
447
		editorclose(REditors[i]);
388
		break;
448
		break;
389
	    }
449
	    }
390
	}
450
	}
391
	reEnc2(name, title, MAX_PATH+1, CE_UTF8, CE_NATIVE, 3);
451
	char *sname = utf8_to_native(name);
392
	Rgui_Edit(name, CE_UTF8, title, 0);
452
	Rgui_Edit(name, CE_UTF8, sname, 0);
-
 
453
	free(name);
-
 
454
	free(sname);
393
    } else show(RConsole);
455
    } else show(RConsole);
394
}
456
}
395
 
457
 
396
void menueditoropen(control m)
458
void menueditoropen(control m)
397
{
459
{
398
    editor c = getdata(m);
460
    editor c = getdata(m);
399
    char *default_name = "";
-
 
400
    /* It really is not clear what is meant here: seems to assume an
461
    /* It really is not clear what is meant here: seems to assume an
401
       editor window but is called from elsewhere, hopefully with NULL
462
       editor window but is called from elsewhere, hopefully with NULL
402
       (since 2.1.1 patched). */
463
       (since 2.1.1 patched). */
403
    if (c) {
464
    if (c) {
404
	textbox t = getdata(c);
465
	textbox t = getdata(c);
405
	EditorData p = getdata(t);
466
	EditorData p = getdata(t);
-
 
467
	if (p->file && p->filename) {
406
	if (p->file) default_name = p->filename;  /* name of currently-open file, if there is one */
468
	    /* name of currently-open file, if there is one */
-
 
469
	    char *sname = utf8_to_native(p->filename);
-
 
470
	    editoropen(sname);
-
 
471
	    free(sname);
-
 
472
	    return;
-
 
473
	}
407
    }
474
    } 
408
    editoropen(default_name);
475
    editoropen("");
409
}
476
}
410
 
477
 
411
 
478
 
412
/*** EDITING FUNCTIONS ***/
479
/*** EDITING FUNCTIONS ***/
413
 
480
 
Line 467... Line 534...
467
/*** FUNCTIONS FOR RUNNING R CODE FROM THE EDITOR ***/
534
/*** FUNCTIONS FOR RUNNING R CODE FROM THE EDITOR ***/
468
 
535
 
469
static void editorrunline(textbox t)
536
static void editorrunline(textbox t)
470
{
537
{
471
    int length = getlinelength(t); /* return character num */
538
    int length = getlinelength(t); /* return character num */
472
    char *line = malloc(length * sizeof(WCHAR) + 2); /* Extra space for null and word length in getcurrentline */
539
    /* Extra space for null and word length in getcurrentline */
-
 
540
    size_t alength = length * MB_CUR_MAX + 1 + sizeof(WORD);
-
 
541
    char *line = malloc(alength);
473
    memset(line, 0, length * sizeof(WCHAR) + 2);
542
    memset(line, 0, alength);
474
    getcurrentline(t, line, length);
543
    getcurrentline(t, line, length);
475
    consolecmd(RConsole, line);
544
    consolecmd(RConsole, line);
476
    free(line);
545
    free(line);
477
    scrollcaret(t, 1);
546
    scrollcaret(t, 1);
478
    show(t);
547
    show(t);
Line 643... Line 712...
643
    editor c;
712
    editor c;
644
    menuitem m;
713
    menuitem m;
645
    textbox t;
714
    textbox t;
646
    long flags;
715
    long flags;
647
    font editorfn = (consolefn ? consolefn : FixedFont);
716
    font editorfn = (consolefn ? consolefn : FixedFont);
648
    EditorData p = neweditordata(0, NULL);
717
    EditorData p = neweditordata(0);
649
    DWORD rand;
718
    DWORD rand;
650
 
719
 
651
    w = (pagercol + 1)*fontwidth(editorfn);
720
    w = (pagercol + 1)*fontwidth(editorfn);
652
    h = (pagerrow + 1)*fontheight(editorfn) + 1;
721
    h = (pagerrow + 1)*fontheight(editorfn) + 1;
653
#ifdef USE_MDI
722
#ifdef USE_MDI