jcs
/wallops
/amendments
/19
chatter: Check for TE overflow, shift out old lines
We can overflow in a few different ways, so check for all of them.
If we're about to overflow, shift out a handful of old lines before
adding new ones, but do it with a blank clipping rect so we don't get
a flashing update.
jcs made amendment 19 over 2 years ago
--- chatter.c Tue Feb 8 12:30:37 2022
+++ chatter.c Tue Feb 8 14:56:52 2022
@@ -21,8 +21,11 @@
#include "irc.h"
#include "util.h"
-#define NICK_LIST_WIDTH 75
+#define NICK_LIST_WIDTH 75
+#define CHATTER_SCRAP_ELEMENTS 20
+static Handle scrp_rec_h = NULL;
+
void chatter_layout(struct chatter *chatter, bool init, Rect *init_bounds);
void chatter_key_down(struct focusable *focusable, EventRecord *event);
void chatter_mouse_down(struct focusable *focusable, EventRecord *event);
@@ -94,7 +97,6 @@ chatter_init(const char *server, const unsigned short
focusable->menu = chatter_menu;
focusable->resume = chatter_resume;
add_focusable(focusable);
-
chatter->focusable = focusable;
}
@@ -475,18 +477,18 @@ chatter_key_down(struct focusable *focusable, EventRec
}
}
-static Handle scrp_rec_h = NULL;
-#define CHATTER_SCRAP_ELEMENTS 20
-
size_t
chatter_printf(struct chatter *chatter, const char *format, ...)
{
static char buf[600], buf_out[600];
StScrpRec *scrp_rec;
ScrpSTElement *scrp_ele, *prev_scrp_ele;
+ RgnHandle savergn;
+ Rect zerorect = { 0, 0, 0, 0 };
va_list argptr;
size_t len, n, buf_out_len, in_this_style;
time_t now = Time;
+ short line_height = 0;
bool stop_formatting = false;
len = 0;
@@ -509,12 +511,14 @@ chatter_printf(struct chatter *chatter, const char *fo
memset(*scrp_rec_h, 0, (4 + (20 * CHATTER_SCRAP_ELEMENTS)));
} else
HLock(scrp_rec_h);
-
+
+ line_height = CHATTER_FONT_SIZE + 3;
+
scrp_rec = (StScrpRec *)(*scrp_rec_h);
scrp_rec->scrpNStyles = 1;
scrp_ele = &scrp_rec->scrpStyleTab[scrp_rec->scrpNStyles - 1];
scrp_ele->scrpStartChar = 0;
- scrp_ele->scrpHeight = CHATTER_FONT_SIZE + 3;
+ scrp_ele->scrpHeight = line_height;
scrp_ele->scrpAscent = CHATTER_FONT_SIZE;
scrp_ele->scrpFont = CHATTER_FONT;
scrp_ele->scrpSize = CHATTER_FONT_SIZE;
@@ -551,7 +555,7 @@ chatter_printf(struct chatter *chatter, const char *fo
stop_formatting = true;
/* FALLTHROUGH */
case '0':
- scrp_ele->scrpHeight = CHATTER_FONT_SIZE + 3;
+ scrp_ele->scrpHeight = line_height;
scrp_ele->scrpAscent = CHATTER_FONT_SIZE;
scrp_ele->scrpFont = CHATTER_FONT;
scrp_ele->scrpSize = CHATTER_FONT_SIZE;
@@ -570,14 +574,57 @@ chatter_printf(struct chatter *chatter, const char *fo
return 0;
}
- TESetSelect(1024 * 32, 1024 * 32, chatter->messages_te);
+ HLock(chatter->messages_te);
+
+ /* check for TE overflow */
+
+ /* too many lines */
+ if ((*(chatter->messages_te))->nLines >=
+ (nitems((*(chatter->messages_te))->lineStarts) - 10))
+ goto te_overflow;
+
+ /* too many characters */
+ if ((*(chatter->messages_te))->teLength >= (SHRT_MAX - 500))
+ goto te_overflow;
+
+ /* rect of all lines is too tall */
+ if ((*(chatter->messages_te))->nLines * line_height >= (SHRT_MAX - 100))
+ goto te_overflow;
+
+ goto no_overflow;
+
+te_overflow:
+ savergn = NewRgn();
+ GetClip(savergn);
+ /* create an empty clip region so all TE updates are hidden */
+ ClipRect(&zerorect);
+
+ /* select some lines at the start, delete them */
+ TESetSelect(0, (*(chatter->messages_te))->lineStarts[5],
+ chatter->messages_te);
+ TEDelete(chatter->messages_te);
+
+ /* scroll up, causing a repaint */
+ TEPinScroll(0, INT_MAX, chatter->messages_te);
+
+ /* then scroll back down to what it looked like before we did anything */
+ TEPinScroll(0, -INT_MAX, chatter->messages_te);
+
+ /* resume normal drawing */
+ SetClip(savergn);
+ DisposeRgn(savergn);
+
+no_overflow:
+ TESetSelect(SHRT_MAX, SHRT_MAX, chatter->messages_te);
TEStylInsert(buf_out, buf_out_len, scrp_rec_h, chatter->messages_te);
HUnlock(scrp_rec_h);
+
TEPinScroll(0, -INT_MAX, chatter->messages_te);
SetCtlValue(chatter->messages_scroller,
GetCtlMax(chatter->messages_scroller));
UpdateScrollbarForTE(chatter->messages_scroller,
chatter->messages_te, false);
+ HUnlock(chatter->messages_te);
return buf_out_len;
}