--- screen.C	2014-12-13 13:22:27.000000000 +0100
+++ /tmp/screen.C	2015-10-24 17:48:25.803878992 +0200
@@ -226,8 +226,10 @@
   if (nrow == 0)
     nrow = 24;
 
-  if (ncol == prev_ncol && nrow == prev_nrow)
-    return;
+  // (HACK)
+  // See the end of this function why this needs to be removed.
+  //if (ncol == prev_ncol && nrow == prev_nrow)
+    //return;
 
   // we need at least two lines for wrapping to work correctly
   while (nrow + saveLines < 2)
@@ -311,6 +313,13 @@
           // to come up with a lean and mean algorithm.
           // TODO: maybe optimise when width didn't change
 
+          // If we execute 'clear' for example, the cursor does not
+          // necessarily need to be at the bottom of the terminal if
+          // scrollback exists. We use this information here to fix up
+          // term_start and screen.cur.row later.
+          int notbottom = (int)prev_nrow - ((int)screen.cur.row+1);
+          int overlap = (int)nrow - ((int)screen.cur.row+1);
+
           row_col_t ocur = screen.cur;
           ocur.row = MOD (term_start + ocur.row, prev_total_rows);
 
@@ -388,17 +397,56 @@
           while (p != pend && q > 0);
 
           term_start = total_rows - nrow;
+          // If the cursor was not at the bottom of the terminal before, we
+          // need to fix some positions.
+          if (notbottom)
+            {
+              // If the cursor would not be overlapped by the border, then
+              // we restore the old position.
+              if (overlap > 0)
+                {
+                  int offset = (int)prev_nrow - (int)nrow;
+                  term_start -= offset;
+                  screen.cur.row += offset;
+                }
+
+              // If the cursor would be overlapped, then we put the cursor
+              // and the last used row at the bottom of the terminal.
+              if (overlap < 0)
+                {
+                  term_start -= (int)prev_nrow - (int)nrow + overlap;
+                  screen.cur.row = nrow;
+                }
+
+              // If overlap equals 0, then everything should be fine.
+            }
           top_row = q - term_start;
 
+          // See below.
+          int tmp = top_row;
+
           // make sure all terminal lines exist
           while (top_row > 0)
             scr_blank_screen_mem (ROW (--top_row), DEFAULT_RSTYLE);
+
+          // If no scrollback exists anymore after resizing we should make
+          // sure that the terminal output starts at the first row.
+          if (tmp > 0)
+            {
+              for (int row = 0; row < nrow-tmp; row++)
+                copy_line(row_buf[term_start+row], row_buf[term_start+row+tmp]);
+              for (int row = nrow-tmp; row < nrow; row++)
+                scr_blank_screen_mem(row_buf[term_start+row], DEFAULT_RSTYLE);
+              screen.cur.row -= tmp;
+            }
         }
       else
         {
           // if no scrollback exists (yet), wing, instead of wrap
 
-          for (int row = min (nrow, prev_nrow); row--; )
+          // We want all the previous rows. If there are too many to fit
+          // on the terminal, then we create scrollback (see below).
+          for (int row = prev_nrow; row--; )
             {
               line_t &src = prev_row_buf [MOD (term_start + row, prev_total_rows)];
               line_t &dst = row_buf [row];
@@ -409,7 +457,11 @@
           for (int row = prev_nrow; row < nrow; row++)
             scr_blank_screen_mem (row_buf [row], DEFAULT_RSTYLE);
 
-          term_start = 0;
+          // Prevent cutting off lines by creating scrollback.
+          if (nrow <= screen.cur.row)
+            scr_scroll_text(0, prev_nrow, screen.cur.row + 1 - nrow);
+          else
+            term_start = 0;
         }
 
       clamp_it (screen.cur.row, 0, nrow - 1);
@@ -439,6 +491,18 @@
   tt_winch ();
 
   HOOK_INVOKE ((this, HOOK_RESET, DT_END));
+
+  // (HACK)
+  // This is caused by the rewrapping logic. It sets term_start to
+  // saveLines. If no scrollback exists after rewrapping and the next call
+  // of scr_reset will create scrollback as explained above, then a bug
+  // will occur (no lines visible at all, most likely because of the
+  // large/invalid term_start value which scr_scroll_text cannot handle).
+  // To fix this, we call scr_reset again to handle everything and set
+  // term_start to 0. This is also why we shouldn't check if ncol and nrow
+  // have actually changed at the beginning of this function.
+  if (!top_row && term_start)
+    scr_reset();
 }
 
 void ecb_cold
