From bff8e40d003921641886221fde90e5dc53680cc0 Mon Sep 17 00:00:00 2001
From: Cedric Roux <cedric.roux@eurecom.fr>
Date: Mon, 5 Dec 2016 17:30:13 +0100
Subject: [PATCH] T: add widget 'textarea'

It's like a label but with fixed dimensions and maximum
characters' capacity at creation time.
---
 common/utils/T/tracer/gui/Makefile   |  4 +-
 common/utils/T/tracer/gui/gui.h      |  3 +
 common/utils/T/tracer/gui/gui_defs.h | 13 ++++-
 common/utils/T/tracer/gui/textarea.c | 83 ++++++++++++++++++++++++++++
 common/utils/T/tracer/gui/widget.c   |  3 +-
 5 files changed, 102 insertions(+), 4 deletions(-)
 create mode 100644 common/utils/T/tracer/gui/textarea.c

diff --git a/common/utils/T/tracer/gui/Makefile b/common/utils/T/tracer/gui/Makefile
index 53f2077eac..2edec111d7 100644
--- a/common/utils/T/tracer/gui/Makefile
+++ b/common/utils/T/tracer/gui/Makefile
@@ -2,8 +2,8 @@ CC=gcc
 CFLAGS=-Wall -g -pthread -I/usr/include/X11/Xft -I/usr/include/freetype2
 
 OBJS=init.o loop.o toplevel_window.o x.o container.o widget.o \
-     gui.o label.o event.o xy_plot.o textlist.o notify.o positioner.o \
-     timeline.o space.o image.o
+     gui.o label.o textarea.o event.o xy_plot.o textlist.o notify.o \
+     positioner.o timeline.o space.o image.o
 
 gui.a: $(OBJS)
 	ar cr gui.a $(OBJS)
diff --git a/common/utils/T/tracer/gui/gui.h b/common/utils/T/tracer/gui/gui.h
index c61c2dc6c0..43b955f91a 100644
--- a/common/utils/T/tracer/gui/gui.h
+++ b/common/utils/T/tracer/gui/gui.h
@@ -30,6 +30,7 @@ widget *new_toplevel_window(gui *gui, int width, int height, char *title);
 widget *new_container(gui *gui, int vertical);
 widget *new_positioner(gui *gui);
 widget *new_label(gui *gui, const char *text);
+widget *new_textarea(gui *gui, int width, int height, int maxsize);
 widget *new_xy_plot(gui *gui, int width, int height, char *label,
     int vruler_width);
 widget *new_textlist(gui *gui, int width, int nlines, int background_color);
@@ -41,6 +42,8 @@ widget *new_image(gui *gui, unsigned char *data, int length);
 void label_set_clickable(gui *gui, widget *label, int clickable);
 void label_set_text(gui *gui, widget *label, char *text);
 
+void textarea_set_text(gui *gui, widget *textarea, char *text);
+
 void container_set_child_growable(gui *_gui, widget *_this,
     widget *child, int growable);
 
diff --git a/common/utils/T/tracer/gui/gui_defs.h b/common/utils/T/tracer/gui/gui_defs.h
index 938641178c..9cb94dc98a 100644
--- a/common/utils/T/tracer/gui/gui_defs.h
+++ b/common/utils/T/tracer/gui/gui_defs.h
@@ -31,7 +31,7 @@ extern int volatile gui_logd;
 
 enum widget_type {
   TOPLEVEL_WINDOW, CONTAINER, POSITIONER, TEXT_LIST, XY_PLOT, BUTTON, LABEL,
-  TIMELINE, SPACE, IMAGE
+  TEXTAREA, TIMELINE, SPACE, IMAGE
 };
 
 struct widget_list;
@@ -148,6 +148,17 @@ struct label_widget {
   int baseline;      /* as given by the graphic's backend */
 };
 
