diff --git a/.gitignore b/.gitignore index 33e2c40..e2ea07a 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ stamp-* *.stackdump *~ valgrind* +*.#* diff --git a/.travis.yml b/.travis.yml index 5199572..97793f2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ language: c script: - "./bootstrap" -- "./configure" +- "./configure --with-selinux" - make before_install: -- sudo apt-get install -y libconfig-dev +- sudo apt-get install -y libconfig-dev libacl1-dev libselinux1-dev diff --git a/Makefile.am b/Makefile.am index 2875e11..048ded5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,12 +3,26 @@ AUTOMAKE_OPTIONS = foreign dfshowconfdir = $(sysconfdir) dfshowdatadir = $(datadir)/dfshow -AM_CFLAGS = -DSYSCONFIG=\"$(dfshowconfdir)\" -DDATADIR=\"$(dfshowdatadir)\" -D_XOPEN_SOURCE_EXTENDED +AM_CFLAGS = -DSYSCONFIG=\"$(dfshowconfdir)\" -DDATADIR=\"$(dfshowdatadir)\" -D_XOPEN_SOURCE_EXTENDED -fno-common + +LDADD = -lm -lconfig if DARWIN -LDADD = -lncurses -lm -lconfig +LDADD += -lncurses else -LDADD = -lncursesw -lm -lconfig -ltinfo +LDADD += -lncursesw +endif + +if LINUX +LDADD += -lacl -ltinfo +endif + +if HURD +LDADD += -lacl -ltinfo +endif + +if SELINUX +LDADD += -lselinux endif bin_PROGRAMS = $(top_builddir)/bin/show $(top_builddir)/bin/sf diff --git a/conf/dfshow.conf b/conf/dfshow.conf index 277f2d0..7fce055 100644 --- a/conf/dfshow.conf +++ b/conf/dfshow.conf @@ -41,6 +41,10 @@ show: group = 1; author = 0; }; + # Show security context of objects (default: 0) + context = 0; + # Skip naviation items if at the top of list (default: 0) + skip-to-first = 0; }; sf: diff --git a/configure.ac b/configure.ac index 93fc87a..d10edb1 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([dfshow], [0.8.2], [https://github.com/roberthawdon/dfshow/issues]) +AC_INIT([dfshow], [0.9.0], [https://github.com/roberthawdon/dfshow/issues]) AC_GNU_SOURCE AM_INIT_AUTOMAKE([subdir-objects]) AC_PROG_CC @@ -6,12 +6,50 @@ AC_PROG_CC_STDC AC_CONFIG_HEADERS([config.h:config.hin]) AC_SUBST([AM_LDFLAGS]) +# Check for ACL_TYPE_NFS4 +AC_CHECK_DECL([ACL_TYPE_NFS4], + [AC_DEFINE(HAVE_ACL_TYPE_NFS4, 1, [True for FreeBSD with NFSv4 ACL support])], + [], + [#include ]) +# MacOS has an acl.h that isn't POSIX. It can be detected by +# checking for ACL_USER +AC_CHECK_DECL([ACL_USER], + [AC_DEFINE(HAVE_ACL_USER, 1, [True for systems with POSIX ACL support])], + [], + [#include ]) +# MacOS has ACL_TYPE_EXTENDED instead +AC_CHECK_DECL([ACL_TYPE_EXTENDED], + [AC_DEFINE(HAVE_ACL_TYPE_EXTENDED, 1, [True for MacOS ACL support])], + [], + [#include + #include ]) +# Solaris and derivates ACLs +AC_CHECK_LIB([sec], [acl_get]) +AC_CHECK_TYPES([aclent_t], [], [], [[#include ]]) +AC_CHECK_TYPES([ace_t], [], [], [[#include ]]) +AC_CHECK_FUNCS(acl_get facl_get acl_set facl_set) + + AC_CHECK_MEMBERS([struct stat.st_author]) -AC_CHECK_HEADERS([stdio.h limits.h signal.h ctype.h wctype.h getopt.h sys/types.h sys/stat.h dirent.h fcntl.h pwd.h string.h stdlib.h unistd.h time.h sys/statvfs.h libgen.h errno.h wchar.h hurd.h math.h sys/sysmacros.h regex.h utime.h]) +AC_CHECK_HEADERS([stdio.h limits.h signal.h ctype.h wctype.h getopt.h sys/types.h sys/stat.h dirent.h fcntl.h pwd.h string.h stdlib.h unistd.h time.h sys/statvfs.h libgen.h errno.h wchar.h hurd.h math.h sys/sysmacros.h regex.h utime.h sys/xattr.h acl/libacl.h]) AC_CHECK_HEADERS(ncurses.h, , AC_MSG_ERROR(ncurses header (ncurses.h) not found. You may need to install an ncurses development package.)) AC_CHECK_HEADERS(libconfig.h, , AC_MSG_ERROR(libconfig header (libconfig.h) not found. You may need to install a libconfig development package.)) +AC_CHECK_HEADERS(sys/acl.h, , AC_MSG_ERROR(libacl header (sys/acl.h) not found. You may need to install a libacl development package.)) -AM_CONDITIONAL([DARWIN], [test $(uname) = "Darwin"]) +AC_ARG_WITH([selinux], AS_HELP_STRING([--with-selinux], [Build with selinux library (default: disabled)])) +AC_ARG_ENABLE([move-between-devices], AS_HELP_STRING([--enable-move-between-devices], [Enable moving objects between mounted devices (default: disabled)])) +AS_IF([test "x$with_selinux" = "xyes"], [ + AC_CHECK_HEADERS(selinux/selinux.h, , AC_MSG_ERROR(selinux header (selinux/selinux.h) not found. You may need to install an selinux development package.)) +]) + +AS_IF([test "x$enable_move_between_devices" = "xyes"], [ + AC_DEFINE(HAVE_MOVE_BETWEEN_DEVICES, 1, [True for enable-move-between-devices]) +]) + +AM_CONDITIONAL([DARWIN], [test $(uname) = "Darwin"]) +AM_CONDITIONAL([LINUX], [test $(uname) = "Linux"]) +AM_CONDITIONAL([HURD], [test $(uname) = "GNU"]) +AM_CONDITIONAL([SELINUX], [test "x$with_selinux" = "xyes"]) AC_CONFIG_FILES([Makefile]) AC_OUTPUT diff --git a/docs/source/conf.py b/docs/source/conf.py index c05f035..7f1a560 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -20,13 +20,13 @@ # -- Project information ----------------------------------------------------- project = 'Directory File Show (DF-SHOW)' -copyright = '2019, Robert Ian Hawdon' +copyright = '2020, Robert Ian Hawdon' author = 'Robert Ian Hawdon' # The short X.Y version -version = '' +version = '0.9' # The full version, including alpha/beta/rc tags -release = '0.8.2-beta' +release = '0.9.0' # -- General configuration --------------------------------------------------- diff --git a/docs/source/installation.rst b/docs/source/installation.rst index 099a8be..e2e3d3d 100644 --- a/docs/source/installation.rst +++ b/docs/source/installation.rst @@ -110,6 +110,8 @@ Download the project and prepare sources. ./bootstrap ./configure +On systems with SELinux, you can enable support for this by passing the ``--with-selinux`` option to configure. + On some BSD systems, you may need to pass extra parameters to configure and build DF-SHOW: .. code-block:: bash diff --git a/docs/source/sf.rst b/docs/source/sf.rst index 3f47387..48a57c6 100644 --- a/docs/source/sf.rst +++ b/docs/source/sf.rst @@ -90,6 +90,9 @@ Further information can be found in the `configuring sf <#configuring-sf>`__ sec ``Ignore Case - Enter string:`` + After a search has been made, the keybinding ``CTRL + F`` will repeat the search + to find further occurrences. + ``Help`` Launches the ``man`` pages for ``sf``. diff --git a/docs/source/show.rst b/docs/source/show.rst index cb6f1af..4422212 100644 --- a/docs/source/show.rst +++ b/docs/source/show.rst @@ -17,6 +17,9 @@ Command line arguments The following options are shared with ``ls``: +``-@`` + Displays extended atributes keys and sizes (macOS only). + ``-a``, ``--all`` Does not ignore files or directories starting with ``.``. The ``.`` and ``..`` objects are never hidden due to their @@ -69,6 +72,12 @@ The following options are shared with ``ls``: ``-U`` Displays output in the order they're found. +``-Z``, ``--context`` + Shows the secuirty context of each file, if one is defined. + +``-1`` + Only shows the file name on display. + ``--help`` Displays help message, then exits. @@ -107,6 +116,9 @@ The following options are specific to ``show``: ``--edit-themes`` Launches ``show`` directly into the theme editor. (colors) +``--skip-to-first`` + Sets the highlighted item to the first object that isn't ``.`` or ``..`` + Commands -------- @@ -615,6 +627,7 @@ The following screen is displayed. [ ] Human readable sizes [ ] Enter key acts like Show < > Owner Column: + [ ] Skip to the first object There are three types of configuration items, each denoted with a different symbol: diff --git a/man/sf.1 b/man/sf.1 index eac029b..76c0cc4 100644 --- a/man/sf.1 +++ b/man/sf.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "SF" "1" "May 2019" "" "" +.TH "SF" "1" "May 2020" "" "" . .SH "NAME" \fBsf\fR \- An interactive file viewer written for Unix\-like systems\. @@ -91,6 +91,9 @@ Following this selection, one of the following prompts will be displayed: .IP \fBIgnore Case \- Enter string:\fR . +.IP +After a search has been made, the keybinding \fBCTRL + F\fR will repeat the search to find further occurrences\. +. .TP \fBHelp\fR Launches the \fBman\fR pages for \fBsf\fR\. @@ -162,7 +165,7 @@ Saves settings for future sessions\. Written by Robert Ian Hawdon\. . .SH "COPYRIGHT" -Copyright (C) 2019 License GPLv3+: GNU GPL version 3 or later \fIhttps://gnu\.org/licenses/gpl\.html\fR\. +Copyright (C) 2020 License GPLv3+: GNU GPL version 3 or later \fIhttps://gnu\.org/licenses/gpl\.html\fR\. . .P This program comes with ABSOLUTELY NO WARRANTY\. This is free software, and you are welcome to redistribute it under certain conditions\. diff --git a/man/sf.1.html b/man/sf.1.html index df2c287..ce6df5f 100644 --- a/man/sf.1.html +++ b/man/sf.1.html @@ -134,7 +134,9 @@

COMMANDS

Match Case - Enter string:

-

Ignore Case - Enter string:

+

Ignore Case - Enter string:

+ +

After a search has been made, the keybinding CTRL + F will repeat the search to find further occurrences.

Help

Launches the man pages for sf.

Position

Position the file window to a specific line of the file or relative from the current file postion. Thew new file postion is requested by the following prompt.

@@ -176,7 +178,7 @@

AUTHOR

-

Copyright (C) 2019 License GPLv3+: GNU GPL version 3 or later https://gnu.org/licenses/gpl.html.

+

Copyright (C) 2020 License GPLv3+: GNU GPL version 3 or later https://gnu.org/licenses/gpl.html.

This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions.

@@ -189,7 +191,7 @@

SEE ALSO

  1. -
  2. May 2019
  3. +
  4. May 2020
  5. sf(1)
diff --git a/man/sf.1.ronn b/man/sf.1.ronn index 65fbb53..1658442 100644 --- a/man/sf.1.ronn +++ b/man/sf.1.ronn @@ -71,6 +71,8 @@ Searches for a string provided in the form of a Regex. Case sensitivity is reque `Ignore Case - Enter string:` + After a search has been made, the keybinding ``CTRL + F`` will repeat the search to find further occurrences. + * `Help`: Launches the `man` pages for `sf`. @@ -120,7 +122,7 @@ Saves settings for future sessions. Written by Robert Ian Hawdon. ## COPYRIGHT -Copyright (C) 2019 License GPLv3+: GNU GPL version 3 or later . +Copyright (C) 2020 License GPLv3+: GNU GPL version 3 or later . This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions. diff --git a/man/show.1 b/man/show.1 index 8bdbdee..ca45c4a 100644 --- a/man/show.1 +++ b/man/show.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "SHOW" "1" "September 2019" "" "" +.TH "SHOW" "1" "May 2020" "" "" . .SH "NAME" \fBshow\fR \- An interactive directory/file browser written for Unix\-like systems\. @@ -15,108 +15,99 @@ DF\-SHOW: An interactive directory/file browser written for Unix\-like systems\. .SH "OPTIONS" The following options are shared with \fBls\fR: . -.TP -\fB\-a\fR, \fB\-\-all\fR -Does not ignore files or directories starting with \fB\.\fR\. The \fB\.\fR and \fB\.\.\fR objects are never hidden due to their navigational functions in \fBshow\fR\. +.IP "\(bu" 4 +\fB\-@\fR Displays extended atributes keys and sizes (macOS only)\. . -.TP -\fB\-\-author\fR -Prints the author of the file in the output\. +.IP "\(bu" 4 +\fB\-a\fR, \fB\-\-all\fR: Does not ignore files or directories starting with \fB\.\fR\. The \fB\.\fR and \fB\.\.\fR objects are never hidden due to their navigational functions in \fBshow\fR\. . -.TP -\fB\-B\fR, \fB\-\-ignore\-backups\fR -Hides files ending in \fB~\fR, often used as backup files\. +.IP "\(bu" 4 +\fB\-\-author\fR: Prints the author of the file in the output\. . -.TP -\fB\-\-color\fR[=\fICOLOR\fR] -Sets colorizing of files and directories\. Can be set to \fBalways\fR or \fBnever\fR\. +.IP "\(bu" 4 +\fB\-B\fR, \fB\-\-ignore\-backups\fR: Hides files ending in \fB~\fR, often used as backup files\. . -.TP -\fB\-f\fR -Does not sort the output, this is equivilent to running \fBshow\fR with \fB\-aU\fR\. +.IP "\(bu" 4 +\fB\-\-color\fR[=\fICOLOR\fR]: Sets colorizing of files and directories\. Can be set to \fBalways\fR or \fBnever\fR\. . -.TP -\fB\-\-full\-time\fR -Sets the Time/Date format to \fBfull\-iso\fR\. +.IP "\(bu" 4 +\fB\-f\fR: Does not sort the output, this is equivilent to running \fBshow\fR with \fB\-aU\fR\. . -.TP -\fB\-g\fR -Only displays the group of each object\. Can be paired with \fB\-\-author\fR\. +.IP "\(bu" 4 +\fB\-\-full\-time\fR: Sets the Time/Date format to \fBfull\-iso\fR\. . -.TP -\fB\-G\fR, \fB\-\-no\-group\fR -Omits the group of each object in the output\. +.IP "\(bu" 4 +\fB\-g\fR: Only displays the group of each object\. Can be paired with \fB\-\-author\fR\. . -.TP -\fB\-h\fR, \fB\-\-human\-readable\fR -Displays the file sizes in a human readable format\. For example, 1024 Bytes will be represented as 1M\. +.IP "\(bu" 4 +\fB\-G\fR, \fB\-\-no\-group\fR: Omits the group of each object in the output\. . -.TP -\fB\-\-si\fR -As above, but uses powers of 1000\. (1000 = 1m) +.IP "\(bu" 4 +\fB\-h\fR, \fB\-\-human\-readable\fR: Displays the file sizes in a human readable format\. For example, 1024 Bytes will be represented as 1M\. . -.TP -\fB\-r\fR, \fB\-\-reverse\fR -Reverse the order of sorting\. Can be paired with \fB\-S\fR or \fB\-t\fR +.IP "\(bu" 4 +\fB\-\-si\fR: As above, but uses powers of 1000\. (1000 = 1m) . -.TP -\fB\-S\fR -Sorts files and directories by size, largest first\. +.IP "\(bu" 4 +\fB\-r\fR, \fB\-\-reverse\fR: Reverse the order of sorting\. Can be paired with \fB\-S\fR or \fB\-t\fR . -.TP -\fB\-\-time\-style\fR=[\fITIME_STYLE\fR] -Time/Date format\. Can be set to \fBfull\-iso\fR, \fBlong\-iso\fR, \fBiso\fR, or \fBlocale\fR\. +.IP "\(bu" 4 +\fB\-S\fR: Sorts files and directories by size, largest first\. . -.TP -\fB\-t\fR -Sorts by modification time, newest first\. +.IP "\(bu" 4 +\fB\-\-time\-style\fR=[\fITIME_STYLE\fR]: Time/Date format\. Can be set to \fBfull\-iso\fR, \fBlong\-iso\fR, \fBiso\fR, or \fBlocale\fR\. . -.TP -\fB\-U\fR -Displays output in the order they\'re found\. +.IP "\(bu" 4 +\fB\-t\fR: Sorts by modification time, newest first\. . -.TP -\fB\-\-help\fR -Displays help message, then exits\. +.IP "\(bu" 4 +\fB\-U\fR: Displays output in the order they\'re found\. . -.TP -\fB\-\-version\fR -Displays program version, then exits\. +.IP "\(bu" 4 +\fB\-Z\fR, \fB\-\-context\fR Shows the secuirty context of each file, if one is defined\. +. +.IP "\(bu" 4 +\fB\-1\fR Only shows the file name on display\. +. +.IP "\(bu" 4 +\fB\-\-help\fR: Displays help message, then exits\. +. +.IP "\(bu" 4 +\fB\-\-version\fR: Displays program version, then exits\. +. +.IP "" 0 . .P The following options are specific to \fBshow\fR: . -.TP -\fB\-\-theme\fR=[\fITHEME\fR] -Color themes\. Passing this argument without an option will display available themes\. +.IP "\(bu" 4 +\fB\-\-theme\fR=[\fITHEME\fR]: Color themes\. Passing this argument without an option will display available themes\. . -.TP -\fB\-\-no\-danger\fR -Disables the danger color scheme when running with elevated privileges\. +.IP "\(bu" 4 +\fB\-\-no\-danger\fR: Disables the danger color scheme when running with elevated privileges\. . -.TP -\fB\-\-marked\fR=[\fIMARKED\fR] -Displays information about marked files\. Can be set to \fBalways\fR, \fBnever\fR, or \fBauto\fR\. +.IP "\(bu" 4 +\fB\-\-marked\fR=[\fIMARKED\fR]: Displays information about marked files\. Can be set to \fBalways\fR, \fBnever\fR, or \fBauto\fR\. . -.TP -\fB\-\-no\-sf\fR -Doesn\'t display files using \fBsf\fR (if installed) and defaults to the user\'s PAGER setting\. +.IP "\(bu" 4 +\fB\-\-no\-sf\fR: Doesn\'t display files using \fBsf\fR (if installed) and defaults to the user\'s PAGER setting\. . -.TP -\fB\-\-show\-on\-enter\fR -Sets the enter key to launch the show command instead of moving the selection down by one\. +.IP "\(bu" 4 +\fB\-\-show\-on\-enter\fR: Sets the enter key to launch the show command instead of moving the selection down by one\. . -.TP -\fB\-\-running\fR -Checks for parent instances of \fBshow\fR, this is useful when using the Run Command option\. +.IP "\(bu" 4 +\fB\-\-running\fR: Checks for parent instances of \fBshow\fR, this is useful when using the Run Command option\. . -.TP -\fB\-\-settings\-menu\fR -Launch \fBshow\fR directly into the settings menu\. +.IP "\(bu" 4 +\fB\-\-settings\-menu\fR: Launch \fBshow\fR directly into the settings menu\. . -.TP -\fB\-\-edit\-themes\fR -Launches \fBshow\fR directly into the theme editor\. (colors) +.IP "\(bu" 4 +\fB\-\-edit\-themes\fR: Launches \fBshow\fR directly into the theme editor\. (colors) +. +.IP "\(bu" 4 +\fB\-\-skip\-to\-first\fR Sets the highlighted item to the first object that isn\'t \fB\.\fR or \fB\.\.\fR +. +.IP "" 0 . .SH "OVERVIEW" The \fBshow\fR application lets users view the names of files and directories on a disk with information about the files\. Files can be copied, moved, viewed, and edited (in your system\'s default editor)\. The application is run using the show command\. The output is similar to the \fBls\fR command\. @@ -763,6 +754,7 @@ The following screen is displayed\. [ ] Human readable sizes [ ] Enter key acts like Show < > Owner Column: + [ ] Skip to the first object . .fi . @@ -805,7 +797,7 @@ DF\-SHOW is designed to be run as a non privileged user, and obeys restrictions Written by Robert Ian Hawdon\. . .SH "COPYRIGHT" -Copyright (C) 2019 License GPLv3+: GNU GPL version 3 or later \fIhttps://gnu\.org/licenses/gpl\.html\fR\. +Copyright (C) 2020 License GPLv3+: GNU GPL version 3 or later \fIhttps://gnu\.org/licenses/gpl\.html\fR\. . .P This program comes with ABSOLUTELY NO WARRANTY\. This is free software, and you are welcome to redistribute it under certain conditions\. diff --git a/man/show.1.html b/man/show.1.html index 78c29eb..f83d8c6 100644 --- a/man/show.1.html +++ b/man/show.1.html @@ -92,40 +92,73 @@

