jcs
/wallops
/amendments
/63
*: Add View menu with hide/show options, fix dropped update events
updateEvt puts the window in .message not .where, so found_focusable
was being null, resulting in no update function called. Defer
finding event_in/found_focusable until we know what type of message
it is.
jcs made amendment 63 2 months ago
--- chatter.c Wed Sep 4 14:18:22 2024
+++ chatter.c Thu Sep 5 10:12:05 2024
@@ -19,6 +19,7 @@
#include <string.h>
#include "chatter.h"
#include "irc.h"
+#include "settings.h"
#include "util.h"
#define NICK_LIST_WIDTH 75
@@ -28,6 +29,7 @@
static Handle scrp_rec_h = NULL;
static Pattern tab_bar_pattern;
+static Rect zerorect = { 0, 0, 0, 0 };
void chatter_layout(struct chatter *chatter, bool init, Rect *init_bounds);
void chatter_draw_tab_bar(struct chatter *chatter);
@@ -86,7 +88,7 @@ chatter_init(const char *server, const unsigned short
padding - (GetMBarHeight() * 2);
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;
@@ -128,16 +130,19 @@ chatter_init(const char *server, const unsigned short
focusable->resume = chatter_resume;
focusable_add(focusable);
chatter->focusable = focusable;
+
+ chatter_update_menu(focusable);
chatter_draw_tab_bar(chatter);
chatter_printf(chatter, NULL, NULL,
- "$B***$0 Welcome to %s",
- PROGRAM_NAME);
+ "$B***$0 Welcome to %s %s",
+ PROGRAM_NAME, get_version(false));
tab = SLIST_FIRST(&chatter->tabs_list);
tab->conn = irc_connect(chatter, server, port, password, nick, ident,
realname, hide_motd, channel);
+
DrawControls(chatter->win);
chatter_update_titlebar(chatter);
chatter_draw_tab_bar(chatter);
@@ -227,7 +232,6 @@ chatter_add_tab(struct chatter *chatter, Rect *win_bou
tab->channel = channel;
chatter_layout_tab(chatter, tab, win_bounds, true);
-
chatter_focus_tab(chatter, tab);
if (conn)
@@ -293,6 +297,7 @@ chatter_layout_tab(struct chatter *chatter, struct cha
bounds.bottom -= 1;
inset_bounds = bounds;
InsetRect(&inset_bounds, 4, 4);
+ EraseRect(&bounds);
if (init) {
tab->messages_te = TEStylNew(&inset_bounds, &bounds);
(*(tab->messages_te))->caretHook = NullCaretHook;
@@ -331,7 +336,7 @@ chatter_focus_tab(struct chatter *chatter, struct chat
r.right = (*(chatter->current_tab->messages_scroller))->contrlRect.right;
ClipRect(&r);
- FillRect(&r, white);
+ EraseRect(&r);
TEDeactivate(chatter->current_tab->messages_te);
if (chatter->current_tab->nick_list)
LDoDraw(false, chatter->current_tab->nick_list);
@@ -347,17 +352,18 @@ chatter_focus_tab(struct chatter *chatter, struct chat
chatter->current_tab = tab;
- FillRect(&(*(tab->messages_te))->viewRect, white);
+ EraseRect(&(*(tab->messages_te))->viewRect);
TEActivate(tab->messages_te);
TEUpdate(&(*(tab->messages_te))->viewRect, tab->messages_te);
ShowControl(tab->messages_scroller);
if (tab->nick_list) {
- FillRect(&(*(tab->nick_list))->rView, white);
+ EraseRect(&(*(tab->nick_list))->rView);
LDoDraw(true, tab->nick_list);
LUpdate(chatter->win->visRgn, tab->nick_list);
}
DrawControls(chatter->win);
+
chatter_draw_tab_bar(chatter);
}
@@ -507,6 +513,7 @@ chatter_update(struct focusable *focusable, EventRecor
TEUpdate(&(*(chatter->input_te))->viewRect, chatter->input_te);
DrawControls(chatter->win);
+
chatter_draw_tab_bar(chatter);
chatter_reveal_shadow(chatter);
break;
@@ -554,7 +561,6 @@ chatter_draw_tab_bar(struct chatter *chatter)
TextSize(9);
tab_offset = 5;
-
tab_width = (chatter->win->portRect.right -
chatter->win->portRect.left - tab_offset - tab_offset) /
chatter->ntabs;
@@ -587,11 +593,11 @@ chatter_draw_tab_bar(struct chatter *chatter)
SLIST_FOREACH(tab, &chatter->tabs_list, list) {
tab->label_rect = r;
- FillRect(&r, white);
+ EraseRect(&r);
FrameRect(&r);
if (tab == chatter->current_tab) {
FrameRect(&r2);
- FillRect(&r2, white);
+ EraseRect(&r2);
tab->have_activity = false;
}
@@ -678,7 +684,7 @@ chatter_draw_grow_icon(struct chatter *chatter)
r.left -= 2;
r.bottom -= 4;
r.right -= 4;
- FillRect(&r, white);
+ EraseRect(&r);
FrameRect(&r);
HUnlock(*(chatter->input_te));
@@ -779,6 +785,7 @@ void
chatter_resize(struct focusable *focusable, EventRecord *event)
{
struct chatter *chatter = (struct chatter *)(focusable->cookie);
+ struct chatter_tab *ttab;
RgnHandle savergn;
Rect bounds;
long newsize, width, height;
@@ -807,9 +814,10 @@ chatter_resize(struct focusable *focusable, EventRecor
ClipRect(&zerorect);
SLIST_FOREACH(ttab, &chatter->tabs_list, list) {
- if (tab == chatter->current_tab)
+ if (ttab == chatter->current_tab)
continue;
+ TEPinScroll(0, -INT_MAX, ttab->messages_te);
chatter_autoscroll(chatter, ttab->messages_te,
ttab->messages_scroller);
}
@@ -867,6 +875,8 @@ chatter_update_menu(struct focusable *focusable)
HLock(chatter->input_te);
HLock(tab->messages_te);
+ EnableItem(view_menu, VIEW_MENU_HIDE_ID);
+
EnableItem(edit_menu, EDIT_MENU_PASTE_ID);
if ((*(chatter->input_te))->selStart != (*(chatter->input_te))->selEnd) {
@@ -946,7 +956,6 @@ chatter_printf(struct chatter *chatter, struct irc_con
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;
@@ -1074,7 +1083,7 @@ te_overflow:
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, (*(tab->messages_te))->lineStarts[5], tab->messages_te);
TEDelete(tab->messages_te);
@@ -1096,7 +1105,7 @@ no_overflow:
/* create an empty clip region so all TE updates are hidden */
ClipRect(&zerorect);
}
-
+
TESetSelect(SHRT_MAX, SHRT_MAX, tab->messages_te);
TEStylInsert(buf_out, buf_out_len, scrp_rec_h, tab->messages_te);
HUnlock(scrp_rec_h);
--- chatter.h Tue Sep 3 16:17:49 2024
+++ chatter.h Thu Sep 5 09:19:25 2024
@@ -44,6 +44,9 @@
#define EDIT_MENU_COPY_ID 2
#define EDIT_MENU_PASTE_ID 3
+#define VIEW_MENU_ID 131
+#define VIEW_MENU_HIDE_ID 1
+
#define WAIT_TYPE_NONE (1 << 0)
#define WAIT_TYPE_BACKGROUND (1 << 1)
#define WAIT_TYPE_FOREGROUND (1 << 2)
@@ -75,7 +78,7 @@ struct chatter {
struct chatter_tab *current_tab;
};
-extern MenuHandle apple_menu, file_menu, edit_menu;
+extern MenuHandle apple_menu, file_menu, edit_menu, view_menu;
void notify(void);
void cancel_notification(void);
--- focusable.c Wed Aug 28 13:55:46 2024
+++ focusable.c Thu Sep 5 10:08:39 2024
@@ -85,12 +85,13 @@ focusable_show(struct focusable *focusable)
}
}
- if (!focusable->visible) {
+ if (focusable->visible)
+ SelectWindow(focusable->win);
+ else {
focusable->visible = true;
ShowWindow(focusable->win);
}
- SelectWindow(focusable->win);
SetPort(focusable->win);
return true;
--- main.c Tue Sep 3 14:56:14 2024
+++ main.c Thu Sep 5 10:08:25 2024
@@ -23,7 +23,7 @@
NMRec notification = { 0 };
struct settings settings;
-MenuHandle apple_menu, file_menu, edit_menu;
+MenuHandle apple_menu, file_menu, edit_menu, view_menu;
void update_menu(void);
void handle_exit(void);
@@ -69,6 +69,8 @@ main(void)
panic("no file menu");
if (!(edit_menu = GetMHandle(EDIT_MENU_ID)))
panic("no edit menu");
+ if (!(view_menu = GetMHandle(VIEW_MENU_ID)))
+ panic("no view menu");
update_menu();
DrawMenuBar();
@@ -92,11 +94,6 @@ main(void)
WaitNextEvent(everyEvent, &event, wait_ticks, 0L);
- if (event.what != nullEvent) {
- event_in = FindWindow(event.where, &event_win);
- found_focusable = focusable_find(event_win);
- }
-
switch (event.what) {
case nullEvent:
for (n = 0; n < nfocusables; n++) {
@@ -115,6 +112,9 @@ main(void)
focusables[0]->key_down(focusables[0], &event);
break;
case mouseDown:
+ event_in = FindWindow(event.where, &event_win);
+ found_focusable = focusable_find(event_win);
+
switch (event_in) {
case inMenuBar:
handle_menu(MenuSelect(event.where));
@@ -154,6 +154,7 @@ main(void)
case updateEvt:
case activateEvt:
event_win = (WindowPtr)event.message;
+ found_focusable = focusable_find(event_win);
GetPort(&old_port);
SetPort(event_win);
@@ -203,7 +204,10 @@ show_connect_dialog(void)
{
bool valid;
- if (!settings_edit(!settings_load()))
+ valid = settings_edit(!settings_load());
+ update_menu();
+
+ if (!valid)
return;
chatter_init(settings.server, settings.port, settings.password,
@@ -252,6 +256,37 @@ handle_menu(long menu_id)
break;
}
break;
+ case VIEW_MENU_ID:
+ switch (LoWord(menu_id)) {
+ case VIEW_MENU_HIDE_ID: {
+ Str255 text;
+ struct focusable **tfocusables = NULL;
+
+ /* hiding and showing adjusts order, so duplicate order */
+ tfocusables = xmalloc(sizeof(struct focusable *) * nfocusables);
+ memcpy(tfocusables, focusables, sizeof(struct focusable *) *
+ nfocusables);
+
+ GetItem(view_menu, VIEW_MENU_HIDE_ID, &text);
+ if (memcmp((char *)text + 1, "Hide", 4) == 0) {
+ for (n = 0; n < nfocusables; n++) {
+ if (tfocusables[n]->visible)
+ focusable_hide(tfocusables[n]);
+ }
+ } else {
+ for (n = 0; n < nfocusables; n++) {
+ if (!tfocusables[n]->visible)
+ focusable_show(tfocusables[n]);
+ }
+ }
+
+ xfree(&tfocusables);
+ update_menu();
+ ret = true;
+ break;
+ }
+ }
+ break;
default:
if (nfocusables && focusables[0]->visible && focusables[0]->menu)
ret = focusables[0]->menu(focusables[0], HiWord(menu_id),
@@ -265,17 +300,30 @@ handle_menu(long menu_id)
void
update_menu(void)
{
- if (nfocusables) {
- if (focusables[0]->visible) {
- EnableItem(edit_menu, 0);
- if (focusables[0]->update_menu)
- focusables[0]->update_menu(focusables[0]);
- } else {
- DisableItem(edit_menu, 0);
+ short n;
+ bool hidden = false;
+
+ for (n = 0; n < nfocusables; n++) {
+ if (!focusables[n]->visible) {
+ hidden = true;
+ break;
}
- } else {
- DisableItem(edit_menu, 0);
}
+
+ if (hidden)
+ SetItem(view_menu, VIEW_MENU_HIDE_ID, "\pShow Windows");
+ else
+ SetItem(view_menu, VIEW_MENU_HIDE_ID, "\pHide Windows");
+
+ if (nfocusables && focusables[0]->visible &&
+ focusables[0]->update_menu) {
+ focusables[0]->update_menu(focusables[0]);
+ return;
+ }
+
+ DisableItem(edit_menu, EDIT_MENU_CUT_ID);
+ DisableItem(edit_menu, EDIT_MENU_COPY_ID);
+ DisableItem(edit_menu, EDIT_MENU_PASTE_ID);
}
void
@@ -309,4 +357,4 @@ cancel_notification(void)
if (notification.qType)
NMRemove(¬ification);
memset(¬ification, 0, sizeof(notification));
-}
\ No newline at end of file
+}