diff options
author | 2007-12-17 15:19:59 +0000 | |
---|---|---|
committer | 2007-12-17 15:19:59 +0000 | |
commit | 7b77f1218624ea26dbb2efd85a19f795f5d4e02e (patch) | |
tree | 19209304095572b4fd61c2a2d6a5aa75c4e471ad /src/emu/debug/textbuf.c | |
parent | 3da7f476068b3ffef713218ba2fc1bd5030f2c38 (diff) |
Initial checkin of MAME 0.121.mame0121
Diffstat (limited to 'src/emu/debug/textbuf.c')
-rw-r--r-- | src/emu/debug/textbuf.c | 326 |
1 files changed, 326 insertions, 0 deletions
diff --git a/src/emu/debug/textbuf.c b/src/emu/debug/textbuf.c new file mode 100644 index 00000000000..25e7dacd9f5 --- /dev/null +++ b/src/emu/debug/textbuf.c @@ -0,0 +1,326 @@ +/*************************************************************************** + + textbuf.c + + Debugger text buffering engine. + + Copyright (c) 1996-2007, Nicola Salmoria and the MAME Team. + Visit http://mamedev.org for licensing and usage restrictions. + +***************************************************************************/ + +#include "mamecore.h" +#include "textbuf.h" + + + +/*************************************************************************** + CONSTANTS +***************************************************************************/ + +#define MAX_LINE_LENGTH 250 + + + +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ + +/* typedef struct _text_buffer text_buffer; -- declared in textbuf.h */ +struct _text_buffer +{ + char * buffer; + INT32 * lineoffs; + INT32 bufsize; + INT32 bufstart; + INT32 bufend; + INT32 linesize; + INT32 linestart; + INT32 lineend; + UINT32 linestartseq; + INT32 maxwidth; +}; + + + +/*************************************************************************** + INLINE FUNCTIONS +***************************************************************************/ + +/*------------------------------------------------- + buffer_used - return the number of bytes + currently held in the buffer +-------------------------------------------------*/ + +INLINE INT32 buffer_used(text_buffer *text) +{ + INT32 used = text->bufend - text->bufstart; + if (used < 0) + used += text->bufsize; + return used; +} + + +/*------------------------------------------------- + buffer_space - return the number of bytes + available in the buffer +-------------------------------------------------*/ + +INLINE INT32 buffer_space(text_buffer *text) +{ + return text->bufsize - buffer_used(text); +} + + + +/*************************************************************************** + + Buffer object management + +***************************************************************************/ + +/*------------------------------------------------- + text_buffer_alloc - allocate a new text buffer +-------------------------------------------------*/ + +text_buffer *text_buffer_alloc(UINT32 bytes, UINT32 lines) +{ + text_buffer *text; + + /* allocate memory for the text buffer object */ + text = malloc(sizeof(*text)); + if (!text) + return NULL; + + /* allocate memory for the buffer itself */ + text->buffer = malloc(bytes); + if (!text->buffer) + { + free(text); + return NULL; + } + + /* allocate memory for the lines array */ + text->lineoffs = malloc(lines * sizeof(text->lineoffs[0])); + if (!text->lineoffs) + { + free(text->buffer); + free(text); + return NULL; + } + + /* initialize the buffer description */ + text->bufsize = bytes; + text->linesize = lines; + text_buffer_clear(text); + + return text; +} + + +/*------------------------------------------------- + text_buffer_free - free a previously allocated + text buffer +-------------------------------------------------*/ + +void text_buffer_free(text_buffer *text) +{ + if (text->lineoffs) + free(text->lineoffs); + if (text->buffer) + free(text->buffer); + free(text); +} + + +/*------------------------------------------------- + text_buffer_clear - clear a text buffer +-------------------------------------------------*/ + +void text_buffer_clear(text_buffer *text) +{ + /* reset all the buffer pointers and other bits */ + text->bufstart = 0; + text->bufend = 0; + + text->linestart = 0; + text->lineend = 0; + text->linestartseq = 0; + + text->maxwidth = 0; + + /* create the initial line */ + text->lineoffs[0] = 0; + text->buffer[text->lineoffs[0]] = 0; +} + + + +/*************************************************************************** + + Adding data to the buffer + +***************************************************************************/ + +/*------------------------------------------------- + text_buffer_print - print data to the text + buffer +-------------------------------------------------*/ + +void text_buffer_print(text_buffer *text, const char *data) +{ + text_buffer_print_wrap(text, data, 10000); +} + + +/*------------------------------------------------- + text_buffer_print_wrap - print data to the + text buffer with word wrapping to a given + column +-------------------------------------------------*/ + +void text_buffer_print_wrap(text_buffer *text, const char *data, int wrapcol) +{ + INT32 stopcol = (wrapcol < MAX_LINE_LENGTH) ? wrapcol : MAX_LINE_LENGTH; + INT32 needed_space; + + /* we need to ensure there is enough space for this string plus enough for the max line length */ + needed_space = (INT32)strlen(data) + MAX_LINE_LENGTH; + + /* make space in the buffer if we need to */ + while (buffer_space(text) < needed_space && text->linestart != text->lineend) + { + text->linestartseq++; + if (++text->linestart >= text->linesize) + text->linestart = 0; + text->bufstart = text->lineoffs[text->linestart]; + } + + /* now add the data */ + for ( ; *data; data++) + { + int ch = *data; + int linelen; + + /* a CR resets our position */ + if (ch == '\r') + text->bufend = text->lineoffs[text->lineend]; + + /* non-CR data is just characters */ + else if (ch != '\n') + text->buffer[text->bufend++] = ch; + + /* an explicit newline or line-too-long condition inserts a newline */ + linelen = text->bufend - text->lineoffs[text->lineend]; + if (ch == '\n' || linelen >= stopcol) + { + int overflow = 0; + + /* if we're wrapping, back off until we hit a space */ + if (linelen >= wrapcol) + { + /* scan backwards, removing characters along the way */ + overflow = 1; + while (overflow < linelen && text->buffer[text->bufend - overflow] != ' ') + overflow++; + + /* if we found a space, take it; otherwise, reset and pretend we didn't try */ + if (overflow < linelen) + linelen -= overflow; + else + overflow = 0; + } + + /* did we beat the max width */ + if (linelen > text->maxwidth) + text->maxwidth = linelen; + + /* append a terminator */ + if (overflow == 0) + text->buffer[text->bufend++] = 0; + else + text->buffer[text->bufend - overflow] = 0; + + /* determine what the next line will be */ + if (++text->lineend >= text->linesize) + text->lineend = 0; + + /* if we're out of lines, consume the next one */ + if (text->lineend == text->linestart) + { + text->linestartseq++; + if (++text->linestart >= text->linesize) + text->linestart = 0; + text->bufstart = text->lineoffs[text->linestart]; + } + + /* if we don't have enough room in the buffer for a max line, wrap to the start */ + if (text->bufend + MAX_LINE_LENGTH + 1 >= text->bufsize) + text->bufend = 0; + + /* create a new empty line */ + text->lineoffs[text->lineend] = text->bufend - (overflow ? (overflow - 1) : 0); + } + } + + /* NULL terminate what we have on this line */ + text->buffer[text->bufend] = 0; +} + + + +/*************************************************************************** + + Reading data from the buffer + +***************************************************************************/ + +/*------------------------------------------------- + text_buffer_max_width - return the maximum + width of all lines seen so far +-------------------------------------------------*/ + +UINT32 text_buffer_max_width(text_buffer *text) +{ + return text->maxwidth; +} + + +/*------------------------------------------------- + text_buffer_num_lines - return the number of + lines in the text buffer +-------------------------------------------------*/ + +UINT32 text_buffer_num_lines(text_buffer *text) +{ + INT32 lines = text->lineend + 1 - text->linestart; + if (lines <= 0) + lines += text->linesize; + return lines; +} + + +/*------------------------------------------------- + text_buffer_line_index_to_seqnum - convert a + line index into a sequence number +-------------------------------------------------*/ + +UINT32 text_buffer_line_index_to_seqnum(text_buffer *text, UINT32 index) +{ + return text->linestartseq + index; +} + + +/*------------------------------------------------- + text_buffer_get_seqnum_line - get a pointer to + an indexed line in the buffer +-------------------------------------------------*/ + +const char *text_buffer_get_seqnum_line(text_buffer *text, UINT32 seqnum) +{ + UINT32 numlines = text_buffer_num_lines(text); + UINT32 index = seqnum - text->linestartseq; + if (index >= numlines) + return NULL; + return &text->buffer[text->lineoffs[(text->linestart + index) % text->linesize]]; +} |