Skip to content

Auto inline images #302

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Conversation

el-remph
Copy link

Deduce an appropriate value for inline_img_protocol rather than requiring it to be set manually with eg. -o auto_inline_img=4 for kitty.

Tangentially, should struct _termialImage {...} TerminalImage at image.c:11,27 be _terminalImage? Not important currently since nothing uses the struct tag as opposed to the TerminalImage typedef, but could surprise someone eventually

@rkta
Copy link
Contributor

rkta commented Jul 14, 2024

Some general remarks:

  • This should be one commit, not three.
  • Missing documentation update.

As someone who does not use images, what problem does this solve?

image.c Outdated
@@ -16,7 +16,7 @@ static int image_index = 0;

/* display image */

typedef struct _termialImage {
typedef struct _termialImage /* [sic]? */ {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just fix it.

main.c Outdated
@@ -127,7 +127,7 @@ static int searchKeyNum(void);
#define help() fusage(stdout, 0)
#define usage() fusage(stderr, 1)

int enable_inline_image;
int enable_inline_image = -1; /* TODO: can't we remove this ifndef USE_IMAGE? */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see an USE_IMAGE here and probably no ;)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's unused without USE_IMAGE, but you also have to ifdef out a few enable_inline_image checks (and the CLI param assignments).

@@ -0,0 +1,127 @@
/* The only externally visible symbol exported by this module is
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code should follow the same style as the code in other units. And I think a better place for this is image.c

@@ -0,0 +1,127 @@
/* The only externally visible symbol exported by this module is
* inline_img_protocol_autodetect(). I appreciate that this name does not
* roll off the tongue
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you trolling?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No? I certainly intended no offence, I must have just been in a good mood while writing that, sorry

main.c Outdated
@@ -720,6 +720,8 @@ main(int argc, char **argv)
}
}
#endif
else if (!strcmp("-auto-inline-img", argv[i]))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to have a command line switch? It's should be an option anyways and the can be set via -o.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I considered that, but thought that inline_img_protocol=5 or enable_inline_image == 5 would imply a built-in protocol rather than use of w3mimgdisplay for any code looking for a positive value to mean that, while auto-detection can resolve to 0 (ie. use w3mimgdisplay). Also, if a new image protocol were to become relevant, such as Terminology's, having auto-detection in the middle of a list of protocols would make no sense. Trouble is, set_param() doesn't allow negative values for P_INT and I thought changing that could have excessively far-reaching implications for anything assuming P_INT was >= 0.

Looking at set_param again, this could fixed by making auto_inline_image with P_SHORT or P_CHARINT and changing the type of enable_inline_image accordingly, but at the time I just went for the easiest and simplest way so I could test it

@bptato
Copy link
Contributor

bptato commented Jul 14, 2024

As someone who does not use images, what problem does this solve?

It avoids having to manually set the inline image output method (since different methods work best depending on your environment). Normally you'd have to go through each option yourself; this patch does the detection automatically.

Some comments on the implementation:

  • Doing terminal capability detection in two passes seems needlessly inefficient. Could we merge the sixel test with get_pixel_per_cell?
  • As rkta says, we don't need a new source file for this. Just put it in terms.c and/or image.c.
  • autodetection should be an option (in rc.c) like the actual image protocols, not a CLI parameter. Then you can default to "autodetect" in new configs, without breaking existing configs. We might want to use a separate variable to store the final chosen image display method.
  • Kitty display depends on ImageMagick, and sixel display needs img2sixel. So we probably want to check if these programs exist on the system at all.
  • IIRC, the iTerm2 implementation does not support image cropping, unlike the sixel implementation (which also works in iTerm2). Personally, I'd just remove the iTerm2 test; correct image dimensions are more important than optimal color output.

@el-remph
Copy link
Author

  • This should be one commit, not three.

Ah my apologies, that's my bad habit of committing WIP as I go so I remember what order I've done things in. But can't the merge simply be squashed? Or should I rebase and squash it myself and open a different PR? (with changes moved to image.c ofc)

  • Missing documentation update.

As far as I could see, -o inline_img_protocol has no documentation to update, though do point me towards it if I missed it

As someone who does not use images, what problem does this solve?

Not every user is aware of the different protocols available, nor which if any are supported by their terminal -- I was unaware that more recent Konsole versions support sixel, iterm2 and kitty images, since I'd been using it since before those versions, and xterm and xfce4-terminal both have undocumented sixel support. Of course, on Wayland the w3mimgdisplay X11 fallback doesn't work

Also, for -o inline_img_protocol=x it isn't clear to the user which values of x correspond to which protocol; even if this were documented, it would still be unintuitive and not easy to remember.

@el-remph
Copy link
Author

  • Doing terminal capability detection in two passes seems needlessly inefficient. Could we merge the sixel test with get_pixel_per_cell?

I don't think so, get_pixel_per_cell uses XTWINOPS CSI Ps ; Ps ; Ps t, test_for_sixel uses CSI Ps c

  • autodetection should be an option (in rc.c) like the actual image protocols, not a CLI parameter. Then you can default to "autodetect" in new configs, without breaking existing configs. We might want to use a separate variable to store the final chosen image display method.

I'm not sure existing config would be broken -- if inline_img_protocol is set in a config, it would override default autodetection. I would have liked to use -o inline_img_protocol=-1, since that's what happens under the hood, so perhaps changing to P_CHARINT is the answer

@bptato
Copy link
Contributor

bptato commented Jul 15, 2024

  • Doing terminal capability detection in two passes seems needlessly inefficient. Could we merge the sixel test with get_pixel_per_cell?

I don't think so, get_pixel_per_cell uses XTWINOPS CSI Ps ; Ps ; Ps t, test_for_sixel uses CSI Ps c

Ah, no, I meant sending them together in a single batch. Terminal query code usually does this in one pass, putting primary DA in the end, because one write/read/timeout cycle will always be faster than two. (Also, pretty much every terminal emulator responds to a primary DA but not necessarily to other queries, so sending it as the final query is a nice timeout prevention measure.)

We can live without that for now, since we only have two queries, both seem to be widely supported, and get_pixel_per_cell often returns without sending a query at all. Just a suggestion for improvement.

I'm not sure existing config would be broken

Yeah, I now see you're right.

The only problem with the current solution remains that it doesn't let the user pick "autodetect" and then stick with it, which would be nice for when you use w3m in different terminals. (Even if you could pick -1 in its current form, it would automatically switch to another option as soon as you change something else in the option setting panel.) Hence my suggestion to use a separate internal variable for the actual image protocol choice.

el-remph added a commit to el-remph/w3m that referenced this pull request Jul 21, 2024
  * Remove iterm2 test
  * Move image protocol detection functions into image.c
  * Replace -auto-inline-img with -o inline_img_protocol=-1, by changing
    inline_img_protcol to a P_CHARINT
  * Test for presence of img2sixel command before allowing sixel protocol
    selection
@el-remph
Copy link
Author

In the absence of any further comments on the clutter of the commit history, I'll just push any further commits and potentially clean up history later (I know `clean up later' is never a good thing to hear ;). The diff against master still looks fairly clean. This implements most of the changes just discussed

Ah, no, I meant sending them together in a single batch

Oh I get it

[...]and get_pixel_per_cell often returns without sending a query at all

inline_img_protocol_autodetect() may also itself return without sending the XTWINOPS query (if protocol_test_environment() returns nonzero), so implementing that may end up being more trouble than it's worth. For startup speed I'm more concerned about the exec call to find img2sixel in have_img2sixel() in image.c, even though it's the same way that img2sixel is found when it's needed in put_image_sixel() in terms.c.

The only problem with the current solution remains that it doesn't let the user pick "autodetect" and then stick with it, which would be nice for when you use w3m in different terminals. (Even if you could pick -1 in its current form, it would automatically switch to another option as soon as you change something else in the option setting panel.)

I'm afraid I don't follow here -- by the time you get to the option setting panel, if autodetect was set it will already have run at startup and resolved to a different value INLINE_IMG_*. Or do you mean it should not run only at startup? The way I see it right now, if the user picks a different setting for inline_img_protocol, this by design should override the auto-detected value

@rkta
Copy link
Contributor

rkta commented Jul 22, 2024

The auto detect should be an option in the options panel, so that a user does not have to use the command line option in order to enable it.

Re: commit history, you can squash the commits and just do a force push into your branch.

Remember to also update the docs, when you are done with the implementation.

@bptato
Copy link
Contributor

bptato commented Jul 22, 2024

The auto detect should be an option in the options panel, so that a user does not have to use the command line option in order to enable it.

Yeah, that's what I meant. You could do something like:

/* in fm.h */
#define INLINE_IMG_AUTODETECT -1
/* maybe move this to fm.h too */
global signed char enable_inline_image init(INLINE_IMG_NONE);
/* ...and set above variable based on this */
global signed char enable_inline_image_config init(INLINE_IMG_AUTODETECT);

So if enable_inline_image_config == INLINE_IMG_AUTODETECT, detect the method and set enable_inline_image to that. Otherwise, set enable_inline_image to enable_inline_image_config as is. (Also, make enable_inline_image_config the user-facing variable you set in rc.c.)

Remember to also update the docs, when you are done with the implementation.

What docs? :P

OK, there's doc/README.sixel, which is a bit outdated and only talks about the sixel method. Also, doc/README.img, which only talks about the X/framebuffer method. I think it would be best to merge the two, and also add some info on the other methods (+ how to select them).

It's kind of my fault for never updating the docs when working on this, so I'll prepare a PR for it once this patch is finalized.

@rkta
Copy link
Contributor

rkta commented Jul 23, 2024 via email

@bptato
Copy link
Contributor

bptato commented Jul 23, 2024

Well, adding a command line option should at least update the man page
and probably also the MANUAL.html.

Wait what? I thought we decided we don't need a command line option...

Looking at the man page and MANUAL.html, neither did ever mention image support. I've started working on an overhauled README.img, I'd say it's easiest to just link to that from MANUAL.html once it's finished.

@rkta
Copy link
Contributor

rkta commented Jul 23, 2024 via email

@el-remph el-remph force-pushed the auto-inline-images branch from 3629d57 to 7d07f7f Compare August 19, 2024 04:03
@el-remph
Copy link
Author

Alright, I've squashed the commits from up til now, and the second commit adds the separate variables for enable_inline_image_config, and INLINE_IMAGE_AUTODETECT to the option table in rc.c. The original enable_inline_image can be unsigned now, so there's no possibility of a negative value being taken as a false positive in a boolean test.

Only issue is now the user can't see in the options panel which protocol was selected automagically, but that's not the end of the world. If it does become necessary, maybe that information would be more suited to debug output on stderr anyway.

Also, looks like enable_inline_image can be ifdef'd out after all

@rkta
Copy link
Contributor

rkta commented Sep 6, 2024

JFTR, I have this on my radar. In the current form it's not easy to review, because there seem to be a lot of unrelated changes mixed into the commits, but I will try to work it out when my time permits.

@rkta
Copy link
Contributor

rkta commented Sep 28, 2024

  • Doing terminal capability detection in two passes seems needlessly inefficient. Could we merge the sixel test with get_pixel_per_cell?

I don't think so, get_pixel_per_cell uses XTWINOPS CSI Ps ; Ps ; Ps t, test_for_sixel uses CSI Ps c

Ah, no, I meant sending them together in a single batch. Terminal query code usually does this in one pass, putting primary DA in the end, because one write/read/timeout cycle will always be faster than two. (Also, pretty much every terminal emulator responds to a primary DA but not necessarily to other queries, so sending it as the final query is a nice timeout prevention measure.)

We can live without that for now, since we only have two queries, both seem to be widely supported, and get_pixel_per_cell often returns without sending a query at all. Just a suggestion for improvement.

Is this still valid? If yes, can you make that improvement @el-remph , please.

@el-remph
Copy link
Author

el-remph commented Dec 7, 2024

Sorry I was away, here's a mockup that seems to work, but I'm not sure if this does optimise anything after all, because to know if we need pixel/char we need to know whether we're using enable_inline_img or not, so (if kitty and mlterm protocols are unavailable) we need to know if the terminal supports sixel before we query pixel/char.

(There's more that could be done to make this prettier, but I'm leaving that until I know if this optimises anything or not)

My 'solution' in this commit, is just call get_pixel_per_char() unconditionally, which will lead to an unnecessary check for pixel/char for those without any supported inline image protocol. On most systems, I don't think this will use XTWINOPS, since TIOCGWINSZ is usually available, so this works out to an extra ioctl call for the typical (I guess) user. I don't know the cost of ioctl so this may not be much, but the only benefits are for those on systems without TIOCGWINSZ so I doubt it's worth it.

Unless anyone has any ideas, I'll rollback this commit

@bptato
Copy link
Contributor

bptato commented Dec 8, 2024

When I wrote "We can live without that for now", I meant it. It isn't that relevant with just two queries, especially when one of those is just a fallback.

The current (as in, before this patch) pixel per column/line logic seems flawed anyway, as the same variables are used for tables too (width attribute, etc.) So right now, toggling inline image support influences table rendering. Querying cell dimensions unconditionally would be preferable, but then it has to be moved outside the image ifdefs, and we have to figure out what to do with the pixel per char/line options... I think it's far beyond the scope of this PR.

@el-remph
Copy link
Author

When I wrote "We can live without that for now", I meant it.

Wrote the commit in response to @rkta here, but yes, I agree; rolling back as planned

@el-remph
Copy link
Author

Rebased with detection of ghostty, which has had support for kitty images since very early on afaict.

Anyone know the status of this pr?

image.c Outdated
Comment on lines 212 to 216
/* the string in the following sizeof expression is what I think the
* largest possible response could be. See
* https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
* for more information, specifically the section on CSI Ps c ("\e[c") */
char term_response[sizeof "\033[?65;1;2;3;4;6;8;9;15;16;17;18;21;22;28;29c"] = "";
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, this is by no means the largest possible response. The list of features on the xterm site are just the ones that xterm supports. DEC documented more than 40 of them, and some modern terminals have defined a few of their own.

That said, no one terminal is likely to report all of them, but there will definitely be terminals with longer responses than the one above. For example, this is an example from a real DEC VT520:

\033[?65;1;2;6;7;8;9;12;15;18;19;21;23;24;42;44;45;46c

A VT525 has at least one more feature than that, so would be even longer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Plus read isn't guaranteed to read the entire response in the first place.
It's better to loop until you see a c.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should also address the problem of snarfing up input on museum pieces, right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. Terminal querying is inherently racy, and the only comprehensive solution to that is to feed back any unexpected data before & after the response to an internal buffer (which w3m does not have) for subsequent processing.
In practice, I doubt anybody will run into this - try using images over a high-latency connection to see why :P

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well then, still using a loop and a dynamically sized buffer seems the right approach here.

@rkta
Copy link
Contributor

rkta commented Jan 16, 2025 via email

image.c Outdated
fd_set fds;
struct timeval timeout = { 0, 0.2 * 1000000 }; /* wait 0.2s, from terms.c */
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
Copy link
Contributor

@bptato bptato Jan 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just realized you're reading from stdin - that won't work: echo test | w3m
Please move the function to terms.c and use the tty variable, like get_pixel_per_cell does.

image.c Outdated
_exit(-1);
default:
return
#ifdef HAVE_WAITPID
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is 2025, I feel we can afford to assume waitpid exists :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be fair, while you are right, this just reuses the pattern used in the rest of the code base. I will need to address this anyways.

Maybe it's OK to keep it for consistency, I don't really care.

Copy link
Contributor

@rkta rkta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still think, this needs to be documented somewhere.

image.c Outdated
static int
protocol_test_environment(void)
{
const char * envptr;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

*envptr

image.c Outdated
const char * envptr;

if ((envptr = getenv("TERM"))) {
/* The purpose of strncmp(3) where used below is like the glob `prefix*',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commentstyle for multi-line comments should be

/*
 * comment
 */

image.c Outdated
_exit(-1);
default:
return
#ifdef HAVE_WAITPID
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be fair, while you are right, this just reuses the pattern used in the rest of the code base. I will need to address this anyways.

Maybe it's OK to keep it for consistency, I don't really care.

image.c Outdated
Comment on lines 212 to 216
/* the string in the following sizeof expression is what I think the
* largest possible response could be. See
* https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
* for more information, specifically the section on CSI Ps c ("\e[c") */
char term_response[sizeof "\033[?65;1;2;3;4;6;8;9;15;16;17;18;21;22;28;29c"] = "";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should also address the problem of snarfing up input on museum pieces, right?

image.c Outdated
* https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
* for more information, specifically the section on CSI Ps c ("\e[c") */
char term_response[sizeof "\033[?65;1;2;3;4;6;8;9;15;16;17;18;21;22;28;29c"] = "";
char * ptr; /* general-purpose pointer to the above buffer */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

*ptr, the asterisks sticks to the name in C.

image.c Outdated
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
if ((nret = select(STDIN_FILENO + 1, &fds, NULL, NULL, &timeout)) <= 0) {
fprintf(stderr, "%s: %s\n", errstr, nret == 0 ? "timed out" : strerror(errno));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please keep it below 80 chars, if there is no very good reason to do otherwise.

Applies to other spots as well.

image.c Outdated
|| memcmp(term_response, "\033[?", 3) != 0
|| !(ptr = memchr(term_response, 'c', nchars_read)))
{
fputs("Malformed terminal attributes\n", stderr);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is writing to stderr good practice here or should this use disp_err_message?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't think it was worth displaying it prominently to a user, just outputting the information to anyone who is looking for it. Writing to stderr seems fairly common throughout the codebase

image.c Outdated
if (*++ptr != '4')
continue;
switch (*++ptr) {
case ';': case 'c':
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't hide the case 'c': on the same line. Put it on a separate line, please.

@@ -449,7 +450,7 @@ struct param_ptr params1[] = {
CMT_EXT_IMAGE_VIEWER, NULL},
{"image_scale", P_SCALE, PI_TEXT, (void *)&image_scale, CMT_IMAGE_SCALE,
NULL},
{"inline_img_protocol", P_INT, PI_SEL_C, (void *)&enable_inline_image,
{"inline_img_protocol", P_CHARINT, PI_SEL_C, (void *)&enable_inline_image_config,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is P_CHARINT needed here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because P_INT does not accept negative values.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, it's ignored when setting the value. I only looked at reading it... Bad naming though...

But then OK.

image.c Outdated
Comment on lines 158 to 159
if (strncmp(envptr, "mlterm", 6) == 0)
return INLINE_IMG_OSC5379;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not in a position to test, but I was under the impression that MLterm had dropped support for OSC 5379 images several years ago. See the 3.8.5 release notes.

I may be misinterpreting what they're saying there, but I think it would be good idea to confirm this actually works (if you haven't already done so) before forcing the use of OSC 5379. MLterm does support Sixel, so you should still have that as a fallback.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, indeed. It's not fully gone, but you have to pass a flag when compiling:
./configure CFLAGS=-DENABLE_OSC5379PICTURE

I suppose it's better to stick with Sixel.

@el-remph
Copy link
Author

Rebased with the changes recommended:

  • Primary devattr querying moved to terms.c, reading from tty into a dynamically resized buffer
  • Test for sixel before testing for mlterm OSC5379, to catch newer versions of mlterm which support sixel but not OSC5379
  • Made rkta's style changes

Also I'd prefer if you would send it the mailing list[1] then I will do
the final review.

Oh, I didn't realise about the mailing list. If these changes pass muster here then I'll submit it to the mailing list

@bptato
Copy link
Contributor

bptato commented Jan 27, 2025

I've tested the latest version:

  • Piping to stdin works now, thanks.
  • It seems initImage gets called twice for some reason, so detection is performed twice too :/
    I guess that's why the activeImage check is there before getCharSize? Maybe you could reuse it.
  • Obscure, but SyncTERM returns \033[= to primary DA instead of \033[?; might as well support it:
diff --git a/terms.c b/terms.c
index f75dcfc6..d663d18e 100644
--- a/terms.c
+++ b/terms.c
@@ -924,7 +924,8 @@ img_protocol_test_for_sixel(void)
 	}
 
 	/* first useful iteration; validate response */
-	if (nchars_read + len >= 3 && memcmp(response, "\033[?", 3) != 0) {
+	if (nchars_read + len >= 3 && memcmp(response, "\033[?", 3) != 0 &&
+	    memcmp(response, "\033[=", 3) != 0) {
 	    fputs("Malformed terminal attributes\n", stderr);
 	    return INLINE_IMG_NONE;
 	}

I still think, this needs to be documented somewhere.

Well, but the image docs in your fork are now different... I can update them in a separate patch, if you're OK with that.

@j4james
Copy link

j4james commented Jan 27, 2025

  • Obscure, but SyncTERM returns \033[= to primary DA instead of \033[?; might as well support it:

@bptato I don't think accepting the \033[= prefix is going to help, though, because the rest of the DA report isn't DEC-compatible. You can't search for a 4 parameter to check for Sixel support - it's just an ASCII encoding of the "CTerm" library name and a version number. So you'd probably have to check specifically for the parameter sequence 67;84;101;114;109 at the start (assuming all versions supported Sixel).

@bptato
Copy link
Contributor

bptato commented Jan 27, 2025

Ah, no, by "support" I meant "don't print an error and stop looping" :P

SyncTERM (at least the version I have, from a few months ago) doesn't do private color registers, so you have to manually configure W3M_IMG2SIXEL for it anyway.

@el-remph
Copy link
Author

  • Obscure, but SyncTERM returns \033[= to primary DA instead of \033[?; might as well support it

@bptato Yep that's obscure alright (:
Done that and also skipped processing the response if it's SyncTERM

  • It seems initImage gets called twice for some reason, so detection is performed twice too :/
    I guess that's why the activeImage check is there before getCharSize? Maybe you could reuse it.

afaict activeImage is only set to TRUE once and never set back to FALSE, so if w3m is started and initImage called without auto-detection, and the user then enables auto-detection, that won't work. I haven't been able to solve this.

One option could be to cache the result of auto-detection once it's done, then reuse that on subsequent calls -- is it possible for the result of auto-detection to change during a session? For example, if the user starts w3m in GNU screen in a non-sixel terminal, then reattaches in a sixel terminal? Is it possible for the TERM environment variable to be modified during a session?

@bptato
Copy link
Contributor

bptato commented Jan 29, 2025

afaict activeImage is only set to TRUE once and never set back to FALSE, so if w3m is started and initImage called without auto-detection, and the user then enables auto-detection, that won't work. I haven't been able to solve this.

Ah, I see. I would have expected that I have to restart w3m, but it's definitely nicer if it works immediately :)

One option could be to cache the result of auto-detection once it's done, then reuse that on subsequent calls -- is it possible for the result of auto-detection to change during a session? For example, if the user starts w3m in GNU screen in a non-sixel terminal, then reattaches in a sixel terminal?

On GNU screen, img2sixel only seems to work with the "penetrate" hack. (But maybe I'm missing something.)

For a working example, see tmux: it reports Sixel capability even on terminals that cannot display Sixel, so you can attach both a Sixel-capable and a non-Sixel-capable terminal at the same time (and see a placeholder when appropriate).

In other words: I wouldn't worry about this.

Is it possible for the TERM environment variable to be modified during a session?

No.

…inal

* Compile out enable_inline_img ifndef USE_IMAGE
* Add enable_inline_img_config for configuration; leave enable_inline_img
  for state
* Make auto-selection of inline_img_protocol the default value of
  enable_inline_img_config
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants