AmendHub

Download:

jcs

/

detritus

/

amendments

/

33

gopher: Draw icons for menu items using TextView's new BitMap support


jcs made amendment 33 about 1 year ago
--- browser.c Mon Nov 11 23:31:50 2024 +++ browser.c Thu Nov 14 14:30:59 2024 @@ -58,6 +58,7 @@ void browser_atexit(struct focusable *focusable); void browser_go(struct browser *browser, short dir); page_handle browser_create_page(struct browser *browser, char *uristr); void browser_draw_status(struct browser *browser); +struct TVStyle * browser_build_tvstyle(struct browser *browser); void browser_finished_loading(struct browser *browser); void browser_follow_redir(struct browser *browser); void browser_stop_loading_page(struct browser *browser); @@ -797,14 +798,13 @@ browser_draw_status(struct browser *browser) DrawText(browser->status_text, 0, browser->status_length); } -size_t -browser_print(struct browser *browser, const char *str, size_t len, - bool newline) +struct TVStyle * +browser_build_tvstyle(struct browser *browser) { - struct TVStyle style; - struct browser_link *link; - size_t n, nlines; + static struct TVStyle style; + memset(&style, 0, sizeof(style)); + style.font = BROWSER_FONT; style.size = BROWSER_FONT_SIZE; style.style = 0; @@ -829,9 +829,33 @@ browser_print(struct browser *browser, const char *str else if (browser->style & STYLE_H3) style.size += 2; + return &style; +} + +size_t +browser_print_bitmap(struct browser *browser, BitMap *icon, + FontInfo *sizing) +{ + struct TVStyle *style; + + style = browser_build_tvstyle(browser); + style->font_info = *sizing; + + return !!TVAppendBitMap(browser->output_tv, icon, style); +} + +size_t +browser_print(struct browser *browser, const char *str, size_t len, + bool newline) +{ + struct TVStyle *style; + size_t n, nlines; + + style = browser_build_tvstyle(browser); + nlines = (*(browser->output_tv))->nlines; - (newline ? TVAppendLine : TVAppend)(browser->output_tv, &style, + (newline ? TVAppendLine : TVAppend)(browser->output_tv, style, (char *)str, len); if ((*(browser->output_tv))->nlines != nlines) --- browser.h Mon Nov 11 23:13:28 2024 +++ browser.h Wed Nov 13 14:17:46 2024 @@ -131,6 +131,8 @@ size_t browser_print_link(struct browser *browser, con size_t url_len, const char *title, size_t title_len, bool newline); size_t browser_print(struct browser *browser, const char *str, size_t len, bool newline); +size_t browser_print_bitmap(struct browser *browser, BitMap *icon, + FontInfo *sizing); void browser_recalc_scrollbar(struct browser *browser); struct page * browser_grow_page_content(struct page *page, size_t len); void browser_go_uri(struct browser *browser, char *uristr); --- gopher.c Mon Nov 11 23:12:46 2024 +++ gopher.c Wed Nov 13 14:24:43 2024 @@ -20,13 +20,28 @@ #include "detritus.h" -#define GOPHER_PORT 70 +#define GOPHER_PORT 70 +#define GOPHER_ICON_SICN_ID 1024 +#define GOPHER_ICON_TEXT_ID 0 +#define GOPHER_ICON_FOLDER_ID 1 +#define GOPHER_ICON_MACARCHIVE_ID 2 +#define GOPHER_ICON_DOSARCHIVE_ID 3 +#define GOPHER_ICON_UNKNOWN_ID 4 +#define GOPHER_ICON_SEARCH_ID 5 +#define GOPHER_ICON_SOUND_ID 6 +#define GOPHER_ICON_IMAGE_ID 7 +#define GOPHER_ICON_DOC_ID 8 + /* printing line-by-line is slow, so only recalc every n lines */ -#define RECALC_EVERY_N_LINES 25 +#define RECALC_EVERY_N_LINES 25 static const char showable_types[] = "013i"; +struct gopher_page { + Handle sicn; +}; + bool gopher_accept_uri(struct URI *uri); bool gopher_request_init(page_handle pageh); bool gopher_process(page_handle pageh); @@ -53,6 +68,7 @@ bool gopher_request_init(page_handle pageh) { struct page *page = *pageh; + struct gopher_page *gopher; size_t selector_len, output_len; char *filename, *output; @@ -82,15 +98,32 @@ gopher_request_init(page_handle pageh) snprintf(output, output_len + 1, "%s\r\n", selector_len ? page->uri->path + 2 : ""); + gopher = xmalloc(sizeof(struct gopher_page)); + if (gopher == NULL) { + xfree(&output); + warn("Out of memory"); + return false; + } + gopher->sicn = Get1Resource('SICN', GOPHER_ICON_SICN_ID); + if (gopher->sicn == NULL) { + xfree(&output); + xfree(&gopher); + warn("Can't find Gopher SICN"); + return false; + } + page->request = request_connect(page->browser, page->uri->hostname, page->uri->port, false, 0); if (page->request == NULL) { + ReleaseResource(gopher->sicn); + xfree(&gopher); xfree(&output); return false; } page->request->output_len = output_len; page->request->output = output; - + page->handler_cookie = gopher; + /* XXX: try to detect server responding with "3" for error? */ if (strchr(showable_types, page->content_type[0]) == NULL) { @@ -208,14 +241,20 @@ static void gopher_print_menu(struct page *page, char *line, size_t len) { static char uri[URI_MAX_STR_LEN + 1], prefix[5]; + struct gopher_page *gopher; + BitMap icon; + FontInfo sizing; char type, *label, *selector = NULL, *hostname = NULL; size_t tlen; unsigned short port = 0; + short icon_off = -1; long n; type = line[0]; label = line + 1; + gopher = (struct gopher_page *)page->handler_cookie; + for (n = 1; n < len; n++) { if (line[n] != '\t') continue; @@ -239,8 +278,86 @@ gopher_print_menu(struct page *page, char *line, size_ browser_print(page->browser, label, strlen(label), true); break; default: - snprintf(prefix, sizeof(prefix), "[%c] ", type); - browser_print(page->browser, prefix, 4, false); + switch (type) { + case '0': + /* text file */ + icon_off = GOPHER_ICON_TEXT_ID; + break; + case '1': + /* submenu */ + icon_off = GOPHER_ICON_FOLDER_ID; + break; + case '3': + /* error page */ + icon_off = GOPHER_ICON_UNKNOWN_ID; + break; + case '5': + /* dos */ + icon_off = GOPHER_ICON_DOSARCHIVE_ID; + break; + case '4': + /* mac binhex */ + icon_off = GOPHER_ICON_MACARCHIVE_ID; + break; + case '7': + /* search */ + icon_off = GOPHER_ICON_SEARCH_ID; + break; + case '2': + /* ccso nameserver? */ + case '+': + /* mirror? */ + case '6': + /* uuencoded */ + case '8': + /* telnet */ + case '9': + /* binary file */ + case 'T': + /* telnet 3270 */ + case 'd': + /* doc */ + case 'h': + /* html */ + case 'r': + /* rtf */ + case 'P': + /* pdf */ + case 'X': + /* xml */ + icon_off = GOPHER_ICON_DOC_ID; + break; + case 'g': + /* gif */ + case 'I': + /* image */ + case 'p': + /* png */ + case ':': + /* bitmap */ + case ';': + /* movie */ + icon_off = GOPHER_ICON_IMAGE_ID; + break; + case '<': + /* sound */ + icon_off = GOPHER_ICON_SOUND_ID; + break; + default: + icon_off = GOPHER_ICON_UNKNOWN_ID; + } + + HLock(gopher->sicn); + icon.baseAddr = (char *)*(gopher->sicn) + (icon_off * 32); + icon.rowBytes = 2; + SetRect(&icon.bounds, 0, 0, 12, 12); + + sizing.ascent = 10; + sizing.descent = 2; + sizing.widMax = 20; + browser_print_bitmap(page->browser, &icon, &sizing); + + HUnlock(gopher->sicn); if (type == 'h' && strncmp(selector, "URL:", 4) == 0) tlen = strlcpy(uri, selector + 4, sizeof(uri));