📄 editcmd.c
字号:
/* editor high level editing commands.
Copyright (C) 1996, 1997 the Free Software Foundation
Authors: 1996, 1997 Paul Sheer
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* #define PIPE_BLOCKS_SO_READ_BYTE_BY_BYTE */
#include <config.h>
#ifdef OS2_NT
#include <io.h>
#include <fcntl.h>
#endif
#include <ctype.h>
#include "edit.h"
#include "editcmddef.h"
#ifndef MIDNIGHT
#include <X11/Xatom.h>
#include "loadfile.h"
#endif
/* globals: */
/* search and replace: */
int replace_scanf = 0;
int replace_regexp = 0;
int replace_all = 0;
int replace_prompt = 1;
int replace_whole = 0;
int replace_case = 0;
int replace_backwards = 0;
/* queries on a save */
#ifdef MIDNIGHT
int edit_confirm_save = 1;
#else
int edit_confirm_save = 0;
#endif
#define NUM_REPL_ARGS 16
#define MAX_REPL_LEN 1024
#ifdef MIDNIGHT
static inline int my_lower_case (int c)
{
return tolower(c);
}
char *strcasechr (const char *s, int c)
{
for (; my_lower_case ((int) *s) != my_lower_case (c); ++s)
if (*s == '\0')
return 0;
return (char *)s;
}
#include "../src/mad.h"
#ifndef HAVE_MEMMOVE
/* for Christophe */
static void *memmove (void *dest, const void *src, size_t n)
{
char *t, *s;
if (dest <= src) {
t = (char *) dest;
s = (char *) src;
while (n--)
*t++ = *s++;
} else {
t = (char *) dest + n;
s = (char *) src + n;
while (n--)
*--t = *--s;
}
return dest;
}
#endif
/* #define itoa MY_itoa <---- this line is now in edit.h */
char *itoa (int i)
{
static char t[14];
char *s = t + 13;
int j = i;
*s-- = 0;
do {
*s-- = i % 10 + '0';
} while ((i = i / 10));
if (j < 0)
*s-- = '-';
return ++s;
}
/*
This joins strings end on end and allocates memory for the result.
The result is later automatically free'd and must not be free'd
by the caller.
*/
char *catstrs (const char *first,...)
{
static char *stacked[16] =
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static int i = 0;
va_list ap;
int len;
char *data;
if (!first)
return 0;
len = strlen (first);
va_start (ap, first);
while ((data = va_arg (ap, char *)) != 0)
len += strlen (data);
len++;
i = (i + 1) % 16;
if (stacked[i])
free (stacked[i]);
stacked[i] = malloc (len);
va_end (ap);
va_start (ap, first);
strcpy (stacked[i], first);
while ((data = va_arg (ap, char *)) != 0)
strcat (stacked[i], data);
va_end (ap);
return stacked[i];
}
#endif
#ifdef MIDNIGHT
void edit_help_cmd (WEdit * edit)
{
char *hlpdir = concat_dir_and_file (mc_home, "mc.hlp");
interactive_display (hlpdir, "[Internal File Editor]");
free (hlpdir);
edit->force |= REDRAW_COMPLETELY;
}
void edit_refresh_cmd (WEdit * edit)
{
#ifndef HAVE_SLANG
clr_scr();
do_refresh();
#else
{
int fg, bg;
edit_get_syntax_color (edit, -1, &fg, &bg);
}
touchwin(stdscr);
#endif
mc_refresh();
doupdate();
}
#else
void edit_help_cmd (WEdit * edit)
{
}
void edit_refresh_cmd (WEdit * edit)
{
}
void CRefreshEditor (WEdit * edit)
{
edit_refresh_cmd (edit);
}
#endif
#ifndef MIDNIGHT
/* three argument open */
int my_open (const char *pathname, int flags,...)
{
int file;
va_list ap;
file = open ((char *) pathname, O_RDONLY);
if (file < 0 && (flags & O_CREAT)) { /* must it be created ? */
mode_t mode;
va_start(ap, flags);
mode = va_arg(ap, mode_t);
va_end(ap);
return creat ((char *) pathname, mode);
}
close (file);
return open ((char *) pathname, flags);
}
#define open my_open
#endif
/* "Oleg Yu. Repin" <repin@ssd.sscc.ru> added backup filenames
...thanks -paul */
/* If 0 (quick save) then a) create/truncate <filename> file,
b) save to <filename>;
if 1 (safe save) then a) save to <tempnam>,
b) rename <tempnam> to <filename>;
if 2 (do backups) then a) save to <tempnam>,
b) rename <filename> to <filename.backup_ext>,
c) rename <tempnam> to <filename>. */
/* returns 0 on error */
int edit_save_file (WEdit * edit, const char *filename)
{
long buf;
long filelen = 0;
int file;
char *savename = (char *) filename;
int this_save_mode;
if ((file = open (savename, O_WRONLY)) == -1) {
this_save_mode = 0; /* the file does not exists yet, so no safe save or backup necessary */
} else {
close (file);
this_save_mode = option_save_mode;
}
if (this_save_mode > 0) {
char *savedir = ".", *slashpos = strrchr (filename, '/');
if (slashpos != 0) {
savedir = strdup (filename);
if (savedir == 0)
return 0;
savedir[slashpos - filename + 1] = '\0';
}
#ifdef HAVE_MAD
savename = strdup (tempnam (savedir, "cooledit"));
#else
savename = tempnam (savedir, "cooledit");
#endif
if (slashpos)
free (savedir);
if (!savename)
return 0;
}
if ((file = open (savename, O_CREAT | O_WRONLY | O_TRUNC | MY_O_TEXT, edit->stat.st_mode)) == -1) {
if (this_save_mode > 0)
free (savename);
return 0;
}
chown (savename, edit->stat.st_uid, edit->stat.st_gid);
buf = 0;
while (buf <= (edit->curs1 >> S_EDIT_BUF_SIZE) - 1) {
filelen += write (file, (char *) edit->buffers1[buf], EDIT_BUF_SIZE);
buf++;
}
filelen += write (file, (char *) edit->buffers1[buf], edit->curs1 & M_EDIT_BUF_SIZE);
if (edit->curs2) {
edit->curs2--;
buf = (edit->curs2 >> S_EDIT_BUF_SIZE);
filelen += write (file, (char *) edit->buffers2[buf] + EDIT_BUF_SIZE - (edit->curs2 & M_EDIT_BUF_SIZE) - 1, 1 + (edit->curs2 & M_EDIT_BUF_SIZE));
buf--;
while (buf >= 0) {
filelen += write (file, (char *) edit->buffers2[buf], EDIT_BUF_SIZE);
buf--;
}
edit->curs2++;
}
close (file);
if (filelen == edit->last_byte) {
if (this_save_mode == 2) {
if (rename (filename, catstrs (filename, option_backup_ext, 0)) == -1) { /* catstrs free's automatically */
free (savename);
return 0;
}
}
if (this_save_mode > 0) {
if (rename (savename, filename) == -1) {
free (savename);
return 0;
}
free (savename);
}
return 1;
} else {
if (this_save_mode > 0)
free (savename);
return 0;
}
}
#ifdef MIDNIGHT
/*
I changed this from Oleg's original routine so
that option_backup_ext works with coolwidgets as well. This
does mean there is a memory leak - paul.
*/
void menu_save_mode_cmd (void)
{
#define DLG_X 36
#define DLG_Y 10
static char *str_result;
static int save_mode_new;
static char *str[] =
{
"Quick save ",
"Safe save ",
"Do backups -->"};
static QuickWidget widgets[] =
{
{quick_button, 18, DLG_X, 7, DLG_Y, "&Cancel", 0,
B_CANCEL, 0, 0, XV_WLAY_DONTCARE, "c"},
{quick_button, 6, DLG_X, 7, DLG_Y, "&Ok", 0,
B_ENTER, 0, 0, XV_WLAY_DONTCARE, "o"},
{quick_input, 23, DLG_X, 5, DLG_Y, 0, 9,
0, 0, &str_result, XV_WLAY_DONTCARE, "i"},
{quick_label, 22, DLG_X, 4, DLG_Y, "Extension:", 0,
0, 0, 0, XV_WLAY_DONTCARE, "savemext"},
{quick_radio, 4, DLG_X, 3, DLG_Y, "", 3,
0, &save_mode_new, str, XV_WLAY_DONTCARE, "t"},
{0}};
static QuickDialog dialog =
/* NLS ? */
{DLG_X, DLG_Y, -1, -1, " Edit Save Mode ", "[Edit Save Mode]",
"esm", widgets};
widgets[2].text = option_backup_ext;
widgets[4].value = option_save_mode;
if (quick_dialog (&dialog) != B_ENTER)
return;
option_save_mode = save_mode_new;
option_backup_ext = str_result; /* this is a memory leak */
option_backup_ext_int = 0;
str_result[min (strlen (str_result), sizeof (int))] = '\0';
memcpy ((char *) &option_backup_ext_int, str_result, strlen (option_backup_ext));
}
#endif
#ifdef MIDNIGHT
void edit_split_filename (WEdit * edit, char *f)
{
if (edit->filename)
free (edit->filename);
edit->filename = strdup (f);
if (edit->dir)
free (edit->dir);
edit->dir = strdup ("");
}
#else
void edit_split_filename (WEdit * edit, char *longname)
{
char *exp, *p;
exp = canonicalize_pathname (longname); /* this ensures a full path */
if (edit->filename)
free (edit->filename);
if (edit->dir)
free (edit->dir);
p = strrchr (exp, '/');
edit->filename = strdup (++p);
*p = 0;
edit->dir = strdup (exp);
free (exp);
}
#endif
/* here we want to warn the user of overwriting an existing file, but only if they
have made a change to the filename */
/* returns 1 on success */
int edit_save_as_cmd (WEdit * edit)
{
/* This heads the 'Save As' dialog box */
char *exp = edit_get_save_file (edit->dir, edit->filename, _(" Save As "));
int different_filename = 0;
edit_push_action (edit, KEY_PRESS + edit->start_display);
edit->force |= REDRAW_COMPLETELY;
if (exp) {
if (!*exp) {
free (exp);
return 0;
} else {
if (strcmp(catstrs (edit->dir, edit->filename, 0), exp)) {
int file;
different_filename = 1;
if ((file = open ((char *) exp, O_RDONLY)) != -1) { /* the file exists */
close (file);
if (edit_query_dialog2 (_(" Warning "),
_(" A file already exists with this name. "),
/* Push buttons to over-write the current file, or cancel the operation */
_("Overwrite"), _("Cancel")))
return 0;
}
}
if (edit_save_file (edit, exp)) {
edit_split_filename (edit, exp);
free (exp);
edit->modified = 0;
#ifdef MIDNIGHT
edit->delete_file = 0;
#endif
if (different_filename && !edit->explicit_syntax)
edit_load_syntax (edit, 0, 0);
return 1;
} else {
free (exp);
edit_error_dialog (_(" Save as "), get_sys_error (_(" Error trying to save file. ")));
return 0;
}
}
} else
return 0;
}
/* {{{ Macro stuff starts here */
#ifdef MIDNIGHT
int raw_callback (struct Dlg_head *h, int key, int Msg)
{
switch (Msg) {
case DLG_DRAW:
attrset (REVERSE_COLOR);
dlg_erase (h);
draw_box (h, 1, 1, h->lines - 2, h->cols - 2);
attrset (COLOR_HOT_NORMAL);
dlg_move (h, 1, 2);
printw (h->title);
break;
case DLG_KEY:
h->running = 0;
h->ret_value = key;
return 1;
}
return 0;
}
/* gets a raw key from the keyboard. Passing cancel = 1 draws
a cancel button thus allowing c-c etc.. Alternatively, cancel = 0
will return the next key pressed */
int edit_raw_key_query (char *heading, char *query, int cancel)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -