From 2535f51e01cfb8b3a27f5e789feadf73cda65939 Mon Sep 17 00:00:00 2001 From: Benno Schulenberg Date: Sat, 30 Apr 2016 17:31:43 +0200 Subject: [PATCH] statusbar: prevent error messages from overwriting each other If during startup there are multiple error messages, currently only the last one remains and can be read. To improve on that, introduce a short pause between error messages -- even if it's not enough to read them all, at least the user will be aware that there are multiple ones. This also causes a few error messages to beep that currently don't beep, such as when a file is unwritable. --- src/browser.c | 25 ++++----- src/color.c | 6 +- src/files.c | 150 +++++++++++++++++++++++++------------------------- src/global.c | 2 + src/help.c | 2 + src/nano.c | 13 +++-- src/nano.h | 4 ++ src/proto.h | 4 +- src/search.c | 6 +- src/text.c | 51 ++++++++++------- src/utils.c | 2 +- src/winio.c | 27 +++++++-- 12 files changed, 164 insertions(+), 128 deletions(-) diff --git a/src/browser.c b/src/browser.c index 1dbdd9d7..48cc4ff2 100644 --- a/src/browser.c +++ b/src/browser.c @@ -107,6 +107,7 @@ char *do_browser(char *path, DIR *dir) /* Make sure that the cursor is off. */ curs_set(0); + alerted = FALSE; #ifndef NANO_TINY if (kbinput == KEY_WINCH) { @@ -118,8 +119,7 @@ char *do_browser(char *path, DIR *dir) if (dir != NULL) goto read_directory_contents; - statusbar(_("Error reading %s: %s"), path, strerror(errno)); - beep(); + statusline(ALERT, _("Error reading %s: %s"), path, strerror(errno)); kbinput = ERR; } #endif @@ -243,8 +243,8 @@ char *do_browser(char *path, DIR *dir) if (check_operating_dir(new_path, FALSE)) { /* TRANSLATORS: This refers to the option --operatingdir, * not to --restricted. */ - statusbar(_("Can't go outside of %s in confined mode"), - operating_dir); + statusline(ALERT, _("Can't go outside of %s " + "in confined mode"), operating_dir); free(new_path); continue; } @@ -253,9 +253,8 @@ char *do_browser(char *path, DIR *dir) dir = opendir(new_path); if (dir == NULL) { /* We can't open this directory for some reason. */ - statusbar(_("Error reading %s: %s"), answer, + statusline(ALERT, _("Error reading %s: %s"), answer, strerror(errno)); - beep(); free(new_path); continue; } @@ -285,8 +284,7 @@ char *do_browser(char *path, DIR *dir) } else if (func == do_enter) { /* We can't move up from "/". */ if (strcmp(filelist[selected], "/..") == 0) { - statusbar(_("Can't move up a directory")); - beep(); + statusline(ALERT, _("Can't move up a directory")); continue; } @@ -295,9 +293,8 @@ char *do_browser(char *path, DIR *dir) * directory if it's ".." or if it's a symlink to a * directory outside the operating directory. */ if (check_operating_dir(filelist[selected], FALSE)) { - statusbar(_("Can't go outside of %s in confined mode"), - operating_dir); - beep(); + statusline(ALERT, _("Can't go outside of %s " + "in confined mode"), operating_dir); continue; } #endif @@ -305,9 +302,8 @@ char *do_browser(char *path, DIR *dir) if (stat(filelist[selected], &st) == -1) { /* We can't open this file for some reason. * Complain. */ - statusbar(_("Error reading %s: %s"), + statusline(ALERT, _("Error reading %s: %s"), filelist[selected], strerror(errno)); - beep(); continue; } @@ -321,9 +317,8 @@ char *do_browser(char *path, DIR *dir) dir = opendir(filelist[selected]); if (dir == NULL) { - statusbar(_("Error reading %s: %s"), + statusline(ALERT, _("Error reading %s: %s"), filelist[selected], strerror(errno)); - beep(); continue; } diff --git a/src/color.c b/src/color.c index 8b173d72..3362b568 100644 --- a/src/color.c +++ b/src/color.c @@ -183,7 +183,7 @@ void color_update(void) } if (sint == NULL) - statusbar(_("Unknown syntax name: %s"), syntaxstr); + statusline(ALERT, _("Unknown syntax name: %s"), syntaxstr); } /* If no syntax-override string was specified, or it didn't match, @@ -241,11 +241,11 @@ void color_update(void) #endif MAGIC_ERROR); if (cookie == NULL || magic_load(cookie, NULL) < 0) - statusbar(_("magic_load() failed: %s"), strerror(errno)); + statusline(ALERT, _("magic_load() failed: %s"), strerror(errno)); else { magicstring = magic_file(cookie, openfile->filename); if (magicstring == NULL) - statusbar(_("magic_file(%s) failed: %s"), + statusline(ALERT, _("magic_file(%s) failed: %s"), openfile->filename, magic_error(cookie)); #ifdef DEBUG fprintf(stderr, "Returned magic string is: %s\n", magicstring); diff --git a/src/files.c b/src/files.c index 4cc8239e..bf54e056 100644 --- a/src/files.c +++ b/src/files.c @@ -44,21 +44,18 @@ bool has_valid_path(const char *filename) if (stat(parentdir, &parentinfo) == -1) { if (errno == ENOENT) - statusbar(_("Directory '%s' does not exist"), parentdir); + statusline(ALERT, _("Directory '%s' does not exist"), parentdir); else - statusbar(_("Path '%s': %s"), parentdir, strerror(errno)); + statusline(ALERT, _("Path '%s': %s"), parentdir, strerror(errno)); } else if (!S_ISDIR(parentinfo.st_mode)) - statusbar(_("Path '%s' is not a directory"), parentdir); + statusline(ALERT, _("Path '%s' is not a directory"), parentdir); else if (access(parentdir, X_OK) == -1) - statusbar(_("Path '%s' is not accessible"), parentdir); + statusline(ALERT, _("Path '%s' is not accessible"), parentdir); else validity = TRUE; free(namecopy); - if (!validity) - beep(); - return validity; } @@ -196,7 +193,8 @@ int write_lockfile(const char *lockfilename, const char *origfilename, bool modi if (errno == ENAMETOOLONG) myhostname[31] = '\0'; else { - statusbar(_("Couldn't determine hostname for lock file: %s"), strerror(errno)); + statusline(HUSH, _("Couldn't determine hostname for lock file: %s"), + strerror(errno)); goto free_and_fail; } } @@ -217,8 +215,8 @@ int write_lockfile(const char *lockfilename, const char *origfilename, bool modi /* Maybe we just don't have write access. Print an error message * and continue. */ if (fd < 0) { - statusbar(_("Error writing lock file %s: %s"), lockfilename, - strerror(errno)); + statusline(HUSH, _("Error writing lock file %s: %s"), + lockfilename, strerror(errno)); free(lockdata); return 0; } @@ -228,7 +226,7 @@ int write_lockfile(const char *lockfilename, const char *origfilename, bool modi filestream = fdopen(fd, "wb"); if (fd < 0 || filestream == NULL) { - statusbar(_("Error writing lock file %s: %s"), lockfilename, + statusline(HUSH, _("Error writing lock file %s: %s"), lockfilename, strerror(errno)); goto free_and_fail; } @@ -265,7 +263,7 @@ int write_lockfile(const char *lockfilename, const char *origfilename, bool modi wroteamt = fwrite(lockdata, sizeof(char), lockdatalen, filestream); if (wroteamt < lockdatalen) { - statusbar(_("Error writing lock file %s: %s"), + statusline(HUSH, _("Error writing lock file %s: %s"), lockfilename, ferror(filestream)); goto free_and_fail; } @@ -275,7 +273,7 @@ int write_lockfile(const char *lockfilename, const char *origfilename, bool modi #endif if (fclose(filestream) == EOF) { - statusbar(_("Error writing lock file %s: %s"), + statusline(HUSH, _("Error writing lock file %s: %s"), lockfilename, strerror(errno)); goto free_and_fail; } @@ -295,7 +293,7 @@ int write_lockfile(const char *lockfilename, const char *origfilename, bool modi int delete_lockfile(const char *lockfilename) { if (unlink(lockfilename) < 0 && errno != ENOENT) { - statusbar(_("Error deleting lock file %s: %s"), lockfilename, + statusline(HUSH, _("Error deleting lock file %s: %s"), lockfilename, strerror(errno)); return -1; } @@ -330,7 +328,7 @@ int do_lockfile(const char *filename) int room, ans; if ((lockfd = open(lockfilename, O_RDONLY)) < 0) { - statusbar(_("Error opening lock file %s: %s"), + statusline(HUSH, _("Error opening lock file %s: %s"), lockfilename, strerror(errno)); goto free_the_name; } @@ -342,8 +340,8 @@ int do_lockfile(const char *filename) } while (readamt > 0 && readtot < LOCKBUFSIZE); if (readtot < 48) { - statusbar(_("Error reading lock file %s: Not enough data read"), - lockfilename); + statusline(HUSH, _("Error reading lock file %s: " + "Not enough data read"), lockfilename); free(lockbuf); goto free_the_name; } @@ -427,8 +425,8 @@ bool open_buffer(const char *filename, bool undoable) #ifndef DISABLE_OPERATINGDIR if (check_operating_dir(filename, FALSE)) { - statusbar(_("Can't insert file from outside of %s"), - operating_dir); + statusline(ALERT, _("Can't insert file from outside of %s"), + operating_dir); return FALSE; } #endif @@ -442,10 +440,9 @@ bool open_buffer(const char *filename, bool undoable) if (stat(realname, &fileinfo) == 0 && !S_ISREG(fileinfo.st_mode)) { if (S_ISDIR(fileinfo.st_mode)) - statusbar(_("\"%s\" is a directory"), realname); + statusline(ALERT, _("\"%s\" is a directory"), realname); else - statusbar(_("\"%s\" is not a normal file"), realname); - beep(); + statusline(ALERT, _("\"%s\" is not a normal file"), realname); free(realname); return FALSE; } @@ -591,7 +588,7 @@ void switch_to_prevnext_buffer(bool to_next, bool quiet) /* Indicate the switch on the statusbar. */ if (!quiet) - statusbar(_("Switched to %s"), + statusline(HUSH, _("Switched to %s"), ((openfile->filename[0] == '\0') ? _("New Buffer") : openfile->filename)); @@ -916,41 +913,48 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable, bool checkw if (format == 3) { if (writable) - statusbar(P_("Read %lu line (Converted from DOS and Mac format)", + statusline(HUSH, + P_("Read %lu line (Converted from DOS and Mac format)", "Read %lu lines (Converted from DOS and Mac format)", (unsigned long)num_lines), (unsigned long)num_lines); else /* TRANSLATORS: Keep the next handful of messages at most 76 characters long. */ - statusbar(P_("Read %lu line (Converted from DOS and Mac format - NO write permission)", + statusline(ALERT, + P_("Read %lu line (Converted from DOS and Mac format - NO write permission)", "Read %lu lines (Converted from DOS and Mac format - NO write permission)", (unsigned long)num_lines), (unsigned long)num_lines); } else if (format == 2) { openfile->fmt = MAC_FILE; if (writable) - statusbar(P_("Read %lu line (Converted from Mac format)", + statusline(HUSH, + P_("Read %lu line (Converted from Mac format)", "Read %lu lines (Converted from Mac format)", (unsigned long)num_lines), (unsigned long)num_lines); else - statusbar(P_("Read %lu line (Converted from Mac format - Warning: No write permission)", + statusline(ALERT, + P_("Read %lu line (Converted from Mac format - Warning: No write permission)", "Read %lu lines (Converted from Mac format - Warning: No write permission)", (unsigned long)num_lines), (unsigned long)num_lines); } else if (format == 1) { openfile->fmt = DOS_FILE; if (writable) - statusbar(P_("Read %lu line (Converted from DOS format)", + statusline(HUSH, + P_("Read %lu line (Converted from DOS format)", "Read %lu lines (Converted from DOS format)", (unsigned long)num_lines), (unsigned long)num_lines); else - statusbar(P_("Read %lu line (Converted from DOS format - Warning: No write permission)", + statusline(ALERT, + P_("Read %lu line (Converted from DOS format - Warning: No write permission)", "Read %lu lines (Converted from DOS format - Warning: No write permission)", (unsigned long)num_lines), (unsigned long)num_lines); } else #endif if (writable) - statusbar(P_("Read %lu line", "Read %lu lines", + statusline(HUSH, P_("Read %lu line", "Read %lu lines", (unsigned long)num_lines), (unsigned long)num_lines); else - statusbar(P_("Read %lu line (Warning: No write permission)", + statusline(ALERT, + P_("Read %lu line (Warning: No write permission)", "Read %lu lines (Warning: No write permission)", (unsigned long)num_lines), (unsigned long)num_lines); @@ -1004,8 +1008,7 @@ int open_file(const char *filename, bool newfie, bool quiet, FILE **f) statusbar(_("New File")); return -2; } - statusbar(_("File \"%s\" not found"), filename); - beep(); + statusline(ALERT, _("File \"%s\" not found"), filename); return -1; } else if (S_ISDIR(fileinfo.st_mode) || S_ISCHR(fileinfo.st_mode) || S_ISBLK(fileinfo.st_mode)) { @@ -1013,23 +1016,20 @@ int open_file(const char *filename, bool newfie, bool quiet, FILE **f) /* Don't open directories, character files, or block files. * Sorry, /dev/sndstat! */ - statusbar(S_ISDIR(fileinfo.st_mode) ? + statusline(ALERT, S_ISDIR(fileinfo.st_mode) ? _("\"%s\" is a directory") : _("\"%s\" is a device file"), filename); - beep(); return -1; } else if ((fd = open(full_filename, O_RDONLY)) == -1) { free(full_filename); - statusbar(_("Error reading %s: %s"), filename, strerror(errno)); - beep(); + statusline(ALERT, _("Error reading %s: %s"), filename, strerror(errno)); return -1; } else { /* The file is A-OK. Open it. */ *f = fdopen(fd, "rb"); if (*f == NULL) { - statusbar(_("Error reading %s: %s"), filename, strerror(errno)); - beep(); + statusline(ALERT, _("Error reading %s: %s"), filename, strerror(errno)); close(fd); } else statusbar(_("Reading File")); @@ -1781,7 +1781,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type /* If we're writing a temporary file, we're probably going outside * the operating directory, so skip the operating directory test. */ if (!tmp && check_operating_dir(realname, FALSE)) { - statusbar(_("Can't write outside of %s"), operating_dir); + statusline(ALERT, _("Can't write outside of %s"), operating_dir); goto cleanup_and_exit; } #endif @@ -1825,9 +1825,8 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type f = fopen(realname, "rb"); if (f == NULL) { - statusbar(_("Error reading %s: %s"), realname, + statusline(ALERT, _("Error reading %s: %s"), realname, strerror(errno)); - beep(); /* If we can't read from the original file, go on, since * only saving the original file is better than saving * nothing. */ @@ -1865,8 +1864,8 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type free(backuptemp); backuptemp = get_next_filename(backupname, "~"); if (*backuptemp == '\0') { - statusbar(_("Error writing backup file %s: %s"), backupname, - _("Too many backup files?")); + statusline(HUSH, _("Error writing backup file %s: %s"), + backupname, _("Too many backup files?")); free(backuptemp); free(backupname); /* If we can't write to the backup, DON'T go on, since @@ -1890,8 +1889,8 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type if (unlink(backupname) < 0 && errno != ENOENT && !ISSET(INSECURE_BACKUP)) { if (prompt_failed_backupwrite(backupname)) goto skip_backup; - statusbar(_("Error writing backup file %s: %s"), backupname, - strerror(errno)); + statusline(HUSH, _("Error writing backup file %s: %s"), + backupname, strerror(errno)); free(backupname); goto cleanup_and_exit; } @@ -1908,8 +1907,8 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type backup_file = fdopen(backup_fd, "wb"); if (backup_fd < 0 || backup_file == NULL) { - statusbar(_("Error writing backup file %s: %s"), backupname, - strerror(errno)); + statusline(HUSH, _("Error writing backup file %s: %s"), + backupname, strerror(errno)); free(backupname); goto cleanup_and_exit; } @@ -1921,8 +1920,8 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type && !ISSET(INSECURE_BACKUP)) { if (prompt_failed_backupwrite(backupname)) goto skip_backup; - statusbar(_("Error writing backup file %s: %s"), backupname, - strerror(errno)); + statusline(HUSH, _("Error writing backup file %s: %s"), + backupname, strerror(errno)); free(backupname); fclose(backup_file); goto cleanup_and_exit; @@ -1932,8 +1931,8 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type && !ISSET(INSECURE_BACKUP)) { if (prompt_failed_backupwrite(backupname)) goto skip_backup; - statusbar(_("Error writing backup file %s: %s"), backupname, - strerror(errno)); + statusline(HUSH, _("Error writing backup file %s: %s"), + backupname, strerror(errno)); free(backupname); fclose(backup_file); /* If we can't write to the backup, DONT go on, since @@ -1951,9 +1950,8 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type copy_status = copy_file(f, backup_file); if (copy_status != 0) { - statusbar(_("Error reading %s: %s"), realname, + statusline(ALERT, _("Error reading %s: %s"), realname, strerror(errno)); - beep(); goto cleanup_and_exit; } @@ -1961,8 +1959,8 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type if (utime(backupname, &filetime) == -1 && !ISSET(INSECURE_BACKUP)) { if (prompt_failed_backupwrite(backupname)) goto skip_backup; - statusbar(_("Error writing backup file %s: %s"), backupname, - strerror(errno)); + statusline(HUSH, _("Error writing backup file %s: %s"), + backupname, strerror(errno)); /* If we can't write to the backup, DON'T go on, since * whatever caused the backup file to fail (e.g. disk full * may well cause the real file write to fail, which means @@ -1996,9 +1994,8 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type f = fopen(realname, "rb"); if (f == NULL) { - statusbar(_("Error reading %s: %s"), realname, + statusline(ALERT, _("Error reading %s: %s"), realname, strerror(errno)); - beep(); goto cleanup_and_exit; } } @@ -2006,7 +2003,8 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type tempname = safe_tempfile(&f); if (tempname == NULL) { - statusbar(_("Error writing temp file: %s"), strerror(errno)); + statusline(HUSH, _("Error writing temp file: %s"), + strerror(errno)); goto cleanup_and_exit; } @@ -2016,9 +2014,8 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type if (fd_source != -1) { f_source = fdopen(fd_source, "rb"); if (f_source == NULL) { - statusbar(_("Error reading %s: %s"), realname, + statusline(ALERT, _("Error reading %s: %s"), realname, strerror(errno)); - beep(); close(fd_source); fclose(f); unlink(tempname); @@ -2028,7 +2025,8 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type } if (f_source == NULL || copy_file(f_source, f) != 0) { - statusbar(_("Error writing %s: %s"), tempname, strerror(errno)); + statusline(HUSH, _("Error writing %s: %s"), tempname, + strerror(errno)); unlink(tempname); goto cleanup_and_exit; } @@ -2046,7 +2044,8 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type /* If we couldn't open the file, give up. */ if (fd == -1) { - statusbar(_("Error writing %s: %s"), realname, strerror(errno)); + statusline(HUSH, _("Error writing %s: %s"), realname, + strerror(errno)); if (tempname != NULL) unlink(tempname); goto cleanup_and_exit; @@ -2055,7 +2054,8 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type f = fdopen(fd, (append == APPEND) ? "ab" : "wb"); if (f == NULL) { - statusbar(_("Error writing %s: %s"), realname, strerror(errno)); + statusline(HUSH, _("Error writing %s: %s"), realname, + strerror(errno)); close(fd); goto cleanup_and_exit; } @@ -2078,7 +2078,8 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type unsunder(fileptr->data, data_len); if (size < data_len) { - statusbar(_("Error writing %s: %s"), realname, strerror(errno)); + statusline(HUSH, _("Error writing %s: %s"), realname, + strerror(errno)); fclose(f); goto cleanup_and_exit; } @@ -2094,7 +2095,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type #ifndef NANO_TINY if (openfile->fmt == DOS_FILE || openfile->fmt == MAC_FILE) { if (putc('\r', f) == EOF) { - statusbar(_("Error writing %s: %s"), realname, + statusline(HUSH, _("Error writing %s: %s"), realname, strerror(errno)); fclose(f); goto cleanup_and_exit; @@ -2104,7 +2105,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type if (openfile->fmt != MAC_FILE) #endif if (putc('\n', f) == EOF) { - statusbar(_("Error writing %s: %s"), realname, + statusline(HUSH, _("Error writing %s: %s"), realname, strerror(errno)); fclose(f); goto cleanup_and_exit; @@ -2129,20 +2130,22 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type } if (f_source == NULL) { - statusbar(_("Error reading %s: %s"), tempname, strerror(errno)); - beep(); + statusline(ALERT, _("Error reading %s: %s"), tempname, + strerror(errno)); fclose(f); goto cleanup_and_exit; } if (copy_file(f_source, f) == -1) { - statusbar(_("Error writing %s: %s"), realname, strerror(errno)); + statusline(HUSH, _("Error writing %s: %s"), realname, + strerror(errno)); goto cleanup_and_exit; } unlink(tempname); } else if (fclose(f) != 0) { - statusbar(_("Error writing %s: %s"), realname, strerror(errno)); + statusline(HUSH, _("Error writing %s: %s"), realname, + strerror(errno)); goto cleanup_and_exit; } @@ -2169,9 +2172,8 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type stat_with_alloc(realname, &openfile->current_stat); #endif - statusbar(P_("Wrote %lu line", "Wrote %lu lines", - (unsigned long)lineswritten), - (unsigned long)lineswritten); + statusline(HUSH, P_("Wrote %lu line", "Wrote %lu lines", + (unsigned long)lineswritten), (unsigned long)lineswritten); openfile->modified = FALSE; titlebar(NULL); } diff --git a/src/global.c b/src/global.c index 243465da..7160cd27 100644 --- a/src/global.c +++ b/src/global.c @@ -39,6 +39,8 @@ bool func_key; /* Whether the current keystroke is an extended keypad value. */ bool focusing = TRUE; /* Whether an update of the edit window should center the cursor. */ +bool alerted = FALSE; + /* Whether the next important message should wait a bit. */ #ifndef NANO_TINY int controlleft = CONTROL_LEFT; diff --git a/src/help.c b/src/help.c index 28add5e5..f7df4c4b 100644 --- a/src/help.c +++ b/src/help.c @@ -118,6 +118,8 @@ void do_help(void) old_line = line; + alerted = FALSE; + kbinput = get_kbinput(edit); #ifndef NANO_TINY diff --git a/src/nano.c b/src/nano.c index a4984f01..1cb16b6b 100644 --- a/src/nano.c +++ b/src/nano.c @@ -1453,7 +1453,8 @@ void do_toggle(int flag) ) enabled = !enabled; - statusbar("%s %s", _(flagtostr(flag)), enabled ? _("enabled") : _("disabled")); + statusline(HUSH, "%s %s", _(flagtostr(flag)), + enabled ? _("enabled") : _("disabled")); } #endif /* !NANO_TINY */ @@ -1567,16 +1568,15 @@ void terminal_init(void) void unbound_key(int code) { if (func_key) - statusbar(_("Unbound key")); + statusline(ALERT, _("Unbound key")); else if (meta_key) { if (0x60 < code && code < 0x7B) code -= 0x20; - statusbar(_("Unbound key: M-%c"), code); + statusline(ALERT, _("Unbound key: M-%c"), code); } else if (code < 0x20) - statusbar(_("Unbound key: ^%c"), code + 0x40); + statusline(ALERT, _("Unbound key: ^%c"), code + 0x40); else - statusbar(_("Unbound key: %c"), code); - beep(); + statusline(ALERT, _("Unbound key: %c"), code); } /* Read in a character, interpret it as a shortcut or toggle if @@ -2657,6 +2657,7 @@ int main(int argc, char **argv) while (TRUE) { currmenu = MMAIN; focusing = TRUE; + alerted = FALSE; /* If constant cursor position display is on, and there are no * keys waiting in the input buffer, display the current cursor diff --git a/src/nano.h b/src/nano.h index 7a9e0083..71407289 100644 --- a/src/nano.h +++ b/src/nano.h @@ -56,6 +56,10 @@ /* Suppress warnings for __attribute__((warn_unused_result)). */ #define IGNORE_CALL_RESULT(call) do { if (call) {} } while(0) +/* Whether to beep when showing a statusbar message. */ +#define ALERT TRUE +#define HUSH FALSE + /* Macros for flags, indexing each bit in a small array. */ #define FLAGS(flag) flags[((flag) / (sizeof(unsigned) * 8))] #define FLAGMASK(flag) (1 << ((flag) % (sizeof(unsigned) * 8))) diff --git a/src/proto.h b/src/proto.h index 07129426..bd6169fa 100644 --- a/src/proto.h +++ b/src/proto.h @@ -33,6 +33,7 @@ extern volatile sig_atomic_t sigwinch_counter; extern bool meta_key; extern bool func_key; extern bool focusing; +extern bool alerted; #ifndef NANO_TINY extern int controlleft; @@ -786,7 +787,8 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool dollars); void titlebar(const char *path); extern void set_modified(void); -void statusbar(const char *msg, ...); +void statusbar(const char *msg); +void statusline(bool sound, const char *msg, ...); void bottombars(int menu); void onekey(const char *keystroke, const char *desc, int length); void reset_cursor(void); diff --git a/src/search.c b/src/search.c index 5f0ce167..56ad96d9 100644 --- a/src/search.c +++ b/src/search.c @@ -58,7 +58,7 @@ bool regexp_init(const char *regexp) char *str = charalloc(len); regerror(rc, &search_regexp, str, len); - statusbar(_("Bad regex \"%s\": %s"), regexp, str); + statusline(ALERT, _("Bad regex \"%s\": %s"), regexp, str); free(str); return FALSE; @@ -92,7 +92,7 @@ void not_found_msg(const char *str) disp = display_string(str, 0, (COLS / 2) + 1, FALSE); numchars = actual_x(disp, mbstrnlen(disp, COLS / 2)); - statusbar(_("\"%.*s%s\" not found"), numchars, disp, + statusline(HUSH, _("\"%.*s%s\" not found"), numchars, disp, (disp[numchars] == '\0') ? "" : "..."); free(disp); @@ -872,7 +872,7 @@ void do_replace(void) edit_refresh(); if (numreplaced >= 0) - statusbar(P_("Replaced %lu occurrence", + statusline(HUSH, P_("Replaced %lu occurrence", "Replaced %lu occurrences", (unsigned long)numreplaced), (unsigned long)numreplaced); diff --git a/src/text.c b/src/text.c index 46b34c51..a73b3844 100644 --- a/src/text.c +++ b/src/text.c @@ -563,7 +563,8 @@ void do_undo(void) break; case ENTER: if (f->next == NULL) { - statusbar(_("Internal error: line is missing. Please save your work.")); + statusline(ALERT, _("Internal error: line is missing. " + "Please save your work.")); break; } undidmsg = _("line break"); @@ -601,12 +602,13 @@ void do_undo(void) f->data = data; break; default: - statusbar(_("Internal error: unknown type. Please save your work.")); + statusline(ALERT, _("Internal error: unknown type. " + "Please save your work.")); break; } if (undidmsg) - statusbar(_("Undid action (%s)"), undidmsg); + statusline(HUSH, _("Undid action (%s)"), undidmsg); renumber(f); openfile->current_undo = openfile->current_undo->next; @@ -633,7 +635,8 @@ void do_redo(void) u = u->next; if (u->next != openfile->current_undo) { - statusbar(_("Internal error: cannot set up redo. Please save your work.")); + statusline(ALERT, _("Internal error: cannot set up redo. " + "Please save your work.")); return; } @@ -694,7 +697,8 @@ void do_redo(void) #endif case JOIN: if (f->next == NULL) { - statusbar(_("Internal error: line is missing. Please save your work.")); + statusline(ALERT, _("Internal error: line is missing. " + "Please save your work.")); break; } redidmsg = _("line join"); @@ -735,12 +739,13 @@ void do_redo(void) u->cutbuffer = NULL; break; default: - statusbar(_("Internal error: unknown type. Please save your work.")); + statusline(ALERT, _("Internal error: unknown type. " + "Please save your work.")); break; } if (redidmsg) - statusbar(_("Redid action (%s)"), redidmsg); + statusline(HUSH, _("Redid action (%s)"), redidmsg); openfile->current_undo = u; openfile->last_action = OTHER; @@ -1032,7 +1037,8 @@ void add_undo(undo_type action) case ENTER: break; default: - statusbar(_("Internal error: unknown type. Please save your work.")); + statusline(ALERT, _("Internal error: unknown type. " + "Please save your work.")); break; } @@ -1176,7 +1182,8 @@ fprintf(stderr, " >> Updating... action = %d, openfile->last_action = %d, openf /* These cases are handled by the earlier check for a new line and action. */ break; default: - statusbar(_("Internal error: unknown type. Please save your work.")); + statusline(ALERT, _("Internal error: unknown type. " + "Please save your work.")); break; } @@ -1855,7 +1862,7 @@ bool find_paragraph(size_t *const quote, size_t *const par) #ifdef HAVE_REGEX_H if (quoterc != 0) { - statusbar(_("Bad quote string %s: %s"), quotestr, quoteerr); + statusline(ALERT, _("Bad quote string %s: %s"), quotestr, quoteerr); return FALSE; } #endif @@ -2416,7 +2423,8 @@ bool do_int_spell_fix(const char *word) /* The word must exist; if not, something is wrong. */ if (result == 0) - statusbar("Internal error: speller listed unfindable word"); + statusline(ALERT, "Internal error: " + "speller listed unfindable word: %s", word); else if (result == 1) { exp_word = display_string(openfile->current->data, xplustabs(), strlenpt(word), FALSE); @@ -2855,7 +2863,7 @@ void do_spell(void) temp = safe_tempfile(&temp_file); if (temp == NULL) { - statusbar(_("Error writing temp file: %s"), strerror(errno)); + statusline(HUSH, _("Error writing temp file: %s"), strerror(errno)); return; } @@ -2867,7 +2875,7 @@ void do_spell(void) status = write_file(temp, temp_file, TRUE, OVERWRITE, FALSE); if (!status) { - statusbar(_("Error writing temp file: %s"), strerror(errno)); + statusline(HUSH, _("Error writing temp file: %s"), strerror(errno)); free(temp); return; } @@ -2889,9 +2897,9 @@ void do_spell(void) if (spell_msg != NULL) { if (errno == 0) /* Don't display an error message of "Success". */ - statusbar(_("Spell checking failed: %s"), spell_msg); + statusline(ALERT, _("Spell checking failed: %s"), spell_msg); else - statusbar(_("Spell checking failed: %s: %s"), spell_msg, + statusline(ALERT, _("Spell checking failed: %s: %s"), spell_msg, strerror(errno)); } else statusbar(_("Finished checking spelling")); @@ -3096,7 +3104,8 @@ void do_linter(void) free(read_buff); if (parsesuccess == 0) { - statusbar(_("Got 0 parsable lines from command: %s"), openfile->syntax->linter); + statusline(HUSH, _("Got 0 parsable lines from command: %s"), + openfile->syntax->linter); goto exit_from_lint; } @@ -3235,7 +3244,7 @@ void do_formatter(void) temp = safe_tempfile(&temp_file); if (temp == NULL) { - statusbar(_("Error writing temp file: %s"), strerror(errno)); + statusline(ALERT, _("Error writing temp file: %s"), strerror(errno)); return; } @@ -3244,7 +3253,7 @@ void do_formatter(void) status = write_file(temp, temp_file, TRUE, OVERWRITE, FALSE); if (!status) { - statusbar(_("Error writing temp file: %s"), strerror(errno)); + statusline(ALERT, _("Error writing temp file: %s"), strerror(errno)); free(temp); return; } @@ -3387,9 +3396,9 @@ void do_wordlinechar_count(void) openfile->placewewant = pww_save; /* Display the total word, line, and character counts on the statusbar. */ - statusbar(_("%sWords: %lu Lines: %ld Chars: %lu"), old_mark_set ? - _("In Selection: ") : "", (unsigned long)words, (long)nlines, - (unsigned long)chars); + statusline(HUSH, _("%sWords: %lu Lines: %ld Chars: %lu"), old_mark_set ? + _("In Selection: ") : "", (unsigned long)words, (long)nlines, + (unsigned long)chars); } #endif /* !NANO_TINY */ diff --git a/src/utils.c b/src/utils.c index 592fca49..5d56b1f9 100644 --- a/src/utils.c +++ b/src/utils.c @@ -624,7 +624,7 @@ filestruct *fsfromline(ssize_t lineno) f = f->next; if (f->lineno != lineno) { - statusbar(_("Internal error: can't match line %d. " + statusline(ALERT, _("Internal error: can't match line %d. " "Please save your work."), lineno); return NULL; } diff --git a/src/winio.c b/src/winio.c index 37222c19..ec107a72 100644 --- a/src/winio.c +++ b/src/winio.c @@ -1108,13 +1108,13 @@ int parse_escape_sequence(WINDOW *win, int kbinput) if (win == edit) { /* TRANSLATORS: This refers to a sequence of escape codes * (from the keyboard) that nano does not know about. */ - statusbar(_("Unknown sequence")); + statusline(ALERT, _("Unknown sequence")); suppress_cursorpos = FALSE; + alerted = FALSE; if (currmenu == MMAIN) { reset_cursor(); curs_set(1); } - beep(); } } @@ -2035,10 +2035,16 @@ void titlebar(const char *path) wnoutrefresh(edit); } +/* Display a normal message on the statusbar, quietly. */ +void statusbar(const char *msg) +{ + statusline(HUSH, msg); +} + /* Display a message on the statusbar, and set suppress_cursorpos to * TRUE, so that the message won't be immediately overwritten if * constant cursor position display is on. */ -void statusbar(const char *msg, ...) +void statusline(bool sound, const char *msg, ...) { va_list ap; char *bar, *foo; @@ -2059,6 +2065,19 @@ void statusbar(const char *msg, ...) return; } + /* If there already was an important message, ignore a normal one and + * delay another important one, to allow the earlier one to be noticed. */ + if (alerted) { + if (sound == HUSH) + return; + napms(1200); + } + + if (sound == ALERT) { + beep(); + alerted = TRUE; + } + /* Turn the cursor off while fiddling in the statusbar. */ curs_set(0); @@ -3076,7 +3095,7 @@ void do_cursorpos(bool constant) colpct = 100 * cur_xpt / cur_lenpt; charpct = (openfile->totsize == 0) ? 0 : 100 * i / openfile->totsize; - statusbar( + statusline(HUSH, _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%lu (%d%%)"), (long)openfile->current->lineno, (long)openfile->filebot->lineno, linepct,