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;