diff --git a/Applications/Terminal/Terminal.cpp b/Applications/Terminal/Terminal.cpp index 52130340a1..9407fdba06 100644 --- a/Applications/Terminal/Terminal.cpp +++ b/Applications/Terminal/Terminal.cpp @@ -13,6 +13,7 @@ #include #include #include +#include //#define TERMINAL_DEBUG @@ -45,21 +46,6 @@ Terminal::Terminal(int ptm_fd) m_line_height = font().glyph_height() + m_line_spacing; set_size(80, 25); - m_horizontal_tabs = static_cast(malloc(columns())); - for (unsigned i = 0; i < columns(); ++i) - m_horizontal_tabs[i] = (i % 8) == 0; - // Rightmost column is always last tab on line. - m_horizontal_tabs[columns() - 1] = 1; - - m_lines = new Line*[rows()]; - for (size_t i = 0; i < rows(); ++i) - m_lines[i] = new Line(columns()); - - m_pixel_width = m_columns * font().glyph_width() + m_inset * 2; - m_pixel_height = (m_rows * (font().glyph_height() + m_line_spacing)) + (m_inset * 2) - m_line_spacing; - - set_size_policy(SizePolicy::Fixed, SizePolicy::Fixed); - set_preferred_size({ m_pixel_width, m_pixel_height }); } Terminal::Line::Line(word columns) @@ -596,8 +582,50 @@ void Terminal::unimplemented_xterm_escape() void Terminal::set_size(word columns, word rows) { + if (columns == m_columns && rows == m_rows) + return; + + if (m_lines) { + for (size_t i = 0; i < m_rows; ++i) + delete m_lines[i]; + delete m_lines; + } + m_columns = columns; m_rows = rows; + + m_cursor_row = 0; + m_cursor_column = 0; + m_saved_cursor_row = 0; + m_saved_cursor_column = 0; + + if (m_horizontal_tabs) + free(m_horizontal_tabs); + m_horizontal_tabs = static_cast(malloc(columns)); + for (unsigned i = 0; i < columns; ++i) + m_horizontal_tabs[i] = (i % 8) == 0; + // Rightmost column is always last tab on line. + m_horizontal_tabs[columns - 1] = 1; + + m_lines = new Line*[rows]; + for (size_t i = 0; i < rows; ++i) + m_lines[i] = new Line(columns); + + m_pixel_width = m_columns * font().glyph_width() + m_inset * 2; + m_pixel_height = (m_rows * (font().glyph_height() + m_line_spacing)) + (m_inset * 2) - m_line_spacing; + + set_size_policy(SizePolicy::Fixed, SizePolicy::Fixed); + set_preferred_size({ m_pixel_width, m_pixel_height }); + + m_rows_to_scroll_backing_store = 0; + m_needs_background_fill = true; + force_repaint(); + + winsize ws; + ws.ws_row = rows; + ws.ws_col = columns; + int rc = ioctl(m_ptm_fd, TIOCSWINSZ, &ws); + ASSERT(rc == 0); } Rect Terminal::glyph_rect(word row, word column) @@ -761,8 +789,9 @@ void Terminal::force_repaint() update(); } -void Terminal::resize_event(GResizeEvent&) +void Terminal::resize_event(GResizeEvent& event) { - m_needs_background_fill = true; - force_repaint(); + int new_columns = event.size().width() / m_font->glyph_width(); + int new_rows = event.size().height() / m_line_height; + set_size(new_columns, new_rows); } diff --git a/Kernel/MasterPTY.cpp b/Kernel/MasterPTY.cpp index 73428d2828..d6af396576 100644 --- a/Kernel/MasterPTY.cpp +++ b/Kernel/MasterPTY.cpp @@ -4,6 +4,7 @@ #include #include #include +#include MasterPTY::MasterPTY(unsigned index) : CharacterDevice(10, index) @@ -87,3 +88,10 @@ void MasterPTY::close() m_slave->hang_up(); } } + +int MasterPTY::ioctl(Process& process, unsigned request, unsigned arg) +{ + if (request == TIOCSWINSZ) + return m_slave->ioctl(process, request, arg); + return -EINVAL; +} diff --git a/Kernel/MasterPTY.h b/Kernel/MasterPTY.h index dfae451cd8..896f094bce 100644 --- a/Kernel/MasterPTY.h +++ b/Kernel/MasterPTY.h @@ -26,6 +26,7 @@ private: virtual bool can_write(Process&) const override; virtual void close() override; virtual bool is_master_pty() const override { return true; } + virtual int ioctl(Process&, unsigned request, unsigned arg) override; virtual const char* class_name() const override { return "MasterPTY"; } RetainPtr m_slave; diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 5e7416b4df..f0ae095cea 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -1868,6 +1868,7 @@ void Process::set_default_signal_dispositions() // FIXME: Set up all the right default actions. See signal(7). memset(&m_signal_action_data, 0, sizeof(m_signal_action_data)); m_signal_action_data[SIGCHLD].handler_or_sigaction = LinearAddress((dword)SIG_IGN); + m_signal_action_data[SIGWINCH].handler_or_sigaction = LinearAddress((dword)SIG_IGN); } int Process::sys$sigaction(int signum, const sigaction* act, sigaction* old_act) diff --git a/Kernel/TTY.cpp b/Kernel/TTY.cpp index df119bcf25..afa3b98cd8 100644 --- a/Kernel/TTY.cpp +++ b/Kernel/TTY.cpp @@ -112,8 +112,13 @@ int TTY::ioctl(Process& process, unsigned request, unsigned arg) termios* tp; winsize* ws; - if (process.tty() && process.tty() != this) +#if 0 + // FIXME: When should we block things? + // How do we make this work together with MasterPTY forwarding to us? + if (process.tty() && process.tty() != this) { return -ENOTTY; + } +#endif switch (request) { case TIOCGPGRP: return m_pgid; @@ -145,6 +150,16 @@ int TTY::ioctl(Process& process, unsigned request, unsigned arg) ws->ws_row = m_rows; ws->ws_col = m_columns; return 0; + case TIOCSWINSZ: + ws = reinterpret_cast(arg); + if (!process.validate_read(ws, sizeof(winsize))) + return -EFAULT; + if (ws->ws_col == m_columns && ws->ws_row == m_rows) + return 0; + m_rows = ws->ws_row; + m_columns = ws->ws_col; + generate_signal(SIGWINCH); + return 0; case TIOCSCTTY: process.set_tty(this); return 0; diff --git a/LibC/sys/ioctl_numbers.h b/LibC/sys/ioctl_numbers.h index 1ed0a9c934..85edc5dbfe 100644 --- a/LibC/sys/ioctl_numbers.h +++ b/LibC/sys/ioctl_numbers.h @@ -10,5 +10,6 @@ enum IOCtlNumber { TIOCGWINSZ, TIOCSCTTY, TIOCNOTTY, + TIOCSWINSZ, };