The R Project SVN R

Rev

Rev 69561 | Rev 79040 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
28991 murdoch 1
/*
2
 *  R : A Computer Language for Statistical Data Analysis
72714 murdoch 3
 *  Copyright (C) 1999-2017  The R Core Team
28991 murdoch 4
 *
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
7
 *  the Free Software Foundation; either version 2 of the License, or
8
 *  (at your option) any later version.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
42300 ripley 16
 *  along with this program; if not, a copy is available at
68956 ripley 17
 *  https://www.R-project.org/Licenses/
28991 murdoch 18
 */
19
 
20
 
21
#ifdef HAVE_CONFIG_H
22
#include <config.h>
23
#endif
33001 ripley 24
#include "win-nls.h"
28991 murdoch 25
 
26
#ifdef Win32
27
#define USE_MDI 1
28
#endif
29
 
40700 ripley 30
#include <Defn.h>
31
#include <Fileio.h>
28991 murdoch 32
#include <stdio.h>
33
#include <Startup.h>
34
#include "graphapp/ga.h"
35
#include "graphapp/graphapp.h"
36
#include "graphapp/stdimg.h"
37
#include "console.h"
38
#include "consolestructs.h"
36901 ripley 39
#define WIN32_LEAN_AND_MEAN 1
28991 murdoch 40
#include <windows.h>
41
#include "rui.h"
42
#include "editor.h"
43
 
63218 ripley 44
/* from sysutils.c */
45
void reEnc2(const char *x, char *y, int ny,
46
	    cetype_t ce_in, cetype_t ce_out, int subst);
47
 
39274 ripley 48
#define gettext GA_gettext
49
 
28991 murdoch 50
#define MCHECK(a) if (!(a)) {del(c); return NULL;}
44201 ripley 51
RECT *RgetMDIsize(void);
28991 murdoch 52
 
53
/* Pointers to currently open editors */
54
static editor REditors[MAXNEDITORS];
55
static int neditors  = 0;
56
static Rboolean fix_editor_up = FALSE;
57
 
43760 ripley 58
static EditorData neweditordata (int file, const char *filename)
28991 murdoch 59
{
60
    EditorData p;
61
    p = (EditorData) malloc(sizeof(struct structEditorData));
62
    p->file = file;
39498 ripley 63
    /* need space for terminator, and to copy it */
64
    p->filename = (char *) malloc((MAX_PATH+1)*sizeof(char));
28991 murdoch 65
    if (filename)
39498 ripley 66
	strncpy(p->filename, filename, MAX_PATH+1);
29062 murdoch 67
    p->title = (char *) malloc((EDITORMAXTITLE + 1)*sizeof(char));
68
    p->title[EDITORMAXTITLE] = p->title[0] = '\0';
28991 murdoch 69
    return p;
70
}
71
 
39498 ripley 72
void deleditordata(EditorData p)
73
{
28991 murdoch 74
    if (p->stealconsole)
75
	fix_editor_up = FALSE;
76
    free(p->filename);
29051 murdoch 77
    free(p->title);
36258 murdoch 78
    free(p->hmenu);
79
    free(p->pmenu);
28991 murdoch 80
    free(p);
81
}
82
 
43760 ripley 83
static void editor_set_title(editor c, const char *title)
39498 ripley 84
{
28991 murdoch 85
    char wtitle[EDITORMAXTITLE+1];
29051 murdoch 86
    textbox t = getdata(c);
87
    EditorData p = getdata(t);
88
    strncpy(wtitle, title, EDITORMAXTITLE);
29062 murdoch 89
    wtitle[EDITORMAXTITLE] = '\0';
29051 murdoch 90
    strcpy(p->title, wtitle);
43410 murdoch 91
    if (strlen(wtitle) + strlen(G_("R Editor")) + 3 < EDITORMAXTITLE) {
45070 ripley 92
	strcat(wtitle, " - ");
93
	strcat(wtitle, G_("R Editor"));
43410 murdoch 94
    }
28991 murdoch 95
    settext(c, wtitle);
96
}
97
 
98
/*** FILE MANAGEMENT FUNCTIONS ***/
99
 
46842 ripley 100
FILE *R_wfopen(const wchar_t *filename, const wchar_t *mode);
101
 