OPTIONS

The following options are shared with ls:

-
-
-a, --all

Does not ignore files or directories starting with .. -The . and .. objects are never hidden due to their navigational functions in show.

-
--author

Prints the author of the file in the output.

-
-B, --ignore-backups

Hides files ending in ~, often used as backup files.

-
--color[=COLOR]

Sets colorizing of files and directories. Can be set to always or never.

-
-f

Does not sort the output, this is equivilent to running show with -aU.

-
--full-time

Sets the Time/Date format to full-iso.

-
-g

Only displays the group of each object. Can be paired with --author.

-
-G, --no-group

Omits the group of each object in the output.

-
-h, --human-readable

Displays the file sizes in a human readable format. For example, 1024 Bytes will be represented as 1M.

-
--si

As above, but uses powers of 1000. (1000 = 1m)

-
-r, --reverse

Reverse the order of sorting. Can be paired with -S or -t

-
-S

Sorts files and directories by size, largest first.

-
--time-style=[TIME_STYLE]

Time/Date format. Can be set to full-iso, long-iso, iso, or locale.

-
-t

Sorts by modification time, newest first.

-
-U

Displays output in the order they're found.

-
--help

Displays help message, then exits.

-
--version

Displays program version, then exits.

-
+
    +
  • -@ +Displays extended atributes keys and sizes (macOS only).

  • +
  • -a, --all: +Does not ignore files or directories starting with .. +The . and .. objects are never hidden due to their navigational functions in show.

  • +
  • --author: +Prints the author of the file in the output.

  • +
  • -B, --ignore-backups: +Hides files ending in ~, often used as backup files.

  • +
  • --color[=COLOR]: +Sets colorizing of files and directories. Can be set to always or never.

  • +
  • -f: +Does not sort the output, this is equivilent to running show with -aU.

  • +
  • --full-time: +Sets the Time/Date format to full-iso.

  • +
  • -g: +Only displays the group of each object. Can be paired with --author.

  • +
  • -G, --no-group: +Omits the group of each object in the output.

  • +
  • -h, --human-readable: +Displays the file sizes in a human readable format. For example, 1024 Bytes will be represented as 1M.

  • +
  • --si: +As above, but uses powers of 1000. (1000 = 1m)

  • +
  • -r, --reverse: +Reverse the order of sorting. Can be paired with -S or -t

  • +
  • -S: +Sorts files and directories by size, largest first.

  • +
  • --time-style=[TIME_STYLE]: +Time/Date format. Can be set to full-iso, long-iso, iso, or locale.

  • +
  • -t: +Sorts by modification time, newest first.

  • +
  • -U: +Displays output in the order they're found.

  • +
  • -Z, --context +Shows the secuirty context of each file, if one is defined.

  • +
  • -1 +Only shows the file name on display.

  • +
  • --help: +Displays help message, then exits.

  • +
  • --version: +Displays program version, then exits.

  • +

The following options are specific to show:

-
-
--theme=[THEME]

Color themes. Passing this argument without an option will display available themes.

-
--no-danger

Disables the danger color scheme when running with elevated privileges.

-
--marked=[MARKED]

Displays information about marked files. Can be set to always, never, or auto.

-
--no-sf

Doesn't display files using sf (if installed) and defaults to the user's PAGER setting.

-
--show-on-enter

Sets the enter key to launch the show command instead of moving the selection down by one.

-
--running

Checks for parent instances of show, this is useful when using the Run Command option.

-
--settings-menu

Launch show directly into the settings menu.

-
--edit-themes

Launches show directly into the theme editor. (colors)

-
+
    +
  • --theme=[THEME]: +Color themes. Passing this argument without an option will display available themes.

  • +
  • --no-danger: +Disables the danger color scheme when running with elevated privileges.

  • +
  • --marked=[MARKED]: +Displays information about marked files. Can be set to always, never, or auto.

  • +
  • --no-sf: +Doesn't display files using sf (if installed) and defaults to the user's PAGER setting.

  • +
  • --show-on-enter: +Sets the enter key to launch the show command instead of moving the selection down by one.

  • +
  • --running: +Checks for parent instances of show, this is useful when using the Run Command option.

  • +
  • --settings-menu: +Launch show directly into the settings menu.

  • +
  • --edit-themes: +Launches show directly into the theme editor. (colors)

  • +
  • --skip-to-first +Sets the highlighted item to the first object that isn't . or ..

  • +

OVERVIEW

@@ -466,6 +499,7 @@

CONFIGURING SHOW

[ ] Human readable sizes [ ] Enter key acts like Show < > Owner Column: <owner> <group> <author> + [ ] Skip to the first object

There are three types of configuration items, each denoted with a different symbol:

@@ -496,7 +530,7 @@

AUTHOR

-

Copyright (C) 2019 License GPLv3+: GNU GPL version 3 or later https://gnu.org/licenses/gpl.html.

+

Copyright (C) 2020 License GPLv3+: GNU GPL version 3 or later https://gnu.org/licenses/gpl.html.

This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions.

@@ -509,7 +543,7 @@

SEE ALSO

  1. -
  2. September 2019
  3. +
  4. May 2020
  5. show(1)
