A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION: heads-up text and input code
28 *
29 *-----------------------------------------------------------------------------
30 */
31
32#include "doomdef.h"
33#include "doomstat.h"
34#include "v_video.h"
35#include "m_swap.h"
36#include "hu_lib.h"
37#include "hu_stuff.h"
38#include "r_main.h"
39#include "r_draw.h"
40
41#include "rockmacros.h"
42
43// boolean : whether the screen is always erased
44#define noterased viewwindowx
45
46extern int key_backspace; // phares
47extern int key_enter; // phares
48
49//
50// not used currently
51// code to initialize HUlib would go here if needed
52//
53void HUlib_init(void)
54{
55}
56
57////////////////////////////////////////////////////////
58//
59// Basic text line widget
60//
61////////////////////////////////////////////////////////
62
63//
64// HUlib_clearTextLine()
65//
66// Blank the internal text line in a hu_textline_t widget
67//
68// Passed a hu_textline_t, returns nothing
69//
70void HUlib_clearTextLine(hu_textline_t* t)
71{
72 t->linelen = // killough 1/23 98: support multiple lines
73 t->len = 0;
74 t->l[0] = 0;
75 t->needsupdate = true;
76}
77
78//
79// HUlib_initTextLine()
80//
81// Initialize a hu_textline_t widget. Set the position, font, start char
82// of the font, and color range to be used.
83//
84// Passed a hu_textline_t, and the values used to initialize
85// Returns nothing
86//
87void HUlib_initTextLine(hu_textline_t* t, int x, int y,
88 const patchnum_t* f, int sc, int cm )
89//jff 2/16/98 add color range parameter
90{
91 t->x = x;
92 t->y = y;
93 t->f = f;
94 t->sc = sc;
95 t->cm = cm;
96 HUlib_clearTextLine(t);
97}
98
99//
100// HUlib_addCharToTextLine()
101//
102// Adds a character at the end of the text line in a hu_textline_t widget
103//
104// Passed the hu_textline_t and the char to add
105// Returns false if already at length limit, true if the character added
106//
107boolean HUlib_addCharToTextLine
108( hu_textline_t* t,
109 char ch )
110{
111 // killough 1/23/98 -- support multiple lines
112 if (t->linelen == HU_MAXLINELENGTH)
113 return false;
114 else
115 {
116 t->linelen++;
117 if (ch == '\n')
118 t->linelen=0;
119
120 t->l[t->len++] = ch;
121 t->l[t->len] = 0;
122 t->needsupdate = 4;
123 return true;
124 }
125
126}
127
128//
129// HUlib_delCharFromTextLine()
130//
131// Deletes a character at the end of the text line in a hu_textline_t widget
132//
133// Passed the hu_textline_t
134// Returns false if already empty, true if the character deleted
135//
136boolean HUlib_delCharFromTextLine(hu_textline_t* t)
137{
138 if (!t->len) return false;
139 else
140 {
141 t->l[--t->len] = 0;
142 t->needsupdate = 4;
143 return true;
144 }
145}
146
147//
148// HUlib_drawTextLine()
149//
150// Draws a hu_textline_t widget
151//
152// Passed the hu_textline_t and flag whether to draw a cursor
153// Returns nothing
154//
155void HUlib_drawTextLine
156( hu_textline_t* l,
157 boolean drawcursor )
158{
159
160 int i;
161 int w;
162 int x;
163 unsigned char c;
164 int oc = l->cm; //jff 2/17/98 remember default color
165 int y = l->y; // killough 1/18/98 -- support multiple lines
166
167 // draw the new stuff
168 x = l->x;
169 for (i=0;i<l->len;i++)
170 {
171 c = toupper(l->l[i]); //jff insure were not getting a cheap toupper conv.
172
173 if (c=='\n') // killough 1/18/98 -- support multiple lines
174 x=0,y+=8;
175 else if (c=='\t') // killough 1/23/98 -- support tab stops
176 x=x-x%80+80;
177 else if (c=='\x1b') //jff 2/17/98 escape code for color change
178 { //jff 3/26/98 changed to actual escape char
179 if (++i<l->len)
180 if (l->l[i]>='0' && l->l[i]<='9')
181 l->cm = l->l[i]-'0';
182 }
183 else if (c != ' ' && c >= l->sc && c <= 127)
184 {
185 w = SHORT(l->f[c - l->sc].width);
186 if (x+w > BASE_WIDTH)
187 break;
188 // killough 1/18/98 -- support multiple lines:
189 // CPhipps - patch drawing updated
190 V_DrawNumPatch(x, y, FG, l->f[c - l->sc].lumpnum, l->cm, VPT_TRANS | VPT_STRETCH);
191 x += w;
192 }
193 else
194 {
195 x += 4;
196 if (x >= BASE_WIDTH)
197 break;
198 }
199 }
200 l->cm = oc; //jff 2/17/98 restore original color
201
202 // draw the cursor if requested
203 if (drawcursor && x + SHORT(l->f['_' - l->sc].width) <= BASE_WIDTH)
204 {
205 // killough 1/18/98 -- support multiple lines
206 // CPhipps - patch drawing updated
207 V_DrawNumPatch(x, y, FG, l->f['_' - l->sc].lumpnum, CR_DEFAULT, VPT_NONE | VPT_STRETCH);
208 }
209}
210
211//
212// HUlib_eraseTextLine()
213//
214// Erases a hu_textline_t widget when screen border is behind text
215// Sorta called by HU_Erase and just better darn get things straight
216//
217// Passed the hu_textline_t
218// Returns nothing
219//
220void HUlib_eraseTextLine(hu_textline_t* l)
221{
222// KK - If someone finds a use for this code, please fix it, I havn't seen the need
223// And it's not written to take into account scaling. Causing some nasty effects
224// on smaller screens.
225 (void)l;
226#if 0
227 int lh;
228 int y;
229 int yoffset;
230
231 // Only erases when NOT in automap and the screen is reduced,
232 // and the text must either need updating or refreshing
233 // (because of a recent change back from the automap)
234
235 if (!(automapmode & am_active) && viewwindowx && l->needsupdate)
236 {
237 lh = SHORT(l->f[0].height) + 1;
238 for (y=l->y,yoffset=y*SCREENWIDTH ; y<l->y+lh ; y++,yoffset+=SCREENWIDTH)
239 {
240 if (y < viewwindowy || y >= viewwindowy + viewheight)
241 R_VideoErase(yoffset, SCREENWIDTH); // erase entire line
242 else
243 {
244 // erase left border
245 R_VideoErase(yoffset, viewwindowx);
246 // erase right border
247 R_VideoErase(yoffset + viewwindowx + viewwidth, viewwindowx);
248 }
249 }
250 }
251 if (l->needsupdate) l->needsupdate--;
252#endif
253}
254
255////////////////////////////////////////////////////////
256//
257// Player message widget (up to 4 lines of text)
258//
259////////////////////////////////////////////////////////
260
261//
262// HUlib_initSText()
263//
264// Initialize a hu_stext_t widget. Set the position, number of lines, font,
265// start char of the font, and color range to be used, and whether enabled.
266//
267// Passed a hu_stext_t, and the values used to initialize
268// Returns nothing
269//
270void HUlib_initSText
271( hu_stext_t* s,
272 int x,
273 int y,
274 int h,
275 const patchnum_t* font,
276 int startchar,
277 int cm, //jff 2/16/98 add color range parameter
278 boolean* on )
279{
280
281 int i;
282
283 s->h = h;
284 s->on = on;
285 s->laston = true;
286 s->cl = 0;
287 for (i=0;i<h;i++)
288 HUlib_initTextLine
289 (
290 &s->l[i],
291 x,
292 y - i*(SHORT(font[0].height)+1),
293 font,
294 startchar,
295 cm
296 );
297}
298
299//
300// HUlib_addLineToSText()
301//
302// Adds a blank line to a hu_stext_t widget
303//
304// Passed a hu_stext_t
305// Returns nothing
306//
307void HUlib_addLineToSText(hu_stext_t* s)
308{
309
310 int i;
311
312 // add a clear line
313 if (++s->cl == s->h)
314 s->cl = 0;
315 HUlib_clearTextLine(&s->l[s->cl]);
316
317 // everything needs updating
318 for (i=0 ; i<s->h ; i++)
319 s->l[i].needsupdate = 4;
320
321}
322
323//
324// HUlib_addMessageToSText()
325//
326// Adds a message line with prefix to a hu_stext_t widget
327//
328// Passed a hu_stext_t, the prefix string, and a message string
329// Returns nothing
330//
331void HUlib_addMessageToSText(hu_stext_t* s, const char* prefix, const char* msg)
332{
333 HUlib_addLineToSText(s);
334 if (prefix)
335 while (*prefix)
336 HUlib_addCharToTextLine(&s->l[s->cl], *(prefix++));
337
338 while (*msg)
339 HUlib_addCharToTextLine(&s->l[s->cl], *(msg++));
340}
341
342//
343// HUlib_drawSText()
344//
345// Displays a hu_stext_t widget
346//
347// Passed a hu_stext_t
348// Returns nothing
349//
350void HUlib_drawSText(hu_stext_t* s)
351{
352 int i, idx;
353 hu_textline_t *l;
354
355 if (!*s->on)
356 return; // if not on, don't draw
357
358 // draw everything
359 for (i=0 ; i<s->h ; i++)
360 {
361 idx = s->cl - i;
362 if (idx < 0)
363 idx += s->h; // handle queue of lines
364
365 l = &s->l[idx];
366
367 // need a decision made here on whether to skip the draw
368 HUlib_drawTextLine(l, false); // no cursor, please
369 }
370}
371
372//
373// HUlib_eraseSText()
374//
375// Erases a hu_stext_t widget, when the screen is not fullsize
376//
377// Passed a hu_stext_t
378// Returns nothing
379//
380void HUlib_eraseSText(hu_stext_t* s)
381{
382 int i;
383
384 for (i=0 ; i<s->h ; i++)
385 {
386 if (s->laston && !*s->on)
387 s->l[i].needsupdate = 4;
388 HUlib_eraseTextLine(&s->l[i]);
389 }
390 s->laston = *s->on;
391}
392
393////////////////////////////////////////////////////////
394//
395// Scrolling message review widget
396//
397// jff added 2/26/98
398//
399////////////////////////////////////////////////////////
400
401//
402// HUlib_initMText()
403//
404// Initialize a hu_mtext_t widget. Set the position, width, number of lines,
405// font, start char of the font, color range, background font, and whether
406// enabled.
407//
408// Passed a hu_mtext_t, and the values used to initialize
409// Returns nothing
410//
411void HUlib_initMText(hu_mtext_t *m, int x, int y, int w, int h,
412 const patchnum_t* font, int startchar, int cm,
413 const patchnum_t* bgfont, boolean *on)
414{
415 int i;
416
417 m->nl = 0;
418 m->nr = 0;
419 m->cl = -1; //jff 4/28/98 prepare for pre-increment
420 m->x = x;
421 m->y = y;
422 m->w = w;
423 m->h = h;
424 m->bg = bgfont;
425 m->on = on;
426 for (i=0;i<HU_MAXMESSAGES;i++)
427 {
428 HUlib_initTextLine
429 (
430 &m->l[i],
431 x,
432 y + (hud_list_bgon? i+1 : i)*HU_REFRESHSPACING,
433 font,
434 startchar,
435 cm
436 );
437 }
438}
439
440//
441// HUlib_addLineToMText()
442//
443// Adds a blank line to a hu_mtext_t widget
444//
445// Passed a hu_mtext_t
446// Returns nothing
447//
448void HUlib_addLineToMText(hu_mtext_t* m)
449{
450 // add a clear line
451 if (++m->cl == hud_msg_lines)
452 m->cl = 0;
453 HUlib_clearTextLine(&m->l[m->cl]);
454
455 if (m->nl<hud_msg_lines)
456 m->nl++;
457
458 // needs updating
459 m->l[m->cl].needsupdate = 4;
460}
461
462//
463// HUlib_addMessageToMText()
464//
465// Adds a message line with prefix to a hu_mtext_t widget
466//
467// Passed a hu_mtext_t, the prefix string, and a message string
468// Returns nothing
469//
470void HUlib_addMessageToMText(hu_mtext_t* m, const char* prefix, const char* msg)
471{
472 HUlib_addLineToMText(m);
473 if (prefix)
474 while (*prefix)
475 HUlib_addCharToTextLine(&m->l[m->cl], *(prefix++));
476
477 while (*msg)
478 HUlib_addCharToTextLine(&m->l[m->cl], *(msg++));
479}
480
481//
482// HUlib_drawMBg()
483//
484// Draws a background box which the message display review widget can
485// display over
486//
487// Passed position, width, height, and the background patches
488// Returns nothing
489//
490void HUlib_drawMBg
491( int x,
492 int y,
493 int w,
494 int h,
495 const patchnum_t* bgp
496)
497{
498 int xs = bgp[0].width;
499 int ys = bgp[0].height;
500 int i,j;
501
502 // CPhipps - patch drawing updated
503 // top rows
504 V_DrawNumPatch(x, y, FG, bgp[0].lumpnum, CR_DEFAULT, VPT_STRETCH); // ul
505 for (j=x+xs;j<x+w-xs;j+=xs) // uc
506 V_DrawNumPatch(j, y, FG, bgp[1].lumpnum, CR_DEFAULT, VPT_STRETCH);
507 V_DrawNumPatch(j, y, FG, bgp[2].lumpnum, CR_DEFAULT, VPT_STRETCH); // ur
508
509 // middle rows
510 for (i=y+ys;i<y+h-ys;i+=ys)
511 {
512 V_DrawNumPatch(x, i, FG, bgp[3].lumpnum, CR_DEFAULT, VPT_STRETCH); // cl
513 for (j=x+xs;j<x+w-xs;j+=xs) // cc
514 V_DrawNumPatch(j, i, FG, bgp[4].lumpnum, CR_DEFAULT, VPT_STRETCH);
515 V_DrawNumPatch(j, i, FG, bgp[5].lumpnum, CR_DEFAULT, VPT_STRETCH); // cr
516 }
517
518 // bottom row
519 V_DrawNumPatch(x, i, FG, bgp[6].lumpnum, CR_DEFAULT, VPT_STRETCH); // ll
520 for (j=x+xs;j<x+w-xs;j+=xs) // lc
521 V_DrawNumPatch(j, i, FG, bgp[7].lumpnum, CR_DEFAULT, VPT_STRETCH);
522 V_DrawNumPatch(j, i, FG, bgp[8].lumpnum, CR_DEFAULT, VPT_STRETCH); // lr
523}
524
525//
526// HUlib_drawMText()
527//
528// Displays a hu_mtext_t widget
529//
530// Passed a hu_mtext_t
531// Returns nothing
532//
533void HUlib_drawMText(hu_mtext_t* m)
534{
535 int i, idx;
536 hu_textline_t *l;
537
538 if (!*m->on)
539 return; // if not on, don't draw
540
541 // draw everything
542 if (hud_list_bgon)
543 HUlib_drawMBg(m->x,m->y,m->w,m->h,m->bg);
544
545 for (i=0 ; i<m->nl ; i++)
546 {
547 idx = m->cl - i;
548 if (idx < 0)
549 idx += m->nl; // handle queue of lines
550
551 l = &m->l[idx];
552 if (hud_list_bgon)
553 {
554 l->x = m->x + 4;
555 l->y = m->y + (i+1)*HU_REFRESHSPACING;
556 }
557 else
558 {
559 l->x = m->x;
560 l->y = m->y + i*HU_REFRESHSPACING;
561 }
562
563 // need a decision made here on whether to skip the draw
564 HUlib_drawTextLine(l, false); // no cursor, please
565 }
566}
567
568//
569// HUlib_eraseMBg()
570//
571// Erases background behind hu_mtext_t widget, when the screen is not fullsize
572//
573// Passed a hu_mtext_t
574// Returns nothing
575//
576static void HUlib_eraseMBg(hu_mtext_t* m)
577{
578 int lh;
579 int y;
580 int yoffset;
581
582 // Only erases when NOT in automap and the screen is reduced,
583 // and the text must either need updating or refreshing
584 // (because of a recent change back from the automap)
585
586 if (!(automapmode & am_active) && viewwindowx)
587 {
588 lh = SHORT(m->l[0].f[0].height) + 1;
589 for (y=m->y,yoffset=y*SCREENWIDTH ; y<m->y+lh*(hud_msg_lines+2) ; y++,yoffset+=SCREENWIDTH)
590 {
591 if (y < viewwindowy || y >= viewwindowy + viewheight)
592 R_VideoErase(yoffset, SCREENWIDTH); // erase entire line
593 else
594 {
595 // erase left border
596 R_VideoErase(yoffset, viewwindowx);
597 // erase right border
598 R_VideoErase(yoffset + viewwindowx + viewwidth, viewwindowx);
599
600 }
601 }
602 }
603}
604
605//
606// HUlib_eraseMText()
607//
608// Erases a hu_mtext_t widget, when the screen is not fullsize
609//
610// Passed a hu_mtext_t
611// Returns nothing
612//
613void HUlib_eraseMText(hu_mtext_t* m)
614{
615 int i;
616
617 if (hud_list_bgon)
618 HUlib_eraseMBg(m);
619
620 for (i=0 ; i< m->nl ; i++)
621 {
622 m->l[i].needsupdate = 4;
623 HUlib_eraseTextLine(&m->l[i]);
624 }
625}
626
627////////////////////////////////////////////////////////
628//
629// Interactive text entry widget
630//
631////////////////////////////////////////////////////////
632
633//
634// HUlib_initIText()
635//
636// Initialize a hu_itext_t widget. Set the position, font,
637// start char of the font, color range, and whether enabled.
638//
639// Passed a hu_itext_t, and the values used to initialize
640// Returns nothing
641//
642void HUlib_initIText
643( hu_itext_t* it,
644 int x,
645 int y,
646 const patchnum_t* font,
647 int startchar,
648 int cm, //jff 2/16/98 add color range parameter
649 boolean* on )
650{
651 it->lm = 0; // default left margin is start of text
652 it->on = on;
653 it->laston = true;
654 HUlib_initTextLine(&it->l, x, y, font, startchar, cm);
655}
656
657// The following deletion routines adhere to the left margin restriction
658
659//
660// HUlib_delCharFromIText()
661//
662// Deletes a character at the end of the text line in a hu_itext_t widget
663//
664// Passed the hu_itext_t
665// Returns nothing
666//
667void HUlib_delCharFromIText(hu_itext_t* it)
668{
669 if (it->l.len != it->lm)
670 HUlib_delCharFromTextLine(&it->l);
671}
672
673//
674// HUlib_eraseLineFromIText()
675//
676// Deletes all characters from a hu_itext_t widget
677//
678// Passed the hu_itext_t
679// Returns nothing
680//
681void HUlib_eraseLineFromIText(hu_itext_t* it)
682{
683 while (it->lm != it->l.len)
684 HUlib_delCharFromTextLine(&it->l);
685}
686
687//
688// HUlib_resetIText()
689//
690// Deletes all characters from a hu_itext_t widget
691// Resets left margin as well
692//
693// Passed the hu_itext_t
694// Returns nothing
695//
696void HUlib_resetIText(hu_itext_t* it)
697{
698 it->lm = 0;
699 HUlib_clearTextLine(&it->l);
700}
701
702//
703// HUlib_addPrefixToIText()
704//
705// Adds a prefix string passed to a hu_itext_t widget
706// Sets left margin to length of string added
707//
708// Passed the hu_itext_t and the prefix string
709// Returns nothing
710//
711void HUlib_addPrefixToIText
712( hu_itext_t* it,
713 char* str )
714{
715 while (*str)
716 HUlib_addCharToTextLine(&it->l, *(str++));
717 it->lm = it->l.len;
718}
719
720//
721// HUlib_keyInIText()
722//
723// Wrapper function for handling general keyed input.
724//
725// Passed the hu_itext_t and the char input
726// Returns true if it ate the key
727//
728boolean HUlib_keyInIText
729( hu_itext_t* it,
730 unsigned char ch )
731{
732
733 if (ch >= ' ' && ch <= '_')
734 HUlib_addCharToTextLine(&it->l, (char) ch);
735 else if (ch == key_backspace) // phares
736 HUlib_delCharFromIText(it);
737 else if (ch != key_enter) // phares
738 return false; // did not eat key
739
740 return true; // ate the key
741}
742
743//
744// HUlib_drawIText()
745//
746// Displays a hu_itext_t widget
747//
748// Passed the hu_itext_t
749// Returns nothing
750//
751void HUlib_drawIText(hu_itext_t* it)
752{
753 hu_textline_t *l = &it->l;
754
755 if (!*it->on)
756 return;
757 HUlib_drawTextLine(l, true); // draw the line w/ cursor
758}
759
760//
761// HUlib_eraseIText()
762//
763// Erases a hu_itext_t widget when the screen is not fullsize
764//
765// Passed the hu_itext_t
766// Returns nothing
767//
768void HUlib_eraseIText(hu_itext_t* it)
769{
770 if (it->laston && !*it->on)
771 it->l.needsupdate = 4;
772 HUlib_eraseTextLine(&it->l);
773 it->laston = *it->on;
774}
775