44016 ripley 102
static void editor_load_file(editor c, const char *name, int enc)
28991 murdoch 103
{
104
    textbox t = getdata(c);
105
    EditorData p = getdata(t);
106
    FILE *f;
63219 ripley 107
    char *buffer = NULL, tmp[MAX_PATH+50], tname[MAX_PATH+1];
108
    const char *sname;
39498 ripley 109
    long num = 1, bufsize;
110
 
46842 ripley 111
    if(enc == CE_UTF8) {
112
	wchar_t wname[MAX_PATH+1];
113
	Rf_utf8towcs(wname, name, MAX_PATH+1);
114
	f = R_wfopen(wname, L"r");
63218 ripley 115
	reEnc2(name, tname, MAX_PATH+1, CE_UTF8, CE_NATIVE, 3);
116
	sname = tname;
46842 ripley 117
    } else {
118
	f = R_fopen(name, "r");
119
	sname = name;
120
    }
121
    if (f == NULL) {
122
	snprintf(tmp, MAX_PATH+50, 
123
		 G_("unable to open file %s for reading"), sname);
124
	R_ShowMessage(tmp);
125
	return;
126
    }
28991 murdoch 127
    p->file = 1;
39498 ripley 128
    strncpy(p->filename, name, MAX_PATH+1);
28991 murdoch 129
    bufsize = 0;
130
    while (num > 0) {
39498 ripley 131
	buffer = realloc(buffer, bufsize + 3000 + 1);
132
	num = fread(buffer + bufsize, 1, 3000 - 1, f);
28991 murdoch 133
	if (num >= 0) {
134
	    bufsize += num;
135
	    buffer[bufsize] = '\0';
136
	}
137
	else {
46842 ripley 138
	    snprintf(tmp, MAX_PATH+50, 
139
		     G_("Could not read from file '%s'"), sname);
28991 murdoch 140
	    askok(tmp);
141
	}
142
    }
143
    setlimittext(t, 2 * strlen(buffer));
144
    settext(t, buffer);
145
    gsetmodified(t, 0);
146
    free(buffer);
147
    fclose(f);
148
}
149
 
46842 ripley 150
static void editor_save_file(editor c, const char *name, int enc)
28991 murdoch 151
{
152
    textbox t = getdata(c);
153
    FILE *f;
63219 ripley 154
    char buf[MAX_PATH+30], tname[MAX_PATH+1];
155
    const char *sname;
46842 ripley 156
 
28991 murdoch 157
    if (name == NULL)
158
	return;
159
    else {
46842 ripley 160
	if(enc == CE_UTF8) {
161
	    wchar_t wname[MAX_PATH+1];
162
	    Rf_utf8towcs(wname, name, MAX_PATH+1);
63218 ripley 163
	    reEnc2(name, tname, MAX_PATH+1, CE_UTF8, CE_NATIVE, 3);
164
	    sname = tname;
46842 ripley 165
	    f = R_wfopen(wname, L"w");
166
	} else {
167
	    sname = name;
168
	    f = R_fopen(sname, "w");
169
	}
28991 murdoch 170
	if (f == NULL) {
46842 ripley 171
	    snprintf(buf, MAX_PATH+30, G_("Could not save file '%s'"), sname);
28991 murdoch 172
	    askok(buf);
173
	    return;
174
	}
175
	fprintf(f, "%s", gettext(t));
176
	fclose(f);
177
    }
178
}
179
 
45070 ripley 180
static void editorsaveas(editor c)
181
{
28991 murdoch 182
    textbox t = getdata(c);
183
    EditorData p = getdata(t);
46842 ripley 184
    wchar_t *wname;
185
 
186
    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"), "");
50851 murdoch 188
    if (wname) {
46842 ripley 189
	char name[4*MAX_PATH+1];
72714 murdoch 190
	wcstoutf8(name, wname, sizeof(name));
57464 ripley 191
	/* now check if it has an extension */
192
	char *q = strchr(name, '.');
193
	if(!q) strncat(name, ".R", 4*MAX_PATH);
46842 ripley 194
	editor_save_file(c, name, CE_UTF8);
28991 murdoch 195
	p->file = 1;
63218 ripley 196
	reEnc2(name, p->filename, MAX_PATH+1, CE_UTF8, CE_NATIVE, 3);
28991 murdoch 197
	gsetmodified(t, 0);
63219 ripley 198
	editor_set_title(c, p->filename);
28991 murdoch 199
    }
50851 murdoch 200
    show(c);
28991 murdoch 201
}
202
 
203
static void menueditorsaveas(control m)
204
{
205
    editor c = getdata(m);
206
    editorsaveas(c);
207
}
208
 
209
static void editorsave(editor c)
210
{
211
    textbox t = getdata(c);
212
    EditorData p = getdata(t);
213
    if (p->file) {  /* save existing file without prompt */
46842 ripley 214
	editor_save_file(c, p->filename, CE_UTF8);
28991 murdoch 215
	gsetmodified(t, 0);
216
    }
217
    /* if new file then prompt for name to save as */
218
    else editorsaveas(c);
219
}
220
 
