AmendHub

Download:

jcs

/

wallops

/

amendments

/

59

chatter: Use a shadow buffer for window redrawing


jcs made amendment 59 3 months ago
--- chatter.c Sat Aug 31 20:05:57 2024 +++ chatter.c Wed Sep 4 14:18:22 2024 @@ -52,6 +52,9 @@ struct chatter_tab * chatter_find_tab_for_conn_and_cha struct chatter *chatter, struct irc_connection *conn, struct irc_channel *channel); +void chatter_use_shadow(struct chatter *chatter); +void chatter_reveal_shadow(struct chatter *chatter); + struct chatter * chatter_init(const char *server, const unsigned short port, const char *password, const char *nick, const char *ident, @@ -84,6 +87,17 @@ chatter_init(const char *server, const unsigned short height = MIN(height, 350); center_in_screen(width, height, true, &bounds); + width = screenBits.bounds.right - screenBits.bounds.left; + height = screenBits.bounds.bottom - screenBits.bounds.top; + chatter->shadow.rowBytes = (((width - 1) / 16) + 1) * 2; + chatter->shadow.baseAddr = xmalloczero(chatter->shadow.rowBytes * + height); + if (chatter->shadow.baseAddr == NULL) { + xfree(&chatter); + xfree(&focusable); + return NULL; + } + snprintf(title, sizeof(title), "%s: Disconnected", PROGRAM_NAME); chatter->win = NewWindow(0L, &bounds, CtoPstr(title), false, documentProc, (WindowPtr)-1L, true, 0); @@ -160,7 +174,7 @@ chatter_layout(struct chatter *chatter, bool init, Rec if (win_bounds == NULL) win_bounds = &chatter->win->portRect; - + /* input */ bounds.left = win_bounds->left; bounds.right = win_bounds->right - SCROLLBAR_WIDTH + 1; @@ -200,6 +214,9 @@ chatter_add_tab(struct chatter *chatter, Rect *win_bou Point cell_size = { 0 }; Cell cell = { 0, 0 }; + if (conn) + chatter_use_shadow(chatter); + if (win_bounds == NULL) win_bounds = &chatter->win->portRect; @@ -212,6 +229,9 @@ chatter_add_tab(struct chatter *chatter, Rect *win_bou chatter_layout_tab(chatter, tab, win_bounds, true); chatter_focus_tab(chatter, tab); + + if (conn) + chatter_reveal_shadow(chatter); return tab; } @@ -380,6 +400,8 @@ chatter_close(struct focusable *focusable) if (chatter->tab_bar.baseAddr) xfree(&chatter->tab_bar.baseAddr); + if (chatter->shadow.baseAddr) + xfree(&chatter->shadow.baseAddr); DisposeWindow(focusable->win); @@ -451,18 +473,17 @@ chatter_update(struct focusable *focusable, EventRecor { struct chatter *chatter = (struct chatter *)(focusable->cookie); struct chatter_tab *tab = chatter->current_tab; - GrafPtr old_port; Rect r; short what = -1; - GetPort(&old_port); - if (event != NULL) what = event->what; switch (what) { case -1: case updateEvt: + chatter_use_shadow(chatter); + TextFont(applFont); TextSize(10); @@ -487,6 +508,7 @@ chatter_update(struct focusable *focusable, EventRecor DrawControls(chatter->win); chatter_draw_tab_bar(chatter); + chatter_reveal_shadow(chatter); break; case activateEvt: if (event->modifiers & activeFlag) { @@ -516,7 +538,7 @@ chatter_draw_tab_bar(struct chatter *chatter) struct chatter_tab *tab; char *label; - cur_bits = chatter->win->portBits; + cur_bits = thePort->portBits; if (chatter->tab_bar.baseAddr == 0) { width = chatter->win->portRect.right - chatter->win->portRect.left; @@ -527,7 +549,7 @@ chatter_draw_tab_bar(struct chatter *chatter) } SetPortBits(&chatter->tab_bar); - + TextFont(geneva); TextSize(9); @@ -619,7 +641,7 @@ chatter_draw_tab_bar(struct chatter *chatter) tab->label_rect.bottom += r.top; } - CopyBits(&chatter->tab_bar, &chatter->win->portBits, + CopyBits(&chatter->tab_bar, &thePort->portBits, &chatter->tab_bar.bounds, &r, srcCopy, nil); chatter_draw_grow_icon(chatter); @@ -720,7 +742,9 @@ chatter_mouse_down(struct focusable *focusable, EventR SLIST_FOREACH(ttab, &chatter->tabs_list, list) { if (PtInRect(p, &ttab->label_rect)) { + chatter_use_shadow(chatter); chatter_focus_tab(chatter, ttab); + chatter_reveal_shadow(chatter); return; } } @@ -755,6 +779,7 @@ void chatter_resize(struct focusable *focusable, EventRecord *event) { struct chatter *chatter = (struct chatter *)(focusable->cookie); + RgnHandle savergn; Rect bounds; long newsize, width, height; @@ -767,16 +792,36 @@ chatter_resize(struct focusable *focusable, EventRecor height = HiWord(newsize); width = LoWord(newsize); + InvalRect(&chatter->win->portRect); SizeWindow(focusable->win, width, height, true); EraseRect(&chatter->win->portRect); - InvalRect(&chatter->win->portRect); /* chatter_draw_tab_bar will recreate this to the new size */ if (chatter->tab_bar.baseAddr) xfree(&chatter->tab_bar.baseAddr); - + + /* update each tab that isn't the current one */ + savergn = NewRgn(); + GetClip(savergn); + /* create an empty clip region so all TE updates are hidden */ + ClipRect(&zerorect); + + SLIST_FOREACH(ttab, &chatter->tabs_list, list) { + if (tab == chatter->current_tab) + continue; + + chatter_autoscroll(chatter, ttab->messages_te, + ttab->messages_scroller); + } + + /* resume normal drawing */ + SetClip(savergn); + DisposeRgn(savergn); + + /* update the current tab as-is */ chatter_layout(chatter, false, NULL); chatter_update(focusable, NULL); + ValidRect(&chatter->win->portRect); } @@ -805,7 +850,7 @@ chatter_menu(struct focusable *focusable, short menu, HUnlock(chatter->input_te); return true; case EDIT_MENU_PASTE_ID: - TEPaste(chatter->input_te); + TEPaste(chatter->input_te); return true; } } @@ -1088,9 +1133,7 @@ void chatter_remove_channel(struct chatter *chatter, struct irc_channel *channel) { - RgnHandle clip; struct chatter_tab *tab = NULL, *ttab = NULL, *next_tab = NULL; - Rect r; short n; SLIST_FOREACH(ttab, &chatter->tabs_list, list) { @@ -1102,28 +1145,14 @@ chatter_remove_channel(struct chatter *chatter, } } + chatter_use_shadow(chatter); + if (tab != NULL) { - GetClip(clip = NewRgn()); - - r.left = 0; - r.top = 0; - r.bottom = (*(tab->messages_scroller))->contrlRect.bottom - 1; - if (tab->nick_list) - r.right = (*(tab->nick_list))->rView.right; - else - r.right = (*(tab->messages_scroller))->contrlRect.right; - - ClipRect(&r); - - FillRect(&r, white); LDispose(tab->nick_list); DisposeControl(tab->messages_scroller); TEDispose(tab->messages_te); SLIST_REMOVE(&chatter->tabs_list, tab, chatter_tab, list); - SetClip(clip); - DisposeRgn(clip); - if (chatter->current_tab == tab) chatter->current_tab = NULL; } @@ -1137,6 +1166,8 @@ chatter_remove_channel(struct chatter *chatter, * Don't bother updating titlebar because we should be inside * irc_dealloc_channel which will then call chatter_update_titlebar */ + + chatter_reveal_shadow(chatter); } void @@ -1238,4 +1269,27 @@ chatter_remove_from_nick_list(struct chatter *chatter, } LDelRow(1, pos, tab->nick_list); -} \ No newline at end of file +} + +static BitMap shadow_cur_bits; + +void +chatter_use_shadow(struct chatter *chatter) +{ + shadow_cur_bits = thePort->portBits; + + SetRect(&chatter->shadow.bounds, 0, 0, + chatter->win->portRect.right - chatter->win->portRect.left, + chatter->win->portRect.bottom - chatter->win->portRect.top); + SetPortBits(&chatter->shadow); +} + +void +chatter_reveal_shadow(struct chatter *chatter) +{ + SetPortBits(&shadow_cur_bits); + + CopyBits(&chatter->shadow, &chatter->win->portBits, + &chatter->shadow.bounds, &chatter->shadow.bounds, srcCopy, nil); + ValidRect(&chatter->win->portRect); +} --- chatter.h Fri Aug 30 21:58:59 2024 +++ chatter.h Tue Sep 3 16:17:49 2024 @@ -65,6 +65,8 @@ SLIST_HEAD(chatter_tabs_head, chatter_tab); struct chatter { struct focusable *focusable; WindowPtr win; + BitMap shadow; + Rect shadow_bounds; TEHandle input_te; bool quitting; BitMap tab_bar;