
(********************************************************************)
(*                                                                  *)
(*  dirx.sd7      Make a directory listing                          *)
(*  Copyright (C) 1994, 2004  Thomas Mertes                         *)
(*                                                                  *)
(*  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 the Free Software Foundation; either version 2 of  *)
(*  the License, or (at your option) any later version.             *)
(*                                                                  *)
(*  This program is distributed in the hope that it will be useful, *)
(*  but WITHOUT ANY WARRANTY; without even the implied warranty of  *)
(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   *)
(*  GNU General Public License for more details.                    *)
(*                                                                  *)
(*  You should have received a copy of the GNU General Public       *)
(*  License along with this program; if not, write to the           *)
(*  Free Software Foundation, Inc., 51 Franklin Street,             *)
(*  Fifth Floor, Boston, MA  02110-1301, USA.                       *)
(*                                                                  *)
(********************************************************************)


$ include "seed7_05.s7i";
  include "stdio.s7i";
  include "osfiles.s7i";
  include "console.s7i";


const func boolean: wildcard_match (in string: main_stri, in string: pattern) is func

  result
    var boolean: doesMatch is FALSE;

  local
    var integer: main_length is 0;
    var integer: main_index is 1;
    var string: pattern_tail is "";

  begin
    if pattern = "" then
      doesMatch := main_stri = "";
    else
      case pattern[1] of
        when {'*'}:
          if pattern = "*" then
            doesMatch := TRUE;
          else
            main_length := length(main_stri);
            pattern_tail := pattern[2 .. ];
            while main_index <= main_length and not doesMatch do
              doesMatch := wildcard_match(main_stri[main_index .. ],
                  pattern_tail);
              incr(main_index);
            end while;
          end if;
        when {'?'}:
          if main_stri <> "" then
            doesMatch := wildcard_match(main_stri[2 .. ], pattern[2 .. ]);
          end if;
        otherwise:
          if main_stri <> "" and main_stri[1] = pattern[1] then
            doesMatch := wildcard_match(main_stri[2 .. ], pattern[2 .. ]);
          end if;
      end case;
    end if;
  end func;


const proc: main is func

  local
    var string: pattern is "";
    var array string: names is 0 times "";
    var integer: number_of_names is 0;
    var integer: index is 0;
    var integer: copy_index is 0;
    var integer: width is 0;
    var integer: num_lines is 0;
    var integer: num_columns is 1;
    var integer: line is 0;
    var integer: column is 0;
    var integer: num2 is 0;

  begin
    OUT := STD_CONSOLE;
    if length(argv(PROGRAM)) = 0 then
      names := readDir(".");
    elsif length(argv(PROGRAM)) = 1 then
      names := readDir(".");
      pattern := argv(PROGRAM)[1];
    else
      names := argv(PROGRAM);
(*  else
      write("pattern? ");
      readln(pattern); *)
    end if;
(*  write("directory? ");
    names := readDir(getln(IN)); *)
    number_of_names := length(names);
    if pattern <> "" then
      copy_index := 1;
      for index range 1 to number_of_names do
        if wildcard_match(names[index], pattern) then
          names[copy_index] := names[index];
          incr(copy_index);
        end if;
      end for;
      number_of_names := pred(copy_index);
    end if;
    if number_of_names <> 0 then
      width := 0;
      for index range 1 to number_of_names do
        if length(names[index]) > width then
          width := length(names[index]);
        end if;
      end for;
      if width < 80 then
        num_columns := 80 div succ(width);
      else
        width := 0;
      end if;
      num2 := succ(pred(number_of_names) mod num_columns);
      if num2 = num_columns then
        decr(num2);
      end if;
      num_lines := succ(pred(number_of_names) div num_columns);
      writeln;
      for line range 1 to num_lines do
        for column range 1 to num2 + 1 do
          if num_columns * pred(line) + column <= number_of_names then
            write(names[line + num_lines * pred(column)] rpad width);
            if column <> num_columns then
              write(" ");
            end if;
          end if;
        end for;
        for column range num2 + 2 to num_columns do
          if num_columns * pred(line) + column <= number_of_names then
            write(names[line + num_lines * num2 +
                pred(num_lines) * pred(column - num2)] rpad width);
            if column <> num_columns then
              write(" ");
            end if;
          end if;
        end for;
        writeln;
      end for;
    end if;
  end func;
