~ubuntu-branches/ubuntu/quantal/mc/quantal

« back to all changes in this revision

Viewing changes to .pc/2832.patch/src/editor/editcmd.c

  • Committer: Package Import Robot
  • Author(s): Dmitry Smirnov
  • Date: 2012-08-25 12:19:25 UTC
  • mfrom: (4.2.19 sid)
  • Revision ID: package-import@ubuntu.com-20120825121925-735z18zgbebhp08i
Tags: 3:4.8.3-6
* xz compression for binary packages.
* new backported patches:
  + to fix "refresh problem in directory tree view" (Closes: #675692).
  + to fix "mcedit can't save file in safe mode" (Closes: #673252).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   Editor high level editing commands
 
3
 
 
4
   Copyright (C) 1996, 1997, 1998, 2001, 2002, 2003, 2004, 2005, 2006,
 
5
   2007, 2011
 
6
   The Free Software Foundation, Inc.
 
7
 
 
8
   Written by:
 
9
   Paul Sheer, 1996, 1997
 
10
 
 
11
   This file is part of the Midnight Commander.
 
12
 
 
13
   The Midnight Commander is free software: you can redistribute it
 
14
   and/or modify it under the terms of the GNU General Public License as
 
15
   published by the Free Software Foundation, either version 3 of the License,
 
16
   or (at your option) any later version.
 
17
 
 
18
   The Midnight Commander is distributed in the hope that it will be useful,
 
19
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
20
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
21
   GNU General Public License for more details.
 
22
 
 
23
   You should have received a copy of the GNU General Public License
 
24
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
25
 */
 
26
 
 
27
/** \file
 
28
 *  \brief Source: editor high level editing commands
 
29
 *  \author Paul Sheer
 
30
 *  \date 1996, 1997
 
31
 */
 
32
 
 
33
/* #define PIPE_BLOCKS_SO_READ_BYTE_BY_BYTE */
 
34
 
 
35
#include <config.h>
 
36
 
 
37
#ifdef HAVE_ASSERT_H
 
38
#include <assert.h>
 
39
#endif
 
40
#include <ctype.h>
 
41
 
 
42
#include <stdio.h>
 
43
#include <stdarg.h>
 
44
#include <sys/types.h>
 
45
#include <unistd.h>
 
46
#include <string.h>
 
47
#include <errno.h>
 
48
#include <sys/stat.h>
 
49
#include <stdlib.h>
 
50
#include <fcntl.h>
 
51
 
 
52
#include "lib/global.h"
 
53
#include "lib/tty/tty.h"
 
54
#include "lib/tty/key.h"        /* XCTRL */
 
55
#include "lib/mcconfig.h"
 
56
#include "lib/skin.h"
 
57
#include "lib/strutil.h"        /* utf string functions */
 
58
#include "lib/lock.h"
 
59
#include "lib/util.h"           /* tilde_expand() */
 
60
#include "lib/vfs/vfs.h"
 
61
#include "lib/widget.h"
 
62
#include "lib/charsets.h"
 
63
#include "lib/event.h"          /* mc_event_raise() */
 
64
 
 
65
#include "src/history.h"
 
66
#include "src/setup.h"          /* option_tab_spacing */
 
67
#include "src/main.h"           /* mactos_t */
 
68
#include "src/selcodepage.h"
 
69
#include "src/keybind-defaults.h"
 
70
#include "src/util.h"           /* check_for_default() */
 
71
#include "src/filemanager/layout.h"     /* mc_refresh()  */
 
72
 
 
73
#include "edit-impl.h"
 
74
#include "edit-widget.h"
 
75
#include "editcmd_dialogs.h"
 
76
#include "etags.h"
 
77
 
 
78
/*** global variables ****************************************************************************/
 
79
 
 
80
/* search and replace: */
 
81
int search_create_bookmark = FALSE;
 
82
 
 
83
/* queries on a save */
 
84
int edit_confirm_save = 1;
 
85
 
 
86
/*** file scope macro definitions ****************************************************************/
 
87
 
 
88
#define space_width 1
 
89
 
 
90
#define TEMP_BUF_LEN 1024
 
91
 
 
92
#define INPUT_INDEX 9
 
93
 
 
94
/* thanks to  Liviu Daia <daia@stoilow.imar.ro>  for getting this
 
95
   (and the above) routines to work properly - paul */
 
96
 
 
97
#define is_digit(x) ((x) >= '0' && (x) <= '9')
 
98
 
 
99
#define MAIL_DLG_HEIGHT 12
 
100
 
 
101
#define MAX_WORD_COMPLETIONS 100        /* in listbox */
 
102
 
 
103
/*** file scope type declarations ****************************************************************/
 
104
 
 
105
/*** file scope variables ************************************************************************/
 
106
 
 
107
/*** file scope functions ************************************************************************/
 
108
/* --------------------------------------------------------------------------------------------- */
 
109
 
 
110
/*  If 0 (quick save) then  a) create/truncate <filename> file,
 
111
   b) save to <filename>;
 
112
   if 1 (safe save) then   a) save to <tempnam>,
 
113
   b) rename <tempnam> to <filename>;
 
114
   if 2 (do backups) then  a) save to <tempnam>,
 
115
   b) rename <filename> to <filename.backup_ext>,
 
116
   c) rename <tempnam> to <filename>. */
 
117
 
 
118
/* returns 0 on error, -1 on abort */
 
119
 
 
120
static int
 
121
edit_save_file (WEdit * edit, const vfs_path_t * filename_vpath)
 
122
{
 
123
    char *p;
 
124
    gchar *tmp;
 
125
    long filelen = 0;
 
126
    int this_save_mode, fd = -1;
 
127
    vfs_path_t *real_filename_vpath;
 
128
    vfs_path_t *savename_vpath = NULL;
 
129
    const char *start_filename;
 
130
    const vfs_path_element_t *vpath_element;
 
131
 
 
132
    vpath_element = vfs_path_get_by_index (filename_vpath, 0);
 
133
    if (vpath_element == NULL)
 
134
        return 0;
 
135
 
 
136
    start_filename = vpath_element->path;
 
137
    if (*start_filename == '\0')
 
138
        return 0;
 
139
 
 
140
    if (*start_filename != PATH_SEP && edit->dir_vpath != NULL)
 
141
    {
 
142
        real_filename_vpath = vfs_path_append_vpath_new (edit->dir_vpath, filename_vpath, NULL);
 
143
    }
 
144
    else
 
145
    {
 
146
        real_filename_vpath = vfs_path_clone (filename_vpath);
 
147
    }
 
148
 
 
149
    this_save_mode = option_save_mode;
 
150
    if (this_save_mode != EDIT_QUICK_SAVE)
 
151
    {
 
152
        if (!vfs_file_is_local (real_filename_vpath)
 
153
            || (fd = mc_open (real_filename_vpath, O_RDONLY | O_BINARY)) == -1)
 
154
        {
 
155
            /*
 
156
             * The file does not exists yet, so no safe save or
 
157
             * backup are necessary.
 
158
             */
 
159
            this_save_mode = EDIT_QUICK_SAVE;
 
160
        }
 
161
        if (fd != -1)
 
162
            mc_close (fd);
 
163
    }
 
164
 
 
165
    if (this_save_mode == EDIT_QUICK_SAVE && !edit->skip_detach_prompt)
 
166
    {
 
167
        int rv;
 
168
        struct stat sb;
 
169
 
 
170
        rv = mc_stat (real_filename_vpath, &sb);
 
171
        if (rv == 0 && sb.st_nlink > 1)
 
172
        {
 
173
            rv = edit_query_dialog3 (_("Warning"),
 
174
                                     _("File has hard-links. Detach before saving?"),
 
175
                                     _("&Yes"), _("&No"), _("&Cancel"));
 
176
            switch (rv)
 
177
            {
 
178
            case 0:
 
179
                this_save_mode = EDIT_SAFE_SAVE;
 
180
                /* fallthrough */
 
181
            case 1:
 
182
                edit->skip_detach_prompt = 1;
 
183
                break;
 
184
            default:
 
185
                vfs_path_free (real_filename_vpath);
 
186
                return -1;
 
187
            }
 
188
        }
 
189
 
 
190
        /* Prevent overwriting changes from other editor sessions. */
 
191
        if (rv == 0 && edit->stat1.st_mtime != 0 && edit->stat1.st_mtime != sb.st_mtime)
 
192
        {
 
193
            /* The default action is "Cancel". */
 
194
            query_set_sel (1);
 
195
 
 
196
            rv = edit_query_dialog2 (_("Warning"),
 
197
                                     _("The file has been modified in the meantime. Save anyway?"),
 
198
                                     _("&Yes"), _("&Cancel"));
 
199
            if (rv != 0)
 
200
            {
 
201
                vfs_path_free (real_filename_vpath);
 
202
                return -1;
 
203
            }
 
204
        }
 
205
    }
 
206
 
 
207
    if (this_save_mode != EDIT_QUICK_SAVE)
 
208
    {
 
209
        char *savedir, *saveprefix;
 
210
 
 
211
        savedir = vfs_path_tokens_get (real_filename_vpath, 0, -1);
 
212
        if (savedir == NULL)
 
213
            savedir = g_strdup (".");
 
214
 
 
215
        saveprefix = mc_build_filename (savedir, "cooledit", NULL);
 
216
        g_free (savedir);
 
217
        fd = mc_mkstemps (&savename_vpath, saveprefix, NULL);
 
218
        g_free (saveprefix);
 
219
        if (savename_vpath == NULL)
 
220
        {
 
221
            vfs_path_free (real_filename_vpath);
 
222
            return 0;
 
223
        }
 
224
        /* FIXME:
 
225
         * Close for now because mc_mkstemps use pure open system call
 
226
         * to create temporary file and it needs to be reopened by
 
227
         * VFS-aware mc_open().
 
228
         */
 
229
        close (fd);
 
230
    }
 
231
    else
 
232
        savename_vpath = vfs_path_clone (real_filename_vpath);
 
233
 
 
234
    (void) mc_chown (savename_vpath, edit->stat1.st_uid, edit->stat1.st_gid);
 
235
    (void) mc_chmod (savename_vpath, edit->stat1.st_mode);
 
236
 
 
237
    fd = mc_open (savename_vpath, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, edit->stat1.st_mode);
 
238
    if (fd == -1)
 
239
        goto error_save;
 
240
 
 
241
    /* pipe save */
 
242
    p = edit_get_write_filter (savename_vpath, real_filename_vpath);
 
243
    if (p != NULL)
 
244
    {
 
245
        FILE *file;
 
246
 
 
247
        mc_close (fd);
 
248
        file = (FILE *) popen (p, "w");
 
249
 
 
250
        if (file)
 
251
        {
 
252
            filelen = edit_write_stream (edit, file);
 
253
#if 1
 
254
            pclose (file);
 
255
#else
 
256
            if (pclose (file) != 0)
 
257
            {
 
258
                tmp = g_strdup_printf (_("Error writing to pipe: %s"), p);
 
259
                edit_error_dialog (_("Error"), tmp);
 
260
                g_free (tmp);
 
261
                g_free (p);
 
262
                goto error_save;
 
263
            }
 
264
#endif
 
265
        }
 
266
        else
 
267
        {
 
268
            tmp = g_strdup_printf (_("Cannot open pipe for writing: %s"), p);
 
269
            edit_error_dialog (_("Error"), get_sys_error (tmp));
 
270
            g_free (p);
 
271
            g_free (tmp);
 
272
            goto error_save;
 
273
        }
 
274
        g_free (p);
 
275
    }
 
276
    else if (edit->lb == LB_ASIS)
 
277
    {                           /* do not change line breaks */
 
278
        long buf;
 
279
        buf = 0;
 
280
        filelen = edit->last_byte;
 
281
        while (buf <= (edit->curs1 >> S_EDIT_BUF_SIZE) - 1)
 
282
        {
 
283
            if (mc_write (fd, (char *) edit->buffers1[buf], EDIT_BUF_SIZE) != EDIT_BUF_SIZE)
 
284
            {
 
285
                mc_close (fd);
 
286
                goto error_save;
 
287
            }
 
288
            buf++;
 
289
        }
 
290
        if (mc_write
 
291
            (fd, (char *) edit->buffers1[buf],
 
292
             edit->curs1 & M_EDIT_BUF_SIZE) != (edit->curs1 & M_EDIT_BUF_SIZE))
 
293
        {
 
294
            filelen = -1;
 
295
        }
 
296
        else if (edit->curs2)
 
297
        {
 
298
            edit->curs2--;
 
299
            buf = (edit->curs2 >> S_EDIT_BUF_SIZE);
 
300
            if (mc_write
 
301
                (fd,
 
302
                 (char *) edit->buffers2[buf] + EDIT_BUF_SIZE -
 
303
                 (edit->curs2 & M_EDIT_BUF_SIZE) - 1,
 
304
                 1 + (edit->curs2 & M_EDIT_BUF_SIZE)) != 1 + (edit->curs2 & M_EDIT_BUF_SIZE))
 
305
            {
 
306
                filelen = -1;
 
307
            }
 
308
            else
 
309
            {
 
310
                while (--buf >= 0)
 
311
                {
 
312
                    if (mc_write (fd, (char *) edit->buffers2[buf], EDIT_BUF_SIZE) != EDIT_BUF_SIZE)
 
313
                    {
 
314
                        filelen = -1;
 
315
                        break;
 
316
                    }
 
317
                }
 
318
            }
 
319
            edit->curs2++;
 
320
        }
 
321
        if (mc_close (fd))
 
322
            goto error_save;
 
323
 
 
324
        /* Update the file information, especially the mtime. */
 
325
        if (mc_stat (savename_vpath, &edit->stat1) == -1)
 
326
            goto error_save;
 
327
    }
 
328
    else
 
329
    {                           /* change line breaks */
 
330
        FILE *file;
 
331
        const vfs_path_element_t *path_element;
 
332
 
 
333
        mc_close (fd);
 
334
 
 
335
        path_element = vfs_path_get_by_index (savename_vpath, -1);
 
336
        file = (FILE *) fopen (path_element->path, "w");
 
337
        if (file != NULL)
 
338
        {
 
339
            filelen = edit_write_stream (edit, file);
 
340
            fclose (file);
 
341
        }
 
342
        else
 
343
        {
 
344
            char *msg;
 
345
 
 
346
            msg = g_strdup_printf (_("Cannot open file for writing: %s"), path_element->path);
 
347
            edit_error_dialog (_("Error"), msg);
 
348
            g_free (msg);
 
349
            goto error_save;
 
350
        }
 
351
    }
 
352
 
 
353
    if (filelen != edit->last_byte)
 
354
        goto error_save;
 
355
 
 
356
    if (this_save_mode == EDIT_DO_BACKUP)
 
357
    {
 
358
        vfs_path_t *tmp_vpath;
 
359
        gboolean ok;
 
360
 
 
361
#ifdef HAVE_ASSERT_H
 
362
        assert (option_backup_ext != NULL);
 
363
#endif
 
364
        tmp_vpath = vfs_path_append_new (real_filename_vpath, option_backup_ext, (char *) NULL);
 
365
        ok = (mc_rename (real_filename_vpath, tmp_vpath) != -1);
 
366
        vfs_path_free (tmp_vpath);
 
367
        if (!ok)
 
368
            goto error_save;
 
369
    }
 
370
 
 
371
    if (this_save_mode != EDIT_QUICK_SAVE)
 
372
        if (mc_rename (savename_vpath, real_filename_vpath) == -1)
 
373
            goto error_save;
 
374
 
 
375
    vfs_path_free (real_filename_vpath);
 
376
    vfs_path_free (savename_vpath);
 
377
    return 1;
 
378
  error_save:
 
379
    /*  FIXME: Is this safe ?
 
380
     *  if (this_save_mode != EDIT_QUICK_SAVE)
 
381
     *      mc_unlink (savename);
 
382
     */
 
383
    vfs_path_free (real_filename_vpath);
 
384
    vfs_path_free (savename_vpath);
 
385
    return 0;
 
386
}
 
387
 
 
388
/* --------------------------------------------------------------------------------------------- */
 
389
 
 
390
static gboolean
 
391
edit_check_newline (WEdit * edit)
 
392
{
 
393
    return !(option_check_nl_at_eof && edit->last_byte > 0
 
394
             && edit_get_byte (edit, edit->last_byte - 1) != '\n'
 
395
             && edit_query_dialog2 (_("Warning"),
 
396
                                    _("The file you are saving is not finished with a newline"),
 
397
                                    _("C&ontinue"), _("&Cancel")));
 
398
}
 
399
 
 
400
/* --------------------------------------------------------------------------------------------- */
 
401
 
 
402
static vfs_path_t *
 
403
edit_get_save_file_as (WEdit * edit)
 
404
{
 
405
#define DLG_WIDTH 64
 
406
#define DLG_HEIGHT 14
 
407
 
 
408
    static LineBreaks cur_lb = LB_ASIS;
 
409
 
 
410
    char *filename = vfs_path_to_str (edit->filename_vpath);
 
411
    char *filename_res;
 
412
 
 
413
    const char *lb_names[LB_NAMES] = {
 
414
        N_("&Do not change"),
 
415
        N_("&Unix format (LF)"),
 
416
        N_("&Windows/DOS format (CR LF)"),
 
417
        N_("&Macintosh format (CR)")
 
418
    };
 
419
 
 
420
    QuickWidget quick_widgets[] = {
 
421
        QUICK_BUTTON (6, 10, DLG_HEIGHT - 3, DLG_HEIGHT, N_("&Cancel"), B_CANCEL, NULL),
 
422
        QUICK_BUTTON (2, 10, DLG_HEIGHT - 3, DLG_HEIGHT, N_("&OK"), B_ENTER, NULL),
 
423
        QUICK_RADIO (5, DLG_WIDTH, DLG_HEIGHT - 8, DLG_HEIGHT, LB_NAMES, lb_names, (int *) &cur_lb),
 
424
        QUICK_LABEL (3, DLG_WIDTH, DLG_HEIGHT - 9, DLG_HEIGHT, N_("Change line breaks to:")),
 
425
        QUICK_INPUT (3, DLG_WIDTH, DLG_HEIGHT - 11, DLG_HEIGHT, filename, DLG_WIDTH - 6, 0,
 
426
                     "save-as", &filename_res),
 
427
        QUICK_LABEL (3, DLG_WIDTH, DLG_HEIGHT - 12, DLG_HEIGHT, N_("Enter file name:")),
 
428
        QUICK_END
 
429
    };
 
430
 
 
431
    QuickDialog Quick_options = {
 
432
        DLG_WIDTH, DLG_HEIGHT, -1, -1,
 
433
        N_("Save As"), "[Save File As]",
 
434
        quick_widgets, NULL, FALSE
 
435
    };
 
436
 
 
437
    if (quick_dialog (&Quick_options) != B_CANCEL)
 
438
    {
 
439
        char *fname;
 
440
        vfs_path_t *ret_vpath;
 
441
 
 
442
        edit->lb = cur_lb;
 
443
        fname = tilde_expand (filename_res);
 
444
        g_free (filename_res);
 
445
        ret_vpath = vfs_path_from_str (fname);
 
446
        g_free (fname);
 
447
        return ret_vpath;
 
448
    }
 
449
    g_free (filename);
 
450
 
 
451
    return NULL;
 
452
 
 
453
#undef DLG_WIDTH
 
454
#undef DLG_HEIGHT
 
455
}
 
456
 
 
457
/* --------------------------------------------------------------------------------------------- */
 
458
 
 
459
/** returns 1 on success */
 
460
 
 
461
static int
 
462
edit_save_cmd (WEdit * edit)
 
463
{
 
464
    int res, save_lock = 0;
 
465
 
 
466
    if (!edit->locked && !edit->delete_file)
 
467
        save_lock = lock_file (edit->filename_vpath);
 
468
    res = edit_save_file (edit, edit->filename_vpath);
 
469
 
 
470
    /* Maintain modify (not save) lock on failure */
 
471
    if ((res > 0 && edit->locked) || save_lock)
 
472
        edit->locked = unlock_file (edit->filename_vpath);
 
473
 
 
474
    /* On failure try 'save as', it does locking on its own */
 
475
    if (!res)
 
476
        return edit_save_as_cmd (edit);
 
477
    edit->force |= REDRAW_COMPLETELY;
 
478
    if (res > 0)
 
479
    {
 
480
        edit->delete_file = 0;
 
481
        edit->modified = 0;
 
482
    }
 
483
 
 
484
    return 1;
 
485
}
 
486
 
 
487
/* --------------------------------------------------------------------------------------------- */
 
488
/** returns 1 on error */
 
489
 
 
490
static int
 
491
edit_load_file_from_filename (WEdit * edit, const vfs_path_t * exp_vpath)
 
492
{
 
493
    int prev_locked = edit->locked;
 
494
    vfs_path_t *prev_filename;
 
495
    int ret = 0;
 
496
 
 
497
    prev_filename = vfs_path_clone (edit->filename_vpath);
 
498
    if (!edit_reload (edit, exp_vpath))
 
499
        ret = 1;
 
500
    else if (prev_locked)
 
501
        unlock_file (prev_filename);
 
502
 
 
503
    vfs_path_free (prev_filename);
 
504
    return ret;
 
505
}
 
506
 
 
507
/* --------------------------------------------------------------------------------------------- */
 
508
 
 
509
static void
 
510
edit_load_syntax_file (WEdit * edit)
 
511
{
 
512
    vfs_path_t *extdir_vpath;
 
513
    int dir = 0;
 
514
 
 
515
    if (geteuid () == 0)
 
516
    {
 
517
        dir = query_dialog (_("Syntax file edit"),
 
518
                            _("Which syntax file you want to edit?"), D_NORMAL, 2,
 
519
                            _("&User"), _("&System Wide"));
 
520
    }
 
521
 
 
522
    extdir_vpath =
 
523
        vfs_path_build_filename (mc_global.sysconfig_dir, "syntax", "Syntax", (char *) NULL);
 
524
    if (!exist_file (vfs_path_get_last_path_str (extdir_vpath)))
 
525
    {
 
526
        vfs_path_free (extdir_vpath);
 
527
        extdir_vpath =
 
528
            vfs_path_build_filename (mc_global.share_data_dir, "syntax", "Syntax", (char *) NULL);
 
529
    }
 
530
 
 
531
    if (dir == 0)
 
532
    {
 
533
        vfs_path_t *user_syntax_file_vpath;
 
534
 
 
535
        user_syntax_file_vpath = mc_config_get_full_vpath (EDIT_SYNTAX_FILE);
 
536
        check_for_default (extdir_vpath, user_syntax_file_vpath);
 
537
        edit_load_file_from_filename (edit, user_syntax_file_vpath);
 
538
        vfs_path_free (user_syntax_file_vpath);
 
539
    }
 
540
    else if (dir == 1)
 
541
        edit_load_file_from_filename (edit, extdir_vpath);
 
542
 
 
543
    vfs_path_free (extdir_vpath);
 
544
}
 
545
 
 
546
/* --------------------------------------------------------------------------------------------- */
 
547
 
 
548
static void
 
549
edit_load_menu_file (WEdit * edit)
 
550
{
 
551
    vfs_path_t *buffer_vpath;
 
552
    vfs_path_t *menufile_vpath;
 
553
    int dir = 0;
 
554
 
 
555
    dir = query_dialog (_("Menu edit"),
 
556
                        _("Which menu file do you want to edit?"), D_NORMAL,
 
557
                        geteuid () != 0 ? 2 : 3, _("&Local"), _("&User"), _("&System Wide"));
 
558
 
 
559
    menufile_vpath = vfs_path_build_filename (mc_global.sysconfig_dir, EDIT_GLOBAL_MENU, NULL);
 
560
 
 
561
    if (!exist_file (vfs_path_get_last_path_str (menufile_vpath)))
 
562
    {
 
563
        vfs_path_free (menufile_vpath);
 
564
        menufile_vpath = vfs_path_build_filename (mc_global.share_data_dir, EDIT_GLOBAL_MENU, NULL);
 
565
    }
 
566
 
 
567
    switch (dir)
 
568
    {
 
569
    case 0:
 
570
        buffer_vpath = vfs_path_from_str (EDIT_LOCAL_MENU);
 
571
        check_for_default (menufile_vpath, buffer_vpath);
 
572
        chmod (vfs_path_get_last_path_str (buffer_vpath), 0600);
 
573
        break;
 
574
 
 
575
    case 1:
 
576
        buffer_vpath = mc_config_get_full_vpath (EDIT_HOME_MENU);
 
577
        check_for_default (menufile_vpath, buffer_vpath);
 
578
        break;
 
579
 
 
580
    case 2:
 
581
        buffer_vpath = vfs_path_build_filename (mc_global.sysconfig_dir, EDIT_GLOBAL_MENU, NULL);
 
582
        if (!exist_file (vfs_path_get_last_path_str (buffer_vpath)))
 
583
        {
 
584
            vfs_path_free (buffer_vpath);
 
585
            buffer_vpath =
 
586
                vfs_path_build_filename (mc_global.share_data_dir, EDIT_GLOBAL_MENU, NULL);
 
587
        }
 
588
        break;
 
589
 
 
590
    default:
 
591
        vfs_path_free (menufile_vpath);
 
592
        return;
 
593
    }
 
594
 
 
595
    edit_load_file_from_filename (edit, buffer_vpath);
 
596
 
 
597
    vfs_path_free (buffer_vpath);
 
598
    vfs_path_free (menufile_vpath);
 
599
}
 
600
 
 
601
/* --------------------------------------------------------------------------------------------- */
 
602
 
 
603
static void
 
604
edit_delete_column_of_text (WEdit * edit)
 
605
{
 
606
    long p, q, r, m1, m2;
 
607
    long b, c, d, n;
 
608
 
 
609
    eval_marks (edit, &m1, &m2);
 
610
    n = edit_move_forward (edit, m1, 0, m2) + 1;
 
611
    c = edit_move_forward3 (edit, edit_bol (edit, m1), 0, m1);
 
612
    d = edit_move_forward3 (edit, edit_bol (edit, m2), 0, m2);
 
613
    b = max (min (c, d), min (edit->column1, edit->column2));
 
614
    c = max (c, max (edit->column1, edit->column2));
 
615
 
 
616
    while (n--)
 
617
    {
 
618
        r = edit_bol (edit, edit->curs1);
 
619
        p = edit_move_forward3 (edit, r, b, 0);
 
620
        q = edit_move_forward3 (edit, r, c, 0);
 
621
        if (p < m1)
 
622
            p = m1;
 
623
        if (q > m2)
 
624
            q = m2;
 
625
        edit_cursor_move (edit, p - edit->curs1);
 
626
        while (q > p)
 
627
        {
 
628
            /* delete line between margins */
 
629
            if (edit_get_byte (edit, edit->curs1) != '\n')
 
630
                edit_delete (edit, 1);
 
631
            q--;
 
632
        }
 
633
        if (n)
 
634
            /* move to next line except on the last delete */
 
635
            edit_cursor_move (edit, edit_move_forward (edit, edit->curs1, 1, 0) - edit->curs1);
 
636
    }
 
637
}
 
638
 
 
639
/* --------------------------------------------------------------------------------------------- */
 
640
/** if success return 0 */
 
641
 
 
642
static int
 
643
edit_block_delete (WEdit * edit)
 
644
{
 
645
    long count;
 
646
    long start_mark, end_mark;
 
647
    int curs_pos, line_width;
 
648
    long curs_line, c1, c2;
 
649
 
 
650
    if (eval_marks (edit, &start_mark, &end_mark))
 
651
        return 0;
 
652
    if (edit->column_highlight && edit->mark2 < 0)
 
653
        edit_mark_cmd (edit, 0);
 
654
    if ((end_mark - start_mark) > option_max_undo / 2)
 
655
    {
 
656
        /* Warning message with a query to continue or cancel the operation */
 
657
        if (edit_query_dialog2
 
658
            (_("Warning"),
 
659
             _
 
660
             ("Block is large, you may not be able to undo this action"),
 
661
             _("C&ontinue"), _("&Cancel")))
 
662
        {
 
663
            return 1;
 
664
        }
 
665
    }
 
666
    c1 = min (edit->column1, edit->column2);
 
667
    c2 = max (edit->column1, edit->column2);
 
668
    edit->column1 = c1;
 
669
    edit->column2 = c2;
 
670
 
 
671
    edit_push_markers (edit);
 
672
 
 
673
    curs_line = edit->curs_line;
 
674
 
 
675
    /* calculate line width and cursor position before cut */
 
676
    line_width = edit_move_forward3 (edit, edit_bol (edit, edit->curs1), 0,
 
677
                                     edit_eol (edit, edit->curs1));
 
678
    curs_pos = edit->curs_col + edit->over_col;
 
679
 
 
680
    /* move cursor to start of selection */
 
681
    edit_cursor_move (edit, start_mark - edit->curs1);
 
682
    edit_scroll_screen_over_cursor (edit);
 
683
    count = start_mark;
 
684
    if (start_mark < end_mark)
 
685
    {
 
686
        if (edit->column_highlight)
 
687
        {
 
688
            if (edit->mark2 < 0)
 
689
                edit_mark_cmd (edit, 0);
 
690
            edit_delete_column_of_text (edit);
 
691
            /* move cursor to the saved position */
 
692
            edit_move_to_line (edit, curs_line);
 
693
            /* calculate line width after cut */
 
694
            line_width = edit_move_forward3 (edit, edit_bol (edit, edit->curs1), 0,
 
695
                                             edit_eol (edit, edit->curs1));
 
696
            if (option_cursor_beyond_eol && curs_pos > line_width)
 
697
                edit->over_col = curs_pos - line_width;
 
698
        }
 
699
        else
 
700
        {
 
701
            while (count < end_mark)
 
702
            {
 
703
                edit_delete (edit, 1);
 
704
                count++;
 
705
            }
 
706
        }
 
707
    }
 
708
    edit_set_markers (edit, 0, 0, 0, 0);
 
709
    edit->force |= REDRAW_PAGE;
 
710
    return 0;
 
711
}
 
712
 
 
713
/* --------------------------------------------------------------------------------------------- */
 
714
/**
 
715
 * Get EOL symbol for searching.
 
716
 *
 
717
 * @param edit editor object
 
718
 * @return EOL symbol
 
719
 */
 
720
 
 
721
static inline char
 
722
edit_search_get_current_end_line_char (const WEdit * edit)
 
723
{
 
724
    switch (edit->lb)
 
725
    {
 
726
    case LB_MAC:
 
727
        return '\r';
 
728
    default:
 
729
        return '\n';
 
730
    }
 
731
}
 
732
 
 
733
/* --------------------------------------------------------------------------------------------- */
 
734
/**
 
735
 * Checking if search condition have BOL(^) or EOL ($) regexp special characters.
 
736
 *
 
737
 * @param search search object
 
738
 * @return result of checks.
 
739
 */
 
740
 
 
741
static edit_search_line_t
 
742
edit_get_search_line_type (mc_search_t * search)
 
743
{
 
744
    edit_search_line_t search_line_type = 0;
 
745
 
 
746
    if (search->search_type != MC_SEARCH_T_REGEX)
 
747
        return search_line_type;
 
748
 
 
749
    if (*search->original == '^')
 
750
        search_line_type |= AT_START_LINE;
 
751
 
 
752
    if (search->original[search->original_len - 1] == '$')
 
753
        search_line_type |= AT_END_LINE;
 
754
    return search_line_type;
 
755
}
 
756
 
 
757
/* --------------------------------------------------------------------------------------------- */
 
758
/**
 
759
 * Calculating the start position of next line.
 
760
 *
 
761
 * @param edit              editor object
 
762
 * @param current_pos       current position
 
763
 * @param max_pos           max position
 
764
 * @param end_string_symbol end of line symbol
 
765
 * @return start position of next line
 
766
 */
 
767
 
 
768
static off_t
 
769
edit_calculate_start_of_next_line (WEdit * edit, off_t current_pos, off_t max_pos,
 
770
                                   char end_string_symbol)
 
771
{
 
772
    off_t i;
 
773
 
 
774
    for (i = current_pos; i < max_pos; i++)
 
775
    {
 
776
        current_pos++;
 
777
        if (edit_get_byte (edit, i) == end_string_symbol)
 
778
            break;
 
779
    }
 
780
 
 
781
    return current_pos;
 
782
}
 
783
 
 
784
/* --------------------------------------------------------------------------------------------- */
 
785
/**
 
786
 * Calculating the end position of previous line.
 
787
 *
 
788
 * @param edit              editor object
 
789
 * @param current_pos       current position
 
790
 * @param end_string_symbol end of line symbol
 
791
 * @return end position of previous line
 
792
 */
 
793
 
 
794
static off_t
 
795
edit_calculate_end_of_previous_line (WEdit * edit, off_t current_pos, char end_string_symbol)
 
796
{
 
797
    off_t i;
 
798
 
 
799
    for (i = current_pos - 1; i >= 0; i--)
 
800
        if (edit_get_byte (edit, i) == end_string_symbol)
 
801
            break;
 
802
 
 
803
    return i;
 
804
}
 
805
 
 
806
/* --------------------------------------------------------------------------------------------- */
 
807
/**
 
808
 * Calculating the start position of previous line.
 
809
 *
 
810
 * @param edit              editor object
 
811
 * @param current_pos       current position
 
812
 * @param end_string_symbol end of line symbol
 
813
 * @return start position of previous line
 
814
 */
 
815
 
 
816
static inline off_t
 
817
edit_calculate_start_of_previous_line (WEdit * edit, off_t current_pos, char end_string_symbol)
 
818
{
 
819
    current_pos = edit_calculate_end_of_previous_line (edit, current_pos, end_string_symbol);
 
820
    current_pos = edit_calculate_end_of_previous_line (edit, current_pos, end_string_symbol);
 
821
 
 
822
    return (current_pos + 1);
 
823
}
 
824
 
 
825
/* --------------------------------------------------------------------------------------------- */
 
826
/**
 
827
 * Calculating the start position of current line.
 
828
 *
 
829
 * @param edit              editor object
 
830
 * @param current_pos       current position
 
831
 * @param end_string_symbol end of line symbol
 
832
 * @return start position of current line
 
833
 */
 
834
 
 
835
static inline off_t
 
836
edit_calculate_start_of_current_line (WEdit * edit, off_t current_pos, char end_string_symbol)
 
837
{
 
838
    current_pos = edit_calculate_end_of_previous_line (edit, current_pos, end_string_symbol);
 
839
 
 
840
    return (current_pos + 1);
 
841
}
 
842
 
 
843
/* --------------------------------------------------------------------------------------------- */
 
844
/**
 
845
 * Fixing (if needed) search start position if 'only in selection' option present.
 
846
 *
 
847
 * @param edit              editor object
 
848
 */
 
849
 
 
850
static void
 
851
edit_search_fix_search_start_if_selection (WEdit * edit)
 
852
{
 
853
    long start_mark = 0;
 
854
    long end_mark = 0;
 
855
 
 
856
    if (!edit_search_options.only_in_selection)
 
857
        return;
 
858
 
 
859
    if (eval_marks (edit, &start_mark, &end_mark) != 0)
 
860
        return;
 
861
 
 
862
    if (edit_search_options.backwards)
 
863
    {
 
864
        if (edit->search_start > end_mark || edit->search_start <= start_mark)
 
865
            edit->search_start = end_mark;
 
866
    }
 
867
    else
 
868
    {
 
869
        if (edit->search_start < start_mark || edit->search_start >= end_mark)
 
870
            edit->search_start = start_mark;
 
871
    }
 
872
}
 
873
 
 
874
/* --------------------------------------------------------------------------------------------- */
 
875
 
 
876
static gboolean
 
877
editcmd_find (WEdit * edit, gsize * len)
 
878
{
 
879
    off_t search_start = edit->search_start;
 
880
    off_t search_end;
 
881
    long start_mark = 0;
 
882
    long end_mark = edit->last_byte;
 
883
    int mark_res = 0;
 
884
    char end_string_symbol;
 
885
 
 
886
    end_string_symbol = edit_search_get_current_end_line_char (edit);
 
887
 
 
888
    /* prepare for search */
 
889
    if (edit_search_options.only_in_selection)
 
890
    {
 
891
        mark_res = eval_marks (edit, &start_mark, &end_mark);
 
892
        if (mark_res != 0)
 
893
        {
 
894
            edit->search->error = MC_SEARCH_E_NOTFOUND;
 
895
            edit->search->error_str = g_strdup (_("Search string not found"));
 
896
            return FALSE;
 
897
        }
 
898
 
 
899
        /* fix the start and the end of search block positions */
 
900
        if ((edit->search_line_type & AT_START_LINE) != 0
 
901
            && (start_mark != 0 || edit_get_byte (edit, start_mark - 1) != end_string_symbol))
 
902
        {
 
903
            start_mark =
 
904
                edit_calculate_start_of_next_line (edit, start_mark, edit->last_byte,
 
905
                                                   end_string_symbol);
 
906
        }
 
907
        if ((edit->search_line_type & AT_END_LINE) != 0
 
908
            && (end_mark - 1 != edit->last_byte
 
909
                || edit_get_byte (edit, end_mark) != end_string_symbol))
 
910
        {
 
911
            end_mark = edit_calculate_end_of_previous_line (edit, end_mark, end_string_symbol);
 
912
        }
 
913
        if (start_mark >= end_mark)
 
914
        {
 
915
            edit->search->error = MC_SEARCH_E_NOTFOUND;
 
916
            edit->search->error_str = g_strdup (_("Search string not found"));
 
917
            return FALSE;
 
918
        }
 
919
    }
 
920
    else
 
921
    {
 
922
        if (edit_search_options.backwards)
 
923
            end_mark = max (1, edit->curs1) - 1;
 
924
    }
 
925
 
 
926
    /* search */
 
927
    if (edit_search_options.backwards)
 
928
    {
 
929
        /* backward search */
 
930
        search_end = end_mark;
 
931
 
 
932
        if ((edit->search_line_type & AT_START_LINE) != 0)
 
933
            search_start =
 
934
                edit_calculate_start_of_current_line (edit, search_start, end_string_symbol);
 
935
 
 
936
        while ((int) search_start >= start_mark)
 
937
        {
 
938
            if (search_end > (off_t) (search_start + edit->search->original_len)
 
939
                && mc_search_is_fixed_search_str (edit->search))
 
940
            {
 
941
                search_end = search_start + edit->search->original_len;
 
942
            }
 
943
            if (mc_search_run (edit->search, (void *) edit, search_start, search_end, len)
 
944
                && edit->search->normal_offset == search_start)
 
945
            {
 
946
                return TRUE;
 
947
            }
 
948
 
 
949
 
 
950
            if ((edit->search_line_type & AT_START_LINE) != 0)
 
951
                search_start =
 
952
                    edit_calculate_start_of_previous_line (edit, search_start, end_string_symbol);
 
953
            else
 
954
                search_start--;
 
955
        }
 
956
        edit->search->error_str = g_strdup (_("Search string not found"));
 
957
    }
 
958
    else
 
959
    {
 
960
        /* forward search */
 
961
        if ((edit->search_line_type & AT_START_LINE) != 0 && search_start != start_mark)
 
962
            search_start =
 
963
                edit_calculate_start_of_next_line (edit, search_start, end_mark, end_string_symbol);
 
964
        return mc_search_run (edit->search, (void *) edit, search_start, end_mark, len);
 
965
    }
 
966
    return FALSE;
 
967
}
 
968
 
 
969
/* --------------------------------------------------------------------------------------------- */
 
970
 
 
971
static char *
 
972
edit_replace_cmd__conv_to_display (char *str)
 
973
{
 
974
#ifdef HAVE_CHARSET
 
975
    GString *tmp;
 
976
 
 
977
    tmp = str_convert_to_display (str);
 
978
    if (tmp != NULL)
 
979
    {
 
980
        if (tmp->len != 0)
 
981
            return g_string_free (tmp, FALSE);
 
982
        g_string_free (tmp, TRUE);
 
983
    }
 
984
#endif
 
985
    return g_strdup (str);
 
986
}
 
987
 
 
988
/* --------------------------------------------------------------------------------------------- */
 
989
 
 
990
static char *
 
991
edit_replace_cmd__conv_to_input (char *str)
 
992
{
 
993
#ifdef HAVE_CHARSET
 
994
    GString *tmp;
 
995
 
 
996
    tmp = str_convert_to_input (str);
 
997
    if (tmp != NULL)
 
998
    {
 
999
        if (tmp->len != 0)
 
1000
            return g_string_free (tmp, FALSE);
 
1001
        g_string_free (tmp, TRUE);
 
1002
    }
 
1003
#endif
 
1004
    return g_strdup (str);
 
1005
}
 
1006
 
 
1007
/* --------------------------------------------------------------------------------------------- */
 
1008
 
 
1009
static void
 
1010
edit_do_search (WEdit * edit)
 
1011
{
 
1012
    gsize len = 0;
 
1013
 
 
1014
    if (edit->search == NULL)
 
1015
        edit->search_start = edit->curs1;
 
1016
 
 
1017
    edit_push_undo_action (edit, KEY_PRESS + edit->start_display);
 
1018
 
 
1019
    if (search_create_bookmark)
 
1020
    {
 
1021
        int found = 0, books = 0;
 
1022
        long l = 0, l_last = -1;
 
1023
        long q = 0;
 
1024
 
 
1025
        search_create_bookmark = FALSE;
 
1026
        book_mark_flush (edit, -1);
 
1027
 
 
1028
        while (TRUE)
 
1029
        {
 
1030
            if (!mc_search_run (edit->search, (void *) edit, q, edit->last_byte, &len))
 
1031
                break;
 
1032
            if (found == 0)
 
1033
                edit->search_start = edit->search->normal_offset;
 
1034
            found++;
 
1035
            l += edit_count_lines (edit, q, edit->search->normal_offset);
 
1036
            if (l != l_last)
 
1037
            {
 
1038
                book_mark_insert (edit, l, BOOK_MARK_FOUND_COLOR);
 
1039
                books++;
 
1040
            }
 
1041
            l_last = l;
 
1042
            q = edit->search->normal_offset + 1;
 
1043
        }
 
1044
 
 
1045
        if (found == 0)
 
1046
            edit_error_dialog (_("Search"), _("Search string not found"));
 
1047
        else
 
1048
            edit_cursor_move (edit, edit->search_start - edit->curs1);
 
1049
    }
 
1050
    else
 
1051
    {
 
1052
        if (edit->found_len != 0 && edit->search_start == edit->found_start + 1
 
1053
            && edit_search_options.backwards)
 
1054
            edit->search_start--;
 
1055
 
 
1056
        if (edit->found_len != 0 && edit->search_start == edit->found_start - 1
 
1057
            && !edit_search_options.backwards)
 
1058
            edit->search_start++;
 
1059
 
 
1060
        if (editcmd_find (edit, &len))
 
1061
        {
 
1062
            edit->found_start = edit->search_start = edit->search->normal_offset;
 
1063
            edit->found_len = len;
 
1064
            edit->over_col = 0;
 
1065
            edit_cursor_move (edit, edit->search_start - edit->curs1);
 
1066
            edit_scroll_screen_over_cursor (edit);
 
1067
            if (edit_search_options.backwards)
 
1068
                edit->search_start--;
 
1069
            else
 
1070
                edit->search_start++;
 
1071
        }
 
1072
        else
 
1073
        {
 
1074
            edit->search_start = edit->curs1;
 
1075
            if (edit->search->error_str != NULL)
 
1076
                edit_error_dialog (_("Search"), edit->search->error_str);
 
1077
        }
 
1078
    }
 
1079
 
 
1080
    edit->force |= REDRAW_COMPLETELY;
 
1081
    edit_scroll_screen_over_cursor (edit);
 
1082
}
 
1083
 
 
1084
/* --------------------------------------------------------------------------------------------- */
 
1085
 
 
1086
static void
 
1087
edit_search (WEdit * edit)
 
1088
{
 
1089
    if (editcmd_dialog_search_show (edit))
 
1090
    {
 
1091
        edit->search_line_type = edit_get_search_line_type (edit->search);
 
1092
        edit_search_fix_search_start_if_selection (edit);
 
1093
        edit_do_search (edit);
 
1094
    }
 
1095
}
 
1096
 
 
1097
/* --------------------------------------------------------------------------------------------- */
 
1098
/** Return a null terminated length of text. Result must be g_free'd */
 
1099
 
 
1100
static unsigned char *
 
1101
edit_get_block (WEdit * edit, long start, long finish, int *l)
 
1102
{
 
1103
    unsigned char *s, *r;
 
1104
    r = s = g_malloc0 (finish - start + 1);
 
1105
    if (edit->column_highlight)
 
1106
    {
 
1107
        *l = 0;
 
1108
        /* copy from buffer, excluding chars that are out of the column 'margins' */
 
1109
        while (start < finish)
 
1110
        {
 
1111
            int c;
 
1112
            long x;
 
1113
            x = edit_move_forward3 (edit, edit_bol (edit, start), 0, start);
 
1114
            c = edit_get_byte (edit, start);
 
1115
            if ((x >= edit->column1 && x < edit->column2)
 
1116
                || (x >= edit->column2 && x < edit->column1) || c == '\n')
 
1117
            {
 
1118
                *s++ = c;
 
1119
                (*l)++;
 
1120
            }
 
1121
            start++;
 
1122
        }
 
1123
    }
 
1124
    else
 
1125
    {
 
1126
        *l = finish - start;
 
1127
        while (start < finish)
 
1128
            *s++ = edit_get_byte (edit, start++);
 
1129
    }
 
1130
    *s = 0;
 
1131
    return r;
 
1132
}
 
1133
 
 
1134
/* --------------------------------------------------------------------------------------------- */
 
1135
/** copies a block to clipboard file */
 
1136
 
 
1137
static int
 
1138
edit_save_block_to_clip_file (WEdit * edit, long start, long finish)
 
1139
{
 
1140
    int ret;
 
1141
    gchar *tmp;
 
1142
    tmp = mc_config_get_full_path (EDIT_CLIP_FILE);
 
1143
    ret = edit_save_block (edit, tmp, start, finish);
 
1144
    g_free (tmp);
 
1145
    return ret;
 
1146
}
 
1147
 
 
1148
/* --------------------------------------------------------------------------------------------- */
 
1149
 
 
1150
static void
 
1151
pipe_mail (WEdit * edit, char *to, char *subject, char *cc)
 
1152
{
 
1153
    FILE *p = 0;
 
1154
    char *s;
 
1155
 
 
1156
    to = name_quote (to, 0);
 
1157
    subject = name_quote (subject, 0);
 
1158
    cc = name_quote (cc, 0);
 
1159
    s = g_strconcat ("mail -s ", subject, *cc ? " -c " : "", cc, " ", to, (char *) NULL);
 
1160
    g_free (to);
 
1161
    g_free (subject);
 
1162
    g_free (cc);
 
1163
 
 
1164
    if (s)
 
1165
    {
 
1166
        p = popen (s, "w");
 
1167
        g_free (s);
 
1168
    }
 
1169
 
 
1170
    if (p)
 
1171
    {
 
1172
        long i;
 
1173
        for (i = 0; i < edit->last_byte; i++)
 
1174
            fputc (edit_get_byte (edit, i), p);
 
1175
        pclose (p);
 
1176
    }
 
1177
}
 
1178
 
 
1179
/* --------------------------------------------------------------------------------------------- */
 
1180
 
 
1181
static gboolean
 
1182
is_break_char (char c)
 
1183
{
 
1184
    return (isspace (c) || strchr ("{}[]()<>=|/\\!?~-+`'\",.;:#$%^&*", c));
 
1185
}
 
1186
 
 
1187
/* --------------------------------------------------------------------------------------------- */
 
1188
/** find first character of current word */
 
1189
 
 
1190
static int
 
1191
edit_find_word_start (WEdit * edit, long *word_start, gsize * word_len)
 
1192
{
 
1193
    int c, last;
 
1194
    gsize i;
 
1195
 
 
1196
    /* return if at begin of file */
 
1197
    if (edit->curs1 <= 0)
 
1198
        return 0;
 
1199
 
 
1200
    c = (unsigned char) edit_get_byte (edit, edit->curs1 - 1);
 
1201
    /* return if not at end or in word */
 
1202
    if (is_break_char (c))
 
1203
        return 0;
 
1204
 
 
1205
    /* search start of word to be completed */
 
1206
    for (i = 2;; i++)
 
1207
    {
 
1208
        /* return if at begin of file */
 
1209
        if ((gsize) edit->curs1 < i)
 
1210
            return 0;
 
1211
 
 
1212
        last = c;
 
1213
        c = (unsigned char) edit_get_byte (edit, edit->curs1 - i);
 
1214
 
 
1215
        if (is_break_char (c))
 
1216
        {
 
1217
            /* return if word starts with digit */
 
1218
            if (isdigit (last))
 
1219
                return 0;
 
1220
 
 
1221
            *word_start = edit->curs1 - (i - 1);        /* start found */
 
1222
            *word_len = i - 1;
 
1223
            break;
 
1224
        }
 
1225
    }
 
1226
    /* success */
 
1227
    return 1;
 
1228
}
 
1229
 
 
1230
/* --------------------------------------------------------------------------------------------- */
 
1231
/**
 
1232
 * Get current word under cursor
 
1233
 *
 
1234
 * @param edit editor object
 
1235
 * @param srch mc_search object
 
1236
 * @param word_start start word position
 
1237
 *
 
1238
 * @return newly allocated string or NULL if no any words under cursor
 
1239
 */
 
1240
 
 
1241
static char *
 
1242
edit_collect_completions_get_current_word (WEdit * edit, mc_search_t * srch, long word_start)
 
1243
{
 
1244
    gsize len = 0, i;
 
1245
    GString *temp;
 
1246
 
 
1247
    if (!mc_search_run (srch, (void *) edit, word_start, edit->last_byte, &len))
 
1248
        return NULL;
 
1249
 
 
1250
    temp = g_string_sized_new (len);
 
1251
 
 
1252
    for (i = 0; i < len; i++)
 
1253
    {
 
1254
        int chr;
 
1255
 
 
1256
        chr = edit_get_byte (edit, word_start + i);
 
1257
        if (!isspace (chr))
 
1258
            g_string_append_c (temp, chr);
 
1259
    }
 
1260
 
 
1261
    return g_string_free (temp, temp->len == 0);
 
1262
}
 
1263
 
 
1264
/* --------------------------------------------------------------------------------------------- */
 
1265
/** collect the possible completions */
 
1266
 
 
1267
static gsize
 
1268
edit_collect_completions (WEdit * edit, long word_start, gsize word_len,
 
1269
                          char *match_expr, struct selection *compl, gsize * num)
 
1270
{
 
1271
    gsize len = 0;
 
1272
    gsize max_len = 0;
 
1273
    gsize i;
 
1274
    int skip;
 
1275
    GString *temp;
 
1276
    mc_search_t *srch;
 
1277
    long last_byte, start = -1;
 
1278
    char *current_word;
 
1279
 
 
1280
    srch = mc_search_new (match_expr, -1);
 
1281
    if (srch == NULL)
 
1282
        return 0;
 
1283
 
 
1284
    if (mc_config_get_bool
 
1285
        (mc_main_config, CONFIG_APP_SECTION, "editor_wordcompletion_collect_entire_file", 0))
 
1286
    {
 
1287
        last_byte = edit->last_byte;
 
1288
    }
 
1289
    else
 
1290
    {
 
1291
        last_byte = word_start;
 
1292
    }
 
1293
 
 
1294
    srch->search_type = MC_SEARCH_T_REGEX;
 
1295
    srch->is_case_sensitive = TRUE;
 
1296
    srch->search_fn = edit_search_cmd_callback;
 
1297
 
 
1298
    current_word = edit_collect_completions_get_current_word (edit, srch, word_start);
 
1299
 
 
1300
    temp = g_string_new ("");
 
1301
 
 
1302
    /* collect max MAX_WORD_COMPLETIONS completions */
 
1303
    while (mc_search_run (srch, (void *) edit, start + 1, last_byte, &len))
 
1304
    {
 
1305
        g_string_set_size (temp, 0);
 
1306
        start = srch->normal_offset;
 
1307
 
 
1308
        /* add matched completion if not yet added */
 
1309
        for (i = 0; i < len; i++)
 
1310
        {
 
1311
            skip = edit_get_byte (edit, start + i);
 
1312
            if (isspace (skip))
 
1313
                continue;
 
1314
 
 
1315
            /* skip current word */
 
1316
            if (start + (long) i == word_start)
 
1317
                break;
 
1318
 
 
1319
            g_string_append_c (temp, skip);
 
1320
        }
 
1321
 
 
1322
        if (temp->len == 0)
 
1323
            continue;
 
1324
 
 
1325
        if (current_word != NULL && strcmp (current_word, temp->str) == 0)
 
1326
            continue;
 
1327
 
 
1328
        skip = 0;
 
1329
 
 
1330
        for (i = 0; i < *num; i++)
 
1331
        {
 
1332
            if (strncmp
 
1333
                ((char *) &compl[i].text[word_len],
 
1334
                 (char *) &temp->str[word_len], max (len, compl[i].len) - word_len) == 0)
 
1335
            {
 
1336
                struct selection this = compl[i];
 
1337
                for (++i; i < *num; i++)
 
1338
                {
 
1339
                    compl[i - 1] = compl[i];
 
1340
                }
 
1341
                compl[*num - 1] = this;
 
1342
                skip = 1;
 
1343
                break;          /* skip it, already added */
 
1344
            }
 
1345
        }
 
1346
        if (skip != 0)
 
1347
            continue;
 
1348
 
 
1349
        if (*num == MAX_WORD_COMPLETIONS)
 
1350
        {
 
1351
            g_free (compl[0].text);
 
1352
            for (i = 1; i < *num; i++)
 
1353
            {
 
1354
                compl[i - 1] = compl[i];
 
1355
            }
 
1356
            (*num)--;
 
1357
        }
 
1358
#ifdef HAVE_CHARSET
 
1359
        {
 
1360
            GString *recoded;
 
1361
            recoded = str_convert_to_display (temp->str);
 
1362
 
 
1363
            if (recoded && recoded->len)
 
1364
                g_string_assign (temp, recoded->str);
 
1365
 
 
1366
            g_string_free (recoded, TRUE);
 
1367
        }
 
1368
#endif
 
1369
        compl[*num].text = g_strdup (temp->str);
 
1370
        compl[*num].len = temp->len;
 
1371
        (*num)++;
 
1372
        start += len;
 
1373
 
 
1374
        /* note the maximal length needed for the completion dialog */
 
1375
        if (len > max_len)
 
1376
            max_len = len;
 
1377
    }
 
1378
 
 
1379
    mc_search_free (srch);
 
1380
    g_string_free (temp, TRUE);
 
1381
    g_free (current_word);
 
1382
 
 
1383
    return max_len;
 
1384
}
 
1385
 
 
1386
/* --------------------------------------------------------------------------------------------- */
 
1387
 
 
1388
static void
 
1389
edit_insert_column_of_text (WEdit * edit, unsigned char *data, int size, int width,
 
1390
                            long *start_pos, long *end_pos, int *col1, int *col2)
 
1391
{
 
1392
    long cursor;
 
1393
    int i, col;
 
1394
 
 
1395
    cursor = edit->curs1;
 
1396
    col = edit_get_col (edit);
 
1397
 
 
1398
    for (i = 0; i < size; i++)
 
1399
    {
 
1400
        if (data[i] != '\n')
 
1401
            edit_insert (edit, data[i]);
 
1402
        else
 
1403
        {                       /* fill in and move to next line */
 
1404
            int l;
 
1405
            long p;
 
1406
 
 
1407
            if (edit_get_byte (edit, edit->curs1) != '\n')
 
1408
            {
 
1409
                l = width - (edit_get_col (edit) - col);
 
1410
                while (l > 0)
 
1411
                {
 
1412
                    edit_insert (edit, ' ');
 
1413
                    l -= space_width;
 
1414
                }
 
1415
            }
 
1416
            for (p = edit->curs1;; p++)
 
1417
            {
 
1418
                if (p == edit->last_byte)
 
1419
                {
 
1420
                    edit_cursor_move (edit, edit->last_byte - edit->curs1);
 
1421
                    edit_insert_ahead (edit, '\n');
 
1422
                    p++;
 
1423
                    break;
 
1424
                }
 
1425
                if (edit_get_byte (edit, p) == '\n')
 
1426
                {
 
1427
                    p++;
 
1428
                    break;
 
1429
                }
 
1430
            }
 
1431
            edit_cursor_move (edit, edit_move_forward3 (edit, p, col, 0) - edit->curs1);
 
1432
            l = col - edit_get_col (edit);
 
1433
            while (l >= space_width)
 
1434
            {
 
1435
                edit_insert (edit, ' ');
 
1436
                l -= space_width;
 
1437
            }
 
1438
        }
 
1439
    }
 
1440
 
 
1441
    *col1 = col;
 
1442
    *col2 = col + width;
 
1443
    *start_pos = cursor;
 
1444
    *end_pos = edit->curs1;
 
1445
    edit_cursor_move (edit, cursor - edit->curs1);
 
1446
}
 
1447
 
 
1448
/* --------------------------------------------------------------------------------------------- */
 
1449
 
 
1450
static int
 
1451
edit_macro_comparator (gconstpointer * macro1, gconstpointer * macro2)
 
1452
{
 
1453
    const macros_t *m1 = (const macros_t *) macro1;
 
1454
    const macros_t *m2 = (const macros_t *) macro2;
 
1455
 
 
1456
    return m1->hotkey - m2->hotkey;
 
1457
}
 
1458
 
 
1459
/* --------------------------------------------------------------------------------------------- */
 
1460
 
 
1461
static void
 
1462
edit_macro_sort_by_hotkey (void)
 
1463
{
 
1464
    if (macros_list != NULL && macros_list->len != 0)
 
1465
        g_array_sort (macros_list, (GCompareFunc) edit_macro_comparator);
 
1466
}
 
1467
 
 
1468
/* --------------------------------------------------------------------------------------------- */
 
1469
 
 
1470
static gboolean
 
1471
edit_get_macro (WEdit * edit, int hotkey, const macros_t ** macros, guint * indx)
 
1472
{
 
1473
    const macros_t *array_start = &g_array_index (macros_list, struct macros_t, 0);
 
1474
    macros_t *result;
 
1475
    macros_t search_macro;
 
1476
 
 
1477
    (void) edit;
 
1478
 
 
1479
    search_macro.hotkey = hotkey;
 
1480
    result = bsearch (&search_macro, macros_list->data, macros_list->len,
 
1481
                      sizeof (macros_t), (GCompareFunc) edit_macro_comparator);
 
1482
 
 
1483
    if (result != NULL && result->macro != NULL)
 
1484
    {
 
1485
        *indx = (result - array_start);
 
1486
        *macros = result;
 
1487
        return TRUE;
 
1488
    }
 
1489
    *indx = 0;
 
1490
    return FALSE;
 
1491
}
 
1492
 
 
1493
/* --------------------------------------------------------------------------------------------- */
 
1494
/** returns FALSE on error */
 
1495
 
 
1496
static gboolean
 
1497
edit_delete_macro (WEdit * edit, int hotkey)
 
1498
{
 
1499
    mc_config_t *macros_config = NULL;
 
1500
    const char *section_name = "editor";
 
1501
    gchar *macros_fname;
 
1502
    guint indx;
 
1503
    char *skeyname;
 
1504
    const macros_t *macros = NULL;
 
1505
 
 
1506
    /* clear array of actions for current hotkey */
 
1507
    while (edit_get_macro (edit, hotkey, &macros, &indx))
 
1508
    {
 
1509
        if (macros->macro != NULL)
 
1510
            g_array_free (macros->macro, TRUE);
 
1511
        macros = NULL;
 
1512
        g_array_remove_index (macros_list, indx);
 
1513
        edit_macro_sort_by_hotkey ();
 
1514
    }
 
1515
 
 
1516
    macros_fname = mc_config_get_full_path (MC_MACRO_FILE);
 
1517
    macros_config = mc_config_init (macros_fname);
 
1518
    g_free (macros_fname);
 
1519
 
 
1520
    if (macros_config == NULL)
 
1521
        return FALSE;
 
1522
 
 
1523
    skeyname = lookup_key_by_code (hotkey);
 
1524
    while (mc_config_del_key (macros_config, section_name, skeyname))
 
1525
        ;
 
1526
    g_free (skeyname);
 
1527
    mc_config_save_file (macros_config, NULL);
 
1528
    mc_config_deinit (macros_config);
 
1529
    return TRUE;
 
1530
}
 
1531
 
 
1532
 
 
1533
/* --------------------------------------------------------------------------------------------- */
 
1534
/*** public functions ****************************************************************************/
 
1535
/* --------------------------------------------------------------------------------------------- */
 
1536
 
 
1537
void
 
1538
edit_help_cmd (WEdit * edit)
 
1539
{
 
1540
    ev_help_t event_data = { NULL, "[Internal File Editor]" };
 
1541
    mc_event_raise (MCEVENT_GROUP_CORE, "help", &event_data);
 
1542
 
 
1543
    edit->force |= REDRAW_COMPLETELY;
 
1544
}
 
1545
 
 
1546
/* --------------------------------------------------------------------------------------------- */
 
1547
 
 
1548
void
 
1549
edit_refresh_cmd (WEdit * edit)
 
1550
{
 
1551
#ifdef HAVE_SLANG
 
1552
    int color;
 
1553
 
 
1554
    edit_get_syntax_color (edit, -1, &color);
 
1555
    tty_touch_screen ();
 
1556
    mc_refresh ();
 
1557
#else
 
1558
    (void) edit;
 
1559
 
 
1560
    clr_scr ();
 
1561
    repaint_screen ();
 
1562
#endif /* !HAVE_SLANG */
 
1563
    tty_keypad (TRUE);
 
1564
}
 
1565
 
 
1566
/* --------------------------------------------------------------------------------------------- */
 
1567
 
 
1568
void
 
1569
menu_save_mode_cmd (void)
 
1570
{
 
1571
    /* diaog sizes */
 
1572
    const int DLG_X = 38;
 
1573
    const int DLG_Y = 13;
 
1574
 
 
1575
    char *str_result;
 
1576
 
 
1577
    const char *str[] = {
 
1578
        N_("&Quick save"),
 
1579
        N_("&Safe save"),
 
1580
        N_("&Do backups with following extension:")
 
1581
    };
 
1582
 
 
1583
    QuickWidget widgets[] = {
 
1584
        /* 0 */
 
1585
        QUICK_BUTTON (18, DLG_X, DLG_Y - 3, DLG_Y, N_("&Cancel"), B_CANCEL, NULL),
 
1586
        /* 1 */
 
1587
        QUICK_BUTTON (6, DLG_X, DLG_Y - 3, DLG_Y, N_("&OK"), B_ENTER, NULL),
 
1588
        /* 2 */
 
1589
        QUICK_CHECKBOX (4, DLG_X, 8, DLG_Y, N_("Check &POSIX new line"), &option_check_nl_at_eof),
 
1590
        /* 3 */
 
1591
        QUICK_INPUT (8, DLG_X, 6, DLG_Y, option_backup_ext, 9, 0, "edit-backup-ext", &str_result),
 
1592
        /* 4 */
 
1593
        QUICK_RADIO (4, DLG_X, 3, DLG_Y, 3, str, &option_save_mode),
 
1594
        QUICK_END
 
1595
    };
 
1596
 
 
1597
    QuickDialog dialog = {
 
1598
        DLG_X, DLG_Y, -1, -1, N_("Edit Save Mode"),
 
1599
        "[Edit Save Mode]", widgets, NULL, FALSE
 
1600
    };
 
1601
 
 
1602
    size_t i;
 
1603
    size_t maxlen = 0;
 
1604
    size_t w0, w1, b_len, w3;
 
1605
 
 
1606
#ifdef HAVE_ASSERT_H
 
1607
    assert (option_backup_ext != NULL);
 
1608
#endif
 
1609
 
 
1610
    /* OK/Cancel buttons */
 
1611
    w0 = str_term_width1 (_(widgets[0].u.button.text)) + 3;
 
1612
    w1 = str_term_width1 (_(widgets[1].u.button.text)) + 5;     /* default button */
 
1613
    b_len = w0 + w1 + 3;
 
1614
 
 
1615
    maxlen = max (b_len, (size_t) str_term_width1 (_(dialog.title)) + 2);
 
1616
 
 
1617
    w3 = 0;
 
1618
    for (i = 0; i < 3; i++)
 
1619
    {
 
1620
#ifdef ENABLE_NLS
 
1621
        str[i] = _(str[i]);
 
1622
#endif
 
1623
        w3 = max (w3, (size_t) str_term_width1 (str[i]));
 
1624
    }
 
1625
 
 
1626
    maxlen = max (maxlen, w3 + 4);
 
1627
 
 
1628
    dialog.xlen = min ((size_t) COLS, maxlen + 8);
 
1629
 
 
1630
    widgets[3].u.input.len = w3;
 
1631
    widgets[1].relative_x = (dialog.xlen - b_len) / 2;
 
1632
    widgets[0].relative_x = widgets[1].relative_x + w0 + 2;
 
1633
 
 
1634
    for (i = 0; i < sizeof (widgets) / sizeof (widgets[0]); i++)
 
1635
        widgets[i].x_divisions = dialog.xlen;
 
1636
 
 
1637
    if (quick_dialog (&dialog) != B_CANCEL)
 
1638
    {
 
1639
        g_free (option_backup_ext);
 
1640
        option_backup_ext = str_result;
 
1641
    }
 
1642
}
 
1643
 
 
1644
/* --------------------------------------------------------------------------------------------- */
 
1645
 
 
1646
void
 
1647
edit_set_filename (WEdit * edit, const vfs_path_t * name_vpath)
 
1648
{
 
1649
    vfs_path_free (edit->filename_vpath);
 
1650
    edit->filename_vpath = vfs_path_clone (name_vpath);
 
1651
 
 
1652
    if (edit->dir_vpath == NULL)
 
1653
        edit->dir_vpath = vfs_path_clone (vfs_get_raw_current_dir ());
 
1654
}
 
1655
 
 
1656
/* --------------------------------------------------------------------------------------------- */
 
1657
/* Here we want to warn the users of overwriting an existing file,
 
1658
   but only if they have made a change to the filename */
 
1659
/* returns 1 on success */
 
1660
int
 
1661
edit_save_as_cmd (WEdit * edit)
 
1662
{
 
1663
    /* This heads the 'Save As' dialog box */
 
1664
    vfs_path_t *exp_vpath;
 
1665
    int save_lock = 0;
 
1666
    int different_filename = 0;
 
1667
 
 
1668
    if (!edit_check_newline (edit))
 
1669
        return 0;
 
1670
 
 
1671
    exp_vpath = edit_get_save_file_as (edit);
 
1672
    edit_push_undo_action (edit, KEY_PRESS + edit->start_display);
 
1673
 
 
1674
    if (exp_vpath != NULL)
 
1675
    {
 
1676
        if (vfs_path_len (exp_vpath) == 0)
 
1677
            goto ret;
 
1678
        else
 
1679
        {
 
1680
            int rv;
 
1681
 
 
1682
            if (vfs_path_cmp (edit->filename_vpath, exp_vpath) != 0)
 
1683
            {
 
1684
                int file;
 
1685
                struct stat sb;
 
1686
 
 
1687
                if (mc_stat (exp_vpath, &sb) == 0 && !S_ISREG (sb.st_mode))
 
1688
                {
 
1689
                    edit_error_dialog (_("Save as"),
 
1690
                                       get_sys_error (_
 
1691
                                                      ("Cannot save: destination is not a regular file")));
 
1692
                    goto ret;
 
1693
                }
 
1694
 
 
1695
                different_filename = 1;
 
1696
                file = mc_open (exp_vpath, O_RDONLY | O_BINARY);
 
1697
 
 
1698
                if (file != -1)
 
1699
                {
 
1700
                    /* the file exists */
 
1701
                    mc_close (file);
 
1702
                    /* Overwrite the current file or cancel the operation */
 
1703
                    if (edit_query_dialog2
 
1704
                        (_("Warning"),
 
1705
                         _("A file already exists with this name"), _("&Overwrite"), _("&Cancel")))
 
1706
                        goto ret;
 
1707
                }
 
1708
                else
 
1709
                {
 
1710
                    edit->stat1.st_mode |= S_IWUSR;
 
1711
                }
 
1712
                save_lock = lock_file (exp_vpath);
 
1713
            }
 
1714
            else
 
1715
            {
 
1716
                /* filenames equal, check if already locked */
 
1717
                if (!edit->locked && !edit->delete_file)
 
1718
                    save_lock = lock_file (exp_vpath);
 
1719
            }
 
1720
 
 
1721
            if (different_filename)
 
1722
            {
 
1723
                /*
 
1724
                 * Allow user to write into saved (under another name) file
 
1725
                 * even if original file had r/o user permissions.
 
1726
                 */
 
1727
                edit->stat1.st_mode |= S_IWRITE;
 
1728
            }
 
1729
 
 
1730
            rv = edit_save_file (edit, exp_vpath);
 
1731
            switch (rv)
 
1732
            {
 
1733
            case 1:
 
1734
                /* Succesful, so unlock both files */
 
1735
                if (different_filename)
 
1736
                {
 
1737
                    if (save_lock)
 
1738
                        unlock_file (exp_vpath);
 
1739
                    if (edit->locked)
 
1740
                        edit->locked = unlock_file (edit->filename_vpath);
 
1741
                }
 
1742
                else
 
1743
                {
 
1744
                    if (edit->locked || save_lock)
 
1745
                        edit->locked = unlock_file (edit->filename_vpath);
 
1746
                }
 
1747
 
 
1748
                edit_set_filename (edit, exp_vpath);
 
1749
                if (edit->lb != LB_ASIS)
 
1750
                    edit_reload (edit, exp_vpath);
 
1751
                edit->modified = 0;
 
1752
                edit->delete_file = 0;
 
1753
                if (different_filename)
 
1754
                    edit_load_syntax (edit, NULL, edit->syntax_type);
 
1755
                vfs_path_free (exp_vpath);
 
1756
                edit->force |= REDRAW_COMPLETELY;
 
1757
                return 1;
 
1758
            default:
 
1759
                edit_error_dialog (_("Save as"), get_sys_error (_("Cannot save file")));
 
1760
                /* fallthrough */
 
1761
            case -1:
 
1762
                /* Failed, so maintain modify (not save) lock */
 
1763
                if (save_lock)
 
1764
                    unlock_file (exp_vpath);
 
1765
                break;
 
1766
            }
 
1767
        }
 
1768
    }
 
1769
 
 
1770
  ret:
 
1771
    vfs_path_free (exp_vpath);
 
1772
    edit->force |= REDRAW_COMPLETELY;
 
1773
    return 0;
 
1774
}
 
1775
 
 
1776
/* {{{ Macro stuff starts here */
 
1777
/* --------------------------------------------------------------------------------------------- */
 
1778
 
 
1779
void
 
1780
edit_delete_macro_cmd (WEdit * edit)
 
1781
{
 
1782
    int hotkey;
 
1783
 
 
1784
    hotkey = editcmd_dialog_raw_key_query (_("Delete macro"), _("Press macro hotkey:"), 1);
 
1785
 
 
1786
    if (hotkey != 0 && !edit_delete_macro (edit, hotkey))
 
1787
        message (D_ERROR, _("Delete macro"), _("Macro not deleted"));
 
1788
}
 
1789
 
 
1790
/* --------------------------------------------------------------------------------------------- */
 
1791
 
 
1792
/** returns FALSE on error */
 
1793
gboolean
 
1794
edit_execute_macro (WEdit * edit, int hotkey)
 
1795
{
 
1796
    gboolean res = FALSE;
 
1797
 
 
1798
    if (hotkey != 0)
 
1799
    {
 
1800
        const macros_t *macros;
 
1801
        guint indx;
 
1802
 
 
1803
        if (edit_get_macro (edit, hotkey, &macros, &indx) &&
 
1804
            macros->macro != NULL && macros->macro->len != 0)
 
1805
        {
 
1806
            guint i;
 
1807
 
 
1808
            edit->force |= REDRAW_PAGE;
 
1809
 
 
1810
            for (i = 0; i < macros->macro->len; i++)
 
1811
            {
 
1812
                const macro_action_t *m_act;
 
1813
 
 
1814
                m_act = &g_array_index (macros->macro, struct macro_action_t, i);
 
1815
                edit_execute_cmd (edit, m_act->action, m_act->ch);
 
1816
                res = TRUE;
 
1817
            }
 
1818
        }
 
1819
    }
 
1820
 
 
1821
    return res;
 
1822
}
 
1823
 
 
1824
/* --------------------------------------------------------------------------------------------- */
 
1825
 
 
1826
/** returns FALSE on error */
 
1827
gboolean
 
1828
edit_store_macro_cmd (WEdit * edit)
 
1829
{
 
1830
    int i;
 
1831
    int hotkey;
 
1832
    GString *marcros_string;
 
1833
    mc_config_t *macros_config = NULL;
 
1834
    const char *section_name = "editor";
 
1835
    gchar *macros_fname;
 
1836
    GArray *macros;             /* current macro */
 
1837
    int tmp_act;
 
1838
    gboolean have_macro = FALSE;
 
1839
    char *skeyname = NULL;
 
1840
 
 
1841
    hotkey = editcmd_dialog_raw_key_query (_("Save macro"), _("Press the macro's new hotkey:"), 1);
 
1842
    if (hotkey == ESC_CHAR)
 
1843
        return FALSE;
 
1844
 
 
1845
    tmp_act = keybind_lookup_keymap_command (editor_map, hotkey);
 
1846
 
 
1847
    /* return FALSE if try assign macro into restricted hotkeys */
 
1848
    if (tmp_act == CK_MacroStartRecord
 
1849
        || tmp_act == CK_MacroStopRecord || tmp_act == CK_MacroStartStopRecord)
 
1850
        return FALSE;
 
1851
 
 
1852
    edit_delete_macro (edit, hotkey);
 
1853
 
 
1854
    macros_fname = mc_config_get_full_path (MC_MACRO_FILE);
 
1855
    macros_config = mc_config_init (macros_fname);
 
1856
    g_free (macros_fname);
 
1857
 
 
1858
    if (macros_config == NULL)
 
1859
        return FALSE;
 
1860
 
 
1861
    edit_push_undo_action (edit, KEY_PRESS + edit->start_display);
 
1862
 
 
1863
    marcros_string = g_string_sized_new (250);
 
1864
    macros = g_array_new (TRUE, FALSE, sizeof (macro_action_t));
 
1865
 
 
1866
    skeyname = lookup_key_by_code (hotkey);
 
1867
 
 
1868
    for (i = 0; i < macro_index; i++)
 
1869
    {
 
1870
        macro_action_t m_act;
 
1871
        const char *action_name;
 
1872
 
 
1873
        action_name = keybind_lookup_actionname (record_macro_buf[i].action);
 
1874
 
 
1875
        if (action_name == NULL)
 
1876
            break;
 
1877
 
 
1878
        m_act.action = record_macro_buf[i].action;
 
1879
        m_act.ch = record_macro_buf[i].ch;
 
1880
        g_array_append_val (macros, m_act);
 
1881
        have_macro = TRUE;
 
1882
        g_string_append_printf (marcros_string, "%s:%i;", action_name,
 
1883
                                (int) record_macro_buf[i].ch);
 
1884
    }
 
1885
    if (have_macro)
 
1886
    {
 
1887
        macros_t macro;
 
1888
        macro.hotkey = hotkey;
 
1889
        macro.macro = macros;
 
1890
        g_array_append_val (macros_list, macro);
 
1891
        mc_config_set_string (macros_config, section_name, skeyname, marcros_string->str);
 
1892
    }
 
1893
    else
 
1894
        mc_config_del_key (macros_config, section_name, skeyname);
 
1895
 
 
1896
    g_free (skeyname);
 
1897
    edit_macro_sort_by_hotkey ();
 
1898
 
 
1899
    g_string_free (marcros_string, TRUE);
 
1900
    mc_config_save_file (macros_config, NULL);
 
1901
    mc_config_deinit (macros_config);
 
1902
    return TRUE;
 
1903
}
 
1904
 
 
1905
 /* --------------------------------------------------------------------------------------------- */
 
1906
 
 
1907
gboolean
 
1908
edit_repeat_macro_cmd (WEdit * edit)
 
1909
{
 
1910
    int i, j;
 
1911
    char *f;
 
1912
    long count_repeat;
 
1913
    char *error = NULL;
 
1914
 
 
1915
    f = input_dialog (_("Repeat last commands"), _("Repeat times:"), MC_HISTORY_EDIT_REPEAT, NULL);
 
1916
    if (f == NULL || *f == '\0')
 
1917
    {
 
1918
        g_free (f);
 
1919
        return FALSE;
 
1920
    }
 
1921
 
 
1922
    count_repeat = strtol (f, &error, 0);
 
1923
 
 
1924
    if (*error != '\0')
 
1925
    {
 
1926
        g_free (f);
 
1927
        return FALSE;
 
1928
    }
 
1929
 
 
1930
    g_free (f);
 
1931
 
 
1932
    edit_push_undo_action (edit, KEY_PRESS + edit->start_display);
 
1933
    edit->force |= REDRAW_PAGE;
 
1934
 
 
1935
    for (j = 0; j < count_repeat; j++)
 
1936
        for (i = 0; i < macro_index; i++)
 
1937
            edit_execute_cmd (edit, record_macro_buf[i].action, record_macro_buf[i].ch);
 
1938
    edit_update_screen (edit);
 
1939
    return TRUE;
 
1940
}
 
1941
 
 
1942
/* --------------------------------------------------------------------------------------------- */
 
1943
/** return FALSE on error */
 
1944
 
 
1945
gboolean
 
1946
edit_load_macro_cmd (WEdit * edit)
 
1947
{
 
1948
    mc_config_t *macros_config = NULL;
 
1949
    gchar **profile_keys, **keys;
 
1950
    gchar **values, **curr_values;
 
1951
    gsize len, values_len;
 
1952
    const char *section_name = "editor";
 
1953
    gchar *macros_fname;
 
1954
    int hotkey;
 
1955
 
 
1956
    (void) edit;
 
1957
 
 
1958
    macros_fname = mc_config_get_full_path (MC_MACRO_FILE);
 
1959
    macros_config = mc_config_init (macros_fname);
 
1960
    g_free (macros_fname);
 
1961
 
 
1962
    if (macros_config == NULL)
 
1963
        return FALSE;
 
1964
 
 
1965
    profile_keys = keys = mc_config_get_keys (macros_config, section_name, &len);
 
1966
    while (*profile_keys != NULL)
 
1967
    {
 
1968
        gboolean have_macro;
 
1969
        GArray *macros;
 
1970
        macros_t macro;
 
1971
 
 
1972
        macros = g_array_new (TRUE, FALSE, sizeof (macro_action_t));
 
1973
 
 
1974
        curr_values = values = mc_config_get_string_list (macros_config, section_name,
 
1975
                                                          *profile_keys, &values_len);
 
1976
        hotkey = lookup_key (*profile_keys, NULL);
 
1977
        have_macro = FALSE;
 
1978
 
 
1979
        while (*curr_values != NULL && *curr_values[0] != '\0')
 
1980
        {
 
1981
            char **macro_pair = NULL;
 
1982
 
 
1983
            macro_pair = g_strsplit (*curr_values, ":", 2);
 
1984
 
 
1985
            if (macro_pair != NULL)
 
1986
            {
 
1987
                macro_action_t m_act;
 
1988
                if (macro_pair[0] == NULL || macro_pair[0][0] == '\0')
 
1989
                    m_act.action = 0;
 
1990
                else
 
1991
                {
 
1992
                    m_act.action = keybind_lookup_action (macro_pair[0]);
 
1993
                    g_free (macro_pair[0]);
 
1994
                    macro_pair[0] = NULL;
 
1995
                }
 
1996
                if (macro_pair[1] == NULL || macro_pair[1][0] == '\0')
 
1997
                    m_act.ch = -1;
 
1998
                else
 
1999
                {
 
2000
                    m_act.ch = strtol (macro_pair[1], NULL, 0);
 
2001
                    g_free (macro_pair[1]);
 
2002
                    macro_pair[1] = NULL;
 
2003
                }
 
2004
                if (m_act.action != 0)
 
2005
                {
 
2006
                    /* a shell command */
 
2007
                    if ((m_act.action / CK_PipeBlock (0)) == 1)
 
2008
                    {
 
2009
                        m_act.action = CK_PipeBlock (0) + (m_act.ch > 0 ? m_act.ch : 0);
 
2010
                        m_act.ch = -1;
 
2011
                    }
 
2012
                    g_array_append_val (macros, m_act);
 
2013
                    have_macro = TRUE;
 
2014
                }
 
2015
                g_strfreev (macro_pair);
 
2016
                macro_pair = NULL;
 
2017
            }
 
2018
            curr_values++;
 
2019
        }
 
2020
        if (have_macro)
 
2021
        {
 
2022
            macro.hotkey = hotkey;
 
2023
            macro.macro = macros;
 
2024
            g_array_append_val (macros_list, macro);
 
2025
        }
 
2026
        profile_keys++;
 
2027
        g_strfreev (values);
 
2028
    }
 
2029
    g_strfreev (keys);
 
2030
    mc_config_deinit (macros_config);
 
2031
    edit_macro_sort_by_hotkey ();
 
2032
    return TRUE;
 
2033
}
 
2034
 
 
2035
/* }}} Macro stuff end here */
 
2036
 
 
2037
/* --------------------------------------------------------------------------------------------- */
 
2038
/** returns 1 on success */
 
2039
 
 
2040
int
 
2041
edit_save_confirm_cmd (WEdit * edit)
 
2042
{
 
2043
    gchar *f = NULL;
 
2044
 
 
2045
    if (edit->filename_vpath == NULL)
 
2046
        return edit_save_as_cmd (edit);
 
2047
 
 
2048
    if (!edit_check_newline (edit))
 
2049
        return 0;
 
2050
 
 
2051
    if (edit_confirm_save)
 
2052
    {
 
2053
        char *filename;
 
2054
        gboolean ok;
 
2055
 
 
2056
        filename = vfs_path_to_str (edit->filename_vpath);
 
2057
        f = g_strdup_printf (_("Confirm save file: \"%s\""), filename);
 
2058
        g_free (filename);
 
2059
        ok = (edit_query_dialog2 (_("Save file"), f, _("&Save"), _("&Cancel")) == 0);
 
2060
        g_free (f);
 
2061
        if (!ok)
 
2062
            return 0;
 
2063
    }
 
2064
    return edit_save_cmd (edit);
 
2065
}
 
2066
 
 
2067
/* --------------------------------------------------------------------------------------------- */
 
2068
/** returns 1 on success */
 
2069
 
 
2070
int
 
2071
edit_new_cmd (WEdit * edit)
 
2072
{
 
2073
    if (edit->modified)
 
2074
    {
 
2075
        if (edit_query_dialog2
 
2076
            (_("Warning"),
 
2077
             _
 
2078
             ("Current text was modified without a file save.\nContinue discards these changes"),
 
2079
             _("C&ontinue"), _("&Cancel")))
 
2080
        {
 
2081
            edit->force |= REDRAW_COMPLETELY;
 
2082
            return 0;
 
2083
        }
 
2084
    }
 
2085
    edit->force |= REDRAW_COMPLETELY;
 
2086
 
 
2087
    return edit_renew (edit);   /* if this gives an error, something has really screwed up */
 
2088
}
 
2089
 
 
2090
/* --------------------------------------------------------------------------------------------- */
 
2091
 
 
2092
int
 
2093
edit_load_cmd (WEdit * edit, edit_current_file_t what)
 
2094
{
 
2095
    if (edit->modified
 
2096
        && (edit_query_dialog2
 
2097
            (_("Warning"),
 
2098
             _("Current text was modified without a file save.\n"
 
2099
               "Continue discards these changes"), _("C&ontinue"), _("&Cancel")) == 1))
 
2100
    {
 
2101
        edit->force |= REDRAW_COMPLETELY;
 
2102
        return 0;
 
2103
    }
 
2104
 
 
2105
    switch (what)
 
2106
    {
 
2107
    case EDIT_FILE_COMMON:
 
2108
        {
 
2109
            char *filename, *exp;
 
2110
 
 
2111
            filename = vfs_path_to_str (edit->filename_vpath);
 
2112
            exp = input_expand_dialog (_("Load"), _("Enter file name:"),
 
2113
                                       MC_HISTORY_EDIT_LOAD, filename);
 
2114
            g_free (filename);
 
2115
 
 
2116
            if (exp != NULL)
 
2117
            {
 
2118
                if (*exp != '\0')
 
2119
                {
 
2120
                    vfs_path_t *exp_vpath;
 
2121
 
 
2122
                    exp_vpath = vfs_path_from_str (exp);
 
2123
                    edit_load_file_from_filename (edit, exp_vpath);
 
2124
                    vfs_path_free (exp_vpath);
 
2125
                }
 
2126
                g_free (exp);
 
2127
            }
 
2128
        }
 
2129
        break;
 
2130
 
 
2131
    case EDIT_FILE_SYNTAX:
 
2132
        edit_load_syntax_file (edit);
 
2133
        break;
 
2134
 
 
2135
    case EDIT_FILE_MENU:
 
2136
        edit_load_menu_file (edit);
 
2137
        break;
 
2138
 
 
2139
    default:
 
2140
        break;
 
2141
    }
 
2142
 
 
2143
    edit->force |= REDRAW_COMPLETELY;
 
2144
    return 0;
 
2145
}
 
2146
 
 
2147
/* --------------------------------------------------------------------------------------------- */
 
2148
/**
 
2149
   if mark2 is -1 then marking is from mark1 to the cursor.
 
2150
   Otherwise its between the markers. This handles this.
 
2151
   Returns 1 if no text is marked.
 
2152
 */
 
2153
 
 
2154
int
 
2155
eval_marks (WEdit * edit, long *start_mark, long *end_mark)
 
2156
{
 
2157
    if (edit->mark1 != edit->mark2)
 
2158
    {
 
2159
        long start_bol, start_eol;
 
2160
        long end_bol, end_eol;
 
2161
        long col1, col2;
 
2162
        long diff1, diff2;
 
2163
        long end_mark_curs;
 
2164
 
 
2165
        if (edit->end_mark_curs < 0)
 
2166
            end_mark_curs = edit->curs1;
 
2167
        else
 
2168
            end_mark_curs = edit->end_mark_curs;
 
2169
 
 
2170
        if (edit->mark2 >= 0)
 
2171
        {
 
2172
            *start_mark = min (edit->mark1, edit->mark2);
 
2173
            *end_mark = max (edit->mark1, edit->mark2);
 
2174
        }
 
2175
        else
 
2176
        {
 
2177
            *start_mark = min (edit->mark1, end_mark_curs);
 
2178
            *end_mark = max (edit->mark1, end_mark_curs);
 
2179
            edit->column2 = edit->curs_col + edit->over_col;
 
2180
        }
 
2181
 
 
2182
        if (edit->column_highlight
 
2183
            && (((edit->mark1 > end_mark_curs) && (edit->column1 < edit->column2))
 
2184
                || ((edit->mark1 < end_mark_curs) && (edit->column1 > edit->column2))))
 
2185
        {
 
2186
            start_bol = edit_bol (edit, *start_mark);
 
2187
            start_eol = edit_eol (edit, start_bol - 1) + 1;
 
2188
            end_bol = edit_bol (edit, *end_mark);
 
2189
            end_eol = edit_eol (edit, *end_mark);
 
2190
            col1 = min (edit->column1, edit->column2);
 
2191
            col2 = max (edit->column1, edit->column2);
 
2192
 
 
2193
            diff1 =
 
2194
                edit_move_forward3 (edit, start_bol, col2, 0) - edit_move_forward3 (edit, start_bol,
 
2195
                                                                                    col1, 0);
 
2196
            diff2 =
 
2197
                edit_move_forward3 (edit, end_bol, col2, 0) - edit_move_forward3 (edit, end_bol,
 
2198
                                                                                  col1, 0);
 
2199
 
 
2200
            *start_mark -= diff1;
 
2201
            *end_mark += diff2;
 
2202
            *start_mark = max (*start_mark, start_eol);
 
2203
            *end_mark = min (*end_mark, end_eol);
 
2204
        }
 
2205
        return 0;
 
2206
    }
 
2207
    else
 
2208
    {
 
2209
        *start_mark = *end_mark = 0;
 
2210
        edit->column2 = edit->column1 = 0;
 
2211
        return 1;
 
2212
    }
 
2213
}
 
2214
 
 
2215
/* --------------------------------------------------------------------------------------------- */
 
2216
 
 
2217
void
 
2218
edit_insert_over (WEdit * edit)
 
2219
{
 
2220
    int i;
 
2221
 
 
2222
    for (i = 0; i < edit->over_col; i++)
 
2223
    {
 
2224
        edit_insert (edit, ' ');
 
2225
    }
 
2226
    edit->over_col = 0;
 
2227
}
 
2228
 
 
2229
/* --------------------------------------------------------------------------------------------- */
 
2230
 
 
2231
int
 
2232
edit_insert_column_of_text_from_file (WEdit * edit, int file,
 
2233
                                      long *start_pos, long *end_pos, int *col1, int *col2)
 
2234
{
 
2235
    long cursor;
 
2236
    int col;
 
2237
    int blocklen = -1, width = 0;
 
2238
    unsigned char *data;
 
2239
 
 
2240
    cursor = edit->curs1;
 
2241
    col = edit_get_col (edit);
 
2242
    data = g_malloc0 (TEMP_BUF_LEN);
 
2243
 
 
2244
    while ((blocklen = mc_read (file, (char *) data, TEMP_BUF_LEN)) > 0)
 
2245
    {
 
2246
        int i;
 
2247
        for (width = 0; width < blocklen; width++)
 
2248
        {
 
2249
            if (data[width] == '\n')
 
2250
                break;
 
2251
        }
 
2252
        for (i = 0; i < blocklen; i++)
 
2253
        {
 
2254
            if (data[i] == '\n')
 
2255
            {                   /* fill in and move to next line */
 
2256
                int l;
 
2257
                long p;
 
2258
                if (edit_get_byte (edit, edit->curs1) != '\n')
 
2259
                {
 
2260
                    l = width - (edit_get_col (edit) - col);
 
2261
                    while (l > 0)
 
2262
                    {
 
2263
                        edit_insert (edit, ' ');
 
2264
                        l -= space_width;
 
2265
                    }
 
2266
                }
 
2267
                for (p = edit->curs1;; p++)
 
2268
                {
 
2269
                    if (p == edit->last_byte)
 
2270
                    {
 
2271
                        edit_cursor_move (edit, edit->last_byte - edit->curs1);
 
2272
                        edit_insert_ahead (edit, '\n');
 
2273
                        p++;
 
2274
                        break;
 
2275
                    }
 
2276
                    if (edit_get_byte (edit, p) == '\n')
 
2277
                    {
 
2278
                        p++;
 
2279
                        break;
 
2280
                    }
 
2281
                }
 
2282
                edit_cursor_move (edit, edit_move_forward3 (edit, p, col, 0) - edit->curs1);
 
2283
                l = col - edit_get_col (edit);
 
2284
                while (l >= space_width)
 
2285
                {
 
2286
                    edit_insert (edit, ' ');
 
2287
                    l -= space_width;
 
2288
                }
 
2289
                continue;
 
2290
            }
 
2291
            edit_insert (edit, data[i]);
 
2292
        }
 
2293
    }
 
2294
    *col1 = col;
 
2295
    *col2 = col + width;
 
2296
    *start_pos = cursor;
 
2297
    *end_pos = edit->curs1;
 
2298
    edit_cursor_move (edit, cursor - edit->curs1);
 
2299
    g_free (data);
 
2300
 
 
2301
    return blocklen;
 
2302
}
 
2303
 
 
2304
/* --------------------------------------------------------------------------------------------- */
 
2305
 
 
2306
void
 
2307
edit_block_copy_cmd (WEdit * edit)
 
2308
{
 
2309
    long start_mark, end_mark, current = edit->curs1;
 
2310
    long col_delta = 0;
 
2311
    long mark1, mark2;
 
2312
    int c1, c2;
 
2313
    int size;
 
2314
    unsigned char *copy_buf;
 
2315
 
 
2316
    edit_update_curs_col (edit);
 
2317
    if (eval_marks (edit, &start_mark, &end_mark))
 
2318
        return;
 
2319
 
 
2320
    copy_buf = edit_get_block (edit, start_mark, end_mark, &size);
 
2321
 
 
2322
    /* all that gets pushed are deletes hence little space is used on the stack */
 
2323
 
 
2324
    edit_push_markers (edit);
 
2325
 
 
2326
    if (edit->column_highlight)
 
2327
    {
 
2328
        col_delta = abs (edit->column2 - edit->column1);
 
2329
        edit_insert_column_of_text (edit, copy_buf, size, col_delta, &mark1, &mark2, &c1, &c2);
 
2330
    }
 
2331
    else
 
2332
    {
 
2333
        while (size--)
 
2334
            edit_insert_ahead (edit, copy_buf[size]);
 
2335
    }
 
2336
 
 
2337
    g_free (copy_buf);
 
2338
    edit_scroll_screen_over_cursor (edit);
 
2339
 
 
2340
    if (edit->column_highlight)
 
2341
        edit_set_markers (edit, edit->curs1, mark2, c1, c2);
 
2342
    else if (start_mark < current && end_mark > current)
 
2343
        edit_set_markers (edit, start_mark, end_mark + end_mark - start_mark, 0, 0);
 
2344
 
 
2345
    edit->force |= REDRAW_PAGE;
 
2346
}
 
2347
 
 
2348
 
 
2349
/* --------------------------------------------------------------------------------------------- */
 
2350
 
 
2351
void
 
2352
edit_block_move_cmd (WEdit * edit)
 
2353
{
 
2354
    long current;
 
2355
    unsigned char *copy_buf = NULL;
 
2356
    long start_mark, end_mark;
 
2357
    long line;
 
2358
 
 
2359
    if (eval_marks (edit, &start_mark, &end_mark))
 
2360
        return;
 
2361
 
 
2362
    line = edit->curs_line;
 
2363
    if (edit->mark2 < 0)
 
2364
        edit_mark_cmd (edit, 0);
 
2365
    edit_push_markers (edit);
 
2366
 
 
2367
    if (edit->column_highlight)
 
2368
    {
 
2369
        long mark1, mark2;
 
2370
        int size;
 
2371
        int b_width = 0;
 
2372
        int c1, c2;
 
2373
        int x, x2;
 
2374
 
 
2375
        c1 = min (edit->column1, edit->column2);
 
2376
        c2 = max (edit->column1, edit->column2);
 
2377
        b_width = (c2 - c1);
 
2378
 
 
2379
        edit_update_curs_col (edit);
 
2380
 
 
2381
        x = edit->curs_col;
 
2382
        x2 = x + edit->over_col;
 
2383
 
 
2384
        /* do nothing when cursor inside first line of selected area */
 
2385
        if ((edit_eol (edit, edit->curs1) == edit_eol (edit, start_mark)) && (x2 > c1 && x2 <= c2))
 
2386
            return;
 
2387
 
 
2388
        if (edit->curs1 > start_mark && edit->curs1 < edit_eol (edit, end_mark))
 
2389
        {
 
2390
            if (x > c2)
 
2391
                x -= b_width;
 
2392
            else if (x > c1 && x <= c2)
 
2393
                x = c1;
 
2394
        }
 
2395
        /* save current selection into buffer */
 
2396
        copy_buf = edit_get_block (edit, start_mark, end_mark, &size);
 
2397
 
 
2398
        /* remove current selection */
 
2399
        edit_block_delete_cmd (edit);
 
2400
 
 
2401
        edit->over_col = max (0, edit->over_col - b_width);
 
2402
        /* calculate the cursor pos after delete block */
 
2403
        current = edit_move_forward3 (edit, edit_bol (edit, edit->curs1), x, 0);
 
2404
        edit_cursor_move (edit, current - edit->curs1);
 
2405
        edit_scroll_screen_over_cursor (edit);
 
2406
 
 
2407
        /* add TWS if need before block insertion */
 
2408
        if (option_cursor_beyond_eol && edit->over_col > 0)
 
2409
            edit_insert_over (edit);
 
2410
 
 
2411
        edit_insert_column_of_text (edit, copy_buf, size, b_width, &mark1, &mark2, &c1, &c2);
 
2412
        edit_set_markers (edit, mark1, mark2, c1, c2);
 
2413
    }
 
2414
    else
 
2415
    {
 
2416
        long count;
 
2417
 
 
2418
        current = edit->curs1;
 
2419
        copy_buf = g_malloc0 (end_mark - start_mark);
 
2420
        edit_cursor_move (edit, start_mark - edit->curs1);
 
2421
        edit_scroll_screen_over_cursor (edit);
 
2422
        count = start_mark;
 
2423
        while (count < end_mark)
 
2424
        {
 
2425
            copy_buf[end_mark - count - 1] = edit_delete (edit, 1);
 
2426
            count++;
 
2427
        }
 
2428
        edit_scroll_screen_over_cursor (edit);
 
2429
        edit_cursor_move (edit,
 
2430
                          current - edit->curs1 -
 
2431
                          (((current - edit->curs1) > 0) ? end_mark - start_mark : 0));
 
2432
        edit_scroll_screen_over_cursor (edit);
 
2433
        while (count-- > start_mark)
 
2434
            edit_insert_ahead (edit, copy_buf[end_mark - count - 1]);
 
2435
        edit_set_markers (edit, edit->curs1, edit->curs1 + end_mark - start_mark, 0, 0);
 
2436
    }
 
2437
 
 
2438
    edit_scroll_screen_over_cursor (edit);
 
2439
    g_free (copy_buf);
 
2440
    edit->force |= REDRAW_PAGE;
 
2441
}
 
2442
 
 
2443
/* --------------------------------------------------------------------------------------------- */
 
2444
/** returns 1 if canceelled by user */
 
2445
 
 
2446
int
 
2447
edit_block_delete_cmd (WEdit * edit)
 
2448
{
 
2449
    long start_mark, end_mark;
 
2450
    if (eval_marks (edit, &start_mark, &end_mark))
 
2451
    {
 
2452
        edit_delete_line (edit);
 
2453
        return 0;
 
2454
    }
 
2455
    return edit_block_delete (edit);
 
2456
}
 
2457
 
 
2458
/* --------------------------------------------------------------------------------------------- */
 
2459
/** call with edit = 0 before shutdown to close memory leaks */
 
2460
 
 
2461
void
 
2462
edit_replace_cmd (WEdit * edit, int again)
 
2463
{
 
2464
    /* 1 = search string, 2 = replace with */
 
2465
    static char *saved1 = NULL; /* saved default[123] */
 
2466
    static char *saved2 = NULL;
 
2467
    char *input1 = NULL;        /* user input from the dialog */
 
2468
    char *input2 = NULL;
 
2469
    GString *input2_str = NULL;
 
2470
    char *disp1 = NULL;
 
2471
    char *disp2 = NULL;
 
2472
    long times_replaced = 0;
 
2473
    gboolean once_found = FALSE;
 
2474
 
 
2475
    if (!edit)
 
2476
    {
 
2477
        g_free (saved1), saved1 = NULL;
 
2478
        g_free (saved2), saved2 = NULL;
 
2479
        return;
 
2480
    }
 
2481
 
 
2482
    edit->force |= REDRAW_COMPLETELY;
 
2483
 
 
2484
    if (again && !saved1 && !saved2)
 
2485
        again = 0;
 
2486
 
 
2487
    if (again)
 
2488
    {
 
2489
        input1 = g_strdup (saved1 ? saved1 : "");
 
2490
        input2 = g_strdup (saved2 ? saved2 : "");
 
2491
    }
 
2492
    else
 
2493
    {
 
2494
        char *tmp_inp1, *tmp_inp2;
 
2495
 
 
2496
        disp1 = edit_replace_cmd__conv_to_display (saved1 ? saved1 : (char *) "");
 
2497
        disp2 = edit_replace_cmd__conv_to_display (saved2 ? saved2 : (char *) "");
 
2498
 
 
2499
        edit_push_undo_action (edit, KEY_PRESS + edit->start_display);
 
2500
 
 
2501
        editcmd_dialog_replace_show (edit, disp1, disp2, &input1, &input2);
 
2502
 
 
2503
        g_free (disp1);
 
2504
        g_free (disp2);
 
2505
 
 
2506
        if (input1 == NULL || *input1 == '\0')
 
2507
        {
 
2508
            edit->force = REDRAW_COMPLETELY;
 
2509
            goto cleanup;
 
2510
        }
 
2511
 
 
2512
        tmp_inp1 = input1;
 
2513
        tmp_inp2 = input2;
 
2514
        input1 = edit_replace_cmd__conv_to_input (input1);
 
2515
        input2 = edit_replace_cmd__conv_to_input (input2);
 
2516
        g_free (tmp_inp1);
 
2517
        g_free (tmp_inp2);
 
2518
 
 
2519
        g_free (saved1), saved1 = g_strdup (input1);
 
2520
        g_free (saved2), saved2 = g_strdup (input2);
 
2521
 
 
2522
        mc_search_free (edit->search);
 
2523
        edit->search = NULL;
 
2524
    }
 
2525
 
 
2526
    input2_str = g_string_new (input2);
 
2527
 
 
2528
    if (!edit->search)
 
2529
    {
 
2530
        edit->search = mc_search_new (input1, -1);
 
2531
        if (edit->search == NULL)
 
2532
        {
 
2533
            edit->search_start = edit->curs1;
 
2534
            goto cleanup;
 
2535
        }
 
2536
        edit->search->search_type = edit_search_options.type;
 
2537
        edit->search->is_all_charsets = edit_search_options.all_codepages;
 
2538
        edit->search->is_case_sensitive = edit_search_options.case_sens;
 
2539
        edit->search->whole_words = edit_search_options.whole_words;
 
2540
        edit->search->search_fn = edit_search_cmd_callback;
 
2541
        edit->search_line_type = edit_get_search_line_type (edit->search);
 
2542
        edit_search_fix_search_start_if_selection (edit);
 
2543
    }
 
2544
 
 
2545
    if (edit->found_len && edit->search_start == edit->found_start + 1
 
2546
        && edit_search_options.backwards)
 
2547
        edit->search_start--;
 
2548
 
 
2549
    if (edit->found_len && edit->search_start == edit->found_start - 1
 
2550
        && !edit_search_options.backwards)
 
2551
        edit->search_start++;
 
2552
 
 
2553
    do
 
2554
    {
 
2555
        gsize len = 0;
 
2556
 
 
2557
        if (!editcmd_find (edit, &len))
 
2558
        {
 
2559
            if (!(edit->search->error == MC_SEARCH_E_OK ||
 
2560
                  (once_found && edit->search->error == MC_SEARCH_E_NOTFOUND)))
 
2561
            {
 
2562
                edit_error_dialog (_("Search"), edit->search->error_str);
 
2563
            }
 
2564
            break;
 
2565
        }
 
2566
        once_found = TRUE;
 
2567
 
 
2568
        edit->search_start = edit->search->normal_offset;
 
2569
        /*returns negative on not found or error in pattern */
 
2570
 
 
2571
        if ((edit->search_start >= 0) && (edit->search_start < edit->last_byte))
 
2572
        {
 
2573
            gsize i;
 
2574
            GString *repl_str;
 
2575
 
 
2576
            edit->found_start = edit->search_start;
 
2577
            i = edit->found_len = len;
 
2578
 
 
2579
            edit_cursor_move (edit, edit->search_start - edit->curs1);
 
2580
            edit_scroll_screen_over_cursor (edit);
 
2581
 
 
2582
            if (edit->replace_mode == 0)
 
2583
            {
 
2584
                int l;
 
2585
                int prompt;
 
2586
 
 
2587
                l = edit->curs_row - edit->widget.lines / 3;
 
2588
                if (l > 0)
 
2589
                    edit_scroll_downward (edit, l);
 
2590
                if (l < 0)
 
2591
                    edit_scroll_upward (edit, -l);
 
2592
 
 
2593
                edit_scroll_screen_over_cursor (edit);
 
2594
                edit->force |= REDRAW_PAGE;
 
2595
                edit_render_keypress (edit);
 
2596
 
 
2597
                /*so that undo stops at each query */
 
2598
                edit_push_key_press (edit);
 
2599
                /* and prompt 2/3 down */
 
2600
                disp1 = edit_replace_cmd__conv_to_display (saved1);
 
2601
                disp2 = edit_replace_cmd__conv_to_display (saved2);
 
2602
                prompt = editcmd_dialog_replace_prompt_show (edit, disp1, disp2, -1, -1);
 
2603
                g_free (disp1);
 
2604
                g_free (disp2);
 
2605
 
 
2606
                if (prompt == B_REPLACE_ALL)
 
2607
                    edit->replace_mode = 1;
 
2608
                else if (prompt == B_SKIP_REPLACE)
 
2609
                {
 
2610
                    if (edit_search_options.backwards)
 
2611
                        edit->search_start--;
 
2612
                    else
 
2613
                        edit->search_start++;
 
2614
                    continue;   /* loop */
 
2615
                }
 
2616
                else if (prompt == B_CANCEL)
 
2617
                {
 
2618
                    edit->replace_mode = -1;
 
2619
                    break;      /* loop */
 
2620
                }
 
2621
            }
 
2622
 
 
2623
            repl_str = mc_search_prepare_replace_str (edit->search, input2_str);
 
2624
 
 
2625
            if (edit->search->error != MC_SEARCH_E_OK)
 
2626
            {
 
2627
                edit_error_dialog (_("Replace"), edit->search->error_str);
 
2628
                g_string_free (repl_str, TRUE);
 
2629
                break;
 
2630
            }
 
2631
 
 
2632
            /* delete then insert new */
 
2633
            for (i = 0; i < len; i++)
 
2634
                edit_delete (edit, 1);
 
2635
 
 
2636
            for (i = 0; i < repl_str->len; i++)
 
2637
                edit_insert (edit, repl_str->str[i]);
 
2638
 
 
2639
            edit->found_len = repl_str->len;
 
2640
            g_string_free (repl_str, TRUE);
 
2641
            times_replaced++;
 
2642
 
 
2643
            /* so that we don't find the same string again */
 
2644
            if (edit_search_options.backwards)
 
2645
            {
 
2646
                edit->search_start--;
 
2647
            }
 
2648
            else
 
2649
            {
 
2650
                edit->search_start += edit->found_len + (len == 0 ? 1 : 0);
 
2651
 
 
2652
                if (edit->search_start >= edit->last_byte)
 
2653
                    break;
 
2654
            }
 
2655
 
 
2656
            edit_scroll_screen_over_cursor (edit);
 
2657
        }
 
2658
        else
 
2659
        {
 
2660
            /* try and find from right here for next search */
 
2661
            edit->search_start = edit->curs1;
 
2662
            edit_update_curs_col (edit);
 
2663
 
 
2664
            edit->force |= REDRAW_PAGE;
 
2665
            edit_render_keypress (edit);
 
2666
 
 
2667
            if (times_replaced == 0)
 
2668
                query_dialog (_("Replace"), _("Search string not found"), D_NORMAL, 1, _("&OK"));
 
2669
            break;
 
2670
        }
 
2671
    }
 
2672
    while (edit->replace_mode >= 0);
 
2673
 
 
2674
    edit_scroll_screen_over_cursor (edit);
 
2675
    edit->force |= REDRAW_COMPLETELY;
 
2676
    edit_render_keypress (edit);
 
2677
 
 
2678
    if ((edit->replace_mode == 1) && (times_replaced != 0))
 
2679
        message (D_NORMAL, _("Replace"), _("%ld replacements made"), times_replaced);
 
2680
 
 
2681
  cleanup:
 
2682
    g_free (input1);
 
2683
    g_free (input2);
 
2684
    if (input2_str != NULL)
 
2685
        g_string_free (input2_str, TRUE);
 
2686
}
 
2687
 
 
2688
/* --------------------------------------------------------------------------------------------- */
 
2689
 
 
2690
mc_search_cbret_t
 
2691
edit_search_cmd_callback (const void *user_data, gsize char_offset, int *current_char)
 
2692
{
 
2693
    *current_char = edit_get_byte ((WEdit *) user_data, (long) char_offset);
 
2694
    return MC_SEARCH_CB_OK;
 
2695
}
 
2696
 
 
2697
/* --------------------------------------------------------------------------------------------- */
 
2698
 
 
2699
void
 
2700
edit_search_cmd (WEdit * edit, gboolean again)
 
2701
{
 
2702
 
 
2703
    if (edit == NULL)
 
2704
        return;
 
2705
 
 
2706
    if (!again)
 
2707
        edit_search (edit);
 
2708
    else if (edit->last_search_string != NULL)
 
2709
        edit_do_search (edit);
 
2710
    else
 
2711
    {
 
2712
        /* find last search string in history */
 
2713
        GList *history;
 
2714
 
 
2715
        history = history_get (MC_HISTORY_SHARED_SEARCH);
 
2716
        if (history != NULL && history->data != NULL)
 
2717
        {
 
2718
            edit->last_search_string = (char *) history->data;
 
2719
            history->data = NULL;
 
2720
            history = g_list_first (history);
 
2721
            g_list_foreach (history, (GFunc) g_free, NULL);
 
2722
            g_list_free (history);
 
2723
 
 
2724
            edit->search = mc_search_new (edit->last_search_string, -1);
 
2725
            if (edit->search == NULL)
 
2726
            {
 
2727
                /* if not... then ask for an expression */
 
2728
                g_free (edit->last_search_string);
 
2729
                edit->last_search_string = NULL;
 
2730
                edit_search (edit);
 
2731
            }
 
2732
            else
 
2733
            {
 
2734
                edit->search->search_type = edit_search_options.type;
 
2735
                edit->search->is_all_charsets = edit_search_options.all_codepages;
 
2736
                edit->search->is_case_sensitive = edit_search_options.case_sens;
 
2737
                edit->search->whole_words = edit_search_options.whole_words;
 
2738
                edit->search->search_fn = edit_search_cmd_callback;
 
2739
                edit->search_line_type = edit_get_search_line_type (edit->search);
 
2740
                edit_do_search (edit);
 
2741
            }
 
2742
        }
 
2743
        else
 
2744
        {
 
2745
            /* if not... then ask for an expression */
 
2746
            g_free (edit->last_search_string);
 
2747
            edit->last_search_string = NULL;
 
2748
            edit_search (edit);
 
2749
        }
 
2750
    }
 
2751
}
 
2752
 
 
2753
 
 
2754
/* --------------------------------------------------------------------------------------------- */
 
2755
/**
 
2756
 * Check if it's OK to close the editor.  If there are unsaved changes,
 
2757
 * ask user.  Return 1 if it's OK to exit, 0 to continue editing.
 
2758
 */
 
2759
 
 
2760
gboolean
 
2761
edit_ok_to_exit (WEdit * edit)
 
2762
{
 
2763
    int act;
 
2764
 
 
2765
    if (!edit->modified)
 
2766
        return TRUE;
 
2767
 
 
2768
    if (!mc_global.midnight_shutdown)
 
2769
    {
 
2770
        if (!edit_check_newline (edit))
 
2771
            return FALSE;
 
2772
 
 
2773
        query_set_sel (2);
 
2774
        act = edit_query_dialog3 (_("Quit"), _("File was modified. Save with exit?"),
 
2775
                                  _("&Yes"), _("&No"), _("&Cancel quit"));
 
2776
    }
 
2777
    else
 
2778
    {
 
2779
        act =
 
2780
            edit_query_dialog2 (_("Quit"),
 
2781
                                _("Midnight Commander is being shut down.\nSave modified file?"),
 
2782
                                _("&Yes"), _("&No"));
 
2783
 
 
2784
        /* Esc is No */
 
2785
        if (act == -1)
 
2786
            act = 1;
 
2787
    }
 
2788
 
 
2789
    switch (act)
 
2790
    {
 
2791
    case 0:                    /* Yes */
 
2792
        edit_push_markers (edit);
 
2793
        edit_set_markers (edit, 0, 0, 0, 0);
 
2794
        if (!edit_save_cmd (edit) || mc_global.midnight_shutdown)
 
2795
            return mc_global.midnight_shutdown;
 
2796
        break;
 
2797
    case 1:                    /* No */
 
2798
        break;
 
2799
    case 2:                    /* Cancel quit */
 
2800
    case -1:                   /* Esc */
 
2801
        return FALSE;
 
2802
    }
 
2803
 
 
2804
    return TRUE;
 
2805
}
 
2806
 
 
2807
/* --------------------------------------------------------------------------------------------- */
 
2808
/** save block, returns 1 on success */
 
2809
 
 
2810
int
 
2811
edit_save_block (WEdit * edit, const char *filename, long start, long finish)
 
2812
{
 
2813
    int len, file;
 
2814
    vfs_path_t *vpath;
 
2815
 
 
2816
    vpath = vfs_path_from_str (filename);
 
2817
    file = mc_open (vpath, O_CREAT | O_WRONLY | O_TRUNC,
 
2818
                    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | O_BINARY);
 
2819
    vfs_path_free (vpath);
 
2820
    if (file == -1)
 
2821
        return 0;
 
2822
 
 
2823
    if (edit->column_highlight)
 
2824
    {
 
2825
        int r;
 
2826
 
 
2827
        r = mc_write (file, VERTICAL_MAGIC, sizeof (VERTICAL_MAGIC));
 
2828
        if (r > 0)
 
2829
        {
 
2830
            unsigned char *block, *p;
 
2831
 
 
2832
            p = block = edit_get_block (edit, start, finish, &len);
 
2833
            while (len)
 
2834
            {
 
2835
                r = mc_write (file, p, len);
 
2836
                if (r < 0)
 
2837
                    break;
 
2838
                p += r;
 
2839
                len -= r;
 
2840
            }
 
2841
            g_free (block);
 
2842
        }
 
2843
    }
 
2844
    else
 
2845
    {
 
2846
        unsigned char *buf;
 
2847
        int i = start, end;
 
2848
 
 
2849
        len = finish - start;
 
2850
        buf = g_malloc0 (TEMP_BUF_LEN);
 
2851
        while (start != finish)
 
2852
        {
 
2853
            end = min (finish, start + TEMP_BUF_LEN);
 
2854
            for (; i < end; i++)
 
2855
                buf[i - start] = edit_get_byte (edit, i);
 
2856
            len -= mc_write (file, (char *) buf, end - start);
 
2857
            start = end;
 
2858
        }
 
2859
        g_free (buf);
 
2860
    }
 
2861
    mc_close (file);
 
2862
    if (len)
 
2863
        return 0;
 
2864
    return 1;
 
2865
}
 
2866
 
 
2867
/* --------------------------------------------------------------------------------------------- */
 
2868
 
 
2869
void
 
2870
edit_paste_from_history (WEdit * edit)
 
2871
{
 
2872
    (void) edit;
 
2873
    edit_error_dialog (_("Error"), _("This function is not implemented"));
 
2874
}
 
2875
 
 
2876
/* --------------------------------------------------------------------------------------------- */
 
2877
 
 
2878
int
 
2879
edit_copy_to_X_buf_cmd (WEdit * edit)
 
2880
{
 
2881
    long start_mark, end_mark;
 
2882
    if (eval_marks (edit, &start_mark, &end_mark))
 
2883
        return 0;
 
2884
    if (!edit_save_block_to_clip_file (edit, start_mark, end_mark))
 
2885
    {
 
2886
        edit_error_dialog (_("Copy to clipboard"), get_sys_error (_("Unable to save to file")));
 
2887
        return 1;
 
2888
    }
 
2889
    /* try use external clipboard utility */
 
2890
    mc_event_raise (MCEVENT_GROUP_CORE, "clipboard_file_to_ext_clip", NULL);
 
2891
 
 
2892
    return 0;
 
2893
}
 
2894
 
 
2895
/* --------------------------------------------------------------------------------------------- */
 
2896
 
 
2897
int
 
2898
edit_cut_to_X_buf_cmd (WEdit * edit)
 
2899
{
 
2900
    long start_mark, end_mark;
 
2901
    if (eval_marks (edit, &start_mark, &end_mark))
 
2902
        return 0;
 
2903
    if (!edit_save_block_to_clip_file (edit, start_mark, end_mark))
 
2904
    {
 
2905
        edit_error_dialog (_("Cut to clipboard"), _("Unable to save to file"));
 
2906
        return 1;
 
2907
    }
 
2908
    /* try use external clipboard utility */
 
2909
    mc_event_raise (MCEVENT_GROUP_CORE, "clipboard_file_to_ext_clip", NULL);
 
2910
 
 
2911
    edit_block_delete_cmd (edit);
 
2912
    edit_mark_cmd (edit, 1);
 
2913
    return 0;
 
2914
}
 
2915
 
 
2916
/* --------------------------------------------------------------------------------------------- */
 
2917
 
 
2918
void
 
2919
edit_paste_from_X_buf_cmd (WEdit * edit)
 
2920
{
 
2921
    vfs_path_t *tmp;
 
2922
 
 
2923
    /* try use external clipboard utility */
 
2924
    mc_event_raise (MCEVENT_GROUP_CORE, "clipboard_file_from_ext_clip", NULL);
 
2925
    tmp = mc_config_get_full_vpath (EDIT_CLIP_FILE);
 
2926
    edit_insert_file (edit, tmp);
 
2927
    vfs_path_free (tmp);
 
2928
}
 
2929
 
 
2930
 
 
2931
/* --------------------------------------------------------------------------------------------- */
 
2932
/**
 
2933
 * Ask user for the line and go to that line.
 
2934
 * Negative numbers mean line from the end (i.e. -1 is the last line).
 
2935
 */
 
2936
 
 
2937
void
 
2938
edit_goto_cmd (WEdit * edit)
 
2939
{
 
2940
    char *f;
 
2941
    static long line = 0;       /* line as typed, saved as default */
 
2942
    long l;
 
2943
    char *error;
 
2944
    char s[32];
 
2945
 
 
2946
    g_snprintf (s, sizeof (s), "%ld", line);
 
2947
    f = input_dialog (_("Goto line"), _("Enter line:"), MC_HISTORY_EDIT_GOTO_LINE, line ? s : "");
 
2948
    if (!f)
 
2949
        return;
 
2950
 
 
2951
    if (!*f)
 
2952
    {
 
2953
        g_free (f);
 
2954
        return;
 
2955
    }
 
2956
 
 
2957
    l = strtol (f, &error, 0);
 
2958
    if (*error)
 
2959
    {
 
2960
        g_free (f);
 
2961
        return;
 
2962
    }
 
2963
 
 
2964
    line = l;
 
2965
    if (l < 0)
 
2966
        l = edit->total_lines + l + 2;
 
2967
    edit_move_display (edit, l - edit->widget.lines / 2 - 1);
 
2968
    edit_move_to_line (edit, l - 1);
 
2969
    edit->force |= REDRAW_COMPLETELY;
 
2970
    g_free (f);
 
2971
}
 
2972
 
 
2973
 
 
2974
/* --------------------------------------------------------------------------------------------- */
 
2975
/** Return 1 on success */
 
2976
 
 
2977
int
 
2978
edit_save_block_cmd (WEdit * edit)
 
2979
{
 
2980
    long start_mark, end_mark;
 
2981
    char *exp, *tmp;
 
2982
 
 
2983
    if (eval_marks (edit, &start_mark, &end_mark))
 
2984
        return 1;
 
2985
 
 
2986
    tmp = mc_config_get_full_path (EDIT_CLIP_FILE);
 
2987
    exp =
 
2988
        input_expand_dialog (_("Save block"), _("Enter file name:"),
 
2989
                             MC_HISTORY_EDIT_SAVE_BLOCK, tmp);
 
2990
    g_free (tmp);
 
2991
    edit_push_undo_action (edit, KEY_PRESS + edit->start_display);
 
2992
    if (exp)
 
2993
    {
 
2994
        if (!*exp)
 
2995
        {
 
2996
            g_free (exp);
 
2997
            return 0;
 
2998
        }
 
2999
        else
 
3000
        {
 
3001
            if (edit_save_block (edit, exp, start_mark, end_mark))
 
3002
            {
 
3003
                g_free (exp);
 
3004
                edit->force |= REDRAW_COMPLETELY;
 
3005
                return 1;
 
3006
            }
 
3007
            else
 
3008
            {
 
3009
                g_free (exp);
 
3010
                edit_error_dialog (_("Save block"), get_sys_error (_("Cannot save file")));
 
3011
            }
 
3012
        }
 
3013
    }
 
3014
    edit->force |= REDRAW_COMPLETELY;
 
3015
    return 0;
 
3016
}
 
3017
 
 
3018
 
 
3019
/* --------------------------------------------------------------------------------------------- */
 
3020
/** returns TRUE on success */
 
3021
 
 
3022
gboolean
 
3023
edit_insert_file_cmd (WEdit * edit)
 
3024
{
 
3025
    char *tmp;
 
3026
    char *exp;
 
3027
    gboolean ret = FALSE;
 
3028
 
 
3029
    tmp = mc_config_get_full_path (EDIT_CLIP_FILE);
 
3030
    exp = input_expand_dialog (_("Insert file"), _("Enter file name:"),
 
3031
                               MC_HISTORY_EDIT_INSERT_FILE, tmp);
 
3032
    g_free (tmp);
 
3033
 
 
3034
    edit_push_undo_action (edit, KEY_PRESS + edit->start_display);
 
3035
 
 
3036
    if (exp != NULL && *exp != '\0')
 
3037
    {
 
3038
        vfs_path_t *exp_vpath;
 
3039
 
 
3040
        exp_vpath = vfs_path_from_str (exp);
 
3041
        ret = (edit_insert_file (edit, exp_vpath) >= 0);
 
3042
        vfs_path_free (exp_vpath);
 
3043
 
 
3044
        if (!ret)
 
3045
            edit_error_dialog (_("Insert file"), get_sys_error (_("Cannot insert file")));
 
3046
    }
 
3047
 
 
3048
    g_free (exp);
 
3049
 
 
3050
    edit->force |= REDRAW_COMPLETELY;
 
3051
    return ret;
 
3052
}
 
3053
 
 
3054
/* --------------------------------------------------------------------------------------------- */
 
3055
/** sorts a block, returns -1 on system fail, 1 on cancel and 0 on success */
 
3056
 
 
3057
int
 
3058
edit_sort_cmd (WEdit * edit)
 
3059
{
 
3060
    static char *old = 0;
 
3061
    char *exp, *tmp, *tmp_edit_block_name, *tmp_edit_temp_name;
 
3062
    long start_mark, end_mark;
 
3063
    int e;
 
3064
 
 
3065
    if (eval_marks (edit, &start_mark, &end_mark))
 
3066
    {
 
3067
        edit_error_dialog (_("Sort block"), _("You must first highlight a block of text"));
 
3068
        return 0;
 
3069
    }
 
3070
 
 
3071
    tmp = mc_config_get_full_path (EDIT_BLOCK_FILE);
 
3072
    edit_save_block (edit, tmp, start_mark, end_mark);
 
3073
    g_free (tmp);
 
3074
 
 
3075
    exp = input_dialog (_("Run sort"),
 
3076
                        _("Enter sort options (see manpage) separated by whitespace:"),
 
3077
                        MC_HISTORY_EDIT_SORT, (old != NULL) ? old : "");
 
3078
 
 
3079
    if (!exp)
 
3080
        return 1;
 
3081
    g_free (old);
 
3082
    old = exp;
 
3083
    tmp_edit_block_name = mc_config_get_full_path (EDIT_BLOCK_FILE);
 
3084
    tmp_edit_temp_name = mc_config_get_full_path (EDIT_TEMP_FILE);
 
3085
    tmp =
 
3086
        g_strconcat (" sort ", exp, " ", tmp_edit_block_name,
 
3087
                     " > ", tmp_edit_temp_name, (char *) NULL);
 
3088
    g_free (tmp_edit_temp_name);
 
3089
    g_free (tmp_edit_block_name);
 
3090
 
 
3091
    e = system (tmp);
 
3092
    g_free (tmp);
 
3093
    if (e)
 
3094
    {
 
3095
        if (e == -1 || e == 127)
 
3096
        {
 
3097
            edit_error_dialog (_("Sort"), get_sys_error (_("Cannot execute sort command")));
 
3098
        }
 
3099
        else
 
3100
        {
 
3101
            char q[8];
 
3102
            sprintf (q, "%d ", e);
 
3103
            tmp = g_strdup_printf (_("Sort returned non-zero: %s"), q);
 
3104
            edit_error_dialog (_("Sort"), tmp);
 
3105
            g_free (tmp);
 
3106
        }
 
3107
        return -1;
 
3108
    }
 
3109
 
 
3110
    edit->force |= REDRAW_COMPLETELY;
 
3111
 
 
3112
    if (edit_block_delete_cmd (edit))
 
3113
        return 1;
 
3114
 
 
3115
    {
 
3116
        vfs_path_t *tmp_vpath;
 
3117
 
 
3118
        tmp_vpath = mc_config_get_full_vpath (EDIT_TEMP_FILE);
 
3119
        edit_insert_file (edit, tmp_vpath);
 
3120
        vfs_path_free (tmp_vpath);
 
3121
    }
 
3122
    return 0;
 
3123
}
 
3124
 
 
3125
/* --------------------------------------------------------------------------------------------- */
 
3126
/**
 
3127
 * Ask user for a command, execute it and paste its output back to the
 
3128
 * editor.
 
3129
 */
 
3130
 
 
3131
int
 
3132
edit_ext_cmd (WEdit * edit)
 
3133
{
 
3134
    char *exp, *tmp, *tmp_edit_temp_file;
 
3135
    int e;
 
3136
 
 
3137
    exp =
 
3138
        input_dialog (_("Paste output of external command"),
 
3139
                      _("Enter shell command(s):"), MC_HISTORY_EDIT_PASTE_EXTCMD, NULL);
 
3140
 
 
3141
    if (!exp)
 
3142
        return 1;
 
3143
 
 
3144
    tmp_edit_temp_file = mc_config_get_full_path (EDIT_TEMP_FILE);
 
3145
    tmp = g_strconcat (exp, " > ", tmp_edit_temp_file, (char *) NULL);
 
3146
    g_free (tmp_edit_temp_file);
 
3147
    e = system (tmp);
 
3148
    g_free (tmp);
 
3149
    g_free (exp);
 
3150
 
 
3151
    if (e)
 
3152
    {
 
3153
        edit_error_dialog (_("External command"), get_sys_error (_("Cannot execute command")));
 
3154
        return -1;
 
3155
    }
 
3156
 
 
3157
    edit->force |= REDRAW_COMPLETELY;
 
3158
 
 
3159
    {
 
3160
        vfs_path_t *tmp_vpath;
 
3161
 
 
3162
        tmp_vpath = mc_config_get_full_vpath (EDIT_TEMP_FILE);
 
3163
        edit_insert_file (edit, tmp_vpath);
 
3164
        vfs_path_free (tmp_vpath);
 
3165
    }
 
3166
    return 0;
 
3167
}
 
3168
 
 
3169
/* --------------------------------------------------------------------------------------------- */
 
3170
/** if block is 1, a block must be highlighted and the shell command
 
3171
   processes it. If block is 0 the shell command is a straight system
 
3172
   command, that just produces some output which is to be inserted */
 
3173
 
 
3174
void
 
3175
edit_block_process_cmd (WEdit * edit, int macro_number)
 
3176
{
 
3177
    char *fname;
 
3178
    char *macros_fname = NULL;
 
3179
 
 
3180
    fname = g_strdup_printf ("%s.%i.sh", MC_EXTMACRO_FILE, macro_number);
 
3181
    macros_fname = g_build_filename (mc_config_get_data_path (), fname, (char *) NULL);
 
3182
    user_menu (edit, macros_fname, 0);
 
3183
    g_free (fname);
 
3184
    g_free (macros_fname);
 
3185
    edit->force |= REDRAW_COMPLETELY;
 
3186
}
 
3187
 
 
3188
/* --------------------------------------------------------------------------------------------- */
 
3189
 
 
3190
void
 
3191
edit_mail_dialog (WEdit * edit)
 
3192
{
 
3193
    char *tmail_to;
 
3194
    char *tmail_subject;
 
3195
    char *tmail_cc;
 
3196
 
 
3197
    static char *mail_cc_last = 0;
 
3198
    static char *mail_subject_last = 0;
 
3199
    static char *mail_to_last = 0;
 
3200
 
 
3201
    QuickWidget quick_widgets[] = {
 
3202
        /* 0 */ QUICK_BUTTON (6, 10, 9, MAIL_DLG_HEIGHT, N_("&Cancel"), B_CANCEL, NULL),
 
3203
        /* 1 */ QUICK_BUTTON (2, 10, 9, MAIL_DLG_HEIGHT, N_("&OK"), B_ENTER, NULL),
 
3204
        /* 2 */ QUICK_INPUT (3, 50, 8, MAIL_DLG_HEIGHT, "", 44, 0, "mail-dlg-input", &tmail_cc),
 
3205
        /* 3 */ QUICK_LABEL (3, 50, 7, MAIL_DLG_HEIGHT, N_("Copies to")),
 
3206
        /* 4 */ QUICK_INPUT (3, 50, 6, MAIL_DLG_HEIGHT, "", 44, 0, "mail-dlg-input-2",
 
3207
                             &tmail_subject),
 
3208
        /* 5 */ QUICK_LABEL (3, 50, 5, MAIL_DLG_HEIGHT, N_("Subject")),
 
3209
        /* 6 */ QUICK_INPUT (3, 50, 4, MAIL_DLG_HEIGHT, "", 44, 0, "mail-dlg-input-3", &tmail_to),
 
3210
        /* 7 */ QUICK_LABEL (3, 50, 3, MAIL_DLG_HEIGHT, N_("To")),
 
3211
        /* 8 */ QUICK_LABEL (3, 50, 2, MAIL_DLG_HEIGHT, N_("mail -s <subject> -c <cc> <to>")),
 
3212
        QUICK_END
 
3213
    };
 
3214
 
 
3215
    QuickDialog Quick_input = {
 
3216
        50, MAIL_DLG_HEIGHT, -1, -1, N_("Mail"),
 
3217
        "[Input Line Keys]", quick_widgets, NULL, FALSE
 
3218
    };
 
3219
 
 
3220
    quick_widgets[2].u.input.text = mail_cc_last ? mail_cc_last : "";
 
3221
    quick_widgets[4].u.input.text = mail_subject_last ? mail_subject_last : "";
 
3222
    quick_widgets[6].u.input.text = mail_to_last ? mail_to_last : "";
 
3223
 
 
3224
    if (quick_dialog (&Quick_input) != B_CANCEL)
 
3225
    {
 
3226
        g_free (mail_cc_last);
 
3227
        g_free (mail_subject_last);
 
3228
        g_free (mail_to_last);
 
3229
        mail_cc_last = tmail_cc;
 
3230
        mail_subject_last = tmail_subject;
 
3231
        mail_to_last = tmail_to;
 
3232
        pipe_mail (edit, mail_to_last, mail_subject_last, mail_cc_last);
 
3233
    }
 
3234
}
 
3235
 
 
3236
 
 
3237
/*******************/
 
3238
/* Word Completion */
 
3239
/*******************/
 
3240
 
 
3241
/* --------------------------------------------------------------------------------------------- */
 
3242
/**
 
3243
 * Complete current word using regular expression search
 
3244
 * backwards beginning at the current cursor position.
 
3245
 */
 
3246
 
 
3247
void
 
3248
edit_complete_word_cmd (WEdit * edit)
 
3249
{
 
3250
    gsize i, max_len, word_len = 0, num_compl = 0;
 
3251
    long word_start = 0;
 
3252
    unsigned char *bufpos;
 
3253
    char *match_expr;
 
3254
    struct selection compl[MAX_WORD_COMPLETIONS];       /* completions */
 
3255
 
 
3256
    /* search start of word to be completed */
 
3257
    if (!edit_find_word_start (edit, &word_start, &word_len))
 
3258
        return;
 
3259
 
 
3260
    /* prepare match expression */
 
3261
    bufpos = &edit->buffers1[word_start >> S_EDIT_BUF_SIZE][word_start & M_EDIT_BUF_SIZE];
 
3262
 
 
3263
    /* match_expr = g_strdup_printf ("\\b%.*s[a-zA-Z_0-9]+", word_len, bufpos); */
 
3264
    match_expr =
 
3265
        g_strdup_printf
 
3266
        ("(^|\\s+|\\b)%.*s[^\\s\\.=\\+\\[\\]\\(\\)\\,\\;\\:\\\"\\'\\-\\?\\/\\|\\\\\\{\\}\\*\\&\\^\\%%\\$#@\\!]+",
 
3267
         (int) word_len, bufpos);
 
3268
 
 
3269
    /* collect the possible completions              */
 
3270
    /* start search from begin to end of file */
 
3271
    max_len =
 
3272
        edit_collect_completions (edit, word_start, word_len, match_expr,
 
3273
                                  (struct selection *) &compl, &num_compl);
 
3274
 
 
3275
    if (num_compl > 0)
 
3276
    {
 
3277
        /* insert completed word if there is only one match */
 
3278
        if (num_compl == 1)
 
3279
        {
 
3280
            for (i = word_len; i < compl[0].len; i++)
 
3281
                edit_insert (edit, *(compl[0].text + i));
 
3282
        }
 
3283
        /* more than one possible completion => ask the user */
 
3284
        else
 
3285
        {
 
3286
            /* !!! usually only a beep is expected and when <ALT-TAB> is !!! */
 
3287
            /* !!! pressed again the selection dialog pops up, but that  !!! */
 
3288
            /* !!! seems to require a further internal state             !!! */
 
3289
            /*tty_beep (); */
 
3290
 
 
3291
            /* let the user select the preferred completion */
 
3292
            editcmd_dialog_completion_show (edit, max_len, word_len,
 
3293
                                            (struct selection *) &compl, num_compl);
 
3294
        }
 
3295
    }
 
3296
 
 
3297
    g_free (match_expr);
 
3298
    /* release memory before return */
 
3299
    for (i = 0; i < num_compl; i++)
 
3300
        g_free (compl[i].text);
 
3301
}
 
3302
 
 
3303
/* --------------------------------------------------------------------------------------------- */
 
3304
 
 
3305
void
 
3306
edit_select_codepage_cmd (WEdit * edit)
 
3307
{
 
3308
#ifdef HAVE_CHARSET
 
3309
    if (do_select_codepage ())
 
3310
        edit_set_codeset (edit);
 
3311
 
 
3312
    edit->force = REDRAW_COMPLETELY;
 
3313
    edit_refresh_cmd (edit);
 
3314
#else
 
3315
    (void) edit;
 
3316
#endif
 
3317
}
 
3318
 
 
3319
/* --------------------------------------------------------------------------------------------- */
 
3320
 
 
3321
void
 
3322
edit_insert_literal_cmd (WEdit * edit)
 
3323
{
 
3324
    int char_for_insertion = editcmd_dialog_raw_key_query (_("Insert literal"),
 
3325
                                                           _("Press any key:"), 0);
 
3326
    edit_execute_key_command (edit, -1, ascii_alpha_to_cntrl (char_for_insertion));
 
3327
}
 
3328
 
 
3329
/* --------------------------------------------------------------------------------------------- */
 
3330
 
 
3331
void
 
3332
edit_begin_end_macro_cmd (WEdit * edit)
 
3333
{
 
3334
    /* edit is a pointer to the widget */
 
3335
    if (edit != NULL)
 
3336
    {
 
3337
        unsigned long command = macro_index < 0 ? CK_MacroStartRecord : CK_MacroStopRecord;
 
3338
        edit_execute_key_command (edit, command, -1);
 
3339
    }
 
3340
}
 
3341
 
 
3342
 /* --------------------------------------------------------------------------------------------- */
 
3343
 
 
3344
void
 
3345
edit_begin_end_repeat_cmd (WEdit * edit)
 
3346
{
 
3347
    /* edit is a pointer to the widget */
 
3348
    if (edit != NULL)
 
3349
    {
 
3350
        unsigned long command = macro_index < 0 ? CK_RepeatStartRecord : CK_RepeatStopRecord;
 
3351
        edit_execute_key_command (edit, command, -1);
 
3352
    }
 
3353
}
 
3354
 
 
3355
/* --------------------------------------------------------------------------------------------- */
 
3356
 
 
3357
int
 
3358
edit_load_forward_cmd (WEdit * edit)
 
3359
{
 
3360
    if (edit->modified)
 
3361
    {
 
3362
        if (edit_query_dialog2
 
3363
            (_("Warning"),
 
3364
             _("Current text was modified without a file save\n"
 
3365
               "Continue discards these changes"), _("C&ontinue"), _("&Cancel")))
 
3366
        {
 
3367
            edit->force |= REDRAW_COMPLETELY;
 
3368
            return 0;
 
3369
        }
 
3370
    }
 
3371
    if (edit_stack_iterator + 1 < MAX_HISTORY_MOVETO)
 
3372
    {
 
3373
        if (edit_history_moveto[edit_stack_iterator + 1].line < 1)
 
3374
        {
 
3375
            return 1;
 
3376
        }
 
3377
        edit_stack_iterator++;
 
3378
        if (edit_history_moveto[edit_stack_iterator].filename_vpath)
 
3379
        {
 
3380
            edit_reload_line (edit, edit_history_moveto[edit_stack_iterator].filename_vpath,
 
3381
                              edit_history_moveto[edit_stack_iterator].line);
 
3382
            return 0;
 
3383
        }
 
3384
        else
 
3385
        {
 
3386
            return 1;
 
3387
        }
 
3388
    }
 
3389
    else
 
3390
    {
 
3391
        return 1;
 
3392
    }
 
3393
}
 
3394
 
 
3395
/* --------------------------------------------------------------------------------------------- */
 
3396
 
 
3397
int
 
3398
edit_load_back_cmd (WEdit * edit)
 
3399
{
 
3400
    if (edit->modified)
 
3401
    {
 
3402
        if (edit_query_dialog2
 
3403
            (_("Warning"),
 
3404
             _("Current text was modified without a file save\n"
 
3405
               "Continue discards these changes"), _("C&ontinue"), _("&Cancel")))
 
3406
        {
 
3407
            edit->force |= REDRAW_COMPLETELY;
 
3408
            return 0;
 
3409
        }
 
3410
    }
 
3411
    if (edit_stack_iterator > 0)
 
3412
    {
 
3413
        edit_stack_iterator--;
 
3414
        if (edit_history_moveto[edit_stack_iterator].filename_vpath)
 
3415
        {
 
3416
            edit_reload_line (edit, edit_history_moveto[edit_stack_iterator].filename_vpath,
 
3417
                              edit_history_moveto[edit_stack_iterator].line);
 
3418
            return 0;
 
3419
        }
 
3420
        else
 
3421
        {
 
3422
            return 1;
 
3423
        }
 
3424
    }
 
3425
    else
 
3426
    {
 
3427
        return 1;
 
3428
    }
 
3429
}
 
3430
 
 
3431
/* --------------------------------------------------------------------------------------------- */
 
3432
 
 
3433
void
 
3434
edit_get_match_keyword_cmd (WEdit * edit)
 
3435
{
 
3436
    gsize word_len = 0, max_len = 0;
 
3437
    int num_def = 0;
 
3438
    int i;
 
3439
    long word_start = 0;
 
3440
    unsigned char *bufpos;
 
3441
    char *match_expr;
 
3442
    char *path = NULL;
 
3443
    char *ptr = NULL;
 
3444
    char *tagfile = NULL;
 
3445
 
 
3446
    etags_hash_t def_hash[MAX_DEFINITIONS];
 
3447
 
 
3448
    for (i = 0; i < MAX_DEFINITIONS; i++)
 
3449
    {
 
3450
        def_hash[i].filename = NULL;
 
3451
    }
 
3452
 
 
3453
    /* search start of word to be completed */
 
3454
    if (!edit_find_word_start (edit, &word_start, &word_len))
 
3455
        return;
 
3456
 
 
3457
    /* prepare match expression */
 
3458
    bufpos = &edit->buffers1[word_start >> S_EDIT_BUF_SIZE][word_start & M_EDIT_BUF_SIZE];
 
3459
    match_expr = g_strdup_printf ("%.*s", (int) word_len, bufpos);
 
3460
 
 
3461
    ptr = g_get_current_dir ();
 
3462
    path = g_strconcat (ptr, G_DIR_SEPARATOR_S, (char *) NULL);
 
3463
    g_free (ptr);
 
3464
 
 
3465
    /* Recursive search file 'TAGS' in parent dirs */
 
3466
    do
 
3467
    {
 
3468
        ptr = g_path_get_dirname (path);
 
3469
        g_free (path);
 
3470
        path = ptr;
 
3471
        g_free (tagfile);
 
3472
        tagfile = mc_build_filename (path, TAGS_NAME, (char *) NULL);
 
3473
        if (exist_file (tagfile))
 
3474
            break;
 
3475
    }
 
3476
    while (strcmp (path, G_DIR_SEPARATOR_S) != 0);
 
3477
 
 
3478
    if (tagfile)
 
3479
    {
 
3480
        num_def =
 
3481
            etags_set_definition_hash (tagfile, path, match_expr, (etags_hash_t *) & def_hash);
 
3482
        g_free (tagfile);
 
3483
    }
 
3484
    g_free (path);
 
3485
 
 
3486
    max_len = MAX_WIDTH_DEF_DIALOG;
 
3487
    word_len = 0;
 
3488
    if (num_def > 0)
 
3489
    {
 
3490
        editcmd_dialog_select_definition_show (edit, match_expr, max_len, word_len,
 
3491
                                               (etags_hash_t *) & def_hash, num_def);
 
3492
    }
 
3493
    g_free (match_expr);
 
3494
}
 
3495
 
 
3496
/* --------------------------------------------------------------------------------------------- */