AmendHub

Download:

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; }