qemacs-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemacs-commit] qemacs qe.h qeconfig.h bufed.c TODO.org charset...


From: Charlie Gordon
Subject: [Qemacs-commit] qemacs qe.h qeconfig.h bufed.c TODO.org charset...
Date: Mon, 17 Apr 2017 14:14:15 -0400 (EDT)

CVSROOT:        /sources/qemacs
Module name:    qemacs
Changes by:     Charlie Gordon <chqrlie>        17/04/17 14:14:15

Modified files:
        .              : qe.h qeconfig.h bufed.c TODO.org charset.c 
                         latex-mode.c search.c shell.c extras.c qe.c 

Log message:
        syntax: improve minibuffer and popup handling
        - remove static state for minibuffer handling, use mode specific state 
attached
          to the buffer.
        - remove static pointer for the popup last active window.  Use new 
          target_window member in EditState.
        - remove EditState.minibuf, replaced by WF_MINIBUF flag in 
EditState.flags
        - rename minibuffer commands for consistency
        - remove unused global variable debug_flags
        - prevent search from minibuffer
        - fix toggle-full-screen refresh bug. C-x f is bound to 
toggle-full-screen
          and could be typed by mistake for C-x C-f, switching to full screen 
mode
          but with a refresh delay.  This caused confusing behavior interpreted 
as a
          layout bug.
        - make charset_ucs2le, charset_ucs2be, charset_ucs4le, charset_ucs4be 
local
          in charset.c
        - make edit_detach() and edit_attach() local in qe.c
        - redraw status and diag messages in edit_display(). This caused 
display 
          bugs in x11 as asynchronous messages were erased by minibuffer window 
          refresh.
        - display status messages in diag area (bottom right screen corner) if
          minibuffer is active.
        - force put_status message update if message starts with !
        - force complete_refresh if window was resized or layout was changed

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/qemacs/qe.h?cvsroot=qemacs&r1=1.251&r2=1.252
http://cvs.savannah.gnu.org/viewcvs/qemacs/qeconfig.h?cvsroot=qemacs&r1=1.66&r2=1.67
http://cvs.savannah.gnu.org/viewcvs/qemacs/bufed.c?cvsroot=qemacs&r1=1.44&r2=1.45
http://cvs.savannah.gnu.org/viewcvs/qemacs/TODO.org?cvsroot=qemacs&r1=1.35&r2=1.36
http://cvs.savannah.gnu.org/viewcvs/qemacs/charset.c?cvsroot=qemacs&r1=1.49&r2=1.50
http://cvs.savannah.gnu.org/viewcvs/qemacs/latex-mode.c?cvsroot=qemacs&r1=1.55&r2=1.56
http://cvs.savannah.gnu.org/viewcvs/qemacs/search.c?cvsroot=qemacs&r1=1.13&r2=1.14
http://cvs.savannah.gnu.org/viewcvs/qemacs/shell.c?cvsroot=qemacs&r1=1.126&r2=1.127
http://cvs.savannah.gnu.org/viewcvs/qemacs/extras.c?cvsroot=qemacs&r1=1.68&r2=1.69
http://cvs.savannah.gnu.org/viewcvs/qemacs/qe.c?cvsroot=qemacs&r1=1.269&r2=1.270

Patches:
Index: qe.h
===================================================================
RCS file: /sources/qemacs/qemacs/qe.h,v
retrieving revision 1.251
retrieving revision 1.252
diff -u -b -r1.251 -r1.252
--- qe.h        16 Apr 2017 21:51:20 -0000      1.251
+++ qe.h        17 Apr 2017 18:14:15 -0000      1.252
@@ -147,8 +147,6 @@
 extern const char str_version[];
 extern const char str_credits[];
 
-extern int debug_flags;
-
 /* low level I/O events */
 void set_read_handler(int fd, void (*cb)(void *opaque), void *opaque);
 void set_write_handler(int fd, void (*cb)(void *opaque), void *opaque);
@@ -725,8 +723,6 @@
 extern struct QECharset charset_8859_1;
 extern struct QECharset charset_utf8;
 extern struct QECharset charset_vt100; /* used for the tty output */
-extern struct QECharset charset_ucs2le, charset_ucs2be;
-extern struct QECharset charset_ucs4le, charset_ucs4be;
 extern struct QECharset charset_mac_roman;
 
 typedef enum EOLType {
@@ -1340,7 +1336,6 @@
                         * if end of file displayed */
     int y_disp;    /* virtual position of the displayed text */
     int x_disp[2]; /* position for LTR and RTL text resp. */
-    int minibuf;   /* true if single line editing */
     int dump_width;  /* width in binary, hex and unihex modes */
     int hex_mode;    /* true if we are currently editing hexa */
     int unihex_mode; /* true if unihex editing (width of hex char dump) */
@@ -1374,6 +1369,7 @@
 
     EditBuffer *last_buffer;    /* for predict_switch_to_buffer */
     ISearchState *isearch_state;  /* active search to colorize matches */
+    EditState *target_window;   /* for minibuf, popleft and popup windows */
 
     /* mode specific info */
     ModeDef *mode;
@@ -1412,6 +1408,7 @@
 #define WF_RSEPARATOR 0x0004 /* right window separator */
 #define WF_POPLEFT    0x0008 /* left side window */
 #define WF_HIDDEN     0x0010 /* hidden window, used for temporary changes */
+#define WF_MINIBUF    0x0020 /* true if single line editing */
 #define WF_FILELIST   0x1000 /* window is interactive file list */
 
     OWNED char *prompt;  /* optional window prompt, utf8 */
@@ -1946,7 +1943,7 @@
 void register_completion(const char *name, CompletionFunc completion_func);
 void put_status(EditState *s, const char *fmt, ...) qe__attr_printf(2,3);
 void put_error(EditState *s, const char *fmt, ...) qe__attr_printf(2,3);
-void minibuffer_edit(const char *input, const char *prompt,
+void minibuffer_edit(EditState *e, const char *input, const char *prompt,
                      StringArray *hist, CompletionFunc completion_func,
                      void (*cb)(void *opaque, char *buf), void *opaque);
 void command_completion(CompleteState *cp);
@@ -1995,7 +1992,6 @@
 void edit_close(EditState **sp);
 EditState *edit_new(EditBuffer *b,
                     int x1, int y1, int width, int height, int flags);
-void edit_detach(EditState *s);
 EditBuffer *check_buffer(EditBuffer **sp);
 EditState *check_window(EditState **sp);
 int get_glyph_width(QEditScreen *screen, EditState *s, QETermStyle style, int 
c);
@@ -2184,15 +2180,14 @@
                          const char *key_bind);
 void qe_save_macros(EditState *s, EditBuffer *b);
 
-void edit_attach(EditState *s, EditState *e);
 #define COMPLETION_TAB    0
 #define COMPLETION_SPACE  1
 #define COMPLETION_OTHER  2
-void do_completion(EditState *s, int type);
-void do_completion_space(EditState *s);
-void do_electric_filename(EditState *s, int key);
+void do_minibuffer_complete(EditState *s, int type);
+void do_minibuffer_complete_space(EditState *s);
+void do_minibuffer_electric(EditState *s, int key);
 void minibuf_complete_scroll_up_down(EditState *s, int dir);
-void do_history(EditState *s, int dir);
+void do_minibuffer_history(EditState *s, int dir);
 void do_minibuffer_get_binary(EditState *s);
 void do_minibuffer_exit(EditState *s, int fabort);
 void do_popup_exit(EditState *s);

Index: qeconfig.h
===================================================================
RCS file: /sources/qemacs/qemacs/qeconfig.h,v
retrieving revision 1.66
retrieving revision 1.67
diff -u -b -r1.66 -r1.67
--- qeconfig.h  15 Apr 2017 13:10:53 -0000      1.66
+++ qeconfig.h  17 Apr 2017 18:14:15 -0000      1.67
@@ -285,9 +285,10 @@
 
     /*---------------- Help ----------------*/
 
+    CMD0( KEY_CTRLH('d'), KEY_NONE,
+          "doctor", do_doctor)
     CMD0( KEY_CTRLH('c'), KEY_CTRLH('k'),
           "describe-key-briefly", do_describe_key_briefly)
-
     CMD0( KEY_CTRLH(KEY_CTRL('h')), KEY_F1,
           "help-for-help", do_help_for_help)
 
@@ -336,8 +337,6 @@
           "exit-qemacs", do_exit_qemacs, ESi, "ui")
     CMD0( KEY_CTRL('l'), KEY_NONE,
           "refresh", do_refresh_complete)
