text_edit.c (4265B)
1 /* 2 * This file is part of the Lumidify ToolKit (LTK) 3 * Copyright (c) 2020 lumidify <nobody@lumidify.org> 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a copy 6 * of this software and associated documentation files (the "Software"), to deal 7 * in the Software without restriction, including without limitation the rights 8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 * copies of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in all 13 * copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 */ 23 24 #include <stdint.h> 25 #include <math.h> 26 #include <X11/Xlib.h> 27 #include <X11/Xutil.h> 28 #include "khash.h" 29 #include "stb_truetype.h" 30 #include <fribidi.h> 31 #include <harfbuzz/hb.h> 32 #include <fontconfig/fontconfig.h> 33 #include "text_common.h" 34 #include "ltk.h" 35 #include "array.h" 36 #include "text_buffer.h" 37 #include "text_edit.h" 38 #include "grid.h" 39 40 void 41 ltk_text_edit_draw(LtkTextEdit *te) { 42 Display *display = ltk_get_display(); 43 LtkTheme *theme = ltk_get_theme(); 44 if (!te->img) 45 ltk_text_edit_resize(te, 0, 0); 46 LtkRect rect = te->widget.rect; 47 LtkWindow *window = te->widget.window; 48 int x = rect.x; 49 if (te->tl->dir == HB_DIRECTION_RTL) 50 x += rect.w - te->img->width; 51 XSetForeground(display, window->gc, theme->window->bg.pixel); 52 XFillRectangle(display, window->xwindow, window->gc, rect.x, rect.y, rect.w, rect.h); 53 XPutImage( 54 display, 55 window->xwindow, 56 window->gc, 57 te->img, 58 0, 0, 59 x, rect.y, 60 te->tl->w_wrapped, te->tl->h_wrapped 61 ); 62 } 63 64 /* FIXME: only recalculate if largest line is too wide */ 65 void 66 ltk_text_edit_resize(LtkTextEdit *te, int orig_w, int orig_h) { 67 if (te->tl->soft_lines->len == 1 && 68 te->widget.rect.w >= te->img->width && orig_w >= te->img->width) 69 return; 70 LtkTheme *theme = ltk_get_theme(); 71 Display *display = ltk_get_display(); 72 Colormap colormap = ltk_get_colormap(); 73 XColor fg = theme->window->fg; 74 XColor bg = theme->window->bg; 75 LtkWindow *window = te->widget.window; 76 ltk_text_line_wrap(te->tl, te->widget.rect.w); 77 if (te->img) XDestroyImage(te->img); 78 te->img = ltk_text_line_render(te->tl, display, window->xwindow, window->gc, colormap, fg, bg); 79 } 80 81 #if 0 82 void 83 ltk_text_edit_tmp(LtkTextEdit *te, XEvent event) { 84 /* this should never be negative, but just to be sure... */ 85 int local_y = abs(event.xbutton.y - te->widget.rect.y); 86 int i = ((double)local_y / (te->tl->h * te->soft_lines->len)) * te->soft_lines->len; 87 i = i >= te->soft_lines->len ? te->soft_lines->len - 1 : i; 88 int x = event.xbutton.x - te->widget.rect.x; 89 if (te->tl->dir == HB_DIRECTION_RTL) 90 x -= (te->widget.rect.w - te->soft_lines->buf[i]->img->width); 91 int found_pos = 0; 92 te->cursor = ltk_soft_line_get_index_from_pos( 93 x, te->tl, te->soft_lines->buf[i], &found_pos); 94 } 95 #endif 96 97 LtkTextEdit * 98 ltk_text_edit_create(LtkWindow *window, const char *text) { 99 LtkTextEdit *te = malloc(sizeof(LtkTextEdit)); 100 if (!te) 101 ltk_fatal("ERROR: Unable to allocate memory for LtkTextEdit.\n"); 102 te->img = NULL; 103 ltk_fill_widget_defaults(&te->widget, window, <k_text_edit_draw, <k_text_edit_destroy, 1); 104 /*te->widget.mouse_press = <k_text_edit_tmp;*/ 105 te->widget.resize = <k_text_edit_resize; 106 te->tl = ltk_text_line_create(20); 107 ltk_text_edit_insert_text(te, text); 108 return te; 109 } 110 111 void 112 ltk_text_edit_insert_text(LtkTextEdit *te, const char *text) { 113 /* FIXME */ 114 ltk_text_line_insert_utf8(te->tl, 0, text); 115 ltk_text_edit_resize(te, 0, 0); 116 ltk_window_invalidate_rect(te->widget.window, te->widget.rect); 117 } 118 119 void ltk_text_edit_destroy(LtkTextEdit *te) { 120 ltk_text_line_destroy(te->tl); 121 if (te->img) XDestroyImage(te->img); 122 free(te); 123 }