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

[PATCH] fix dselect crashing when resizing xterm (or similiar X terminal)



Here's another whopper, the old "dselect crashes when I resize xterm" bug.
I basically snatched a few lines from view.c (an ncurses example file found
in /usr/doc/libncurses4-dev/examples) to handle SIGWINCH, so this is pretty
much a textbook example.

Thanks to Sean 'Shaleh' Perry <shaleh@debian.org> for the pointers on what
to look for.

This patch also has the odd affect of allowing dselect to actually resize
its display with the window. If the window is too small, ncurses causes a
beep, and doesn't display.

Ben
diff -urN dpkg-1.4.1.13.old/dselect/dselect.h dpkg-1.4.1.13/dselect/dselect.h
--- dpkg-1.4.1.13.old/dselect/dselect.h	Sun Nov  1 11:04:31 1998
+++ dpkg-1.4.1.13/dselect/dselect.h	Mon Oct 11 13:20:51 1999
@@ -27,6 +27,17 @@
 
 #include <signal.h>
 
+#if defined(SIGWINCH) && defined(TIOCGWINSZ) && defined(NCURSES_VERSION)
+#define CAN_RESIZE 1
+#else
+#define CAN_RESIZE 0
+#endif
+
+#if CAN_RESIZE
+static RETSIGTYPE adjust(int sig);
+static int          interrupted;
+#endif
+
 struct helpmenuentry {
   char key;
   const struct helpmessage *msg;
diff -urN dpkg-1.4.1.13.old/dselect/main.cc dpkg-1.4.1.13/dselect/main.cc
--- dpkg-1.4.1.13.old/dselect/main.cc	Sun Nov  1 11:04:37 1998
+++ dpkg-1.4.1.13/dselect/main.cc	Mon Oct 11 13:20:37 1999
@@ -96,6 +96,32 @@
        stdout)) werr("stdout");
 }
 
+#if CAN_RESIZE
+/*
+ * This uses functions that are "unsafe", but it seems to work on SunOS and
+ * Linux.  The 'wrefresh(curscr)' is needed to force the refresh to start from
+ * the top of the screen -- some xterms mangle the bitmap while resizing.
+ *
+ * Borrowed from the ncurses example view.c
+ */
+static RETSIGTYPE adjust(int sig)
+{
+  if (waiting || sig == 0) {
+    struct winsize size;
+
+    if (ioctl(fileno(stdout), TIOCGWINSZ, &size) == 0) {
+      resizeterm(size.ws_row, size.ws_col);
+      wrefresh(curscr);       /* Linux needs this */
+      show_all();
+    }
+    interrupted = FALSE;
+  } else {
+    interrupted = TRUE;
+  }
+  (void) signal(SIGWINCH, adjust);        /* some systems need this */
+}
+#endif  /* CAN_RESIZE */
+
 /* These are called by C code, so need to have C calling convention */
 extern "C" {
 
@@ -279,6 +305,10 @@
 
 int main(int, const char *const *argv) {
   jmp_buf ejbuf;
+
+#if CAN_RESIZE
+  (void) signal(SIGWINCH, adjust); /* arrange interrupts to resize */
+#endif
 
   if (setjmp(ejbuf)) { /* expect warning about possible clobbering of argv */
     cursesoff();
diff -urN dpkg-1.4.1.13.old/dselect/pkglist.cc dpkg-1.4.1.13/dselect/pkglist.cc
--- dpkg-1.4.1.13.old/dselect/pkglist.cc	Sun Nov  1 11:04:54 1998
+++ dpkg-1.4.1.13/dselect/pkglist.cc	Mon Oct 11 13:17:18 1999
@@ -490,16 +490,22 @@
   setupsigwinch();
   startdisplay();
   displayhelp(helpmenulist(),'i');
 
   if (debug) fprintf(debug,"packagelist[%p]::display() entering loop\n",this);
   for (;;) {
+#if CAN_RESIZE
+    if (interrupted)
+      adjust(0);
+#endif
     if (whatinfo_height) wcursyncup(whatinfowin);
     if (doupdate() == ERR) ohshite("doupdate failed");
     signallist= this;
     if (sigprocmask(SIG_UNBLOCK,&sigwinchset,0)) ohshite("failed to unblock SIGWINCH");
     response= getch();
     if (sigprocmask(SIG_BLOCK,&sigwinchset,0)) ohshite("failed to re-block SIGWINCH");
+#if CAN_RESIZE
     if (response == ERR) ohshite("getch failed");
+#endif
     interp= (*bindings)(response);
     if (debug)
       fprintf(debug,"packagelist[%p]::display() response=%d interp=%s\n",

Attachment: pgpeD_UNbTnQz.pgp
Description: PGP signature


Reply to: