📄 editcmd.c
字号:
/* editor high level editing commands. Copyright (C) 1996-2000 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.*//* #define PIPE_BLOCKS_SO_READ_BYTE_BY_BYTE */#include <config.h>#ifdef NEEDS_IO_H#include <io.h>#include <fcntl.h>#endif#include <ctype.h>#include "edit.h"#include "editcmddef.h"#ifndef MIDNIGHT#include <X11/Xatom.h>#ifndef GTK#include "loadfile.h"#endif#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;int search_create_bookmark = 0;/* queries on a save */#ifdef MIDNIGHTint edit_confirm_save = 1;#elseint edit_confirm_save = 0;#endif#define NUM_REPL_ARGS 64#define MAX_REPL_LEN 1024#if defined(MIDNIGHT) || defined(GTK)static inline int my_lower_case (int c){ return tolower(c & 0xFF);}char *strcasechr (const unsigned char *s, int c){ for (; my_lower_case ((int) *s) != my_lower_case (c); ++s) if (*s == '\0') return 0; return (char *) s;}#ifdef MIDNIGHT#include "../src/mad.h"#elif !defined (GTK)#include "mad.h"#endif#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 MIDNIGHTvoid 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();}#elsevoid edit_help_cmd (WEdit * edit){}void edit_refresh_cmd (WEdit * edit){ int fg, bg; edit_get_syntax_color (edit, -1, &fg, &bg); edit->force |= REDRAW_COMPLETELY;}void CRefreshEditor (WEdit * edit){ edit_refresh_cmd (edit);}#endif#ifndef MIDNIGHT#ifndef GTK/* 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#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){ char *p; long filelen = 0; FILE *file; char *savename = 0; int this_save_mode, fd; if (!filename) return 0; if (!*filename) return 0; savename = (char *) strdup ((char *) filename); if ((fd = open (savename, O_WRONLY)) == -1) { this_save_mode = 0; /* the file does not exists yet, so no safe save or backup necessary */ } else { close (fd); this_save_mode = option_save_mode; } if (this_save_mode > 0) { char *savedir, *slashpos; savedir = (char *) strdup ("."); slashpos = strrchr (filename, '/'); if (slashpos) { free (savedir); savedir = (char *) strdup (filename); savedir[slashpos - filename + 1] = '\0'; } if (savename) free (savename); savename = (char *) tempnam (savedir, "cooledit"); free (savedir); if (!savename) goto error_save; } if ((file = fopen (savename, "w+")) == 0) goto error_save; chmod (savename, edit->stat.st_mode); chown (savename, edit->stat.st_uid, edit->stat.st_gid);/* pipe save */ if ((p = (char *) edit_get_write_filter (savename, filename))) { fclose (file); file = (FILE *) popen (p, "w"); if (file) { filelen = edit_write_stream (edit, file);#if 1 pclose (file);#else if (pclose (file) > 0) { edit_error_dialog (_ (" Error "), catstrs (_ (" Error writing to pipe: "), p, " ", 0)); free (p); goto error_save; }#endif } else { edit_error_dialog (_ (" Error "), get_sys_error (catstrs (_ (" Failed trying to open pipe for writing: "), p, " ", 0))); free (p); goto error_save; } free (p);#ifdef CR_LF_TRANSLATION } else { /* optimised save */ filelen = edit_write_stream (edit, f); fclose (file);#else } else { long buf; buf = 0; filelen = edit->last_byte; while (buf <= (edit->curs1 >> S_EDIT_BUF_SIZE) - 1) { if (fwrite ((char *) edit->buffers1[buf], EDIT_BUF_SIZE, 1, file) != 1) { filelen = -1; break; } buf++; } if (fwrite ((char *) edit->buffers1[buf], edit->curs1 & M_EDIT_BUF_SIZE, 1, file) == -1) { filelen = -1; } else if (edit->curs2) { edit->curs2--; buf = (edit->curs2 >> S_EDIT_BUF_SIZE); if (fwrite ((char *) edit->buffers2[buf] + EDIT_BUF_SIZE - (edit->curs2 & M_EDIT_BUF_SIZE) - 1, 1 + (edit->curs2 & M_EDIT_BUF_SIZE), 1, file) != 1) { filelen = -1; } else { buf--; while (buf >= 0) { if (fwrite ((char *) edit->buffers2[buf], EDIT_BUF_SIZE, 1, file) != 1) { filelen = -1; break; } buf--; } } edit->curs2++; } fclose (file);#endif } if (filelen != edit->last_byte) goto error_save; if (this_save_mode == 2) if (rename (filename, catstrs (filename, option_backup_ext, 0)) == -1) goto error_save; if (this_save_mode > 0) if (rename (savename, filename) == -1) goto error_save; if (savename) free (savename); return 1; error_save: if (savename) 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 38#define DLG_Y 10 static char *str_result; static int save_mode_new; static char *str[] = { N_("Quick save "), N_("Safe save "), N_("Do backups -->")}; static QuickWidget widgets[] = { {quick_button, 18, DLG_X, 7, DLG_Y, N_("&Cancel"), 0, B_CANCEL, 0, 0, XV_WLAY_DONTCARE, "c"}, {quick_button, 6, DLG_X, 7, DLG_Y, N_("&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, N_("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, N_(" Edit Save Mode "), "[Edit Save Mode]", "esm", widgets}; static int i18n_flag = 0; if (!i18n_flag) { int i; for (i = 0; i < 3; i++ ) str[i] = _(str[i]); i18n_flag = 1; } 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 MIDNIGHTvoid edit_split_filename (WEdit * edit, char *f){ if (edit->filename) free (edit->filename); edit->filename = (char *) strdup (f); if (edit->dir) free (edit->dir); edit->dir = (char *) strdup ("");}#else#ifdef GTKstatic char cwd[1040];static char *canonicalize_pathname (char *p){ char *q, *r; if (*p != '/') { if (strlen (cwd) == 0) {#ifdef HAVE_GETCWD getcwd (cwd, MAX_PATH_LEN);#else getwd (cwd);#endif } r = malloc (strlen (cwd) + strlen (p) + 2); strcpy (r, cwd); strcat (r, "/"); strcat (r, p); p = r; } r = q = malloc (strlen (p) + 2); for (;;) { if (!*p) { *q = '\0'; break; } if (*p != '/') { *q++ = *p++; } else { while (*p == '/') { *q = '/'; if (!strncmp (p, "/./", 3) || !strcmp (p, "/.")) p++; else if (!strncmp (p, "/../", 4) || !strcmp (p, "/..")) { p += 2; *q = ' '; q = strrchr (r, '/'); if (!q) { q = r; *q = '/'; } } p++; } q++; } }/* get rid of trailing / */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -