diff --git a/docs/woofhud.md b/docs/woofhud.md index c9102f5c..aa8f9f25 100644 --- a/docs/woofhud.md +++ b/docs/woofhud.md @@ -17,6 +17,8 @@ The following lines start with the name of the HUD widget which is to be positio Possible values for the HUD widget names: * "title" or "levelname" + * "message" (new in Woof! 12.0.0) + * "secret" (new in Woof! 12.0.0) * "armor" * "health" * "ammo" @@ -100,6 +102,7 @@ The "title" widget is only visible if the Automap is enabled. The "monsec", "stt A centered widget does not allow for any other left or right aligned widget on the same line. HUD modes without a paragraph remain unchanged. Widgets which are not mentioned in a paragraph will *never* be visible in the respective HUD mode. So, it is a good idea to *always* include the five widgets which make up the `hud 0` paragraph in the example above in *any* other paragraph. +The Vanilla Doom widgets (i.e. "title", "message", "secret"), however, will *always* be visible, whether they are explicitly mentioned in a paragraph or not (new in Woof! 12.0.0). It is currently impossible to use the WOOFHUD lump to modify the appearance of the Status Bar or the Crispy HUD. However, when using the Crispy HUD or the Automap, the visible widgets will align corresponding to the last active HUD mode. diff --git a/src/hu_lib.c b/src/hu_lib.c index dd9e8487..7b765ecb 100644 --- a/src/hu_lib.c +++ b/src/hu_lib.c @@ -17,47 +17,22 @@ // //----------------------------------------------------------------------------- -#include "doomdef.h" #include "doomstat.h" #include "doomkeys.h" -#include "v_video.h" #include "m_swap.h" #include "hu_lib.h" #include "hu_stuff.h" -#include "r_main.h" -#include "r_draw.h" -// boolean : whether the screen is always erased -#define noterased viewwindowx +// [FG] horizontal alignment +#define SPCWIDTH 5 #define TABWIDTH (16 - 1) -static int align_offset[num_aligns]; - -void HUlib_resetAlignOffsets (void) -{ - int bottom = ORIGHEIGHT - 1; - - if (scaledviewheight < SCREENHEIGHT || - (crispy_hud && hud_active > 0) || - automap_on) - { - bottom -= 32; // ST_HEIGHT - } - - align_offset[align_topleft] = 0; - align_offset[align_topright] = 0; - align_offset[align_topcenter] = 0; - align_offset[align_bottomleft] = bottom; - align_offset[align_bottomright] = bottom; - align_offset[align_bottomcenter] = bottom; -} - #define HU_GAPX 2 static int left_margin, right_margin; int hud_widescreen_widgets; -void HUlib_setMargins (void) +void HUlib_set_margins (void) { left_margin = HU_GAPX; @@ -69,89 +44,111 @@ void HUlib_setMargins (void) right_margin = ORIGWIDTH - left_margin; } -// -// not used currently -// code to initialize HUlib would go here if needed -// -void HUlib_init(void) +// [FG] vertical alignment + +typedef enum { + offset_topleft, + offset_topright, + + offset_bottomleft, + offset_bottomright, + + num_offsets, +} offset_t; + +static int align_offset[num_offsets]; + +void HUlib_reset_align_offsets (void) { + int bottom = ORIGHEIGHT - 1; + + if (scaledviewheight < SCREENHEIGHT || + (crispy_hud && hud_active > 0) || + automap_on) + { + bottom -= 32; // ST_HEIGHT + } + + align_offset[offset_topleft] = 0; + align_offset[offset_topright] = 0; + align_offset[offset_bottomleft] = bottom; + align_offset[offset_bottomright] = bottom; } -//////////////////////////////////////////////////////// -// -// Basic text line widget -// -//////////////////////////////////////////////////////// +// [FG] clear line -// -// HUlib_clearTextLine() -// -// Blank the internal text line in a hu_textline_t widget -// -// Passed a hu_textline_t, returns nothing -// -void HUlib_clearTextLine(hu_textline_t* t) +void HUlib_clear_line (hu_line_t* l) { - t->linelen = 0; // killough 1/23/98: support multiple lines - t->len = 0; - t->l[0] = 0; - t->needsupdate = true; - t->width = 0; - t->visible = false; + l->line[0] = '\0'; + l->len = 0; + l->width = 0; } -// -// HUlib_initTextLine() -// -// Initialize a hu_textline_t widget. Set the position, font, start char -// of the font, and color range to be used. -// -// Passed a hu_textline_t, and the values used to initialize -// Returns nothing -// - -void HUlib_initTextLine(hu_textline_t *t, int x, int y, patch_t ***f, - char *cr, void (*builder)(void)) //jff 2/16/98 add color range parameter +void HUlib_clear_cur_line (hu_multiline_t *m) { - t->x = x; - t->y = y; - t->f = f; - t->cr = cr; - t->builder = builder; - HUlib_clearTextLine(t); + HUlib_clear_line(m->lines[m->curline]); } -// -// HUlib_addCharToTextLine() -// -// Adds a character at the end of the text line in a hu_textline_t widget -// -// Passed the hu_textline_t and the char to add -// Returns false if already at length limit, true if the character added -// +// [FG] add single char to line, increasing its length but not its width -boolean HUlib_addCharToTextLine(hu_textline_t *t, char ch) +static boolean add_char_to_line(hu_line_t *const t, const char ch) { - // killough 1/23/98 -- support multiple lines - if (t->linelen == HU_MAXLINELENGTH) + if (t->len == HU_MAXLINELENGTH) return false; else - { - t->linelen++; - if (ch == '\n') - t->linelen=0; - t->l[t->len++] = ch; - t->l[t->len] = 0; - t->needsupdate = 4; - return true; - } + { + t->line[t->len++] = ch; + t->line[t->len] = '\0'; + return true; + } } -void HUlib_addStringToTextLine(hu_textline_t *l, char *s) +static boolean del_char_from_line(hu_line_t* l) +{ + return l->len ? l->line[--l->len] = '\0', true : false; +} + +// [FG] add printable char to line, handle Backspace and Enter (for w_chat) + +boolean HUlib_add_key_to_line(hu_line_t *const l, unsigned char ch) +{ + if (ch >= ' ' && ch <= '_') + add_char_to_line(l, (char) ch); + else + if (ch == KEY_BACKSPACE) // phares + del_char_from_line(l); + else + if (ch != KEY_ENTER) // phares + return false; // did not eat key + return true; // ate the key +} + +boolean HUlib_add_key_to_cur_line(hu_multiline_t *const m, unsigned char ch) +{ + hu_line_t *const l = m->lines[m->curline]; + + return HUlib_add_key_to_line(l, ch); +} + +// [FG] point curline to the next line in a multiline if available + +static inline void inc_cur_line (hu_multiline_t *const m) +{ + if (m->numlines > 1) + { + if (++m->curline >= m->numlines) + { + m->curline = 0; + } + } +} + +// [FG] add string to line, increasing its (length and) width + +static void add_string_to_line (hu_line_t *const l, patch_t *const *const f, const char *s) { int w = 0; unsigned char c; - patch_t *const *const f = *l->f; if (!*s) return; @@ -162,8 +159,8 @@ void HUlib_addStringToTextLine(hu_textline_t *l, char *s) if (c == '\x1b') { - HUlib_addCharToTextLine(l, c); - HUlib_addCharToTextLine(l, *s++); + add_char_to_line(l, c); + add_char_to_line(l, *s++); continue; } else if (c == '\t') @@ -171,541 +168,316 @@ void HUlib_addStringToTextLine(hu_textline_t *l, char *s) else if (c != ' ' && c >= HU_FONTSTART && c <= HU_FONTEND + 6) w += SHORT(f[c - HU_FONTSTART]->width); else - w += 4; + w += SPCWIDTH; - HUlib_addCharToTextLine(l, c); + add_char_to_line(l, c); } while (*--s == ' ') - w -= 4; + w -= SPCWIDTH; - l->width = w; - l->visible = true; + l->width += w; } -// -// HUlib_delCharFromTextLine() -// -// Deletes a character at the end of the text line in a hu_textline_t widget -// -// Passed the hu_textline_t -// Returns false if already empty, true if the character deleted -// +// [FG] add string to current line, point to next line if available -static boolean HUlib_delCharFromTextLine(hu_textline_t* t) +void HUlib_add_strings_to_cur_line (hu_multiline_t *const m, const char *prefix, const char *s) { - return t->len ? t->l[--t->len] = 0, t->needsupdate = 4, true : false; + hu_line_t *const l = m->lines[m->curline]; + + HUlib_clear_line(l); + + if (prefix) + { + add_string_to_line(l, *m->font, prefix); + } + + add_string_to_line(l, *m->font, s); + + inc_cur_line(m); } -// -// HUlib_drawTextLine() -// -// Draws a hu_textline_t widget -// -// Passed the hu_textline_t and flag whether to draw a cursor -// Returns nothing -// - -static void HUlib_alignWidget(hu_textline_t *l, align_t align) +void HUlib_add_string_to_cur_line (hu_multiline_t *const m, const char *s) +{ + HUlib_add_strings_to_cur_line(m, NULL, s); +} + +// [FG] horizontal and vertical alignment + +static int horz_align_widget(const hu_widget_t *const w, const hu_line_t *const l, const align_t h_align) +{ + if (h_align == align_left) + { + return left_margin; + } + else if (h_align == align_right) + { + return right_margin - l->width; + } + else if (h_align == align_center) + { + return ORIGWIDTH/2 - l->width/2; + } + + // [FG] align_direct + return w->x; +} + +static int vert_align_widget(const hu_widget_t *const w, const hu_multiline_t *const m, patch_t *const *const f, const align_t h_align, const align_t v_align) { - patch_t *const *const f = *l->f; const int font_height = SHORT(f['A'-HU_FONTSTART]->height) + 1; - switch (align) + int y = 0; + + if (v_align == align_direct) { - case align_topleft: - case align_topleft_exclusive: - l->x = left_margin; - l->y = align_offset[align_topleft]; - align_offset[align_topleft] += font_height; - if (align == align_topleft_exclusive) - align_offset[align_topright] = align_offset[align_topleft]; - break; - case align_topright: - l->x = right_margin - l->width; - l->y = align_offset[align_topright]; - align_offset[align_topright] += font_height; - break; - case align_bottomleft: - align_offset[align_bottomleft] -= font_height; - l->x = left_margin; - l->y = align_offset[align_bottomleft]; - break; - case align_bottomright: - align_offset[align_bottomright] -= font_height; - l->x = right_margin - l->width; - l->y = align_offset[align_bottomright]; - break; - case align_topcenter: - l->x = ORIGWIDTH / 2 - l->width / 2; - align_offset[align_topcenter] = MAX(align_offset[align_topleft], align_offset[align_topright]); - l->y = align_offset[align_topcenter]; - align_offset[align_topcenter] += font_height; - align_offset[align_topleft] = align_offset[align_topright] = align_offset[align_topcenter]; - break; - case align_bottomcenter: - l->x = ORIGWIDTH / 2 - l->width / 2; - align_offset[align_bottomcenter] = MIN(align_offset[align_bottomleft], align_offset[align_bottomright]); - align_offset[align_bottomcenter] -= font_height; - l->y = align_offset[align_bottomcenter]; - align_offset[align_bottomleft] = align_offset[align_bottomright] = align_offset[align_bottomcenter]; - break; - default: - case align_direct: - break; + return w->y; } + // [FG] centered and Vanilla widgets are always exclusive, + // i.e. they don't allow any other widget on the same line + else if (h_align == align_center || m->on) + { + if (v_align == align_top) + { + y = MAX(align_offset[offset_topleft], + align_offset[offset_topright]); + + align_offset[offset_topleft] = + align_offset[offset_topright] = y + font_height; + } + else if (v_align == align_bottom) + { + y = MIN(align_offset[offset_bottomleft], + align_offset[offset_bottomright]) - font_height; + + align_offset[offset_bottomleft] = + align_offset[offset_bottomright] = y; + } + } + else if (v_align == align_top) + { + if (h_align == align_left) + { + y = align_offset[offset_topleft]; + align_offset[offset_topleft] += font_height; + } + else if (h_align == align_right) + { + y = align_offset[offset_topright]; + align_offset[offset_topright] += font_height; + } + } + else if (v_align == align_bottom) + { + if (h_align == align_left) + { + align_offset[offset_bottomleft] -= font_height; + y = align_offset[offset_bottomleft]; + } + else if (h_align == align_right) + { + align_offset[offset_bottomright] -= font_height; + y = align_offset[offset_bottomright]; + } + } + + return y; } -static void HUlib_drawTextLineAligned(hu_textline_t *l, boolean drawcursor) +// [FG] draw a line to a given screen coordinates using the given font + +static void draw_line_aligned (const hu_multiline_t *m, const hu_line_t *l, patch_t *const *const f, int x, int y) { - int i, x = l->x, y = l->y; // killough 1/18/98 -- support multiple lines + int i; unsigned char c; - char *oc = l->cr; //jff 2/17/98 remember default color - patch_t *const *const f = *l->f; + char *cr = m->cr; // draw the new stuff for (i = 0; i < l->len; i++) + { + c = toupper(l->line[i]); //jff insure were not getting a cheap toupper conv. + +#if 0 + if (c == '\n') { - c = toupper(l->l[i]); //jff insure were not getting a cheap toupper conv. - - if (c=='\n') // killough 1/18/98 -- support multiple lines - x = 0, y += 8; - else - if (c=='\t') // killough 1/23/98 -- support tab stops - x = (l->x + x + TABWIDTH) & ~TABWIDTH; - else - if (c == '\x1b') //jff 2/17/98 escape code for color change - { //jff 3/26/98 changed to actual escape char - if (++i < l->len) - { - if (l->l[i] >= '0' && l->l[i] <= '0'+CR_NONE) - l->cr = colrngs[l->l[i]-'0']; - else if (l->l[i] == '0'+CR_ORIG) // [FG] reset to original color - l->cr = oc; - } - } - else - if (c != ' ' && c >= HU_FONTSTART && c <= HU_FONTEND + 6) - { - int w = SHORT(f[c - HU_FONTSTART]->width); - if (x+w > SCREENWIDTH) - break; - // killough 1/18/98 -- support multiple lines: - V_DrawPatchTranslated(x, y, FG, f[c - HU_FONTSTART], l->cr); - x += w; - } - else - if ((x+=4) >= SCREENWIDTH) - break; + // [FG] TODO line breaks! } + else +#endif + if (c == '\t') // killough 1/23/98 -- support tab stops + { + x = (x + TABWIDTH) & ~TABWIDTH; + } + else if (c == '\x1b') //jff 2/17/98 escape code for color change + { //jff 3/26/98 changed to actual escape char + if (++i < l->len) + { + if (l->line[i] >= '0' && l->line[i] <= '0'+CR_NONE) + cr = colrngs[l->line[i]-'0']; + else if (l->line[i] == '0'+CR_ORIG) // [FG] reset to original color + cr = m->cr; + } + } + else if (c != ' ' && c >= HU_FONTSTART && c <= HU_FONTEND + 6) + { + int w = SHORT(f[c-HU_FONTSTART]->width); - l->cr = oc; //jff 2/17/98 restore original color + if (x+w > SCREENWIDTH) + break; + + // killough 1/18/98 -- support multiple lines: + V_DrawPatchTranslated(x, y, FG, f[c-HU_FONTSTART], cr); + x += w; + } + else if ((x += SPCWIDTH) >= SCREENWIDTH) + break; + } // draw the cursor if requested // killough 1/18/98 -- support multiple lines - if (drawcursor && x + SHORT(f['_' - HU_FONTSTART]->width) <= SCREENWIDTH) - V_DrawPatchTranslated(x, y, FG, f['_' - HU_FONTSTART], l->cr); + if (m->drawcursor && (leveltime & 16)) + { + cr = m->cr; //jff 2/17/98 restore original color + V_DrawPatchTranslated(x, y, FG, f['_' - HU_FONTSTART], cr); + } } -void HUlib_drawTextLine(hu_textline_t *l, align_t align, boolean drawcursor) +// [FG] shortcut for single-lined wigets + +static void draw_widget_single (const hu_widget_t *const w, patch_t *const *const f) { - HUlib_alignWidget(l, align); - HUlib_drawTextLineAligned(l, drawcursor); + const hu_multiline_t *m = w->multiline; + const int h_align = w->h_align, v_align = w->v_align; + + const int cl = m->curline; + const hu_line_t *l = m->lines[cl]; + + if (l->width || m->drawcursor) + { + int x, y; + + x = horz_align_widget(w, l, h_align); + y = vert_align_widget(w, m, f, h_align, v_align); + draw_line_aligned(m, l, f, x, y); + } } -// -// HUlib_eraseTextLine() -// -// Erases a hu_textline_t widget when screen border is behind text -// Sorta called by HU_Erase and just better darn get things straight -// -// Passed the hu_textline_t -// Returns nothing -// +// [FG] the w_messages widget is drawn bottom-up if v_align == align_top, +// i.e. the last message is drawn first, same for all other widgets +// if v_align == align_bottom -void HUlib_eraseTextLine(hu_textline_t* l) +static void draw_widget_bottomup (const hu_widget_t *const w, patch_t *const *const f) { - // killough 11/98: trick to shadow variables - int x = viewwindowx, y = viewwindowy; - int viewwindowx = x >> hires, viewwindowy = y >> hires; // killough 11/98 - patch_t *const *const f = *l->f; + const hu_multiline_t *m = w->multiline; + const int h_align = w->h_align, v_align = w->v_align; - // Only erases when NOT in automap and the screen is reduced, - // and the text must either need updating or refreshing - // (because of a recent change back from the automap) + const int nl = m->numlines; + int cl = m->curline - 1; - if (!automapactive && viewwindowx && l->needsupdate) + int i, x, y; + + for (i = 0; i < nl; i++, cl--) + { + const hu_line_t *l; + + if (cl < 0) + cl = nl - 1; + + l = m->lines[cl]; + + if (l->width) { - int yoffset, lh = SHORT(f['A'-HU_FONTSTART]->height) + 1; - for (y=l->y,yoffset=y*SCREENWIDTH ; yy+lh ; y++,yoffset+=SCREENWIDTH) - if (y < viewwindowy || y >= viewwindowy + scaledviewheight) // killough 11/98: - R_VideoErase(yoffset, SCREENWIDTH); // erase entire line - else - { - // erase left border - R_VideoErase(yoffset, viewwindowx); - // erase right border - R_VideoErase(yoffset + viewwindowx + scaledviewwidth, viewwindowx); // killough 11/98 - } + x = horz_align_widget(w, l, h_align); + y = vert_align_widget(w, m, f, h_align, v_align); + draw_line_aligned(m, l, f, x, y); } - - if (l->needsupdate) - l->needsupdate--; + } } -//////////////////////////////////////////////////////// -// -// Player message widget (up to 4 lines of text) -// -//////////////////////////////////////////////////////// +// [FG] standard behavior, the first line is drawn first -// -// HUlib_initSText() -// -// Initialize a hu_stext_t widget. Set the position, number of lines, font, -// start char of the font, and color range to be used, and whether enabled. -// -// Passed a hu_stext_t, and the values used to initialize -// Returns nothing -// -//jff 2/16/98 add color range parameter - -void HUlib_initSText(hu_mtext_t *s, int x, int y, int h, patch_t ***font, - char *cr, boolean *on) +static void draw_widget_topdown (const hu_widget_t *const w, patch_t *const *const f) { - int i; + const hu_multiline_t *m = w->multiline; + const int h_align = w->h_align, v_align = w->v_align; - s->nl = h; - s->on = on; - s->laston = true; - s->cl = 0; - for (i=0;il+i, x, y - i*(SHORT((*font[0])->height)+1), - font, cr, NULL); -} + const int nl = m->numlines; + int cl = m->curline; -// -// HUlib_addLineToSText() -// -// Adds a blank line to a hu_stext_t widget -// -// Passed a hu_stext_t -// Returns nothing -// + int i, x, y; -static void HUlib_addLineToSText(hu_mtext_t* s) -{ - int i; - if (++s->cl >= s->nl) // add a clear line - s->cl = 0; - HUlib_clearTextLine(s->l + s->cl); - for (i=0 ; inl ; i++) // everything needs updating - s->l[i].needsupdate = 4; -} + for (i = 0; i < nl; i++, cl++) + { + const hu_line_t *l; -// -// HUlib_addMessageToSText() -// -// Adds a message line with prefix to a hu_stext_t widget -// -// Passed a hu_stext_t, the prefix string, and a message string -// Returns nothing -// + if (cl >= nl) + cl = 0; -void HUlib_addMessageToSText(hu_mtext_t *s, char *prefix, char *msg) -{ - HUlib_addLineToSText(s); - if (prefix) - HUlib_addStringToTextLine(&s->l[s->cl], prefix); - HUlib_addStringToTextLine(&s->l[s->cl], msg); -} + l = m->lines[cl]; -// -// HUlib_drawSText() -// -// Displays a hu_stext_t widget -// -// Passed a hu_stext_t -// Returns nothing -// - -void HUlib_drawSText(hu_mtext_t* s, align_t align) -{ - int i; - if (*s->on) - for (i=0; inl; i++) - { - int idx = s->cl - i; - if (idx < 0) - idx += s->nl; // handle queue of lines - // need a decision made here on whether to skip the draw - HUlib_drawTextLine(&s->l[idx], align, false); // no cursor, please - } -} - -// -// HUlib_eraseSText() -// -// Erases a hu_stext_t widget, when the screen is not fullsize -// -// Passed a hu_stext_t -// Returns nothing -// - -void HUlib_eraseSText(hu_mtext_t* s) -{ - int i; - - for (i=0 ; inl ; i++) + if (l->width) { - if (s->laston && !*s->on) - s->l[i].needsupdate = 4; - HUlib_eraseTextLine(&s->l[i]); + x = horz_align_widget(w, l, h_align); + y = vert_align_widget(w, m, f, h_align, v_align); + draw_line_aligned(m, l, f, x, y); } - s->laston = *s->on; + } } -//////////////////////////////////////////////////////// -// -// Scrolling message review widget -// -// jff added 2/26/98 -// -//////////////////////////////////////////////////////// +void HUlib_draw_widget (const hu_widget_t *const w) +{ + const hu_multiline_t *m = w->multiline; + patch_t *const *const f = *m->font; -// -// HUlib_initMText() -// -// Initialize a hu_mtext_t widget. Set the position, width, number of lines, -// font, start char of the font, color range, background font, and whether -// enabled. -// -// Passed a hu_mtext_t, and the values used to initialize -// Returns nothing -// + if (m->numlines == 1) + draw_widget_single(w, f); + // [FG] Vanilla widget with top alignment, + // or Boom widget with bottom alignment + else if ((m->on != NULL) ^ (w->v_align == align_bottom)) + draw_widget_bottomup(w, f); + else + draw_widget_topdown(w, f); +} -void HUlib_initMText(hu_mtext_t *m, int x, int y, patch_t ***font, - char *cr, boolean *on) +void HUlib_init_multiline(hu_multiline_t *m, + int nl, + patch_t ***f, + char *cr, + boolean *on, + void (*builder)(void)) { int i; - m->nl = 0; - m->cl = -1; //jff 4/28/98 prepare for pre-increment - m->pos = x; + // [FG] dynamically allocate lines array + if (m->numlines != nl) + { + for (i = 0; i < m->numlines; i++) + { + free(m->lines[i]); + m->lines[i] = NULL; + } + } + + m->numlines = nl; + m->curline = 0; + + for (i = 0; i < m->numlines; i++) + { + if (m->lines[i] == NULL) + { + m->lines[i] = malloc(sizeof(hu_line_t)); + HUlib_clear_line(m->lines[i]); + } + } + + m->font = f; + m->cr = cr; + m->drawcursor = false; + m->on = on; - // killough 11/98: simplify - - y += HU_REFRESHSPACING * hud_msg_lines; - for (i=0; il[i], x, y, font, cr, NULL); -} - -// -// HUlib_addLineToMText() -// -// Adds a blank line to a hu_mtext_t widget -// -// Passed a hu_mtext_t -// Returns nothing -// - -static void HUlib_addLineToMText(hu_mtext_t *m) -{ - // add a clear line - if (++m->cl >= hud_msg_lines) - m->cl = 0; - - HUlib_clearTextLine(&m->l[m->cl]); - - m->l[m->cl].x = m->pos; - - if (m->nl < hud_msg_lines) - m->nl++; - - // needs updating - m->l[m->cl].needsupdate = 4; -} - -// -// HUlib_addMessageToMText() -// -// Adds a message line with prefix to a hu_mtext_t widget -// -// Passed a hu_mtext_t, the prefix string, and a message string -// Returns nothing -// - -void HUlib_addMessageToMText(hu_mtext_t *m, char *prefix, char *msg) -{ - HUlib_addLineToMText(m); - - if (prefix) - HUlib_addStringToTextLine(&m->l[m->cl], prefix); - - HUlib_addStringToTextLine(&m->l[m->cl], msg); -} - -// -// HUlib_drawMText() -// -// Displays a hu_mtext_t widget -// -// Passed a hu_mtext_t -// Returns nothing -// -// killough 11/98: Simplified, allowed text to scroll in either direction - -void HUlib_drawMText(hu_mtext_t* m, align_t align) -{ - int i; - - if (!*m->on) - return; // if not on, don't draw - - for (i=0 ; inl ; i++) - { - int idx = m->cl - i; - - if (idx < 0) - idx += m->nl; // handle queue of lines - - m->l[idx].y = i * HU_REFRESHSPACING; - - HUlib_drawTextLine(&m->l[idx], align, false); // no cursor, please - } -} - -// -// HUlib_eraseMText() -// -// Erases a hu_mtext_t widget, when the screen is not fullsize -// -// Passed a hu_mtext_t -// Returns nothing -// - -void HUlib_eraseMText(hu_mtext_t *m) -{ - int i; - - for (i=0 ; i< m->nl ; i++) - { - m->l[i].needsupdate = 4; - HUlib_eraseTextLine(&m->l[i]); - } -} - -//////////////////////////////////////////////////////// -// -// Interactive text entry widget -// -//////////////////////////////////////////////////////// - -// -// HUlib_initIText() -// -// Initialize a hu_itext_t widget. Set the position, font, -// start char of the font, color range, and whether enabled. -// -// Passed a hu_itext_t, and the values used to initialize -// Returns nothing -// -//jff 2/16/98 add color range parameter - -void HUlib_initIText(hu_mtext_t *it, int x, int y, patch_t ***font, - char *cr, boolean *on) -{ - it->on = on; - it->laston = true; - HUlib_initTextLine(&it->l[0], x, y, font, cr, NULL); -} - -// The following deletion routines adhere to the left margin restriction - -// -// HUlib_delCharFromIText() -// -// Deletes a character at the end of the text line in a hu_itext_t widget -// -// Passed the hu_itext_t -// Returns nothing -// - -static void HUlib_delCharFromIText(hu_mtext_t *it) -{ - if (it->l[0].len > 0) - HUlib_delCharFromTextLine(&it->l[0]); -} - -// -// HUlib_resetIText() -// -// Deletes all characters from a hu_itext_t widget -// Resets left margin as well -// -// Passed the hu_itext_t -// Returns nothing -// - -void HUlib_resetIText(hu_mtext_t *it) -{ - HUlib_clearTextLine(&it->l[0]); -} - -// -// HUlib_keyInIText() -// -// Wrapper function for handling general keyed input. -// -// Passed the hu_itext_t and the char input -// Returns true if it ate the key -// - -boolean HUlib_keyInIText(hu_mtext_t *it, unsigned char ch) -{ - if (ch >= ' ' && ch <= '_') - HUlib_addCharToTextLine(&it->l[0], (char) ch); - else - if (ch == KEY_BACKSPACE) // phares - HUlib_delCharFromIText(it); - else - if (ch != KEY_ENTER) // phares - return false; // did not eat key - return true; // ate the key -} - -// -// HUlib_drawIText() -// -// Displays a hu_itext_t widget -// -// Passed the hu_itext_t -// Returns nothing -// - -void HUlib_drawIText(hu_mtext_t *it, align_t align) -{ - hu_textline_t *l = &it->l[0]; - if ((l->visible = *it->on)) - HUlib_drawTextLine(l, align, true); // draw the line w/ cursor -} - -// -// HUlib_eraseIText() -// -// Erases a hu_itext_t widget when the screen is not fullsize -// -// Passed the hu_itext_t -// Returns nothing -// - -void HUlib_eraseIText(hu_mtext_t* it) -{ - if (it->laston && !*it->on) - it->l[0].needsupdate = 4; - HUlib_eraseTextLine(&it->l[0]); - it->laston = *it->on; + m->builder = builder; + m->built = false; } //---------------------------------------------------------------------------- diff --git a/src/hu_lib.h b/src/hu_lib.h index 474d4dfa..46d3d7cc 100644 --- a/src/hu_lib.h +++ b/src/hu_lib.h @@ -1,6 +1,7 @@ // // Copyright (C) 1999 by // id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman +// Copyright (C) 2023 Fabian Greffrath // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -19,203 +20,101 @@ #ifndef __HULIB__ #define __HULIB__ -// We are referring to patches. -#include "r_defs.h" -#include "v_video.h" //jff 2/16/52 include color range defs +#include "v_video.h" //jff 2/16/52 include color range defs #define CR_ORIG (-1) // [FG] reset to original color // background and foreground screen numbers // different from other modules. -#define BG 1 -#define FG 0 +#define BG 1 +#define FG 0 -// font stuff -// #define HU_CHARERASE KEY_BACKSPACE // not used // phares +#define HU_MAXLINELENGTH 80 -#define HU_MAXLINES 4 -#define HU_MAXLINELENGTH 80 -#define HU_REFRESHSPACING 8 /*jff 2/26/98 space lines in text refresh widget*/ //jff 2/26/98 maximum number of messages allowed in refresh list #define HU_MAXMESSAGES 8 -// -// Typedefs of widgets -// - -// Text Line widget -// (parent of Scrolling Text and Input Text widgets) -typedef struct -{ - // left-justified position of scrolling text window - int x; - int y; - - patch_t ***f; // font - char *cr; //jff 2/16/52 output color range - - // killough 1/23/98: Support multiple lines: - #define MAXLINES 25 - - int linelen; - char l[HU_MAXLINELENGTH*MAXLINES+1]; // line of text - int len; // current line length - - // whether this line needs to be udpated - int needsupdate; - - int width; - boolean visible; - void (*builder) (void); - -} hu_textline_t; - typedef enum { - align_topleft, - align_topleft_exclusive, - align_topright, - align_topcenter, - align_bottomleft, - align_bottomright, - align_bottomcenter, + // [FG] h_align / v_align align_direct, + + // [FG] h_align + align_left, + align_right, + align_center, + + // [FG] v_align + align_top, + align_bottom, + num_aligns, } align_t; -typedef struct { - hu_textline_t *line; - align_t align; - int x, y; -} widget_t; +// [FG] a single line of information -//jff 2/26/98 new widget to display last hud_msg_lines of messages -// Message refresh window widget typedef struct { - hu_textline_t l[HU_MAXMESSAGES]; // text lines to draw - int nl; // height in lines - int cl; // current line number - int pos; // current line x + char line[HU_MAXLINELENGTH]; + + // [FG] length in chars + int len; + + // [FG] length in chars + int width; + +} hu_line_t; + +// [FG] an array of lines with common properties + +typedef struct hu_multiline_s +{ + hu_line_t *lines[HU_MAXMESSAGES]; // text lines to draw + int numlines; // number of lines + int curline; // current line number + + patch_t ***font; // font + char *cr; //jff 2/16/52 output color range + boolean drawcursor; // pointer to boolean stating whether to update window - boolean* on; - boolean laston; // last value of *->on. + boolean *on; -} hu_mtext_t; + void (*builder)(void); + boolean built; -// -// Widget creation, access, and update routines -// +} hu_multiline_t; -// initializes heads-up widget library -void HUlib_init(void); +// [FG] configured alignment and coordinates for multilines -// -// textline code -// +typedef struct hu_widget_s +{ + hu_multiline_t *multiline; -// clear a line of text -void HUlib_clearTextLine(hu_textline_t *t); + align_t h_align, v_align; -void HUlib_initTextLine -( - hu_textline_t *t, - int x, - int y, - patch_t ***f, - char *cr, //jff 2/16/98 add color range parameter - void (*builder)(void) -); + // [FG] align_direct + int x, y; -// returns success -boolean HUlib_addCharToTextLine(hu_textline_t *t, char ch); -void HUlib_addStringToTextLine(hu_textline_t *t, char *s); +} hu_widget_t; -// draws tline -void HUlib_drawTextLine(hu_textline_t *l, align_t align, boolean drawcursor); -void HUlib_resetAlignOffsets(); -void HUlib_setMargins (void); +void HUlib_set_margins (void); +void HUlib_reset_align_offsets (void); -// erases text line -void HUlib_eraseTextLine(hu_textline_t *l); +void HUlib_clear_line (hu_line_t *const l); +void HUlib_clear_cur_line (hu_multiline_t *const m); +void HUlib_add_string_to_cur_line (hu_multiline_t *const m, const char *s); +void HUlib_add_strings_to_cur_line (hu_multiline_t *const m, const char *prefix, const char *msg); -// -// Scrolling Text window widget routines -// +void HUlib_draw_widget (const hu_widget_t *const w); -// initialize an stext widget -void HUlib_initSText -( hu_mtext_t* s, - int x, - int y, - int h, - patch_t ***font, - char *cr, //jff 2/16/98 add color range parameter - boolean* on ); +void HUlib_init_multiline (hu_multiline_t *const m, int nl, patch_t ***f, char *cr, boolean *on, void (*builder)(void)); -// add a text message to an stext widget -void HUlib_addMessageToSText -( hu_mtext_t* s, - char* prefix, - char* msg ); - -// draws stext -void HUlib_drawSText(hu_mtext_t* s, align_t align); - -// erases all stext lines -void HUlib_eraseSText(hu_mtext_t* s); - -//jff 2/26/98 message refresh widget -// initialize refresh text widget -void HUlib_initMText -( hu_mtext_t *m, - int x, - int y, - patch_t ***font, - char *cr, - boolean *on -); - -//jff 2/26/98 message refresh widget -// add a text message to refresh text widget -void HUlib_addMessageToMText -( hu_mtext_t* m, - char* prefix, - char* msg ); - -//jff 2/26/98 message refresh widget -// draws mtext -void HUlib_drawMText(hu_mtext_t* m, align_t align); - -//jff 4/28/98 erases behind message list -void HUlib_eraseMText(hu_mtext_t* m); - -// Input Text Line widget routines -void HUlib_initIText -( hu_mtext_t* it, - int x, - int y, - patch_t ***font, - char *cr, //jff 2/16/98 add color range parameter - boolean* on ); - -// resets line and left margin -void HUlib_resetIText(hu_mtext_t* it); - -// whether eaten -boolean HUlib_keyInIText -( hu_mtext_t* it, - unsigned char ch ); - -void HUlib_drawIText(hu_mtext_t* it, align_t align); - -// erases all itext lines -void HUlib_eraseIText(hu_mtext_t* it); +boolean HUlib_add_key_to_line (hu_line_t *const l, unsigned char ch); +boolean HUlib_add_key_to_cur_line (hu_multiline_t *const m, unsigned char ch); #endif - //---------------------------------------------------------------------------- // // $Log: hu_lib.h,v $ diff --git a/src/hu_stuff.c b/src/hu_stuff.c index c360e1d2..da255fa8 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -58,15 +58,7 @@ static boolean draw_crispy_hud; #define HU_TITLEP (*mapnamesp[gamemap-1]) #define HU_TITLET (*mapnamest[gamemap-1]) -#define HU_TITLEX (0 - WIDESCREENDELTA) -#define HU_TITLEY (ST_Y - 1 - SHORT(hu_font[0]->height)) - -#define HU_HUDX (2 - WIDESCREENDELTA) - -#define HU_INPUTX (HU_MSGX) -#define HU_INPUTY (HU_MSGY + HU_REFRESHSPACING) - -char* chat_macros[] = // Ty 03/27/98 - *not* externalized +char *chat_macros[] = // Ty 03/27/98 - *not* externalized { HUSTR_CHATMACRO0, HUSTR_CHATMACRO1, @@ -91,7 +83,7 @@ char **player_names[] = //jff 3/17/98 translate player colmap to text color ranges int plyrcoltran[MAXPLAYERS]={CR_GREEN,CR_GRAY,CR_BROWN,CR_RED}; -static player_t* plr; +static player_t *plr; // font sets static patch_t* hu_fontA[HU_FONTSIZE+6]; @@ -101,79 +93,101 @@ patch_t **hu_font2 = hu_fontB; static int CR_BLUE = CR_BLUE1; // widgets -static hu_textline_t w_title; -static hu_mtext_t w_message; -static hu_mtext_t w_chat; -static hu_mtext_t w_inputbuffer[MAXPLAYERS]; -static hu_textline_t w_coord; -static hu_textline_t w_fps; -static hu_textline_t w_ammo; //jff 2/16/98 new ammo widget for hud -static hu_textline_t w_health; //jff 2/16/98 new health widget for hud -static hu_textline_t w_armor; //jff 2/16/98 new armor widget for hud -static hu_textline_t w_weapon; //jff 2/16/98 new weapon widget for hud -static hu_textline_t w_keys; //jff 2/16/98 new keys widget for hud -static hu_textline_t w_monsec; //jff 2/16/98 new kill/secret widget for hud -static hu_mtext_t w_rtext; //jff 2/26/98 text message refresh widget -static hu_mtext_t w_secret; // [crispy] secret message widget -static hu_textline_t w_sttime; // time above status bar + +// [FG] Vanilla widgets point to a boolean variable (*on) to determine +// if they are enabled, always hu_fontA, mostly left-aligned +static hu_multiline_t w_title; +static hu_multiline_t w_message; +static hu_multiline_t w_chat; +static hu_multiline_t w_secret; // [crispy] secret message widget + +// [FG] special pony, per-player chat input buffer +static hu_line_t w_inputbuffer[MAXPLAYERS]; + +// [FG] Boom widgets are built using builder() functions +static hu_multiline_t w_ammo; //jff 2/16/98 new ammo widget for hud +static hu_multiline_t w_armor; //jff 2/16/98 new armor widget for hud +static hu_multiline_t w_health; //jff 2/16/98 new health widget for hud +static hu_multiline_t w_keys; //jff 2/16/98 new keys widget for hud +static hu_multiline_t w_weapon; //jff 2/16/98 new weapon widget for hud + +// [FG] extra Boom widgets, that need to be explicitly enabled +static hu_multiline_t w_monsec; //jff 2/16/98 new kill/secret widget for hud +static hu_multiline_t w_sttime; // time above status bar +static hu_multiline_t w_coord; +static hu_multiline_t w_fps; #define MAX_HUDS 3 -#define MAX_WIDGETS 12 +#define MAX_WIDGETS 10 -static widget_t widgets[MAX_HUDS][MAX_WIDGETS] = { +static hu_widget_t doom_widgets[MAX_HUDS][MAX_WIDGETS] = { { - {&w_title, align_bottomleft}, - - {&w_monsec, align_bottomleft}, - {&w_sttime, align_bottomleft}, - {&w_coord, align_topright}, - {&w_fps, align_topright}, + {&w_title, align_left, align_bottom}, + {&w_message, align_left, align_top}, + {&w_chat, align_left, align_top}, + {&w_secret, align_center, align_direct, 0, 84}, {NULL} }, { - {&w_title, align_bottomleft}, - - {&w_armor, align_bottomleft}, - {&w_health, align_bottomleft}, - {&w_ammo, align_bottomleft}, - {&w_weapon, align_bottomleft}, - {&w_keys, align_bottomleft}, - - {&w_monsec, align_bottomleft}, - {&w_sttime, align_bottomleft}, - {&w_coord, align_topright}, - {&w_fps, align_topright}, + {&w_title, align_left, align_bottom}, + {&w_message, align_left, align_top}, + {&w_chat, align_left, align_top}, + {&w_secret, align_center, align_direct, 0, 84}, {NULL} }, { - {&w_title, align_bottomleft}, - - {&w_health, align_topright}, - {&w_armor, align_topright}, - {&w_ammo, align_bottomright}, - {&w_weapon, align_bottomright}, - {&w_keys, align_bottomleft}, - - {&w_monsec, align_bottomleft}, - {&w_sttime, align_bottomleft}, - {&w_coord , align_topright}, - {&w_fps, align_topright}, + {&w_title, align_left, align_bottom}, + {&w_message, align_left, align_top}, + {&w_chat, align_left, align_top}, + {&w_secret, align_center, align_direct, 0, 84}, {NULL} } }; -static widget_t *widget = *widgets; +static hu_widget_t boom_widgets[MAX_HUDS][MAX_WIDGETS] = { + { + {&w_monsec, align_left, align_bottom}, + {&w_sttime, align_left, align_bottom}, + {&w_coord, align_right, align_top}, + {&w_fps, align_right, align_top}, + {NULL} + }, { + {&w_armor, align_left, align_bottom}, + {&w_health, align_left, align_bottom}, + {&w_ammo, align_left, align_bottom}, + {&w_weapon, align_left, align_bottom}, + {&w_keys, align_left, align_bottom}, + + {&w_monsec, align_left, align_bottom}, + {&w_sttime, align_left, align_bottom}, + {&w_coord, align_right, align_top}, + {&w_fps, align_right, align_top}, + {NULL} + }, { + {&w_health, align_right, align_top}, + {&w_armor, align_right, align_top}, + {&w_ammo, align_right, align_bottom}, + {&w_weapon, align_right, align_bottom}, + {&w_keys, align_left, align_bottom}, + + {&w_monsec, align_left, align_bottom}, + {&w_sttime, align_left, align_bottom}, + {&w_coord , align_right, align_top}, + {&w_fps, align_right, align_top}, + {NULL} + } +}; + +static hu_widget_t *doom_widget = doom_widgets[0], + *boom_widget = boom_widgets[0]; static void HU_ParseHUD (void); -static boolean always_off = false; static char chat_dest[MAXPLAYERS]; boolean chat_on; static boolean message_on; -static boolean message_list_on; // killough 11/98 static boolean has_message; // killough 12/98 boolean message_dontfuckwithme; static boolean message_nottobefuckedwith; static int message_counter; -static int message_list_counter; // killough 11/98 static int message_count; // killough 11/98 static int chat_count; // killough 11/98 static boolean secret_on; @@ -217,9 +231,7 @@ extern char **mapnamest[]; // jff 5/10/98 french support removed, // as it was not being used and couldn't be easily tested // -const char* shiftxform; - -const char english_shiftxform[] = +const char shiftxform[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, @@ -382,8 +394,6 @@ void HU_Init(void) int i, j; char buffer[9]; - shiftxform = english_shiftxform; - // load the heads-up font j = HU_FONTSTART; for (i = 0; i < HU_FONTSIZE; i++, j++) @@ -484,26 +494,49 @@ void HU_Init(void) HU_ResetMessageColors(); } -static inline void HU_enableWidget (hu_textline_t *line, boolean cond) +// [FG] support centered player messages + +static void HU_set_centered_message() { - if (cond) + int i, j; + + for (i = 0; i < MAX_HUDS; i++) { - line->visible = true; + hu_widget_t *const d_w = doom_widgets[i]; + + for (j = 0; d_w[j].multiline; j++) + { + if (d_w[j].multiline == &w_message) + { + if (d_w[j].h_align == align_direct) + continue; + + // [FG] save original alignment in the unused x coordinate + if (d_w[j].x == 0) + d_w[j].x = d_w[j].h_align; + + d_w[j].h_align = message_centered ? align_center : d_w[j].x; + } + } } } -void HU_disableAllWidgets (void) +static inline void HU_cond_build_widget (hu_multiline_t *const multiline, boolean cond) { - widget_t *w = widget; - - while (w->line) + if (cond) { - if (w->align == align_direct) - { - w->line->x = w->x; - w->line->y = w->y; - } - w->line->visible = false; + multiline->builder(); + multiline->built = true; + } +} + +void HU_disable_all_widgets (void) +{ + hu_widget_t *w = boom_widget; + + while (w->multiline) + { + w->multiline->built = false; w++; } } @@ -559,8 +592,7 @@ void HU_Start(void) secret_on = false; // killough 11/98: - message_list_on = false; - message_counter = message_list_counter = 0; + message_counter = 0; message_count = (message_timer * TICRATE) / 1000 + 1; chat_count = (chat_msg_timer * TICRATE) / 1000 + 1; @@ -568,71 +600,83 @@ void HU_Start(void) I_GetScreenDimensions(); // create the message widget - // messages to player in upper-left of screen - HUlib_initSText(&w_message, HU_MSGX, HU_MSGY, HU_MSGHEIGHT, &hu_font, - colrngs[hudcolor_mesg], &message_on); + HUlib_init_multiline(&w_message, message_list ? hud_msg_lines : 1, + &hu_font, colrngs[hudcolor_mesg], + &message_on, NULL); // create the secret message widget - HUlib_initSText(&w_secret, 0, 100 - 2*SHORT(hu_font[0]->height), HU_MSGHEIGHT, &hu_font, - colrngs[CR_GOLD], &secret_on); - - //jff 2/26/98 add the text refresh widget initialization - HUlib_initMText(&w_rtext, HU_MSGX, HU_MSGY, &hu_font, - colrngs[hudcolor_mesg], &message_list_on); // killough 11/98 - - // create the hud text refresh widget - // scrolling display of last hud_msg_lines messages received - if (hud_msg_lines > HU_MAXMESSAGES) - { - hud_msg_lines = HU_MAXMESSAGES; - } + HUlib_init_multiline(&w_secret, 1, + &hu_font, colrngs[CR_GOLD], + &secret_on, NULL); // create the chat widget - HUlib_initIText(&w_chat, HU_INPUTX, HU_INPUTY, &hu_font, - colrngs[hudcolor_chat], &chat_on); + HUlib_init_multiline(&w_chat, 1, + &hu_font, colrngs[hudcolor_chat], + &chat_on, NULL); + // [FG] only the chat widget draws a cursor + w_chat.drawcursor = true; // create the inputbuffer widgets, one per player for (i = 0; i < MAXPLAYERS; i++) { - HUlib_initIText(&w_inputbuffer[i], 0, 0, 0, - colrngs[hudcolor_chat], &always_off); + HUlib_clear_line(&w_inputbuffer[i]); } //jff 2/16/98 added some HUD widgets - // create the map title widget - map title display in lower left of automap - HUlib_initTextLine(&w_title, HU_TITLEX, HU_TITLEY, &hu_font, - colrngs[hudcolor_titl], NULL); // [FG] built only once below + // create the map title widget + HUlib_init_multiline(&w_title, 1, + &hu_font, colrngs[hudcolor_titl], + &automapactive, HU_widget_build_title); + // [FG] built only once right here + w_title.builder(); // create the hud health widget - HUlib_initTextLine(&w_health, 0, 0, &hu_font2, colrngs[CR_GREEN], HU_widget_build_health); + HUlib_init_multiline(&w_health, 1, + &hu_font2, colrngs[CR_GREEN], + NULL, HU_widget_build_health); // create the hud armor widget - HUlib_initTextLine(&w_armor, 0, 0, &hu_font2, colrngs[CR_GREEN], HU_widget_build_armor); + HUlib_init_multiline(&w_armor, 1, + &hu_font2, colrngs[CR_GREEN], + NULL, HU_widget_build_armor); // create the hud ammo widget - HUlib_initTextLine(&w_ammo, 0, 0, &hu_font2, colrngs[CR_GOLD], HU_widget_build_ammo); + HUlib_init_multiline(&w_ammo, 1, + &hu_font2, colrngs[CR_GOLD], + NULL, HU_widget_build_ammo); // create the hud weapons widget - HUlib_initTextLine(&w_weapon, 0, 0, &hu_font2, colrngs[CR_GRAY], HU_widget_build_weapon); + HUlib_init_multiline(&w_weapon, 1, + &hu_font2, colrngs[CR_GRAY], + NULL, HU_widget_build_weapon); // create the hud keys widget - HUlib_initTextLine(&w_keys, 0, 0, &hu_font2, colrngs[CR_GRAY], deathmatch ? HU_widget_build_frag : HU_widget_build_keys); + HUlib_init_multiline(&w_keys, 1, + &hu_font2, colrngs[CR_GRAY], + NULL, deathmatch ? HU_widget_build_frag : HU_widget_build_keys); // create the hud monster/secret widget - HUlib_initTextLine(&w_monsec, 0, 0, &hu_font2, colrngs[CR_GRAY], HU_widget_build_monsec); + HUlib_init_multiline(&w_monsec, 1, + &hu_font2, colrngs[CR_GRAY], + NULL, HU_widget_build_monsec); - HUlib_initTextLine(&w_sttime, 0, 0, &hu_font2, colrngs[CR_GRAY], HU_widget_build_sttime); + HUlib_init_multiline(&w_sttime, 1, + &hu_font2, colrngs[CR_GRAY], + NULL, HU_widget_build_sttime); // create the automaps coordinate widget - HUlib_initTextLine(&w_coord, 0, 0, &hu_font2, colrngs[hudcolor_xyco], HU_widget_build_coord); + HUlib_init_multiline(&w_coord, 1, + &hu_font2, colrngs[hudcolor_xyco], + NULL, HU_widget_build_coord); - HUlib_initTextLine(&w_fps, 0, 0, &hu_font2, colrngs[hudcolor_xyco], HU_widget_build_fps); + HUlib_init_multiline(&w_fps, 1, + &hu_font2, colrngs[hudcolor_xyco], + NULL, HU_widget_build_fps); - // initialize the automap's level title widget - HU_widget_build_title(); + HU_set_centered_message(); - HU_disableAllWidgets(); - HUlib_setMargins(); + HU_disable_all_widgets(); + HUlib_set_margins(); // init crosshair if (hud_crosshair) @@ -687,8 +731,8 @@ static void HU_widget_build_title (void) } M_StringConcat(hud_titlestr, s, sizeof(hud_titlestr)); - HUlib_clearTextLine(&w_title); - HUlib_addStringToTextLine(&w_title, hud_titlestr); + + HUlib_add_string_to_cur_line(&w_title, hud_titlestr); } // do the hud ammo display @@ -697,15 +741,12 @@ static void HU_widget_build_ammo (void) char hud_ammostr[HU_MAXLINELENGTH] = "AMM "; int i = 4; - // clear the widgets internal line - HUlib_clearTextLine(&w_ammo); - // special case for weapon with no ammo selected - blank bargraph + N/A if (weaponinfo[plr->readyweapon].ammo == am_noammo) { if (hud_draw_bargraphs) { - strcat(hud_ammostr, "\x7f\x7f\x7f\x7f\x7f\x7f\x7f "); + strcat(hud_ammostr, "\x7f\x7f\x7f\x7f\x7f\x7f\x7f"); } strcat(hud_ammostr, "N/A"); w_ammo.cr = colrngs[CR_GRAY]; @@ -747,7 +788,7 @@ static void HU_widget_build_ammo (void) } // build the numeric amount init string - sprintf(hud_ammostr + i, "%d/%d", ammo, fullammo); + sprintf(hud_ammostr + i, "%3d/%3d", ammo, fullammo); // backpack changes thresholds (ammo widget) if (plr->backpack && !hud_backpack_thresholds && fullammo) @@ -765,7 +806,7 @@ static void HU_widget_build_ammo (void) } // transfer the init string to the widget - HUlib_addStringToTextLine(&w_ammo, hud_ammostr); + HUlib_add_string_to_cur_line(&w_ammo, hud_ammostr); } // do the hud health display @@ -775,9 +816,6 @@ static void HU_widget_build_health (void) int i = 4; int healthbars = (st_health > 100) ? 25 : (st_health / 4); - // clear the widgets internal line - HUlib_clearTextLine(&w_health); - // build the bargraph string if (hud_draw_bargraphs) { @@ -814,7 +852,7 @@ static void HU_widget_build_health (void) w_health.cr = ColorByHealth(plr->health, 100, st_invul); // transfer the init string to the widget - HUlib_addStringToTextLine(&w_health, hud_healthstr); + HUlib_add_string_to_cur_line(&w_health, hud_healthstr); } // do the hud armor display @@ -824,9 +862,6 @@ static void HU_widget_build_armor (void) int i = 4; int armorbars = (st_armor > 100) ? 25 : (st_armor / 4); - // clear the widgets internal line - HUlib_clearTextLine(&w_armor); - // build the bargraph string if (hud_draw_bargraphs) { @@ -882,7 +917,7 @@ static void HU_widget_build_armor (void) } // transfer the init string to the widget - HUlib_addStringToTextLine(&w_armor, hud_armorstr); + HUlib_add_string_to_cur_line(&w_armor, hud_armorstr); } // do the hud weapon display @@ -891,9 +926,6 @@ static void HU_widget_build_weapon (void) char hud_weapstr[HU_MAXLINELENGTH] = "WEA "; int i = 4, w, ammo, fullammo, ammopct; - // clear the widgets internal line - HUlib_clearTextLine(&w_weapon); - // do each weapon that exists in current gamemode for (w = 0; w <= wp_supershotgun; w++) //jff 3/4/98 show fists too, why not? { @@ -951,10 +983,32 @@ static void HU_widget_build_weapon (void) } // transfer the init string to the widget - HUlib_addStringToTextLine(&w_weapon, hud_weapstr); + HUlib_add_string_to_cur_line(&w_weapon, hud_weapstr); } -static inline int HU_top(char *fragstr, int i, int idx1, int top1) +static void HU_widget_build_keys (void) +{ + char hud_keysstr[HU_MAXLINELENGTH] = { 'K', 'E', 'Y', '\x1b', '0'+CR_NONE, ' ', '\0' }; + int i = 6, k; + + // build text string whose characters call out graphic keys + for (k = 0; k < 6; k++) + { + // skip keys not possessed + if (!plr->cards[k]) + continue; + + hud_keysstr[i++] = HU_FONTEND + k + 1; // key number plus HU_FONTEND is char for key + hud_keysstr[i++] = ' '; // spacing + hud_keysstr[i++] = ' '; + } + hud_keysstr[i] = '\0'; + + // transfer the built string (frags or key title) to the widget + HUlib_add_string_to_cur_line(&w_keys, hud_keysstr); +} + +static inline int HU_top (char *const fragstr, int i, const int idx1, const int top1) { if (idx1 > -1) { @@ -972,41 +1026,15 @@ static inline int HU_top(char *fragstr, int i, int idx1, int top1) return i; } -static void HU_widget_build_keys (void) -{ - char hud_keysstr[HU_MAXLINELENGTH] = { 'K', 'E', 'Y', ' ', '\x1b', '0'+CR_NONE, '\0' }; - int i = 6, k; - - HUlib_clearTextLine(&w_keys); // clear the widget strings - - // build text string whose characters call out graphic keys - for (k = 0; k < 6; k++) - { - // skip keys not possessed - if (!plr->cards[k]) - continue; - - hud_keysstr[i++] = HU_FONTEND + k + 1; // key number plus HU_FONTEND is char for key - hud_keysstr[i++] = ' '; // spacing - hud_keysstr[i++] = ' '; - } - hud_keysstr[i] = '\0'; - - // transfer the built string (frags or key title) to the widget - HUlib_addStringToTextLine(&w_keys, hud_keysstr); -} - static void HU_widget_build_frag (void) { - char hud_fragstr[HU_MAXLINELENGTH] = { 'F', 'R', 'G', ' ', '\x1b', '0'+CR_ORIG, '\0' }; + char hud_fragstr[HU_MAXLINELENGTH] = { 'F', 'R', 'G', '\x1b', '0'+CR_ORIG, ' ', '\0' }; int i = 6, k; int top1 = -999, top2 = -999, top3 = -999, top4 = -999; int idx1 = -1, idx2 = -1, idx3 = -1, idx4 = -1; int fragcount, m; - HUlib_clearTextLine(&w_keys); // clear the widget strings - // scan thru players for (k = 0; k < MAXPLAYERS; k++) { @@ -1069,7 +1097,7 @@ static void HU_widget_build_frag (void) hud_fragstr[i] = '\0'; // transfer the built string (frags or key title) to the widget - HUlib_addStringToTextLine(&w_keys, hud_fragstr); + HUlib_add_string_to_cur_line(&w_keys, hud_fragstr); } static void HU_widget_build_monsec(void) @@ -1136,8 +1164,7 @@ static void HU_widget_build_monsec(void) '0'+CR_RED, items_color, items, totalitems, '0'+CR_RED, secrets_color, secrets, totalsecret); - HUlib_clearTextLine(&w_monsec); - HUlib_addStringToTextLine(&w_monsec, hud_monsecstr); + HUlib_add_string_to_cur_line(&w_monsec, hud_monsecstr); } static void HU_widget_build_sttime(void) @@ -1162,8 +1189,7 @@ static void HU_widget_build_sttime(void) sprintf(hud_timestr + offset, "\x1b%c%d:%05.2f\t", '0'+CR_GRAY, leveltime/TICRATE/60, (float)(leveltime%(60*TICRATE))/TICRATE); - HUlib_clearTextLine(&w_sttime); - HUlib_addStringToTextLine(&w_sttime, hud_timestr); + HUlib_add_string_to_cur_line(&w_sttime, hud_timestr); } static void HU_widget_build_coord (void) @@ -1181,8 +1207,7 @@ static void HU_widget_build_coord (void) '0'+CR_GRAY, y >> FRACBITS, '0'+hudcolor_xyco, '0'+CR_GRAY, z >> FRACBITS); - HUlib_clearTextLine(&w_coord); - HUlib_addStringToTextLine(&w_coord, hud_coordstr); + HUlib_add_string_to_cur_line(&w_coord, hud_coordstr); } static void HU_widget_build_fps (void) @@ -1191,8 +1216,7 @@ static void HU_widget_build_fps (void) extern int fps; sprintf(hud_fpsstr,"\x1b%c%d \x1b%cFPS", '0'+CR_GRAY, fps, '0'+CR_ORIG); - HUlib_clearTextLine(&w_fps); - HUlib_addStringToTextLine(&w_fps, hud_fpsstr); + HUlib_add_string_to_cur_line(&w_fps, hud_fpsstr); } // Crosshair @@ -1369,10 +1393,9 @@ int hud_level_stats, hud_level_time; // void HU_Drawer(void) { - widget_t *w = widget; - align_t align_text = message_centered ? align_topcenter : align_topleft_exclusive; + hu_widget_t *w; - HUlib_resetAlignOffsets(); + HUlib_reset_align_offsets(); // jff 4/24/98 Erase current lines before drawing current // needed when screen not fullsize @@ -1383,26 +1406,27 @@ void HU_Drawer(void) HU_Erase(); } - if (message_list) - HUlib_drawMText(&w_rtext, align_text); - else - HUlib_drawSText(&w_message, align_text); - - // display the interactive buffer for chat entry - HUlib_drawIText(&w_chat, align_topleft_exclusive); - - HUlib_drawSText(&w_secret, align_direct); + w = doom_widget; + while (w->multiline) + { + if (*w->multiline->on) + { + HUlib_draw_widget(w); + } + w++; + } if (draw_crispy_hud) { ST_Drawer (false, true); } - while (w->line) + w = boom_widget; + while (w->multiline) { - if (w->line->visible) + if (w->multiline->built) { - HUlib_drawTextLine(w->line, w->align, false); + HUlib_draw_widget(w); } w++; } @@ -1411,13 +1435,14 @@ void HU_Drawer(void) // [FG] draw Time widget on intermission screen void WI_DrawTimeWidget(void) { + hu_widget_t w = {&w_sttime, align_left, align_top}; + if (hud_level_time) { - w_sttime.x = HU_HUDX; - w_sttime.y = 0; + HUlib_reset_align_offsets(); // leveltime is already added to totalleveltimes before WI_Start() //HU_widget_build_sttime(); - HUlib_drawTextLine(&w_sttime, align_direct, false); + HUlib_draw_widget(&w); } } @@ -1431,26 +1456,9 @@ void WI_DrawTimeWidget(void) void HU_Erase(void) { - // erase the message display or the message review display - if (!message_list) - HUlib_eraseSText(&w_message); - else - HUlib_eraseMText(&w_rtext); - - HUlib_eraseSText(&w_secret); - - // erase the interactive text buffer for chat entry - HUlib_eraseIText(&w_chat); - - // erase the automap title - HUlib_eraseTextLine(&w_title); - - // [FG] erase FPS counter widget - HUlib_eraseTextLine(&w_coord); - HUlib_eraseTextLine(&w_fps); - - HUlib_eraseTextLine(&w_monsec); - HUlib_eraseTextLine(&w_sttime); + // [FG] TODO optimize! + if (!automapactive && viewwindowx) + R_DrawViewBorder(); } // @@ -1468,10 +1476,11 @@ int M_StringWidth(char *string); void HU_Ticker(void) { - widget_t *w = widget = widgets[hud_active]; + doom_widget = doom_widgets[hud_active]; + boom_widget = boom_widgets[hud_active]; plr = &players[displayplayer]; // killough 3/7/98 - HU_disableAllWidgets(); + HU_disable_all_widgets(); draw_crispy_hud = false; if ((automapactive && hud_widget_font == 1) || hud_widget_font == 2) @@ -1485,14 +1494,10 @@ void HU_Ticker(void) CR_BLUE = CR_BLUE1; } - // killough 11/98: support counter for message list as well as regular msg - if (message_list_counter && !--message_list_counter) - message_list_on = false; - // wait a few tics before sending a backspace character if (bsdown && bscounter++ > 9) { - HUlib_keyInIText(&w_chat, KEY_BACKSPACE); + HUlib_add_key_to_cur_line(&w_chat, KEY_BACKSPACE); bscounter = 8; } @@ -1506,9 +1511,7 @@ void HU_Ticker(void) // [Woof!] "A secret is revealed!" message if (plr->secretmessage) { - w_secret.l[0].x = ORIGWIDTH/2 - M_StringWidth(plr->secretmessage)/2; - - HUlib_addMessageToSText(&w_secret, 0, plr->secretmessage); + HUlib_add_string_to_cur_line(&w_secret, plr->secretmessage); plr->secretmessage = NULL; secret_on = true; secret_counter = 5*TICRATE/2; // [crispy] 2.5 seconds @@ -1522,26 +1525,14 @@ void HU_Ticker(void) (!message_nottobefuckedwith || message_dontfuckwithme)) { //post the message to the message widget - HUlib_addMessageToSText(&w_message, 0, plr->message); - - //jff 2/26/98 add message to refresh text widget too - HUlib_addMessageToMText(&w_rtext, 0, plr->message); + HUlib_add_string_to_cur_line(&w_message, plr->message); // clear the message to avoid posting multiple times plr->message = 0; - // killough 11/98: display message list, possibly timed - if (message_list) - { - message_list_on = true; - message_list_counter = message_count; - } - else - { - message_on = true; // note a message is displayed - // start the message persistence counter - message_counter = message_count; - } + message_on = true; // note a message is displayed + // start the message persistence counter + message_counter = message_count; has_message = true; // killough 12/98 @@ -1573,16 +1564,16 @@ void HU_Ticker(void) if (c >= 'a' && c <= 'z') c = (char) shiftxform[(unsigned char) c]; - rc = HUlib_keyInIText(&w_inputbuffer[i], c); + rc = HUlib_add_key_to_line(&w_inputbuffer[i], c); if (rc && c == KEY_ENTER) { - if (w_inputbuffer[i].l[0].len && + if (w_inputbuffer[i].len && (chat_dest[i] == consoleplayer + 1 || chat_dest[i] == HU_BROADCAST)) { - HUlib_addMessageToSText(&w_message, - *player_names[i], - w_inputbuffer[i].l[0].l); + HUlib_add_strings_to_cur_line(&w_message, + *player_names[i], + w_inputbuffer[i].line); has_message = true; // killough 12/98 message_nottobefuckedwith = true; @@ -1591,7 +1582,7 @@ void HU_Ticker(void) S_StartSound(0, gamemode == commercial ? sfx_radio : sfx_tink); } - HUlib_resetIText(&w_inputbuffer[i]); + HUlib_clear_line(&w_inputbuffer[i]); } } players[i].cmd.chatchar = 0; @@ -1603,19 +1594,16 @@ void HU_Ticker(void) if (automapactive) { - // map title - HU_enableWidget(&w_title, true); - - HU_enableWidget(&w_monsec, map_level_stats); - HU_enableWidget(&w_sttime, map_level_time); - HU_enableWidget(&w_coord, STRICTMODE(map_player_coords)); + HU_cond_build_widget(&w_monsec, map_level_stats); + HU_cond_build_widget(&w_sttime, map_level_time); + HU_cond_build_widget(&w_coord, STRICTMODE(map_player_coords)); } else { - HU_enableWidget(&w_coord, STRICTMODE(map_player_coords) == 2); + HU_cond_build_widget(&w_coord, STRICTMODE(map_player_coords) == 2); } - HU_enableWidget(&w_fps, plr->cheats & CF_SHOWFPS); + HU_cond_build_widget(&w_fps, plr->cheats & CF_SHOWFPS); if (hud_displayed && scaledviewheight == SCREENHEIGHT && @@ -1628,32 +1616,22 @@ void HU_Ticker(void) } else { - HU_enableWidget(&w_weapon, true); - HU_enableWidget(&w_armor, true); - HU_enableWidget(&w_health, true); - HU_enableWidget(&w_ammo, true); - HU_enableWidget(&w_keys, true); + HU_cond_build_widget(&w_weapon, true); + HU_cond_build_widget(&w_armor, true); + HU_cond_build_widget(&w_health, true); + HU_cond_build_widget(&w_ammo, true); + HU_cond_build_widget(&w_keys, true); } - HU_enableWidget(&w_monsec, hud_level_stats); - HU_enableWidget(&w_sttime, hud_level_time); + HU_cond_build_widget(&w_monsec, hud_level_stats); + HU_cond_build_widget(&w_sttime, hud_level_time); } else if (scaledviewheight && scaledviewheight < SCREENHEIGHT && automap_off) { - HU_enableWidget(&w_monsec, hud_level_stats); - HU_enableWidget(&w_sttime, hud_level_time); - } - - while (w->line) - { - if (w->line->visible) - { - if (w->line->builder) - w->line->builder(); - } - w++; + HU_cond_build_widget(&w_monsec, hud_level_stats); + HU_cond_build_widget(&w_sttime, hud_level_time); } // update crosshair properties @@ -1768,18 +1746,8 @@ boolean HU_Responder(event_t *ev) if (has_message) { - // killough 11/98: Support timed or continuous message lists - - if (!message_list) // if not message list, refresh message - { message_counter = message_count; message_on = true; - } - else - { - message_list_counter = message_count; - message_list_on = true; - } } eatkey = true; } //jff 2/26/98 no chat if message review is displayed @@ -1789,7 +1757,7 @@ boolean HU_Responder(event_t *ev) if (netgame && M_InputActivated(input_chat)) { eatkey = chat_on = true; - HUlib_resetIText(&w_chat); + HUlib_clear_cur_line(&w_chat); HU_queueChatChar(HU_BROADCAST); }//jff 2/26/98 else // killough 11/98: simplify @@ -1808,7 +1776,7 @@ boolean HU_Responder(event_t *ev) if (playeringame[i]) { eatkey = chat_on = true; - HUlib_resetIText(&w_chat); + HUlib_clear_cur_line(&w_chat); HU_queueChatChar((char)(i+1)); break; } @@ -1849,16 +1817,16 @@ boolean HU_Responder(event_t *ev) { if (shiftdown || (c >= 'a' && c <= 'z')) c = shiftxform[c]; - eatkey = HUlib_keyInIText(&w_chat, c); + eatkey = HUlib_add_key_to_cur_line(&w_chat, c); if (eatkey) HU_queueChatChar(c); if (c == KEY_ENTER) // phares { chat_on = false; - if (w_chat.l[0].len) + if (w_chat.lines[0]->len) { - strcpy(lastmessage, w_chat.l[0].l); + strcpy(lastmessage, w_chat.lines[0]->line); displaymsg("%s", lastmessage); } } @@ -1872,23 +1840,36 @@ boolean HU_Responder(event_t *ev) // [FG] dynamic HUD alignment -static const struct { +typedef struct { const char *name, *altname; - hu_textline_t *const line; -} w_names[] = { - {"title", "levelname", &w_title}, - {"armor", NULL, &w_armor}, - {"health", NULL, &w_health}, - {"ammo", NULL, &w_ammo}, - {"weapon", "weapons", &w_weapon}, - {"keys", NULL, &w_keys}, - {"monsec", "stats", &w_monsec}, - {"sttime", "time", &w_sttime}, - {"coord", "coords", &w_coord}, - {"fps", "rate", &w_fps}, + hu_multiline_t *const multiline; +} multiline_names_t; + +static const multiline_names_t + doom_names[] = { + {"title", NULL, &w_title}, + {"message", NULL, &w_message}, +// [FG] TODO due to its variable width and the trailing cursor, +// the w_chat widget *must* currently remain left-aligned +// {"chat", NULL, &w_chat}, + {"secret", NULL, &w_secret}, + {NULL}, + }, + boom_names[] = { + {"ammo", NULL, &w_ammo}, + {"armor", NULL, &w_armor}, + {"health", NULL, &w_health}, + {"keys", NULL, &w_keys}, + {"weapon", "weapons", &w_weapon}, + + {"monsec", "stats", &w_monsec}, + {"sttime", "time", &w_sttime}, + {"coord", "coords", &w_coord}, + {"fps", "rate", &w_fps}, + {NULL}, }; -static boolean HU_AddToWidgets (hu_textline_t *widget, int hud, align_t align, int x, int y) +static boolean HU_ReplaceInDoomWidgets (hu_multiline_t *multiline, int hud, align_t h_align, align_t v_align, int x, int y) { int i; @@ -1899,7 +1880,32 @@ static boolean HU_AddToWidgets (hu_textline_t *widget, int hud, align_t align, i for (i = 0; i < MAX_WIDGETS - 1; i++) { - if (widgets[hud][i].line == NULL) + if (doom_widgets[hud][i].multiline == multiline) + { + doom_widgets[hud][i].h_align = h_align; + doom_widgets[hud][i].v_align = v_align; + doom_widgets[hud][i].x = x; + doom_widgets[hud][i].y = y; + + return true; + } + } + + return false; +} + +static boolean HU_AddToBoomWidgets (hu_multiline_t *multiline, int hud, align_t h_align, align_t v_align, int x, int y) +{ + int i; + + if (hud < 0 || hud >= MAX_HUDS) + { + return false; + } + + for (i = 0; i < MAX_WIDGETS - 1; i++) + { + if (boom_widgets[hud][i].multiline == NULL) { break; } @@ -1910,26 +1916,41 @@ static boolean HU_AddToWidgets (hu_textline_t *widget, int hud, align_t align, i return false; } - widgets[hud][i].line = widget; - widgets[hud][i].align = align; - widgets[hud][i].x = x; - widgets[hud][i].y = y; + boom_widgets[hud][i].multiline = multiline; + boom_widgets[hud][i].h_align = h_align; + boom_widgets[hud][i].v_align = v_align; + boom_widgets[hud][i].x = x; + boom_widgets[hud][i].y = y; - widgets[hud][i + 1].line = NULL; + boom_widgets[hud][i + 1].multiline = NULL; return true; } -static hu_textline_t *HU_WidgetByName (const char *name) +static boolean HU_AddToWidgets (hu_multiline_t *multiline, const multiline_names_t *names, int hud, align_t h_align, align_t v_align, int x, int y) +{ + if (names == doom_names) + { + return HU_ReplaceInDoomWidgets(multiline, hud, h_align, v_align, x, y); + } + else if (names == boom_names) + { + return HU_AddToBoomWidgets(multiline, hud, h_align, v_align, x, y); + } + + return false; +} + +static hu_multiline_t *HU_MultilineByName (const char *name, const multiline_names_t *names) { int i; - for (i = 0; i < arrlen(w_names); i++) + for (i = 0; names[i].name; i++) { - if (strcasecmp(name, w_names[i].name) == 0 || - (w_names[i].altname && strcasecmp(name, w_names[i].altname) == 0)) + if (strcasecmp(name, names[i].name) == 0 || + (names[i].altname && strcasecmp(name, names[i].altname) == 0)) { - return w_names[i].line; + return names[i].multiline; } } @@ -1938,9 +1959,16 @@ static hu_textline_t *HU_WidgetByName (const char *name) static boolean HU_AddHUDCoords (char *name, int hud, int x, int y) { - hu_textline_t *widget = HU_WidgetByName(name); + const multiline_names_t *names = doom_names; + hu_multiline_t *multiline = HU_MultilineByName(name, names); - if (widget == NULL) + if (multiline == NULL) + { + names = boom_names; + multiline = HU_MultilineByName(name, names); + } + + if (multiline == NULL) { return false; } @@ -1960,41 +1988,48 @@ static boolean HU_AddHUDCoords (char *name, int hud, int x, int y) return false; } - return HU_AddToWidgets(widget, hud, align_direct, x, y); + return HU_AddToWidgets(multiline, names, hud, align_direct, align_direct, x, y); } static boolean HU_AddHUDAlignment (char *name, int hud, char *alignstr) { - hu_textline_t *widget = HU_WidgetByName(name); + const multiline_names_t *names = doom_names; + hu_multiline_t *multiline = HU_MultilineByName(name, names); - if (widget == NULL) + if (multiline == NULL) + { + names = boom_names; + multiline = HU_MultilineByName(name, names); + } + + if (multiline == NULL) { return false; } if (!strcasecmp(alignstr, "topleft") || !strcasecmp(alignstr, "upperleft")) { - return HU_AddToWidgets(widget, hud, align_topleft, 0, 0); + return HU_AddToWidgets(multiline, names, hud, align_left, align_top, 0, 0); } else if (!strcasecmp(alignstr, "topright") || !strcasecmp(alignstr, "upperright")) { - return HU_AddToWidgets(widget, hud, align_topright, 0, 0); + return HU_AddToWidgets(multiline, names, hud, align_right, align_top, 0, 0); } else if (!strcasecmp(alignstr, "topcenter") || !strcasecmp(alignstr, "uppercenter")) { - return HU_AddToWidgets(widget, hud, align_topcenter, 0, 0); + return HU_AddToWidgets(multiline, names, hud, align_center, align_top, 0, 0); } else if (!strcasecmp(alignstr, "bottomleft") || !strcasecmp(alignstr, "lowerleft")) { - return HU_AddToWidgets(widget, hud, align_bottomleft, 0, 0); + return HU_AddToWidgets(multiline, names, hud, align_left, align_bottom, 0, 0); } else if (!strcasecmp(alignstr, "bottomright") || !strcasecmp(alignstr, "lowerright")) { - return HU_AddToWidgets(widget, hud, align_bottomright, 0, 0); + return HU_AddToWidgets(multiline, names, hud, align_right, align_bottom, 0, 0); } else if (!strcasecmp(alignstr, "bottomcenter")|| !strcasecmp(alignstr, "lowercenter")) { - return HU_AddToWidgets(widget, hud, align_bottomcenter, 0, 0); + return HU_AddToWidgets(multiline, names, hud, align_center, align_bottom, 0, 0); } return false; @@ -2039,7 +2074,7 @@ static void HU_ParseHUD (void) U_Error(s, "HUD (%d) must be between 0 and %d", hud, MAX_HUDS - 1); } - memset(widgets[hud], 0, sizeof(widgets[hud])); + memset(boom_widgets[hud], 0, sizeof(boom_widgets[hud])); continue; } diff --git a/src/hu_stuff.h b/src/hu_stuff.h index bd3a0a11..cddbde34 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -1,5 +1,6 @@ // Copyright (C) 1999 by // id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman +// Copyright (C) 2023 Fabian Greffrath // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -47,7 +48,7 @@ extern patch_t **hu_font; // void HU_Init(void); void HU_Start(void); -void HU_disableAllWidgets (void); +void HU_disable_all_widgets (void); boolean HU_Responder(event_t* ev); diff --git a/src/m_menu.c b/src/m_menu.c index d5b38acd..f453f83e 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -236,7 +236,7 @@ extern int mapcolor_frnd; // friends colors // killough 8/8/98 extern int map_point_coordinates; // killough 10/98 extern char *chat_macros[]; // chat macros -extern const char *shiftxform; +extern const char shiftxform[]; extern int map_secret_after; //secrets do not appear til after bagged extern default_t defaults[]; @@ -5756,7 +5756,7 @@ boolean M_Responder (event_t* ev) { hud_displayed = 1; //jff 3/3/98 turn hud on hud_active = (hud_active + 1) % 3; // cycle hud_active - HU_disableAllWidgets(); + HU_disable_all_widgets(); } return true; } diff --git a/src/r_main.c b/src/r_main.c index 610a7692..2a7faa34 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -542,7 +542,7 @@ void R_ExecuteSetViewSize (void) } } - HU_disableAllWidgets(); + HU_disable_all_widgets(); // [crispy] forcefully initialize the status bar backing screen ST_refreshBackground(true);