Hello Jan,
Jan Chaloupka <[email protected]> wrote:
|-------- Original Message --------
|Subject: [PATCH] list.c: h+ does nothing, it should show next message
|headers
|Date: Tue, 19 Aug 2014 16:32:44 +0200
|From: Jan Chaloupka <[email protected]>
|To: [email protected]
|CC: [email protected], [email protected]
thanks for Cc:ing me :) and reporting this issue after all.
Now this..
..but note first that the S-nail v14.8 minor is long dedicated to
overhauling the list selection and thread display issues..
|https://bugzilla.redhat.com/show_bug.cgi?id=1131533
|
|When running mailx -f testemails, h+ command is not showing next message
|headers. This patch fix this issue.
|
|TPLUS action only skips those messages, that are not vissible (list.c:293).
|Instead, it should find the next message header that belongs to the next
|screen. Thus, I go through messages and skip every visible message belonging
|to the actual screen. Once I reach message for the next screen, I stop.
|Index i is set at the beggining of the current screen instead of valdot
|(I need to start counting from the beggining of the screen, valdot can point
|to the first unread message).
Nope, this is wrong. TPLUS is supposed to do exactly that [1]:
The next undeleted message, or the next deleted message for the
undelete command. In sorted/threaded mode, the next such message
in the sorted/threaded order.
and [2], section "EXTENDED DESCRIPTION":
+ The next undeleted message, or the next deleted message for
the undelete command.
[1]
<http://sdaoden.users.sourceforge.net/code-nail.html#x53504543494659494e47204d45535341474553>
[2] <http://pubs.opengroup.org/onlinepubs/9699919799/utilities/mailx.html>
Instead you would have to adjust the headers() command in cmd1.c.
Note however that the current _documented_ behaviour is
non-standard (again [2]):
Write the page of headers that includes the message specified.
If the message argument is not specified, the current message
shall not change. However, if the message argument is specified,
the current message shall become the message that appears at the
top of the page of headers that includes the message specified.
The current implementation is falsely documented and overly wrong,
e.g., it takes a message list argument, which is what bite you (it
should simply take a string and parse it itself).
So this is what i did for S-nail now, rewriting `headers' to have
`0', `-', `+' and `$' special arguments, as well as the
one-message argument. It is (still) not completely POSIX
compliant yet, in respect to the dot and where the dot is placed,
i hope i can get that done for S-nail v14.8.
So why don't you simply let Red Hat switch over to S-nail, it
really has seen quite many bugfixes, extensions and improvements,
and it *is* getting better.
And i actually bought Red Hat before it was at the Wall Street :)
(and used the telephone support only once; but then went to Red
Hat-based Halloween Linux).
I'll attach the patch (it is on the [next] branch of S-nail, but
should cleanly apply to the last release, of S-nail, that is).
Ciao,
--steffen
commit 4e40cac
Author: Steffen (Daode) Nurpmeso <[email protected]>
Date: 2014-08-20 16:03:09 +0200
[-] Fix `headers' command (Jan Chaloupka)..
Jan Chaloupka reported on nail-devel@ mess with the `headers'
command, which is falsely documented but acts completely insane
indeed (if anything else but no arguments is requested).
So here is a first implementation that fixes the reported issue by
giving `0', `-', `+' and `$' special meaning (just as for `z'
a.k.a. scrolling) and also being POSIX compliant in that "headers
MSG" will now scroll to around `MSG'.
XXX Handling of dot is not yet compliant and overall insane.
XXX A given message will not be placed at screen top (POSIX).
---
cmd1.c | 296 +++++++++++++++++++++++++++++++++++++------------------------
cmd_tab.h | 7 +-
lex.c | 2 +-
nail.1 | 11 ++-
nailfuns.h | 5 +-
thread.c | 6 +-
6 files changed, 198 insertions(+), 129 deletions(-)
diff --git a/cmd1.c b/cmd1.c
index 455558e..f38c48a 100644
--- a/cmd1.c
+++ b/cmd1.c
@@ -67,8 +67,13 @@ static char * __subject(struct message *mp, bool_t threaded,
static int __putindent(FILE *fp, struct message *mp, int maxwidth);
static int _dispc(struct message *mp, char const *a);
+
+/* Shared `z' implementation */
static int _scroll1(char *arg, int onlynew);
+/* Shared `headers' implementation */
+static int _headers(int msgspec);
+
/* Show the requested messages */
static int _type1(int *msgvec, bool_t doign, bool_t dopage, bool_t dopipe,
bool_t dodecode, char *cmd, off_t *tstats);
@@ -642,11 +647,14 @@ _dispc(struct message *mp, char const *a)
static int
_scroll1(char *arg, int onlynew)
{
- int cur[1], size;
+ int msgspec, size;
NYD_ENTER;
- cur[0] = onlynew ? -1 : 0;
+ msgspec = onlynew ? -1 : 0;
size = screensize();
+
+ if (arg[0] != '\0' && arg[1] != '\0')
+ goto jerr;
switch (*arg) {
case '1': case '2': case '3': case '4': case '5':
case '6': case '7': case '8': case '9': case '0':
@@ -669,7 +677,6 @@ jscroll_forward:
printf(_("On last screenful of messages\n"));
}
break;
-
case '-':
if (arg[1] == '\0')
--_screen;
@@ -679,22 +686,151 @@ jscroll_forward:
_screen = 0;
printf(_("On first screenful of messages\n"));
}
- if (cur[0] == -1)
- cur[0] = -2;
+ if (msgspec == -1)
+ msgspec = -2;
break;
-
default:
+jerr:
fprintf(stderr, _("Unrecognized scrolling command \"%s\"\n"), arg);
size = 1;
goto jleave;
}
- size = c_headers(cur);
+
+ size = _headers(msgspec);
jleave:
NYD_LEAVE;
return size;
}
static int
+_headers(int msgspec) /* FIXME msgspec specials; POSIX compliance <-> dot */
+{
+ ui32_t flag;
+ int g, k, mesg, size, lastg = 1;
+ struct message *mp, *mq, *lastmq = NULL;
+ enum mflag fl = MNEW | MFLAGGED;
+ NYD_ENTER;
+
+ time_current_update(&time_current, FAL0);
+
+ flag = 0;
+ size = screensize();
+ if (_screen < 0)
+ _screen = 0;
+ if (msgspec <= 0)
+ k = _screen * size;
+ else
+ k = msgspec;
+ if (k >= msgCount)
+ k = msgCount - size;
+ if (k < 0)
+ k = 0;
+
+ if (mb.mb_threaded == 0) {
+ g = 0;
+ mq = message;
+ for (mp = message; PTRCMP(mp, <, message + msgCount); ++mp)
+ if (visible(mp)) {
+ if (g % size == 0)
+ mq = mp;
+ if (mp->m_flag & fl) {
+ lastg = g;
+ lastmq = mq;
+ }
+ if ((msgspec > 0 && PTRCMP(mp, ==, message + msgspec - 1)) ||
+ (msgspec == 0 && g == k) ||
+ (msgspec == -2 && g == k + size && lastmq) ||
+ (msgspec < 0 && g >= k && (mp->m_flag & fl) != 0))
+ break;
+ g++;
+ }
+ if (lastmq && (msgspec == -2 ||
+ (msgspec == -1 && PTRCMP(mp, ==, message + msgCount)))) {
+ g = lastg;
+ mq = lastmq;
+ }
+ _screen = g / size;
+ mp = mq;
+ mesg = (int)PTR2SIZE(mp - message);
+ if (PTRCMP(dot, !=, message + msgspec - 1)) { /* TODO really?? */
+ for (mq = mp; PTRCMP(mq, <, message + msgCount); ++mq)
+ if (visible(mq)) {
+ setdot(mq);
+ break;
+ }
+ }
+#ifdef HAVE_IMAP
+ if (mb.mb_type == MB_IMAP)
+ imap_getheaders(mesg + 1, mesg + size);
+#endif
+ srelax_hold();
+ for (; PTRCMP(mp, <, message + msgCount); ++mp) {
+ ++mesg;
+ if (!visible(mp))
+ continue;
+ if (UICMP(32, flag++, >=, size))
+ break;
+ _print_head(0, mesg, stdout, 0);
+ srelax();
+ }
+ srelax_rele();
+ } else { /* threaded */
+ g = 0;
+ mq = threadroot;
+ for (mp = threadroot; mp; mp = next_in_thread(mp))
+ if (visible(mp) &&
+ (mp->m_collapsed <= 0 ||
+ PTRCMP(mp, ==, message + msgspec - 1))) {
+ if (g % size == 0)
+ mq = mp;
+ if (mp->m_flag & fl) {
+ lastg = g;
+ lastmq = mq;
+ }
+ if ((msgspec > 0 && PTRCMP(mp, ==, message + msgspec - 1)) ||
+ (msgspec == 0 && g == k) ||
+ (msgspec == -2 && g == k + size && lastmq) ||
+ (msgspec < 0 && g >= k && (mp->m_flag & fl) != 0))
+ break;
+ g++;
+ }
+ if (lastmq && (msgspec == -2 ||
+ (msgspec == -1 && PTRCMP(mp, ==, message + msgCount)))) {
+ g = lastg;
+ mq = lastmq;
+ }
+ _screen = g / size;
+ mp = mq;
+ if (PTRCMP(dot, !=, message + msgspec - 1)) { /* TODO really?? */
+ for (mq = mp; mq; mq = next_in_thread(mq))
+ if (visible(mq) && mq->m_collapsed <= 0) {
+ setdot(mq);
+ break;
+ }
+ }
+ srelax_hold();
+ while (mp) {
+ if (visible(mp) &&
+ (mp->m_collapsed <= 0 ||
+ PTRCMP(mp, ==, message + msgspec - 1))) {
+ if (UICMP(32, flag++, >=, size))
+ break;
+ _print_head(flag - 1, PTR2SIZE(mp - message + 1), stdout,
+ mb.mb_threaded);
+ srelax();
+ }
+ mp = next_in_thread(mp);
+ }
+ srelax_rele();
+ }
+
+ if (!flag)
+ printf(_("No more mail.\n"));
+ NYD_LEAVE;
+ return !flag;
+}
+
+static int
_type1(int *msgvec, bool_t doign, bool_t dopage, bool_t dopipe,
bool_t dodecode, char *cmd, off_t *tstats)
{
@@ -879,123 +1015,47 @@ c_cmdnotsupp(void *v) /* TODO -> lex.c */
FL int
c_headers(void *v)
{
- ui32_t flag;
- int *msgvec = v, g, k, n, mesg, size, lastg = 1;
- struct message *mp, *mq, *lastmq = NULL;
- enum mflag fl = MNEW | MFLAGGED;
+ char const *args = v;
+ int rv;
NYD_ENTER;
- time_current_update(&time_current, FAL0);
-
- flag = 0;
- size = screensize();
- n = msgvec[0]; /* n == {-2, -1, 0}: called from scroll() */
- if (_screen < 0)
- _screen = 0;
- k = _screen * size;
- if (k >= msgCount)
- k = msgCount - size;
- if (k < 0)
- k = 0;
-
- if (mb.mb_threaded == 0) {
- g = 0;
- mq = message;
- for (mp = message; PTRCMP(mp, <, message + msgCount); ++mp)
- if (visible(mp)) {
- if (g % size == 0)
- mq = mp;
- if (mp->m_flag & fl) {
- lastg = g;
- lastmq = mq;
- }
- if ((n > 0 && PTRCMP(mp, ==, message + n - 1)) ||
- (n == 0 && g == k) || (n == -2 && g == k + size && lastmq) ||
- (n < 0 && g >= k && (mp->m_flag & fl) != 0))
- break;
- g++;
- }
- if (lastmq && (n == -2 ||
- (n == -1 && PTRCMP(mp, ==, message + msgCount)))) {
- g = lastg;
- mq = lastmq;
- }
- _screen = g / size;
- mp = mq;
- mesg = (int)PTR2SIZE(mp - message);
- if (PTRCMP(dot, !=, message + n - 1)) {
- for (mq = mp; PTRCMP(mq, <, message + msgCount); ++mq)
- if (visible(mq)) {
- setdot(mq);
- break;
- }
- }
-#ifdef HAVE_IMAP
- if (mb.mb_type == MB_IMAP)
- imap_getheaders(mesg + 1, mesg + size);
-#endif
- srelax_hold();
- for (; PTRCMP(mp, <, message + msgCount); ++mp) {
- ++mesg;
- if (!visible(mp))
- continue;
- if (UICMP(32, flag++, >=, size))
- break;
- _print_head(0, mesg, stdout, 0);
- srelax();
- }
- srelax_rele();
- } else { /* threaded */
- g = 0;
- mq = threadroot;
- for (mp = threadroot; mp; mp = next_in_thread(mp))
- if (visible(mp) &&
- (mp->m_collapsed <= 0 || PTRCMP(mp, ==, message + n - 1))) {
- if (g % size == 0)
- mq = mp;
- if (mp->m_flag & fl) {
- lastg = g;
- lastmq = mq;
- }
- if ((n > 0 && PTRCMP(mp, ==, message + n - 1)) ||
- (n == 0 && g == k) || (n == -2 && g == k + size && lastmq) ||
- (n < 0 && g >= k && (mp->m_flag & fl) != 0))
- break;
- g++;
- }
- if (lastmq && (n == -2 ||
- (n == -1 && PTRCMP(mp, ==, message + msgCount)))) {
- g = lastg;
- mq = lastmq;
- }
- _screen = g / size;
- mp = mq;
- if (PTRCMP(dot, !=, message + n - 1)) {
- for (mq = mp; mq; mq = next_in_thread(mq))
- if (visible(mq) && mq->m_collapsed <= 0) {
- setdot(mq);
- break;
- }
- }
- srelax_hold();
- while (mp) {
- if (visible(mp) &&
- (mp->m_collapsed <= 0 || PTRCMP(mp, ==, message + n - 1))) {
- if (UICMP(32, flag++, >=, size))
- break;
- _print_head(flag - 1, PTR2SIZE(mp - message + 1), stdout,
- mb.mb_threaded);
- srelax();
- }
- mp = next_in_thread(mp);
+ if (*args == '\0')
+ rv = 0;
+ /* Used as `z' alias? */
+ else if (args[1] == '\0' &&
+ (*args == '0' || *args == '-' || *args == '+' || *args == '$')) {
+ rv = _scroll1(v, 0);
+ goto jleave;
+ } else {
+ /* Must be a single message, parse number off command line */
+ char *eptr;
+ long m;
+
+ if ((m = strtol(args, &eptr, 10)) <= 0 || m >= msgCount ||
+ *eptr != '\0') {
+ fprintf(stderr, _("Invalid `headers' argument: `%s'\n"), args);
+ rv = 1;
+ goto jleave;
}
- srelax_rele();
+ rv = (int)m;
+ dot = message + rv - 1; /* TODO; AND: doesn't end at screentop (POSIX) */
}
+ rv = _headers(rv);
+jleave:
+ NYD_LEAVE;
+ return rv;
+}
- if (!flag)
- printf(_("No more mail.\n"));
+FL int
+print_header_group(int *vector)
+{
+ int rv;
+ NYD_ENTER;
+
+ assert(vector != NULL && vector != (void*)-1);
+ rv = _headers(vector[0]);
NYD_LEAVE;
- return !flag;
+ return rv;
}
FL int
diff --git a/cmd_tab.h b/cmd_tab.h
index 019bf9a..809cefe 100644
--- a/cmd_tab.h
+++ b/cmd_tab.h
@@ -158,11 +158,12 @@
{ "folders", &c_folders, (T | M | RAWLIST), 0, 1
DS(N_("List mailboxes below the given or the global folder")) },
{ "z", &c_scroll, (A | M | STRLIST), 0, 0
- DS(N_("Scroll to next/previous window of headers")) },
+ DS(N_("Scroll header display as indicated by the argument (0,-,+,$)")) },
{ "Z", &c_Scroll, (A | M | STRLIST), 0, 0
DS(N_("Like \"z\", but continues to the next flagged message")) },
- { "headers", &c_headers, (A | MSGLIST), 0, MMNDEL
- DS(N_("Show the current(/last/next) 18-message group of headers")) },
+ { "headers", &c_headers, (A | M | STRLIST), 0, 0
+ DS(N_("Show the current group of headers "
+ "(after setting dot to <message>, if given)")) },
{ "help", &c_help, (H | M | RAWLIST), 0, 1
DS(N_("Show command help (for the given one)")) },
{ "?", &c_help, (H | M | RAWLIST), 0, 1
diff --git a/lex.c b/lex.c
index be05ccc..f5b107b 100644
--- a/lex.c
+++ b/lex.c
@@ -1142,7 +1142,7 @@ announce(int printheaders)
dot = message + mdot - 1;
if (printheaders && msgCount > 0 && ok_blook(header)) {
++_lex_inithdr;
- c_headers(vec); /* XXX errors? */
+ print_header_group(vec); /* XXX errors? */
_lex_inithdr = 0;
}
NYD_LEAVE;
diff --git a/nail.1 b/nail.1
index 63e5428..4edf1e7 100644
--- a/nail.1
+++ b/nail.1
@@ -1866,9 +1866,14 @@ Also see
.Dl ? ghost ls '!ls -latro'
.Dl ? ls /usr/local
.It Ic headers
-(h) Lists the current range of headers, which is an 18-message group.
-If a `+' argument is given the next 18-message group is printed,
-likewise the previous is printed if the argument was `-'.
+(h) Show the current group of headers, the size of which depends on
+the variable
+.Va screen .
+If a valid message is specified this will first become the new dot and
+define the new current group of headers.
+The special values `0', `-', `+' and `$' have the same meaning as for
+the scrolling command
+.Ic z .
.It Ic help
A synonym for
.Ic \&? .
diff --git a/nailfuns.h b/nailfuns.h
index a5e833c..c0ec32e 100644
--- a/nailfuns.h
+++ b/nailfuns.h
@@ -438,9 +438,12 @@ FL bool_t _smemcheck(char const *file, int line);
FL int c_cmdnotsupp(void *v);
-/* Show header group */
+/* `headers' (show header group, possibly after setting dot) */
FL int c_headers(void *v);
+/* Like c_headers(), but pre-prepared message vector */
+FL int print_header_group(int *vector);
+
/* Scroll to the next/previous screen */
FL int c_scroll(void *v);
FL int c_Scroll(void *v);
diff --git a/thread.c b/thread.c
index 75a2999..c33545f 100644
--- a/thread.c
+++ b/thread.c
@@ -520,7 +520,7 @@ c_thread(void *vp)
}
if (vp != NULL && vp != (void*)-1 && !inhook && ok_blook(header))
- rv = c_headers(vp);
+ rv = print_header_group(vp);
else
rv = 0;
NYD_LEAVE;
@@ -542,7 +542,7 @@ c_unthread(void *vp)
m->m_collapsed = 0;
if (vp && !inhook && ok_blook(header))
- rv = c_headers(vp);
+ rv = print_header_group(vp);
else
rv = 0;
NYD_LEAVE;
@@ -795,7 +795,7 @@ jmethok:
}
ac_free(ms);
i = ((vp != NULL && vp != (void*)-1 && !inhook && ok_blook(header))
- ? c_headers(msgvec) : 0);
+ ? print_header_group(msgvec) : 0);
jleave:
NYD_LEAVE;
return i;
------------------------------------------------------------------------------
Slashdot TV.
Video for Nerds. Stuff that matters.
http://tv.slashdot.org/
_______________________________________________
S-nail-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/s-nail-users