ltkx

GUI toolkit for X11 (old)
git clone git://lumidify.org/ltkx.git (fast, but not encrypted)
git clone https://lumidify.org/ltkx.git (encrypted, but very slow)
git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/ltkx.git (over tor)
Log | Files | Refs | README | LICENSE

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, &ltk_text_edit_draw, &ltk_text_edit_destroy, 1);
    104 	/*te->widget.mouse_press = &ltk_text_edit_tmp;*/
    105 	te->widget.resize = &ltk_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 }