*/
void resize_screen (void)
{
+ /* V6 games are asked to redraw. Other versions have no means for that
+ so we do what we can. */
+ if (h_version == V6)
+ h_flags |= REFRESH_FLAG;
+ else {
+ int scroll;
- if (h_version != V6) {
wp[0].x_size = h_screen_width;
if (wp[0].x_cursor > h_screen_width)
wp[0].x_cursor = h_screen_width;
if (wp[7].x_cursor > h_screen_width)
wp[7].x_cursor = h_screen_width;
- /*XXX This needs to be in sync with unix_resize_display. */
+ /*TODO What if this becomes negative? */
wp[0].y_size = h_screen_height - wp[1].y_size - wp[7].y_size;
- if (wp[0].y_cursor > wp[0].y_size)
+ scroll = wp[0].y_cursor - wp[0].y_size;
+ if (scroll > 0) {
wp[0].y_cursor = wp[0].y_size;
+ os_repaint_window(0, wp[0].y_pos + scroll, wp[0].y_pos,
+ wp[0].x_pos, wp[0].y_size, wp[0].x_size);
+ }
}
}/* resize_screen */
}/* os_scroll_area */
-/*
- * unix_resize_display
- *
- * Resize the display and redraw.
- *
+/**
+ * Resize the display and redraw. Retain the old screen starting from the
+ * top left. Call resize_screen, which may repaint more accurately.
*/
void unix_resize_display(void)
{
- int x, y, start = 0,
- lines = h_screen_rows, cols = h_screen_cols;
-
- if ((saved_screen = newpad(lines, cols))
+ if ((saved_screen = newpad(h_screen_rows, h_screen_cols))
&& overwrite(stdscr, saved_screen) == ERR) {
delwin(saved_screen);
saved_screen = NULL;
}
- getyx(stdscr, y, x);
+ if (saved_screen) {
+ int y, x;
+ getyx(stdscr, y, x);
+ wmove(saved_screen, y, x);
+ }
endwin();
refresh();
unix_get_terminal_size();
- if (lines > h_screen_rows) {
- lines = h_screen_rows;
- if (y >= h_screen_rows) {
- /* Lose some topmost lines to keep the cursor on screen. */
- start = y + 1 - h_screen_rows;
- y = h_screen_rows - 1;
- }
- }
- if (cols > h_screen_cols)
- cols = h_screen_cols;
- if (x >= h_screen_cols)
- x = h_screen_cols - 1;
- if (saved_screen)
- copywin(saved_screen, stdscr, start, 0, 0, 0,
- lines - 1, cols - 1, FALSE);
- move(y, x);
- refresh();
-
- /* Notify the game that the display needs refreshing */
- if (h_version == V6)
- h_flags |= REFRESH_FLAG;
+ resize_screen();
if (zmp != NULL) {
- resize_screen();
restart_header();
}
if (saved_screen) {
saved_screen = NULL;
}
}/* unix_redraw_display */
+
+
+/**
+ * Repaint a window.
+ *
+ * This can only be called from resize_screen. It copies part of the screen
+ * as it was before the resize onto the current screen. The source and
+ * destination rectangles may start at different rows but the columns
+ * are the same. Positions are 1-based. win should be the index
+ * of the window that is being repainted. If it equals the current window,
+ * the saved cursor position adjusted by ypos_new - ypos_old is also restored.
+ *
+ * The copied rectangle is clipped to the saved window size. Returns true
+ * on success, false if anything went wrong.
+ */
+bool os_repaint_window(int win, int ypos_old, int ypos_new, int xpos,
+ int ysize, int xsize)
+{
+ int lines, cols;
+ if (!saved_screen)
+ return false;
+ getmaxyx(saved_screen, lines, cols);
+ ypos_old--, ypos_new--, xpos--;
+ if (xpos + xsize > cols)
+ xsize = cols - xpos;
+ if (ypos_old + ysize > lines)
+ ysize = lines - ypos_old;
+ /* Most of the time we are in os_read_line, where the cursor position
+ is different from that in the window properties. So use the real cursor
+ position. */
+ if (win == cwin) {
+ int y, x;
+ getyx(saved_screen, y, x);
+ y += ypos_new - ypos_old;
+ if (y >= ypos_new && y< ypos_new + ysize
+ && x >= xpos && x < xpos + xsize)
+ move(y, x);
+ }
+ if (xsize <= 0 || ysize <= 0)
+ return false;
+ return copywin(saved_screen, stdscr, ypos_old, xpos, ypos_new, xpos,
+ ypos_new + ysize - 1, xpos + xsize - 1, FALSE) != ERR;
+}