jcs
/wallops
/amendments
/47
*: Smoother screen/tab updates, fix close/quit/dealloc sequences
jcs made amendment 47 over 2 years ago
--- chatter.c	Tue Jan 10 15:22:50 2023
+++ chatter.c	Tue Jan 17 23:14:56 2023
@@ -24,6 +24,7 @@
 #define NICK_LIST_WIDTH			75
 #define CHATTER_SCRAP_ELEMENTS	20
 #define MAX_TAB_WIDTH			100
+#define TAB_BAR_HEIGHT			15
 
 static Handle scrp_rec_h = NULL;
 static Pattern tab_bar_pattern;
@@ -101,6 +102,8 @@ chatter_init(const char *server, const unsigned short 
 	focusable->resume = chatter_resume;
 	focusable_add(focusable);
 	chatter->focusable = focusable;
+
+	chatter_draw_tab_bar(chatter);
 	
 	chatter_printf(chatter, NULL, NULL,
 	  "$B***$0 Welcome to %s",
@@ -109,10 +112,10 @@ chatter_init(const char *server, const unsigned short 
 	tab = SLIST_FIRST(&chatter->tabs_list);
 	tab->conn = irc_connect(chatter, server, port, password, nick, ident,
 	  realname, channel);
-	InvalRect(&bounds);
 	DrawControls(chatter->win);
-	chatter_draw_tab_bar(chatter);
 	chatter_update_titlebar(chatter);
+	
+	ValidRect(&bounds);
 
 	return chatter;
 }
@@ -237,14 +240,33 @@ chatter_add_tab(struct chatter *chatter, Rect *win_bou
 void
 chatter_focus_tab(struct chatter *chatter, struct chatter_tab *tab)
 {
+	RgnHandle clip;
+	Rect zerorect = { 0, 0, 0, 0 }, r;
+
 	if (chatter->current_tab) {
 		if (chatter->current_tab == tab)
 			return;
 		
+		/*
+		 * Doing the HideControl takes out the top line of our tab bar,
+		 * so clip to just above it
+		 */
+		GetClip(clip = NewRgn());
+		r.left = 0;
+		r.top = 0;
+		r.right =
+		  (*(chatter->current_tab->messages_scroller))->contrlRect.right;
+		r.bottom =
+		   (*(chatter->current_tab->messages_scroller))->contrlRect.bottom
+		   - 1;
+		ClipRect(&r);
+		
 		TEDeactivate(chatter->current_tab->messages_te);
 		if (chatter->current_tab->nick_list)
 			LDoDraw(false, chatter->current_tab->nick_list);
 		HideControl(chatter->current_tab->messages_scroller);
+		
+		SetClip(clip);
 	}
 	
 	chatter->current_tab = tab;
@@ -277,14 +299,9 @@ chatter_close(struct focusable *focusable)
 {
 	struct chatter *chatter = (struct chatter *)(focusable->cookie);
 	struct chatter_tab *tab;
-	struct irc_connection *conn;
+	struct irc_connection *conn, *tconn;
 	bool connected = false;
 	
-	if (chatter->quitting) {
-		DisposeWindow(focusable->win);
-		return true;
-	}
-	
 	SLIST_FOREACH(tab, &chatter->tabs_list, list) {
 		if (tab->conn->state == IRC_STATE_CONNECTED) {
 			connected = true;
@@ -292,13 +309,24 @@ chatter_close(struct focusable *focusable)
 		}
 	}
 	
-	if (connected) {
+	if (connected && !chatter->quitting) {
 		focusable_hide(focusable);
 		return false;
 	}
+
+	SLIST_FOREACH_SAFE(conn, &irc_connections_list, list, tconn) {
+		if (conn->chatter == chatter) {
+			irc_close_connection(conn);
+			/* this will kill any channels as well */
+			irc_dealloc_connection(conn);
+		}
+	}
 	
-	/* TODO: maybe ask the user whether they want to hide or close? */
-	chatter_quit(focusable);
+	if (chatter->tab_port.baseAddr)
+		xfree(&chatter->tab_port.baseAddr);
+	
+	DisposeWindow(focusable->win);
+	
 	return true;
 }
 
@@ -306,16 +334,10 @@ bool
 chatter_quit(struct focusable *focusable)
 {
 	struct chatter *chatter = (struct chatter *)(focusable->cookie);
-	struct chatter_tab *tab;
-	short n;
 	
-	SLIST_FOREACH(tab, &chatter->tabs_list, list) {
-		/* TODO: quit with a proper quit message */
-		irc_close_connection(tab->conn);
-	}
-	
 	chatter->quitting = true;
 	focusable_close(focusable);
+	
 	return true;
 }
 
@@ -422,12 +444,25 @@ chatter_draw_tab_bar(struct chatter *chatter)
 {
 	Rect r, r2;
 	RgnHandle clip;
+	BitMap cur_bits;
 	short tab_width, tab_offset, n, width;
 	size_t len;
 	static const char no_connection[] = "Disconnected";
 	struct chatter_tab *tab;
 	char *label;
+
+	cur_bits = chatter->win->portBits;
 	
+	if (chatter->tab_port.baseAddr == 0) {
+		width = chatter->win->portRect.right - chatter->win->portRect.left;
+		chatter->tab_port.rowBytes = (((width - 1) / 16) + 1) * 2;
+		chatter->tab_port.baseAddr = xmalloczero(
+		  chatter->tab_port.rowBytes * TAB_BAR_HEIGHT, "tab_port");
+		SetRect(&chatter->tab_port.bounds, 0, 0, width, TAB_BAR_HEIGHT);
+	}
+	
+	SetPortBits(&chatter->tab_port);
+	
 	TextFont(geneva);
 	TextSize(9);
 	
@@ -439,15 +474,20 @@ chatter_draw_tab_bar(struct chatter *chatter)
 	if (tab_width > MAX_TAB_WIDTH)
 		tab_width = MAX_TAB_WIDTH;
 	
-	r = (*(chatter->input_te))->viewRect;
-	r.bottom = r.top - 1;
-	r.right = chatter->win->portRect.right;
-	r.top -= 14;
+	r.top = 0;
+	r.bottom = TAB_BAR_HEIGHT;
+	r.left = 0;
+	r.right = chatter->win->portRect.right - chatter->win->portRect.left;
 	FillRect(&r, tab_bar_pattern);
+	
+	r.left--;
+	r.right++;
+	FrameRect(&r);
+	r.left++;
+	r.right--;
 
-	r.left = chatter->win->portRect.left + tab_offset;
-	r.top -= 1;
-	r.bottom -= 1;
+	r.left = tab_offset;
+	r.bottom -= 2;
 	r.right = r.left + tab_width;
 	
 	r2.left = r.left + 1;
@@ -503,6 +543,20 @@ chatter_draw_tab_bar(struct chatter *chatter)
 	TextSize(10);
 	TextFace(0);
 
+	SetPortBits(&cur_bits);
+
+	r = chatter->tab_port.bounds;
+	r.bottom = (*(chatter->input_te))->viewRect.top;
+	r.top += r.bottom - TAB_BAR_HEIGHT;
+	
+	SLIST_FOREACH(tab, &chatter->tabs_list, list) {
+		tab->label_rect.top += r.top;
+		tab->label_rect.bottom += r.top;
+	}
+	
+	CopyBits(&chatter->tab_port, &chatter->win->portBits,
+	  &chatter->tab_port.bounds, &r, srcCopy, nil);
+	
 	chatter_draw_grow_icon(chatter);
 }
 
@@ -650,6 +704,11 @@ chatter_resize(struct focusable *focusable, EventRecor
 	width = LoWord(newsize);
 	SizeWindow(focusable->win, width, height, true);
 	EraseRect(&chatter->win->portRect);
+	
+	/* chatter_draw_tab_bar will recreate this to the new size */
+	if (chatter->tab_port.baseAddr)
+		xfree(&chatter->tab_port.baseAddr);
+		
 	chatter_layout(chatter, false, NULL);
 }
 
--- chatter.h	Tue Jan 10 10:22:54 2023
+++ chatter.h	Mon Jan 16 14:41:22 2023
@@ -90,6 +90,7 @@ struct chatter {
 	WindowPtr win;
 	TEHandle input_te;
 	bool quitting;
+	BitMap tab_port;
 	short ntabs;
 	struct chatter_tabs_head tabs_list;
 	struct chatter_tab *current_tab;
--- irc.c	Tue Jan 10 10:15:56 2023
+++ irc.c	Tue Jan 17 14:23:25 2023
@@ -995,7 +995,6 @@ irc_dealloc_channel(struct irc_channel *channel)
 	struct irc_connection *conn = channel->connection;
 	struct irc_channel *tchannel;
 	struct chatter *chatter = channel->chatter;
-	short n;
 
 	chatter_remove_channel(chatter, channel);
 	
--- main.c	Mon Jan  9 16:42:00 2023
+++ main.c	Tue Jan 17 13:48:47 2023
@@ -168,9 +168,8 @@ main(void)
 					found_focusable->resize(found_focusable, &event);
 				break;
 			case inGoAway:
-				if (TrackGoAway(event_win, event.where) &&
-				  found_focusable && found_focusable->close)
-					found_focusable->close(found_focusable);
+				if (TrackGoAway(event_win, event.where) && found_focusable)
+					focusable_close(found_focusable);
 				break;
 			case inContent:
 				if (event_win != FrontWindow()) {