From 79ef1d23718aec51d59bb49078a58bb0fabfda2a Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Sun, 28 Oct 2007 21:19:50 +0000 Subject: copied bbogart/entry/entry.c and changed names svn path=/trunk/externals/hcs/; revision=8899 --- listbox-help.pd | 170 +++++++++++++ listbox.c | 766 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ textbox-help.pd | 170 +++++++++++++ textbox.c | 766 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1872 insertions(+) create mode 100644 listbox-help.pd create mode 100644 listbox.c create mode 100644 textbox-help.pd create mode 100644 textbox.c diff --git a/listbox-help.pd b/listbox-help.pd new file mode 100644 index 0000000..bd79734 --- /dev/null +++ b/listbox-help.pd @@ -0,0 +1,170 @@ +#N canvas 172 88 748 676 10; +#X obj 73 212 entry 150 100 grey black; +#X obj 11 84 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 32 346 print; +#X msg 100 95 clear; +#X msg 157 99 set one two three four five six; +#X msg 72 50 fgcolour yellow; +#X msg 50 23 bgcolour purple; +#X obj 142 462 entry 100 50 grey70 purple; +#X text 8 365 Creation arguments are: width height bgcolor fgcolor. +The width and height are in pixels.; +#X obj 251 254 select return; +#X obj 79 347 pddp/print; +#X obj 176 173 trigger bang bang; +#X msg 176 194 clear; +#X symbolatom 216 319 10 0 0 1 last_key_typed - -; +#X text 255 275 ^-- hit return to output; +#X msg 219 430 size 400 200; +#X msg 29 4 bgcolour grey; +#X msg 84 71 fgcolour black; +#X text 12 394 The size message currently only takes affect after a +save and reopen.; +#X msg 169 127 add seven eight nine; +#X msg 196 149 add ten eleven.; +#X msg 30 459 fontsize \$1; +#X msg 52 432 12; +#X msg 20 431 9; +#X msg 85 429 98; +#X obj 166 18 pddp/pddplink http://tcl.tk/man/tcl8.4/TkCmd/text.htm +; +#X obj 572 91 entry 300 50 grey70 black; +#X msg 572 67 option relief \$1; +#X obj 571 46 symbol; +#X msg 469 11 flat; +#X msg 504 11 groove; +#X msg 551 11 raised; +#X msg 599 10 ridge; +#X msg 640 10 solid; +#X msg 681 10 sunken; +#X obj 366 524 entry 124 100 grey70 black; +#X obj 368 468 symbol; +#X obj 558 526 entry 124 100 grey70 black; +#X obj 558 478 symbol; +#X msg 541 454 on; +#X msg 575 453 off; +#X msg 349 443 normal; +#X msg 395 443 disabled; +#X msg 367 491 option state \$1; +#X msg 558 500 option undo \$1; +#X msg 132 430 size 100 50; +#X text 421 470 disable editing; +#X text 608 469 turn on undo; +#X obj 572 217 entry 100 50 grey70 black; +#X obj 571 172 symbol; +#X obj 502 394 entry 100 50 grey70 black; +#X obj 501 349 symbol; +#X msg 572 193 option wrap \$1; +#X msg 529 147 none; +#X msg 564 147 char; +#X msg 601 147 word; +#X text 618 171 word wrapping; +#X msg 502 370 option selectbackground \$1; +#X msg 419 304 blue; +#X msg 454 304 purple; +#X msg 501 304 orange; +#X msg 549 303 magenta; +#X obj 425 281 pddp/pddplink http://en.wikipedia.org/wiki/X11_color_names +; +#X msg 603 303 DarkSlateBlue; +#X msg 603 342 limegreen; +#X msg 603 323 lightyellow; +#X obj 384 218 entry 100 50 grey70 black; +#X obj 386 167 hsl 128 15 0 127 0 0 empty empty empty -2 -6 0 10 -262144 +-1 -1 0 1; +#X obj 52 601 entry 100 50 grey70 black; +#X obj 51 556 symbol; +#X obj 161 636 pddp/pddplink http://tcl.tk/man/tcl8.4/TkCmd/cursors.htm +; +#X msg 49 521 boat; +#X msg 84 521 bogosity; +#X msg 52 577 option cursor \$1; +#X msg 9 521 clock; +#X msg 145 521 dot; +#X msg 175 521 dotbox; +#X msg 222 521 gumby; +#X msg 265 521 gobbler; +#X msg 266 590 pirate; +#X msg 266 547 mouse; +#X msg 266 569 target; +#X text 174 615 for more:; +#X msg 266 611 trek; +#X msg 384 194 option insertwidth \$1; +#X obj 386 48 hsl 128 15 0 127 0 0 empty empty empty -2 -6 0 10 -262144 +-1 -1 0 1; +#X msg 383 68 option borderwidth \$1; +#X msg 395 366 scrollbar \$1; +#X obj 395 346 tgl 15 0 empty empty empty 0 -6 0 10 -262144 -1 -1 0 +1; +#X connect 0 0 2 0; +#X connect 0 0 10 0; +#X connect 0 1 9 0; +#X connect 0 1 13 0; +#X connect 1 0 0 0; +#X connect 3 0 0 0; +#X connect 4 0 0 0; +#X connect 5 0 0 0; +#X connect 6 0 0 0; +#X connect 9 0 11 0; +#X connect 11 0 12 0; +#X connect 11 1 0 0; +#X connect 12 0 0 0; +#X connect 15 0 7 0; +#X connect 16 0 0 0; +#X connect 17 0 0 0; +#X connect 19 0 0 0; +#X connect 20 0 0 0; +#X connect 21 0 7 0; +#X connect 22 0 21 0; +#X connect 23 0 21 0; +#X connect 24 0 21 0; +#X connect 27 0 26 0; +#X connect 28 0 27 0; +#X connect 29 0 28 0; +#X connect 30 0 28 0; +#X connect 31 0 28 0; +#X connect 32 0 28 0; +#X connect 33 0 28 0; +#X connect 34 0 28 0; +#X connect 36 0 43 0; +#X connect 38 0 44 0; +#X connect 39 0 38 0; +#X connect 40 0 38 0; +#X connect 41 0 36 0; +#X connect 42 0 36 0; +#X connect 43 0 35 0; +#X connect 44 0 37 0; +#X connect 45 0 7 0; +#X connect 49 0 52 0; +#X connect 51 0 57 0; +#X connect 52 0 48 0; +#X connect 53 0 49 0; +#X connect 54 0 49 0; +#X connect 55 0 49 0; +#X connect 57 0 50 0; +#X connect 58 0 51 0; +#X connect 59 0 51 0; +#X connect 60 0 51 0; +#X connect 61 0 51 0; +#X connect 63 0 51 0; +#X connect 64 0 51 0; +#X connect 65 0 51 0; +#X connect 67 0 84 0; +#X connect 69 0 73 0; +#X connect 71 0 69 0; +#X connect 72 0 69 0; +#X connect 73 0 68 0; +#X connect 75 0 69 0; +#X connect 76 0 69 0; +#X connect 77 0 69 0; +#X connect 78 0 69 0; +#X connect 79 0 69 0; +#X connect 80 0 69 0; +#X connect 81 0 69 0; +#X connect 83 0 69 0; +#X connect 84 0 66 0; +#X connect 85 0 86 0; +#X connect 86 0 26 0; +#X connect 87 0 50 0; +#X connect 88 0 87 0; diff --git a/listbox.c b/listbox.c new file mode 100644 index 0000000..0c427b3 --- /dev/null +++ b/listbox.c @@ -0,0 +1,766 @@ +/* text entry widget for PD * + * Based on button from GGEE by Guenter Geiger * + * Copyright 2004 Ben Bogart 2004 ben@ekran.org * + * Copyright 2007 Free Software Foundation + + * This program is distributed under the terms of the GNU General Public * + * License * + + * entry is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + + * listbox is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. */ + +#include +#include +#include +#include +#include + +/* TODO: make "display only" option, to force box to never accept focus */ +/* TODO: make focus option only accept regular and shifted chars, not Cmd, Alt, Ctrl */ +/* TODO: make listbox_save include whole classname, including namespace prefix */ +/* TODO: make [size( message redraw object */ +/* TODO: set message doesnt work with a loadbang */ +/* TODO: make message to add a single character to the existing text */ +/* TODO: complete inlet draw/erase logic */ + +#ifdef _MSC_VER +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +#ifndef IOWIDTH +#define IOWIDTH 4 +#endif + +#define BACKGROUNDCOLOR "grey70" + +#define DEBUG(x) x + +typedef struct _listbox +{ + t_object x_obj; + + t_glist * x_glist; + int x_rect_width; + int x_rect_height; + t_symbol* x_receive_name; + +/* TODO: these all should be settable by messages */ + int x_height; + int x_width; + + t_symbol* x_bgcolour; + t_symbol* x_fgcolour; + + t_symbol *x_font_face; + t_int x_font_size; + t_symbol *x_font_weight; + + t_float x_border; + t_float x_highlightthickness; + t_symbol *x_relief; + t_int x_have_scrollbar; + + t_outlet* x_data_outlet; + t_outlet* x_status_outlet; +} t_listbox; + + +static t_class *listbox_class; + + +static t_symbol *backspace_symbol; +static t_symbol *return_symbol; +static t_symbol *space_symbol; +static t_symbol *tab_symbol; +static t_symbol *escape_symbol; +static t_symbol *left_symbol; +static t_symbol *right_symbol; +static t_symbol *up_symbol; +static t_symbol *down_symbol; + +/* function prototypes */ + +static void listbox_getrect(t_gobj *z, t_glist *owner, int *xp1, int *yp1, int *xp2, int *yp2); +static void listbox_displace(t_gobj *z, t_glist *glist, int dx, int dy); +static void listbox_select(t_gobj *z, t_glist *glist, int state); +static void listbox_activate(t_gobj *z, t_glist *glist, int state); +static void listbox_delete(t_gobj *z, t_glist *glist); +static void listbox_vis(t_gobj *z, t_glist *glist, int vis); +static void listbox_save(t_gobj *z, t_binbuf *b); + + +t_widgetbehavior listbox_widgetbehavior = { +w_getrectfn: listbox_getrect, +w_displacefn: listbox_displace, +w_selectfn: listbox_select, +w_activatefn: listbox_activate, +w_deletefn: listbox_delete, +w_visfn: listbox_vis, +w_clickfn: NULL, +}; + +/* widget helper functions */ + +static int calculate_onset(t_listbox *x, t_glist *glist, int i, int nplus) +{ + return(text_xpix(&x->x_obj, glist) + (x->x_rect_width - IOWIDTH) * i / nplus); +} + +static void draw_inlets(t_listbox *x, t_glist *glist, int firsttime, int nin, int nout) +{ + DEBUG(post("draw_inlets in: %d out: %d", nin, nout);); + + int nplus, i, onset; + t_canvas *canvas = glist_getcanvas(glist); + + nplus = (nin == 1 ? 1 : nin-1); + /* inlets */ + for (i = 0; i < nin; i++) + { + onset = calculate_onset(x,glist,i,nplus); + if (firsttime) + { + DEBUG(post(".x%x.c create rectangle %d %d %d %d -tags {%xi%d %xi}\n", + canvas, onset, text_ypix(&x->x_obj, glist) - 2, + onset + IOWIDTH, text_ypix(&x->x_obj, glist) - 1, + x, i, x);); + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags {%xi%d %xi}\n", + canvas, onset, text_ypix(&x->x_obj, glist) - 2, + onset + IOWIDTH, text_ypix(&x->x_obj, glist) - 1, + x, i, x); + } + else + { + DEBUG(post(".x%x.c coords %xi%d %d %d %d %d\n", + canvas, x, i, onset, text_ypix(&x->x_obj, glist) - 2, + onset + IOWIDTH, text_ypix(&x->x_obj, glist) - 1);); + sys_vgui(".x%x.c coords %xi%d %d %d %d %d\n", + canvas, x, i, onset, text_ypix(&x->x_obj, glist) - 2, + onset + IOWIDTH, text_ypix(&x->x_obj, glist)- 1); + } + } + nplus = (nout == 1 ? 1 : nout-1); + for (i = 0; i < nout; i++) /* outlets */ + { + onset = calculate_onset(x,glist,i,nplus); + if (firsttime) + { + DEBUG(post(".x%x.c create rectangle %d %d %d %d -tags {%xo%d %xo}\n", + canvas, onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 2, + onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height-1, + x, i, x);); + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags {%xo%d %xo}\n", + canvas, onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 2, + onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height-1, + x, i, x); + } + else + { + DEBUG(post(".x%x.c coords %xo%d %d %d %d %d\n", + canvas, x, i, + onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 2, + onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height-1);); + sys_vgui(".x%x.c coords %xo%d %d %d %d %d\n", + canvas, x, i, + onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 2, + onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height-1); + } + } + DEBUG(post("draw inlet end");); +} + +static void erase_inlets(t_listbox *x, t_canvas *canvas) +{ + DEBUG(post("erase_inlets");); +/* Added tag for all inlets of one instance */ + DEBUG(post(".x%x.c delete %xi\n", canvas,x);); + sys_vgui(".x%x.c delete %xi\n", canvas,x); + DEBUG(post(".x%x.c delete %xo\n", canvas,x);); + sys_vgui(".x%x.c delete %xo\n", canvas,x); +/* Added tag for all outlets of one instance */ + DEBUG(post(".x%x.c delete %xhandle\n", canvas,x,0);); + sys_vgui(".x%x.c delete %xhandle\n", canvas,x,0); +} + +/* currently unused + static void draw_handle(t_listbox *x, t_glist *glist, int firsttime) { + int onset = text_xpix(&x->x_obj, glist) + (x->x_rect_width - IOWIDTH+2); + + if (firsttime) + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xhandle\n", + glist_getcanvas(glist), + onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 12, + onset + IOWIDTH-2, text_ypix(&x->x_obj, glist) + x->x_rect_height-4, + x); + else + sys_vgui(".x%x.c coords %xhandle %d %d %d %d\n", + glist_getcanvas(glist), x, + onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 12, + onset + IOWIDTH-2, text_ypix(&x->x_obj, glist) + x->x_rect_height-4); + } +*/ +static void draw_scrollbar(t_listbox *x) +{ + DEBUG(post("pack .x%x.c.s%x.scrollbar -side right -fill y -before .x%x.c.s%x.text \n", + x->x_glist, x, x->x_glist, x);); + sys_vgui("pack .x%x.c.s%x.scrollbar -side right -fill y -before .x%x.c.s%x.text \n", + x->x_glist, x, x->x_glist, x); + x->x_have_scrollbar = 1; +} + +static void erase_scrollbar(t_listbox *x) +{ + DEBUG(post("pack forget .x%x.c.s%x.scrollbar \n", x->x_glist, x);); + sys_vgui("pack forget .x%x.c.s%x.scrollbar \n", x->x_glist, x); + x->x_have_scrollbar = 0; +} + +static void create_widget(t_listbox *x, t_glist *glist) +{ + DEBUG(post("create_widget");); + t_canvas *canvas=glist_getcanvas(glist); + /* I guess this is for fine-tuning of the rect size based on width and height? */ + x->x_rect_width = x->x_width; + x->x_rect_height = x->x_height+2; + + DEBUG(post("namespace eval listbox%lx {} \n", x);); + sys_vgui("namespace eval listbox%lx {} \n", x); + + /* Seems we have to delete the widget in case it already exists (Provided by Guenter)*/ + DEBUG(post("destroy .x%x.c.s%x\n", canvas, x);); + sys_vgui("destroy .x%x.c.s%x\n", canvas, x); + + + DEBUG(post("frame .x%x.c.s%x \n",canvas, x);); + sys_vgui("frame .x%x.c.s%x \n",canvas, x); + DEBUG(post("text .x%x.c.s%x.text -font {%s %d %s} -border 1 \ + -highlightthickness 1 -relief sunken -bg \"%s\" -fg \"%s\" \ + -yscrollcommand {.x%x.c.s%x.scrollbar set} \n", + canvas, x, x->x_font_face->s_name, x->x_font_size, + x->x_font_weight->s_name, + x->x_bgcolour->s_name,x->x_fgcolour->s_name, + canvas, x);); + sys_vgui("text .x%x.c.s%x.text -font {%s %d %s} -border 1 \ + -highlightthickness 1 -relief sunken -bg \"%s\" -fg \"%s\" \ + -yscrollcommand {.x%x.c.s%x.scrollbar set} \n", + canvas, x, x->x_font_face->s_name, x->x_font_size, + x->x_font_weight->s_name, + x->x_bgcolour->s_name, x->x_fgcolour->s_name, + canvas, x); + DEBUG(post("scrollbar .x%x.c.s%x.scrollbar -command {.x%x.c.s%x.text yview} \n",canvas, x, canvas, x);); + sys_vgui("scrollbar .x%x.c.s%x.scrollbar -command {.x%x.c.s%x.text yview} \n",canvas, x ,canvas, x); + DEBUG(post("pack .x%x.c.s%x.scrollbar -side right -fill y \n",canvas, x);); + sys_vgui("pack .x%x.c.s%x.scrollbar -side right -fill y \n",canvas, x); + DEBUG(post("pack .x%x.c.s%x.text -side left -fill both -expand 1 \n",canvas, x);); + sys_vgui("pack .x%x.c.s%x.text -side left -fill both -expand 1 \n",canvas, x); + DEBUG(post("pack .x%x.c.s%x -side bottom -fill both -expand 1 \n",canvas, x);); + sys_vgui("pack .x%x.c.s%x -side bottom -fill both -expand 1 \n",canvas, x); + + DEBUG(post("bind .x%x.c.s%x.text {+pd %s keyup %%N \\;} \n", + canvas, x, x->x_receive_name->s_name);); + sys_vgui("bind .x%x.c.s%x.text {+pd %s keyup %%N \\;} \n", + canvas, x, x->x_receive_name->s_name); + DEBUG(post("bind .x%x.c.s%x.text {focus [winfo parent .x%x.c.s%x]} \n", + canvas, x, canvas, x);); + sys_vgui("bind .x%x.c.s%x.text {focus [winfo parent .x%x.c.s%x]} \n", + canvas, x, canvas, x); +} + +static void listbox_drawme(t_listbox *x, t_glist *glist, int firsttime) +{ + DEBUG(post("listbox_drawme");); + t_canvas *canvas=glist_getcanvas(glist); + DEBUG(post("drawme %d",firsttime);); + if (firsttime) + { + x->x_glist = canvas; + create_widget(x,glist); + DEBUG(post(".x%x.c create window %d %d -anchor nw -window .x%x.c.s%x \ + -tags %xS -width %d -height %d \n", canvas, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + canvas, x, x, x->x_width, x->x_height);); + sys_vgui(".x%x.c create window %d %d -anchor nw -window .x%x.c.s%x \ + -tags %xS -width %d -height %d \n", canvas, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + canvas, x,x, x->x_width, x->x_height); + } + else + { + DEBUG(post(".x%x.c coords %xS %d %d\n", canvas, x, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist));); + sys_vgui(".x%x.c coords %xS %d %d\n", canvas, x, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)); + } + post("canvas: %d glist: %d", canvas->gl_edit, glist->gl_edit); + if( (x->x_glist->gl_edit) && (canvas == x->x_glist) ) + draw_inlets(x, glist, firsttime, 1,2); + else + erase_inlets(x, canvas); + // draw_handle(x, glist, firsttime); +} + + +static void listbox_erase(t_listbox* x,t_glist* glist) +{ + DEBUG(post("listbox_erase");); + t_canvas *canvas = glist_getcanvas(glist); + DEBUG(post("destroy .x%x.c.s%x\n", canvas, x);); + sys_vgui("destroy .x%x.c.s%x\n", canvas, x); + + DEBUG(post(".x%x.c delete %xS\n", canvas, x);); + sys_vgui(".x%x.c delete %xS\n", canvas, x); + + erase_inlets(x, canvas); +} + + + +/* ------------------------ text widgetbehaviour----------------------------- */ + + +static void listbox_getrect(t_gobj *z, t_glist *owner, + int *xp1, int *yp1, int *xp2, int *yp2) +{ +/* DEBUG(post("listbox_getrect");); */ + int width, height; + t_listbox* s = (t_listbox*)z; + + width = s->x_rect_width; + height = s->x_rect_height; + *xp1 = text_xpix(&s->x_obj, owner); + *yp1 = text_ypix(&s->x_obj, owner) - 1; + *xp2 = text_xpix(&s->x_obj, owner) + width; + *yp2 = text_ypix(&s->x_obj, owner) + height; +} + +static void listbox_displace(t_gobj *z, t_glist *glist, int dx, int dy) +{ + DEBUG(post("listbox_displace");); + t_listbox *x = (t_listbox *)z; + x->x_obj.te_xpix += dx; + x->x_obj.te_ypix += dy; + if (glist_isvisible(glist)) + { + t_canvas *canvas = glist_getcanvas(glist); + DEBUG(post(".x%x.c coords %xSEL %d %d %d %d\n", canvas, x, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)-1, + text_xpix(&x->x_obj, glist) + x->x_rect_width, + text_ypix(&x->x_obj, glist) + x->x_rect_height-2);); + sys_vgui(".x%x.c coords %xSEL %d %d %d %d\n", canvas, x, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)-1, + text_xpix(&x->x_obj, glist) + x->x_rect_width, + text_ypix(&x->x_obj, glist) + x->x_rect_height-2); + + listbox_drawme(x, glist, 0); + canvas_fixlinesfor(canvas, (t_text*) x); + } + DEBUG(post("displace end");); +} + +static void listbox_select(t_gobj *z, t_glist *glist, int state) +{ + DEBUG(post("listbox_select");); + t_listbox *x = (t_listbox *)z; + t_canvas *canvas = glist_getcanvas(glist); + if (state) { + DEBUG(post(".x%x.c create rectangle %d %d %d %d -tags %xSEL -outline blue\n", + canvas, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)-1, + text_xpix(&x->x_obj, glist) + x->x_rect_width, + text_ypix(&x->x_obj, glist) + x->x_rect_height-2, x);); + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xSEL -outline blue\n", + canvas, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)-1, + text_xpix(&x->x_obj, glist) + x->x_rect_width, + text_ypix(&x->x_obj, glist) + x->x_rect_height-2, x); + } + else { + DEBUG(post(".x%x.c delete %xSEL\n", canvas, x);); + sys_vgui(".x%x.c delete %xSEL\n", canvas, x); + } +} + +static void listbox_activate(t_gobj *z, t_glist *glist, int state) +{ + DEBUG(post("listbox_activate");); +/* this is currently unused + t_text *x = (t_text *)z; + t_rtext *y = glist_findrtext(glist, x); + if (z->g_pd != gatom_class) rtext_activate(y, state); +*/ +} + +static void listbox_delete(t_gobj *z, t_glist *glist) +{ + DEBUG(post("listbox_delete");); + t_text *x = (t_text *)z; + canvas_deletelinesfor(glist_getcanvas(glist), x); +} + + +static void listbox_vis(t_gobj *z, t_glist *glist, int vis) +{ + DEBUG(post("listbox_vis");); + t_listbox* s = (t_listbox*)z; + t_rtext *y; + DEBUG(post("vis: %d",vis);); + if (vis) { + y = (t_rtext *) rtext_new(glist, (t_text *)z); + listbox_drawme(s, glist, 1); + } + else { + y = glist_findrtext(glist, (t_text *)z); + listbox_erase(s,glist); + rtext_free(y); + } +} + +static void listbox_add(t_listbox* x, t_symbol *s, int argc, t_atom *argv) +{ + DEBUG(post("listbox_add");); + int i; + t_symbol *tmp_symbol = s; /* <-- this gets rid of the unused variable warning */ + t_float tmp_float; + + for(i=0; is_name );); + sys_vgui("lappend ::listbox%lx::list %s \n", x, tmp_symbol->s_name ); + } + } + DEBUG(post("append ::listbox%lx::list \" \"\n", x);); + sys_vgui("append ::listbox%lx::list \" \"\n", x); + DEBUG(post(".x%x.c.s%x.text insert end $::listbox%lx::list ; unset ::listbox%lx::list \n", + x->x_glist, x, x, x );); + sys_vgui(".x%x.c.s%x.text insert end $::listbox%lx::list ; unset ::listbox%lx::list \n", + x->x_glist, x, x, x ); + DEBUG(post(".x%x.c.s%x.text yview end-2char \n", x->x_glist, x );); + sys_vgui(".x%x.c.s%x.text yview end-2char \n", x->x_glist, x ); +} + +/* Clear the contents of the text widget */ +static void listbox_clear(t_listbox* x) +{ + DEBUG(post(".x%x.c.s%x.text delete 0.0 end \n", x->x_glist, x);); + sys_vgui(".x%x.c.s%x.text delete 0.0 end \n", x->x_glist, x); +} + +/* Function to reset the contents of the listbox box */ +static void listbox_set(t_listbox* x, t_symbol *s, int argc, t_atom *argv) +{ + DEBUG(post("listbox_set");); + int i; + + listbox_clear(x); + listbox_add(x, s, argc, argv); +} + +/* Output the symbol */ +/* , t_symbol *s, int argc, t_atom *argv) */ +static void listbox_output(t_listbox* x, t_symbol *s, int argc, t_atom *argv) +{ + outlet_list(x->x_data_outlet, s, argc, argv ); +} + +/* Pass the contents of the text widget onto the listbox_output fuction above */ +static void listbox_bang_output(t_listbox* x) +{ + /* With "," and ";" escaping thanks to JMZ */ + DEBUG(post("pd [concat %s output [string map {\",\" \"\\\\,\" \";\" \"\\\\;\"} \ + [.x%x.c.s%x.text get 0.0 end]] \\;]\n", + x->x_receive_name->s_name, x->x_glist, x);); + sys_vgui("pd [concat %s output [string map {\",\" \"\\\\,\" \";\" \"\\\\;\"} \ + [.x%x.c.s%x.text get 0.0 end]] \\;]\n", + x->x_receive_name->s_name, x->x_glist, x); + + DEBUG(post("bind .x%x.c.s%x.text {focus [winfo parent .x%x.c.s%x]} \n", + x->x_glist, x, x->x_glist, x);); + sys_vgui("bind .x%x.c.s%x.text {focus [winfo parent .x%x.c.s%x]} \n", + x->x_glist, x, x->x_glist, x); +} + +static void listbox_keyup(t_listbox *x, t_float f) +{ +/* DEBUG(post("listbox_keyup");); */ + int keycode = (int) f; + char buf[10]; + t_symbol *output_symbol; + + if( (keycode > 32 ) && (keycode < 65288) ) + { + snprintf(buf, 2, "%c", keycode); + output_symbol = gensym(buf); + } else + switch(keycode) + { + case 32: /* space */ + output_symbol = space_symbol; + break; + case 65293: /* return */ + output_symbol = return_symbol; + break; + case 65288: /* backspace */ + output_symbol = backspace_symbol; + break; + case 65289: /* tab */ + output_symbol = tab_symbol; + break; + case 65307: /* escape */ + output_symbol = escape_symbol; + break; + case 65361: /* left */ + output_symbol = left_symbol; + break; + case 65363: /* right */ + output_symbol = right_symbol; + break; + case 65362: /* up */ + output_symbol = up_symbol; + break; + case 65364: /* down */ + output_symbol = down_symbol; + break; + default: + snprintf(buf, 10, "key_%d", keycode); + DEBUG(post("keyup: %d", keycode);); + output_symbol = gensym(buf); + } + outlet_symbol(x->x_status_outlet, output_symbol); +} + +static void listbox_save(t_gobj *z, t_binbuf *b) +{ + t_listbox *x = (t_listbox *)z; + + binbuf_addv(b, "ssiisiiss", gensym("#X"),gensym("obj"), + x->x_obj.te_xpix, x->x_obj.te_ypix, + gensym("listbox"), x->x_width, x->x_height, x->x_bgcolour, x->x_fgcolour); + binbuf_addv(b, ";"); +} + + +static void listbox_option_float(t_listbox* x, t_symbol *option, t_float value) +{ + DEBUG(post(".x%x.c.s%x.text configure -%s %f \n", + x->x_glist, x, option->s_name, value);); + sys_vgui(".x%x.c.s%x.text configure -%s %f \n", + x->x_glist, x, option->s_name, value); +} + +static void listbox_option_symbol(t_listbox* x, t_symbol *option, t_symbol *value) +{ + DEBUG(post(".x%x.c.s%x.text configure -%s {%s} \n", + x->x_glist, x, option->s_name, value->s_name);); + sys_vgui(".x%x.c.s%x.text configure -%s {%s} \n", + x->x_glist, x, option->s_name, value->s_name); +} + +static void listbox_option(t_listbox *x, t_symbol *s, int argc, t_atom *argv) +{ + t_symbol *tmp_symbol = s; /* <-- this gets rid of the unused variable warning */ + + tmp_symbol = atom_getsymbolarg(1, argc, argv); + if(tmp_symbol == &s_) + { + listbox_option_float(x,atom_getsymbolarg(0, argc, argv), + atom_getfloatarg(1, argc, argv)); + } + else + { + listbox_option_symbol(x,atom_getsymbolarg(0, argc, argv),tmp_symbol); + } +} + +static void listbox_scrollbar(t_listbox *x, t_float f) +{ + if(f > 0) + draw_scrollbar(x); + else + erase_scrollbar(x); +} + + +/* function to change colour of text background */ +void listbox_bgcolour(t_listbox* x, t_symbol* bgcol) +{ + x->x_bgcolour = bgcol; + DEBUG(post(".x%x.c.s%x.text configure -background \"%s\" \n", + x->x_glist, x, x->x_bgcolour->s_name);); + sys_vgui(".x%x.c.s%x.text configure -background \"%s\" \n", + x->x_glist, x, x->x_bgcolour->s_name); +} + +/* function to change colour of text foreground */ +void listbox_fgcolour(t_listbox* x, t_symbol* fgcol) +{ + x->x_fgcolour = fgcol; + DEBUG(post(".x%x.c.s%x.text configure -foreground \"%s\" \n", + x->x_glist, x, x->x_fgcolour->s_name);); + sys_vgui(".x%x.c.s%x.text configure -foreground \"%s\" \n", + x->x_glist, x, x->x_fgcolour->s_name); +} + +static void listbox_fontsize(t_listbox *x, t_float font_size) +{ + DEBUG(post("listbox_fontsize");); + post("font size: %f",font_size); + if(font_size > 8) + { + x->x_font_size = (t_int)font_size; + DEBUG(post(".x%x.c.s%x.text configure -font {%s %d %s} \n", + x->x_glist, x, + x->x_font_face->s_name, x->x_font_size, x->x_font_weight->s_name);); + sys_vgui(".x%x.c.s%x.text configure -font {%s %d %s} \n", + x->x_glist, x, + x->x_font_face->s_name, x->x_font_size, + x->x_font_weight->s_name); + } + else + pd_error(x,"listbox: invalid font size: %f",font_size); +} + +static void listbox_size(t_listbox *x, t_float width, t_float height) +{ + DEBUG(post("listbox_size");); + x->x_height = height; + x->x_width = width; +} + +static void listbox_free(t_listbox *x) +{ + pd_unbind(&x->x_obj.ob_pd, x->x_receive_name); +} + +static void *listbox_new(t_symbol *s, int argc, t_atom *argv) +{ + DEBUG(post("listbox_new");); + t_listbox *x = (t_listbox *)pd_new(listbox_class); + char buf[MAXPDSTRING]; + + x->x_height = 1; + x->x_font_face = gensym("helvetica"); + x->x_font_size = 10; + x->x_font_weight = gensym("normal"); + x->x_have_scrollbar = 1; + + if (argc < 4) + { + post("listbox: You must enter at least 4 arguments. Default values used."); + x->x_width = 124; + x->x_height = 100; + x->x_bgcolour = gensym("grey70"); + x->x_fgcolour = gensym("black"); + + } else { + /* Copy args into structure */ + x->x_width = atom_getint(argv); + x->x_height = atom_getint(argv+1); + x->x_bgcolour = atom_getsymbol(argv+2); + x->x_fgcolour = atom_getsymbol(argv+3); + } + + x->x_data_outlet = outlet_new(&x->x_obj, &s_float); + x->x_status_outlet = outlet_new(&x->x_obj, &s_symbol); + + snprintf(buf,MAXPDSTRING,"#listbox%lx",(long unsigned int)x); + x->x_receive_name = gensym(buf); + pd_bind(&x->x_obj.ob_pd, x->x_receive_name); + + return (x); +} + +void listbox_setup(void) { + listbox_class = class_new(gensym("listbox"), (t_newmethod)listbox_new, + (t_method)listbox_free, sizeof(t_listbox),0,A_GIMME,0); + + class_addbang(listbox_class, (t_method)listbox_bang_output); + + class_addmethod(listbox_class, (t_method)listbox_keyup, + gensym("keyup"), + A_DEFFLOAT, + 0); + + class_addmethod(listbox_class, (t_method)listbox_scrollbar, + gensym("scrollbar"), + A_DEFFLOAT, + 0); + + class_addmethod(listbox_class, (t_method)listbox_option, + gensym("option"), + A_GIMME, + 0); + + class_addmethod(listbox_class, (t_method)listbox_size, + gensym("size"), + A_DEFFLOAT, + A_DEFFLOAT, + 0); + + class_addmethod(listbox_class, (t_method)listbox_fontsize, + gensym("fontsize"), + A_DEFFLOAT, + 0); + + class_addmethod(listbox_class, (t_method)listbox_output, + gensym("output"), + A_GIMME, + 0); + + class_addmethod(listbox_class, (t_method)listbox_set, + gensym("set"), + A_GIMME, + 0); + + class_addmethod(listbox_class, (t_method)listbox_add, + gensym("add"), + A_GIMME, + 0); + + class_addmethod(listbox_class, (t_method)listbox_clear, + gensym("clear"), + 0); + + class_addmethod(listbox_class, (t_method)listbox_bgcolour, + gensym("bgcolour"), + A_DEFSYMBOL, + 0); + + class_addmethod(listbox_class, (t_method)listbox_fgcolour, + gensym("fgcolour"), + A_DEFSYMBOL, + 0); + + class_setwidget(listbox_class,&listbox_widgetbehavior); + class_setsavefn(listbox_class,&listbox_save); + + backspace_symbol = gensym("backspace"); + return_symbol = gensym("return"); + space_symbol = gensym("space"); + tab_symbol = gensym("tab"); + escape_symbol = gensym("escape"); + left_symbol = gensym("left"); + right_symbol = gensym("right"); + up_symbol = gensym("up"); + down_symbol = gensym("down"); + + post("Text v0.1 Ben Bogart.\nCVS: $Revision: 1.1 $ $Date: 2007-10-28 21:19:50 $"); +} + + diff --git a/textbox-help.pd b/textbox-help.pd new file mode 100644 index 0000000..bd79734 --- /dev/null +++ b/textbox-help.pd @@ -0,0 +1,170 @@ +#N canvas 172 88 748 676 10; +#X obj 73 212 entry 150 100 grey black; +#X obj 11 84 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 32 346 print; +#X msg 100 95 clear; +#X msg 157 99 set one two three four five six; +#X msg 72 50 fgcolour yellow; +#X msg 50 23 bgcolour purple; +#X obj 142 462 entry 100 50 grey70 purple; +#X text 8 365 Creation arguments are: width height bgcolor fgcolor. +The width and height are in pixels.; +#X obj 251 254 select return; +#X obj 79 347 pddp/print; +#X obj 176 173 trigger bang bang; +#X msg 176 194 clear; +#X symbolatom 216 319 10 0 0 1 last_key_typed - -; +#X text 255 275 ^-- hit return to output; +#X msg 219 430 size 400 200; +#X msg 29 4 bgcolour grey; +#X msg 84 71 fgcolour black; +#X text 12 394 The size message currently only takes affect after a +save and reopen.; +#X msg 169 127 add seven eight nine; +#X msg 196 149 add ten eleven.; +#X msg 30 459 fontsize \$1; +#X msg 52 432 12; +#X msg 20 431 9; +#X msg 85 429 98; +#X obj 166 18 pddp/pddplink http://tcl.tk/man/tcl8.4/TkCmd/text.htm +; +#X obj 572 91 entry 300 50 grey70 black; +#X msg 572 67 option relief \$1; +#X obj 571 46 symbol; +#X msg 469 11 flat; +#X msg 504 11 groove; +#X msg 551 11 raised; +#X msg 599 10 ridge; +#X msg 640 10 solid; +#X msg 681 10 sunken; +#X obj 366 524 entry 124 100 grey70 black; +#X obj 368 468 symbol; +#X obj 558 526 entry 124 100 grey70 black; +#X obj 558 478 symbol; +#X msg 541 454 on; +#X msg 575 453 off; +#X msg 349 443 normal; +#X msg 395 443 disabled; +#X msg 367 491 option state \$1; +#X msg 558 500 option undo \$1; +#X msg 132 430 size 100 50; +#X text 421 470 disable editing; +#X text 608 469 turn on undo; +#X obj 572 217 entry 100 50 grey70 black; +#X obj 571 172 symbol; +#X obj 502 394 entry 100 50 grey70 black; +#X obj 501 349 symbol; +#X msg 572 193 option wrap \$1; +#X msg 529 147 none; +#X msg 564 147 char; +#X msg 601 147 word; +#X text 618 171 word wrapping; +#X msg 502 370 option selectbackground \$1; +#X msg 419 304 blue; +#X msg 454 304 purple; +#X msg 501 304 orange; +#X msg 549 303 magenta; +#X obj 425 281 pddp/pddplink http://en.wikipedia.org/wiki/X11_color_names +; +#X msg 603 303 DarkSlateBlue; +#X msg 603 342 limegreen; +#X msg 603 323 lightyellow; +#X obj 384 218 entry 100 50 grey70 black; +#X obj 386 167 hsl 128 15 0 127 0 0 empty empty empty -2 -6 0 10 -262144 +-1 -1 0 1; +#X obj 52 601 entry 100 50 grey70 black; +#X obj 51 556 symbol; +#X obj 161 636 pddp/pddplink http://tcl.tk/man/tcl8.4/TkCmd/cursors.htm +; +#X msg 49 521 boat; +#X msg 84 521 bogosity; +#X msg 52 577 option cursor \$1; +#X msg 9 521 clock; +#X msg 145 521 dot; +#X msg 175 521 dotbox; +#X msg 222 521 gumby; +#X msg 265 521 gobbler; +#X msg 266 590 pirate; +#X msg 266 547 mouse; +#X msg 266 569 target; +#X text 174 615 for more:; +#X msg 266 611 trek; +#X msg 384 194 option insertwidth \$1; +#X obj 386 48 hsl 128 15 0 127 0 0 empty empty empty -2 -6 0 10 -262144 +-1 -1 0 1; +#X msg 383 68 option borderwidth \$1; +#X msg 395 366 scrollbar \$1; +#X obj 395 346 tgl 15 0 empty empty empty 0 -6 0 10 -262144 -1 -1 0 +1; +#X connect 0 0 2 0; +#X connect 0 0 10 0; +#X connect 0 1 9 0; +#X connect 0 1 13 0; +#X connect 1 0 0 0; +#X connect 3 0 0 0; +#X connect 4 0 0 0; +#X connect 5 0 0 0; +#X connect 6 0 0 0; +#X connect 9 0 11 0; +#X connect 11 0 12 0; +#X connect 11 1 0 0; +#X connect 12 0 0 0; +#X connect 15 0 7 0; +#X connect 16 0 0 0; +#X connect 17 0 0 0; +#X connect 19 0 0 0; +#X connect 20 0 0 0; +#X connect 21 0 7 0; +#X connect 22 0 21 0; +#X connect 23 0 21 0; +#X connect 24 0 21 0; +#X connect 27 0 26 0; +#X connect 28 0 27 0; +#X connect 29 0 28 0; +#X connect 30 0 28 0; +#X connect 31 0 28 0; +#X connect 32 0 28 0; +#X connect 33 0 28 0; +#X connect 34 0 28 0; +#X connect 36 0 43 0; +#X connect 38 0 44 0; +#X connect 39 0 38 0; +#X connect 40 0 38 0; +#X connect 41 0 36 0; +#X connect 42 0 36 0; +#X connect 43 0 35 0; +#X connect 44 0 37 0; +#X connect 45 0 7 0; +#X connect 49 0 52 0; +#X connect 51 0 57 0; +#X connect 52 0 48 0; +#X connect 53 0 49 0; +#X connect 54 0 49 0; +#X connect 55 0 49 0; +#X connect 57 0 50 0; +#X connect 58 0 51 0; +#X connect 59 0 51 0; +#X connect 60 0 51 0; +#X connect 61 0 51 0; +#X connect 63 0 51 0; +#X connect 64 0 51 0; +#X connect 65 0 51 0; +#X connect 67 0 84 0; +#X connect 69 0 73 0; +#X connect 71 0 69 0; +#X connect 72 0 69 0; +#X connect 73 0 68 0; +#X connect 75 0 69 0; +#X connect 76 0 69 0; +#X connect 77 0 69 0; +#X connect 78 0 69 0; +#X connect 79 0 69 0; +#X connect 80 0 69 0; +#X connect 81 0 69 0; +#X connect 83 0 69 0; +#X connect 84 0 66 0; +#X connect 85 0 86 0; +#X connect 86 0 26 0; +#X connect 87 0 50 0; +#X connect 88 0 87 0; diff --git a/textbox.c b/textbox.c new file mode 100644 index 0000000..5b1c358 --- /dev/null +++ b/textbox.c @@ -0,0 +1,766 @@ +/* text textbox widget for PD * + * Based on button from GGEE by Guenter Geiger * + * Copyright Ben Bogart 2004 ben@ekran.org * + * Copyright 2007 Free Software Foundation * + + * This program is distributed under the terms of the GNU General Public * + * License * + + * textbox is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + + * textbox is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. */ + +#include +#include +#include +#include +#include + +/* TODO: make "display only" option, to force box to never accept focus */ +/* TODO: make focus option only accept regular and shifted chars, not Cmd, Alt, Ctrl */ +/* TODO: make textbox_save include whole classname, including namespace prefix */ +/* TODO: make [size( message redraw object */ +/* TODO: set message doesnt work with a loadbang */ +/* TODO: make message to add a single character to the existing text */ +/* TODO: complete inlet draw/erase logic */ + +#ifdef _MSC_VER +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +#ifndef IOWIDTH +#define IOWIDTH 4 +#endif + +#define BACKGROUNDCOLOR "grey70" + +#define DEBUG(x) x + +typedef struct _textbox +{ + t_object x_obj; + + t_glist * x_glist; + int x_rect_width; + int x_rect_height; + t_symbol* x_receive_name; + +/* TODO: these all should be settable by messages */ + int x_height; + int x_width; + + t_symbol* x_bgcolour; + t_symbol* x_fgcolour; + + t_symbol *x_font_face; + t_int x_font_size; + t_symbol *x_font_weight; + + t_float x_border; + t_float x_highlightthickness; + t_symbol *x_relief; + t_int x_have_scrollbar; + + t_outlet* x_data_outlet; + t_outlet* x_status_outlet; +} t_textbox; + + +static t_class *textbox_class; + + +static t_symbol *backspace_symbol; +static t_symbol *return_symbol; +static t_symbol *space_symbol; +static t_symbol *tab_symbol; +static t_symbol *escape_symbol; +static t_symbol *left_symbol; +static t_symbol *right_symbol; +static t_symbol *up_symbol; +static t_symbol *down_symbol; + +/* function prototypes */ + +static void textbox_getrect(t_gobj *z, t_glist *owner, int *xp1, int *yp1, int *xp2, int *yp2); +static void textbox_displace(t_gobj *z, t_glist *glist, int dx, int dy); +static void textbox_select(t_gobj *z, t_glist *glist, int state); +static void textbox_activate(t_gobj *z, t_glist *glist, int state); +static void textbox_delete(t_gobj *z, t_glist *glist); +static void textbox_vis(t_gobj *z, t_glist *glist, int vis); +static void textbox_save(t_gobj *z, t_binbuf *b); + + +t_widgetbehavior textbox_widgetbehavior = { +w_getrectfn: textbox_getrect, +w_displacefn: textbox_displace, +w_selectfn: textbox_select, +w_activatefn: textbox_activate, +w_deletefn: textbox_delete, +w_visfn: textbox_vis, +w_clickfn: NULL, +}; + +/* widget helper functions */ + +static int calculate_onset(t_textbox *x, t_glist *glist, int i, int nplus) +{ + return(text_xpix(&x->x_obj, glist) + (x->x_rect_width - IOWIDTH) * i / nplus); +} + +static void draw_inlets(t_textbox *x, t_glist *glist, int firsttime, int nin, int nout) +{ + DEBUG(post("draw_inlets in: %d out: %d", nin, nout);); + + int nplus, i, onset; + t_canvas *canvas = glist_getcanvas(glist); + + nplus = (nin == 1 ? 1 : nin-1); + /* inlets */ + for (i = 0; i < nin; i++) + { + onset = calculate_onset(x,glist,i,nplus); + if (firsttime) + { + DEBUG(post(".x%x.c create rectangle %d %d %d %d -tags {%xi%d %xi}\n", + canvas, onset, text_ypix(&x->x_obj, glist) - 2, + onset + IOWIDTH, text_ypix(&x->x_obj, glist) - 1, + x, i, x);); + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags {%xi%d %xi}\n", + canvas, onset, text_ypix(&x->x_obj, glist) - 2, + onset + IOWIDTH, text_ypix(&x->x_obj, glist) - 1, + x, i, x); + } + else + { + DEBUG(post(".x%x.c coords %xi%d %d %d %d %d\n", + canvas, x, i, onset, text_ypix(&x->x_obj, glist) - 2, + onset + IOWIDTH, text_ypix(&x->x_obj, glist) - 1);); + sys_vgui(".x%x.c coords %xi%d %d %d %d %d\n", + canvas, x, i, onset, text_ypix(&x->x_obj, glist) - 2, + onset + IOWIDTH, text_ypix(&x->x_obj, glist)- 1); + } + } + nplus = (nout == 1 ? 1 : nout-1); + for (i = 0; i < nout; i++) /* outlets */ + { + onset = calculate_onset(x,glist,i,nplus); + if (firsttime) + { + DEBUG(post(".x%x.c create rectangle %d %d %d %d -tags {%xo%d %xo}\n", + canvas, onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 2, + onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height-1, + x, i, x);); + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags {%xo%d %xo}\n", + canvas, onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 2, + onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height-1, + x, i, x); + } + else + { + DEBUG(post(".x%x.c coords %xo%d %d %d %d %d\n", + canvas, x, i, + onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 2, + onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height-1);); + sys_vgui(".x%x.c coords %xo%d %d %d %d %d\n", + canvas, x, i, + onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 2, + onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height-1); + } + } + DEBUG(post("draw inlet end");); +} + +static void erase_inlets(t_textbox *x, t_canvas *canvas) +{ + DEBUG(post("erase_inlets");); +/* Added tag for all inlets of one instance */ + DEBUG(post(".x%x.c delete %xi\n", canvas,x);); + sys_vgui(".x%x.c delete %xi\n", canvas,x); + DEBUG(post(".x%x.c delete %xo\n", canvas,x);); + sys_vgui(".x%x.c delete %xo\n", canvas,x); +/* Added tag for all outlets of one instance */ + DEBUG(post(".x%x.c delete %xhandle\n", canvas,x,0);); + sys_vgui(".x%x.c delete %xhandle\n", canvas,x,0); +} + +/* currently unused + static void draw_handle(t_textbox *x, t_glist *glist, int firsttime) { + int onset = text_xpix(&x->x_obj, glist) + (x->x_rect_width - IOWIDTH+2); + + if (firsttime) + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xhandle\n", + glist_getcanvas(glist), + onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 12, + onset + IOWIDTH-2, text_ypix(&x->x_obj, glist) + x->x_rect_height-4, + x); + else + sys_vgui(".x%x.c coords %xhandle %d %d %d %d\n", + glist_getcanvas(glist), x, + onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 12, + onset + IOWIDTH-2, text_ypix(&x->x_obj, glist) + x->x_rect_height-4); + } +*/ +static void draw_scrollbar(t_textbox *x) +{ + DEBUG(post("pack .x%x.c.s%x.scrollbar -side right -fill y -before .x%x.c.s%x.text \n", + x->x_glist, x, x->x_glist, x);); + sys_vgui("pack .x%x.c.s%x.scrollbar -side right -fill y -before .x%x.c.s%x.text \n", + x->x_glist, x, x->x_glist, x); + x->x_have_scrollbar = 1; +} + +static void erase_scrollbar(t_textbox *x) +{ + DEBUG(post("pack forget .x%x.c.s%x.scrollbar \n", x->x_glist, x);); + sys_vgui("pack forget .x%x.c.s%x.scrollbar \n", x->x_glist, x); + x->x_have_scrollbar = 0; +} + +static void create_widget(t_textbox *x, t_glist *glist) +{ + DEBUG(post("create_widget");); + t_canvas *canvas=glist_getcanvas(glist); + /* I guess this is for fine-tuning of the rect size based on width and height? */ + x->x_rect_width = x->x_width; + x->x_rect_height = x->x_height+2; + + DEBUG(post("namespace eval textbox%lx {} \n", x);); + sys_vgui("namespace eval textbox%lx {} \n", x); + + /* Seems we have to delete the widget in case it already exists (Provided by Guenter)*/ + DEBUG(post("destroy .x%x.c.s%x\n", canvas, x);); + sys_vgui("destroy .x%x.c.s%x\n", canvas, x); + + + DEBUG(post("frame .x%x.c.s%x \n",canvas, x);); + sys_vgui("frame .x%x.c.s%x \n",canvas, x); + DEBUG(post("text .x%x.c.s%x.text -font {%s %d %s} -border 1 \ + -highlightthickness 1 -relief sunken -bg \"%s\" -fg \"%s\" \ + -yscrollcommand {.x%x.c.s%x.scrollbar set} \n", + canvas, x, x->x_font_face->s_name, x->x_font_size, + x->x_font_weight->s_name, + x->x_bgcolour->s_name,x->x_fgcolour->s_name, + canvas, x);); + sys_vgui("text .x%x.c.s%x.text -font {%s %d %s} -border 1 \ + -highlightthickness 1 -relief sunken -bg \"%s\" -fg \"%s\" \ + -yscrollcommand {.x%x.c.s%x.scrollbar set} \n", + canvas, x, x->x_font_face->s_name, x->x_font_size, + x->x_font_weight->s_name, + x->x_bgcolour->s_name, x->x_fgcolour->s_name, + canvas, x); + DEBUG(post("scrollbar .x%x.c.s%x.scrollbar -command {.x%x.c.s%x.text yview} \n",canvas, x, canvas, x);); + sys_vgui("scrollbar .x%x.c.s%x.scrollbar -command {.x%x.c.s%x.text yview} \n",canvas, x ,canvas, x); + DEBUG(post("pack .x%x.c.s%x.scrollbar -side right -fill y \n",canvas, x);); + sys_vgui("pack .x%x.c.s%x.scrollbar -side right -fill y \n",canvas, x); + DEBUG(post("pack .x%x.c.s%x.text -side left -fill both -expand 1 \n",canvas, x);); + sys_vgui("pack .x%x.c.s%x.text -side left -fill both -expand 1 \n",canvas, x); + DEBUG(post("pack .x%x.c.s%x -side bottom -fill both -expand 1 \n",canvas, x);); + sys_vgui("pack .x%x.c.s%x -side bottom -fill both -expand 1 \n",canvas, x); + + DEBUG(post("bind .x%x.c.s%x.text {+pd %s keyup %%N \\;} \n", + canvas, x, x->x_receive_name->s_name);); + sys_vgui("bind .x%x.c.s%x.text {+pd %s keyup %%N \\;} \n", + canvas, x, x->x_receive_name->s_name); + DEBUG(post("bind .x%x.c.s%x.text {focus [winfo parent .x%x.c.s%x]} \n", + canvas, x, canvas, x);); + sys_vgui("bind .x%x.c.s%x.text {focus [winfo parent .x%x.c.s%x]} \n", + canvas, x, canvas, x); +} + +static void textbox_drawme(t_textbox *x, t_glist *glist, int firsttime) +{ + DEBUG(post("textbox_drawme");); + t_canvas *canvas=glist_getcanvas(glist); + DEBUG(post("drawme %d",firsttime);); + if (firsttime) + { + x->x_glist = canvas; + create_widget(x,glist); + DEBUG(post(".x%x.c create window %d %d -anchor nw -window .x%x.c.s%x \ + -tags %xS -width %d -height %d \n", canvas, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + canvas, x, x, x->x_width, x->x_height);); + sys_vgui(".x%x.c create window %d %d -anchor nw -window .x%x.c.s%x \ + -tags %xS -width %d -height %d \n", canvas, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + canvas, x,x, x->x_width, x->x_height); + } + else + { + DEBUG(post(".x%x.c coords %xS %d %d\n", canvas, x, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist));); + sys_vgui(".x%x.c coords %xS %d %d\n", canvas, x, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)); + } + post("canvas: %d glist: %d", canvas->gl_edit, glist->gl_edit); + if( (x->x_glist->gl_edit) && (canvas == x->x_glist) ) + draw_inlets(x, glist, firsttime, 1,2); + else + erase_inlets(x, canvas); + // draw_handle(x, glist, firsttime); +} + + +static void textbox_erase(t_textbox* x,t_glist* glist) +{ + DEBUG(post("textbox_erase");); + t_canvas *canvas = glist_getcanvas(glist); + DEBUG(post("destroy .x%x.c.s%x\n", canvas, x);); + sys_vgui("destroy .x%x.c.s%x\n", canvas, x); + + DEBUG(post(".x%x.c delete %xS\n", canvas, x);); + sys_vgui(".x%x.c delete %xS\n", canvas, x); + + erase_inlets(x, canvas); +} + + + +/* ------------------------ text widgetbehaviour----------------------------- */ + + +static void textbox_getrect(t_gobj *z, t_glist *owner, + int *xp1, int *yp1, int *xp2, int *yp2) +{ +/* DEBUG(post("textbox_getrect");); */ + int width, height; + t_textbox* s = (t_textbox*)z; + + width = s->x_rect_width; + height = s->x_rect_height; + *xp1 = text_xpix(&s->x_obj, owner); + *yp1 = text_ypix(&s->x_obj, owner) - 1; + *xp2 = text_xpix(&s->x_obj, owner) + width; + *yp2 = text_ypix(&s->x_obj, owner) + height; +} + +static void textbox_displace(t_gobj *z, t_glist *glist, int dx, int dy) +{ + DEBUG(post("textbox_displace");); + t_textbox *x = (t_textbox *)z; + x->x_obj.te_xpix += dx; + x->x_obj.te_ypix += dy; + if (glist_isvisible(glist)) + { + t_canvas *canvas = glist_getcanvas(glist); + DEBUG(post(".x%x.c coords %xSEL %d %d %d %d\n", canvas, x, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)-1, + text_xpix(&x->x_obj, glist) + x->x_rect_width, + text_ypix(&x->x_obj, glist) + x->x_rect_height-2);); + sys_vgui(".x%x.c coords %xSEL %d %d %d %d\n", canvas, x, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)-1, + text_xpix(&x->x_obj, glist) + x->x_rect_width, + text_ypix(&x->x_obj, glist) + x->x_rect_height-2); + + textbox_drawme(x, glist, 0); + canvas_fixlinesfor(canvas, (t_text*) x); + } + DEBUG(post("displace end");); +} + +static void textbox_select(t_gobj *z, t_glist *glist, int state) +{ + DEBUG(post("textbox_select");); + t_textbox *x = (t_textbox *)z; + t_canvas *canvas = glist_getcanvas(glist); + if (state) { + DEBUG(post(".x%x.c create rectangle %d %d %d %d -tags %xSEL -outline blue\n", + canvas, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)-1, + text_xpix(&x->x_obj, glist) + x->x_rect_width, + text_ypix(&x->x_obj, glist) + x->x_rect_height-2, x);); + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xSEL -outline blue\n", + canvas, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)-1, + text_xpix(&x->x_obj, glist) + x->x_rect_width, + text_ypix(&x->x_obj, glist) + x->x_rect_height-2, x); + } + else { + DEBUG(post(".x%x.c delete %xSEL\n", canvas, x);); + sys_vgui(".x%x.c delete %xSEL\n", canvas, x); + } +} + +static void textbox_activate(t_gobj *z, t_glist *glist, int state) +{ + DEBUG(post("textbox_activate");); +/* this is currently unused + t_text *x = (t_text *)z; + t_rtext *y = glist_findrtext(glist, x); + if (z->g_pd != gatom_class) rtext_activate(y, state); +*/ +} + +static void textbox_delete(t_gobj *z, t_glist *glist) +{ + DEBUG(post("textbox_delete");); + t_text *x = (t_text *)z; + canvas_deletelinesfor(glist_getcanvas(glist), x); +} + + +static void textbox_vis(t_gobj *z, t_glist *glist, int vis) +{ + DEBUG(post("textbox_vis");); + t_textbox* s = (t_textbox*)z; + t_rtext *y; + DEBUG(post("vis: %d",vis);); + if (vis) { + y = (t_rtext *) rtext_new(glist, (t_text *)z); + textbox_drawme(s, glist, 1); + } + else { + y = glist_findrtext(glist, (t_text *)z); + textbox_erase(s,glist); + rtext_free(y); + } +} + +static void textbox_add(t_textbox* x, t_symbol *s, int argc, t_atom *argv) +{ + DEBUG(post("textbox_add");); + int i; + t_symbol *tmp_symbol = s; /* <-- this gets rid of the unused variable warning */ + t_float tmp_float; + + for(i=0; is_name );); + sys_vgui("lappend ::textbox%lx::list %s \n", x, tmp_symbol->s_name ); + } + } + DEBUG(post("append ::textbox%lx::list \" \"\n", x);); + sys_vgui("append ::textbox%lx::list \" \"\n", x); + DEBUG(post(".x%x.c.s%x.text insert end $::textbox%lx::list ; unset ::textbox%lx::list \n", + x->x_glist, x, x, x );); + sys_vgui(".x%x.c.s%x.text insert end $::textbox%lx::list ; unset ::textbox%lx::list \n", + x->x_glist, x, x, x ); + DEBUG(post(".x%x.c.s%x.text yview end-2char \n", x->x_glist, x );); + sys_vgui(".x%x.c.s%x.text yview end-2char \n", x->x_glist, x ); +} + +/* Clear the contents of the text widget */ +static void textbox_clear(t_textbox* x) +{ + DEBUG(post(".x%x.c.s%x.text delete 0.0 end \n", x->x_glist, x);); + sys_vgui(".x%x.c.s%x.text delete 0.0 end \n", x->x_glist, x); +} + +/* Function to reset the contents of the textbox box */ +static void textbox_set(t_textbox* x, t_symbol *s, int argc, t_atom *argv) +{ + DEBUG(post("textbox_set");); + int i; + + textbox_clear(x); + textbox_add(x, s, argc, argv); +} + +/* Output the symbol */ +/* , t_symbol *s, int argc, t_atom *argv) */ +static void textbox_output(t_textbox* x, t_symbol *s, int argc, t_atom *argv) +{ + outlet_list(x->x_data_outlet, s, argc, argv ); +} + +/* Pass the contents of the text widget onto the textbox_output fuction above */ +static void textbox_bang_output(t_textbox* x) +{ + /* With "," and ";" escaping thanks to JMZ */ + DEBUG(post("pd [concat %s output [string map {\",\" \"\\\\,\" \";\" \"\\\\;\"} \ + [.x%x.c.s%x.text get 0.0 end]] \\;]\n", + x->x_receive_name->s_name, x->x_glist, x);); + sys_vgui("pd [concat %s output [string map {\",\" \"\\\\,\" \";\" \"\\\\;\"} \ + [.x%x.c.s%x.text get 0.0 end]] \\;]\n", + x->x_receive_name->s_name, x->x_glist, x); + + DEBUG(post("bind .x%x.c.s%x.text {focus [winfo parent .x%x.c.s%x]} \n", + x->x_glist, x, x->x_glist, x);); + sys_vgui("bind .x%x.c.s%x.text {focus [winfo parent .x%x.c.s%x]} \n", + x->x_glist, x, x->x_glist, x); +} + +static void textbox_keyup(t_textbox *x, t_float f) +{ +/* DEBUG(post("textbox_keyup");); */ + int keycode = (int) f; + char buf[10]; + t_symbol *output_symbol; + + if( (keycode > 32 ) && (keycode < 65288) ) + { + snprintf(buf, 2, "%c", keycode); + output_symbol = gensym(buf); + } else + switch(keycode) + { + case 32: /* space */ + output_symbol = space_symbol; + break; + case 65293: /* return */ + output_symbol = return_symbol; + break; + case 65288: /* backspace */ + output_symbol = backspace_symbol; + break; + case 65289: /* tab */ + output_symbol = tab_symbol; + break; + case 65307: /* escape */ + output_symbol = escape_symbol; + break; + case 65361: /* left */ + output_symbol = left_symbol; + break; + case 65363: /* right */ + output_symbol = right_symbol; + break; + case 65362: /* up */ + output_symbol = up_symbol; + break; + case 65364: /* down */ + output_symbol = down_symbol; + break; + default: + snprintf(buf, 10, "key_%d", keycode); + DEBUG(post("keyup: %d", keycode);); + output_symbol = gensym(buf); + } + outlet_symbol(x->x_status_outlet, output_symbol); +} + +static void textbox_save(t_gobj *z, t_binbuf *b) +{ + t_textbox *x = (t_textbox *)z; + + binbuf_addv(b, "ssiisiiss", gensym("#X"),gensym("obj"), + x->x_obj.te_xpix, x->x_obj.te_ypix, + gensym("textbox"), x->x_width, x->x_height, x->x_bgcolour, x->x_fgcolour); + binbuf_addv(b, ";"); +} + + +static void textbox_option_float(t_textbox* x, t_symbol *option, t_float value) +{ + DEBUG(post(".x%x.c.s%x.text configure -%s %f \n", + x->x_glist, x, option->s_name, value);); + sys_vgui(".x%x.c.s%x.text configure -%s %f \n", + x->x_glist, x, option->s_name, value); +} + +static void textbox_option_symbol(t_textbox* x, t_symbol *option, t_symbol *value) +{ + DEBUG(post(".x%x.c.s%x.text configure -%s {%s} \n", + x->x_glist, x, option->s_name, value->s_name);); + sys_vgui(".x%x.c.s%x.text configure -%s {%s} \n", + x->x_glist, x, option->s_name, value->s_name); +} + +static void textbox_option(t_textbox *x, t_symbol *s, int argc, t_atom *argv) +{ + t_symbol *tmp_symbol = s; /* <-- this gets rid of the unused variable warning */ + + tmp_symbol = atom_getsymbolarg(1, argc, argv); + if(tmp_symbol == &s_) + { + textbox_option_float(x,atom_getsymbolarg(0, argc, argv), + atom_getfloatarg(1, argc, argv)); + } + else + { + textbox_option_symbol(x,atom_getsymbolarg(0, argc, argv),tmp_symbol); + } +} + +static void textbox_scrollbar(t_textbox *x, t_float f) +{ + if(f > 0) + draw_scrollbar(x); + else + erase_scrollbar(x); +} + + +/* function to change colour of text background */ +void textbox_bgcolour(t_textbox* x, t_symbol* bgcol) +{ + x->x_bgcolour = bgcol; + DEBUG(post(".x%x.c.s%x.text configure -background \"%s\" \n", + x->x_glist, x, x->x_bgcolour->s_name);); + sys_vgui(".x%x.c.s%x.text configure -background \"%s\" \n", + x->x_glist, x, x->x_bgcolour->s_name); +} + +/* function to change colour of text foreground */ +void textbox_fgcolour(t_textbox* x, t_symbol* fgcol) +{ + x->x_fgcolour = fgcol; + DEBUG(post(".x%x.c.s%x.text configure -foreground \"%s\" \n", + x->x_glist, x, x->x_fgcolour->s_name);); + sys_vgui(".x%x.c.s%x.text configure -foreground \"%s\" \n", + x->x_glist, x, x->x_fgcolour->s_name); +} + +static void textbox_fontsize(t_textbox *x, t_float font_size) +{ + DEBUG(post("textbox_fontsize");); + post("font size: %f",font_size); + if(font_size > 8) + { + x->x_font_size = (t_int)font_size; + DEBUG(post(".x%x.c.s%x.text configure -font {%s %d %s} \n", + x->x_glist, x, + x->x_font_face->s_name, x->x_font_size, x->x_font_weight->s_name);); + sys_vgui(".x%x.c.s%x.text configure -font {%s %d %s} \n", + x->x_glist, x, + x->x_font_face->s_name, x->x_font_size, + x->x_font_weight->s_name); + } + else + pd_error(x,"textbox: invalid font size: %f",font_size); +} + +static void textbox_size(t_textbox *x, t_float width, t_float height) +{ + DEBUG(post("textbox_size");); + x->x_height = height; + x->x_width = width; +} + +static void textbox_free(t_textbox *x) +{ + pd_unbind(&x->x_obj.ob_pd, x->x_receive_name); +} + +static void *textbox_new(t_symbol *s, int argc, t_atom *argv) +{ + DEBUG(post("textbox_new");); + t_textbox *x = (t_textbox *)pd_new(textbox_class); + char buf[MAXPDSTRING]; + + x->x_height = 1; + x->x_font_face = gensym("helvetica"); + x->x_font_size = 10; + x->x_font_weight = gensym("normal"); + x->x_have_scrollbar = 1; + + if (argc < 4) + { + post("textbox: You must enter at least 4 arguments. Default values used."); + x->x_width = 124; + x->x_height = 100; + x->x_bgcolour = gensym("grey70"); + x->x_fgcolour = gensym("black"); + + } else { + /* Copy args into structure */ + x->x_width = atom_getint(argv); + x->x_height = atom_getint(argv+1); + x->x_bgcolour = atom_getsymbol(argv+2); + x->x_fgcolour = atom_getsymbol(argv+3); + } + + x->x_data_outlet = outlet_new(&x->x_obj, &s_float); + x->x_status_outlet = outlet_new(&x->x_obj, &s_symbol); + + snprintf(buf,MAXPDSTRING,"#textbox%lx",(long unsigned int)x); + x->x_receive_name = gensym(buf); + pd_bind(&x->x_obj.ob_pd, x->x_receive_name); + + return (x); +} + +void textbox_setup(void) { + textbox_class = class_new(gensym("textbox"), (t_newmethod)textbox_new, + (t_method)textbox_free, sizeof(t_textbox),0,A_GIMME,0); + + class_addbang(textbox_class, (t_method)textbox_bang_output); + + class_addmethod(textbox_class, (t_method)textbox_keyup, + gensym("keyup"), + A_DEFFLOAT, + 0); + + class_addmethod(textbox_class, (t_method)textbox_scrollbar, + gensym("scrollbar"), + A_DEFFLOAT, + 0); + + class_addmethod(textbox_class, (t_method)textbox_option, + gensym("option"), + A_GIMME, + 0); + + class_addmethod(textbox_class, (t_method)textbox_size, + gensym("size"), + A_DEFFLOAT, + A_DEFFLOAT, + 0); + + class_addmethod(textbox_class, (t_method)textbox_fontsize, + gensym("fontsize"), + A_DEFFLOAT, + 0); + + class_addmethod(textbox_class, (t_method)textbox_output, + gensym("output"), + A_GIMME, + 0); + + class_addmethod(textbox_class, (t_method)textbox_set, + gensym("set"), + A_GIMME, + 0); + + class_addmethod(textbox_class, (t_method)textbox_add, + gensym("add"), + A_GIMME, + 0); + + class_addmethod(textbox_class, (t_method)textbox_clear, + gensym("clear"), + 0); + + class_addmethod(textbox_class, (t_method)textbox_bgcolour, + gensym("bgcolour"), + A_DEFSYMBOL, + 0); + + class_addmethod(textbox_class, (t_method)textbox_fgcolour, + gensym("fgcolour"), + A_DEFSYMBOL, + 0); + + class_setwidget(textbox_class,&textbox_widgetbehavior); + class_setsavefn(textbox_class,&textbox_save); + + backspace_symbol = gensym("backspace"); + return_symbol = gensym("return"); + space_symbol = gensym("space"); + tab_symbol = gensym("tab"); + escape_symbol = gensym("escape"); + left_symbol = gensym("left"); + right_symbol = gensym("right"); + up_symbol = gensym("up"); + down_symbol = gensym("down"); + + post("Text v0.1 Ben Bogart.\nCVS: $Revision: 1.1 $ $Date: 2007-10-28 21:19:50 $"); +} + + -- cgit v1.2.1