221
static void menueditorsave(control m)
222
{
223
    editor c = getdata(m);
224
    editorsave(c);
225
    show(c); /* steal focus back from tool button */
226
}
227
 
228
/* global console configuration variables */
229
char fontname[LF_FACESIZE+1];
230
int fontsty, pointsize;
231
 
232
static void editorprint(control m)
233
{
234
    printer lpr;
235
    font f;
236
    textbox t = getdata(m);
43800 ripley 237
    const char *contents = gettext(t);
28991 murdoch 238
    char msg[LF_FACESIZE + 128];
239
    char *linebuf = NULL;
240
    int cc, rr, fh, page, linep, i, j, istartline;
241
    int top, left;
242
 
243
    if (!(lpr = newprinter(0.0, 0.0, ""))) return;
244
    f = gnewfont(lpr, strcmp(fontname, "FixedFont") ? fontname : "Courier New",
44575 ripley 245
		 fontsty, pointsize, 0.0, 1);
28991 murdoch 246
    top = devicepixelsy(lpr) / 5;
247
    left = devicepixelsx(lpr) / 5;
248
    fh = fontheight(f);
249
    rr = getheight(lpr) - top;
250
    cc = getwidth(lpr) - 2*left;
251
 
252
    linep = rr; /* line in printer page */
253
    page = 1;
254
    i = 0;
255
    while (i < strlen(contents)) {
256
	if ( linep + fh >= rr ) { /* new page */
257
	    if (page > 1) nextpage(lpr);
62583 ripley 258
	    snprintf(msg, LF_FACESIZE + 128, "Page %d", page++);
45070 ripley 259
	    gdrawstr(lpr, f, Black, pt(cc - gstrwidth(lpr, f, msg) - 1, top),
39498 ripley 260
		     msg);
28991 murdoch 261
	    linep = top + 2*fh;
262
	}
263
	j = 0;
264
	istartline = i;
265
	while (contents[i] != '\n' && contents[i] != '\0') {
266
	    ++i; ++j;
267
	}
268
	linebuf = realloc(linebuf, (j+1)*sizeof(char));
269
	strncpy(linebuf, &contents[istartline], j);
270
	linebuf[j] = '\0';
45070 ripley 271
	gdrawstr(lpr, f, Black, pt(left, linep), linebuf);
28991 murdoch 272
	linep += fh;
273
	++i;
274
    }
275
    free(linebuf);
276
    if (f != FixedFont) del(f);
277
    del(lpr);
278
}
279
 
280
static void editorconsole(editor c)
281
{
282
    show(RConsole);
283
}
284
 
39498 ripley 285
/* Remove global pointer to editor when closing an editor. Fill the
286
 * gap in the array with the last editor in the list */
28991 murdoch 287
 
39498 ripley 288
static void editorupdateglobals(editor c)
289
{
290
    int i = 0;
28991 murdoch 291
    if (neditors > 1) {
292
	while (REditors[i] != c) ++i;
293
	if (i < neditors - 1)
294
	    REditors[i] = REditors[neditors-1];
295
    }
296
    --neditors;
297
}
298
 
29062 murdoch 299
/* Hooks called when editor window is destroyed */
28991 murdoch 300
 
39498 ripley 301
static void editordel(editor c)
302
{
29062 murdoch 303
    editorupdateglobals(c);
304
}
305
 
39498 ripley 306
static void textboxdel(textbox t)
307
{
28991 murdoch 308
    EditorData p = getdata(t);
309
    deleditordata(p);
310
}
311
 
39498 ripley 312
int editorchecksave(editor c)
313
{
28991 murdoch 314
    textbox t = getdata(c);
315
    EditorData p = getdata(t);
316
    int save;
317
    char buf[EDITORMAXTITLE + 100];
318
    if (ggetmodified(t)) {
33756 ripley 319
	snprintf(buf, EDITORMAXTITLE + 100,
32604 ripley 320
		 "\"%s\" has been modified.  Do you want to save the changes?",
29051 murdoch 321
		 (p->title ? p->title : "Untitled"));
28991 murdoch 322
	save = askyesnocancel(buf);
323
	switch (save) {
324
	case YES:
325
	    editorsave(c);
326
	    break;
327
	case NO:
328
	    break;
329
	case CANCEL:
61963 ripley 330
	    return 1;
28991 murdoch 331
	}
332
    }
333
    return 0;
334
}
335
 
