###############################################################################
#
# File:         fileutils-3.12.LS.hidden.patch
# RCS:          $Header: $
# Description:  add support for .hidden files to gnu ls
# Author:       Christian Limpach <chris@nice.ch>
# Created:      Mon Apr  3 20:50:18 1995
# Modified:     Mon Apr  3 21:44:50 1995 (Christian Limpach) chris@nice.ch
# Language:     patch
# Package:      N/A
# Status:       Experimental (Do Not Distribute)
#
# (C) Copyright 1995, Christian Limpach, all rights reserved.
# This is free software, and you are welcome to redistribute it
# under certain conditions; see ftp://nice.ethz.ch/users/chris/TERMS
# for details. This software comes with ABSOLUTELY NO WARRANTY.
#
###############################################################################

# patches for 3.9 by Marcel Waldvogel
# updated to 3.12
diff -rc /tmp/fileutils-3.12/src/ls.c fileutils-3.12/src/ls.c
*** /tmp/fileutils-3.12/src/ls.c	Fri Nov  4 06:08:15 1994
--- fileutils-3.12/src/ls.c	Sat Apr  1 23:47:39 1995
***************
*** 117,122 ****
--- 117,125 ----
  static int is_not_dot_or_dotdot ();
  static int length_of_file_name_and_frills ();
  static void add_ignore_pattern ();
+ static void add_hidden_pattern ();
+ static void clear_hidden_patterns ();
+ static void hide_files ();
  static void attach ();
  static void clear_files ();
  static void extract_dirs_from_files ();
***************
*** 344,349 ****
--- 347,360 ----
  
  static struct ignore_pattern *ignore_patterns;
  
+ /* Same as before, but these are per directory. */
+ 
+ static struct ignore_pattern *hidden_patterns;
+ 
+ /* Nonzero means hide files listed in .hidden.  -h  */
+ 
+ static int ignore_from_dot_hidden;
+ 
  /* Nonzero means quote nongraphic chars in file names.  -b  */
  
  static int quote_funny_chars;
***************
*** 400,405 ****
--- 411,417 ----
    {"directory", no_argument, 0, 'd'},
    {"dired", no_argument, 0, 'D'},
    {"full-time", no_argument, &full_time, 1},
+   {"hidden", no_argument, 0, 'h'},
    {"inode", no_argument, 0, 'i'},
    {"kilobytes", no_argument, 0, 'k'},
    {"numeric-uid-gid", no_argument, 0, 'n'},
***************
*** 698,704 ****
    p = getenv ("TABSIZE");
    tabsize = p ? atoi (p) : 8;
  
!   while ((c = getopt_long (argc, argv, "abcdfgiklmnpqrstuw:xABCDFGI:LNQRST:UX1",
  			   long_options, (int *) 0)) != EOF)
      {
        switch (c)
--- 710,717 ----
    p = getenv ("TABSIZE");
    tabsize = p ? atoi (p) : 8;
  
!   while ((c = getopt_long (argc, argv,
!                            "abcdfghiklmnpqrstuw:xABCDFGI:LNQRST:UX1",
  			   long_options, (int *) 0)) != EOF)
      {
        switch (c)
***************
*** 739,744 ****
--- 752,762 ----
  	  /* No effect.  For BSD compatibility. */
  	  break;
  
+ 	case 'h':
+ 	  /* Interprete the .hidden files. */
+ 	  ignore_from_dot_hidden = 1;
+ 	  break;
+ 
  	case 'i':
  	  print_inode = 1;
  	  break;
***************
*** 952,957 ****
--- 970,978 ----
  
    clear_files ();
  
+   if (ignore_from_dot_hidden)
+     hide_files (name);
+ 
    while ((next = readdir (reading)) != NULL)
      if (file_interesting (next))
        total_blocks += gobble_file (next->d_name, 0, name);
***************
*** 1016,1021 ****
--- 1037,1130 ----
    ignore_patterns = ignore;
  }
  
+ /* The same as before, but add it to the hidden_patterns list after having
+    copied the string.   */
+ 
+ static void
+ add_hidden_pattern (pattern)
+      char *pattern;
+ {
+   register struct ignore_pattern *hidden;
+   
+   hidden = (struct ignore_pattern *) xmalloc (sizeof (struct ignore_pattern));
+   hidden->pattern = xstrdup (pattern);
+   /* Add it to the head of the linked list. */
+   hidden->next = hidden_patterns;
+   hidden_patterns = hidden;
+ }
+ 
+ /* Removes all entries from the list of hidden patterns, freeing the
+    patterns also.   */
+ 
+ static void
+ clear_hidden_patterns ()
+ {
+   register struct ignore_pattern *hidden, *next;
+  
+   hidden = hidden_patterns;
+   hidden_patterns = NULL;
+  
+   while (hidden != NULL)
+   {
+     next = hidden->next;
+     free(hidden->pattern);
+     free(hidden);
+     hidden = next;
+   }
+ }
+ 
+ /* Add all files from .hidden in the current directory (if it exists)
+    to the hidden_patterns list, after clearing it first.   */
+ 
+ static void
+ hide_files (dirname)
+      char *dirname;
+ {
+   register char *path, *line;
+   int linesize, length, offset;
+   FILE *hidden;
+   clear_hidden_patterns ();
+  
+   path = (char *) xmalloc (strlen (dirname) + sizeof (".hidden") + 2);
+   attach (path, dirname, ".hidden");
+   hidden = fopen (path, "r");
+   if (hidden != NULL)
+   {
+     /* If there was an error while opening, we just ignore it */
+     /* Start at 32 chars per line and double each time it isn't enough */
+     linesize = 32;
+     offset = 0;
+     line = (char *) xmalloc (linesize);
+    
+     while (!feof (hidden))
+     {
+       if (fgets (line + offset, linesize - offset, hidden) == NULL)
+         break;        /* We got to the file end */
+       length = strlen(line);
+       if (length == 0) /* Should not happen */
+         break;
+       if (line[length - 1] != '\n')
+       {
+         /* There wasn't enough space in the buffer, we make it twice as big
+          and append the rest by trying again.  */
+       offset = length;
+       linesize *= 2;
+       line = (char *) xrealloc (line, linesize);
+       }
+       else
+       {
+         /* Add the line to the pattern space */
+         line[length - 1] = '\0';
+       add_hidden_pattern (line);
+       offset = 0;
+       }
+     }
+     free (line);
+     fclose (hidden);
+   }
+   free (path);
+ }
+ 
  /* Return nonzero if the file in `next' should be listed. */
  
  static int
***************
*** 1028,1033 ****
--- 1137,1145 ----
      if (fnmatch (ignore->pattern, next->d_name, FNM_PERIOD) == 0)
        return 0;
  
+   for (ignore = hidden_patterns; ignore; ignore = ignore->next)
+     if (fnmatch (ignore->pattern, next->d_name, FNM_PERIOD) == 0)
+       return 0;
    if (really_all_files
        || next->d_name[0] != '.'
        || (all_files
***************
*** 2126,2131 ****
--- 2238,2244 ----
        printf ("\
    -G, --no-group             inhibit display of group information\n\
    -g                         (ignored)\n\
+   -h, --hidden               don't show files listed in the .hidden file\n\
    -I, --ignore=PATTERN       do not list implied entries matching shell PATTERN\n\
    -i, --inode                print index number of each file\n\
    -k, --kilobytes            use 1024 blocks, not 512 despite POSIXLY_CORRECT\n\
