#include #include namespace raleigh { entry::entry(uint32_t rows, uint32_t cols, const char *default_text, const struct font_info *fi, _pixel_t bg, _pixel_t fg, _pixel_t border_color) : fi(fi), border_color(border_color), fg(fg), bg(bg), rows(rows), cols(cols), text_back(default_text, strlen(default_text) + 1), flower(text_back.buf, cols, rows) { size = coord(fi->space_width * (cols - 1) + fi->char_width + 6, fi->space_height * (rows - 1) + fi->char_height + 6);\ closest_opaque = this; } __attribute__ ((pure)) const char *entry::get_contents() { return text_back.buf; } void entry::set_contents(const char *s) { text_back.copy_from(s, strlen(s) + 1); on_text_change(); } void entry::paint(_pixel_t *pixbuf, uint32_t pitch) { if (next_paint_full) { for (uint32_t x = window_offset.x; x < window_offset.x + size.x; ++x) { pixbuf[window_offset.y * pitch + x] = border_color; pixbuf[(window_offset.y + size.y - 1) * pitch + x] = border_color; } for (uint32_t y = window_offset.y + 1; y < window_offset.y + size.y - 1; ++y) { pixbuf[y * pitch + window_offset.x] = border_color; pixbuf[y * pitch + window_offset.x + size.x - 1] = border_color; } for (uint32_t y = window_offset.y + 1; y < window_offset.y + size.y - 1; ++y) for (uint32_t x = window_offset.x + 1; x < window_offset.x + size.x - 1; ++x) pixbuf[y * pitch + x] = bg; } if (next_paint_full || text_change) { for (uint32_t y = window_offset.y + 3; y < window_offset.y + size.y - 3; ++y) for (uint32_t x = window_offset.x + 3; x < window_offset.x + size.x - 3; ++x) pixbuf[y * pitch + x] = bg; flower.draw_text(pixbuf + (window_offset.y + 3) * pitch + window_offset.x + 3, pitch, fi, fg); } else if ((cursor_change || !is_cur) && was_cur_before) { const uint32_t y_start = window_offset.y + 3 + fi->space_height * old_cur_y; const uint32_t x_start = window_offset.x + 3 + fi->space_width * old_cur_x; if (old_cur_x == cols) for (uint32_t y = y_start; y < y_start + fi->char_height; ++y) { pixbuf[y * pitch + x_start] = bg; pixbuf[y * pitch + x_start + 1] = bg; } else put_char(fi, flower.get_nth_line(old_cur_y)[old_cur_x], pixbuf + y_start * pitch + x_start, pitch, bg, fg); } if (is_cur) { const uint32_t y_start = window_offset.y + 3 + fi->space_height * cur_y; const uint32_t x_start = window_offset.x + 3 + fi->space_width * cur_x; if (old_cur_x == cols) for (uint32_t y = y_start; y < y_start + fi->char_height; ++y) { pixbuf[y * pitch + x_start] = fg; pixbuf[y * pitch + x_start + 1] = fg; } } next_paint_full = false; text_change = false; cursor_change = false; was_cur_before = is_cur; old_cur_x = cur_x; old_cur_y = cur_y; } void entry::notify_has_opaque_parent(widget *parent) {} void entry::handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up) { if (up || (click_type != mouse_packet::LEFT)) return; if (window_coords.x < window_offset.x) window_coords.x = window_offset.x; if (window_coords.y < window_offset.y) window_coords.y = window_offset.y; cur_x = (window_coords.x - window_offset.x) / fi->space_width; cur_y = (window_coords.y - window_offset.y) / fi->space_height; check_y(); check_x(); on_cursor_change(); } void entry::check_y() { if (cur_y >= flower.get_n_lines()) cur_y = flower.get_n_lines() - 1; } void entry::check_x() { if (cur_x > strlen(flower.get_nth_line(cur_y))) cur_x = strlen(flower.get_nth_line(cur_y)); } void entry::on_text_change() { flower.s = text_back.buf; flower.flow_text(); text_change = true; w->notify_needs_paint(*this); } void entry::on_cursor_change() { cursor_change = true; w->notify_needs_paint(*this); } void entry::handle_key(struct key_packet kp) { const uint32_t pos = flower.get_line_offset(cur_y) + cur_x; const char ch = key_to_char(kp); if (kp.key_id == kp.KEY_BSPACE) { if (pos) { text_back.remove(pos - 1); left(); on_text_change(); } } else if (kp.key_id == kp.KEY_DELETE) { if (pos != text_back.n_entries - 1) { text_back.remove(pos); on_text_change(); } } else if (kp.key_id == kp.KEY_LEFT_ARROW) left(); else if (kp.key_id == kp.KEY_RIGHT_ARROW) right(); else if (kp.key_id == kp.KEY_UP_ARROW) up(); else if (kp.key_id == kp.KEY_DOWN_ARROW) down(); else if (ch) { text_back.insert(pos, ch); on_text_change(); } } void entry::left() { if (cur_x) --cur_x; else if (cur_y) { --cur_y; check_x(); } else return; on_cursor_change(); } void entry::right() { if (++cur_x <= strlen(flower.get_nth_line(cur_y))) on_cursor_change(); else if (cur_y != flower.get_n_lines()) { ++cur_y; cur_x = 0; on_cursor_change(); } } void entry::up() { if (cur_y) { --cur_y; check_x(); on_cursor_change(); } else if (!cur_x) { cur_x = 0; on_cursor_change(); } } void entry::down() { if (cur_y != flower.get_n_lines()) { ++cur_y; check_x(); on_cursor_change(); } else if (cur_x < strlen(flower.get_nth_line(cur_y))) { cur_x = strlen(flower.get_nth_line(cur_y)); on_cursor_change(); } } void entry::on_focus() { is_cur = true; w->notify_needs_paint(*this); } void entry::on_unfocus() { is_cur = false; w->notify_needs_paint(*this); } }