336
static void editorclose(editor c)
337
{
338
    if (!editorchecksave(c))
339
	del(c);
340
}
341
 
342
static void menueditorclose(control m)
343
{
344
    editor c = getdata(m);
345
    editorclose(c);
346
}
347
 
348
/* Called when exiting Rgui, check if any open editors need saving */
349
 
44201 ripley 350
void editorcleanall(void)
28991 murdoch 351
{
352
    int i;
353
    for (i = neditors-1;  i >= 0; --i) {
61963 ripley 354
	if (editorchecksave(REditors[i])) {
355
	    R_ProcessEvents();  // see R_CleanUp
356
	    jump_to_toplevel();
357
	}
28991 murdoch 358
	del(REditors[i]);
359
    }
360
}
361
 
44201 ripley 362
static void editornew(void)
28991 murdoch 363
{
44016 ripley 364
    Rgui_Edit("", CE_NATIVE, "", 0);
28991 murdoch 365
}
366
 
367
void menueditornew(control m)
368
{
369
    editornew();
370
}
371
 
43760 ripley 372
static void editoropen(const char *default_name)
28991 murdoch 373
{
46842 ripley 374
    wchar_t *wname;
72714 murdoch 375
    char name[4*MAX_PATH + 1], title[4*MAX_PATH];
46842 ripley 376
 
28991 murdoch 377
    int i; textbox t; EditorData p;
46842 ripley 378
    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 */
380
    if (wname) {
72714 murdoch 381
	wcstoutf8(name, wname, sizeof(name));
28991 murdoch 382
	/* check if file is already open in an editor. If so, close and open again */
39498 ripley 383
	for (i = 0; i < neditors; ++i) {
28991 murdoch 384
	    t = getdata(REditors[i]);
385
	    p = getdata(t);
386
	    if (!strcmp (name, p->filename)) {
387
		editorclose(REditors[i]);
388
		break;
389
	    }
390
	}
63218 ripley 391
	reEnc2(name, title, MAX_PATH+1, CE_UTF8, CE_NATIVE, 3);
46842 ripley 392
	Rgui_Edit(name, CE_UTF8, title, 0);
50851 murdoch 393
    } else show(RConsole);
28991 murdoch 394
}
395
 
396
void menueditoropen(control m)
397
{
398
    editor c = getdata(m);
399
    char *default_name = "";
45070 ripley 400
    /* It really is not clear what is meant here: seems to assume an
401
       editor window but is called from elsewhere, hopefully with NULL
35234 ripley 402
       (since 2.1.1 patched). */
28991 murdoch 403
    if (c) {
404
	textbox t = getdata(c);
405
	EditorData p = getdata(t);
406
	if (p->file) default_name = p->filename;  /* name of currently-open file, if there is one */
407
    }
408
    editoropen(default_name);
409
}
410
 
411
 
412
/*** EDITING FUNCTIONS ***/
413
 
414
static void editorundo(control m)
415
{
416
    textbox t = getdata(m);
417
    undotext(t);
418
}
419
 
420
static void editorcut(control m)
421
{
422
    textbox t = getdata(m);
423
    cuttext(t);
424
}
425
 
426
static void editorcopy(control m)
427
{
428
    textbox t = getdata(m);
429
    copytext(t);
430
}
431
 
432
static void editorpaste(control m)
433
{
434
    textbox t = getdata(m);
39498 ripley 435
    /* check whether the widget text limit needs to be increased
436
     * before doing the paste */
28991 murdoch 437
    int pastelen = getpastelength();
438
    checklimittext(t, pastelen + 1);
439
    pastetext(t);
440
}
441
 
442
static void editordelete(control m)
443
{
444
    textbox t = getdata(m);
445
    cleartext(t);
446
}
447
 
448
static void editorselectall(control m)
449
{
450
    textbox t = getdata(m);
451
    selecttextex(t, 0, -1);
452
}
453
 
454
static void editorfind(control m)
455
{
456
    textbox t = getdata(m);
457
    finddialog(t);  /* actual find/replace work is in graphapp/dialogs.c */
458
}
459
 
460
static void editorreplace(control m)
461
{
462
    textbox t = getdata(m);
463
    replacedialog(t);
464
}
465
 
466
 
467
/*** FUNCTIONS FOR RUNNING R CODE FROM THE EDITOR ***/
468
 
