} // end: hex_make
+ /*
+ * The sructure hung from a WIN_t when 'other' filtering is active. */
+struct osel_s {
+ int flg; // include == 1, exclude == 0
+ FLG_t enu; // field (procflag) to filter
+ char *val; // value included or excluded
+ char *(*cmp)(const char *, const char *); // string comparison function
+ char *raw; // raw user input (dup check)
+ struct osel_s *nxt; // the next criteria or NULL.
+};
+
+
+ /*
+ * A function to turn off any 'other' filtering in the given window */
+static void osel_clear (WIN_t *q) {
+ struct osel_s *osel = q->osel_1st;
+
+ while (osel) {
+ struct osel_s *nxt = osel->nxt;
+ free(osel->val);
+ free(osel->raw);
+ free(osel);
+ osel = nxt;
+ }
+ q->osel_tot = 0;
+ q->osel_1st = NULL;
+ free (q->osel_prt);
+ q->osel_prt = NULL;
+#ifndef USE_X_COLHDR
+ OFFw(Curwin, NOHISEL_xxx);
+#endif
+} // end: osel_clear
+
+
+ /*
+ * Determine if there's a matching value among the 'other' criteria
+ * in a given window -- it's called from only one place, and likely
+ * inlined even without the directive */
+static inline int osel_matched (const WIN_t *q, FLG_t enu, const char *str) {
+ struct osel_s *osel = q->osel_1st;
+
+ while (osel) {
+ if (osel->enu == enu) {
+ char *p = osel->cmp(str, osel->val);
+ if (p && !osel->flg) return 0;
+ if (!p && osel->flg) return 0;
+ }
+ osel = osel->nxt;
+ }
+ return 1;
+} // end: osel_matched
+
+
/*
* Validate the passed string as a user name or number,
* and/or update the window's 'u/U' selection stuff. */
break;
}
#ifndef USE_X_COLHDR
- OFFw(w, NOHIFND_xxx);
+ OFFw(w, NOHIFND_xxx | NOHISEL_xxx);
#endif
} // end: for (GROUPSMAX)
for (i = 0; i < P_MAXPFLGS; i++)
if (!STRCMP(cp, N_col(i))) break;
if (i == P_MAXPFLGS)
- error_exit(fmtmk(N_fmt(XTRA_sortopt_fmt), cp));
+ error_exit(fmtmk(N_fmt(XTRA_badflds_fmt), cp));
OFFw(Curwin, Show_FOREST);
Curwin->rc.sortindx = i;
cp += strlen(cp);
q->rc.maxtasks = q->usrseltyp = q->begpflg = q->begtask = 0;
#endif
Monpidsidx = 0;
+ osel_clear(q);
} // end: win_reset
if (Curwin->findstr[0]) {
SETw(Curwin, INFINDS_xxx);
for (i = Curwin->begtask; i < Frame_maxtask; i++) {
- if (-1 < find_ofs(Curwin, task_show(Curwin, Curwin->ppt[i]))) {
+ const char *row = task_show(Curwin, Curwin->ppt[i]);
+ if (*row && -1 < find_ofs(Curwin, row)) {
found = 1;
if (i == Curwin->begtask) continue;
Curwin->begtask = i;
} // end: help_view
+static void other_selection (int ch) {
+ char *(*cmp)(const char *, const char *);
+ char raw[MEDBUFSIZ], *glob, *pval;
+ struct osel_s *osel;
+ const char *typ;
+ int flg, enu;
+
+ if (ch == 'o') {
+ typ = N_txt(OSEL_casenot_txt);
+ cmp = strcasestr;
+ } else {
+ typ = N_txt(OSEL_caseyes_txt);
+ cmp = strstr;
+ }
+ glob = ioline(fmtmk(N_fmt(OSEL_prompts_fmt), Curwin->osel_tot + 1, typ));
+ if (!snprintf(raw, sizeof(raw), "%s", glob)) return;
+ for (osel = Curwin->osel_1st; osel; ) {
+ if (!strcmp(osel->raw, glob)) { // #1: is criteria duplicate?
+ show_msg(N_txt(OSEL_errdups_txt));
+ return;
+ }
+ osel = osel->nxt;
+ }
+ if (*glob != '!') flg = 1; // #2: is it include/exclude?
+ else { ++glob; flg = 0; }
+ if (!(pval = strchr(glob, ':'))) { // #3: do we see a delimiter?
+ show_msg(fmtmk(N_fmt(OSEL_errdelm_fmt)
+ , flg ? N_txt(WORD_include_txt) : N_txt(WORD_exclude_txt)));
+ return;
+ }
+ *(pval++) = '\0';
+ for (enu = 0; enu < P_MAXPFLGS; enu++) // #4: is this a valid field?
+ if (!STRCMP(N_col(enu), glob)) break;
+ if (enu == P_MAXPFLGS) {
+ show_msg(fmtmk(N_fmt(XTRA_badflds_fmt), glob));
+ return;
+ }
+ if (!(*pval)) { // #5: did we get some value?
+ show_msg(fmtmk(N_fmt(OSEL_errvalu_fmt)
+ , flg ? N_txt(WORD_include_txt) : N_txt(WORD_exclude_txt)));
+ return;
+ }
+ osel = alloc_c(sizeof(struct osel_s));
+ osel->flg = flg;
+ osel->enu = enu;
+ osel->val = alloc_s(pval);
+ osel->cmp = cmp;
+ osel->raw = alloc_s(raw);
+ osel->nxt = Curwin->osel_1st;
+ Curwin->osel_1st = osel;
+ Curwin->osel_tot += 1;
+ if (!Curwin->osel_prt) Curwin->osel_prt = alloc_c(strlen(raw) + 3);
+ else Curwin->osel_prt = alloc_r(Curwin->osel_prt, strlen(Curwin->osel_prt) + strlen(raw) + 6);
+ strcat(Curwin->osel_prt, fmtmk("%s'%s'", (Curwin->osel_tot > 1) ? " + " : "", raw));
+#ifndef USE_X_COLHDR
+ SETw(Curwin, NOHISEL_xxx);
+#endif
+} // end: other_selection
+
+
static void write_rcfile (void) {
FILE *fp;
int i;
? N_txt(ON_word_only_txt) : N_txt(OFF_one_word_txt)));
}
break;
+ case 'O':
+ case 'o':
+ if (VIZCHKw(w)) other_selection(ch);
+ break;
case 'U':
case 'u':
if (VIZCHKw(w)) {
capsmk(w);
}
break;
+ case kbd_CtrlO:
+ if (VIZCHKw(w))
+ ioline(fmtmk(N_fmt(OSEL_statlin_fmt)
+ , w->osel_prt ? w->osel_prt : N_txt(WORD_noneone_txt)));
+ break;
default: // keep gcc happy
break;
}
break;
case '&':
case 'L':
- if (VIZCHKw(w)) { // ( next 2 are strictly for the UI )
- SETw(w, Show_IDLEPS); // make sure we're showing idle tasks
- w->usrseltyp = 0; // make sure we're not user filtering
- find_string(ch); // ( we'll search entire ppt anyway )
- }
+ if (VIZCHKw(w)) find_string(ch);
break;
case 'A':
Rc.mode_altscr = !Rc.mode_altscr;
{ keys_summary,
{ '1', 'C', 'l', 'm', 't', '\0' } },
{ keys_task,
- { '#', '<', '>', 'b', 'c', 'i', 'J', 'j', 'n', 'R', 'S'
- , 'U', 'u', 'V', 'x', 'y', 'z', '\0' } },
+ { '#', '<', '>', 'b', 'c', 'i', 'J', 'j', 'n', 'O', 'o'
+ , 'R', 'S', 'U', 'u', 'V', 'x', 'y', 'z'
+ , kbd_CtrlO, '\0' } },
{ keys_window,
{ '+', '-', '=', '_', '&', 'A', 'a', 'G', 'L', 'w'
, kbd_UP, kbd_DOWN, kbd_LEFT, kbd_RIGHT, kbd_PGUP, kbd_PGDN
case X_XON:
case X_XOF:
cp = NULL;
- if (!CHKw(q, INFINDS_xxx | NOHIFND_xxx)) {
+ if (!CHKw(q, INFINDS_xxx | NOHIFND_xxx | NOHISEL_xxx)) {
/* treat running tasks specially - entire row may get highlighted
so we needn't turn it on and we MUST NOT turn it off */
if (!('R' == p->state && CHKw(q, Show_HIROWS)))
} // end: switch 'procflag'
- if (cp)
+ if (cp) {
+ if (q->osel_tot && !osel_matched(q, i, cp)) return "";
rp = scat(rp, cp);
-
+ }
#undef S
#undef W
#undef Js
checking some stuff with each iteration and check it just once... */
if (CHKw(q, Show_IDLEPS) && !q->usrseltyp)
while (i < Frame_maxtask && lwin < wmax) {
- task_show(q, q->ppt[i++]);
- ++lwin;
+ if (*task_show(q, q->ppt[i++]))
+ ++lwin;
}
else
while (i < Frame_maxtask && lwin < wmax) {
if ((CHKw(q, Show_IDLEPS) || isBUSY(q->ppt[i]))
- && user_matched(q, q->ppt[i])) {
- task_show(q, q->ppt[i]);
+ && user_matched(q, q->ppt[i])
+ && *task_show(q, q->ppt[i++]))
++lwin;
- }
++i;
}
#define linux_version_code LINUX_VERSION(2,5,43)
#endif
-#ifdef STRINGCASENO
// pretend as if #define _GNU_SOURCE
char *strcasestr(const char *haystack, const char *needle);
+
+#ifdef STRINGCASENO
#define STRSTR strcasestr
#define STRCMP strcasecmp
#else
#define kbd_BKSP 137
#define kbd_INS 138
#define kbd_DEL 139
+#define kbd_CtrlO '\017'
/* Special value in Pseudo_row to force an additional procs refresh
-- used at startup and for task/thread mode transitions */
#define INFINDS_xxx 0x010000 // build rows for find_string, not display
#define EQUWINS_xxx 0x000001 // rebalance all wins & tasks (off i,n,u/U)
#ifndef USE_X_COLHDR
-#define NOHIFND_xxx 0x100000 // must restrict Show_HICOLS temporarily
+#define NOHISEL_xxx 0x200000 // restrict Show_HICOLS for osel temporarily
+#define NOHIFND_xxx 0x100000 // restrict Show_HICOLS for find temporarily
#endif
// Default flags if there's no rcfile to provide user customizations
columnhdr [SCREENMAX], // column headings for procflgs
#endif
*captab [CAPTABMAX]; // captab needed by show_special()
+ struct osel_s *osel_1st; // other selection criteria anchor
+ int osel_tot; // total of other selection criteria
+ char *osel_prt; // other stuff printable as status line
char *findstr; // window's current/active search string
int findlen; // above's strlen, without call overhead
proc_t **ppt; // this window's proc_t ptr array
//atic float get_float (const char *prompt);
//atic int get_int (const char *prompt);
//atic inline const char *hex_make (KLONG num, int noz);
+//atic void osel_clear (WIN_t *q);
+//atic inline int osel_matched (const WIN_t *q, FLG_t enu, const char *str);
//atic const char *user_certify (WIN_t *q, const char *str, char typ);
//atic inline int user_matched (const WIN_t *q, const proc_t *p);
/*------ Basic Formatting support --------------------------------------*/
//atic inline int find_ofs (const WIN_t *q, const char *buf);
//atic void find_string (int ch);
//atic void help_view (void);
+//atic void other_selection (int ch);
//atic void write_rcfile (void);
/*------ Interactive Input Secondary support (do_key helpers) ----------*/
//atic void keys_global (int ch);
Norm_nlstab[FIND_no_find_fmt] = _("%s\"%s\" not found");
Norm_nlstab[XTRA_fixwide_fmt] = _("width incr is %d, change to (0 default, -1 auto)");
Norm_nlstab[XTRA_warncfg_txt] = _("Overwrite existing obsolete/corrupted rcfile?");
- Norm_nlstab[XTRA_sortopt_fmt] = _("unrecognized field name '%s'");
+ Norm_nlstab[XTRA_badflds_fmt] = _("unrecognized field name '%s'");
Norm_nlstab[XTRA_winsize_txt] = _("even using field names only, window is now too small");
#ifndef INSP_OFFDEMO
Norm_nlstab[YINSP_demo01_txt] = _("Open Files");
Norm_nlstab[YINSP_rcfile_fmt] = _("could not parse rcfile inspect entry %d");
Norm_nlstab[YINSP_status_fmt] = _("%s: %*d-%-*d lines, %*d-%*d columns, %lu bytes read");
Norm_nlstab[YINSP_workin_txt] = _("patience please, working...");
+/* Translation Hint: Below are 2 abbreviations which can be as long as needed:
+ . FLD = FIELD, VAL = VALUE */
+ Norm_nlstab[OSEL_prompts_fmt] = _("add filter #%d (%s) as: [!]FLD:VAL");
+ Norm_nlstab[OSEL_casenot_txt] = _("ignoring case");
+ Norm_nlstab[OSEL_caseyes_txt] = _("case sensitive");
+ Norm_nlstab[OSEL_errdups_txt] = _("duplicate filter was ignored");
+ Norm_nlstab[OSEL_errdelm_fmt] = _("'%s' filter delimiter is missing");
+ Norm_nlstab[OSEL_errvalu_fmt] = _("'%s' filter value is missing");
+ Norm_nlstab[WORD_include_txt] = _("include");
+ Norm_nlstab[WORD_exclude_txt] = _("exclude");
+ Norm_nlstab[OSEL_statlin_fmt] = _("<Enter> to resume, filters = %s");
+ Norm_nlstab[WORD_noneone_txt] = _("none");
}
" c,i,S,j . Toggle: '~1c~2' Cmd name/line; '~1i~2' Idle; '~1S~2' Time; '~1j~2' Str justify\n"
" x~5,~1y~5 . Toggle highlights: '~1x~2' sort field; '~1y~2' running tasks\n"
" z~5,~1b~5 . Toggle: '~1z~2' color/mono; '~1b~2' bold/reverse (only if 'x' or 'y')\n"
- " u,U . Filter by: '~1u~2' effective user; '~1U~2' effective/file/real/saved user\n"
- " n or # . Set maximum tasks displayed\n"
+ " u,U,o,O . Filter by: '~1u~2'/'~1U~2' effective/any user; '~1o~2'/'~1O~2' other criteria\n"
+ " n,#,^O . Set: '~1n~2'/'~1#~2' max tasks displayed; Show: ~1Ctrl~2+'~1O~2' other filter(s)\n"
" C,... . Toggle scroll coordinates msg for: ~1up~2,~1down~2,~1left~2,~1right~2,~1home~2,~1end~2\n"
"\n"
"%s"
GET_sigs_num_fmt, GET_user_ids_txt, HELP_cmdline_fmt, HILIGHT_cant_txt,
IRIX_curmode_fmt, LIMIT_exceed_fmt, MISSING_args_fmt, NAME_windows_fmt,
NOT_onsecure_txt, NOT_smp_cpus_txt, OFF_one_word_txt, ON_word_only_txt,
- RC_bad_entry_fmt, RC_bad_files_fmt, SCROLL_coord_fmt, SELECT_clash_txt,
- THREADS_show_fmt, TIME_accumed_fmt, UNKNOWN_cmds_txt, UNKNOWN_opts_fmt,
- USAGE_abbrev_txt, WORD_allcpus_txt, WORD_another_txt, WORD_eachcpu_fmt,
- WORD_process_txt, WORD_threads_txt, WRITE_rcfile_fmt, WRONG_switch_fmt,
- XTRA_fixwide_fmt, XTRA_sortopt_fmt, XTRA_warncfg_txt, XTRA_winsize_txt,
+ OSEL_casenot_txt, OSEL_caseyes_txt, OSEL_errdelm_fmt, OSEL_errdups_txt,
+ OSEL_errvalu_fmt, OSEL_prompts_fmt, OSEL_statlin_fmt, RC_bad_entry_fmt,
+ RC_bad_files_fmt, SCROLL_coord_fmt, SELECT_clash_txt, THREADS_show_fmt,
+ TIME_accumed_fmt, UNKNOWN_cmds_txt, UNKNOWN_opts_fmt, USAGE_abbrev_txt,
+ WORD_allcpus_txt, WORD_another_txt, WORD_eachcpu_fmt, WORD_exclude_txt,
+ WORD_include_txt, WORD_noneone_txt, WORD_process_txt, WORD_threads_txt,
+ WRITE_rcfile_fmt, WRONG_switch_fmt, XTRA_badflds_fmt, XTRA_fixwide_fmt,
+ XTRA_warncfg_txt, XTRA_winsize_txt,
#ifndef INSP_OFFDEMO
YINSP_demo01_txt, YINSP_demo02_txt, YINSP_demo03_txt, YINSP_deqfmt_txt,
YINSP_deqtyp_txt, YINSP_dstory_txt,