-    CMD0( KEY_NONE, KEY_NONE,
-          "doctor", do_doctor)
     CMD0( KEY_CTRLX('u'), KEY_CTRL('_'),
           "undo", do_undo)
     CMD0( KEY_CTRLX('r'), KEY_CTRLX(KEY_CTRL('_')),
@@ -421,23 +420,23 @@
           "*" "kiui")
     CMD1( KEY_RET, KEY_NONE,
           "minibuffer-exit", do_minibuffer_exit, 0)
-    CMD1( KEY_CTRL('g'), KEY_NONE,
+    CMD1( KEY_CTRL('g'), KEY_CTRLX(KEY_CTRL('g')),
           "minibuffer-abort", do_minibuffer_exit, 1)
     CMD1( KEY_CTRL('i'), KEY_NONE,
-          "minibuffer-complete", do_completion, COMPLETION_TAB)
+          "minibuffer-complete", do_minibuffer_complete, COMPLETION_TAB)
     /* should take numeric prefix to specify word size */
     CMD0( KEY_META('='), KEY_NONE,
           "minibuffer-get-binary", do_minibuffer_get_binary)
     CMD0( ' ', KEY_NONE,
-          "minibuffer-complete-space", do_completion_space)
+          "minibuffer-complete-space", do_minibuffer_complete_space)
     CMD1( KEY_CTRL('p'), KEY_UP,
-          "minibuffer-previous-history-element", do_history, -1)
+          "minibuffer-previous-history-element", do_minibuffer_history, -1)
     CMD1( KEY_CTRL('n'), KEY_DOWN,
-          "minibuffer-next-history-element", do_history, 1)
+          "minibuffer-next-history-element", do_minibuffer_history, 1)
     CMD3( '/', KEY_NONE,
-          "minibuffer-electric-slash", do_electric_filename, ESi, '/', "*v")
+          "minibuffer-electric-slash", do_minibuffer_electric, ESi, '/', "*v")
     CMD3( '~', KEY_NONE,
-          "minibuffer-electric-tilde", do_electric_filename, ESi, '~', "*v")
+          "minibuffer-electric-tilde", do_minibuffer_electric, ESi, '~', "*v")
     CMD_DEF_END,
 };
 

Index: bufed.c
===================================================================
RCS file: /sources/qemacs/qemacs/bufed.c,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -b -r1.44 -r1.45
--- bufed.c     26 Mar 2017 15:57:24 -0000      1.44
+++ bufed.c     17 Apr 2017 18:14:15 -0000      1.45
@@ -273,7 +273,7 @@
     int i;
 
     /* ignore command from the minibuffer and popups */