469
static void editorrunline(textbox t)
470
{
38972 ripley 471
    int length = getlinelength(t); /* return character num */
472
    char *line = malloc(length * sizeof(WCHAR) + 2); /* Extra space for null and word length in getcurrentline */
473
    memset(line, 0, length * sizeof(WCHAR) + 2);
28991 murdoch 474
    getcurrentline(t, line, length);
475
    consolecmd(RConsole, line);
476
    free(line);
477
    scrollcaret(t, 1);
478
    show(t);
479
}
480
 
481
/* For the moment, send the selected text to the console via the
482
   clipboard. Wasteful, but currently consolecmd only allows a maximum
483
   of 8K of text */
484
 
485
static void editorrunselection(textbox t, long start, long end)
486
{
487
    copytext(t);
488
    if (consolecanpaste(RConsole)) {
489
	consolepaste(RConsole);
490
	if (gettext(t)[end-1] != '\n')
491
	    consolenewline(RConsole);
492
    }
493
}
494
 
29001 murdoch 495
static Rboolean busy_running = FALSE;
496
 
28991 murdoch 497
static void editorrun(textbox t)
498
{
29001 murdoch 499
    if (!busy_running) {
45070 ripley 500
	long start=0, end=0;
501
	if (CharacterMode != RGui) {
502
	    R_ShowMessage(G_("No RGui console to paste to"));
503
	    return;
504
	}
505
	busy_running = TRUE;
506
	textselectionex(t, &start, &end);
507
	if (start >= end)
29001 murdoch 508
	    editorrunline(t);
45070 ripley 509
	else {
29001 murdoch 510
	    editorrunselection(t, start, end);
511
	    selecttextex(t, end, end); /* move insertion point to end of selection after running */
45070 ripley 512
	}
513
	busy_running = FALSE;
28991 murdoch 514
    }
515
}
516
 
517
static void menueditorrun(control m)
518
{
519
    textbox t = getdata(m);
520
    editorrun(t);
521
}
522
 
523
static void editorrunall(control m)
524
{
525
    textbox t = getdata(m);
526
    long start=0, end=0;
527
    textselectionex(t, &start, &end); /* save current selection state */
528
    selecttextex(t, 0, -1);
29001 murdoch 529
    editorrun(t);
28991 murdoch 530
    selecttextex(t, start, end);  /* return to original selection state */
531
}
532
 
533
/* Grey out menu buttons as appropriate */
534
 
535
static void editormenuact(control m)
536
{
537
    long start, end;
538
    textbox t = getdata(m);
539
    EditorData p = getdata(t);
540
    textselectionex(t, &start, &end);
541
    if (start < end) {
45070 ripley 542
	enable(p->mcut);
543
	enable(p->mcopy);
544
	enable(p->mdelete);
545
	enable(p->mpopcut);
546
	enable(p->mpopcopy);
547
	enable(p->mpopdelete);
28991 murdoch 548
    }
549
    else {
550
	disable(p->mcut);
551
	disable(p->mcopy);
552
	disable(p->mdelete);
553
	disable(p->mpopcut);
554
	disable(p->mpopcopy);
555
	disable(p->mpopdelete);
556
    }
557
    if (modeless_active()){
558
	disable(p->mfind);
559
	disable(p->mreplace);
560
    }
561
    else {
562
	enable(p->mfind);
563
	enable(p->mreplace);
564
    }
36258 murdoch 565
    helpmenuact(p->hmenu);
566
    pkgmenuact(p->pmenu);
28991 murdoch 567
}
568
 
569
static void editorresize(editor c, rect r)
570
{
571
    resize(getdata(c), r);
572
    resize(c, r);
573
}
574
 
575
static void editorcontrolkeydown(textbox t, int key)
576
{
577
    switch (key) {
578
    case F5:
579
	editorrun(t);
580
	break;
581
    }
582
}
583
 
584
static void editorasciikeydown(textbox t, int key)
585
{
586
    /* check whether the text limit is about to be exceeded and
45070 ripley 587
       increase it if necessary.  Ugh - this callback is called after
588
       the text is inserted, so we make space for two characters */
28991 murdoch 589
    checklimittext(t, 2);
590
}
591
 
592
/* Set keyboard focus to the text editing area when the editor window receives focus */
593
 
594
static void editorfocus(editor c)
595
{
596
    textbox t = getdata(c);
597
    show(t);
598
}
599
 
