diff --git a/src/gmnlm.c b/src/gmnlm.c

index 26654324b4fb845633f7db2b2ac01e5e3b4635a1..99ecb7d1d76f8b5f0c856ca9dcd2d6abf5dd6de6 100644

--- a/src/gmnlm.c

+++ b/src/gmnlm.c

@@ -35,6 +35,7 @@ struct gemini_tofu tofu;

enum tofu_action tofu_mode;

FILE *tty;

+ char *meta;

char *plain_url;

char *page_title;

struct Curl_URL *url;

@@ -206,6 +207,52 @@ snprintf(url, sizeof(url), "file://%s", path);

set_url(browser, url, &browser->history);

}

+static void

+print_media_parameters(FILE *out, char *params)

+{

+ if (params == NULL) {

+ fprintf(out, "No media parameters\n");

+ return;

+ }

+ for (char *param = strtok(params, ";"); param;

+ param = strtok(NULL, ";")) {

+ char *value = strchr(param, '=');

+ if (value == NULL) {

+ fprintf(out, "Invalid media type parameter '%s'\n",

+ trim_ws(param));

+ continue;

+ }

+ *value = 0;

+ fprintf(out, "%s: ", trim_ws(param));

+ *value++ = '=';

+ if (*value != '"') {

+ fprintf(out, "%s\n", value);

+ continue;

+ }

+ while (value++) {

+ switch (*value) {

+ case '\0':

+ if ((value = strtok(NULL, ";")) != NULL) {

+ fprintf(out, ";%c", *value);

+ }

+ break;

+ case '"':

+ value = NULL;

+ break;

+ case '\\':

+ if (value[1] == '\0') {

+ break;

+ }

+ value++;

+ /* fallthrough */

+ default:

+ putc(*value, out);

+ }

+ }

+ putc('\n', out);

+ }

+}

+

static enum prompt_result

do_prompts(const char *prompt, struct browser *browser)

{

@@ -329,6 +376,12 @@ case 'r':

if (in[1]) break;

result = PROMPT_ANSWERED;

goto exit;

+ case 'i':

+ if (in[1]) break;

+ print_media_parameters(browser->tty, browser->meta

+ ? strchr(browser->meta, ';') : NULL);

+ result = PROMPT_AGAIN;

+ goto exit;

case '?':

if (in[1]) break;

fprintf(browser->tty, "%s", help_msg);

@@ -539,12 +592,19 @@ ++row; col = 0;

if (browser->pagination && row >= ws.ws_row - 4) {

char prompt[4096];

+ char *end = NULL;

+ if (browser->meta && (end = strchr(resp->meta, ';')) != NULL) {

+ *end = 0;

+ }

snprintf(prompt, sizeof(prompt), "\n%s at %s\n"

"[Enter]: read more; %s[N]: follow Nth link; %s%s[q]uit; [?]; or type a URL\n"

"(more) => ", resp->meta, browser->plain_url,

browser->searching ? "[n]ext result; " : "",

browser->history->prev ? "[b]ack; " : "",

browser->history->next ? "[f]orward; " : "");

+ if (end != NULL) {

+ *end = ';';

+ }

enum prompt_result result = PROMPT_AGAIN;

while (result == PROMPT_AGAIN) {

result = do_prompts(prompt, browser);

@@ -714,6 +774,7 @@ &browser->opts, resp);

if (res != GEMINI_OK) {

fprintf(stderr, "Error: %s\n", gemini_strerr(res, resp));

requesting = false;

+ resp->status = 70 + res;

break;

}

@@ -858,6 +919,7 @@ .tofu_mode = TOFU_ASK,

.unicode = true,

.url = curl_url(),

.tty = fopen("/dev/tty", "w+"),

+ .meta = NULL,

};

int c;

@@ -909,38 +971,45 @@ struct gemini_response resp;

browser.running = true;

while (browser.running) {

static char prompt[4096];

- if (do_requests(&browser, &resp)) {

- // Skip prompts

- gemini_response_finish(&resp);

- goto next;

+ bool skip_prompt = do_requests(&browser, &resp);

+ if (browser.meta) {

+ free(browser.meta);

}

-

- snprintf(prompt, sizeof(prompt), "\n%s at %s\n"

- "[N]: follow Nth link; %s%s[q]uit; [?]; or type a URL\n"

- "=> ",

- resp.status == GEMINI_STATUS_SUCCESS ? resp.meta : "",

- browser.plain_url,

- browser.history->prev ? "[b]ack; " : "",

- browser.history->next ? "[f]orward; " : "");

+ browser.meta = resp.status == GEMINI_STATUS_SUCCESS

+ ? strdup(resp.meta) : NULL;

gemini_response_finish(&resp);

+ if (!skip_prompt) {

+ char *end = NULL;

+ if (browser.meta && (end = strchr(browser.meta, ';')) != NULL) {

+ *end = 0;

+ }

+ snprintf(prompt, sizeof(prompt), "\n%s at %s\n"

+ "[N]: follow Nth link; %s%s[q]uit; [?]; or type a URL\n"

+ "=> ", browser.meta ? browser.meta

+ : "[request failed]", browser.plain_url,

+ browser.history->prev ? "[b]ack; " : "",

+ browser.history->next ? "[f]orward; " : "");

+ if (end != NULL) {

+ *end = ';';

+ }

- enum prompt_result result = PROMPT_AGAIN;

- while (result == PROMPT_AGAIN || result == PROMPT_MORE) {

- result = do_prompts(prompt, &browser);

- }

- switch (result) {

- case PROMPT_AGAIN:

- case PROMPT_MORE:

- assert(0);

- case PROMPT_QUIT:

- browser.running = false;

- break;

- case PROMPT_ANSWERED:

- case PROMPT_NEXT:

- break;

+ enum prompt_result result = PROMPT_AGAIN;

+ while (result == PROMPT_AGAIN || result == PROMPT_MORE) {

+ result = do_prompts(prompt, &browser);

+ }

+ switch (result) {

+ case PROMPT_AGAIN:

+ case PROMPT_MORE:

+ assert(0);

+ case PROMPT_QUIT:

+ browser.running = false;

+ break;

+ case PROMPT_ANSWERED:

+ case PROMPT_NEXT:

+ break;

+ }

}

-next:;

struct link *link = browser.links;

while (link) {

struct link *next = link->next;

@@ -961,6 +1030,9 @@ SSL_CTX_free(browser.opts.ssl_ctx);

curl_url_cleanup(browser.url);

free(browser.page_title);

free(browser.plain_url);

+ if (browser.meta != NULL) {

+ free(browser.meta);

+ }

fclose(browser.tty);

return 0;

}