static TEXT_CHUNK_REC *create_text_chunk(GUI_WINDOW_REC *gui) { TEXT_CHUNK_REC *rec; char *buffer, *ptr; g_return_val_if_fail(gui != NULL, NULL); rec = g_new(TEXT_CHUNK_REC, 1); rec->overflow[0] = 0; rec->overflow[1] = (char) LINE_CMD_OVERFLOW; rec->pos = 0; rec->lines = 0; if (gui->cur_line != NULL && gui->cur_line->text != NULL) { /* create a link to new block from the old block */ buffer = gui->cur_text->buffer + gui->cur_text->pos; *buffer++ = 0; *buffer++ = (char) LINE_CMD_CONTINUE; ptr = rec->buffer; memcpy(buffer, &ptr, sizeof(char *)); } else { /* just to be safe */ mark_temp_eol(rec); } gui->cur_text = rec; gui->text_chunks = g_slist_append(gui->text_chunks, rec); return rec; }
static TEXT_CHUNK_REC *text_chunk_create(TEXT_BUFFER_REC *buffer) { TEXT_CHUNK_REC *rec; unsigned char *buf, *ptr, **pptr; rec = g_slice_new(TEXT_CHUNK_REC); rec->pos = 0; rec->refcount = 0; if (buffer->cur_line != NULL && buffer->cur_line->text != NULL) { /* create a link to new block from the old block */ buf = buffer->cur_text->buffer + buffer->cur_text->pos; *buf++ = 0; *buf++ = (char) LINE_CMD_CONTINUE; /* we want to store pointer to beginning of the new text block to char* buffer. this probably isn't ANSI-C compatible, and trying this without the pptr variable breaks at least NetBSD/Alpha, so don't go "optimize" it :) */ ptr = rec->buffer; pptr = &ptr; memcpy(buf, pptr, sizeof(unsigned char *)); } else { /* just to be safe */ mark_temp_eol(rec); } buffer->cur_text = rec; buffer->text_chunks = g_slist_append(buffer->text_chunks, rec); return rec; }
static void text_chunk_append(TEXT_BUFFER_REC *buffer, const unsigned char *data, int len) { TEXT_CHUNK_REC *chunk; int left; if (len == 0) return; chunk = buffer->cur_text; while (chunk->pos + len >= TEXT_CHUNK_USABLE_SIZE) { left = TEXT_CHUNK_USABLE_SIZE - chunk->pos; if (left > 0 && data[left-1] == 0) left--; /* don't split the commands */ memcpy(chunk->buffer + chunk->pos, data, left); chunk->pos += left; chunk = text_chunk_create(buffer); chunk->refcount++; len -= left; data += left; } memcpy(chunk->buffer + chunk->pos, data, len); chunk->pos += len; mark_temp_eol(chunk); }
static LINE_REC *create_line(GUI_WINDOW_REC *gui, int level) { LINE_REC *rec; g_return_val_if_fail(gui != NULL, NULL); g_return_val_if_fail(gui->cur_text != NULL, NULL); rec = g_mem_chunk_alloc(gui->line_chunk); rec->text = gui->cur_text->buffer+gui->cur_text->pos; rec->level = GPOINTER_TO_INT(level); rec->time = time(NULL); mark_temp_eol(gui->cur_text); gui->cur_text->lines++; gui->last_color = -1; gui->last_flags = 0; if (gui->temp_line != NULL) { int pos = g_list_index(gui->lines, gui->temp_line); gui->lines = g_list_insert(gui->lines, rec, pos+1); gui->temp_line = rec; } else { gui->cur_line = rec; gui->lines = g_list_append(gui->lines, rec); if (gui->startline == NULL) { /* first line */ gui->startline = gui->lines; gui->bottom_startline = gui->lines; } } return rec; }
static void text_chunk_append(TEXT_BUFFER_REC *buffer, const unsigned char *data, int len) { TEXT_CHUNK_REC *chunk; int left; int i; if (len == 0) return; chunk = buffer->cur_text; while (chunk->pos + len >= TEXT_CHUNK_USABLE_SIZE) { left = TEXT_CHUNK_USABLE_SIZE - chunk->pos; /* don't split utf-8 character. (assume we can split non-utf8 anywhere.) */ if (left < len && !is_utf8_leading(data[left])) { int i; for (i = 1; i < 4 && left >= i; i++) if (is_utf8_leading(data[left - i])) { left -= i; break; } } for (i = 5; i > 0; --i) { if (left >= i && data[left-i] == 0) { left -= i; /* don't split the commands */ break; } } memcpy(chunk->buffer + chunk->pos, data, left); chunk->pos += left; chunk = text_chunk_create(buffer); chunk->refcount++; len -= left; data += left; } memcpy(chunk->buffer + chunk->pos, data, len); chunk->pos += len; mark_temp_eol(chunk); }
static LINE_REC *create_line(GUI_WINDOW_REC *gui, int level) { g_return_val_if_fail(gui != NULL, NULL); g_return_val_if_fail(gui->cur_text != NULL, NULL); gui->cur_line = g_mem_chunk_alloc(gui->line_chunk); gui->cur_line->text = gui->cur_text->buffer+gui->cur_text->pos; gui->cur_line->level = GPOINTER_TO_INT(level); gui->cur_line->time = time(NULL); mark_temp_eol(gui->cur_text); gui->last_color = -1; gui->last_flags = 0; gui->lines = g_list_append(gui->lines, gui->cur_line); if (gui->startline == NULL) { /* first line */ gui->startline = gui->lines; gui->bottom_startline = gui->lines; } return gui->cur_line; }
static void gui_printtext(WINDOW_REC *window, gpointer fgcolor, gpointer bgcolor, gpointer pflags, char *str, gpointer level) { GUI_WINDOW_REC *gui; LINE_REC *line; int fg, bg, flags, new_lines, n, visible, ypos, subline; g_return_if_fail(window != NULL); remove_old_lines(window); gui = WINDOW_GUI(window); visible = is_window_visible(window) && gui->bottom; flags = GPOINTER_TO_INT(pflags); fg = GPOINTER_TO_INT(fgcolor); bg = GPOINTER_TO_INT(bgcolor); if (gui->cur_text == NULL) create_text_chunk(gui); /* \n can be only at the start of the line.. */ if (*str == '\n') { str++; linebuf_add(gui, "\0\x80", 2); /* mark EOL */ line = create_line(gui, 0); gui_window_newline(gui, visible); gui->cur_text->lines++; gui->last_subline = 0; } else { line = gui->cur_line != NULL ? gui->cur_line : create_line(gui, 0); if (line->level == 0) line->level = GPOINTER_TO_INT(level); } get_colors(flags, &fg, &bg); line_add_colors(gui, fg, bg, flags); linebuf_add(gui, str, strlen(str)); mark_temp_eol(gui->cur_text); gui_window_cache_remove(gui, line); new_lines = gui_window_get_linecount(gui, line)-1 - gui->last_subline; for (n = 0; n < new_lines; n++) gui_window_newline(gui, visible); if (visible) { /* draw the line to screen. */ ypos = gui->ypos-new_lines; if (new_lines > 0) { set_color(0); move(gui->parent->first_line+ypos, 0); clrtoeol(); } if (ypos >= 0) subline = gui->last_subline; else { /* *LONG* line - longer than screen height */ subline = -ypos+gui->last_subline; ypos = 0; } ypos += gui->parent->first_line; gui_window_line_draw(gui, line, ypos, subline, -1); } gui->last_subline += new_lines; }
static void sig_gui_print_text(WINDOW_REC *window, void *fgcolor, void *bgcolor, void *pflags, char *str, void *level) { GUI_WINDOW_REC *gui; LINE_REC *line; int fg, bg, flags, new_lines, n, visible, ypos, subline; flags = GPOINTER_TO_INT(pflags); fg = GPOINTER_TO_INT(fgcolor); bg = GPOINTER_TO_INT(bgcolor); get_colors(flags, &fg, &bg); if (window == NULL && next_xpos != -1) { wmove(stdscr, next_ypos, next_xpos); set_color(stdscr, fg | (bg << 4)); addstr(str); next_xpos += strlen(str); return; } g_return_if_fail(window != NULL); gui = WINDOW_GUI(window); visible = is_window_visible(window) && gui->bottom; if (gui->cur_text == NULL) create_text_chunk(gui); /* newline can be only at the start of the line.. */ if (flags & PRINTFLAG_NEWLINE) { remove_old_lines(window); if (!gui->eol_marked) { if (format->len > 0 || gui->temp_line != NULL) { /* mark format continuing to next line */ char tmp[2] = { 0, (char)LINE_CMD_FORMAT_CONT }; linebuf_add(gui, tmp, 2); } linebuf_add(gui, "\0\200", 2); /* mark EOL */ } gui->eol_marked = FALSE; line = create_line(gui, 0); if (gui->temp_line == NULL || g_list_find(gui->startline, gui->temp_line) != NULL) gui_window_newline(gui, visible); gui->last_subline = 0; } else { line = gui->temp_line != NULL ? gui->temp_line : gui->cur_line != NULL ? gui->cur_line : create_line(gui, 0); if (line->level == 0) line->level = GPOINTER_TO_INT(level); } line_add_colors(gui, fg, bg, flags); linebuf_add(gui, str, strlen(str)); mark_temp_eol(gui->cur_text); gui_window_cache_remove(gui, line); if (gui->temp_line != NULL) { /* updating existing line - don't even try to print it to screen */ return; } new_lines = gui_window_get_linecount(gui, line)-1 - gui->last_subline; for (n = 0; n < new_lines; n++) gui_window_newline(gui, visible); if (visible) { /* draw the line to screen. */ ypos = gui->ypos-new_lines; if (new_lines > 0) { #ifdef USE_CURSES_WINDOWS set_color(gui->parent->curses_win, 0); wmove(gui->parent->curses_win, ypos, 0); wclrtoeol(gui->parent->curses_win); #else set_color(stdscr, 0); move(ypos + gui->parent->first_line, 0); wclrtoeol(stdscr); #endif } if (ypos >= 0) subline = gui->last_subline; else { /* *LONG* line - longer than screen height */ subline = -ypos+gui->last_subline; ypos = 0; } gui_window_line_draw(gui, line, ypos, subline, -1); } gui->last_subline += new_lines; }
void gui_window_line_append(GUI_WINDOW_REC *gui, const char *str, int len) { linebuf_add(gui, str, len); mark_temp_eol(gui->cur_text); }