44201 ripley 600
static void editorhelp(void)
28991 murdoch 601
{
602
    char s[4096];
603
 
39498 ripley 604
    strcpy(s, G_("R EDITOR\n"));
605
    strcat(s, "\n");
606
    strcat(s, G_("A standard text editor for editing and running R code.\n"));
607
    strcat(s, "\n");
608
    strcat(s, G_("RUNNING COMMANDS\n"));
609
    strcat(s, G_("To run a line or section of R code, select the code and either\n"));
610
    strcat(s, G_("     Press Ctrl-R\n"));
611
    strcat(s, G_("     Select \"Run line or selection\" from the \"Edit\" menu\n"));
612
    strcat(s, G_("     Press the \"Run line or selection\" icon on the toolbar\n"));
613
    strcat(s, G_("This will copy the selected commands to the console and evaluate them.\n"));
614
    strcat(s, G_("If there is no selection, this will just run the current line and advance\n"));
615
    strcat(s, G_("the cursor by one line.\n"));
28991 murdoch 616
 
617
    askok(s);
618
}
619
 
620
 
621
static void menueditorhelp(control m)
622
{
623
    editorhelp();
624
}
625
 
626
static MenuItem EditorPopup[] = {                /* Numbers used below */
33001 ripley 627
    {GN_("Run line or selection"), menueditorrun, 'R', 0}, /* 0 */
28991 murdoch 628
    {"-", 0, 0, 0},
33001 ripley 629
    {GN_("Undo"), editorundo, 'Z', 0},                     /* 2 */
28991 murdoch 630
    {"-", 0, 0, 0},
33001 ripley 631
    {GN_("Cut"), editorcut, 'X', 0},                       /* 4 */
632
    {GN_("Copy"), editorcopy, 'C', 0},                     /* 5 */
633
    {GN_("Paste"), editorpaste, 'V', 0},                   /* 6 */
634
    {GN_("Delete"), editordelete, 0, 0},                   /* 7 */
28991 murdoch 635
    {"-", 0, 0, 0},
33001 ripley 636
    {GN_("Select all"), editorselectall, 'A', 0},          /* 9 */
28991 murdoch 637
    LASTMENUITEM
638
};
639
 
