jcs
/wikipedia
/amendments
/12
browser: Add stylized text viewing
jcs made amendment 12 over 2 years ago
--- browser.c Thu Aug 18 22:03:09 2022
+++ browser.c Wed Aug 24 20:50:52 2022
@@ -21,6 +21,7 @@
#include "wikipedia.h"
#include "browser.h"
#include "focusable.h"
+#include "http.h"
#include "util.h"
#define PADDING 10
@@ -33,13 +34,21 @@ void browser_key_down(struct focusable *focusable, Eve
void browser_mouse_down(struct focusable *focusable, EventRecord *event);
bool browser_handle_menu(struct focusable *focusable, short menu,
short item);
+void browser_atexit(struct focusable *focusable);
Pattern fill_pattern;
void
browser_idle(struct focusable *focusable, EventRecord *event)
-{
+{
struct browser *browser = (struct browser *)focusable->cookie;
+ size_t len;
+
+ TEIdle(browser->input_te);
+
+ if (browser->wpr)
+ wikipedia_request_process(browser->wpr);
+
#if 0
switch (browser->state) {
case BROWSER_STATE_IDLE:
@@ -122,12 +131,24 @@ browser_init(void)
bounds.top = PADDING;
bounds.left = PADDING;
+ bounds.right = browser->win->portRect.right - PADDING;
+ bounds.bottom = bounds.top + 18;
+ te_bounds = bounds;
+ InsetRect(&te_bounds, 2, 2);
+ TextFont(geneva);
+ TextSize(10);
+ browser->input_te = TENew(&te_bounds, &bounds);
+ TEAutoView(true, browser->input_te);
+ TEActivate(browser->input_te);
+
+ bounds.top = bounds.bottom + PADDING;
+ bounds.left = PADDING;
bounds.right = browser->win->portRect.right - SCROLLBAR_WIDTH - PADDING;
bounds.bottom = browser->win->portRect.bottom - PADDING;
te_bounds = bounds;
InsetRect(&te_bounds, 2, 2);
browser->te = TEStylNew(&te_bounds, &bounds);
- TEAutoView(true, browser->te);
+ TEAutoView(false, browser->te);
(*(browser->te))->caretHook = NullCaretHook;
TEActivate(browser->te);
@@ -148,10 +169,12 @@ browser_init(void)
focusable->idle = browser_idle;
focusable->update = browser_update;
focusable->mouse_down = browser_mouse_down;
+ focusable->key_down = browser_key_down;
focusable->menu = browser_handle_menu;
focusable->close = browser_close;
+ focusable->atexit = browser_atexit;
focusable_add(focusable);
-
+
return browser;
}
@@ -160,6 +183,11 @@ browser_close(struct focusable *focusable)
{
struct browser *browser = (struct browser *)focusable->cookie;
+ if (browser->wpr) {
+ wikipedia_request_abort(browser->wpr);
+ browser->wpr = NULL;
+ }
+
TEDispose(browser->te);
DisposeWindow(browser->win);
@@ -169,6 +197,17 @@ browser_close(struct focusable *focusable)
}
void
+browser_atexit(struct focusable *focusable)
+{
+ struct browser *browser = (struct browser *)focusable->cookie;
+
+ if (browser->wpr) {
+ wikipedia_request_abort(browser->wpr);
+ browser->wpr = NULL;
+ }
+}
+
+void
browser_update_menu(struct browser *browser)
{
size_t vlines;
@@ -211,6 +250,12 @@ browser_update(struct focusable *focusable, EventRecor
case updateEvt:
FillRect(&browser->win->portRect, fill_pattern);
+ r = (*(browser->input_te))->viewRect;
+ FillRect(&r, white);
+ TEUpdate(&r, browser->input_te);
+ InsetRect(&r, -1, -1);
+ FrameRect(&r);
+
r = (*(browser->te))->viewRect;
FillRect(&r, white);
TEUpdate(&r, browser->te);
@@ -239,7 +284,13 @@ browser_mouse_down(struct focusable *focusable, EventR
p = event->where;
GlobalToLocal(&p);
- /* is it in TE? */
+ r = (*(browser->input_te))->viewRect;
+ if (PtInRect(p, &r)) {
+ TEClick(p, ((event->modifiers & shiftKey) != 0), browser->input_te);
+ browser_update_menu(browser);
+ return;
+ }
+
r = (*(browser->te))->viewRect;
if (PtInRect(p, &r)) {
TEClick(p, ((event->modifiers & shiftKey) != 0), browser->te);
@@ -276,6 +327,30 @@ browser_mouse_down(struct focusable *focusable, EventR
}
}
+void
+browser_key_down(struct focusable *focusable, EventRecord *event)
+{
+ struct browser *browser = (struct browser *)(focusable->cookie);
+ TERec *te;
+ char *input, k;
+
+ k = (event->message & charCodeMask);
+ if (k == '\r') {
+ HLock(browser->input_te);
+ te = *(browser->input_te);
+ HLock(te->hText);
+ (*(te->hText))[te->teLength] = '\0';
+ input = xstrdup(*(te->hText), "browser te input");
+ HUnlock(te->hText);
+ HUnlock(browser->input_te);
+ browser->wpr = wikipedia_fetch_article(browser, input);
+ free(input);
+ } else {
+ TEKey(k, browser->input_te);
+ TESelView(browser->input_te);
+ }
+}
+
bool
browser_handle_menu(struct focusable *focusable, short menu, short item)
{
@@ -295,4 +370,131 @@ browser_handle_menu(struct focusable *focusable, short
}
return false;
-}
+}
+
+#define BROWSER_SCRAP_ELEMENTS 20
+#define BROWSER_FONT_SIZE 10
+#define BROWSER_FONT geneva
+static Handle scrp_rec_h = NULL;
+
+size_t
+browser_print(struct browser *browser, const char *str, size_t len,
+ unsigned short style)
+{
+ StScrpRec *scrp_rec;
+ ScrpSTElement *scrp_ele;
+ RgnHandle savergn;
+ Rect zerorect = { 0, 0, 0, 0 };
+ size_t n;
+ short line_height = 0;
+ static unsigned short last_style = 0;
+
+ if (scrp_rec_h == NULL) {
+ scrp_rec_h = xNewHandle(sizeof(short) +
+ (sizeof(ScrpSTElement) * BROWSER_SCRAP_ELEMENTS));
+ HLock(scrp_rec_h);
+ memset(*scrp_rec_h, 0, GetHandleSize(scrp_rec_h));
+ } else {
+ HLock(scrp_rec_h);
+ }
+
+ line_height = BROWSER_FONT_SIZE + 3;
+
+ scrp_rec = (StScrpRec *)(*scrp_rec_h);
+ scrp_rec->scrpNStyles = 1;
+ scrp_ele = &scrp_rec->scrpStyleTab[0];
+ scrp_ele->scrpHeight = line_height;
+ scrp_ele->scrpAscent = BROWSER_FONT_SIZE;
+ scrp_ele->scrpFont = BROWSER_FONT;
+ scrp_ele->scrpSize = BROWSER_FONT_SIZE;
+ scrp_ele->scrpFace = 0;
+
+ if (style & STYLE_BOLD)
+ scrp_ele->scrpFace |= bold | condense;
+ if (style & (STYLE_H1 | STYLE_H2 | STYLE_H3 | STYLE_H4 | STYLE_H5))
+ scrp_ele->scrpFace |= bold;
+ if (style & STYLE_ITALIC)
+ scrp_ele->scrpFace |= italic;
+ if (style & STYLE_LINK)
+ scrp_ele->scrpFace |= underline;
+ if (style & STYLE_H1) {
+ scrp_ele->scrpSize += 8;
+ scrp_ele->scrpHeight += 8;
+ scrp_ele->scrpAscent += 8;
+ }
+
+ if (style & STYLE_LINK) {
+ /* remove link destinations for now */
+ for (n = 0; n < len; n++) {
+ if (str[n] == '|') {
+ str += n + 1;
+ len -= n + 1;
+ break;
+ }
+ }
+ }
+
+ HUnlock(scrp_rec_h);
+
+ HLock(browser->te);
+
+ /* check for TE overflow */
+
+ /* too many lines */
+ if ((*(browser->te))->nLines >=
+ (nitems((*(browser->te))->lineStarts) - 10))
+ goto te_overflow;
+
+ /* too many characters */
+ if ((*(browser->te))->teLength >= (SHRT_MAX - 500))
+ goto te_overflow;
+
+ /* rect of all lines is too tall */
+ if ((*(browser->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, (*(browser->te))->lineStarts[5], browser->te);
+ TEDelete(browser->te);
+
+ /* scroll up, causing a repaint */
+ TEPinScroll(0, INT_MAX, browser->te);
+
+ /* then scroll back down to what it looked like before we did anything */
+ TEPinScroll(0, -INT_MAX, browser->te);
+
+ /* resume normal drawing */
+ SetClip(savergn);
+ DisposeRgn(savergn);
+
+no_overflow:
+ TESetSelect(SHRT_MAX, SHRT_MAX, browser->te);
+ if ((last_style & STYLE_ITALIC) && !(style & STYLE_ITALIC))
+ TEStylInsert(" ", 1, scrp_rec_h, browser->te);
+
+ progress(NULL);
+ TEStylInsert(str, len, scrp_rec_h, browser->te);
+
+ TEPinScroll(0, -INT_MAX, browser->te);
+ SetCtlValue(browser->te_scroller, GetCtlMax(browser->te_scroller));
+ UpdateScrollbarForTE(browser->te_scroller, browser->te, false);
+ HUnlock(browser->te);
+
+ last_style = style;
+
+ if (style & STYLE_H1) {
+ browser_print(browser,
+ "\r------------------------------------------------------------\r",
+ 62, STYLE_BOLD);
+ }
+
+ return len;
+}
--- browser.h Thu Aug 18 22:01:49 2022
+++ browser.h Wed Aug 24 17:30:16 2022
@@ -18,18 +18,32 @@
#define __BROWSER_H__
#include <stdlib.h>
+#include "http.h"
enum {
BROWSER_STATE_IDLE
};
+#define STYLE_BOLD (1 << 0)
+#define STYLE_ITALIC (1 << 1)
+#define STYLE_H1 (1 << 2)
+#define STYLE_H2 (1 << 3)
+#define STYLE_H3 (1 << 4)
+#define STYLE_H4 (1 << 5)
+#define STYLE_H5 (1 << 6)
+#define STYLE_LINK (1 << 7)
+
struct browser {
short state;
WindowPtr win;
+ TEHandle input_te;
TEHandle te;
ControlHandle te_scroller;
+ struct wikipedia_request *wpr;
};
struct browser *browser_init(void);
-
+size_t browser_print(struct browser *browser, const char *str, size_t len,
+ unsigned short style);
+
#endif
--- focusable.c Sun Aug 21 22:46:07 2022
+++ focusable.c Wed Aug 24 15:17:18 2022
@@ -180,9 +180,19 @@ void
focusables_atexit(void)
{
short n;
+ short tnfocusables = nfocusables;
+ struct focusable **tfocusables;
+
+ if (!nfocusables)
+ return;
+
+ tfocusables = xcalloc(sizeof(Ptr), tnfocusables, "tfocusables");
+ memcpy(tfocusables, focusables, sizeof(Ptr) * tnfocusables);
- for (n = 0; n < nfocusables; n++) {
- if (focusables[n]->atexit)
- focusables[n]->atexit(focusables[n]);
+ for (n = 0; n < tnfocusables; n++) {
+ if (tfocusables[n] && tfocusables[n]->atexit)
+ tfocusables[n]->atexit(tfocusables[n]);
}
+
+ free(tfocusables);
}
--- main.c Fri Aug 19 13:30:37 2022
+++ main.c Sun Aug 21 22:45:43 2022
@@ -50,7 +50,8 @@ main(void)
MaxApplZone();
util_init();
-
+ _atexit(focusables_atexit);
+
mbar = GetNewMBar(MBAR_ID);
SetMenuBar(mbar);
apple_menu = GetMHandle(APPLE_MENU_ID);