{$mode objfpc}{$H+}
//   https://docs.microsoft.com/en-us/windows/desktop/api/commdlg/nf-commdlg-getopenfilenamea
//   https://docs.microsoft.com/en-us/windows/desktop/api/commdlg/ns-commdlg-tagofna
Uses
  sysutils,Windows,Commdlg,Classes,CRT;
Var
Open_File          : TOpenFileNameA;
ret                : array[0..100000] of char;
Filenum            : Word;
Target_File        : AnsiString;
File_Stringlist    : tstringList;
{=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=}
Procedure Display_File_StringList(Var Display_String_List:tStringList);
Var
  SL_Loop : Word;
Begin
   If Display_String_List.Count=0 then
      Begin
         Textcolor(12);
         Writeln('0 Files Selected')
      End
   Else
   If Display_String_List.Count=1 then
      Begin
         TextColor(10);
         Writeln(Display_String_List[0]);
         Textcolor(14);
         Writeln('1 Files Selected');
      End
   Else
      Begin
         TextColor(13);
         Writeln('Path for all files: ',Display_String_List[0]);
         TextColor(10);
         For SL_Loop:= 1 to Display_String_List.Count-1 Do
            Writeln('File #',SL_Loop,': ',Display_String_List[SL_Loop]);
         Textcolor(14);
         Writeln(Display_String_List.Count-1,' Files Selected');
      End;
End;
{=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=}
Function Get_Files_Into_Stringlist(Var String_List:tStringList):Boolean;
Var
   Open_File_Result      : Boolean;
   Position_of_Filename  : Word;
Begin
   String_List.Clear;
   Open_File_Result:=GetOpenFileNameA(@Open_File);
   If Open_File_Result then
      Begin
         Position_of_Filename:=0;
         Repeat
            String_List.add(StrPas(@Open_File.lpstrFile[Position_of_Filename]));
            inc(Position_of_Filename,length(String_List[String_List.Count-1])+1);
         Until Open_File.lpstrFile[Position_of_Filename]=#0;
      End;
   Writeln(Open_File_Result);
   Get_Files_Into_Stringlist:=Open_File_Result;
End;
{=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=}
Procedure Process_File(Some_File: AnsiString);
Begin
   TextColor(11);
   Writeln('Processing File: ',Some_File);
End;
{=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=}
Begin {Main Program}
   fillchar(Open_File, sizeof(Open_File), 0);
   fillchar(ret, sizeof(ret), 0);
   Open_File.lStructSize:=sizeof(Open_File);
   Open_File.hwndOwner:=0;
   Open_File.lpstrFile:=ret;
   Open_File.lpstrFile[0]:=#0;
   Open_File.nMaxFile:=100000;
   Open_File.Flags := OFN_EXPLORER or OFN_FILEMUSTEXIST or OFN_ALLOWMULTISELECT;
   Open_File.lpstrDefExt:='.txt';
   Open_File.lpstrTitle:='My Program - Open File';
   Open_File.lpstrFilter:='All Files (*.*)'+#0+'*.*'+#0;
   File_Stringlist:=TStringlist.Create;
   If paramstr(1)<>'' then
      Begin
         Target_File:=paramstr(1);
         Process_File(Target_File);
      End
   else
      Target_File:='';
   Repeat
      If Target_File<>'' then
         Begin
            // The following line seems to cause my program to crash.
            // It does seem to work as I expect.  It puts me in the directory
            // of the file and shows the file name, but for some reason if I select
            // more than one file than I get
            // An unhandled exception occurred at $0040B428:
            // EAccessViolation:
            // $0040B428
            // $0040A03D
            // $00414447
            // $0040AE1E
            // $0040A03D
            // $00414447
            // $0040AE1E
            // $0040A03D
            // $00414447
            // $0040AE1E
            // $0040A03D
            // $00414447
            // $0040AE1E
            // $0040A03D
            // $00414447
            // $0040AE1E
            // $0040A03D
            // in a repeating loop if I use the command with two #0 at the end of
            // Open_File.lpstrFile:=Pchar(Target_File+#0+#0);
            
            // Or I get:
            // EAccessViolation: An unhandled exception occurred at $0040BB56:
            // with an exit code of 253
            // or 
            // An unhandled exception occurred at $0040BDD2:
            // EAccessViolation: Access violation
            // $0040BDD2
            // with an exit with a code 217
            // if I use one #0 at the end of
            // Open_File.lpstrFile:=Pchar(Target_File+#0);
            
            // these errors seem to show up more if I select multiple files or 
            // change directories.  
            Open_File.lpstrFile:=Pchar(Target_File+#0);
            
            
            // If I leaved the above commented out, then I should be able to use the 
            // command below to just put me in the directory specified, but with no default file
            // This does not work the way I expect it to work at all.
            // It does not put me into the directory of the file used as a parameter, it
            // Then for other files it puts me one level before the one I was just in
            // I want to be back where I was.  If I give it a parameter, I want to 
            // be in the directory of the file the parameter specifies, and then
            // I want to be in the directory of the previous file.
            // This just is not working the way I expect but does not cause any crash.
            Open_File.lpstrInitialDir:=Pchar(ExtractFilePath(Target_File)+#0+#0);
         End;
      Get_Files_Into_Stringlist(File_Stringlist);
      Display_File_StringList(File_Stringlist);
      If (File_Stringlist.Count=1) and FileExists(File_Stringlist[0]) Then
         Begin
            Target_File:=File_Stringlist[0];
            Process_File(Target_File);
         End
      Else
      If (File_Stringlist.Count>1) Then
         Begin
            Filenum:=0;
            Repeat
               Inc(Filenum);
               If (Filenum<File_Stringlist.Count) Then
                  Begin
                     Target_File:=File_Stringlist[0];
                     If Target_File[Length(Target_File)]<>'\' Then
                        Target_File:=Target_File+'\';
                     Target_File:=Target_File+File_Stringlist[Filenum];
                     Process_File(Target_File);
                  End;
            Until Filenum>=File_Stringlist.Count;
         End;
   Until File_Stringlist.count=0;
   File_Stringlist.Free;
end.
{=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=}