44201 ripley 640
static editor neweditor(void)
28991 murdoch 641
{
642
    int x, y, w, h, w0, h0;
643
    editor c;
644
    menuitem m;
645
    textbox t;
646
    long flags;
647
    font editorfn = (consolefn ? consolefn : FixedFont);
648
    EditorData p = neweditordata(0, NULL);
649
    DWORD rand;
650
 
651
    w = (pagercol + 1)*fontwidth(editorfn);
652
    h = (pagerrow + 1)*fontheight(editorfn) + 1;
653
#ifdef USE_MDI
654
    if(ismdi()) {
655
	RECT *pR = RgetMDIsize();
656
	w0 = pR->right;
657
	h0 = pR->bottom;
658
    } else {
659
#endif
660
	w0 = devicewidth(NULL);
661
	h0 = deviceheight(NULL);
662
#ifdef USE_MDI
663
    }
664
#endif
665
    x = (w0 - w) / 2; x = x > 20 ? x : 20;
666
    y = (h0 - h) / 2; y = y > 20 ? y : 20;
667
    rand = GetTickCount();
668
    w0 = 0.4*x; h0 = 0.4*y;
669
    w0 = w0 > 20 ? w0 : 20;
670
    h0 = h0 > 20 ? h0 : 20;
671
    x += (rand % w0) - w0/2;
672
    y += ((rand/w0) % h0) - h0/2;
673
    flags = StandardWindow | Menubar;
674
#ifdef USE_MDI
675
    if (ismdi()) flags |= Document;
676
#endif
677
    c = (editor) newwindow("", rect(x, y, w, h), flags);
678
    t = newrichtextarea(NULL, rect(0, 0, w, h));
679
    setdata(c, t);
680
    setdata(t, p);
681
 
682
    gsetcursor(c, ArrowCursor);
46784 murdoch 683
    setforeground(c, guiColors[editorfg]);
684
    setbackground(c, guiColors[editorbg]);
685
    setbackground(t, guiColors[editorbg]);
46774 murdoch 686
 
28991 murdoch 687
#ifdef USE_MDI
688
    if (ismdi() && (RguiMDI & RW_TOOLBAR)) {
689
	int btsize = 24;
690
	rect r = rect(2, 2, btsize, btsize);
691
	control tb, bt;
692
	addto(c);
693
	MCHECK(tb = newtoolbar(btsize + 4));
694
	addto(tb);
695
	MCHECK(bt = newtoolbutton(open_image, r, menueditoropen));
33001 ripley 696
	MCHECK(addtooltip(bt, G_("Open script")));
28991 murdoch 697
	setdata(bt, c);
698
	r.x += (btsize + 1) ;
699
	MCHECK(bt = newtoolbutton(save_image, r, menueditorsave));
33001 ripley 700
	MCHECK(addtooltip(bt,  G_("Save script")));
28991 murdoch 701
	setdata(bt, c);
702
	r.x += (btsize + 6);
703
	MCHECK(bt = newtoolbutton(copy1_image, r, menueditorrun));
33001 ripley 704
	MCHECK(addtooltip(bt, G_("Run line or selection")));
28991 murdoch 705
	setdata(bt, t);
706
	r.x += (btsize + 6);
707
	MCHECK(bt = newtoolbutton(console_image, r, editorconsole));
33001 ripley 708
	MCHECK(addtooltip(bt, G_("Return focus to Console")));
28991 murdoch 709
	r.x += (btsize + 6);
710
	MCHECK(bt = newtoolbutton(print_image, r, editorprint));
33001 ripley 711
	MCHECK(addtooltip(bt, G_("Print script")));
28991 murdoch 712
	setdata(bt, t);
33001 ripley 713
	MCHECK(addtooltip(bt, G_("Print")));
28991 murdoch 714
    }
715
#endif
716
    addto(c);
717
    /* Right-click context menu */
718
    MCHECK(m = gpopup(editormenuact, EditorPopup));
719
    setdata(m, t);
720
    setdata(EditorPopup[0].m, t);
721
    setdata(EditorPopup[2].m, t);
722
    setdata(p->mpopcut = EditorPopup[4].m, t);
723
    setdata(p->mpopcopy = EditorPopup[5].m, t);
724
    setdata(EditorPopup[6].m, t);
725
    setdata(p->mpopdelete = EditorPopup[7].m, t);
726
    setdata(EditorPopup[9].m, t);
727
 
728
    addto(c);
729
    MCHECK(m = newmenubar(editormenuact));
730
    setdata(m, t);
33001 ripley 731
    MCHECK(newmenu(G_("File")));
732
    MCHECK(m = newmenuitem(G_("New script"), 'N', menueditornew));
28991 murdoch 733
    setdata(m, c);
33001 ripley 734
    MCHECK(m = newmenuitem(G_("Open script..."), 'O', menueditoropen));
28991 murdoch 735
    setdata(m, c);
33001 ripley 736
    MCHECK(m = newmenuitem(G_("Save"), 'S', menueditorsave));
28991 murdoch 737
    setdata(m, c);
33001 ripley 738
    MCHECK(m = newmenuitem(G_("Save as..."), 0, menueditorsaveas));
28991 murdoch 739
    setdata(m, c);
740
    MCHECK(m = newmenuitem("-", 0, NULL));
69561 murdoch 741
    MCHECK(m = newmenuitem(G_("Print..."), 'P', editorprint));
28991 murdoch 742
    setdata(m, t);
743
    MCHECK(m = newmenuitem("-", 0, NULL));
33001 ripley 744
    MCHECK(m = newmenuitem(G_("Close script"), 0, menueditorclose));
28991 murdoch 745
    setdata(m, c);
33001 ripley 746
    MCHECK(newmenu(G_("Edit")));
747
    MCHECK(m = newmenuitem(G_("Undo"), 'Z', editorundo));
28991 murdoch 748
    setdata(m, t);
749
    MCHECK(m = newmenuitem("-", 0, NULL));
33001 ripley 750
    MCHECK(p->mcut = newmenuitem(G_("Cut"), 'X', editorcut));
28991 murdoch 751
    setdata(p->mcut, t);
33001 ripley 752
    MCHECK(p->mcopy = newmenuitem(G_("Copy"), 'C', editorcopy));
28991 murdoch 753
    setdata(p->mcopy, t);
33001 ripley 754
    MCHECK(m = newmenuitem(G_("Paste"), 'V', editorpaste));
28991 murdoch 755
    setdata(m, t);
33001 ripley 756
    MCHECK(p->mdelete = newmenuitem(G_("Delete"), 0, editordelete));
28991 murdoch 757
    setdata(p->mdelete, t);
33001 ripley 758
    MCHECK(m = newmenuitem(G_("Select all"), 'A', editorselectall));
28991 murdoch 759
    setdata(m, t);
33001 ripley 760
    MCHECK(newmenuitem(G_("Clear console"), 'L', menuclear));
28991 murdoch 761
    MCHECK(m = newmenuitem("-", 0, NULL));
33001 ripley 762
    MCHECK(m = newmenuitem(G_("Run line or selection"), 'R', menueditorrun));
28991 murdoch 763
    setdata(m, t);
33001 ripley 764
    MCHECK(m = newmenuitem(G_("Run all"), 0, editorrunall));
28991 murdoch 765
    setdata(m, t);
766
    MCHECK(m = newmenuitem("-", 0, NULL));
33001 ripley 767
    MCHECK(p->mfind = newmenuitem(G_("Find..."), 'F', editorfind));
28991 murdoch 768
    setdata(p->mfind, t);
33001 ripley 769
    MCHECK(p->mreplace = newmenuitem(G_("Replace..."), 'H', editorreplace));
28991 murdoch 770
    setdata(p->mreplace, t);
771
    MCHECK(m = newmenuitem("-", 0, NULL));
33001 ripley 772
    MCHECK(newmenuitem(G_("GUI preferences..."), 0, menuconfig));
28991 murdoch 773
 
774
    /* Packages menu should go here */
36258 murdoch 775
    p->pmenu = (PkgMenuItems) malloc(sizeof(struct structPkgMenuItems));
776
    RguiPackageMenu(p->pmenu);
777
 
28991 murdoch 778
#ifdef USE_MDI
779
    newmdimenu(); /* Create and fill the 'Window' menu */
780
#endif
781
 
33001 ripley 782
    MCHECK(m = newmenu(G_("Help")));
783
    MCHECK(newmenuitem(G_("Editor"), 0, menueditorhelp));
28991 murdoch 784
    MCHECK(newmenuitem("-", 0, NULL));
36258 murdoch 785
    p->hmenu = (HelpMenuItems) malloc(sizeof(struct structHelpMenuItems));
786
    RguiCommonHelp(m, p->hmenu);
28991 murdoch 787
 
788
    settextfont(t, editorfn);
46784 murdoch 789
    setforeground(t, guiColors[editorfg]);    
28991 murdoch 790
    setresize(c, editorresize);
791
    setclose(c, editorclose);
792
    setdel(c, editordel);
29062 murdoch 793
    setdel(t, textboxdel);
28991 murdoch 794
    setonfocus(c, editorfocus);
795
    setkeyaction(t, editorcontrolkeydown);
796
    setkeydown(t, editorasciikeydown);
797
 
798
    /* Store pointer to new editor in global array */
799
    REditors[neditors] = c;
800
    ++neditors;
801
    return c;
802
}
803
 