diff --git a/man/show.1.ronn b/man/show.1.ronn index 23d5bc9..819ff49 100644 --- a/man/show.1.ronn +++ b/man/show.1.ronn @@ -13,6 +13,9 @@ DF-SHOW: An interactive directory/file browser written for Unix-like systems. Ba The following options are shared with `ls`: +* `-@` +Displays extended atributes keys and sizes (macOS only). + * `-a`, `--all`: Does not ignore files or directories starting with `.`. The `.` and `..` objects are never hidden due to their navigational functions in `show`. @@ -59,6 +62,12 @@ Sorts by modification time, newest first. * `-U`: Displays output in the order they're found. +* `-Z`, `--context` +Shows the secuirty context of each file, if one is defined. + +* `-1` +Only shows the file name on display. + * `--help`: Displays help message, then exits. @@ -91,6 +100,9 @@ Launch `show` directly into the settings menu. * `--edit-themes`: Launches `show` directly into the theme editor. (colors) +* `--skip-to-first` +Sets the highlighted item to the first object that isn't `.` or `..` + ## OVERVIEW The `show` application lets users view the names of files and directories on a disk with information about the files. Files can be copied, moved, viewed, and edited (in your system's default editor). The application is run using the show command. The output is similar to the `ls` command. @@ -555,6 +567,7 @@ The following screen is displayed. [ ] Human readable sizes [ ] Enter key acts like Show < > Owner Column: + [ ] Skip to the first object There are three types of configuration items, each denoted with a different symbol: @@ -585,7 +598,7 @@ DF-SHOW is designed to be run as a non privileged user, and obeys restrictions s Written by Robert Ian Hawdon. ## COPYRIGHT -Copyright (C) 2019 License GPLv3+: GNU GPL version 3 or later . +Copyright (C) 2020 License GPLv3+: GNU GPL version 3 or later . This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions. diff --git a/misc/auto-completion/bash/sf-completion.bash b/misc/auto-completion/bash/sf-completion.bash new file mode 100644 index 0000000..4642b7f --- /dev/null +++ b/misc/auto-completion/bash/sf-completion.bash @@ -0,0 +1,25 @@ +# bash completion for sf -*- shell-script -*- + +_sf() +{ + COMPREPLY=() + local IFS=$'\n' + local cur=$2 prev=$3 + local -a options + options=( + --wrap + --help + --version + --theme + --settings-menu + ) + if [[ $cur == -* ]]; then + COMPREPLY=( $( compgen -W "${options[*]}" -- "$cur" ) ) + else + COMPREPLY=( $( compgen -d -f -- "$cur") ) + fi + +} + +complete -o filenames -F _sf sf + diff --git a/misc/auto-completion/bash/show-completion.bash b/misc/auto-completion/bash/show-completion.bash new file mode 100644 index 0000000..4652547 --- /dev/null +++ b/misc/auto-completion/bash/show-completion.bash @@ -0,0 +1,49 @@ +# bash completion for show -*- shell-script -*- + +_show() +{ + COMPREPLY=() + local IFS=$'\n' + local cur=$2 prev=$3 + local -a options + options=( + -@ + --all + --author + --ignore-backups + --color + -f + --full-time + -g + --no-group + --human-readable + --si + --reverse + -S + --time-style + -t + -U + --context + -1 + --help + --version + --theme + --no-danger + --marked + --no-sf + --show-on-enter + --running + --settings-menu + --edit-themes + --skip-to-first + ) + if [[ $cur == -* ]]; then + COMPREPLY=( $( compgen -W "${options[*]}" -- "$cur" ) ) + else + COMPREPLY=( $( compgen -d -- "$cur") ) + fi + +} + +complete -o dirnames -F _show show + diff --git a/misc/auto-completion/zsh/_sf b/misc/auto-completion/zsh/_sf new file mode 100644 index 0000000..1cb7a3c --- /dev/null +++ b/misc/auto-completion/zsh/_sf @@ -0,0 +1,15 @@ +#compdef sf + +setopt localoptions noshwordsplit noksharrays +local -a args +args=( + '(-w --wrap)'{-w,--wrap}"["'Trun line wrapping on'"]" + '(--help)--help[Displays help message, then exits]' + '(--version)--version[Displays version, then exits]' + '(--theme)--theme[Color themes]' + '(--settings-menu)--settings-menu[Launch settings menu]' + '*:filename:_files' + ) + +_arguments -S -s $args + diff --git a/misc/auto-completion/zsh/_show b/misc/auto-completion/zsh/_show new file mode 100644 index 0000000..f2b9adb --- /dev/null +++ b/misc/auto-completion/zsh/_show @@ -0,0 +1,40 @@ +#compdef show + +zstyle ':completion:*:show:*' file-patterns '*(/):directories' +setopt localoptions noshwordsplit noksharrays +local -a args +args=( + '(-@)-@[Display extended attribute keys and sizes]' + '(-a --all)'{-a,--all}"["'Do not ignore entries starting with .'"]" + '(--author)--author[Prints the author of each file]' + '(-B --ignore-backups)'{-B,--ignore-backups}"["'Do not list implied entries ending with ~'"]" + '(--color)--color[Colorize the output]' + '(-f)-f[Do not sort, enables -aU]' + '(--full-time)--full-time[Display time as full-iso format]' + '(-g)-g[Only show group]' + '(-G --no-group)'{-G,--no-group}"["'Do not show group'"]" + '(-h --human-readable)'{-h,--human-readable}"["'Print sizes like 1K 234M 2G etc.'"]" + '(--si)--si[As above, but use powers of 1000 not 1024]' + '(-r --reverse)'{-r,--reverse}"["'Reverse order while sorting'"]" + '(-S)-S[Sort file by size, largest first]' + '(--time-style)--time-style[Time/date format]' + '(-t)-t[Sort by modification time, newset first]' + '(-U)-U[Do not sort; lists objects in directory order]' + '(-Z --context)'{-Z,--context}"["'Show security context of each file, if any'"]" + '(-1)-1[Only show file name, one per line]' + '(--help)--help[Displays help message, then exits]' + '(--version)--version[Displays version, then exits]' + '(--theme)--theme[Color themes]' + '(--no-danger)--no-danger[Turns off danger colors when running with elevated privileges]' + '(--marked)--marked[Shows information about marked objects]' + '(--no-sf)--no-sf[Does not display files in sf]' + '(--show-on-enter)--show-on-enter[Repurposes the Enter key to launch the show command]' + '(--running)--running[Display number of parent show processes]' + '(--settings-menu)--settings-menu[Launch settings menu]' + '(--edit-themes)--edit-themes[Launches directly into the theme editor]' + '(--skip-to-first)--skip-to-first[Skips navigation items if at the top of list]' + '*:filename:_files' + ) + +_arguments -S -s $args + diff --git a/src/colors.c b/src/colors.c index 3b94828..9ff7a96 100644 --- a/src/colors.c +++ b/src/colors.c @@ -1,6 +1,7 @@ /* - DF-SHOW - A clone of 'SHOW' directory browser from DF-EDIT by Larry Kroeker - Copyright (C) 2018-2019 Robert Ian Hawdon + DF-SHOW: An interactive directory/file browser written for Unix-like systems. + Based on the applications from the PC-DOS DF-EDIT suite by Larry Kroeker. + Copyright (C) 2018-2020 Robert Ian Hawdon This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/common.c b/src/common.c index 51bd03b..af17883 100644 --- a/src/common.c +++ b/src/common.c @@ -1,6 +1,7 @@ /* - DF-SHOW - A clone of 'SHOW' directory browser from DF-EDIT by Larry Kroeker - Copyright (C) 2018-2019 Robert Ian Hawdon + DF-SHOW: An interactive directory/file browser written for Unix-like systems. + Based on the applications from the PC-DOS DF-EDIT suite by Larry Kroeker. + Copyright (C) 2018-2020 Robert Ian Hawdon This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -389,7 +390,7 @@ char * objectFromPath(const char *myStr){ void printVersion(char* programName){ printf (("Directory File Show (DF-SHOW) - %s %s\n"), programName, VERSION); fputs (("\ -Copyright (C) 2019 Robert Ian Hawdon\n\ +Copyright (C) 2020 Robert Ian Hawdon\n\ License GPLv3+: GNU GPL version 3 or later .\n\ This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you\n\ are welcome to redistribute it under certain conditions.\n"), stdout); diff --git a/src/common.h b/src/common.h index 1f3990d..f9ab1f5 100644 --- a/src/common.h +++ b/src/common.h @@ -1,6 +1,12 @@ #define PROGRAM_DESC "\nDF-SHOW: An interactive directory/file browser written for Unix-like systems.\nBased on the applications from the PC-DOS DF-EDIT suite by Larry Kroeker.\n" #define CONF_NAME "dfshow.conf" #define HOME_CONF_DIR ".dfshow" + +#define SETTING_BOOL 0 +#define SETTING_SELECT 1 +#define SETTING_MULTI 2 +#define SETTING_FREE 3 + #include typedef struct { @@ -37,6 +43,11 @@ typedef struct { int boolVal; } t2BinValues; +typedef struct node { + int val; + struct node * next; +} node_t; + int getch10th (void); int cmp_menu_ref(const void *lhs, const void *rhs); int splitPath(pathDirs **dirStruct, char *path); diff --git a/src/sf.c b/src/sf.c index fe2568e..fdbf5e3 100644 --- a/src/sf.c +++ b/src/sf.c @@ -1,6 +1,7 @@ /* - DF-SHOW - A clone of 'SHOW' directory browser from DF-EDIT by Larry Kroeker - Copyright (C) 2018-2019 Robert Ian Hawdon + DF-SHOW: An interactive directory/file browser written for Unix-like systems. + Based on the applications from the PC-DOS DF-EDIT suite by Larry Kroeker. + Copyright (C) 2018-2020 Robert Ian Hawdon This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -374,15 +375,15 @@ void saveConfig(const char * confFile, settingIndex **settings, t1CharValues **v for (i = 0; i < items; i++){ config_setting_remove(group, (*settings)[i].refLabel); - if ((*settings)[i].type == 0){ + if ((*settings)[i].type == SETTING_BOOL){ setting = config_setting_add(group, (*settings)[i].refLabel, CONFIG_TYPE_INT); if (!strcmp((*settings)[i].refLabel, "wrap")){ config_setting_set_int(setting, wrap); } - } else if ((*settings)[i].type == 1){ + } else if ((*settings)[i].type == SETTING_SELECT){ // None of those in SF (yet?) - } else if ((*settings)[i].type == 2){ + } else if ((*settings)[i].type == SETTING_MULTI){ // None of those in SF (yet?) } } @@ -421,7 +422,7 @@ void settingsMenuView() clear(); wPrintMenu(0,0,settingsMenuLabel); - importSetting(&settingIndex, &items, "wrap", L"Enable text wrapping", 0, wrap, -1, 0); + importSetting(&settingIndex, &items, "wrap", L"Enable text wrapping", SETTING_BOOL, wrap, -1, 0); while(1) { diff --git a/src/sfmenus.c b/src/sfmenus.c index 2795abd..e8d5a8d 100644 --- a/src/sfmenus.c +++ b/src/sfmenus.c @@ -1,6 +1,7 @@ /* - DF-SHOW - A clone of 'SHOW' directory browser from DF-EDIT by Larry Kroeker - Copyright (C) 2018-2019 Robert Ian Hawdon + DF-SHOW: An interactive directory/file browser written for Unix-like systems. + Based on the applications from the PC-DOS DF-EDIT suite by Larry Kroeker. + Copyright (C) 2018-2020 Robert Ian Hawdon This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,6 +32,8 @@ int * pc = &c; int abortinput = 0; +bool findSet = false; + menuDef *fileMenu; int fileMenuSize = 0; wchar_t *fileMenuLabel; @@ -101,28 +104,32 @@ void unloadMenuLabels(){ free(settingsMenuLabel); } -void show_file_find(int charcase) +void show_file_find(bool charcase, bool useLast) { int regexcase; int result; char inputmessage[32]; char errormessage[1024]; - if (charcase){ - regexcase = 0; - strcpy(inputmessage, "Match Case - Enter string:"); - } else { - regexcase = REG_ICASE; - strcpy(inputmessage, "Ignore Case - Enter string:"); + if (!useLast){ + if (charcase){ + regexcase = 0; + strcpy(inputmessage, "Match Case - Enter string:"); + } else { + regexcase = REG_ICASE; + strcpy(inputmessage, "Ignore Case - Enter string:"); + } + move(0,0); + clrtoeol(); + mvprintw(0, 0, inputmessage); + curs_set(TRUE); + move(0, strlen(inputmessage) + 1); + curs_set(FALSE); + if (readline(regexinput, 1024, regexinput) == -1 ){ + abortinput = 1; + } } - move(0,0); - clrtoeol(); - mvprintw(0, 0, inputmessage); - curs_set(TRUE); - move(0, strlen(inputmessage) + 1); - curs_set(FALSE); - if (readline(regexinput, 1024, regexinput) == -1 ){ - abortinput = 1; - } else { + if (abortinput != 1) { + findSet = true; result = findInFile(fileName, regexinput, regexcase); if ( result > 0 ){ topline = result; @@ -210,11 +217,16 @@ void show_file_inputs() if (*pc == menuHotkeyLookup(fileMenu,"f_find", fileMenuSize)){ e = show_file_find_case_input(); if (e != -1){ - show_file_find(e); + show_file_find(e, false); } else { abortinput = 0; } wPrintMenu(0, 0, fileMenuLabel); + } else if (*pc == 6){ + if (findSet){ + show_file_find(false, true); + } + wPrintMenu(0, 0, fileMenuLabel); } else if (*pc == menuHotkeyLookup(fileMenu, "f_help", fileMenuSize)){ showManPage("sf"); wPrintMenu(0, 0, fileMenuLabel); diff --git a/src/sfmenus.h b/src/sfmenus.h index 74eeda1..5f3c982 100644 --- a/src/sfmenus.h +++ b/src/sfmenus.h @@ -1,7 +1,7 @@ void generateDefaultMenus(); void refreshMenuLabels(); void unloadMenuLabels(); -void show_file_find(int charcase); +void show_file_find(bool charcase, bool useLast); int show_file_find_case_input(); void show_file_position_input(int currentpos); void show_file_inputs(); diff --git a/src/show.c b/src/show.c index 737a80b..3c904c6 100644 --- a/src/show.c +++ b/src/show.c @@ -1,6 +1,7 @@ /* - DF-SHOW - A clone of 'SHOW' directory browser from DF-EDIT by Larry Kroeker - Copyright (C) 2018-2019 Robert Ian Hawdon + DF-SHOW: An interactive directory/file browser written for Unix-like systems. + Based on the applications from the PC-DOS DF-EDIT suite by Larry Kroeker. + Copyright (C) 2018-2020 Robert Ian Hawdon This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -54,7 +55,8 @@ int markedinfo = 0; int useEnvPager = 0; int launchThemeEditor = 0; int launchSettingsMenu = 0; - +int oneLine = 0; +int skipToFirstFile = 0; int plugins = 0; // Not yet implemented @@ -64,10 +66,21 @@ int messageBreak = 0; int showProcesses; +int showContext = 0; + +int showXAttrs = 0; + +int showAcls = 0; // Might end up not implementing this. + char *objectWild; results *ob; +int segOrder[8] = {COL_MARK, COL_ATTR, COL_HLINK, COL_OWNER, COL_CONTEXT, COL_SIZE, COL_DATE, COL_NAME}; +// int segOrder[8] = {COL_MARK, COL_NAME, COL_SIZE, COL_DATE, COL_ATTR}; // Emulating NET-DF-EDIT's XENIX layout + +extern int skippable; + extern int settingsPos; extern int settingsBinPos; @@ -79,6 +92,7 @@ extern int * pc; extern history *hs; extern int topfileref; +extern int lineStart; extern int selected; extern int totalfilecount; extern int showhidden; @@ -100,6 +114,9 @@ extern wchar_t *modifyMenuLabel; extern wchar_t *sortMenuLabel; extern wchar_t *linkMenuLabel; +extern xattrList *xa; +extern int xattrPos; + int setMarked(char* markedinput); int checkStyle(char* styleinput); @@ -108,6 +125,7 @@ void readConfig(const char * confFile) config_t cfg; config_setting_t *root, *setting, *group, *array; //probably don't need the array, but it may be used in the future. char markedParam[8]; + int i, n; config_init(&cfg); if (config_read_file(&cfg, confFile)){ // Deal with the globals first @@ -212,6 +230,38 @@ void readConfig(const char * confFile) enterAsShow = 1; } } + // Check Security Context + setting = config_setting_get_member(group, "context"); + if (setting){ + if (config_setting_get_int(setting)){ + showContext = 1; + } + } + // Check Skip To First Object + setting = config_setting_get_member(group, "skip-to-first"); + if (setting){ + if (config_setting_get_int(setting)){ + skipToFirstFile = 1; + } + } + // Check Showing XAttrs + setting = config_setting_get_member(group, "showXAttrs"); + if (setting){ + if (config_setting_get_int(setting)){ + showXAttrs = 1; + } + } + // Check Layout + array = config_setting_get_member(group, "layout"); + if (array){ + for (i = 0; i < 8; i++){ + if (config_setting_get_elem(array, i) != NULL){ + segOrder[i] = config_setting_get_int_elem(array, i); + } else { + segOrder[i] = -1; + } + } + } } // Check owner column group = config_lookup(&cfg, "show.owner"); @@ -259,7 +309,7 @@ void saveConfig(const char * confFile, settingIndex **settings, t1CharValues **v for (i = 0; i < items; i++){ config_setting_remove(group, (*settings)[i].refLabel); - if ((*settings)[i].type == 0){ + if ((*settings)[i].type == SETTING_BOOL){ setting = config_setting_add(group, (*settings)[i].refLabel, CONFIG_TYPE_INT); if (!strcmp((*settings)[i].refLabel, "color")){ @@ -280,8 +330,14 @@ void saveConfig(const char * confFile, settingIndex **settings, t1CharValues **v config_setting_set_int(setting, human); } else if (!strcmp((*settings)[i].refLabel, "show-on-enter")){ config_setting_set_int(setting, enterAsShow); + } else if (!strcmp((*settings)[i].refLabel, "context")){ + config_setting_set_int(setting, showContext); + } else if (!strcmp((*settings)[i].refLabel, "skip-to-first")){ + config_setting_set_int(setting, skipToFirstFile); + } else if (!strcmp((*settings)[i].refLabel, "showXAttrs")){ + config_setting_set_int(setting, showXAttrs); } - } else if ((*settings)[i].type == 1){ + } else if ((*settings)[i].type == SETTING_SELECT){ // setting = config_setting_add(group, (*settings)[i].refLabel, CONFIG_TYPE_STRING); if (!strcmp((*settings)[i].refLabel, "marked")){ @@ -295,7 +351,7 @@ void saveConfig(const char * confFile, settingIndex **settings, t1CharValues **v } else if (!strcmp((*settings)[i].refLabel, "timestyle")){ config_setting_set_string(setting, timestyle); } - } else if ((*settings)[i].type == 2){ + } else if ((*settings)[i].type == SETTING_MULTI){ if (!strcmp((*settings)[i].refLabel, "owner")){ subgroup = config_setting_add(group, "owner", CONFIG_TYPE_GROUP); for (v = 0; v < binIndex; v++){ @@ -335,6 +391,10 @@ void applySettings(settingIndex **settings, t1CharValues **values, int items, in enterAsShow = (*settings)[i].intSetting; } else if (!strcmp((*settings)[i].refLabel, "marked")){ markedinfo = (*settings)[i].intSetting; + } else if (!strcmp((*settings)[i].refLabel, "context")){ + showContext = (*settings)[i].intSetting; + } else if (!strcmp((*settings)[i].refLabel, "skip-to-first")){ + skipToFirstFile = (*settings)[i].intSetting; } else if (!strcmp((*settings)[i].refLabel, "sortmode")){ for (j = 0; j < valuesCount; j++){ if (!strcmp((*values)[j].refLabel, "sortmode") && ((*values)[j].index == (*settings)[i].intSetting)){ @@ -349,6 +409,8 @@ void applySettings(settingIndex **settings, t1CharValues **values, int items, in } } else if (!strcmp((*settings)[i].refLabel, "owner")){ ogavis = (*settings)[i].intSetting; + } else if (!strcmp((*settings)[i].refLabel, "showXAttrs")){ + showXAttrs = (*settings)[i].intSetting; } } } @@ -395,21 +457,26 @@ void settingsMenuView(){ sortmodeInt = textValueLookup(&charValues, &charValuesCount, "sortmode", sortmode); timestyleInt = textValueLookup(&charValues, &charValuesCount, "timestyle", timestyle); - importSetting(&settingIndex, &items, "color", L"Display file colors", 0, filecolors, -1, 0); - importSetting(&settingIndex, &items, "marked", L"Show marked file info", 1, markedinfo, markedCount, 0); - importSetting(&settingIndex, &items, "sortmode", L"Sorting mode", 1, sortmodeInt, sortmodeCount, 0); - importSetting(&settingIndex, &items, "reverse", L"Reverse sorting order", 0, reverse, -1, 0); - importSetting(&settingIndex, &items, "timestyle", L"Time style", 1, timestyleInt, timestyleCount, 0); - importSetting(&settingIndex, &items, "hidden", L"Show hidden files", 0, showhidden, -1, 0); - importSetting(&settingIndex, &items, "ignore-backups", L"Hide backup files", 0, showbackup, -1, 1); - importSetting(&settingIndex, &items, "no-sf", L"Use 3rd party pager over SF", 0, useEnvPager, -1, 0); + importSetting(&settingIndex, &items, "color", L"Display file colors", SETTING_BOOL, filecolors, -1, 0); + importSetting(&settingIndex, &items, "marked", L"Show marked file info", SETTING_SELECT, markedinfo, markedCount, 0); + importSetting(&settingIndex, &items, "sortmode", L"Sorting mode", SETTING_SELECT, sortmodeInt, sortmodeCount, 0); + importSetting(&settingIndex, &items, "reverse", L"Reverse sorting order", SETTING_BOOL, reverse, -1, 0); + importSetting(&settingIndex, &items, "timestyle", L"Time style", SETTING_SELECT, timestyleInt, timestyleCount, 0); + importSetting(&settingIndex, &items, "hidden", L"Show hidden files", SETTING_BOOL, showhidden, -1, 0); + importSetting(&settingIndex, &items, "ignore-backups", L"Hide backup files", SETTING_BOOL, showbackup, -1, 1); + importSetting(&settingIndex, &items, "no-sf", L"Use 3rd party pager over SF", SETTING_BOOL, useEnvPager, -1, 0); if (uid == 0 || euid == 0){ - importSetting(&settingIndex, &items, "no-danger", L"Hide danger lines as root", 0, danger, -1, 1); + importSetting(&settingIndex, &items, "no-danger", L"Hide danger lines as root", SETTING_BOOL, danger, -1, 1); } - importSetting(&settingIndex, &items, "si", L"Use SI units", 0, si, -1, 0); - importSetting(&settingIndex, &items, "human-readable", L"Human readable sizes", 0, human, -1, 0); - importSetting(&settingIndex, &items, "show-on-enter", L"Enter key acts like Show", 0, enterAsShow, -1, 0); - importSetting(&settingIndex, &items, "owner", L"Owner Column", 2, ogavis, ownerCount, 0); + importSetting(&settingIndex, &items, "si", L"Use SI units", SETTING_BOOL, si, -1, 0); + importSetting(&settingIndex, &items, "human-readable", L"Human readable sizes", SETTING_BOOL, human, -1, 0); + importSetting(&settingIndex, &items, "show-on-enter", L"Enter key acts like Show", SETTING_BOOL, enterAsShow, -1, 0); + importSetting(&settingIndex, &items, "owner", L"Owner Column", SETTING_MULTI, ogavis, ownerCount, 0); + importSetting(&settingIndex, &items, "context", L"Show security context of files", SETTING_BOOL, showContext, -1, 0); + importSetting(&settingIndex, &items, "skip-to-first", L"Skip to the first object", SETTING_BOOL, skipToFirstFile, -1, 0); +#ifdef HAVE_ACL_TYPE_EXTENDED + importSetting(&settingIndex, &items, "showXAttrs", L"Display extended attribute keys and sizes", SETTING_BOOL, showXAttrs, -1, 0); +#endif populateBool(&binValues, "owner", ogavis, binValuesCount); @@ -501,7 +568,8 @@ int directory_view(char * currentpwd) strcpy(objectWild, ""); } - topfileref = 0; + // topfileref = 0; + lineStart = 0; clear(); setColors(COMMAND_PAIR); @@ -511,20 +579,30 @@ int directory_view(char * currentpwd) set_history(currentpwd, "", "", 0, 0); freeResults(ob, totalfilecount); + freeXAttrs(xa, xattrPos); ob = get_dir(currentpwd); reorder_ob(ob, sortmode); - display_dir(currentpwd, ob, topfileref, 0); + generateEntryLineIndex(ob); + + if (skipToFirstFile == 1 && skippable == 1){ + selected = 2; + } else { + selected = 0; + } + + display_dir(currentpwd, ob); // function_key_menu(); //printMenu(LINES-1, 0, functionMenuText); - wPrintMenu(LINES-1, 0, functionMenuLabel); + // wPrintMenu(LINES-1, 0, functionMenuLabel); refresh(); directory_view_menu_inputs(); freeResults(ob, totalfilecount); //freeing memory + freeXAttrs(xa, xattrPos); return 0; } @@ -636,8 +714,11 @@ void printHelp(char* programName){ Sorts objects alphabetically if -St is not set.\n\ "), stdout); fputs (("\n\ -Options shared with ls:\n\ - -a, --all do not ignore entries starting with .\n\ +Options shared with ls:\n"), stdout); +#ifdef HAVE_ACL_TYPE_EXTENDED + fputs((" -@ display extended attribute keys and sizes\n"), stdout); +#endif + fputs((" -a, --all do not ignore entries starting with .\n\ --author prints the author of each file\n\ -B, --ignore-backups do not list implied entries ending with ~\n\ --color[=WHEN] colorize the output, see the color section below\n\ @@ -652,6 +733,8 @@ Options shared with ls:\n\ --time-style=TIME_STYLE time/date format, see TIME_STYLE section below\n\ -t sort by modification time, newest first\n\ -U do not sort; lists objects in directory order\n\ + -Z, --context show security context of each file, if any\n\ + -1 only show file name, one per line\n\ --help displays help message, then exits\n\ --version displays version, then exits\n"), stdout); fputs (("\n\ @@ -672,7 +755,8 @@ Options specific to show:\n\ command\n\ --running display number of parent show processes\n\ --settings-menu launch settings menu\n\ - --edit-themes launchs directly into the theme editor\n"), stdout); + --edit-themes launchs directly into the theme editor\n\ + --skip-to-first skips navigation items if at the top of list\n"), stdout); fputs (("\n\ The THEME argument can be:\n"), stdout); listThemes(); @@ -689,6 +773,13 @@ int main(int argc, char *argv[]) uid_t uid=getuid(), euid=geteuid(); int c; char * tmpPwd; + char options[20]; + +#ifdef HAVE_ACL_TYPE_EXTENDED + strcpy(options, "@aABfgGhlrStUZ1"); +#else + strcpy(options, "aABfgGhlrStUZ1"); +#endif showProcesses = checkRunningEnv() + 1; @@ -736,11 +827,13 @@ int main(int argc, char *argv[]) {"full-time", no_argument, 0, GETOPT_FULLTIME_CHAR}, {"edit-themes", no_argument, 0, GETOPT_THEMEEDIT_CHAR}, {"settings-menu", no_argument, 0, GETOPT_OPTIONSMENU_CHAR}, + {"contect", no_argument, 0, 'Z'}, + {"skip-to-first", no_argument, 0, GETOPT_SKIPTOFIRST_CHAR}, {0, 0, 0, 0} }; int option_index = 0; - c = getopt_long(argc, argv, "aABfgGhrStU", long_options, &option_index); + c = getopt_long(argc, argv, options, long_options, &option_index); if ( c == -1 ){ break; @@ -789,6 +882,8 @@ Valid arguments are:\n\ strcpy(sortmode, "unsorted"); // This needs to be set to "unsorted" to allow the settings menu to render correctly. showhidden = 1; break; + case 'l': + break; // Allows for accidental -l from `ls` muscle memory commands. Does nothing. case 'S': strcpy(sortmode, "size"); break; @@ -877,6 +972,18 @@ Valid arguments are:\n\ case GETOPT_OPTIONSMENU_CHAR: launchSettingsMenu = 1; break; + case 'Z': + showContext = 1; + break; + case '1': + oneLine = 1; + break; + case GETOPT_SKIPTOFIRST_CHAR: + skipToFirstFile = 1; + break; + case '@': + showXAttrs = 1; + break; default: // abort(); exit(2); diff --git a/src/show.h b/src/show.h index 300cd79..0178085 100644 --- a/src/show.h +++ b/src/show.h @@ -18,7 +18,8 @@ enum GETOPT_SHOWRUNNING_CHAR = (CHAR_MIN - 13), GETOPT_FULLTIME_CHAR = (CHAR_MIN - 14), GETOPT_THEMEEDIT_CHAR = (CHAR_MIN - 15), - GETOPT_OPTIONSMENU_CHAR = (CHAR_MIN - 16) + GETOPT_OPTIONSMENU_CHAR = (CHAR_MIN - 16), + GETOPT_SKIPTOFIRST_CHAR = (CHAR_MIN - 17) }; void readConfig(const char * confFile); diff --git a/src/showfunctions.c b/src/showfunctions.c index d8b8b56..8864370 100644 --- a/src/showfunctions.c +++ b/src/showfunctions.c @@ -1,6 +1,7 @@ /* - DF-SHOW - A clone of 'SHOW' directory browser from DF-EDIT by Larry Kroeker - Copyright (C) 2018-2019 Robert Ian Hawdon + DF-SHOW: An interactive directory/file browser written for Unix-like systems. + Based on the applications from the PC-DOS DF-EDIT suite by Larry Kroeker. + Copyright (C) 2018-2020 Robert Ian Hawdon This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,12 +31,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include "common.h" #include "config.h" #include "showfunctions.h" @@ -43,6 +46,10 @@ #include "colors.h" #include "show.h" +#if HAVE_ACL_LIBACL_H +# include +#endif + #if HAVE_SYS_SYSMACROS_H # include #endif @@ -51,13 +58,22 @@ # include #endif +#if HAVE_SELINUX_SELINUX_H +# include +# else +#endif + +#if HAVE_SYS_XATTR_H +# include +#endif + // It turns out most systems don't have an ST_AUTHOR, so for those systems, we set the author as the owner. Yup, `ls` does this too. #if ! HAVE_STRUCT_STAT_ST_AUTHOR # define st_author st_uid #endif char hlinkstr[6], sizestr[32], majorstr[6], minorstr[6]; -char headAttrs[12], headOG[25], headSize[14], headDT[18], headName[13]; +char headAttrs[12], headOG[25], headSize[14], headDT[18], headName[13], headContext[14]; int hlinklen; int ownerlen; @@ -69,9 +85,14 @@ int minorlen; int datelen; int namelen; int slinklen; +int contextlen; +int nameSegLen; +int xattrKeyLen; + int nameAndSLink = 0; int entryMetaLen, entryNameLen, entrySLinkLen = 0; +int charPos = 0; int ogalen; @@ -90,6 +111,7 @@ int totalfilecount; int selected; int topfileref = 0; +int lineStart = 0; int hpos = 0; int maxdisplaywidth; int displaysize; // Calculate area to print @@ -107,15 +129,35 @@ int mmMode = 0; int dirAbort = 0; -unsigned long int savailable = 0; +int axDisplay = 0; + +int markedSegmentLen, attrSegmentLen, hlinkSegmentLen, ownerSegmentLen, contextSegmentLen, sizeSegmentLen, dateSegmentLen, nameSegmentDataLen, linkSegmentLen, tmpSegmentLen; + +uintmax_t savailable = 0; unsigned long int sused = 0; history *hs; time_t currenttime; +int skippable = 0; + +xattrList *xa; +int xattrPos; + +int lineCount; +int bottomFileRef; +int visibleObjects; + +int visibleOffset; + +int listLen; +entryLines *el; + extern DIR *folder; +extern int segOrder[8]; + extern int messageBreak; extern char currentpwd[4096]; extern char timestyle[9]; @@ -133,9 +175,20 @@ extern int markedinfo; extern int useEnvPager; extern int showProcesses; extern int exitCode; +extern int showContext; +extern int oneLine; +extern int skipToFirstFile; +extern int showXAttrs; +extern int showAcls; extern char sortmode[9]; +#ifdef HAVE_MOVE_BETWEEN_DEVICES +bool moveBetweenDevices = true; +#else +bool moveBetweenDevices = false; +#endif + /* Formatting time in a similar fashion to `ls` */ static char const *long_time_format[2] = { @@ -156,8 +209,12 @@ void freeResults(results *ob, int count) free(ob[i].author); free(ob[i].slink); free(ob[i].datedisplay); + free(ob[i].contextText); + free(ob[i].xattrs); + // acl_free(ob[i].acl); } free(ob); + free(el); } void freeHistory(history *hs, int count) @@ -171,6 +228,16 @@ void freeHistory(history *hs, int count) free(hs); } +void freeXAttrs(xattrList *xa, int count) +{ + int i; + for (i = 0; i < (count - 1); i++){ + free(xa[i].name); + free(xa[i].xattr); + } + free(xa); +} + int checkRunningEnv(){ int i; if (!getenv("DFS_RUNNING")){ @@ -181,6 +248,61 @@ int checkRunningEnv(){ return i; } +int processXAttrs(xattrList **xa, char *name, unsigned char *xattrs, size_t xattrLen, int pos, int *xattrsNum) +{ + char *xattrTmp; + int i, n; + bool reset = false; //To-Do, swap all 0/1 ints to bools + xattrList *tmp; + + xattrTmp = malloc(sizeof(char)); + + for (i = 0; i < xattrLen + 1; i++){ + if (i == 0 || reset == true){ + n = 0; + free(xattrTmp); + xattrTmp = calloc(xattrLen, sizeof(char)); + if (pos == 0){ + tmp = malloc(sizeof(xattrList) * 2); + } else { + tmp = realloc(*xa, (pos + 1) * (sizeof(xattrList) + 1) ); + } + if (tmp){ + *xa = tmp; + } + reset = false; + } + if (xattrs[i] != '\0'){ + xattrTmp[n] = xattrs[i]; + n++; + } + if (xattrs[i] == '\0' && xattrTmp[0] != '\0'){ + (*xa)[pos].name = calloc(strlen(name) + 1, sizeof(char)); + strcpy((*xa)[pos].name, name); + (*xa)[pos].xattr = calloc(strlen(xattrTmp) + 1, sizeof(char)); + strcpy((*xa)[pos].xattr, xattrTmp); + // (*xa)[pos].xattrSize = strlen((*xa)[pos].xattr); + #ifdef HAVE_ACL_TYPE_EXTENDED + (*xa)[pos].xattrSize = getxattr(name, xattrTmp, NULL, 0, 0, XATTR_NOFOLLOW); + #else + #ifdef HAVE_SYS_XATTR_H + (*xa)[pos].xattrSize = lgetxattr(name, xattrTmp, NULL, 0); + #else + (*xa)[pos].xattrSize = 0; + #endif + #endif + // endwin(); + // printf("%s - %s - %zu\n", (*xa)[pos].name, (*xa)[pos].xattr, (*xa)[pos].xattrSize); + reset = true; + pos++; + ++*xattrsNum; + } + } + free(xattrTmp); + + return pos; +} + char *getRelativePath(char *file, char *target) { char *result = malloc(sizeof(char) + 1); @@ -357,7 +479,7 @@ int wildcard(const char *value, char *wcard) return match; } -int writePermsEntry(char * perms, mode_t mode){ +int writePermsEntry(char * perms, mode_t mode, int axFlag, int sLinkCheck){ typecolor = DISPLAY_PAIR; @@ -367,14 +489,18 @@ int writePermsEntry(char * perms, mode_t mode){ perms[0] = 'd'; typecolor = DIR_PAIR; } else if (S_ISCHR(mode)){ - mmMode = 1; + if (!sLinkCheck){ + mmMode = 1; + } perms[0] = 'c'; } else if (S_ISLNK(mode)){ perms[0] = 'l'; } else if (S_ISFIFO(mode)){ perms[0] = 'p'; } else if (S_ISBLK(mode)){ - mmMode = 1; + if (!sLinkCheck){ + mmMode = 1; + } perms[0] = 'b'; } else if (S_ISSOCK(mode)){ perms[0] = 's'; @@ -458,19 +584,53 @@ int writePermsEntry(char * perms, mode_t mode){ perms[9] = '-'; } + if (axFlag == ACL_XATTR){ + perms[10] = '@'; + } else if (axFlag == ACL_TRUE){ + perms[10] = '+'; + } else if (axFlag == ACL_SELINUX){ + perms[10] = '.'; + } else { + perms[10] = ' '; + } + return typecolor; } -void writeResultStruct(results* ob, const char * filename, struct stat buffer, int count){ - char perms[11] = {0}; +void writeResultStruct(results* ob, const char * filename, struct stat buffer, int count, bool xAcl, ssize_t xattr, int seLinuxCon, char * contextText, char * xattrs, const int xattrsNum){ + char perms[12] = {0}; struct group *gr; struct passwd *pw; struct passwd *au; char *filedate; ssize_t cslinklen = 0, datedisplayLen = 0; + int axFlag = 0; + int i; - writePermsEntry(perms, buffer.st_mode); + ob[count].xAcl = xAcl; + ob[count].xattr = xattr; + ob[count].xattrsNum = xattrsNum; + + if (xAcl){ + axFlag = ACL_TRUE; + } + + if (xattr > 0){ + axFlag = ACL_XATTR; + } + + if (seLinuxCon > 0){ + axFlag = ACL_SELINUX; + } + + ob[count].xattrs = malloc(sizeof(char) * xattr); + // strcpy(ob[count].xattrs, xattrs); + for ( i = 0; i < xattr; i++ ){ + ob[count].xattrs[i] = xattrs[i]; + } + + writePermsEntry(perms, buffer.st_mode, axFlag, 0); // Writing our structure if ( markall && !(buffer.st_mode & S_IFDIR) ) { @@ -551,6 +711,9 @@ void writeResultStruct(results* ob, const char * filename, struct stat buffer, i strcpy(ob[count].slink, ""); } + ob[count].contextText = malloc(sizeof(char) * (strlen(contextText) + 1)); + strcpy(ob[count].contextText, contextText); + ob[count].color = typecolor; free(filedate); @@ -567,7 +730,12 @@ int findResultByName(results *ob, char *name) i++; } //If there's no match, we'll fall back to the top item in the list - return 0; + // if (skipToFirstFile == 1 && skippable == 1){ + // return 2; + // } else { + // return 0; + // } + return -1; } char *dateString(time_t date, char *style) @@ -648,20 +816,144 @@ char *genPadding(int num_of_spaces) { return dest; } -void printEntry(int start, int hlinklen, int ownerlen, int grouplen, int authorlen, int sizelen, int majorlen, int minorlen, int datelen, int namelen, int selected, int listref, int topref, results* ob){ +wchar_t *wWriteSegment(int segLen, wchar_t *text, int align){ + wchar_t *segment; + int paddingLen; + char *padding; + int textLen; + int i; + + textLen = wcslen(text); + paddingLen = segLen - textLen; + segment = calloc((segLen + 2), sizeof(wchar_t)); + + if (align == LEFT){ + padding = genPadding(paddingLen); + swprintf(segment, (segLen + 2), L"%ls%s ", text, padding); + } else { + if (paddingLen < 0){ + padding = genPadding(paddingLen - 1); + } else { + padding = genPadding(paddingLen); + } + swprintf(segment, (segLen + 2), L"%s%ls ", padding, text); + } + free(padding); + return(segment); +} + +char *writeSegment(int segLen, char *text, int align){ + // Another wrapper for char to wchar_t + char *segment; + wchar_t *inputText; + wchar_t *wWriteSegmentString; + inputText = calloc((strlen(text) + 1), sizeof(wchar_t)); + swprintf(inputText, (strlen(text) + 1), L"%s", text); + segment = calloc((segLen + 2), sizeof(char)); + wWriteSegmentString = wWriteSegment(segLen, inputText, align); + free(inputText); + sprintf(segment, "%ls", wWriteSegmentString); + free(wWriteSegmentString); + return(segment); +} + +void printXattr(int start, int selected, int listref, int currentItem, int subIndex, xattrList* xa, results* ob){ int i; + int maxlen = COLS - start - 1; + + char *tmpXattrAt; + int xattrAtPos; + bool hasXattr = false; + int tmpXattrDataLen; + char *tmpXattrPrint; + char *tmpXattrSize; + int tmpXattrSizeLen; + char *tmpXattrPadding; + int linepadding; + int xattrKeySegmentLen; + char *xattrKeySegment; + int xattrSizeSegmentLen; + char *xattrSizeSegment; + char xattrPrePad[13] = " "; + char *paddingE0; + + charPos = 0; + + // Setting highlight + if (selected) { + setColors(SELECT_PAIR); + } else { + setColors(DISPLAY_PAIR); + } + + for (i = 0; i < xattrPos; i++){ + if (!strcmp(xa[i].name, ob[currentItem].name)) { + xattrAtPos = i; + break; + } + } + if (human){ + tmpXattrSize = malloc(sizeof(char) * 10); + readableSize(xa[xattrAtPos + subIndex].xattrSize, tmpXattrSize, si); + } else { + tmpXattrSizeLen = snprintf(NULL, 0, "%zu", xa[xattrAtPos + subIndex].xattrSize); + tmpXattrSize = malloc(sizeof(char) * tmpXattrSizeLen); + sprintf(tmpXattrSize, "%zu", xa[xattrAtPos + subIndex].xattrSize); + } + + xattrKeySegment = writeSegment(xattrKeyLen, xa[xattrAtPos + subIndex].xattr, LEFT); + + tmpXattrPrint = calloc(COLS, sizeof(char)); + // tmpXattrDataLen = snprintf(NULL, 0, " %s %s", xa[xattrAtPos + subIndex].xattr, tmpXattrSize); + // tmpXattrPadding = genPadding(COLS - tmpXattrDataLen); + sprintf(tmpXattrPrint, "%s%s%s", xattrPrePad, xattrKeySegment, tmpXattrSize); + for (i = 0; i < maxlen; i++){ + mvprintw(displaystart + listref, start + charPos, "%c", tmpXattrPrint[i]); + charPos++; + if (i == strlen(tmpXattrPrint) - 1){ + break; + } + } + // mvprintw(displaystart + listref + offset + i, start + charPos, " %s", xa[(xattrAtPos + (i - 1))].xattr); + free(tmpXattrPrint); + free(tmpXattrSize); + free(tmpXattrPadding); + + free(xattrKeySegment); + + linepadding = COLS - charPos - start; + + if (linepadding > 0){ + if ((charPos + start) > 0){ + paddingE0 = genPadding(linepadding); + mvprintw(displaystart + listref, charPos + start, "%s", paddingE0); + } else { + paddingE0 = genPadding(COLS); + mvprintw(displaystart + listref, 0, "%s", paddingE0); + } + free(paddingE0); + } + // mvprintw(displaystart + listref + start, 0, " %s %s", "uk.me.robertianhawdon.test", "27"); +} + +void printEntry(int start, int hlinklen, int ownerlen, int grouplen, int authorlen, int sizelen, int majorlen, int minorlen, int datelen, int namelen, int contextlen, int selected, int listref, int currentitem, results* ob){ + + int i, n, t; + char marked[2]; - wchar_t *entryMeta = malloc(sizeof(wchar_t) + 1); + // wchar_t *entryMeta = malloc(sizeof(wchar_t) + 1); wchar_t *entryName = malloc(sizeof(wchar_t) + 1); wchar_t *entrySLink = malloc(sizeof(wchar_t) + 1); int maxlen = COLS - start - 1; - int currentitem = listref + topref; + // int currentitem = listref + topref; + int nameminlen = strlen(headName); // Length of "Name" heading int ogminlen = strlen(headOG); // Length of "Owner & Group" heading int sizeminlen = strlen(headSize); // Length of "Size" heading int dateminlen = strlen(headDT); // Length of "Date" heading + int contextminlen = strlen(headContext); // Length of "Context" heading int oggap, gagap = 0; @@ -669,22 +961,48 @@ void printEntry(int start, int hlinklen, int ownerlen, int grouplen, int authorl char *ogaval; + int hlinkCharLen; + char *hlinkChar; + int ogseglen = ogalen + ogapad; int ogpad = 0; int sizepad = 0; int mmpad = 0; + int contextpad = 0; int datepad = 0; - char *s1, *s2, *s3, *s4; + // char *s1, *s2, *s3, *s4, *s5, *s6; + + char *sizePadding; char *sizestring; + char *contextText; + + int printSegment, printNameSegment = 0; + + int nameCombineLen, nameFullSegPadding; + + char *markedSegment; + char *attrSegment; + char *hlinkSegment; + char *ownerSegment; + char *contextSegment; + char *sizeSegment; + wchar_t *dateSegment; + wchar_t *linkSegment; + nameStruct *nameSegmentData; + + wchar_t *tmpSegment; + int linepadding; int colpos; - char tmpperms[11]; + char tmpperms[12]; + + char *printPerm; struct stat buffer; int status; @@ -695,6 +1013,8 @@ void printEntry(int start, int hlinklen, int ownerlen, int grouplen, int authorl strcpy(slinkpoint, " -> \0"); + charPos = 0; + // Owner, Group, Author switch(ogavis){ case 0: @@ -762,12 +1082,36 @@ void printEntry(int start, int hlinklen, int ownerlen, int grouplen, int authorl if (!ogavis){ ogpad = 0; + ownerSegment = malloc(sizeof(char)); + sprintf(ownerSegment, ""); } else { if ( (ogminlen - ogseglen) > 0 ) { - ogpad = ogminlen - strlen(ogaval); + ownerSegmentLen = ogminlen; } else { - ogpad = ogseglen - strlen(ogaval); + ownerSegmentLen = ogseglen; } + ownerSegment = writeSegment(ownerSegmentLen, ogaval, LEFT); + } + + + if (showContext){ + // Test + // endwin(); + // printf("%s - %s\n", ob[currentitem].name, ob[currentitem].contextText); + contextText = malloc(sizeof(char) * (strlen(ob[currentitem].contextText) + 1)); + sprintf(contextText, "%s", ob[currentitem].contextText); + if (contextlen < contextminlen) { + contextSegmentLen = contextminlen; + } else { + contextSegmentLen = contextlen; + } + contextSegment = writeSegment(contextSegmentLen, contextText, LEFT); + } else { + contextSegmentLen = 1; + contextText = malloc(sizeof(char) * contextSegmentLen); + sprintf(contextText, ""); + contextSegment = malloc(sizeof(char) * contextSegmentLen); + sprintf(contextSegment, ""); } if (ob[currentitem].minor > 1){ @@ -777,13 +1121,15 @@ void printEntry(int start, int hlinklen, int ownerlen, int grouplen, int authorl } if (mmpad > 0 ){ - s4 = genPadding(mmpad); + sizePadding = genPadding(mmpad); } if ((ob[currentitem].major > 0) || (ob[currentitem].minor > 0)){ // If either of these are not 0, then we're dealing with a Character or Block device. - sizestring = malloc (sizeof (char) * (sizelen + 5)); - sprintf(sizestring, "%i,%s%i", ob[currentitem].major, s4, ob[currentitem].minor); + // sizestring = malloc (sizeof (char) * (sizelen + 5)); + sizelen = snprintf(NULL, 0, "%i,%s%i", ob[currentitem].major, sizePadding, ob[currentitem].minor); + sizestring = malloc (sizeof (char) * (sizelen + 1)); + sprintf(sizestring, "%i,%s%i", ob[currentitem].major, sizePadding, ob[currentitem].minor); } else { if (human){ sizestring = malloc (sizeof (char) * 10); @@ -799,37 +1145,107 @@ void printEntry(int start, int hlinklen, int ownerlen, int grouplen, int authorl sizelen = sizeminlen; } - sizepad = (sizelen - strlen(sizestring)) + ogpad + 1; + sizeSegmentLen = sizelen; // this is a mess + + sizepad = (sizelen - strlen(sizestring)); + + // Experemental segment + sizeSegment = writeSegment(sizeSegmentLen, sizestring, RIGHT); if ( (dateminlen - datelen) > 0 ) { - datepad = dateminlen - wcslen(ob[currentitem].datedisplay); + dateSegmentLen = dateminlen; } else { - datepad = datelen - wcslen(ob[currentitem].datedisplay); + dateSegmentLen = datelen; } + dateSegment = wWriteSegment(dateSegmentLen, ob[currentitem].datedisplay, LEFT); - if (hlinkstart > -1){ - s1 = genPadding(hlinkstart); - } - if (sizepad > -1){ - s2 = genPadding(sizepad); + // if (hlinkstart > -1){ + // s1 = genPadding(hlinkstart); + // } + // if (sizepad > -1){ + // s2 = genPadding(sizepad); + // } + // if (datepad > -1){ + // s3 = genPadding(datepad); + // } + + markedSegmentLen = 3; + + if ( *ob[currentitem].marked ){ + markedSegment = writeSegment(markedSegmentLen, "*", RIGHT); + } else { + markedSegment = writeSegment(markedSegmentLen, " ", RIGHT); } - if (datepad > -1){ - s3 = genPadding(datepad); + + if (axDisplay){ + attrSegmentLen = 11; + } else { + attrSegmentLen = 10; } - if ( *ob[currentitem].marked ){ - strcpy(marked, "*"); + if (*ob[currentitem].hlink > 0){ + hlinkCharLen = (log10(*ob[currentitem].hlink) + 2); } else { - strcpy(marked, " "); + hlinkCharLen = 2; + } + + hlinkChar = malloc(sizeof(char) * (hlinkCharLen)); + + sprintf(hlinkChar, "%i", *ob[currentitem].hlink); + + hlinkSegmentLen = hlinklen; // messy + + hlinkSegment = writeSegment(hlinkSegmentLen, hlinkChar, RIGHT); + + free(hlinkChar); + + printPerm = malloc(sizeof(char) * attrSegmentLen + 1); + for (i = 0; i < attrSegmentLen; i++){ + printPerm[i] = ob[currentitem].perm[i]; + printPerm[attrSegmentLen] = '\0'; } - entryMetaLen = snprintf(NULL, 0, " %s %s%s%i %s%s%s %ls%s ", marked, ob[currentitem].perm, s1, *ob[currentitem].hlink, ogaval, s2, sizestring, ob[currentitem].datedisplay, s3); + attrSegment = writeSegment(attrSegmentLen, printPerm, LEFT); - entryMeta = realloc(entryMeta, sizeof(wchar_t) * (entryMetaLen + 1)); + // entryMetaLen = snprintf(NULL, 0, "%s%s%s%s%s%s%ls", markedSegment, attrSegment, hlinkSegment, ownerSegment, contextSegment, sizeSegment, dateSegment); - swprintf(entryMeta, (entryMetaLen + 1), L" %s %s%s%i %s%s%s %ls%s ", marked, ob[currentitem].perm, s1, *ob[currentitem].hlink, ogaval, s2, sizestring, ob[currentitem].datedisplay, s3); + // entryMeta = realloc(entryMeta, sizeof(wchar_t) * (entryMetaLen + 1)); + + // swprintf(entryMeta, (entryMetaLen + 1), L"%s%s%s%s%s%s%ls", markedSegment, attrSegment, hlinkSegment, ownerSegment, contextSegment, sizeSegment, dateSegment); + + free(printPerm); + + // entryMetaLen = wcslen(entryMeta); + + // Writing Name Segment Data + nameSegmentData = malloc(sizeof(nameStruct)); + nameSegmentData[0].name = malloc(sizeof(wchar_t) * (strlen(ob[currentitem].name) + 1)); + swprintf(nameSegmentData[0].name, (strlen(ob[currentitem].name) + 1), L"%s", ob[currentitem].name); + if ( !strcmp(ob[currentitem].slink, "") ){ + nameSegmentData[0].linkStat = 0; + nameSegmentData[0].link = malloc(sizeof(wchar_t)); + } else { + nameSegmentData[0].linkStat = 1; + nameSegmentData[0].link = malloc(sizeof(wchar_t) * (strlen(ob[currentitem].slink) + 1)); + swprintf(nameSegmentData[0].link, (strlen(ob[currentitem].slink) + 1), L"%s", ob[currentitem].slink); + } + if ( nameSegmentData[0].linkStat ){ + nameCombineLen = (wcslen(nameSegmentData[0].name) + wcslen(nameSegmentData[0].link) + 4); + } else { + nameCombineLen = wcslen(nameSegmentData[0].name); + } + if (nameSegLen > nameminlen){ + nameFullSegPadding = nameSegLen - nameCombineLen + 1; + nameSegmentDataLen = nameSegLen; + } else { + nameFullSegPadding = nameminlen - nameCombineLen + 1; + nameSegmentDataLen = nameminlen; + } + if ( nameFullSegPadding < 1 ){ + nameFullSegPadding = 1; + } + nameSegmentData[0].padding = genPadding(nameFullSegPadding); - entryMetaLen = wcslen(entryMeta); entryNameLen = snprintf(NULL, 0, "%s", ob[currentitem].name) + 1; @@ -861,76 +1277,198 @@ void printEntry(int start, int hlinklen, int ownerlen, int grouplen, int authorl setColors(DISPLAY_PAIR); } - for ( i = 0; i < maxlen; i++ ){ - mvprintw(displaystart + listref, start + i,"%lc", entryMeta[i]); - if ( i == entryMetaLen ){ + // // Temp + // if (showXAttrs){ + // hasXattr = false; + // xattrAtPos = 0; + // for(i = 0; i < xattrPos; i++){ + // if (!strcmp(ob[currentitem].name, xa[i].name)){ + // xattrAtPos = i; + // hasXattr = true; + // break; + // } + // } + // // endwin(); + // // printf("\n%s:\n", ob[currentitem].name); + // for(i = 0; i < ob[currentitem].xattrsNum + 1; i++){ + // // printf("%lu < %i\n", (listref - (ob[currentitem].xattrsNum - i)), visibleObjects); + // if ((listref - (ob[currentitem].xattrsNum - i)) < (visibleObjects + visibleOffset)){ + // if (hasXattr && i != 0){ + // if (human){ + // tmpXattrSize = malloc(sizeof(char) * 10); + // readableSize(xa[xattrAtPos + (i - 1)].xattrSize, tmpXattrSize, si); + // } else { + // tmpXattrSizeLen = snprintf(NULL, 0, "%zu", xa[xattrAtPos + (i - 1)].xattrSize); + // tmpXattrSize = malloc(sizeof(char) * tmpXattrSizeLen); + // sprintf(tmpXattrSize, "%zu", xa[xattrAtPos + (i - 1)].xattrSize); + // } + // tmpXattrPrint = calloc(COLS, sizeof(char)); + // tmpXattrDataLen = snprintf(NULL, 0, " %s %s", xa[(xattrAtPos + (i - 1))].xattr, tmpXattrSize); + // tmpXattrPadding = genPadding(COLS - tmpXattrDataLen); + // sprintf(tmpXattrPrint, " %s %s%s", xa[(xattrAtPos + (i - 1))].xattr, tmpXattrSize, tmpXattrPadding); + // for (n = 0; n < strlen(tmpXattrPrint); n++){ + // mvprintw(displaystart + listref + offset + i, start + charPos + n, "%c", tmpXattrPrint[n]); + // } + // // mvprintw(displaystart + listref + offset + i, start + charPos, " %s", xa[(xattrAtPos + (i - 1))].xattr); + // free(tmpXattrPrint); + // free(tmpXattrSize); + // free(tmpXattrPadding); + // } + // } + // } + // } + + for ( n = 0; n < (sizeof(segOrder) / sizeof(segOrder[0])); n++){ + t = segOrder[n]; + switch(t){ + case COL_MARK: + printSegment = 1; + tmpSegmentLen = markedSegmentLen + 2; + tmpSegment = malloc(sizeof(wchar_t) * tmpSegmentLen); + swprintf(tmpSegment, tmpSegmentLen, L"%s", markedSegment); + break; + case COL_ATTR: + printSegment = 1; + tmpSegmentLen = attrSegmentLen + 2; + tmpSegment = malloc(sizeof(wchar_t) * tmpSegmentLen); + swprintf(tmpSegment, tmpSegmentLen, L"%s", attrSegment); + break; + case COL_HLINK: + printSegment = 1; + tmpSegmentLen = hlinkSegmentLen + 2; + tmpSegment = malloc(sizeof(wchar_t) * tmpSegmentLen); + swprintf(tmpSegment, tmpSegmentLen, L"%s", hlinkSegment); + break; + case COL_OWNER: + if (ogavis){ + printSegment = 1; + tmpSegmentLen = ownerSegmentLen + 2; + tmpSegment = malloc(sizeof(wchar_t) * tmpSegmentLen); + swprintf(tmpSegment, tmpSegmentLen, L"%s", ownerSegment); + } + break; + case COL_CONTEXT: + if (showContext){ + printSegment = 1; + tmpSegmentLen = contextSegmentLen + 2; + tmpSegment = malloc(sizeof(wchar_t) * tmpSegmentLen); + swprintf(tmpSegment, tmpSegmentLen, L"%s", contextSegment); + } + break; + case COL_SIZE: + printSegment = 1; + tmpSegmentLen = sizeSegmentLen + 2; + tmpSegment = malloc(sizeof(wchar_t) * tmpSegmentLen); + swprintf(tmpSegment, tmpSegmentLen, L"%s", sizeSegment); + break; + case COL_DATE: + printSegment = 1; + tmpSegmentLen = dateSegmentLen + 2; + tmpSegment = malloc(sizeof(wchar_t) * tmpSegmentLen); + swprintf(tmpSegment, tmpSegmentLen, L"%ls", dateSegment); + break; + case COL_NAME: + printSegment = 0; + printNameSegment = 1; + break; + default: + printSegment = 0; break; } - } - if (filecolors && !selected){ - if ( strcmp(ob[currentitem].slink, "" )) { - if (check_file(ob[currentitem].slink)){ - setColors(SLINK_PAIR); - } else { - setColors(DEADLINK_PAIR); + if (printSegment){ + for ( i = 0; i < maxlen; i++ ){ + mvprintw(displaystart + listref, start + charPos, "%lc", tmpSegment[i]); + charPos++; + if (i == tmpSegmentLen - 2){ + break; + } } - } else { - setColors(ob[currentitem].color); + free(tmpSegment); + printSegment = 0; } - } - for ( i = 0; i < maxlen; i++ ){ - mvprintw(displaystart + listref, (entryMetaLen + start) + i,"%lc", entryName[i]); - if ( i == entryNameLen ){ - colpos = (entryMetaLen + start) + i; - break; - } - } + if (printNameSegment){ + if (filecolors && !selected){ + if ( strcmp(ob[currentitem].slink, "" )) { + if (check_file(ob[currentitem].slink)){ + setColors(SLINK_PAIR); + } else { + setColors(DEADLINK_PAIR); + } + } else { + setColors(ob[currentitem].color); + } + } - if ( strcmp(ob[currentitem].slink, "") ){ - if (!selected){ - setColors(DISPLAY_PAIR); - } + for ( i = 0; i < maxlen; i++ ){ + mvprintw(displaystart + listref, start + charPos, "%lc", nameSegmentData[0].name[i]); + charPos++; + if ( i == wcslen(nameSegmentData[0].name) - 1 ){ + break; + } + } - for ( i = 0; i < strlen(slinkpoint); i++) { - mvprintw(displaystart + listref, (entryMetaLen + entryNameLen + start) + i, "%c", slinkpoint[i]); - } + if ( nameSegmentData[0].linkStat ){ + if (!selected){ + setColors(DISPLAY_PAIR); + } - if (filecolors && !selected){ - if ( strcmp(ob[currentitem].slink, "" )) { - if ( check_dir(ob[currentitem].slink) ){ - setColors(DIR_PAIR); - } else if ( !check_file(ob[currentitem].slink) ){ - setColors(DEADLINK_PAIR); - } else { - // setColors(ob[currentitem].color); - status = lstat(ob[currentitem].slink, &buffer); - setColors(writePermsEntry(tmpperms, buffer.st_mode)); + for ( i = 0; i < strlen(slinkpoint); i++) { + mvprintw(displaystart + listref, start + charPos, "%c", slinkpoint[i]); + charPos++; + } + + if (filecolors && !selected){ + if ( nameSegmentData[0].linkStat ) { + if ( check_dir(ob[currentitem].slink) ){ + setColors(DIR_PAIR); + } else if ( !check_file(ob[currentitem].slink) ){ + setColors(DEADLINK_PAIR); + } else { + // setColors(ob[currentitem].color); + status = lstat(ob[currentitem].slink, &buffer); + setColors(writePermsEntry(tmpperms, buffer.st_mode, -1, 1)); + } + } + } + + for ( i = 0; i < maxlen; i++ ){ + mvprintw(displaystart + listref, start + charPos,"%lc", nameSegmentData[0].link[i]); + charPos++; + if ( i == wcslen(nameSegmentData[0].link) - 1 ){ + break; + } + } } + + if (filecolors && !selected){ + setColors(DISPLAY_PAIR); } - } - for ( i = 0; i < maxlen; i++ ){ - mvprintw(displaystart + listref, (entryMetaLen + entryNameLen + 4 + start) + i,"%lc", entrySLink[i]); - if ( i == entrySLinkLen ){ - colpos = (entryMetaLen + entryNameLen + 4 + start) + i; - break; + for ( i = 0; i < maxlen; i++){ + mvprintw(displaystart + listref, start + charPos, "%c", nameSegmentData[0].padding[i]); + charPos++; + if ( i == strlen(nameSegmentData[0].padding) - 1 ){ + break; + } } - } - } - if (filecolors && !selected){ - setColors(DISPLAY_PAIR); + printNameSegment = 0; + } } - linepadding = COLS - colpos; + free(nameSegmentData[0].name); + free(nameSegmentData[0].link); + free(nameSegmentData[0].padding); + free(nameSegmentData); + linepadding = COLS - charPos - start; if (linepadding > 0){ - if (colpos > -1){ + if ((charPos + start) > 0){ paddingE0 = genPadding(linepadding); - mvprintw(displaystart + listref, colpos, "%s", paddingE0); + mvprintw(displaystart + listref, charPos + start, "%s", paddingE0); } else { paddingE0 = genPadding(COLS); mvprintw(displaystart + listref, 0, "%s", paddingE0); @@ -938,12 +1476,24 @@ void printEntry(int start, int hlinklen, int ownerlen, int grouplen, int authorl free(paddingE0); } - free(s1); - free(s2); - free(s3); - free(s4); + // Free segments + free(markedSegment); + free(attrSegment); + free(hlinkSegment); + free(ownerSegment); + free(contextSegment); + free(sizeSegment); + free(dateSegment); + + // free(s1); + // free(s2); + // free(s3); + // free(s4); + // free(s5); + // free(s6); free(sizestring); - free(entryMeta); + free(sizePadding); + // free(entryMeta); free(entryName); free(entrySLink); free(ogaval); @@ -955,19 +1505,21 @@ void LaunchShell() sprintf(c, "%i", showProcesses); setenv("DFS_RUNNING", c, 1); clear(); + def_prog_mode(); endwin(); // system("clear"); // Not exactly sure if I want this yet. // printf("\nUse 'exit' to return to Show.\n\n"); write(STDOUT_FILENO, "\nUse 'exit' to return to Show.\n\n", 32); system(getenv("SHELL")); + reset_prog_mode(); initscr(); refreshScreen(); } void LaunchExecutable(const char* object, const char* args) { - char *command = malloc(sizeof(char) * (strlen(object) + strlen(args) + 2)); - sprintf(command, "%s %s", object, args); + char *command = malloc(sizeof(char) * (strlen(object) + strlen(args) + 4)); + sprintf(command, "'%s' %s", object, args); system("clear"); // Just to be sure system(command); free(command); @@ -1027,10 +1579,12 @@ int SendToPager(char* object) char *escObject = str_replace(object, "'", "'\"'\"'"); if (can_run_command("sf")){ - setenv("DFS_THEME_OVERRIDE", "TRUE", 1); - page = realloc(page, (sizeof(char) * 3)); - sprintf(page, "sf"); - pset = 1; + if (!useEnvPager){ + setenv("DFS_THEME_OVERRIDE", "TRUE", 1); + page = realloc(page, (sizeof(char) * 3)); + sprintf(page, "sf"); + pset = 1; + } } else { useEnvPager = 1; } @@ -1050,7 +1604,10 @@ int SendToPager(char* object) if (access(object, R_OK) == 0){ // clear(); // endwin(); + def_prog_mode(); + endwin(); e = system(pagerCommand); + reset_prog_mode(); // initscr(); refreshScreen(); return e; @@ -1090,7 +1647,10 @@ int SendToEditor(char* object) if (access(object, R_OK) == 0){ clear(); // endwin(); + def_prog_mode(); + endwin(); e = system(editorCommand); + reset_prog_mode(); // initscr(); refreshScreen(); return e; @@ -1105,22 +1665,31 @@ int SendToEditor(char* object) return 0; } -size_t GetAvailableSpace(const char* path) +uintmax_t GetAvailableSpace(const char* path) { struct statvfs stat; + uintmax_t bavail; + uintmax_t frsize; + uintmax_t result; if (statvfs(path, &stat) != 0) { // error happens, just quits here, but returns 0 return 0; } + bavail = stat.f_bavail; + frsize = stat.f_frsize; + result = bavail * frsize; + // the available size is f_bsize * f_bavail - //return stat.f_bsize * stat.f_bavail; - // // endwin(); - // // clear(); - // // printf("f_bavail: %i\nf_frsize: %i\n", stat.f_bavail, stat.f_frsize); + // return stat.f_bsize * stat.f_bavail; + // endwin(); + // clear(); + // printf("f_bavail: %jd\nf_frsize: %jd\n", (uintmax_t) bavail, (uintmax_t) frsize); + // printf("f_bavail * f_frsize: %jd\n", (uintmax_t) (bavail * frsize)); + // printf("f_bfree: %li\n", stat.f_bfree); // // exit(0); - return stat.f_bavail * stat.f_frsize; + return result; } long GetUsedSpace(const char* path) @@ -1147,49 +1716,57 @@ int seglength(const void *seg, char *segname, int LEN) size_t i; - if (!strcmp(segname, "owner")) { - longest = strlen(dfseg[0].owner); - } - else if (!strcmp(segname, "group")) { - longest = strlen(dfseg[0].group); - } - else if (!strcmp(segname, "author")) { - longest = strlen(dfseg[0].author); - } - else if (!strcmp(segname, "hlink")) { - sprintf(hlinkstr, "%d", *dfseg[0].hlink); - longest = strlen(hlinkstr); - } - else if (!strcmp(segname, "size")) { - if (human){ - readableSize(dfseg[0].size, sizestr, si); - } else { - sprintf(sizestr, "%lu", dfseg[0].size); - } - longest = strlen(sizestr); - } - else if (!strcmp(segname, "major")) { - sprintf(majorstr, "%d", dfseg[0].major); - longest = strlen(majorstr); - } - else if (!strcmp(segname, "minor")) { - sprintf(minorstr, "%d", dfseg[0].minor); - longest = strlen(minorstr); - } - else if (!strcmp(segname, "datedisplay")) { - longest = wcslen(dfseg[0].datedisplay); - } - else if (!strcmp(segname, "name")) { - longest = strlen(dfseg[0].name); - } - else if (!strcmp(segname, "slink")) { - longest = strlen(dfseg[0].slink); - } - else { - longest = 0; - } - - for(i = 1; i < LEN; i++) + // This seems unnessessary, what was I thinking? + + + // if (!strcmp(segname, "owner")) { + // longest = strlen(dfseg[0].owner); + // } + // else if (!strcmp(segname, "group")) { + // longest = strlen(dfseg[0].group); + // } + // else if (!strcmp(segname, "author")) { + // longest = strlen(dfseg[0].author); + // } + // else if (!strcmp(segname, "hlink")) { + // sprintf(hlinkstr, "%d", *dfseg[0].hlink); + // longest = strlen(hlinkstr); + // } + // else if (!strcmp(segname, "size")) { + // if (human){ + // readableSize(dfseg[0].size, sizestr, si); + // } else { + // sprintf(sizestr, "%lu", dfseg[0].size); + // } + // longest = strlen(sizestr); + // } + // else if (!strcmp(segname, "major")) { + // sprintf(majorstr, "%d", dfseg[0].major); + // longest = strlen(majorstr); + // } + // else if (!strcmp(segname, "minor")) { + // sprintf(minorstr, "%d", dfseg[0].minor); + // longest = strlen(minorstr); + // } + // else if (!strcmp(segname, "datedisplay")) { + // longest = wcslen(dfseg[0].datedisplay); + // } + // else if (!strcmp(segname, "name")) { + // longest = strlen(dfseg[0].name); + // } + // else if (!strcmp(segname, "slink")) { + // longest = strlen(dfseg[0].slink); + // } + // else if (!strcmp(segname, "contextText")) { + // longest = strlen(dfseg[0].contextText); + // } + // else { + // longest = 0; + // } + + longest = 0; + + for(i = 0; i < LEN; i++) { if (!strcmp(segname, "owner")) { len = strlen(dfseg[i].owner); @@ -1229,6 +1806,16 @@ int seglength(const void *seg, char *segname, int LEN) else if (!strcmp(segname, "slink")) { len = strlen(dfseg[i].slink); } + else if (!strcmp(segname, "contextText")) { + len = strlen(dfseg[i].contextText); + } + else if (!strcmp(segname, "nameSegBlock")) { + if (strlen(dfseg[i].slink) > 0){ + len = (strlen(dfseg[i].name) + strlen(dfseg[i].slink) + 4); + } else { + len = strlen(dfseg[i].name); + } + } else { len = 0; } @@ -1388,6 +1975,7 @@ int RenameObject(char* source, char* dest) char *destPath; struct stat sourcebuffer; struct stat destbuffer; + struct utimbuf touchDate; int e; destPath = dirFromPath(dest); @@ -1411,9 +1999,24 @@ int RenameObject(char* source, char* dest) } else { // Destination is NOT in the same filesystem, the file will need copying then deleting. //mvprintw(0,66,"FAIL: %s:%s", sourceDevId, destDevId); // test fail - topLineMessage("Error: Unable to move file between mount points"); - free(destPath); - return 1; + if (moveBetweenDevices){ + // To Do + copy_file(source, dest, sourcebuffer.st_mode); + touchDate.actime = sourcebuffer.st_atime; + touchDate.modtime = sourcebuffer.st_mtime; + e = utime(dest, &touchDate); + if (e == 0){ + e = chown(dest, sourcebuffer.st_uid, sourcebuffer.st_gid); + } + if (e == 0){ + e = remove(source); + } + return e; + } else { + topLineMessage("Error: Unable to move file between mount points"); + free(destPath); + return 1; + } } } else { // Destination directory not found @@ -1440,7 +2043,7 @@ int CheckMarked(results* ob) return(result); } -void set_history(char *pwd, char *objectWild, char *name, int topfileref, int selected) +void set_history(char *pwd, char *objectWild, char *name, int lineStart, int selected) { if (sessionhistory == 0){ history *hs = malloc(sizeof(history)); @@ -1461,8 +2064,9 @@ void set_history(char *pwd, char *objectWild, char *name, int topfileref, int se strcpy(hs[historyref].path, pwd); strcpy(hs[historyref].objectWild, objectWild); strcpy(hs[historyref].name, name); - hs[historyref].topfileref = topfileref; + hs[historyref].lineStart = lineStart; hs[historyref].selected = selected; + hs[historyref].visibleObjects = visibleObjects; historyref++; } @@ -1527,7 +2131,7 @@ char *markedDisplay(results* ob) if (markedSize == 0){ markedSizeString = malloc (sizeof (char) * 1); } else { - markedSizeString = malloc (sizeof (char) * (log10(markedSize) + 1)); + markedSizeString = malloc (sizeof (char) * (log10(markedSize) + 2)); } sprintf(markedSizeString, "%lu", markedSize); } @@ -1552,6 +2156,7 @@ char *markedDisplay(results* ob) results* get_dir(char *pwd) { //sused = GetUsedSpace(pwd); // Original DF-EDIT added the sizes to show what was used in that directory, rather than the whole disk. + int i; size_t count = 0; size_t file_count = 0; size_t dirErrorSize = 0; @@ -1561,11 +2166,29 @@ results* get_dir(char *pwd) struct stat buffer; int status; int pass = 0; + int axFlag = 0; char *dirError = malloc(sizeof(char) + 1); // char direrror[1024]; // char filename[256]; + acl_t acl; + acl_entry_t dummy; + int haveAcl; + ssize_t xattr; + char *xattrs; + unsigned char *uXattrs; + int seLinuxCon = 0; + int xattrsNum; + #ifdef HAVE_SELINUX_SELINUX_H + security_context_t context; + #endif + char *contextText; + char *fullFilePath; results *ob = malloc(sizeof(results)); // Allocating a tiny amount of memory. We'll expand this on each file found. + // xattrList *xa = malloc(sizeof(xattrList)); + // int xattrPos = 0; + xa = malloc(sizeof(xattrList)); + xattrPos = 0; fetch: @@ -1574,6 +2197,16 @@ results* get_dir(char *pwd) time ( ¤ttime ); savailable = GetAvailableSpace(pwd); sused = 0; // Resetting used value + axDisplay = 0; + + + if (oneLine){ + segOrder[0] = COL_MARK; + segOrder[1] = COL_NAME; + for (i = 2; i < (sizeof(segOrder) / sizeof(segOrder[0])); i++){ + segOrder[i] = -1; + } + } //if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)){ if (check_object(path) == 1){ @@ -1583,6 +2216,14 @@ results* get_dir(char *pwd) if (access ( path, F_OK ) != -1 ){ if ( folder ){ while ( ( res = readdir ( folder ) ) != NULL ){ + fullFilePath = calloc((strlen(pwd) + 2 + (strlen(res->d_name))), sizeof(char)); + sprintf(fullFilePath, "%s/%s", pwd, res->d_name); + acl = NULL; // Resetting + xattr = 0; // Resetting + seLinuxCon = 0; //Resetting + xattrsNum = 0; + haveAcl = 0; + contextText = malloc(sizeof(char) * 2); if ( showhidden == 0 && check_first_char(res->d_name, ".") && strcmp(res->d_name, ".") && strcmp(res->d_name, "..") ) { continue; // Skipping hidden files } @@ -1607,7 +2248,79 @@ results* get_dir(char *pwd) sprintf(hlinkstr, "%d", buffer.st_nlink); sprintf(sizestr, "%lld", (long long)buffer.st_size); - writeResultStruct(ob, res->d_name, buffer, count); + // axflag here + + // axDisplay = 1; + // axFlag = 0; + + #ifdef HAVE_ACL_TYPE_EXTENDED + // acl = acl_get_file(res->d_name, ACL_TYPE_EXTENDED); + acl = acl_get_link_np(fullFilePath, ACL_TYPE_EXTENDED); + if (acl && acl_get_entry(acl, ACL_FIRST_ENTRY, &dummy) == -1) { + acl_free(acl); + acl = NULL; + } + if (acl != NULL) { + haveAcl = 1; + } + xattr = listxattr(res->d_name, NULL, 0, XATTR_NOFOLLOW); + if (xattr < 0){ + xattr = 0; + } + xattrs = malloc(sizeof(char) * xattr); + listxattr(res->d_name, xattrs, xattr, XATTR_NOFOLLOW); + uXattrs = calloc(xattr, sizeof(unsigned char)); + memcpy(uXattrs, xattrs, xattr); + // endwin(); + // printf("%s\n", uXattrs); + // xa = realloc(xa, (count +1) * sizeof(xattrList)); + xattrPos = processXAttrs(&xa, res->d_name, uXattrs, xattr, xattrPos, &xattrsNum); + free(uXattrs); + // endwin(); + // printf("%s - %zu - %i\n", res->d_name, count, xattrPos); + #else + #ifdef HAVE_SYS_ACL_H + xattrs = malloc(sizeof(char) * 1); + strcpy(xattrs, ""); + #if HAVE_ACL_LIBACL_H + haveAcl = acl_extended_file(res->d_name); + if (haveAcl == -1){ + haveAcl = 0; + } + #endif + // acl = acl_get_file(res->d_name, ACL_TYPE_ACCESS); + // if (errno == ENOENT) { + // acl_free(acl); + // acl = NULL; + // } + #endif + #ifdef HAVE_SELINUX_SELINUX_H + seLinuxCon = lgetfilecon(res->d_name, &context); + if (seLinuxCon > 0){ + contextText = realloc(contextText, sizeof(char) * seLinuxCon); + strcpy(contextText, context); + } else { + seLinuxCon = 0; + } + freecon(context); + #endif + #endif + + if (haveAcl != 0 || seLinuxCon != 0 || xattr != 0){ + axDisplay = 1; + } + + if (seLinuxCon == 0){ + sprintf(contextText, "?"); + } + + writeResultStruct(ob, res->d_name, buffer, count, haveAcl, xattr, seLinuxCon, contextText, xattrs, xattrsNum); + + acl_free(acl); + + free(contextText); + free(xattrs); + free(fullFilePath); sused = sused + buffer.st_size; // Adding the size values @@ -1696,6 +2409,18 @@ results* get_dir(char *pwd) datelen = seglength(ob, "datedisplay", count); namelen = seglength(ob, "name", count); slinklen = seglength(ob, "slink", count); + contextlen = seglength(ob, "contextText", count); + + // nameSegLen = namelen + slinklen + 4; // The 4 is the length of " -> " + nameSegLen = seglength(ob, "nameSegBlock", count); + + xattrKeyLen = 0; + + for (i = 0; i < xattrPos; i++){ + if (xattrKeyLen < strlen(xa[i].xattr)){ + xattrKeyLen = strlen(xa[i].xattr); + } + } free(dirError); free(res); @@ -1706,35 +2431,150 @@ results* reorder_ob(results* ob, char *order){ //mvprintw(2,66,"%i",*ob[0].sys); int count = totalfilecount; + skippable = 0; + if ( !strcmp(order, "name")){ qsort(ob, count, sizeof(results), cmp_dflist_name); } else if ( !strcmp(order, "date")){ + qsort(ob, count, sizeof(results), cmp_dflist_name); qsort(ob, count, sizeof(results), cmp_dflist_date); } else if ( !strcmp(order, "size")){ + qsort(ob, count, sizeof(results), cmp_dflist_name); qsort(ob, count, sizeof(results), cmp_dflist_size); } + if (count > 2){ + if (!strcmp(ob[0].name, ".") && !strcmp(ob[1].name, "..")){ + skippable = 1; + } + } + return ob; } -void display_dir(char *pwd, results* ob, int topfileref, int selected){ +void generateEntryLineIndex(results *ob){ + int i, n, t; + acl_entry_t entry = NULL; + + listLen = totalfilecount; + + if (showXAttrs) { + listLen = totalfilecount + xattrPos; + } + + el = calloc(listLen, sizeof(entryLines)); + n = 0; + for (i = 0; i < totalfilecount; i++){ + entry = NULL; + el[n].entryLineType = ET_OBJECT; + el[n].subIndex = 0; + el[n].fileRef = i; + n++; + if (showXAttrs){ + if (ob[i].xattrsNum > 0){ + for (t = 0; t < ob[i].xattrsNum; t++){ + el[n].entryLineType = ET_XATTR; + el[n].subIndex = t; + el[n].fileRef = i; + n++; + } + } + } + // if (showAcls){ + // if (ob[i].acl != NULL){ + // entry = NULL; + // //endwin(); + // //printf("%i - %i: %s\n", acl_get_entry(ob[i].acl, entry == NULL ? ACL_FIRST_ENTRY : ACL_NEXT_ENTRY, &entry), errno, strerror(errno)); + // for (t = 0; acl_get_entry(ob[i].acl, entry == NULL ? ACL_FIRST_ENTRY : ACL_NEXT_ENTRY, &entry) == 0; t++) { + // listLen++; + // el = realloc(el, sizeof(entryLines) * listLen); + // el[n].entryLineType = ET_ACL; + // el[n].subIndex = t; + // el[n].fileRef = i; + // n++; + // } + // } + // } + } + + // // Test + // endwin(); + // for (i = 0; i < listLen; i++){ + // printf("I: %d, F: %d, T: %d, S: %d\n", i, el[i].fileRef, el[i].entryLineType, el[i].subIndex); + // } + // exit(4); +} + +void adjustViewForSelected(int selected, entryLines* el, int listLen, int displaysize){ + int i; + + for (i = 0; i < listLen; i++){ + if ((el[i].fileRef == selected) && (el[i].entryLineType == ET_OBJECT)){ + if (listLen < displaysize) { + lineStart = 0; + } else if ((i + displaysize) > listLen){ + lineStart = listLen - displaysize; + } else { + lineStart = i; + } + topfileref = el[lineStart].fileRef; + if ((lineStart + displaysize) > listLen){ + bottomFileRef = el[listLen - 1].fileRef; + } else { + bottomFileRef = el[(lineStart + displaysize) - 1].fileRef; + } + break; + } + } +} + +int lineStartFromBottomFileRef(int fileRef, entryLines* el, int listLen, int displaySize){ + int i; + int output = 0; + + for (i = 0; i < listLen; i++){ + if ((el[i].fileRef == fileRef) &&(el[i].entryLineType == ET_OBJECT)){ + if ((i - displaySize) > -1){ + output = i - displaySize + 1; + } else { + output = 0; + } + break; + } + } + return output; +} + +void display_dir(char *pwd, results* ob){ + + int i, n, t; size_t list_count = 0; - int count = totalfilecount; + // int count = totalfilecount; + int count = listLen; int printSelect = 0; //char sizeHeader[256], headings[256]; char *sizeHeader = malloc(sizeof(char) + 1); char *headings = malloc(sizeof(char) + 1); size_t sizeHeaderLen; size_t headingsLen; - int i, s1, s2, s3; + int padIntHeadOG, padIntHeadContext, padIntHeadSize, padIntHeadDT; int headerpos, displaypos; char *susedString, *savailableString; wchar_t *pwdPrint = malloc(sizeof(wchar_t) + 1); size_t pwdPrintSize; - char *markedInfoLine, *padding0, *padding1, *padding2, *padding3; + char *markedInfoLine; + // char *padCharHeadAttrs, *padCharHeadOG, *padCharHeadContext, *padCharHeadSize, *padCharHeadDT; + char *headerCombined = malloc(sizeof(char) + 1); + int headerCombinedLen = 1; + char *markedHeadSeg, *attrHeadSeg, *hlinkHeadSeg, *ownerHeadSeg, *contextHeadSeg, *sizeHeadSeg, *dateHeadSeg, *nameHeadSeg; + int xattrOffset = 0; + int origTopFileRef; + int currentItem; + + topfileref = el[lineStart].fileRef; if (markedinfo == 2 && (CheckMarked(ob) > 0)){ automark = 1; @@ -1748,14 +2588,86 @@ void display_dir(char *pwd, results* ob, int topfileref, int selected){ } else{ displaysize = LINES - 5; displaystart = 4; - if ((totalfilecount >= displaysize) && (topfileref + (displaysize ) > totalfilecount )){ - topfileref--; - } + // TO DO: REFACTOR + // if ((totalfilecount >= displaysize) && (lineStart + (displaysize ) > totalfilecount )){ + // lineStart--; + // } + } + + // endwin(); + if ((lineStart + displaysize) > listLen){ + bottomFileRef = el[listLen - 1].fileRef; + } else { + bottomFileRef = el[(lineStart + displaysize) - 1].fileRef; + } + + // Replacement to "sanitizeTopFileRef" - should be simpler with the lookup table. + if ((selected > bottomFileRef) || ((selected < topfileref + 1))){ + adjustViewForSelected(selected, el, listLen, displaysize); + } + + i = 0; + + rerunCalc: + + // Hacky, but this will stop show hanging if the topfileref check fails after 50 times. It's in place as if CTRL-C is disabled, then this lock can't be exited without killing show from another terminal. + if (i > 50){ + exit(27); + } + + lineCount = 0; + // bottomFileRef = 0; + visibleOffset = 0; + + // origTopFileRef = topfileref; + + // for(list_count = topfileref; list_count < totalfilecount; list_count++ ){ + // lineCount++; + + // if (showXAttrs){ + // lineCount += ob[list_count].xattrsNum; + // // visibleOffset += ob[list_count].xattrsNum; + // } + + // if (lineCount > displaysize){ + // // lineCount--; + // break; + // } + // // bottomFileRef = list_count; + // } + + // visibleObjects = bottomFileRef - topfileref + 1; + + // // Hacky, but it works. + // if ((visibleObjects + visibleOffset) > displaysize){ + // visibleOffset -= (visibleObjects + visibleOffset) - displaysize; + // } + + if (displaysize > count){ + displaycount = count + 1; + } else { + displaycount = displaysize; + } + + // displaycount = visibleObjects; + + if (displaycount < 0){ + displaycount = 0; } - topfileref = sanitizeTopFileRef(topfileref); + // topfileref = sanitizeTopFileRef(topfileref); + // endwin(); + // printf("OTFR: %i, NTFR: %i\n", origTopFileRef, topfileref); + + // if (topfileref != origTopFileRef){ + // i++; + // goto rerunCalc; + // } + + // printf("\n"); + + // selected = selected - topfileref; - selected = selected - topfileref; pwdPrintSize = (strlen(pwd) + strlen(objectWild) + 2); @@ -1776,19 +2688,25 @@ void display_dir(char *pwd, results* ob, int topfileref, int selected){ if (sused == 0){ susedString = malloc (sizeof (char) * 1); } else { - susedString = malloc (sizeof (char) * (log10(sused) + 1)); + susedString = malloc (sizeof (char) * (log10(sused) + 2)); } if (savailable == 0){ savailableString = malloc (sizeof (char) * 1); } else { - savailableString = malloc (sizeof (char) * (log10(savailable) + 1)); + savailableString = malloc (sizeof (char) * (log10(savailable) + 2)); } sprintf(susedString, "%lu", sused); - sprintf(savailableString, "%lu", savailable); + sprintf(savailableString, "%ju", (uintmax_t) savailable); } strcpy(headAttrs, "---Attrs---"); + if (showContext){ + strcpy(headContext, "---Context---"); + } else { + strcpy(headContext, ""); + } + if ( mmMode ){ strcpy(headSize, "-Driver/Size-"); } else { @@ -1836,34 +2754,63 @@ void display_dir(char *pwd, results* ob, int topfileref, int selected){ break; } - if (displaysize > count){ - displaycount = count; - } else { - displaycount = displaysize; - } + // mvprintw(LINES-1, 0, "bottomFileRef: %i", bottomFileRef); + // mvprintw(LINES-1, 0, "visibleObjects: %i", visibleObjects); + // if (showXAttrs){ + // if (display) + // } else { + // } - if (displaycount < 0){ - displaycount = 0; + if (el[lineStart].entryLineType != ET_OBJECT){ + topfileref++; } - for(list_count = 0; list_count < displaycount; list_count++ ){ - if (list_count < totalfilecount){ + for(list_count = 0; list_count < displaycount + 1; list_count++ ){ + // endwin(); + // printf("%zu, %i, %i, - %i\n", list_count, lineStart, listLen, displaycount + 1); + if ((list_count + lineStart) < listLen){ // Setting highlight - if (list_count == selected) { + // if (list_count == selected) { + if (el[(list_count + lineStart)].fileRef == selected) { printSelect = 1; } else { printSelect = 0; } - ownstart = hlinklen + 2; - hlinkstart = ownstart - 1 - *ob[list_count + topfileref].hlinklens; + // ownstart = hlinklen + 2; + // hlinkstart = ownstart - 1 - *ob[list_count + lineStart].hlinklens; displaypos = 0 - hpos; + currentItem = el[(list_count + lineStart)].fileRef; + // endwin(); // printf("LC: %i, TFR: %i, DC: %i\n", list_count, topfileref, displaycount); - printEntry(displaypos, hlinklen, ownerlen, grouplen, authorlen, sizelen, majorlen, minorlen, datelen, namelen, printSelect, list_count, topfileref, ob); + // printf("DP: %i, HL: %i, OL: %i, GL: %i, AL: %i, SL: %i, MaL: %i, MiL: %i, DL: %i, NL: %i, CL: %i, PS: %i, LC: %i, TF: %i, XO: %i\n", displaypos, hlinklen, ownerlen, grouplen, authorlen, sizelen, majorlen, minorlen, datelen, namelen, contextlen, printSelect, list_count, topfileref, xattrOffset); + // mvprintw(list_count + 4, 0, "DP: %i, HL: %i, OL: %i, GL: %i, AL: %i, SL: %i, MaL: %i, MiL: %i, DL: %i, NL: %i, CL: %i, PS: %i, LC: %i, TF: %i, XO: %i", displaypos, hlinklen, ownerlen, grouplen, authorlen, sizelen, majorlen, minorlen, datelen, namelen, contextlen, printSelect, list_count, topfileref, xattrOffset); + if (el[(list_count + lineStart)].entryLineType == ET_OBJECT){ + printEntry(displaypos, hlinklen, ownerlen, grouplen, authorlen, sizelen, majorlen, minorlen, datelen, namelen, contextlen, printSelect, list_count, currentItem, ob); + // mvprintw(displaystart + list_count, 0, "%i - THIS SHOULDN'T BE HERE! - %s", printSelect, ob[el[(list_count + lineStart)].fileRef].name); + } else if (el[(list_count + lineStart)].entryLineType == ET_ACL) { + // Not implemented yet + } else if (el[(list_count + lineStart)].entryLineType == ET_XATTR) { + // Not implemented yet + printXattr(displaypos, printSelect, list_count, currentItem, el[(list_count + lineStart)].subIndex, xa, ob); + } else { + mvprintw(displaystart + list_count, 0, "THIS SHOULDN'T BE HERE! - entryLineType: %d", el[(list_count + lineStart)].entryLineType); + } + + if (charPos > maxdisplaywidth){ + maxdisplaywidth = charPos; + } + + // if (showXAttrs && ob[list_count + topfileref].xattrsNum > 0){ + // // displaysize = displaysize - ob[list_count + topfileref].xattrsNum; + // // displaycount = displaycount + ob[list_count + topfileref].xattrsNum; + // // list_count = list_count + ob[list_count + topfileref].xattrsNum; + // xattrOffset += ob[list_count + topfileref].xattrsNum; + // } //list_count++; } else { @@ -1871,60 +2818,145 @@ void display_dir(char *pwd, results* ob, int topfileref, int selected){ } } - if (slinklen == 0){ - maxdisplaywidth = entryMetaLen + namelen; - } else { - // maxdisplaywidth = entryMetaLen + namelen + slinklen + 4; - maxdisplaywidth = entryMetaLen + nameAndSLink; - } + + // if (slinklen == 0){ + // maxdisplaywidth = charPos + namelen; + // } else { + // // maxdisplaywidth = entryMetaLen + namelen + slinklen + 4; + // maxdisplaywidth = charPos + nameAndSLink; + // } //mvprintw(0, 66, "%d %d", historyref, sessionhistory); // the space between the largest owner and largest group should always end up being 1... in theory. // 2018-07-05: That assumption was solid, until we added a third element (Owner, Group, and Author) if (!ogavis){ - s1 = 1; + padIntHeadOG = 0; } else { if ( (ogalen + ogapad) > strlen(headOG)){ - s1 = (ogalen + ogapad) - strlen(headOG) + 1; + padIntHeadOG = (ogalen + ogapad) - strlen(headOG) + 1; } else { - s1 = 1; + padIntHeadOG = 1; } } + if ( showContext ){ + if ( contextlen > strlen(headContext)){ + padIntHeadContext = ((contextlen - strlen(headContext)) + 1 ); + } else { + padIntHeadContext = 1; + } + } else { + padIntHeadContext = 0; + } + if ( sizelen > strlen(headSize)) { - s2 = sizelen - strlen(headSize); + padIntHeadSize = sizelen - strlen(headSize); } else { - s2 = 0; + padIntHeadSize = 0; } if ( datelen > strlen(headDT)) { - s3 = (datelen - strlen(headDT)) + 1; + padIntHeadDT = (datelen - strlen(headDT)) + 1; } else { - s3 = 1; + padIntHeadDT = 1; } - sizeHeaderLen = snprintf(NULL, 0, "%i Objects %s Used %s Available", count, susedString, savailableString); + sizeHeaderLen = snprintf(NULL, 0, "%i Objects %s Used %s Available", totalfilecount, susedString, savailableString); sizeHeader = realloc(sizeHeader, sizeof(char) * (sizeHeaderLen + 1)); - sprintf(sizeHeader, "%i Objects %s Used %s Available", count, susedString, savailableString); - - padding0 = genPadding(hlinklen + 1); - padding1 = genPadding(s1); - padding2 = genPadding(s2); - padding3 = genPadding(s3); - - headingsLen = snprintf(NULL, 0, "%s%s%s%s%s%s%s%s%s%s", headAttrs, padding0, headOG, padding1, padding2, headSize, " ", headDT, padding3, headName); - - headings = realloc(headings, sizeof(char) * (headingsLen + 1)); + sprintf(sizeHeader, "%i Objects %s Used %s Available", totalfilecount, susedString, savailableString); + + // padCharHeadAttrs = genPadding(hlinklen + 1 + axDisplay); + // padCharHeadOG = genPadding(padIntHeadOG); + // padCharHeadContext = genPadding(padIntHeadContext); + // padCharHeadSize = genPadding(padIntHeadSize); + // padCharHeadDT = genPadding(padIntHeadDT); + + // headingsLen = snprintf(NULL, 0, "%s%s%s%s%s%s%s%s%s%s%s%s", headAttrs, padCharHeadAttrs, headOG, padCharHeadOG, headContext, padCharHeadContext, padCharHeadSize, headSize, " ", headDT, padCharHeadDT, headName); + + // headings = realloc(headings, sizeof(char) * (headingsLen + 1)); + + // sprintf(headings, "%s%s%s%s%s%s%s%s%s%s%s%s", headAttrs, padCharHeadAttrs, headOG, padCharHeadOG, headContext, padCharHeadContext, padCharHeadSize, headSize, " ", headDT, padCharHeadDT, headName); + + markedHeadSeg = writeSegment(3, "", RIGHT); + attrHeadSeg = writeSegment(attrSegmentLen, headAttrs, LEFT); + hlinkHeadSeg = writeSegment(hlinkSegmentLen, "", RIGHT); + ownerHeadSeg = writeSegment(ownerSegmentLen, headOG, LEFT); + contextHeadSeg = writeSegment(contextSegmentLen, headContext, LEFT); + sizeHeadSeg = writeSegment(sizeSegmentLen, headSize, RIGHT); + dateHeadSeg = writeSegment(dateSegmentLen, headDT, LEFT); + nameHeadSeg = writeSegment(nameSegmentDataLen, headName, LEFT); + + sprintf(headerCombined, ""); + for ( n = 0; n < (sizeof(segOrder) / sizeof(segOrder[0])); n++){ + t = segOrder[n]; + switch(t){ + case COL_MARK: + headerCombinedLen = (headerCombinedLen + strlen(markedHeadSeg)); + headerCombined = realloc(headerCombined, sizeof(char) * headerCombinedLen); + strcat(headerCombined, markedHeadSeg); + break; + case COL_ATTR: + headerCombinedLen = (headerCombinedLen + strlen(attrHeadSeg)); + headerCombined = realloc(headerCombined, sizeof(char) * headerCombinedLen); + strcat(headerCombined, attrHeadSeg); + break; + case COL_HLINK: + headerCombinedLen = (headerCombinedLen + strlen(hlinkHeadSeg)); + headerCombined = realloc(headerCombined, sizeof(char) * headerCombinedLen); + strcat(headerCombined, hlinkHeadSeg); + break; + case COL_OWNER: + if (ogavis){ + headerCombinedLen = (headerCombinedLen + strlen(ownerHeadSeg)); + headerCombined = realloc(headerCombined, sizeof(char) * headerCombinedLen); + strcat(headerCombined, ownerHeadSeg); + } + break; + case COL_CONTEXT: + if (showContext){ + headerCombinedLen = (headerCombinedLen + strlen(contextHeadSeg)); + headerCombined = realloc(headerCombined, sizeof(char) * headerCombinedLen); + strcat(headerCombined, contextHeadSeg); + } + break; + case COL_SIZE: + headerCombinedLen = (headerCombinedLen + strlen(sizeHeadSeg)); + headerCombined = realloc(headerCombined, sizeof(char) * headerCombinedLen); + strcat(headerCombined, sizeHeadSeg); + break; + case COL_DATE: + headerCombinedLen = (headerCombinedLen + strlen(dateHeadSeg)); + headerCombined = realloc(headerCombined, sizeof(char) * headerCombinedLen); + strcat(headerCombined, dateHeadSeg); + break; + case COL_NAME: + headerCombinedLen = (headerCombinedLen + strlen(nameHeadSeg)); + headerCombined = realloc(headerCombined, sizeof(char) * headerCombinedLen); + strcat(headerCombined, nameHeadSeg); + break; + default: + break; + } + } - sprintf(headings, "%s%s%s%s%s%s%s%s%s%s", headAttrs, padding0, headOG, padding1, padding2, headSize, " ", headDT, padding3, headName); + // Freeing Segments + free(markedHeadSeg); + free(attrHeadSeg); + free(hlinkHeadSeg); + free(ownerHeadSeg); + free(contextHeadSeg); + free(sizeHeadSeg); + free(dateHeadSeg); + free(nameHeadSeg); - free(padding0); - free(padding1); - free(padding2); - free(padding3); + // free(padCharHeadAttrs); + // free(padCharHeadOG); + // free(padCharHeadContext); + // free(padCharHeadSize); + // free(padCharHeadDT); if ( danger ) { setColors(DANGER_PAIR); @@ -1950,32 +2982,35 @@ void display_dir(char *pwd, results* ob, int topfileref, int selected){ setColors(HEADING_PAIR); } - headerpos = 4 - hpos; + // headerpos = 4 - hpos; if (markedinfo == 1 || (markedinfo == 2 && (CheckMarked(ob) > 0))){ - printLine (4, headerpos, headings); + // printLine (4, headerpos, headings); + printLine (4, (0 - hpos), headerCombined); } else { - printLine (3, headerpos, headings); + // printLine (3, headerpos, headings); + printLine (3, (0 - hpos), headerCombined); } setColors(COMMAND_PAIR); free(susedString); free(savailableString); free(sizeHeader); free(headings); + free(headerCombined); } void resizeDisplayDir(results* ob){ displaysize = (LINES - 5); - if ( (selected - topfileref) > (LINES - 6 )) { - topfileref = selected - (LINES - 6); - } else if ( topfileref + (LINES - 6) > totalfilecount ) { + if ( (selected - lineStart) > (LINES - 6 )) { + lineStart = selected - (LINES - 6); + } else if ( lineStart + (LINES - 6) > totalfilecount ) { if (totalfilecount < (LINES - 6)){ - topfileref = 0; + lineStart = 0; } else { - topfileref = totalfilecount - (LINES - 5); + lineStart = totalfilecount - (LINES - 5); } } - refreshDirectory(sortmode, topfileref, selected, -1); - // display_dir(currentpwd, ob, topfileref, selected); + refreshDirectory(sortmode, lineStart, selected, -1); + // display_dir(currentpwd, ob); } diff --git a/src/showfunctions.h b/src/showfunctions.h index b49b64a..96be791 100644 --- a/src/showfunctions.h +++ b/src/showfunctions.h @@ -1,8 +1,40 @@ #include +#include + +#define MULTICHAR '*' +#define ONECHAR '?' + +#define ACL_NONE 0 +#define ACL_TRUE 1 +#define ACL_SELINUX 2 // Linux Specific +#define ACL_XATTR 3 // macOS Specific + +#define LEFT 0 +#define RIGHT 1 + +#define COL_MARK 0 +#define COL_ATTR 1 +#define COL_HLINK 2 +#define COL_OWNER 3 +#define COL_CONTEXT 4 +#define COL_SIZE 5 +#define COL_DATE 6 +#define COL_NAME 7 + +#define ET_OBJECT 0 +#define ET_ACL 1 +#define ET_XATTR 2 + +#define V_TOP 0; +#define V_BOTTOM 1; typedef struct { int marked[1]; mode_t mode; + bool xAcl; + ssize_t xattr; + int seLinuxCon; + char *contextText; char *perm; int hlink[4]; int hlinklens[5]; @@ -19,19 +51,46 @@ typedef struct { char *name; char *slink; int color; + char *xattrs; + int xattrsNum; } results; typedef struct { char *path; char *name; char *objectWild; - int topfileref; + int lineStart; int selected; + int visibleObjects; } history; +typedef struct { + char *name; + char *xattr; + size_t xattrSize; +} xattrList; + +typedef struct { + wchar_t *name; + int linkStat; + wchar_t *link; + char *padding; +} nameStruct; + +typedef struct { + int fileRef; + int entryLineType; + int subIndex; +} entryLines; + +void adjustViewForSelected(int selected, entryLines* el, int listLen, int displaysize); +int lineStartFromBottomFileRef(int fileRef, entryLines* el, int listLen, int displaySize); int checkRunningEnv(); void freeResults(results *ob, int count); void freeHistory(history *hs, int count); +void freeXAttrs(xattrList *xa, int count); +int processXAttrs(xattrList **xa, char *name, unsigned char *xattrs, size_t xattrLen, int pos, int *xattrsNum); +void generateEntryLineIndex(results *ob); char *getRelativePath(char *file, char *target); int wildcard(const char *value, char *wcard); int findResultByName(results *ob, char *name); @@ -47,9 +106,9 @@ int cmp_dflist_date(const void *lhs, const void *rhs); int cmp_dflist_size(const void *lhs, const void *rhs); results* get_dir(char *pwd); results* reorder_ob(results* ob, char *order); -void display_dir(char *pwd, results* ob, int topfileref, int selected); -void set_history(char *pwd, char *objectWild, char *name, int topfileref, int selected); -size_t GetAvailableSpace(const char* path); +void display_dir(char *pwd, results* ob); +void set_history(char *pwd, char *objectWild, char *name, int lineStart, int selected); +uintmax_t GetAvailableSpace(const char* path); long GetUsedSpace(const char* path); int SendToPager(char* object); int SendToEditor(char* object); @@ -59,15 +118,16 @@ void LaunchExecutable(const char* object, const char* args); int UpdateOwnerGroup(const char* object, const char* pwdstr, const char* grpstr); int RenameObject(char* source, char* dest); int CheckMarked(results* ob); -void printEntry(int start, int hlinklen, int ownerlen, int grouplen, int authorlen, int sizelen, int majorlen, int minorlen, int datelen, int namelen, int selected, int listref, int topref, results* ob); +wchar_t *wWriteSegment(int segLen, wchar_t *text, int align); +char *writeSegment(int segLen, char *text, int align); +void printEntry(int start, int hlinklen, int ownerlen, int grouplen, int authorlen, int sizelen, int majorlen, int minorlen, int datelen, int namelen, int contextlen, int selected, int listref, int currentitem, results* ob); +void printXattr(int start, int selected, int listref, int currentItem, int subIndex, xattrList* xa, results* ob); void padstring(char *str, int len, char c); char *genPadding(int num_of_spaces); void resizeDisplayDir(results* ob); char *readableSize(double size, char *buf, int si); -int writePermsEntry(char * perms, mode_t mode); -void writeResultStruct(results* ob, const char * filename, struct stat buffer, int count); +int writePermsEntry(char * perms, mode_t mode, int axFlag, int sLinkCheck); +void writeResultStruct(results* ob, const char * filename, struct stat buffer, int count, bool xAcl, ssize_t xattr, int seLinuxCon, char * contextText, char * xattrs, const int xattrsNum); char *markedDisplay(results* ob); int huntFile(const char * file, const char * search, int charcase); -#define MULTICHAR '*' -#define ONECHAR '?' diff --git a/src/showmenus.c b/src/showmenus.c index d500eec..d885afb 100644 --- a/src/showmenus.c +++ b/src/showmenus.c @@ -1,6 +1,7 @@ /* - DF-SHOW - A clone of 'SHOW' directory browser from DF-EDIT by Larry Kroeker - Copyright (C) 2018-2019 Robert Ian Hawdon + DF-SHOW: An interactive directory/file browser written for Unix-like systems. + Based on the applications from the PC-DOS DF-EDIT suite by Larry Kroeker. + Copyright (C) 2018-2020 Robert Ian Hawdon This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -70,6 +71,9 @@ extern int historyref; extern int sessionhistory; extern int selected; extern int topfileref; +extern int lineStart; +extern int bottomFileRef; +extern int visibleObjects; extern int hpos; extern int maxdisplaywidth; extern int totalfilecount; @@ -80,6 +84,9 @@ extern int markall; extern int viewMode; extern int markedinfo; extern int automark; +extern int skipToFirstFile; + +extern int skippable; extern int plugins; @@ -103,6 +110,15 @@ extern int dirAbort; extern int exitCode; +extern xattrList *xa; +extern int xattrPos; + +extern int visibleOffset; + +extern entryLines *el; + +extern int listLen; + menuDef *globalMenu; int globalMenuSize = 0; wchar_t *globalMenuLabel; @@ -291,7 +307,7 @@ int sanitizeTopFileRef(int topfileref) return topfileref; } -void refreshDirectory(char *sortmode, int origtopfileref, int origselected, int destructive) +void refreshDirectory(char *sortmode, int origlineStart, int origselected, int destructive) { char currentselectname[512]; int i; @@ -310,13 +326,15 @@ void refreshDirectory(char *sortmode, int origtopfileref, int origselected, int } if (destructive != -1){ freeResults(ob, totalfilecount); + freeXAttrs(xa, xattrPos); ob = get_dir(currentpwd); clear_workspace(); reorder_ob(ob, sortmode); + generateEntryLineIndex(ob); } if (destructive > 0){ i = findResultByName(ob, currentselectname); - if (i != 0){ + if (i != -1){ selected = i; } else { if (selected > totalfilecount - 1){ @@ -327,21 +345,43 @@ void refreshDirectory(char *sortmode, int origtopfileref, int origselected, int } } else { selected = findResultByName(ob, currentselectname); + } } else { - strcpy(currentpwd, hs[historyref - 2].path); - objectWild = hs[historyref - 2].objectWild; - historyref--; - chdir(currentpwd); - goto handleMissingDir; + if (historyref > 1){ + strcpy(currentpwd, hs[historyref - 2].path); + objectWild = hs[historyref - 2].objectWild; + historyref--; + chdir(currentpwd); + goto handleMissingDir; + } else { + global_menu(); + } } - topfileref = sanitizeTopFileRef(origtopfileref); + // topfileref = sanitizeTopFileRef(origtopfileref); if (dirAbort == 1){ - topfileref = hs[historyref].topfileref; + lineStart = hs[historyref].lineStart; selected = hs[historyref].selected; dirAbort = 0; } - display_dir(currentpwd, ob, topfileref, selected); + if (destructive == -2){ + if (skipToFirstFile == 1 && skippable == 1){ + selected = 2; + } else { + selected = 0; + } + } + // endwin(); + // printf("%i\n", selected); + // exit(123); + if (selected == -1){ + if (skipToFirstFile == 1 && skippable == 1){ + selected = 2; + } else { + selected = 0; + } + } + display_dir(currentpwd, ob); } void directory_view_menu_inputs(); // Needed to allow menu inputs to switch between each other @@ -387,12 +427,12 @@ void show_directory_input() // invalidstart = 0; set_history(currentpwd, "", "", 0, 0); } else { - set_history(currentpwd, objectWild, ob[selected].name, topfileref, selected); + set_history(currentpwd, objectWild, ob[selected].name, lineStart, selected); } - topfileref = 0; + lineStart = 0; selected = 0; chdir(currentpwd); - refreshDirectory(sortmode, 0, selected, 0); + refreshDirectory(sortmode, 0, selected, -2); } else { direrrorLen = snprintf(NULL, 0, "The location %s cannot be opened or is not a directory\n", currentpwd); direrror = realloc(direrror, sizeof(char) * (direrrorLen + 1)); @@ -622,7 +662,7 @@ void edit_file_input() readline(filepath, 4096, ""); curs_set(FALSE); SendToEditor(filepath); - refreshDirectory(sortmode, topfileref, selected, 1); + refreshDirectory(sortmode, lineStart, selected, 1); } void rename_file_input(char *file) @@ -716,6 +756,11 @@ void make_directory_input() } } // curs_set(FALSE); + testSlash: + if (check_last_char(currentpwd, "/") && strcmp(currentpwd, "/")){ + currentpwd[strlen(currentpwd) - 1] = '\0'; + goto testSlash; + } refreshDirectory(sortmode, 0, selected, 0); } directory_view_menu_inputs(); @@ -859,6 +904,11 @@ void touch_file_input() topLineMessage(errmessage); } } + testSlash: + if (check_last_char(currentpwd, "/") && strcmp(currentpwd, "/")){ + currentpwd[strlen(currentpwd) - 1] = '\0'; + goto testSlash; + } refreshDirectory(sortmode, 0, selected, 0); } directory_view_menu_inputs(); @@ -982,7 +1032,7 @@ void delete_file_confirm_input(char *file) { case 'y': delete_file(file); - refreshDirectory(sortmode, topfileref, selected, 1); + refreshDirectory(sortmode, lineStart, selected, 1); // Not breaking here, intentionally dropping through to the default default: directory_view_menu_inputs(); @@ -1006,7 +1056,7 @@ void delete_directory_confirm_input(char *directory) sprintf(errmessage, "Error: %s", strerror(errno)); topLineMessage(errmessage); } - refreshDirectory(sortmode, topfileref, selected, 1); + refreshDirectory(sortmode, lineStart, selected, 1); // Not breaking here, intentionally dropping through to the default default: directory_view_menu_inputs(); @@ -1100,7 +1150,7 @@ void sort_view_inputs() strcpy(sortmode, "size"); reverse = 1; } - refreshDirectory(sortmode, topfileref, selected, 0); + refreshDirectory(sortmode, lineStart, selected, 0); directory_view_menu_inputs(); } } @@ -1181,7 +1231,7 @@ void modify_group_input() } free(ofile); } - refreshDirectory(sortmode, topfileref, selected, 0); + refreshDirectory(sortmode, lineStart, selected, 0); directory_view_menu_inputs(); } @@ -1279,7 +1329,7 @@ void modify_permissions_input() chmod(pfile, newperm); free(pfile); } - refreshDirectory(sortmode, topfileref, selected, 0); + refreshDirectory(sortmode, lineStart, selected, 0); } directory_view_menu_inputs(); @@ -1463,7 +1513,7 @@ void directory_view_menu_inputs() } else if (*pc == menuHotkeyLookup(fileMenu, "f_delete", fileMenuSize)){ if ( (CheckMarked(ob) > 0) ) { delete_multi_file_confirm_input(ob); - refreshDirectory(sortmode, topfileref, selected, 1); + refreshDirectory(sortmode, lineStart, selected, 1); directory_view_menu_inputs(); } else { strcpy(selfile, currentpwd); @@ -1485,7 +1535,7 @@ void directory_view_menu_inputs() strcat(chpwd, ob[selected].name); if (!check_dir(chpwd)){ SendToEditor(chpwd); - refreshDirectory(sortmode, topfileref, selected, 1); + refreshDirectory(sortmode, lineStart, selected, 1); } } else if (*pc == menuHotkeyLookup(fileMenu, "f_hidden", fileMenuSize)){ strcpy(currentfilename, ob[selected].name); @@ -1495,11 +1545,20 @@ void directory_view_menu_inputs() showhidden = 0; } freeResults(ob, totalfilecount); + freeXAttrs(xa, xattrPos); ob = get_dir(currentpwd); clear_workspace(); reorder_ob(ob, sortmode); + generateEntryLineIndex(ob); selected = findResultByName(ob, currentfilename); - refreshDirectory(sortmode, topfileref, selected, 0); + if (selected == -1){ + if (skipToFirstFile == 1 && skippable == 1){ + selected = 2; + } else { + selected = 0; + } + } + refreshDirectory(sortmode, lineStart, selected, 0); } else if (*pc == menuHotkeyLookup(fileMenu, "f_link", fileMenuSize)){ if ( !(CheckMarked(ob) > 0) ) { link_key_menu_inputs(); @@ -1519,12 +1578,24 @@ void directory_view_menu_inputs() strcpy(currentpwd, chpwd); chdir(currentpwd); freeResults(ob, totalfilecount); + freeXAttrs(xa, xattrPos); ob = get_dir(currentpwd); reorder_ob(ob, sortmode); + generateEntryLineIndex(ob); selected = findResultByName(ob, hs[historyref].name); - topfileref = sanitizeTopFileRef(hs[historyref].topfileref); + if (selected == -1){ + if (skipToFirstFile == 1 && skippable == 1){ + selected = 2; + } else { + selected = 0; + } + } + // visibleObjects = hs[historyref].visibleObjects; + // topfileref = sanitizeTopFileRef(hs[historyref].topfileref); + // topfileref = hs[historyref].topfileref; + lineStart = hs[historyref].lineStart; clear_workspace(); - display_dir(currentpwd, ob, topfileref, selected); + display_dir(currentpwd, ob); } else { // Skip removed directories historyref--; @@ -1563,28 +1634,28 @@ void directory_view_menu_inputs() chpwd[strlen(chpwd) - 1] = '\0'; goto testSlash; } - set_history(chpwd, objectWild, ob[selected].name, topfileref, selected); - topfileref = 0; + set_history(chpwd, objectWild, ob[selected].name, lineStart, selected); + lineStart = 0; selected = 0; strcpy(currentpwd, chpwd); chdir(currentpwd); - refreshDirectory(sortmode, topfileref, selected, 0); + refreshDirectory(sortmode, lineStart, selected, -2); } } else if (!strcmp(ob[selected].name, ".")) { // Do nothing } else { if (check_dir(chpwd)){ objectWild = ""; - set_history(chpwd, objectWild, ob[selected].name, topfileref, selected); - topfileref = 0; + set_history(chpwd, objectWild, ob[selected].name, lineStart, selected); + lineStart = 0; selected = 0; strcpy(currentpwd, chpwd); chdir(currentpwd); - refreshDirectory(sortmode, topfileref, selected, 0); + refreshDirectory(sortmode, lineStart, selected, -2); } else { e = SendToPager(chpwd); - refreshDirectory(sortmode, topfileref, selected, 1); - // display_dir(currentpwd, ob, topfileref, selected); + refreshDirectory(sortmode, lineStart, selected, 1); + // display_dir(currentpwd, ob); } } } else if (*pc == menuHotkeyLookup(fileMenu, "f_touch", fileMenuSize)){ @@ -1616,14 +1687,14 @@ void directory_view_menu_inputs() abortinput = 0; } } - refreshDirectory(sortmode, topfileref, selected, 0); + refreshDirectory(sortmode, lineStart, selected, 0); } else if (*pc == menuHotkeyLookup(fileMenu, "f_uhunt", fileMenuSize)){ e = huntCaseSelectInput(); if (e != -1){ huntInput(selected, e); } abortinput = 0; - display_dir(currentpwd, ob, topfileref, selected); + display_dir(currentpwd, ob); } else if (*pc == menuHotkeyLookup(fileMenu, "f_xexec", fileMenuSize)){ strcpy(chpwd, currentpwd); if (!check_last_char(chpwd, "/")){ @@ -1637,52 +1708,70 @@ void directory_view_menu_inputs() free(execArgs); } abortinput = 0; - display_dir(currentpwd, ob, topfileref, selected); + display_dir(currentpwd, ob); } else { topLineMessage("Error: Permission denied"); } } else if (*pc == menuHotkeyLookup(functionMenu, "f_01", functionMenuSize) || *pc == 338){ if (selected < (totalfilecount - 1) ) { clear_workspace(); - topfileref = topfileref + displaycount; - if (topfileref > (totalfilecount - displaycount)){ - topfileref = totalfilecount - displaycount; + for (i = lineStart; i < listLen; i++){ + if (el[i].fileRef == selected) { + if ((i + displaysize) < listLen){ + selected = el[i + displaysize].fileRef; + } else { + selected = totalfilecount - 1; + } + break; + } } - selected = selected + displaycount; - if (selected > totalfilecount - 1){ - selected = totalfilecount - 1; + if (listLen < displaysize){ + lineStart = 0; + } else { + lineStart = lineStart + displaysize; + if (lineStart > (listLen - displaysize)){ + lineStart = listLen - displaysize; + } } } - display_dir(currentpwd, ob, topfileref, selected); + display_dir(currentpwd, ob); } else if (*pc == menuHotkeyLookup(functionMenu, "f_02", functionMenuSize) || *pc == 339){ if (selected > 0){ clear_workspace(); - topfileref = topfileref - displaysize; - if (topfileref < 0){ - topfileref = 0; + lineStart = lineStart - displaysize; + if (lineStart < 0){ + lineStart = 0; } - selected = selected - displaysize; - if (selected < 0){ - selected = 0; + for (i = 0; i < listLen; i++){ + if ((el[i].fileRef == selected) && (el[i].entryLineType == ET_OBJECT)){ + if ((i - displaysize) < 0) { + selected = 0; + } else { + selected = el[i - displaysize].fileRef; + if (el[i - displaysize].entryLineType != ET_OBJECT){ + selected++; + } + } + } } } - display_dir(currentpwd, ob, topfileref, selected); + display_dir(currentpwd, ob); } else if (*pc == menuHotkeyLookup(functionMenu, "f_03", functionMenuSize)){ clear_workspace(); selected = 0; - topfileref =0; - display_dir(currentpwd, ob, topfileref, selected); + lineStart = 0; + display_dir(currentpwd, ob); } else if (*pc == menuHotkeyLookup(functionMenu, "f_04", functionMenuSize)){ clear_workspace(); selected = totalfilecount - 1; - if (totalfilecount > displaysize){ - topfileref = totalfilecount - displaysize; + if (totalfilecount > bottomFileRef){ + lineStart = listLen - displaysize; } else { - topfileref = 0; + lineStart = 0; } - display_dir(currentpwd, ob, topfileref, selected); + display_dir(currentpwd, ob); } else if (*pc == menuHotkeyLookup(functionMenu, "f_05", functionMenuSize)){ - refreshDirectory(sortmode, topfileref, selected, 0); + refreshDirectory(sortmode, lineStart, selected, 0); } else if (*pc == menuHotkeyLookup(functionMenu, "f_06", functionMenuSize)){ strcpy(selfile, currentpwd); if (!check_last_char(selfile, "/")){ @@ -1698,35 +1787,39 @@ void directory_view_menu_inputs() } if (selected < (totalfilecount - 1)) { selected++; - if (selected > ((topfileref + displaysize) - 1)){ - topfileref++; + if (selected > bottomFileRef){ + lineStart = lineStartFromBottomFileRef(selected, el, listLen, displaysize); if (markedinfo == 2 && automark == 0){ - topfileref++; + lineStart++; } } } else { if (markedinfo == 2 && automark == 0){ - topfileref++; + lineStart++; } } clear_workspace(); - display_dir(currentpwd, ob, topfileref, selected); + display_dir(currentpwd, ob); } } else if (*pc == menuHotkeyLookup(functionMenu, "f_07", functionMenuSize)){ markall = 1; freeResults(ob, totalfilecount); + freeXAttrs(xa, xattrPos); ob = get_dir(currentpwd); markall = 0; // Leaving this set as 1 keeps things marked even after refresh. This is bad clear_workspace(); reorder_ob(ob, sortmode); - display_dir(currentpwd, ob, topfileref, selected); + generateEntryLineIndex(ob); + display_dir(currentpwd, ob); } else if (*pc == menuHotkeyLookup(functionMenu, "f_08", functionMenuSize)){ markall = 0; freeResults(ob, totalfilecount); + freeXAttrs(xa, xattrPos); ob = get_dir(currentpwd); clear_workspace(); reorder_ob(ob, sortmode); - display_dir(currentpwd, ob, topfileref, selected); + generateEntryLineIndex(ob); + display_dir(currentpwd, ob); } else if (*pc == menuHotkeyLookup(functionMenu, "f_09", functionMenuSize)){ sort_view_inputs(); } else if (*pc == menuHotkeyLookup(functionMenu, "f_10", functionMenuSize)){ @@ -1743,19 +1836,19 @@ void directory_view_menu_inputs() } if (selected < (totalfilecount - 1)) { selected++; - if (selected > ((topfileref + displaysize) - 1)){ - topfileref++; + if (selected > bottomFileRef){ + lineStart = lineStartFromBottomFileRef(selected, el, listLen, displaysize); if (markedinfo == 2 && automark == 0){ - topfileref++; + lineStart++; } } } else { if (markedinfo == 2 && automark == 0){ - topfileref++; + lineStart++; } } clear_workspace(); - display_dir(currentpwd, ob, topfileref, selected); + display_dir(currentpwd, ob); } else { blockend = selected; if (blockstart > blockend){ @@ -1774,7 +1867,7 @@ void directory_view_menu_inputs() } } blockstart = blockend = -1; - display_dir(currentpwd, ob, topfileref, selected); + display_dir(currentpwd, ob); } } } else if (*pc == 10){ @@ -1791,45 +1884,82 @@ void directory_view_menu_inputs() // Down Arrow moveDown: if (selected < (totalfilecount - 1)) { - selected++; - if (selected > ((topfileref + displaysize) - 1)){ - topfileref++; - clear_workspace(); + if (selected != bottomFileRef){ + selected++; + } else { + if (el[lineStart + displaysize].fileRef == el[lineStart + displaysize - 1].fileRef){ + lineStart++; + } else { + selected++; + lineStart++; + } } - display_dir(currentpwd, ob, topfileref, selected); + clear_workspace(); + display_dir(currentpwd, ob); } } else if (*pc == 259){ // Up Arrow if (selected > 0){ - selected--; - if (selected < topfileref){ - topfileref--; - clear_workspace(); + //topfileref is correct here. + if (selected == topfileref){ + if (el[lineStart - 1].entryLineType != ET_OBJECT){ + lineStart--; + } else { + selected--; + lineStart--; + } + } else { + selected--; } - display_dir(currentpwd, ob, topfileref, selected); + clear_workspace(); + display_dir(currentpwd, ob); } } else if (*pc == 260){ // Left Arrow if (hpos > 0){ hpos--; clear_workspace(); - display_dir(currentpwd, ob, topfileref, selected); + display_dir(currentpwd, ob); } } else if (*pc == 261){ // Right Arrow if (hpos < (maxdisplaywidth - COLS)){ hpos++; clear_workspace(); - display_dir(currentpwd, ob, topfileref, selected); + display_dir(currentpwd, ob); } } else if (*pc == 262){ // Home Key - selected = topfileref; - display_dir(currentpwd, ob, topfileref, selected); + selected = el[lineStart].fileRef; + display_dir(currentpwd, ob); } else if (*pc == 360){ // End Key - selected = topfileref + (displaycount - 1); - display_dir(currentpwd, ob, topfileref, selected); + // selected = topfileref + (displaycount - 1); + selected = bottomFileRef; + display_dir(currentpwd, ob); + } else if (*pc == 276){ + // F12 Key + endwin(); + printf("Debug Exit Triggered.\n\n"); + printf("selected: %i\n\n", selected); + + printf("topfileref: %i\n", topfileref); + printf("bottomFileRef: %i\n", bottomFileRef); + printf("DIFFERENCE: %i\n\n", bottomFileRef - topfileref); + + printf("displaysize: %i\n", displaysize); + + printf("\nTotal Files (objects): %i\n", totalfilecount); + printf("Total xattr lines: %i\n", xattrPos); + printf("Total lines: %i\n", (totalfilecount + xattrPos)); + + printf("\nBottom File Ref + 0: %i\n", el[lineStart + displaysize - 1].fileRef); + printf("Bottom File Ref + 1: %i\n", el[lineStart + displaysize].fileRef); + + printf("\nlineStart: %i\n", lineStart); + + printf("\nlistLen: %i\n", listLen); + exit(3); } } } @@ -1852,8 +1982,8 @@ void global_menu_inputs() clear(); global_menu_inputs(); } else { - refreshDirectory(sortmode, topfileref, selected, 0); - display_dir(currentpwd, ob, topfileref, selected); + refreshDirectory(sortmode, lineStart, selected, 0); + // display_dir(currentpwd, ob, topfileref, selected); wPrintMenu(LINES-1, 0, functionMenuLabel); // printMenu(LINES-1, 0, functionMenuText); // Global menu inputs doesn't include this. Even though it isn't used. global_menu_inputs(); @@ -1864,8 +1994,8 @@ void global_menu_inputs() clear(); global_menu_inputs(); } else { - refreshDirectory(sortmode, topfileref, selected, 0); - display_dir(currentpwd, ob, topfileref, selected); + refreshDirectory(sortmode, lineStart, selected, 0); + // display_dir(currentpwd, ob); wPrintMenu(LINES-1, 0, functionMenuLabel); global_menu_inputs(); } @@ -1876,7 +2006,7 @@ void global_menu_inputs() // printMenu(0, 0, globalMenuText); } else { // display_dir(currentpwd, ob, topfileref, selected); - refreshDirectory(sortmode, topfileref, selected, 1); + refreshDirectory(sortmode, lineStart, selected, 1); directory_view_menu_inputs(); } } else if (*pc == menuHotkeyLookup(globalMenu, "g_edit", globalMenuSize)) { @@ -1885,7 +2015,7 @@ void global_menu_inputs() wPrintMenu(0,0,globalMenuLabel); } else { // display_dir(currentpwd, ob, topfileref, selected); - refreshDirectory(sortmode, topfileref, selected, 1); + refreshDirectory(sortmode, lineStart, selected, 1); directory_view_menu_inputs(); } } else if (*pc == menuHotkeyLookup(globalMenu, "g_help", globalMenuSize)) { diff --git a/src/showmenus.h b/src/showmenus.h index 072a878..d76e767 100644 --- a/src/showmenus.h +++ b/src/showmenus.h @@ -28,5 +28,5 @@ void copy_multi_file(results* ob, char *dest); void rename_multi_file_input(results* ob, char *input); int huntCaseSelectInput(); void huntInput(int selected, int charcase); -void refreshDirectory(char *sortmode, int origtopfileref, int origselected, int destructive); +void refreshDirectory(char *sortmode, int origlineStart, int origselected, int destructive); int sanitizeTopFileRef(int topfileref); diff --git a/themes/mac b/themes/mac new file mode 100644 index 0000000..9f779e5 --- /dev/null +++ b/themes/mac @@ -0,0 +1,20 @@ +theme : +{ + command = [ -1, -1, 0 ]; + info = [ 2, -1, 0 ]; + input = [ 0, 7, 0 ]; + select = [ 12, -1, 0 ]; + display = [ -1, -1, 0 ]; + danger = [ 9, -1, 0 ]; + dir = [ 14, -1, 0 ]; + symlink = [ 5, -1, 0 ]; + exec = [ 1, -1, 0 ]; + suid = [ 0, 1, 0 ]; + sgid = [ 0, 15, 0 ]; + hilite = [ -1, -1, 1 ]; + error = [ -1, -1, 1 ]; + heading = [ 2, -1, 0 ]; + deadlink = [ 9, -1, 0 ]; + sticky = [ 0, 2, 0 ]; + sticky-ow = [ 0, 3, 0 ]; +}; diff --git a/themes/ti b/themes/ti new file mode 100644 index 0000000..8eac13a --- /dev/null +++ b/themes/ti @@ -0,0 +1,20 @@ +theme : +{ + command = [ -1, -1, 0 ]; + info = [ 2, -1, 0 ]; + input = [ -1, -1, 1 ]; + select = [ 12, -1, 0 ]; + display = [ 6, -1, 0 ]; + danger = [ 9, -1, 0 ]; + dir = [ 13, -1, 0 ]; + symlink = [ -1, -1, 1 ]; + exec = [ 11, -1, 0 ]; + suid = [ -1, 1, 0 ]; + sgid = [ 0, 2, 1 ]; + hilite = [ 0, 7, 0 ]; + error = [ -1, -1, 1 ]; + heading = [ 2, -1, 0 ]; + deadlink = [ 9, -1, 0 ]; + sticky = [ 7, 4, 0 ]; + sticky-ow = [ 0, 2, 0 ]; +};