+struct textarea_widget {
+  struct widget common;
+  char *t;
+  int tmaxsize;
+  int color;
+  int wanted_width;
+  int wanted_height;
+  int baseline;      /* as given by the graphic's backend */
+  int text_width;    /* as given by the graphic's backend */
+};
+
 struct space_widget {
   struct widget common;
   int wanted_width;
diff --git a/common/utils/T/tracer/gui/textarea.c b/common/utils/T/tracer/gui/textarea.c
new file mode 100644
index 0000000000..da84f850ca
--- /dev/null
+++ b/common/utils/T/tracer/gui/textarea.c
@@ -0,0 +1,83 @@
+#include "gui.h"
+#include "gui_defs.h"
+#include "x.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static void paint(gui *_gui, widget *_w)
+{
+  struct gui *g = _gui;
+  struct textarea_widget *t = _w;
+  LOGD("PAINT textarea '%s'\n", t->t);
+  x_fill_rectangle(g->x, g->xwin, BACKGROUND_COLOR,
+      t->common.x, t->common.y,
+      t->common.width, t->common.height);
+  x_draw_clipped_string(g->x, g->xwin, DEFAULT_FONT, t->color,
+      t->common.x + t->common.width - t->text_width,
+      t->common.y + t->baseline, t->t,
+      t->common.x, t->common.y,
+      t->common.width, t->common.height);
+}
+
+static void hints(gui *_gui, widget *_w, int *width, int *height)
+{
+  struct textarea_widget *t = _w;
+  LOGD("HINTS textarea '%s'\n", t->t);
+  *width = t->wanted_width;
+  *height = t->wanted_height;
+}
+
+widget *new_textarea(gui *_gui, int width, int height, int maxsize)
+{
+  struct gui *g = _gui;
+  struct textarea_widget *w;
+  int _;
+
+  glock(g);
+
+  w = new_widget(g, TEXTAREA, sizeof(struct textarea_widget));
+
+  w->t = calloc(maxsize, 1);
+  if (w->t == NULL) OOM;
+  w->tmaxsize = maxsize;
+  w->wanted_width = width;
+  w->wanted_height = height;
+  w->color = FOREGROUND_COLOR;
+  w->text_width = 0;
+
+  x_text_get_dimensions(g->x, DEFAULT_FONT, "jlM",
+      &_, &_, &w->baseline);
+
+  w->common.paint = paint;
+  w->common.hints = hints;
+
+  gunlock(g);
+
+  return w;
+}
+
+/*************************************************************************/
+/*                             public functions                          */
+/*************************************************************************/
+
+void textarea_set_text(gui *_g, widget *_this, char *text)
+{
+  struct gui *g = _g;
+  struct textarea_widget *this = _this;
+  int _;
+  int len = strlen(text);
+  if (len >= this->tmaxsize) {
+    fprintf(stderr, "ERROR: string '%s' too big for textarea\n", text);
+    return;
+  }
+
+  glock(g);
+
+  strcpy(this->t, text);
+  x_text_get_dimensions(g->x, DEFAULT_FONT, text,
+      &this->text_width, &_, &this->baseline);
+  send_event(g, DIRTY, this->common.id);
+
+  gunlock(g);
+}
diff --git a/common/utils/T/tracer/gui/widget.c b/common/utils/T/tracer/gui/widget.c
index 362d2e1e48..b8ccba6d54 100644
--- a/common/utils/T/tracer/gui/widget.c
+++ b/common/utils/T/tracer/gui/widget.c
@@ -265,7 +265,7 @@ void widget_dirty(gui *_gui, widget *_this)
 
 static const char *names[] = {
   "TOPLEVEL_WINDOW", "CONTAINER", "POSITIONER", "TEXT_LIST",
-  "XY_PLOT", "BUTTON", "LABEL", "TIMELINE", "SPACE", "IMAGE"
+  "XY_PLOT", "BUTTON", "LABEL", "TEXTAREA", "TIMELINE", "SPACE", "IMAGE"
 };
 const char *widget_name(enum widget_type type)
 {
@@ -277,6 +277,7 @@ const char *widget_name(enum widget_type type)
   case XY_PLOT:
   case BUTTON:
   case LABEL:
+  case TEXTAREA:
   case TIMELINE:
   case SPACE:
   case IMAGE:
-- 
2.26.2