804
/* Change the font used in all running editors */
805
 
806
void editorsetfont(font f)
807
{
808
    int i, ismod;
809
    textbox t;
33756 ripley 810
    for (i = 0; i < neditors; i++) {
28991 murdoch 811
	t = getdata(REditors[i]);
45070 ripley 812
	ismod = ggetmodified(t);
33756 ripley 813
	/* Don't change the modification flag when changing font  */
28991 murdoch 814
	settextfont(t, f);
815
	gsetmodified(t, ismod);
816
	show(t);
817
    }
818
}
819
 
820
static void eventloop(editor c)
821
{
822
    while (fix_editor_up) {
823
	/* avoid consuming 100% CPU time here */
64106 murdoch 824
	R_WaitEvent();
28991 murdoch 825
	R_ProcessEvents();
826
    }
827
}
828
 
829
/* Open existing file for editing or open blank editor for a new
830
   file. If calling from fix() or edit(), then don't send events to
831
   the console until editor is closed.  */
832
 
29219 ripley 833
#include <unistd.h>
834
 
44016 ripley 835
int Rgui_Edit(const char *filename, int enc, const char *title,
836
	      int modal)
28991 murdoch 837
{
838
    editor c;
839
    EditorData p;
29219 ripley 840
 
28991 murdoch 841
    if (neditors == MAXNEDITORS) {
33001 ripley 842
	R_ShowMessage(G_("Maximum number of editors reached"));
28991 murdoch 843
	return 1;
844
    }
845
    c = neweditor();
846
    if (!c) {
33001 ripley 847
	R_ShowMessage(G_("Unable to create editor window"));
28991 murdoch 848
	return 1;
849
    }
850
    if (strlen(filename) > 0) {
46842 ripley 851
	editor_load_file(c, filename, enc);
29051 murdoch 852
	editor_set_title(c, title);
28991 murdoch 853
    }
854
    else {
33001 ripley 855
	editor_set_title(c, G_("Untitled"));
28991 murdoch 856
    }
857
    show(c);
45070 ripley 858
 
36252 murdoch 859
    p = getdata(getdata(c));
44016 ripley 860
    p->stealconsole = modal;
861
    if (modal) {
45070 ripley 862
	fix_editor_up = TRUE;
863
	eventloop(c);
36258 murdoch 864
    }
28991 murdoch 865
    return 0;
866
}