A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1/* Copyright (c) 1997-1999 Miller Puckette.
2* For information on usage and redistribution, and for a DISCLAIMER OF ALL
3* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
4
5/* changes by Thomas Musil IEM KUG Graz Austria 2001 */
6/* have to insert gui-objects into editor-list */
7/* all changes are labeled with iemlib */
8
9#ifdef ROCKBOX
10#include "plugin.h"
11#include "ctype.h"
12#include "../../pdbox.h"
13#include "m_pd.h"
14#include "g_canvas.h"
15#define snprintf rb->snprintf
16#else /* ROCKBOX */
17#include <stdlib.h>
18#include <string.h>
19#include <stdio.h>
20#include <ctype.h>
21#include "m_pd.h"
22#include "s_stuff.h"
23#include "g_canvas.h"
24#include "t_tk.h"
25#endif /* ROCKBOX */
26
27#define LMARGIN 1
28#define RMARGIN 1
29#define TMARGIN 2
30#define BMARGIN 2
31
32#define SEND_FIRST 1
33#define SEND_UPDATE 2
34#define SEND_CHECK 0
35
36struct _rtext
37{
38 char *x_buf;
39 int x_bufsize;
40 int x_selstart;
41 int x_selend;
42 int x_active;
43 int x_dragfrom;
44 int x_height;
45 int x_drawnwidth;
46 int x_drawnheight;
47 t_text *x_text;
48 t_glist *x_glist;
49 char x_tag[50];
50 struct _rtext *x_next;
51};
52
53t_rtext *rtext_new(t_glist *glist, t_text *who)
54{
55 t_rtext *x = (t_rtext *)getbytes(sizeof *x);
56#ifndef ROCKBOX
57 int w = 0, h = 0, indx;
58#endif
59 x->x_height = -1;
60 x->x_text = who;
61 x->x_glist = glist;
62 x->x_next = glist->gl_editor->e_rtext;
63 x->x_selstart = x->x_selend = x->x_active =
64 x->x_drawnwidth = x->x_drawnheight = 0;
65 binbuf_gettext(who->te_binbuf, &x->x_buf, &x->x_bufsize);
66 glist->gl_editor->e_rtext = x;
67#ifdef ROCKBOX
68 snprintf(x->x_tag, strlen(x->x_tag),
69 ".x%lx.t%lx", (unsigned long) (t_int) glist_getcanvas(x->x_glist),
70 (unsigned long) (t_int) x);
71#else /* ROCKBOX */
72 sprintf(x->x_tag, ".x%x.t%x", (t_int)glist_getcanvas(x->x_glist),
73 (t_int)x);
74#endif /* ROCKBOX */
75 return (x);
76}
77
78static t_rtext *rtext_entered;
79
80void rtext_free(t_rtext *x)
81{
82 if (x->x_glist->gl_editor->e_textedfor == x)
83 x->x_glist->gl_editor->e_textedfor = 0;
84 if (x->x_glist->gl_editor->e_rtext == x)
85 x->x_glist->gl_editor->e_rtext = x->x_next;
86 else
87 {
88 t_rtext *e2;
89 for (e2 = x->x_glist->gl_editor->e_rtext; e2; e2 = e2->x_next)
90 if (e2->x_next == x)
91 {
92 e2->x_next = x->x_next;
93 break;
94 }
95 }
96 if (rtext_entered == x) rtext_entered = 0;
97 freebytes(x->x_buf, x->x_bufsize);
98 freebytes(x, sizeof *x);
99}
100
101char *rtext_gettag(t_rtext *x)
102{
103 return (x->x_tag);
104}
105
106void rtext_gettext(t_rtext *x, char **buf, int *bufsize)
107{
108 *buf = x->x_buf;
109 *bufsize = x->x_bufsize;
110}
111
112
113/* LATER deal with tcl-significant characters */
114
115static int firstone(char *s, int c, int n)
116{
117 char *s2 = s + n;
118 int i = 0;
119 while (s != s2)
120 {
121 if (*s == c) return (i);
122 i++;
123 s++;
124 }
125 return (-1);
126}
127
128static int lastone(char *s, int c, int n)
129{
130 char *s2 = s + n;
131 while (s2 != s)
132 {
133 s2--;
134 n--;
135 if (*s2 == c) return (n);
136 }
137 return (-1);
138}
139
140 /* the following routine computes line breaks and carries out
141 some action which could be:
142 SEND_FIRST - draw the box for the first time
143 SEND_UPDATE - redraw the updated box
144 otherwise - don't draw, just calculate.
145 Called with *widthp and *heightpas coordinates of
146 a test point, the routine reports the index of the character found
147 there in *indexp. *widthp and *heightp are set to the width and height
148 of the entire text in pixels.
149 */
150
151 /* LATER get this and sys_vgui to work together properly,
152 breaking up messages as needed. As of now, there's
153 a limit of 1950 characters, imposed by sys_vgui(). */
154#define UPBUFSIZE 4000
155#define BOXWIDTH 60
156
157/* Older (pre-8.3.4) TCL versions handle text selection differently; this
158flag is set from the GUI if this happens. LATER take this out: early 2006? */
159
160extern int sys_oldtclversion;
161
162static void rtext_senditup(t_rtext *x, int action, int *widthp, int *heightp,
163 int *indexp)
164{
165#ifndef ROCKBOX
166 float dispx, dispy;
167#endif
168 char tempbuf[UPBUFSIZE], *tp = tempbuf, *bp = x->x_buf;
169 int outchars, inchars = x->x_bufsize, nlines = 0, ncolumns = 0,
170 pixwide, pixhigh;
171#ifdef ROCKBOX
172 int fontwidth = 8, fontheight = 10;
173#else
174 int font = glist_getfont(x->x_glist);
175 int fontwidth = sys_fontwidth(font), fontheight = sys_fontheight(font);
176#endif
177 int findx = (*widthp + (fontwidth/2)) / fontwidth,
178 findy = *heightp / fontheight;
179 int reportedindex = 0;
180#ifndef ROCKBOX
181 t_canvas *canvas = glist_getcanvas(x->x_glist);
182#endif
183 int widthspec = x->x_text->te_width;
184 int widthlimit = (widthspec ? widthspec : BOXWIDTH);
185 while (inchars)
186 {
187 int maxindex = (inchars > widthlimit ? widthlimit : inchars);
188 int eatchar = 1;
189 int foundit = firstone(bp, '\n', maxindex);
190 if (foundit < 0)
191 {
192 if (inchars > widthlimit)
193 {
194 foundit = lastone(bp, ' ', maxindex);
195 if (foundit < 0)
196 {
197 foundit = maxindex;
198 eatchar = 0;
199 }
200 }
201 else
202 {
203 foundit = inchars;
204 eatchar = 0;
205 }
206 }
207 if (nlines == findy)
208 {
209 int actualx = (findx < 0 ? 0 :
210 (findx > foundit ? foundit : findx));
211 *indexp = (bp - x->x_buf) + actualx;
212 reportedindex = 1;
213 }
214 strncpy(tp, bp, foundit);
215 tp += foundit;
216 bp += (foundit + eatchar);
217 inchars -= (foundit + eatchar);
218 if (inchars) *tp++ = '\n';
219 if (foundit > ncolumns) ncolumns = foundit;
220 nlines++;
221 }
222 outchars = tp - tempbuf;
223 if (outchars > 1950) outchars = 1950;
224 if (!reportedindex)
225 *indexp = outchars;
226#ifndef ROCKBOX
227 dispx = text_xpix(x->x_text, x->x_glist);
228 dispy = text_ypix(x->x_text, x->x_glist);
229#endif
230 if (nlines < 1) nlines = 1;
231 if (!widthspec)
232 {
233 while (ncolumns < 3)
234 {
235 tempbuf[outchars++] = ' ';
236 ncolumns++;
237 }
238 }
239 else ncolumns = widthspec;
240 pixwide = ncolumns * fontwidth + (LMARGIN + RMARGIN);
241 pixhigh = nlines * fontheight + (TMARGIN + BMARGIN);
242
243 if (action == SEND_FIRST)
244#ifdef ROCKBOX
245 ;
246#else /* ROCKBOX */
247 sys_vgui("pdtk_text_new .x%x.c %s %f %f {%.*s} %d %s\n",
248 canvas, x->x_tag,
249 dispx + LMARGIN, dispy + TMARGIN,
250 outchars, tempbuf, sys_hostfontsize(font),
251 (glist_isselected(x->x_glist,
252 &x->x_glist->gl_gobj)? "blue" : "black"));
253#endif /* ROCKBOX */
254 else if (action == SEND_UPDATE)
255 {
256#ifndef ROCKBOX
257 sys_vgui("pdtk_text_set .x%x.c %s {%.*s}\n",
258 canvas, x->x_tag, outchars, tempbuf);
259#endif
260 if (pixwide != x->x_drawnwidth || pixhigh != x->x_drawnheight)
261 text_drawborder(x->x_text, x->x_glist, x->x_tag,
262 pixwide, pixhigh, 0);
263 if (x->x_active)
264 {
265 if (x->x_selend > x->x_selstart)
266 {
267#ifndef ROCKBOX
268 sys_vgui(".x%x.c select from %s %d\n", canvas,
269 x->x_tag, x->x_selstart);
270 sys_vgui(".x%x.c select to %s %d\n", canvas,
271 x->x_tag, x->x_selend + (sys_oldtclversion ? 0 : -1));
272 sys_vgui(".x%x.c focus \"\"\n", canvas);
273#endif
274 }
275 else
276 {
277#ifndef ROCKBOX
278 sys_vgui(".x%x.c select clear\n", canvas);
279 sys_vgui(".x%x.c icursor %s %d\n", canvas, x->x_tag,
280 x->x_selstart);
281 sys_vgui(".x%x.c focus %s\n", canvas, x->x_tag);
282#endif
283 }
284 }
285 }
286 x->x_drawnwidth = pixwide;
287 x->x_drawnheight = pixhigh;
288
289 *widthp = pixwide;
290 *heightp = pixhigh;
291}
292
293void rtext_retext(t_rtext *x)
294{
295 int w = 0, h = 0, indx;
296 t_text *text = x->x_text;
297 t_freebytes(x->x_buf, x->x_bufsize);
298 binbuf_gettext(text->te_binbuf, &x->x_buf, &x->x_bufsize);
299 /* special case: for number boxes, try to pare the number down
300 to the specified width of the box. */
301 if (text->te_width > 0 && text->te_type == T_ATOM &&
302 x->x_bufsize > text->te_width)
303 {
304 t_atom *atomp = binbuf_getvec(text->te_binbuf);
305 int natom = binbuf_getnatom(text->te_binbuf);
306 int bufsize = x->x_bufsize;
307 if (natom == 1 && atomp->a_type == A_FLOAT)
308 {
309 /* try to reduce size by dropping decimal digits */
310 int wantreduce = bufsize - text->te_width;
311 char *decimal = 0, *nextchar, *ebuf = x->x_buf + bufsize,
312 *s1, *s2;
313#ifndef ROCKBOX
314 int ndecimals;
315#endif
316 for (decimal = x->x_buf; decimal < ebuf; decimal++)
317 if (*decimal == '.')
318 break;
319 if (decimal >= ebuf)
320 goto giveup;
321 for (nextchar = decimal + 1; nextchar < ebuf; nextchar++)
322 if (*nextchar < '0' || *nextchar > '9')
323 break;
324 if (nextchar - decimal - 1 < wantreduce)
325 goto giveup;
326 for (s1 = nextchar - wantreduce, s2 = s1 + wantreduce;
327 s2 < ebuf; s1++, s2++)
328 *s1 = *s2;
329 t_resizebytes(x->x_buf, bufsize, text->te_width);
330 bufsize = text->te_width;
331 goto done;
332 giveup:
333 /* give up and bash it to "+" or "-" */
334 x->x_buf[0] = (atomp->a_w.w_float < 0 ? '-' : '+');
335 t_resizebytes(x->x_buf, bufsize, 1);
336 bufsize = 1;
337 }
338 else if (bufsize > text->te_width)
339 {
340 x->x_buf[text->te_width - 1] = '>';
341 t_resizebytes(x->x_buf, bufsize, text->te_width);
342 bufsize = text->te_width;
343 }
344 done:
345 x->x_bufsize = bufsize;
346 }
347 rtext_senditup(x, SEND_UPDATE, &w, &h, &indx);
348}
349
350/* find the rtext that goes with a text item */
351t_rtext *glist_findrtext(t_glist *gl, t_text *who)
352{
353 t_rtext *x = gl->gl_editor->e_rtext;
354 while (x && x->x_text != who) x = x->x_next;
355 if (!x) bug("glist_findrtext");
356 return (x);
357}
358
359int rtext_width(t_rtext *x)
360{
361 int w = 0, h = 0, indx;
362 rtext_senditup(x, SEND_CHECK, &w, &h, &indx);
363 return (w);
364}
365
366int rtext_height(t_rtext *x)
367{
368 int w = 0, h = 0, indx;
369 rtext_senditup(x, SEND_CHECK, &w, &h, &indx);
370 return (h);
371}
372
373void rtext_draw(t_rtext *x)
374{
375 int w = 0, h = 0, indx;
376 rtext_senditup(x, SEND_FIRST, &w, &h, &indx);
377}
378
379void rtext_erase(t_rtext *x)
380{
381#ifdef ROCKBOX
382 (void) x;
383#else
384 sys_vgui(".x%x.c delete %s\n", glist_getcanvas(x->x_glist), x->x_tag);
385#endif
386}
387
388void rtext_displace(t_rtext *x, int dx, int dy)
389{
390#ifdef ROCKBOX
391 (void) x;
392 (void) dx;
393 (void) dy;
394#else /* ROCKBOX */
395 sys_vgui(".x%x.c move %s %d %d\n", glist_getcanvas(x->x_glist),
396 x->x_tag, dx, dy);
397#endif /* ROCKBOX */
398}
399
400void rtext_select(t_rtext *x, int state)
401{
402 t_glist *glist = x->x_glist;
403 t_canvas *canvas = glist_getcanvas(glist);
404#ifdef ROCKBOX
405 (void) state;
406#else /* ROCKBOX */
407 sys_vgui(".x%x.c itemconfigure %s -fill %s\n", canvas,
408 x->x_tag, (state? "blue" : "black"));
409#endif /* ROCKBOX */
410 canvas_editing = canvas;
411}
412
413void rtext_activate(t_rtext *x, int state)
414{
415 int w = 0, h = 0, indx;
416 t_glist *glist = x->x_glist;
417#ifndef ROCKBOX
418 t_canvas *canvas = glist_getcanvas(glist);
419#endif
420 if (state)
421 {
422#ifndef ROCKBOX
423 sys_vgui(".x%x.c focus %s\n", canvas, x->x_tag);
424#endif
425 glist->gl_editor->e_textedfor = x;
426 glist->gl_editor->e_textdirty = 0;
427 x->x_dragfrom = x->x_selstart = 0;
428 x->x_selend = x->x_bufsize;
429 x->x_active = 1;
430 }
431 else
432 {
433#ifndef ROCKBOX
434 sys_vgui("selection clear .x%x.c\n", canvas);
435 sys_vgui(".x%x.c focus \"\"\n", canvas);
436#endif
437 if (glist->gl_editor->e_textedfor == x)
438 glist->gl_editor->e_textedfor = 0;
439 x->x_active = 0;
440 }
441 rtext_senditup(x, SEND_UPDATE, &w, &h, &indx);
442}
443
444void rtext_key(t_rtext *x, int keynum, t_symbol *keysym)
445{
446 int w = 0, h = 0, indx, i, newsize, ndel;
447#ifndef ROCKBOX
448 char *s1, *s2;
449#endif
450 if (keynum)
451 {
452 int n = keynum;
453 if (n == '\r') n = '\n';
454 if (n == '\b') /* backspace */
455 {
456 /* LATER delete the box if all text is selected...
457 this causes reentrancy problems now. */
458 /* if ((!x->x_selstart) && (x->x_selend == x->x_bufsize))
459 {
460 ....
461 } */
462 if (x->x_selstart && (x->x_selstart == x->x_selend))
463 x->x_selstart--;
464 }
465 else if (n == 127) /* delete */
466 {
467 if (x->x_selend < x->x_bufsize && (x->x_selstart == x->x_selend))
468 x->x_selend++;
469 }
470
471 ndel = x->x_selend - x->x_selstart;
472 for (i = x->x_selend; i < x->x_bufsize; i++)
473 x->x_buf[i- ndel] = x->x_buf[i];
474 newsize = x->x_bufsize - ndel;
475 x->x_buf = resizebytes(x->x_buf, x->x_bufsize, newsize);
476 x->x_bufsize = newsize;
477
478 if (n == '\n' || isprint(n))
479 {
480 newsize = x->x_bufsize+1;
481 x->x_buf = resizebytes(x->x_buf, x->x_bufsize, newsize);
482 for (i = x->x_bufsize; i > x->x_selstart; i--)
483 x->x_buf[i] = x->x_buf[i-1];
484 x->x_buf[x->x_selstart] = n;
485 x->x_bufsize = newsize;
486 x->x_selstart = x->x_selstart + 1;
487 }
488 x->x_selend = x->x_selstart;
489 x->x_glist->gl_editor->e_textdirty = 1;
490 }
491 else if (!strcmp(keysym->s_name, "Right"))
492 {
493 if (x->x_selend == x->x_selstart && x->x_selstart < x->x_bufsize)
494 x->x_selend = x->x_selstart = x->x_selstart + 1;
495 else
496 x->x_selstart = x->x_selend;
497 }
498 else if (!strcmp(keysym->s_name, "Left"))
499 {
500 if (x->x_selend == x->x_selstart && x->x_selstart > 0)
501 x->x_selend = x->x_selstart = x->x_selstart - 1;
502 else
503 x->x_selend = x->x_selstart;
504 }
505 /* this should be improved... life's too short */
506 else if (!strcmp(keysym->s_name, "Up"))
507 {
508 if (x->x_selstart)
509 x->x_selstart--;
510 while (x->x_selstart > 0 && x->x_buf[x->x_selstart] != '\n')
511 x->x_selstart--;
512 x->x_selend = x->x_selstart;
513 }
514 else if (!strcmp(keysym->s_name, "Down"))
515 {
516 while (x->x_selend < x->x_bufsize &&
517 x->x_buf[x->x_selend] != '\n')
518 x->x_selend++;
519 if (x->x_selend < x->x_bufsize)
520 x->x_selend++;
521 x->x_selstart = x->x_selend;
522 }
523 rtext_senditup(x, SEND_UPDATE, &w, &h, &indx);
524}
525
526void rtext_mouse(t_rtext *x, int xval, int yval, int flag)
527{
528 int w = xval, h = yval, indx;
529 rtext_senditup(x, SEND_CHECK, &w, &h, &indx);
530 if (flag == RTEXT_DOWN)
531 {
532 x->x_dragfrom = x->x_selstart = x->x_selend = indx;
533 }
534 else if (flag == RTEXT_SHIFT)
535 {
536 if (indx * 2 > x->x_selstart + x->x_selend)
537 x->x_dragfrom = x->x_selstart, x->x_selend = indx;
538 else
539 x->x_dragfrom = x->x_selend, x->x_selstart = indx;
540 }
541 else if (flag == RTEXT_DRAG)
542 {
543 x->x_selstart = (x->x_dragfrom < indx ? x->x_dragfrom : indx);
544 x->x_selend = (x->x_dragfrom > indx ? x->x_dragfrom : indx);
545 }
546 rtext_senditup(x, SEND_UPDATE, &w, &h, &indx);
547}
548