A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 548 lines 14 kB view raw
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