diff --git a/include/QF/console.h b/include/QF/console.h index 0b2cea79c..0142eb06e 100644 --- a/include/QF/console.h +++ b/include/QF/console.h @@ -61,6 +61,20 @@ typedef struct inputline_s void (*draw)(struct inputline_s *); // draw input line to screen } inputline_t; +typedef struct { + byte *text; + size_t len; +} con_line_t; + +typedef struct { + byte *buffer; + size_t buffer_size; + con_line_t *lines; + int max_lines; // size of lines array + int num_lines; // number of lines used + int cur_line; // current line +} con_buffer_t; + extern old_console_t con_main; extern old_console_t con_chat; extern old_console_t *con; // point to either con_main or con_chat @@ -75,7 +89,6 @@ extern int con_notifylines; // scan lines to clear for notify lines void Con_DrawCharacter (int cx, int line, int num); void Con_CheckResize (void); -void Con_ProcessInputLine (inputline_t *il, int ch); void Con_DrawConsole (int lines); void Con_DrawDownload (int lines); @@ -100,6 +113,12 @@ void Con_DisplayList(const char **list, int con_linewidth); inputline_t *Con_CreateInputLine (int lines, int width, char prompt); void Con_DestroyInputLine (inputline_t *inputline); +void Con_ProcessInputLine (inputline_t *il, int ch); + +con_buffer_t *Con_CreateBuffer (size_t buffer_size, int max_lines); +void Con_DestroyBuffer (con_buffer_t *buffer); +void Con_BufferAddText (con_buffer_t *buf, const char *text); +#define Con_BufferLine(b,l) ((b)->lines + ((l) + (b)->max_lines) % (b)->max_lines) // init/shutdown functions void Con_Init (const char *plugin_name); diff --git a/libs/console/Makefile.am b/libs/console/Makefile.am index 267b78158..7412794fb 100644 --- a/libs/console/Makefile.am +++ b/libs/console/Makefile.am @@ -3,7 +3,7 @@ INCLUDES= -I$(top_srcdir)/include lib_LTLIBRARIES= libQFconsole.la plugin_LTLIBRARIES= libconsole_server.la #libconsole_client.la -common_sources= complete.c console.c inputline.c list.c +common_sources= buffer.c complete.c console.c inputline.c list.c client_sources= client.c server_sources= server.c diff --git a/libs/console/buffer.c b/libs/console/buffer.c new file mode 100644 index 000000000..a1192a2a3 --- /dev/null +++ b/libs/console/buffer.c @@ -0,0 +1,122 @@ +/* + buffer.c + + console buffer support + + Copyright (C) 2001 BillCurrie + + Author: BillCurrie + Date: 2001/09/28 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +static const char rcsid[] = + "$Id$"; + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include "string.h" +#endif +#ifdef HAVE_STRINGS_H +# include "strings.h" +#endif + +#include + +#include "QF/console.h" + +con_buffer_t * +Con_CreateBuffer (size_t buffer_size, int max_lines) +{ + con_buffer_t *buffer; + + if (!(buffer = malloc (sizeof (con_buffer_t)))) + return 0; + if (!(buffer->buffer = malloc (buffer_size))) + goto err; + buffer->buffer_size = buffer_size; + if (!(buffer->lines = calloc (max_lines, sizeof (con_line_t)))) + goto err; + buffer->max_lines = max_lines; + buffer->num_lines = 1; + buffer->cur_line = 0; + buffer->lines[0].text = buffer->buffer; + return buffer; +err: + if (buffer->buffer) + free (buffer->buffer); + free (buffer); + return 0; +} + +void +Con_DestroyBuffer (con_buffer_t *buffer) +{ + free (buffer->buffer); + free (buffer->lines); + free (buffer); +} + +void +Con_BufferAddText (con_buffer_t *buf, const char *text) +{ + con_line_t *cur_line = &buf->lines[buf->cur_line]; + con_line_t *tail_line; + size_t len = strlen (text); + byte *pos = cur_line->text + cur_line->len; + + if (pos >= buf->buffer + buf->buffer_size) + pos -= buf->buffer_size; + tail_line = buf->lines + (buf->cur_line + buf->max_lines + 1 + - buf->num_lines) % buf->max_lines; + if (len > buf->buffer_size) { + text += len - buf->buffer_size; + len = buf->buffer_size; + } + while (len--) { + byte c = *pos++ = *text++; + if (pos - buf->buffer >= buf->buffer_size) + pos = buf->buffer; + cur_line->len++; + if (c == '\n') { + if (buf->num_lines < buf->max_lines) + buf->num_lines++; + cur_line++; + buf->cur_line++; + if (cur_line - buf->lines >= buf->max_lines) + cur_line = buf->lines; + cur_line->text = pos; + cur_line->len = 0; + } + if (pos == tail_line->text) { + if (buf->num_lines > 0) + buf->num_lines--; + tail_line->text = 0; + tail_line->len = 0; + tail_line++; + if (tail_line - buf->lines >= buf->max_lines) + tail_line = buf->lines; + } + } + buf->cur_line %= buf->max_lines; +} diff --git a/libs/console/console.c b/libs/console/console.c index e5d1120b2..1979207d4 100644 --- a/libs/console/console.c +++ b/libs/console/console.c @@ -46,6 +46,7 @@ int con_linewidth; // characters across screen static plugin_t *con_module; +static con_buffer_t *(*const buffer) (size_t, int) = Con_CreateBuffer; static void (*const complete)(inputline_t *) = Con_BasicCompleteCommandLine; static inputline_t *(*const create)(int, int, char) = Con_CreateInputLine; static void (*const display)(const char **, int) = Con_DisplayList; diff --git a/libs/console/server.c b/libs/console/server.c index 14fe965b9..193502685 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -79,6 +79,10 @@ static int interrupted; #define MAXCMDLINE 256 static inputline_t *input_line; +#define BUFFER_SIZE 32768 +#define MAX_LINES 1024 +static con_buffer_t *output_buffer; + static chtype attr_table[4] = { A_NORMAL, COLOR_PAIR(1), @@ -117,6 +121,44 @@ C_ExecLine (const char *line) static void C_DrawOutput (void) { + // this is not the most efficient way to update the screen, but oh well + int lines = screen_y - 3; // leave a blank line + int width = screen_x; + int cur_line = output_buffer->cur_line; + int i; + + if (lines < 1) + return; + + for (i = 0; i < lines; i++) { + con_line_t *l = Con_BufferLine (output_buffer, cur_line - i); + if (!l->text) { + i--; + break; + } + i += l->len / width; // really dumb line wrap algo :) + } + cur_line -= min (i, lines); + i -= lines; + wmove (output, 0, 0); + do { + con_line_t *l = Con_BufferLine (output_buffer, cur_line++); + byte *text = l->text; + int len = l->len; + + if (i > 0) { + text += i * width; + len -= i * width; + i = 0; + } + while (len--) { + chtype ch = *text++; + ch = sys_char_map[ch] | attr_table[attr_map[ch]]; + waddch (output, ch); + } + } while (cur_line < output_buffer->cur_line); + //wrefresh (stdscr); + wrefresh (output); } static void @@ -197,7 +239,7 @@ C_Init (void) init_pair (4, COLOR_YELLOW, COLOR_BLUE); init_pair (5, COLOR_CYAN, COLOR_BLACK); - scrollok (output, TRUE); + scrollok (output, FALSE); leaveok (output, TRUE); scrollok (status, FALSE); @@ -217,6 +259,8 @@ C_Init (void) wrefresh (status); wrefresh (input); + output_buffer = Con_CreateBuffer (BUFFER_SIZE, MAX_LINES); + input_line = Con_CreateInputLine (16, MAXCMDLINE, ']'); input_line->complete = Con_BasicCompleteCommandLine; input_line->enter = C_ExecLine; @@ -264,17 +308,9 @@ C_Print (const char *fmt, va_list args) txt = buffer; #ifdef HAVE_CURSES_H if (use_curses) { - chtype ch; - - txt = buffer; - - while ((ch = (byte)*txt++)) { - ch = sys_char_map[ch] | attr_table[attr_map[ch]]; - waddch (output, ch); - } - touchwin (stdscr); - wrefresh (output); - wrefresh (input); + Con_BufferAddText (output_buffer, buffer); + C_DrawOutput (); + wrefresh (input); // move the screen cursor back to the input line } else #endif {