+typedef struct
+{
+ dp_font_t *font;
+ float alignment; // 0 = left, 0.5 = center, 1 = right
+ float fontsize;
+ float x;
+ float y;
+ float width;
+ float ymin, ymax;
+ const char *continuationString;
+
+ // PRIVATE:
+ int colorindex; // init to -1
+}
+con_text_info_t;
+
+float Con_WordWidthFunc(void *passthrough, const char *w, size_t *length, float maxWidth)
+{
+ con_text_info_t *ti = (con_text_info_t *) passthrough;
+ if(w == NULL)
+ {
+ ti->colorindex = -1;
+ return ti->fontsize * ti->font->maxwidth;
+ }
+ if(maxWidth >= 0)
+ return DrawQ_TextWidth_Font_UntilWidth(w, length, false, ti->font, maxWidth / ti->fontsize) * ti->fontsize;
+ else if(maxWidth == -1)
+ return DrawQ_TextWidth_Font(w, *length, false, ti->font) * ti->fontsize;
+ else
+ {
+ printf("Con_WordWidthFunc: can't get here (maxWidth should never be %f)\n", maxWidth);
+ // Note: this is NOT a Con_Printf, as it could print recursively
+ return 0;
+ }
+}
+
+int Con_CountLineFunc(void *passthrough, const char *line, size_t length, float width, qboolean isContinuation)
+{
+ (void) passthrough;
+ (void) line;
+ (void) length;
+ (void) width;
+ (void) isContinuation;
+ return 1;
+}
+
+int Con_DisplayLineFunc(void *passthrough, const char *line, size_t length, float width, qboolean isContinuation)
+{
+ con_text_info_t *ti = (con_text_info_t *) passthrough;
+
+ if(ti->y < ti->ymin - 0.001)
+ (void) 0;
+ else if(ti->y > ti->ymax - ti->fontsize + 0.001)
+ (void) 0;
+ else
+ {
+ int x = ti->x + (ti->width - width) * ti->alignment;
+ if(isContinuation && *ti->continuationString)
+ x += DrawQ_String_Font(x, ti->y, ti->continuationString, strlen(ti->continuationString), ti->fontsize, ti->fontsize, 1.0, 1.0, 1.0, 1.0, 0, NULL, false, ti->font);
+ if(length > 0)
+ DrawQ_String_Font(x, ti->y, line, length, ti->fontsize, ti->fontsize, 1.0, 1.0, 1.0, 1.0, 0, &(ti->colorindex), false, ti->font);
+ }
+
+ ti->y += ti->fontsize;
+ return 1;
+}
+
+
+int Con_DrawNotifyRect(int mask_must, int mask_mustnot, float maxage, float x, float y, float width, float height, float fontsize, float alignment_x, float alignment_y, const char *continuationString)
+{
+ int i;
+ int lines = 0;
+ int maxlines = (int) floor(height / fontsize + 0.01f);
+ int startidx;
+ int nskip = 0;
+ int continuationWidth = 0;
+ size_t l;
+ double t = cl.time; // saved so it won't change
+ con_text_info_t ti;
+
+ ti.font = (mask_must & CON_MASK_CHAT) ? FONT_CHAT : FONT_NOTIFY;
+ ti.fontsize = fontsize;
+ ti.alignment = alignment_x;
+ ti.width = width;
+ ti.ymin = y;
+ ti.ymax = y + height;
+ ti.continuationString = continuationString;
+
+ l = 0;
+ Con_WordWidthFunc(&ti, NULL, &l, -1);
+ l = strlen(continuationString);
+ continuationWidth = Con_WordWidthFunc(&ti, continuationString, &l, -1);
+
+ // first find the first line to draw by backwards iterating and word wrapping to find their length...
+ startidx = con_lines_count;
+ for(i = con_lines_count - 1; i >= 0; --i)
+ {
+ con_lineinfo *l = &CON_LINES(i);
+ int mylines;
+
+ if((l->mask & mask_must) != mask_must)
+ continue;
+ if(l->mask & mask_mustnot)
+ continue;
+ if(maxage && (l->addtime < t - maxage))
+ continue;
+
+ // WE FOUND ONE!
+ // Calculate its actual height...
+ mylines = COM_Wordwrap(l->start, l->len, continuationWidth, width, Con_WordWidthFunc, &ti, Con_CountLineFunc, &ti);
+ if(lines + mylines >= maxlines)
+ {
+ nskip = lines + mylines - maxlines;
+ lines = maxlines;
+ startidx = i;
+ break;
+ }
+ lines += mylines;
+ startidx = i;
+ }
+
+ // then center according to the calculated amount of lines...
+ ti.x = x;
+ ti.y = y + alignment_y * (height - lines * fontsize) - nskip * fontsize;
+
+ // then actually draw
+ for(i = startidx; i < con_lines_count; ++i)
+ {
+ con_lineinfo *l = &CON_LINES(i);
+
+ if((l->mask & mask_must) != mask_must)
+ continue;
+ if(l->mask & mask_mustnot)
+ continue;
+ if(maxage && (l->addtime < t - maxage))
+ continue;
+
+ COM_Wordwrap(l->start, l->len, continuationWidth, width, Con_WordWidthFunc, &ti, Con_DisplayLineFunc, &ti);
+ }
+
+ return lines;
+}