AmendHub

jcs

/

wikipedia

/

amendments

/

12

browser: Add stylized text viewing


jcs made amendment 12 5 months 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);