aboutsummaryrefslogtreecommitdiff
path: root/src/hu_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/hu_lib.c')
-rw-r--r--src/hu_lib.c767
1 files changed, 767 insertions, 0 deletions
diff --git a/src/hu_lib.c b/src/hu_lib.c
new file mode 100644
index 0000000..93c6a62
--- /dev/null
+++ b/src/hu_lib.c
@@ -0,0 +1,767 @@
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 * Copyright 2005, 2006 by
12 * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 * 02111-1307, USA.
28 *
29 * DESCRIPTION: heads-up text and input code
30 *
31 *-----------------------------------------------------------------------------
32 */
33
34#include "doomdef.h"
35#include "doomstat.h"
36#include "v_video.h"
37#include "m_swap.h"
38#include "hu_lib.h"
39#include "hu_stuff.h"
40#include "r_main.h"
41#include "r_draw.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//
53static void 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//
136static boolean 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 = 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 + 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 int lh;
223 int y;
224
225 // Only erases when NOT in automap and the screen is reduced,
226 // and the text must either need updating or refreshing
227 // (because of a recent change back from the automap)
228
229 if (!(automapmode & am_active) && viewwindowx && l->needsupdate)
230 {
231 lh = l->f[0].height + 1;
232 for (y=l->y; y<l->y+lh ; y++)
233 {
234 if (y < viewwindowy || y >= viewwindowy + viewheight)
235 R_VideoErase(0, y, SCREENWIDTH); // erase entire line
236 else
237 {
238 // erase left border
239 R_VideoErase(0, y, viewwindowx);
240 // erase right border
241 R_VideoErase(viewwindowx + viewwidth, y, viewwindowx);
242 }
243 }
244 }
245
246 if (l->needsupdate) l->needsupdate--;
247}
248
249////////////////////////////////////////////////////////
250//
251// Player message widget (up to 4 lines of text)
252//
253////////////////////////////////////////////////////////
254
255//
256// HUlib_initSText()
257//
258// Initialize a hu_stext_t widget. Set the position, number of lines, font,
259// start char of the font, and color range to be used, and whether enabled.
260//
261// Passed a hu_stext_t, and the values used to initialize
262// Returns nothing
263//
264void HUlib_initSText
265( hu_stext_t* s,
266 int x,
267 int y,
268 int h,
269 const patchnum_t* font,
270 int startchar,
271 int cm, //jff 2/16/98 add color range parameter
272 boolean* on )
273{
274
275 int i;
276
277 s->h = h;
278 s->on = on;
279 s->laston = true;
280 s->cl = 0;
281 for (i=0;i<h;i++)
282 HUlib_initTextLine
283 (
284 &s->l[i],
285 x,
286 y - i*(font[0].height+1),
287 font,
288 startchar,
289 cm
290 );
291}
292
293//
294// HUlib_addLineToSText()
295//
296// Adds a blank line to a hu_stext_t widget
297//
298// Passed a hu_stext_t
299// Returns nothing
300//
301static void HUlib_addLineToSText(hu_stext_t* s)
302{
303
304 int i;
305
306 // add a clear line
307 if (++s->cl == s->h)
308 s->cl = 0;
309 HUlib_clearTextLine(&s->l[s->cl]);
310
311 // everything needs updating
312 for (i=0 ; i<s->h ; i++)
313 s->l[i].needsupdate = 4;
314
315}
316
317//
318// HUlib_addMessageToSText()
319//
320// Adds a message line with prefix to a hu_stext_t widget
321//
322// Passed a hu_stext_t, the prefix string, and a message string
323// Returns nothing
324//
325void HUlib_addMessageToSText(hu_stext_t* s, const char* prefix, const char* msg)
326{
327 HUlib_addLineToSText(s);
328 if (prefix)
329 while (*prefix)
330 HUlib_addCharToTextLine(&s->l[s->cl], *(prefix++));
331
332 while (*msg)
333 HUlib_addCharToTextLine(&s->l[s->cl], *(msg++));
334}
335
336//
337// HUlib_drawSText()
338//
339// Displays a hu_stext_t widget
340//
341// Passed a hu_stext_t
342// Returns nothing
343//
344void HUlib_drawSText(hu_stext_t* s)
345{
346 int i, idx;
347 hu_textline_t *l;
348
349 if (!*s->on)
350 return; // if not on, don't draw
351
352 // draw everything
353 for (i=0 ; i<s->h ; i++)
354 {
355 idx = s->cl - i;
356 if (idx < 0)
357 idx += s->h; // handle queue of lines
358
359 l = &s->l[idx];
360
361 // need a decision made here on whether to skip the draw
362 HUlib_drawTextLine(l, false); // no cursor, please
363 }
364}
365
366//
367// HUlib_eraseSText()
368//
369// Erases a hu_stext_t widget, when the screen is not fullsize
370//
371// Passed a hu_stext_t
372// Returns nothing
373//
374void HUlib_eraseSText(hu_stext_t* s)
375{
376 int i;
377
378 for (i=0 ; i<s->h ; i++)
379 {
380 if (s->laston && !*s->on)
381 s->l[i].needsupdate = 4;
382 HUlib_eraseTextLine(&s->l[i]);
383 }
384 s->laston = *s->on;
385}
386
387////////////////////////////////////////////////////////
388//
389// Scrolling message review widget
390//
391// jff added 2/26/98
392//
393////////////////////////////////////////////////////////
394
395//
396// HUlib_initMText()
397//
398// Initialize a hu_mtext_t widget. Set the position, width, number of lines,
399// font, start char of the font, color range, background font, and whether
400// enabled.
401//
402// Passed a hu_mtext_t, and the values used to initialize
403// Returns nothing
404//
405void HUlib_initMText(hu_mtext_t *m, int x, int y, int w, int h,
406 const patchnum_t* font, int startchar, int cm,
407 const patchnum_t* bgfont, boolean *on)
408{
409 int i;
410
411 m->nl = 0;
412 m->nr = 0;
413 m->cl = -1; //jff 4/28/98 prepare for pre-increment
414 m->x = x;
415 m->y = y;
416 m->w = w;
417 m->h = h;
418 m->bg = bgfont;
419 m->on = on;
420 for (i=0;i<HU_MAXMESSAGES;i++)
421 {
422 HUlib_initTextLine
423 (
424 &m->l[i],
425 x,
426 y + (hud_list_bgon? i+1 : i)*HU_REFRESHSPACING,
427 font,
428 startchar,
429 cm
430 );
431 }
432}
433
434//
435// HUlib_addLineToMText()
436//
437// Adds a blank line to a hu_mtext_t widget
438//
439// Passed a hu_mtext_t
440// Returns nothing
441//
442static void HUlib_addLineToMText(hu_mtext_t* m)
443{
444 // add a clear line
445 if (++m->cl == hud_msg_lines)
446 m->cl = 0;
447 HUlib_clearTextLine(&m->l[m->cl]);
448
449 if (m->nl<hud_msg_lines)
450 m->nl++;
451
452 // needs updating
453 m->l[m->cl].needsupdate = 4;
454}
455
456//
457// HUlib_addMessageToMText()
458//
459// Adds a message line with prefix to a hu_mtext_t widget
460//
461// Passed a hu_mtext_t, the prefix string, and a message string
462// Returns nothing
463//
464void HUlib_addMessageToMText(hu_mtext_t* m, const char* prefix, const char* msg)
465{
466 HUlib_addLineToMText(m);
467 if (prefix)
468 while (*prefix)
469 HUlib_addCharToTextLine(&m->l[m->cl], *(prefix++));
470
471 while (*msg)
472 HUlib_addCharToTextLine(&m->l[m->cl], *(msg++));
473}
474
475//
476// HUlib_drawMBg()
477//
478// Draws a background box which the message display review widget can
479// display over
480//
481// Passed position, width, height, and the background patches
482// Returns nothing
483//
484void HUlib_drawMBg
485( int x,
486 int y,
487 int w,
488 int h,
489 const patchnum_t* bgp
490)
491{
492 int xs = bgp[0].width;
493 int ys = bgp[0].height;
494 int i,j;
495
496 // CPhipps - patch drawing updated
497 // top rows
498 V_DrawNumPatch(x, y, FG, bgp[0].lumpnum, CR_DEFAULT, VPT_STRETCH); // ul
499 for (j=x+xs;j<x+w-xs;j+=xs) // uc
500 V_DrawNumPatch(j, y, FG, bgp[1].lumpnum, CR_DEFAULT, VPT_STRETCH);
501 V_DrawNumPatch(j, y, FG, bgp[2].lumpnum, CR_DEFAULT, VPT_STRETCH); // ur
502
503 // middle rows
504 for (i=y+ys;i<y+h-ys;i+=ys)
505 {
506 V_DrawNumPatch(x, i, FG, bgp[3].lumpnum, CR_DEFAULT, VPT_STRETCH); // cl
507 for (j=x+xs;j<x+w-xs;j+=xs) // cc
508 V_DrawNumPatch(j, i, FG, bgp[4].lumpnum, CR_DEFAULT, VPT_STRETCH);
509 V_DrawNumPatch(j, i, FG, bgp[5].lumpnum, CR_DEFAULT, VPT_STRETCH); // cr
510 }
511
512 // bottom row
513 V_DrawNumPatch(x, i, FG, bgp[6].lumpnum, CR_DEFAULT, VPT_STRETCH); // ll
514 for (j=x+xs;j<x+w-xs;j+=xs) // lc
515 V_DrawNumPatch(j, i, FG, bgp[7].lumpnum, CR_DEFAULT, VPT_STRETCH);
516 V_DrawNumPatch(j, i, FG, bgp[8].lumpnum, CR_DEFAULT, VPT_STRETCH); // lr
517}
518
519//
520// HUlib_drawMText()
521//
522// Displays a hu_mtext_t widget
523//
524// Passed a hu_mtext_t
525// Returns nothing
526//
527void HUlib_drawMText(hu_mtext_t* m)
528{
529 int i, idx, y;
530 hu_textline_t *l;
531
532 if (!*m->on)
533 return; // if not on, don't draw
534
535 // draw everything
536 if (hud_list_bgon)
537 HUlib_drawMBg(m->x,m->y,m->w,m->h,m->bg);
538 y = m->y + HU_REFRESHSPACING;
539 for (i=0 ; i<m->nl ; i++)
540 {
541 idx = m->cl - i;
542 if (idx < 0)
543 idx += m->nl; // handle queue of lines
544
545 l = &m->l[idx];
546 if (hud_list_bgon)
547 {
548 l->x = m->x + 4;
549 l->y = m->y + (i+1)*HU_REFRESHSPACING;
550 }
551 else
552 {
553 l->x = m->x;
554 l->y = m->y + i*HU_REFRESHSPACING;
555 }
556
557 // need a decision made here on whether to skip the draw
558 HUlib_drawTextLine(l, false); // no cursor, please
559 }
560}
561
562//
563// HUlib_eraseMBg()
564//
565// Erases background behind hu_mtext_t widget, when the screen is not fullsize
566//
567// Passed a hu_mtext_t
568// Returns nothing
569//
570static void HUlib_eraseMBg(hu_mtext_t* m)
571{
572 int lh;
573 int y;
574
575 // Only erases when NOT in automap and the screen is reduced,
576 // and the text must either need updating or refreshing
577 // (because of a recent change back from the automap)
578
579 if (!(automapmode & am_active) && viewwindowx)
580 {
581 lh = m->l[0].f[0].height + 1;
582 for (y=m->y; y<m->y+lh*(hud_msg_lines+2) ; y++)
583 {
584 if (y < viewwindowy || y >= viewwindowy + viewheight)
585 R_VideoErase(0, y, SCREENWIDTH); // erase entire line
586 else
587 {
588 // erase left border
589 R_VideoErase(0, y, viewwindowx);
590 // erase right border
591 R_VideoErase(viewwindowx + viewwidth, y, viewwindowx);
592
593 }
594 }
595 }
596}
597
598//
599// HUlib_eraseMText()
600//
601// Erases a hu_mtext_t widget, when the screen is not fullsize
602//
603// Passed a hu_mtext_t
604// Returns nothing
605//
606void HUlib_eraseMText(hu_mtext_t* m)
607{
608 int i;
609
610 if (hud_list_bgon)
611 HUlib_eraseMBg(m);
612
613 for (i=0 ; i< m->nl ; i++)
614 {
615 m->l[i].needsupdate = 4;
616 HUlib_eraseTextLine(&m->l[i]);
617 }
618}
619
620////////////////////////////////////////////////////////
621//
622// Interactive text entry widget
623//
624////////////////////////////////////////////////////////
625
626//
627// HUlib_initIText()
628//
629// Initialize a hu_itext_t widget. Set the position, font,
630// start char of the font, color range, and whether enabled.
631//
632// Passed a hu_itext_t, and the values used to initialize
633// Returns nothing
634//
635void HUlib_initIText
636( hu_itext_t* it,
637 int x,
638 int y,
639 const patchnum_t* font,
640 int startchar,
641 int cm, //jff 2/16/98 add color range parameter
642 boolean* on )
643{
644 it->lm = 0; // default left margin is start of text
645 it->on = on;
646 it->laston = true;
647 HUlib_initTextLine(&it->l, x, y, font, startchar, cm);
648}
649
650// The following deletion routines adhere to the left margin restriction
651
652//
653// HUlib_delCharFromIText()
654//
655// Deletes a character at the end of the text line in a hu_itext_t widget
656//
657// Passed the hu_itext_t
658// Returns nothing
659//
660static void HUlib_delCharFromIText(hu_itext_t* it)
661{
662 if (it->l.len != it->lm)
663 HUlib_delCharFromTextLine(&it->l);
664}
665
666//
667// HUlib_eraseLineFromIText()
668//
669// Deletes all characters from a hu_itext_t widget
670//
671// Passed the hu_itext_t
672// Returns nothing
673//
674static void HUlib_eraseLineFromIText(hu_itext_t* it)
675{
676 while (it->lm != it->l.len)
677 HUlib_delCharFromTextLine(&it->l);
678}
679
680//
681// HUlib_resetIText()
682//
683// Deletes all characters from a hu_itext_t widget
684// Resets left margin as well
685//
686// Passed the hu_itext_t
687// Returns nothing
688//
689void HUlib_resetIText(hu_itext_t* it)
690{
691 it->lm = 0;
692 HUlib_clearTextLine(&it->l);
693}
694
695//
696// HUlib_addPrefixToIText()
697//
698// Adds a prefix string passed to a hu_itext_t widget
699// Sets left margin to length of string added
700//
701// Passed the hu_itext_t and the prefix string
702// Returns nothing
703//
704void HUlib_addPrefixToIText
705( hu_itext_t* it,
706 char* str )
707{
708 while (*str)
709 HUlib_addCharToTextLine(&it->l, *(str++));
710 it->lm = it->l.len;
711}
712
713//
714// HUlib_keyInIText()
715//
716// Wrapper function for handling general keyed input.
717//
718// Passed the hu_itext_t and the char input
719// Returns true if it ate the key
720//
721boolean HUlib_keyInIText
722( hu_itext_t* it,
723 unsigned char ch )
724{
725
726 if (ch >= ' ' && ch <= '_')
727 HUlib_addCharToTextLine(&it->l, (char) ch);
728 else if (ch == key_backspace) // phares
729 HUlib_delCharFromIText(it);
730 else if (ch != key_enter) // phares
731 return false; // did not eat key
732
733 return true; // ate the key
734}
735
736//
737// HUlib_drawIText()
738//
739// Displays a hu_itext_t widget
740//
741// Passed the hu_itext_t
742// Returns nothing
743//
744void HUlib_drawIText(hu_itext_t* it)
745{
746 hu_textline_t *l = &it->l;
747
748 if (!*it->on)
749 return;
750 HUlib_drawTextLine(l, true); // draw the line w/ cursor
751}
752
753//
754// HUlib_eraseIText()
755//
756// Erases a hu_itext_t widget when the screen is not fullsize
757//
758// Passed the hu_itext_t
759// Returns nothing
760//
761void HUlib_eraseIText(hu_itext_t* it)
762{
763 if (it->laston && !*it->on)
764 it->l.needsupdate = 4;
765 HUlib_eraseTextLine(&it->l);
766 it->laston = *it->on;
767}