#include #include #include #include namespace raleigh { entry::entry(uint32_t rows, uint32_t cols, const char *default_text, const char *font, _pixel_t bg, _pixel_t fg, _pixel_t border_color) : rows(rows), cols(cols), bg(bg), fg(fg), border_color(border_color), fi(get_font(font)), data(new char[rows * cols]), line_indices(new uint32_t[rows + 1]), first_paint(true) { size = coord(fi->space_width * (cols - 1) + fi->char_width + 6, fi->space_height * (rows - 1) + fi->char_height + 6); closest_opaque = this; end_x = 0; end_y = 0; line_indices[0] = 0; for (end_d = 0; default_text[end_d]; ++end_d) { if (end_d == rows * cols - 1) break; data[end_d] = default_text[end_d]; if ((default_text[end_d] == '\n') || (++end_x == cols)) { if (end_y == rows - 1) break; line_indices[++end_y] = end_d + 1; end_x = 0; } } line_indices[end_y + 1] = end_d; cur_x = end_x; cur_y = end_y; cur_d = end_d; data[end_d] = '\0'; } void entry::notify_window_change() {} void entry::paint_text(_pixel_t *pixbuf, uint32_t pitch) { uint32_t y = 0; uint32_t x = -1; for (const char *i = data; *i; ++i) { if (*i == '\n') { ++y; x = -1; } else { if (++x == cols) { ++y; x = 0; } put_char_no_bg(fi, *i, pixbuf + (window_offset.y + 3 + y * fi->space_height) * pitch + (window_offset.x + 3 + x * fi->space_width), pitch, fg); } } } void entry::paint(_pixel_t *pixbuf, uint32_t pitch) { _pixel_t *const cur_ptr = pixbuf + (window_offset.y + 3 + cur_y * fi->space_height) * pitch + (window_offset.x + 3 + cur_x * fi->space_width); _pixel_t *const old_cur_ptr = pixbuf + (window_offset.y + 3 + cur_y_last_paint * fi->space_height) * pitch + (window_offset.x + 3 + cur_x_last_paint * fi->space_width); if (first_paint) { for (uint32_t x = 0; x < size.x; ++x) { pixbuf[(window_offset.y) * pitch + window_offset.x + x] = border_color; pixbuf[(window_offset.y + size.y - 1) * pitch + window_offset.x + x] = border_color; } for (uint32_t y = 1; y < size.y - 1; ++y) { pixbuf[(window_offset.y + y) * pitch + window_offset.x] = border_color; pixbuf[(window_offset.y + y) * pitch + window_offset.x + size.x - 1] = border_color; } for (uint32_t y = 1; y < size.y - 1; ++y) for (uint32_t x = 1; x < size.x - 1; ++x) pixbuf[(window_offset.y + y) * pitch + (window_offset.x + x)] = bg; paint_text(pixbuf, pitch); first_paint = false; } else if (text_changed_since_last_paint) { for (uint32_t y = 3; y < size.y - 3; ++y) for (uint32_t x = 3; x < size.x - 3; ++x) pixbuf[(window_offset.y + y) * pitch + (window_offset.x + x)] = bg; paint_text(pixbuf, pitch); text_changed_since_last_paint = false; } else { for (uint32_t y = 0; y < fi->char_height; ++y) { old_cur_ptr[y * pitch] = bg; old_cur_ptr[y * pitch + 1] = bg; } if (data[cur_d_last_paint] && (data[cur_d_last_paint] != '\n')) put_char_no_bg(fi, data[cur_d_last_paint], old_cur_ptr, pitch, fg); } for (uint32_t y = 0; y < fi->char_height; ++y) { cur_ptr[y * pitch] = fg; cur_ptr[y * pitch + 1] = fg; } cur_y_last_paint = cur_y; cur_x_last_paint = cur_x; cur_d_last_paint = cur_d; } bool entry::try_handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up) { if (up || (click_type != mouse_packet::LEFT)) return false; if (window_coords.x - window_offset.x < 3) window_coords.x = 3 + window_offset.x; else if (window_coords.x - window_offset.x > size.x - 4) window_coords.x = size.x - 4 + window_offset.x; if (window_coords.y - window_offset.y < 3) window_coords.y = 3 + window_offset.y; else if (window_coords.y - window_offset.y > size.y - 4) window_coords.y = size.y - 4 + window_offset.y; cur_y = (window_coords.y - window_offset.y - 3) / fi->space_height; cur_x = (window_coords.x - window_offset.x - 3) / fi->space_width; if (cur_y > end_y) { cur_y = end_y; cur_x = end_x; } cur_d = line_indices[cur_y] + cur_x; if (cur_d >= line_indices[cur_y + 1]) { cur_d = line_indices[cur_y + 1] - 1; if (data[cur_d] != '\n') ++cur_d; cur_x = cur_d - line_indices[cur_y]; } w->notify_needs_paint(*this); return true; } void entry::notify_has_opaque_parent(widget *parent) {} }