-    if (s->minibuf || (s->flags & WF_POPUP))
+    if (s->flags & (WF_POPUP | WF_MINIBUF))
         return;
 
     if (s->flags & WF_POPLEFT) {

Index: TODO.org
===================================================================
RCS file: /sources/qemacs/qemacs/TODO.org,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -b -r1.35 -r1.36
--- TODO.org    15 Apr 2017 13:10:53 -0000      1.35
+++ TODO.org    17 Apr 2017 18:14:15 -0000      1.36
@@ -1,13 +1,12 @@
 ; TODO list for qemacs
 ;
 ; Author: Charles Gordon
-; Updated: 2017-04-11
+; Updated: 2017-04-17
 
 * Recent bugs and ideas
 
-** display: fix window split bug
 ** basic: backspace delete hacking tabs
-** basic: prevent search inside minibuf
+** display: minibuffer and popup windows should be in a separate lists
 ** display: save display-width in binary and hex modes upon window change
 ** display: default display-width of 0 is automatic, other values are shared 
between binary and hex modes
 ** display: hex-mode should optionally display chunks of 2, 4 or 8 bytes in 
big or little endian order
@@ -132,7 +131,6 @@
    count-matches, delete-matching-lines (might need recursive edit)
 ** search: add regex support
 ** search: hex-mode search strings should mix hex ut8 strings and ASCII 
control char names
-** search: make isearch bindings for minibuffer
 ** search: handle word and case toggles matches in query-replace
 ** session: register session store functions
 ** session: save previous answers, ...

Index: charset.c
===================================================================
RCS file: /sources/qemacs/qemacs/charset.c,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -b -r1.49 -r1.50
--- charset.c   16 Apr 2017 21:51:19 -0000      1.49
+++ charset.c   17 Apr 2017 18:14:15 -0000      1.50
@@ -558,6 +558,8 @@
 /********************************************************/
 /* UCS2/UCS4 */
 
+extern struct QECharset charset_ucs2le, charset_ucs2be;
+
 static int probe_ucs2le(qe__unused__ QECharset *charset, const u8 *buf, int 
size)
 {
     const uint32_t magic = (1U << '\b') | (1U << '\t') | (1U << '\f') |
@@ -833,6 +835,8 @@
     2, 0, 0, 10, 0, 0, table_none, NULL, NULL,
 };
 
+extern struct QECharset charset_ucs4le, charset_ucs4be;
+
 static int probe_ucs4le(qe__unused__ QECharset *charset, const u8 *buf, int 
size)
 {
     const uint32_t magic = (1U << '\b') | (1U << '\t') | (1U << '\f') |

Index: latex-mode.c
===================================================================
RCS file: /sources/qemacs/qemacs/latex-mode.c,v
retrieving revision 1.55
retrieving revision 1.56
diff -u -b -r1.55 -r1.56
--- latex-mode.c        23 Dec 2016 09:51:40 -0000      1.55
+++ latex-mode.c        17 Apr 2017 18:14:15 -0000      1.56
@@ -314,7 +314,7 @@
         if (func->ask) {
             char prompt[128];
             snprintf(prompt, sizeof(prompt), "%s command: ", func->name);
-            minibuffer_edit(buf, prompt, &func->history,
+            minibuffer_edit(e, buf, prompt, &func->history,
                             NULL /* completion */,
                             latex_cmd_run, func);
         } else {

Index: search.c
===================================================================
RCS file: /sources/qemacs/qemacs/search.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- search.c    3 Apr 2017 08:33:57 -0000       1.13
+++ search.c    17 Apr 2017 18:14:15 -0000      1.14
@@ -529,6 +529,10 @@
     EditState *e;
     int flags = SEARCH_FLAG_SMARTCASE;
 
+    /* prevent search from minibuffer */
+    if (s->flags & WF_MINIBUF)
+        return;
+
     /* stop displaying search matches on last window */
     e = check_window(&is->s);
     if (e) {
@@ -800,6 +804,10 @@
 {
     QueryReplaceState *is;
 
+    /* prevent replace from minibuffer */
+    if (s->flags & WF_MINIBUF)
+        return;
+
     if (s->b->flags & BF_READONLY)
         return;
 

Index: shell.c
===================================================================
RCS file: /sources/qemacs/qemacs/shell.c,v
retrieving revision 1.126
retrieving revision 1.127
diff -u -b -r1.126 -r1.127
--- shell.c     15 Apr 2017 09:39:02 -0000      1.126
+++ shell.c     17 Apr 2017 18:14:15 -0000      1.127
@@ -1669,7 +1669,7 @@
     ShellState *shs;
     EditBuffer *b = NULL;
 
-    if (s->flags & WF_POPUP)
+    if (s->flags & (WF_POPUP | WF_MINIBUF))
         return;
 
     if (s->flags & WF_POPLEFT) {

Index: extras.c
===================================================================
RCS file: /sources/qemacs/qemacs/extras.c,v
retrieving revision 1.68
retrieving revision 1.69
diff -u -b -r1.68 -r1.69
--- extras.c    16 Apr 2017 21:51:20 -0000      1.68
+++ extras.c    17 Apr 2017 18:14:15 -0000      1.69
@@ -1427,11 +1427,12 @@
     eb_printf(b1, "%*s: %d, %d\n", w, "xleft, ytop", s->xleft, s->ytop);
     eb_printf(b1, "%*s: %d, %d\n", w, "width, height", s->width, s->height);
     eb_printf(b1, "%*s: %d, %d, %d, %d\n", w, "x1, y1, x2, y2", s->x1, s->y1, 
s->x2, s->y2);
-    eb_printf(b1, "%*s: %#x%s%s%s%s%s%s\n", w, "flags", s->flags,
+    eb_printf(b1, "%*s: %#x%s%s%s%s%s%s%s\n", w, "flags", s->flags,
               (s->flags & WF_POPUP) ? " POPUP" : "",
               (s->flags & WF_MODELINE) ? " MODELINE" : "",
               (s->flags & WF_RSEPARATOR) ? " RSEPARATOR" : "",
               (s->flags & WF_POPLEFT) ? " POPLEFT" : "",
+              (s->flags & WF_MINIBUF) ? " MINIBUF" : "",
               (s->flags & WF_HIDDEN) ? " HIDDEN" : "",
               (s->flags & WF_FILELIST) ? " FILELIST" : "");
     eb_printf(b1, "%*s: %d\n", w, "offset", s->offset);
@@ -1439,7 +1440,6 @@
     eb_printf(b1, "%*s: %d\n", w, "offset_bottom", s->offset_bottom);
     eb_printf(b1, "%*s: %d\n", w, "y_disp", s->y_disp);
     eb_printf(b1, "%*s: %d, %d\n", w, "x_disp[]", s->x_disp[0], s->x_disp[1]);
-    eb_printf(b1, "%*s: %d\n", w, "minibuf", s->minibuf);
     eb_printf(b1, "%*s: %d\n", w, "dump_width", s->dump_width);
     eb_printf(b1, "%*s: %d\n", w, "hex_mode", s->hex_mode);
     eb_printf(b1, "%*s: %d\n", w, "unihex_mode", s->unihex_mode);

Index: qe.c
===================================================================
RCS file: /sources/qemacs/qemacs/qe.c,v
retrieving revision 1.269
retrieving revision 1.270
diff -u -b -r1.269 -r1.270
--- qe.c        16 Apr 2017 21:51:20 -0000      1.269
+++ qe.c        17 Apr 2017 18:14:15 -0000      1.270
@@ -42,8 +42,6 @@
     char name[32];
 } HistoryEntry;
 
-int debug_flags;
-
 #ifdef CONFIG_INIT_CALLS
 static int (*qe__initcall_first)(void) qe__init_call = NULL;
 static void (*qe__exitcall_first)(void) qe__exit_call = NULL;
@@ -1032,6 +1030,7 @@
     if (s->b->flags & BF_PREVIEW) {
         EditState *e = find_window(s, KEY_LEFT, NULL);
         if (e && (e->flags & WF_FILELIST)
+        &&  s->qe_state->active_window == s
         &&  dir < 0 && eb_at_bol(s->b, s->offset)) {
             s->qe_state->active_window = e;
             return;
@@ -1622,7 +1621,7 @@
     struct QuoteKeyArgument *qa = opaque;
     EditState *s = qa->s;
 
-    put_status(s, "");
+    put_status(s, "");  /* erase "Quote: " message */
 
     if (!s)
         return;
@@ -2982,6 +2981,7 @@
     else
         s->flags |= WF_MODELINE;
     qs->hide_status = qs->is_full_screen;
+    do_refresh(s);
 }
 
 void do_toggle_mode_line(EditState *s)
@@ -4150,7 +4150,7 @@
                 ds->style = sbuf[char_index];
             }
             c = eb_nextc(s->b, offset, &offset);
-            if (c == '\n' && !s->minibuf) {
+            if (c == '\n' && !(s->flags & WF_MINIBUF)) {
                 display_eol(ds, offset0, offset);
                 break;
             }
@@ -4680,7 +4680,7 @@
                 pstrcat(prompt, sizeof(prompt), es->default_input);
                 pstrcat(prompt, sizeof(prompt), ") ");
             }
-            minibuffer_edit(def_input, prompt,
+            minibuffer_edit(s, def_input, prompt,
                             get_history(history),
                             find_completion(completion_name),
                             arg_edit_cb, es);
@@ -4831,7 +4831,7 @@
 void edit_display(QEmacsState *qs)
 {
     EditState *s;
-    int has_popups;
+    int has_popups, has_minibuf;
     int start_time, elapsed_time;
 
     start_time = get_clock_ms();
@@ -4845,16 +4845,20 @@
     /* count popups */
     /* CG: maybe a separate list for popups? */
     has_popups = 0;
+    has_minibuf = 0;
     for (s = qs->first_window; s != NULL; s = s->next_window) {
         if (s->flags & WF_POPUP) {
-            has_popups = 1;
+            has_popups++;
+        }
+        if (s->flags & WF_MINIBUF) {
+            has_minibuf++;
         }
     }
 
     /* refresh normal windows and minibuf with popup kludge */
     for (s = qs->first_window; s != NULL; s = s->next_window) {
         if (!(s->flags & WF_POPUP) &&
-            (s->minibuf || !has_popups || qs->complete_refresh)) {
+            ((s->flags & WF_MINIBUF) || !has_popups || qs->complete_refresh)) {
             window_display(s);
         }
     }
@@ -4869,6 +4873,24 @@
         }
     }
 
+    /* Redraw status and diag messages */
+    if (*qs->status_shadow || *qs->diag_shadow) {
+        int width = qs->screen->width;
+        int height = qs->status_height;
+        int x = 0, y = qs->screen->height - height;
+
+        if (*qs->status_shadow && !has_minibuf) {
+            print_at_byte(qs->screen, x, y, width, height,
+                          qs->status_shadow, QE_STYLE_STATUS);
+        }
+        if (*qs->diag_shadow) {
+            int w = strlen(qs->diag_shadow) + 1;
+            w *= get_glyph_width(qs->screen, NULL, QE_STYLE_STATUS, '0');
+            print_at_byte(qs->screen, x + width - w, y, w, height,
+                          qs->diag_shadow, QE_STYLE_STATUS);
+        }
+    }
+
     elapsed_time = get_clock_ms() - start_time;
     if (elapsed_time >= 100)
         put_status(s, "|edit_display: %dms", elapsed_time);
@@ -5151,6 +5173,7 @@
     CmdDef *d;
     char buf1[128];
     buf_t outbuf, *out;
+    int len;
 
     if (qs->defining_macro && !qs->executing_macro) {
         macro_add_key(key);
@@ -5176,10 +5199,8 @@
 
     c->keys[c->nb_keys++] = key;
     s = qs->active_window;
-    if (!s->minibuf) {
-        put_status(s, " ");
+    put_status(s, " ");     /* Erase pending keystrokes and message */
         dpy_flush(&global_screen);
-    }
 
     /* Special case for escape: we transform it as meta so
        that unix users are happy ! */
@@ -5287,11 +5308,8 @@
     }
  next:
     /* display key pressed */
-    if (!s->minibuf) {
-        int len;
-
         len = strlen(c->buf);
-        if (len >= 1)
+    if (len > 0)
             c->buf[len-1] = ' ';
         /* Should print argument if any in a more readable way */
         out = buf_attach(&outbuf, c->buf, sizeof(c->buf), len);
@@ -5299,7 +5317,6 @@
         buf_put_byte(out, '-');
         put_status(s, "~%s", c->buf);
         dpy_flush(&global_screen);
-    }
 }
 
 /* Print a utf-8 encoded buffer as unicode */
@@ -5368,26 +5385,35 @@
     eb_format_message(qs, "*errors*", buf);
 }
 
-void put_status(qe__unused__ EditState *s, const char *fmt, ...)
+void put_status(EditState *s, const char *fmt, ...)
 {
-    /* CG: s is not used and may be NULL! */
-    QEmacsState *qs = &qe_state;
+    /* XXX: s may be NULL! */
+    QEmacsState *qs = s ? s->qe_state : &qe_state;
     char buf[MAX_SCREEN_WIDTH];
     const char *p;
     va_list ap;
     int silent = 0;
     int diag = 0;
+    int force = 0;
 
     va_start(ap, fmt);
     vsnprintf(buf, sizeof(buf), fmt, ap);
     va_end(ap);
 
+    if (qs->active_window && (qs->active_window->flags & WF_MINIBUF)) {
+        /* display status messages in diag area if minibuffer is active */
+        diag = 1;
+    }
+
     for (p = buf;; p++) {
         if (*p == '|') {
             diag = 1;
         } else
         if (*p == '~') {
             silent = 1;
+        } else
+        if (*p == '!') {
+            force = 1;
         } else {
             break;
         }
@@ -5396,31 +5422,30 @@
     if (!qs->screen->dpy.dpy_probe) {
         eb_format_message(qs, "*errors*", p);
     } else {
+        int width = qs->screen->width;
+        int height = qs->status_height;
+        int x = 0, y = qs->screen->height - height;
+
         if (diag) {
-            if (!strequal(p, qs->diag_shadow)) {
+            if (force || !strequal(p, qs->diag_shadow)) {
                 /* right align display and overwrite last diag message */
                 int w = strlen(qs->diag_shadow);
                 w = snprintf(qs->diag_shadow, sizeof(qs->diag_shadow),
                              "%*s", w, p) + 1;
                 w *= get_glyph_width(qs->screen, NULL, QE_STYLE_STATUS, '0');
-                print_at_byte(qs->screen,
-                              qs->screen->width - w,
-                              qs->screen->height - qs->status_height,
-                              qs->screen->width - w, qs->status_height,
+                print_at_byte(qs->screen, x + width - w, y, w, height,
                               qs->diag_shadow, QE_STYLE_STATUS);
                 pstrcpy(qs->diag_shadow, sizeof(qs->diag_shadow), p);
             }
         } else {
-            if (!strequal(p, qs->status_shadow)) {
-                print_at_byte(qs->screen,
-                              0, qs->screen->height - qs->status_height,
-                              qs->screen->width, qs->status_height,
+            if (force || !strequal(p, qs->status_shadow)) {
+                print_at_byte(qs->screen, x, y, width, height,
                               p, QE_STYLE_STATUS);
                 pstrcpy(qs->status_shadow, sizeof(qs->status_shadow), p);
             }
         }
         skip_spaces(&p);
-        if (!silent && *buf)
+        if (!silent && *p)
             eb_format_message(qs, "*messages*", buf);
     }
 }
@@ -5507,6 +5532,60 @@
     }
 }
 
+/* detach the window from the window tree. */
+static void edit_detach(EditState *s)
+{
+    QEmacsState *qs = s->qe_state;
+    EditState **ep;
+
+    /* unlink the window from the frame */
+    for (ep = &qs->first_window; *ep;) {
+        if ((*ep)->target_window == s) {
+            (*ep)->target_window = NULL;
+        }
+        if (*ep == s) {
+            *ep = s->next_window;
+            s->next_window = NULL;
+        } else {
+            ep = &(*ep)->next_window;
+        }
+    }
+    /* if window was active, activate target window or default window */
+    if (qs->active_window == s) {
+        if (s->target_window)
+            qs->active_window = s->target_window;
+        else
+            qs->active_window = qs->first_window;
+    }
+}
+
+/* move a window before another one */
+static void edit_attach(EditState *s, EditState *e)
+{
+    QEmacsState *qs = s->qe_state;
+    EditState **ep;
+
+    if (s != e) {
+        /* Detach the window from the frame */
+        for (ep = &qs->first_window; *ep; ep = &(*ep)->next_window) {
+            if (*ep == s) {
+                *ep = s->next_window;
+                s->next_window = NULL;
+                break;
+            }
+        }
+        /* Re-attach the window before `e` */
+        for (ep = &qs->first_window; *ep; ep = &(*ep)->next_window) {
+            if (*ep == e)
+                break;
+        }
+        s->next_window = *ep;
+        *ep = s;
+        if (qs->active_window == NULL)
+            qs->active_window = s;
+    }
+}
+
 /* compute the client area from the window position */
 static void compute_client_area(EditState *s)
 {
@@ -5570,43 +5649,6 @@
     return s;
 }
 
-/* detach the window from the window tree. */
-void edit_detach(EditState *s)
-{
-    QEmacsState *qs = s->qe_state;
-    EditState **ep;
-
-    for (ep = &qs->first_window; *ep; ep = &(*ep)->next_window) {
-        if (*ep == s) {
-            *ep = s->next_window;
-            s->next_window = NULL;
-            break;
-        }
-    }
-    if (qs->active_window == s)
-        qs->active_window = qs->first_window;
-}
-
-/* move a window before another one */
-void edit_attach(EditState *s, EditState *e)
-{
-    QEmacsState *qs = s->qe_state;
-    EditState *active_window = qs->active_window;
-    EditState **ep;
-
-    if (s != e) {
-        edit_detach(s);
-
-        for (ep = &qs->first_window; *ep; ep = &(*ep)->next_window) {
-            if (*ep == e)
-                break;
-        }
-        s->next_window = *ep;
-        *ep = s;
-        qs->active_window = active_window ? active_window : s;
-    }
-}
-
 /* Close the edit window.
  * Save the window state to the buffer for later retrieval.
  * If it is active, find another window to activate.
@@ -5768,25 +5810,27 @@
 
 /* mini buffer stuff */
 
-struct MinibufState {
+typedef struct MinibufState {
+    QEModeData base;
+
     void (*cb)(void *opaque, char *buf);
     void *opaque;
-    EditState *saved_active;
 
-    EditState *completion_popup_window;
+    EditState *completion_popup_window;  /* XXX: should have a popup_window 
member */
     CompletionFunc completion_function;
 
     StringArray *history;
     int history_index;
     int history_saved_offset;
-};
+} MinibufState;
 
 static ModeDef minibuffer_mode;
 
-/* XXX: should be opaque mode data */
-static struct MinibufState minibuffer;
+static inline MinibufState *minibuffer_get_state(EditState *e, int status) {
+    return qe_get_buffer_mode_data(e->b, &minibuffer_mode, status ? e : NULL);
+}
 
-void do_completion(EditState *s, int type)
+void do_minibuffer_complete(EditState *s, int type)
 {
     QEmacsState *qs = s->qe_state;
     int count, i, match_len, c;
@@ -5795,8 +5839,12 @@
     EditState *e;
     EditBuffer *b;
     int w, h, h1, w1;
+    MinibufState *mb;
 
-    if (!minibuffer.completion_function)
+    if ((mb = minibuffer_get_state(s, 1)) == NULL)
+        return;
+
+    if (!mb->completion_function)
         return;
 
     /* Remove highlighted selection. */
@@ -5810,18 +5858,18 @@
      */
 
     /* check completion window */
-    check_window(&minibuffer.completion_popup_window);
-    if (minibuffer.completion_popup_window
+    check_window(&mb->completion_popup_window);
+    if (mb->completion_popup_window
     &&  type == COMPLETION_TAB
     &&  qs->last_cmd_func == qs->this_cmd_func) {
         /* toggle cpmpletion popup on TAB */
-        edit_close(&minibuffer.completion_popup_window);
+        edit_close(&mb->completion_popup_window);
         do_refresh(s);
         return;
     }
 
-    complete_start(&cs, s, check_window(&minibuffer.saved_active));
-    (*minibuffer.completion_function)(&cs);
+    complete_start(&cs, s, s->target_window);
+    (*mb->completion_function)(&cs);
     count = cs.cs.nb_items;
     outputs = cs.cs.items;
 #if 0
@@ -5862,7 +5910,7 @@
         if (count > 1) {
             /* if more than one match, then display them in a new popup
                buffer */
-            if (!minibuffer.completion_popup_window) {
+            if (!mb->completion_popup_window) {
                 b = eb_new("*completion*", 
                            BF_SYSTEM | BF_UTF8 | BF_TRANSIENT | BF_STYLE1);
                 b->default_mode = &list_mode;
@@ -5871,19 +5919,20 @@
                 w = (w1 * 3) / 4;
                 h = (h1 * 3) / 4;
                 e = edit_new(b, (w1 - w) / 2, (h1 - h) / 2, w, h, WF_POPUP);
+                e->target_window = s;
+                mb->completion_popup_window = e;
                 do_refresh(e);
-                minibuffer.completion_popup_window = e;
             }
         } else
         if (count == 0 || type != COMPLETION_OTHER) {
             /* close the popup when minibuf contents matches nothing */
-            edit_close(&minibuffer.completion_popup_window);
+            edit_close(&mb->completion_popup_window);
             do_refresh(s);
         }
     }
-    if (minibuffer.completion_popup_window) {
+    if (mb->completion_popup_window) {
         /* modify the list with the current matches */
-        e = minibuffer.completion_popup_window;
+        e = mb->completion_popup_window;
         b = e->b;
         qsort(outputs, count, sizeof(StringItem *), completion_sort_func);
         b->flags &= ~BF_READONLY;
@@ -5914,11 +5963,12 @@
     return 1;
 }
 
-void do_electric_filename(EditState *s, int key)
+void do_minibuffer_electric(EditState *s, int key)
 {
     int c, offset, stop;
+    MinibufState *mb = minibuffer_get_state(s, 0);
 
-    if (minibuffer.completion_function == file_completion) {
+    if (mb && mb->completion_function == file_completion) {
         stop = s->offset;
         c = eb_prevc(s->b, s->offset, &offset);
         if (c == '/') {
@@ -5934,42 +5984,48 @@
 }
 
 /* space does completion only if a completion method is defined */
-void do_completion_space(EditState *s)
+void do_minibuffer_complete_space(EditState *s)
 {
     QEmacsState *qs = s->qe_state;
+    MinibufState *mb = minibuffer_get_state(s, 0);
 
-    if (!minibuffer.completion_function) {
+    if (!mb || !mb->completion_function) {
         do_char(s, ' ', 1);
     } else
-    if (minibuffer.completion_popup_window && qs->last_cmd_func == 
qs->this_cmd_func) {
+    if (check_window(&mb->completion_popup_window)
+    &&  qs->last_cmd_func == qs->this_cmd_func) {
         /* page through the list */
         // XXX: should close the popup at the bottom of the list
-        do_scroll_up_down(minibuffer.completion_popup_window, 2);
+        do_scroll_up_down(mb->completion_popup_window, 2);
     } else {
-        do_completion(s, COMPLETION_SPACE);
+        do_minibuffer_complete(s, COMPLETION_SPACE);
     }
 }
 
 static void do_minibuffer_char(EditState *s, int key, int argval)
 {
+    MinibufState *mb = minibuffer_get_state(s, 0);
+
     do_char(s, key, argval);
-    if (minibuffer.completion_popup_window) {
+    if (mb && check_window(&mb->completion_popup_window)) {
         /* automatic filtering of completion list */
         // XXX: should prevent auto-completion
-        do_completion(s, COMPLETION_OTHER);
+        do_minibuffer_complete(s, COMPLETION_OTHER);
     }
 }
 
 /* scroll in completion popup */
 void minibuf_complete_scroll_up_down(qe__unused__ EditState *s, int dir)
 {
-    if (minibuffer.completion_popup_window) {
-        minibuffer.completion_popup_window->force_highlight = 1;
-        do_scroll_up_down(minibuffer.completion_popup_window, dir);
+    MinibufState *mb = minibuffer_get_state(s, 0);
+
+    if (mb && check_window(&mb->completion_popup_window)) {
+        mb->completion_popup_window->force_highlight = 1;
+        do_scroll_up_down(mb->completion_popup_window, dir);
     }
 }
 
-static void set_minibuffer_str(EditState *s, const char *str)
+static void minibuf_set_str(EditState *s, const char *str)
 {
     int len;
 
@@ -6002,38 +6058,45 @@
     return &p->history;
 }
 
-void do_history(EditState *s, int dir)
+void do_minibuffer_history(EditState *s, int dir)
 {
     QEmacsState *qs = s->qe_state;
-    StringArray *hist = minibuffer.history;
+    MinibufState *mb;
+    StringArray *hist;
     int index;
     char *str;
     char buf[1024];
 
+    if ((mb = minibuffer_get_state(s, 0)) == NULL)
+        return;
+
     /* if completion visible, move in it */
-    if (minibuffer.completion_popup_window) {
-        minibuffer.completion_popup_window->force_highlight = 1;
-        do_up_down(minibuffer.completion_popup_window, dir);
+    if (check_window(&mb->completion_popup_window)) {
+        mb->completion_popup_window->force_highlight = 1;
+        do_up_down(mb->completion_popup_window, dir);
         return;
     }
 
+    hist = mb->history;
     if (!hist)
         return;
-    index = minibuffer.history_index + dir;
+
+    index = mb->history_index + dir;
     if (index < 0 || index >= hist->nb_items)
         return;
-    if (qs->last_cmd_func != (CmdFunc)do_history) {
+
+    if (qs->last_cmd_func != (CmdFunc)do_minibuffer_history) {
         /* save currently edited line */
         eb_get_contents(s->b, buf, sizeof(buf));
         set_string(hist, hist->nb_items - 1, buf, 0);
-        minibuffer.history_saved_offset = s->offset;
+        mb->history_saved_offset = s->offset;
     }
     /* insert history text */
-    minibuffer.history_index = index;
+    mb->history_index = index;
     str = hist->items[index]->str;
-    set_minibuffer_str(s, str);
+    minibuf_set_str(s, str);
     if (index == hist->nb_items - 1) {
-        s->offset = minibuffer.history_saved_offset;
+        s->offset = mb->history_saved_offset;
     }
 }
 
@@ -6041,9 +6104,8 @@
 {
     unsigned long offset;
 
-    if (minibuffer.saved_active) {
-        eb_read(minibuffer.saved_active->b,
-                minibuffer.saved_active->offset,
+    if (s->target_window) {
+        eb_read(s->target_window->b, s->target_window->offset,
                 &offset, sizeof(offset));
         eb_printf(s->b, "%lu", offset);
     }
@@ -6051,13 +6113,20 @@
 
 void do_minibuffer_exit(EditState *s, int do_abort)
 {
-    QEmacsState *qs = s->qe_state;
-    StringArray *hist = minibuffer.history;
+    char buf[4096], *retstr;
+    MinibufState *mb;
+    StringArray *hist;
+    EditState *cw;
+    EditState *target;
     void (*cb)(void *opaque, char *buf);
     void *opaque;
-    char buf[4096], *retstr;
-    EditState *cw = minibuffer.completion_popup_window;
 
+    if ((mb = minibuffer_get_state(s, 1)) == NULL)
+        return;
+
+    cw = check_window(&mb->completion_popup_window);
+
+    if (!do_abort) {
     /* if completion is activated, then select current file only if
        the selection is highlighted */
     if (cw && cw->force_highlight) {
@@ -6066,19 +6135,14 @@
         len = eb_fgets(cw->b, buf, sizeof(buf), list_get_offset(cw), &offset);
         buf[len] = '\0';   /* strip the trailing newline if any */
         if (len > 0) {
-            set_minibuffer_str(s, buf + 1);
-        }
+                minibuf_set_str(s, buf + 1);
     }
-
-    /* remove completion popup if present */
-    /* CG: assuming minibuffer.completion_popup_window != s */
-    if (cw) {
-        edit_close(&minibuffer.completion_popup_window);
-        cw = NULL;
-        do_refresh(s);
     }
 
     eb_get_contents(s->b, buf, sizeof(buf));
+
+        /* Append response to history list */
+        hist = mb->history;
     if (hist && hist->nb_items > 0) {
         /* if null string, do not insert in history */
         hist->nb_items--;
@@ -6086,100 +6150,124 @@
         if (buf[0] != '\0')
             add_string(hist, buf, 0);
     }
+    }
 
-    s->b->flags |= BF_TRANSIENT;
-    /* Close the minibuffer window */
-    edit_close(&s);
+    /* remove completion popup if present */
+    if (cw) {
+        edit_close(&mb->completion_popup_window);
+        cw = NULL;
+        do_refresh(s);
+    }
 
-    /* restore active window */
-    qs->active_window = check_window(&minibuffer.saved_active);
-    minibuffer.saved_active = NULL;
-
-    /* force status update */
-    //pstrcpy(qs->status_shadow, sizeof(qs->status_shadow), " ");
-    if (do_abort)
-        put_status(NULL, "Canceled.");
-    else
-        put_status(NULL, "");
+    cb = mb->cb;
+    opaque = mb->opaque;
+    target = s->target_window;
+    mb->cb = NULL;
+    mb->opaque = NULL;
 
-    /* call the callback */
-    cb = minibuffer.cb;
-    opaque = minibuffer.opaque;
-    minibuffer.cb = NULL;
-    minibuffer.opaque = NULL;
+    /* Close the minibuffer window */
+    s->b->flags |= BF_TRANSIENT;
+    edit_close(&s);
 
+    /* Force status update and call the callback */
     if (do_abort) {
-        cb(opaque, NULL);
+        put_status(target, "!Canceled.");
+        (*cb)(opaque, NULL);
     } else {
+        put_status(target, "!");
         retstr = qe_strdup(buf);
-        cb(opaque, retstr);
+        (*cb)(opaque, retstr);
     }
 }
 
 /* Start minibuffer editing. When editing is finished, the callback is
    called with an allocated string. If the string is null, it means
    editing was aborted. */
-void minibuffer_edit(const char *input, const char *prompt,
+void minibuffer_edit(EditState *e, const char *input, const char *prompt,
                      StringArray *hist, CompletionFunc completion_func,
                      void (*cb)(void *opaque, char *buf), void *opaque)
 {
-
-    EditState *s;
     QEmacsState *qs = &qe_state;
+    MinibufState *mb;
+    EditState *s;
     EditBuffer *b;
     int len;
 
     /* check if already in minibuffer editing */
-    if (minibuffer.cb) {
-        put_status(NULL, "Already editing in minibuffer");
+    if (e->flags & WF_MINIBUF) {
+        put_status(NULL, "|Already editing in minibuffer");
         cb(opaque, NULL);
         return;
     }
 
-    minibuffer.cb = cb;
-    minibuffer.opaque = opaque;
-
     b = eb_new("*minibuf*", BF_SYSTEM | BF_SAVELOG | BF_UTF8);
     b->default_mode = &minibuffer_mode;
 
     s = edit_new(b, 0, qs->screen->height - qs->status_height,
-                 qs->screen->width, qs->status_height, 0);
-    /* Should insert at end of window list */
-    /* XXX: should qe_free previous value? */
+                 qs->screen->width, qs->status_height, WF_MINIBUF);
+    s->target_window = e;
     s->prompt = qe_strdup(prompt);
-    s->minibuf = 1;
     s->bidir = 0;
     s->default_style = QE_STYLE_MINIBUF;
     s->wrap = WRAP_TRUNCATE;
 
     /* add default input */
     if (input) {
-        /* XXX: should insert utf-8? */
+        /* Default input should already be encoded as utf-8 */
         len = strlen(input);
         eb_write(b, 0, (u8 *)input, len);
         s->offset = len;
     }
 
-    minibuffer.saved_active = qs->active_window;
-    qs->active_window = s;
-
-    minibuffer.completion_popup_window = NULL;
-    minibuffer.completion_function = completion_func;
-    minibuffer.history = hist;
-    minibuffer.history_saved_offset = 0;
+    mb = minibuffer_get_state(s, 0);
+    if (mb) {
+        mb->completion_popup_window = NULL;
+        mb->completion_function = completion_func;
+        mb->history = hist;
+        mb->history_saved_offset = 0;
     if (hist) {
-        minibuffer.history_index = hist->nb_items;
+            mb->history_index = hist->nb_items;
         add_string(hist, "", 0);
     }
+        mb->cb = cb;
+        mb->opaque = opaque;
+        qs->active_window = s;
+    }
+}
+
+static void minibuffer_mode_free(EditBuffer *b, void *state)
+{
+    /* If minibuffer is destroyed, call callback with NULL pointer */
+    MinibufState *mb = state;
+    void (*cb)(void *opaque, char *buf);
+    void *opaque;
+
+    if (!mb)
+        return;
+
+    if (check_window(&mb->completion_popup_window))
+        edit_close(&mb->completion_popup_window);
+
+    cb = mb->cb;
+    opaque = mb->opaque;
+    mb->cb = NULL;
+    mb->opaque = NULL;
+
+    if (cb) {
+        put_status(NULL, "!Abort.");
+        (*cb)(opaque, NULL);
+    }
 }
 
 void minibuffer_init(void)
 {
-    /* minibuf mode inherits from text mode */
+    /* populate and register minibuffer mode and commands */
     memcpy(&minibuffer_mode, &text_mode, sizeof(ModeDef));
     minibuffer_mode.name = "minibuffer";
     minibuffer_mode.mode_name = NULL;
     minibuffer_mode.mode_probe = NULL;
+    minibuffer_mode.buffer_instance_size = sizeof(MinibufState);
+    minibuffer_mode.mode_free = minibuffer_mode_free;
     minibuffer_mode.scroll_up_down = minibuf_complete_scroll_up_down;
     qe_register_mode(&minibuffer_mode, MODEF_NOCMD | MODEF_VIEW);
     qe_register_cmd_table(minibuffer_commands, &minibuffer_mode);
@@ -6189,9 +6277,6 @@
 
 static ModeDef popup_mode;
 
-/* XXX: incorrect to save it. Should use window target member */
-static EditState *popup_saved_active;
-
 /* Verify that window still exists, return argument or NULL,
  * update handle if window is invalid.
  */
@@ -6216,9 +6301,6 @@
         s->b->flags |= BF_TRANSIENT;
         edit_close(&s);
 
-        qs->active_window = check_window(&popup_saved_active);
-        popup_saved_active = NULL;
-
         do_refresh(qs->active_window);
     }
 }
@@ -6226,7 +6308,7 @@
 /* show a popup on a readonly buffer */
 EditState *show_popup(EditState *s, EditBuffer *b)
 {
-    QEmacsState *qs = &qe_state;
+    QEmacsState *qs = s->qe_state;
     EditState *e;
     int w, h, w1, h1;
 
@@ -6240,11 +6322,10 @@
     w = (w1 * 4) / 5;
     h = (h1 * 3) / 4;
 
+    b->default_mode = &popup_mode;
     e = edit_new(b, (w1 - w) / 2, (h1 - h) / 2, w, h, WF_POPUP);
-    edit_set_mode(e, &popup_mode);
     e->wrap = WRAP_TRUNCATE;
-
-    popup_saved_active = qs->active_window;
+    e->target_window = s;
     qs->active_window = e;
     do_refresh(e);
     return e;
@@ -6271,7 +6352,7 @@
 
     for (e = qs->first_window; e != NULL; e = e_next) {
         e_next = e->next_window;
-        if (e->minibuf)
+        if (e->flags & WF_MINIBUF)
             continue;
         if (e->x2 <= width) {
             edit_close(&e);
@@ -6298,7 +6379,7 @@
      * non regular window layouts
      */
     for (e = qs->first_window; e != NULL; e = e->next_window) {
-        if (e->minibuf)
+        if (e->flags & WF_MINIBUF)
             continue;
         if (e->y1 < s->y2 && e->y2 > s->y1) {
             /* horizontal overlap */
@@ -6350,6 +6431,9 @@
 {
     EditBuffer *b;
 
+    if (s->flags & WF_MINIBUF)
+        return;
+
     /* XXX: Default buffer charset should be selectable */
     b = eb_find_new(bufname, BF_SAVELOG | BF_UTF8);
     if (b)
@@ -6392,7 +6476,7 @@
         if (!force && b->modified && b->filename[0] != '\0') {
             snprintf(buf, sizeof(buf),
                      "Buffer %s modified; kill anyway? (yes or no) ", bufname);
-            minibuffer_edit(NULL, buf, NULL, NULL,
+            minibuffer_edit(s, NULL, buf, NULL, NULL,
                             kill_buffer_confirm_cb, b);
         } else {
             qe_kill_buffer(b);
@@ -6650,15 +6734,15 @@
 }
 
 static EditState *qe_find_target_window(EditState *s, int activate) {
+    QEmacsState *qs = s->qe_state;
     EditState *e;
 
     /* Find the target window for some commands run from the dired window */
     if (s->flags & WF_POPUP) {
-        e = check_window(&popup_saved_active);
-        popup_saved_active = NULL;
+        e = check_window(&s->target_window);
         if (e) {
-            if (activate && s->qe_state->active_window == s)
-                s->qe_state->active_window = e;
+            if (activate && qs->active_window == s)
+                qs->active_window = e;
         }
         s->b->flags |= BF_TRANSIENT;
         edit_close(&s);
@@ -6666,11 +6750,11 @@
         do_refresh(s);
     }
 #ifndef CONFIG_TINY
-    if ((s->flags & WF_POPLEFT) && s->x1 == 0) {
+    if (s && (s->flags & WF_POPLEFT) && s->x1 == 0) {
         e = find_window(s, KEY_RIGHT, NULL);
         if (e) {
-            if (activate && s->qe_state->active_window == s)
-                s->qe_state->active_window = e;
+            if (activate && qs->active_window == s)
+                qs->active_window = e;
             s = e;
         }
     }
@@ -6685,7 +6769,7 @@
  */
 void do_set_next_mode(EditState *s, int dir)
 {
-    if (s->flags & WF_POPUP)
+    if (s->flags & (WF_POPUP | WF_MINIBUF))
         return;
 
     /* next-mode from the dired window applies to the target window */
@@ -6700,8 +6784,22 @@
     ModeDef *modes[32];
     int scores[32];
     int i, nb, found;
-    EditBuffer *b = s->b;
+    EditBuffer *b;
 
+    if (s->flags & WF_MINIBUF)
+        return;
+
+#ifndef CONFIG_TINY
+    /* Find target window for POPLEFT pane */
+    if ((s->flags & WF_POPLEFT) && s->x1 == 0) {
+        EditState *e = find_window(s, KEY_RIGHT, NULL);
+        if (e) {
+            s = e;
+        }
+    }
+#endif
+
+    b = s->b;
     size = eb_read(b, 0, buf, sizeof(buf) - 1);
     buf[size] = '\0';
 
@@ -6754,7 +6852,7 @@
     }
 #endif
 
-    if (s->flags & WF_POPUP)
+    if (s->flags & (WF_POPUP | WF_MINIBUF))
         return - 1;
 
     if (lflags & LF_SPLIT_WINDOW) {
@@ -7086,6 +7184,7 @@
 /* analyse next buffer and ask question if needed */
 static void quit_examine_buffers(QuitState *is)
 {
+    QEmacsState *qs = &qe_state;
     EditBuffer *b;
 
     while (is->b != NULL) {
@@ -7094,8 +7193,8 @@
             switch (is->state) {
             case QS_ASK:
                 /* XXX: display cursor */
-                put_status(NULL, "Save file %s? (y, n, !, ., q) ",
-                           b->filename);
+                put_status(qs->active_window,
+                           "Save file %s? (y, n, !, ., q) ", b->filename);
                 dpy_flush(&global_screen);
                 /* will wait for a key */
                 return;
@@ -7113,15 +7212,15 @@
 
     /* now asks for confirmation or exit directly */
     if (is->modified) {
-        minibuffer_edit(NULL, "Modified buffers exist; exit anyway? (yes or 
no) ",
-                        NULL, NULL,
-                        quit_confirm_cb, NULL);
+        minibuffer_edit(qs->active_window,
+                        NULL, "Modified buffers exist; exit anyway? (yes or 
no) ",
+                        NULL, NULL, quit_confirm_cb, NULL);
         edit_display(&qe_state);
         dpy_flush(&global_screen);
     } else {
 #ifndef CONFIG_TINY
         if (use_session_file)
-            do_save_session(qe_state.active_window, 0);
+            do_save_session(qs->active_window, 0);
 #endif
         qe_free(&is);
         url_exit();
@@ -7223,10 +7322,10 @@
 }
 
 /* refresh the screen, s1 can be any edit window */
-void do_refresh(qe__unused__ EditState *s1)
+void do_refresh(EditState *s1)
 {
     /* CG: s1 may be NULL */
-    QEmacsState *qs = &qe_state;
+    QEmacsState *qs = s1 ? s1->qe_state : &qe_state;
     EditState *e;
     int new_status_height, new_mode_line_height, content_height;
     int width, height, resized;
@@ -7251,6 +7350,11 @@
     if (!qs->hide_status)
         content_height -= new_status_height;
 
+    /* Prevent potential division overflow */
+    width = max(1, width);
+    height = max(1, height);
+    content_height = max(1, content_height);
+
     resized = 0;
 
     /* see if resize is necessary */
@@ -7262,14 +7366,16 @@
 
         /* do the resize */
         resized = 1;
+        qs->complete_refresh = 1;
         for (e = qs->first_window; e != NULL; e = e->next_window) {
-            if (e->minibuf) {
+            if (e->flags & WF_MINIBUF) {
                 /* first resize minibuffer if present */
                 e->x1 = 0;
                 e->y1 = content_height;
                 e->x2 = width;
                 e->y2 = height;
-            } else if (qs->height == 0) {
+            } else
+            if (qs->height == 0 || qs->width == 0 || qs->content_height == 0) {
                 /* needed only to init the window size for the first time */
                 e->x1 = 0;
                 e->y1 = 0;
@@ -7357,11 +7463,11 @@
 
     count = 0;
     for (e = qs->first_window; e != NULL; e = e->next_window) {
-        if (!e->minibuf && !(e->flags & WF_POPUP))
+        if (!(e->flags & (WF_POPUP | WF_MINIBUF)))
             count++;
     }
     /* cannot close minibuf or if single window */
-    if ((s->minibuf || count <= 1) && !force)
+    if (((s->flags & WF_MINIBUF) || count <= 1) && !force)
         return;
 
     if (!(s->flags & WF_POPUP)) {
@@ -7376,7 +7482,7 @@
 
         for (pass = 0; pass < 2; pass++) {
             for (e = qs->first_window; e != NULL; e = e->next_window) {
-                if (e->minibuf || e == s || (e->flags & WF_POPUP))
+                if (e == s || (e->flags & (WF_POPUP | WF_MINIBUF)))
                     continue;
 
                 if (x1 == e->x2 && y1 == e->y1 && y2 >= e->y2) {
@@ -7422,14 +7528,21 @@
 void do_delete_other_windows(EditState *s, int all)
 {
     QEmacsState *qs = s->qe_state;
-    EditState *e, *e1;
+    EditState *e;
 
-    if (s->minibuf || (s->flags & WF_POPUP))
+    if (s->flags & (WF_POPUP | WF_MINIBUF))
         return;
 
-    for (e = qs->first_window; e != NULL; e = e1) {
-        e1 = e->next_window;
-        if (!e->minibuf && e != s)
+    for (;;) {
+        for (e = qs->first_window; e != NULL; e = e->next_window) {
+            if (!(e->flags & WF_MINIBUF) && e != s)
+                break;
+        }
+        if (e == NULL)
+            break;
+        /* rescan after closing a window because another window could
+         * be closed as a side effect
+         */
             edit_close(&e);
     }
     if (all) {
@@ -7474,7 +7587,7 @@
     int x, y;
 
     /* cannot split minibuf or popup */
-    if (s->minibuf || (s->flags & WF_POPUP))
+    if (s->flags & (WF_POPUP | WF_MINIBUF))
         return;
 
     /* This will clone mode and mode data to the newly created window */
@@ -7733,7 +7846,7 @@
         return;
 
     for (e = qs->first_window; e != NULL; e = e->next_window) {
-        if (e->minibuf || e == s)
+        if ((e->flags & WF_MINIBUF) || e == s)
             continue;
         window_get_min_size(e, &min_w, &min_h);
         if (e->y1 == s->y2) {
@@ -7758,7 +7871,7 @@
 
     /* now everything is OK, we can resize all windows */
     for (e = qs->first_window; e != NULL; e = e->next_window) {
-        if (e->minibuf || e == s)
+        if ((e->flags & WF_MINIBUF) || e == s)
             continue;
         if (e->y1 == s->y2)
             e->y1 += delta_y;
@@ -8172,6 +8285,7 @@
         qs->active_window = e;
         parse_config_file(e, buf);
     }
+    if (check_window(&saved))
     qs->active_window = saved;
 }
 
@@ -8743,7 +8857,6 @@
     qs->ec.function = NULL;
 }
 
-
 #ifdef CONFIG_WIN32
 int main1(int argc, char **argv)
 #else



reply via email to

[Prev in Thread] Current Thread [Next in Thread]