-- tmenu is tiny menu on 80x25 -- Tmenu is Copyright (C) 2025 Manuel De Girardi ;  -- -- 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA -- -- Date := "2025-11-21 19:07:47" -- Version := "0.0.0r" with T ; with Ada.Wide_Text_Io ; with Ada.Text_Io ; use Ada ; with Gnat.Os_Lib ; use Gnat ; use Gnat.Os_Lib; with Ada.Directories ; with Ada.Characters.Handling ; use Ada.Characters ; with Ada.Wide_Characters.Handling ; use Ada.Wide_Characters.Handling ; with Ada.Strings.Fixed ; use Ada.Strings ; with PragmARC.Ansi_TTY_Control ; use PragmARC ; procedure Tmenu is package W_Io renames Ada.Wide_Text_Io; use Text_Io; Target : Wide_String(1..57) := (others => Wide_Character ' Val (32)) ; Last : Natural := 0 ; Args : Os_Lib.Argument_List_Access; Cmd_Name : String_Access; Arg_Top : Natural := 0; Errno : Integer := 0; Menu_Filename : constant String := "main_menu.txt"; Top_Col : Positive := 20; Entry_Line : Positive := 23; Top_Line : constant Positive := 4; Menu_File : W_Io.File_Type; Program_Name : String_Access; Input_Line : String_Access; Top_Name : constant Positive := 32; Name_Index : Natural := 0; File_Index : Natural := 0; type Action_Array is array (Positive range <>) of String_Access; Done : Boolean := False; Success : Boolean := False; Args_Index : Natural := 0; Menu_24 : Action_Array(1..18) := ( new String ' (Handling.To_String("")), new String ' (Handling.To_String("")), new String ' (Handling.To_String("")), new String ' (Handling.To_String("")), new String ' (Handling.To_String("")), new String ' (Handling.To_String("")), new String ' (Handling.To_String("")), new String ' (Handling.To_String("")), new String ' (Handling.To_String("")), new String ' (Handling.To_String("")), new String ' (Handling.To_String("")), new String ' (Handling.To_String("")), new String ' (Handling.To_String("")), new String ' (Handling.To_String("")), new String ' (Handling.To_String("")), new String ' (Handling.To_String("")), new String ' (Handling.To_String("")), new String ' (Handling.To_String("")) ); begin loop Put(Ansi_TTY_Control.Clear_Screen); if Os_Lib.Is_Regular_File(Menu_Filename) then W_Io.Open(Menu_File, W_Io.In_File, Menu_Filename, Form => "WCEM=8"); else return; end if; if not W_Io.End_Of_File(Menu_File) then begin Input_Line := new String ' (handling.To_String(W_Io.Get_Line(Menu_File))); Put_Line(Input_Line.all); Os_Lib.Free(Input_Line); Input_Line := new String ' (handling.To_String(W_Io.Get_Line(Menu_File))); Put_Line(Input_Line.all); Os_Lib.Free(Input_Line); Input_Line := new String ' (handling.To_String(W_Io.Get_Line(Menu_File))); Put_Line(Input_Line.all); Os_Lib.Free(Input_Line); exception when others => Put_Line("Error during reading menu file."); return; end; end if; for Item in Menu_24 ' Range loop if not W_Io.End_Of_File(Menu_File) then Input_Line := new String ' (handling.To_String(W_Io.Get_Line(Menu_File))); Put_Line(Input_Line.all); Os_Lib.Free(Menu_24(Item)); Name_Index := Fixed.Index(Input_Line.all, Character'Val(27) & "", Top_Name); Menu_24(Item) := new String ' (Input_Line(Top_Name..Name_Index-1)); Os_Lib.Free(Input_Line); File_Index := File_Index + 1; end if; end loop; if not W_Io.End_Of_File(Menu_File) then begin Input_Line := new String ' (handling.To_String(W_Io.Get_Line(Menu_File))); Put_Line(Input_Line.all); Os_Lib.Free(Input_Line); Input_Line := new String ' (handling.To_String(W_Io.Get_Line(Menu_File))); Put_Line(Input_Line.all); Os_Lib.Free(Input_Line); Input_Line := new String ' (handling.To_String(W_Io.Get_Line(Menu_File))); Put_Line(Input_Line.all); Os_Lib.Free(Input_Line); exception when others => Put_Line("Error during reading menu file."); New_Line(2); return; end; end if; W_Io.Close(Menu_File); Main : loop declare Wchar : Wide_Character := Wide_Character ' Val (32); begin Menu : loop Put(Ansi_TTY_Control.Position(Entry_Line, Top_Col) & Handling.To_String(Target(Target'First .. Last))); W_Io.Get_immediate(Wchar); if Is_Control (Wchar) then case Wchar is when Wide_Character ' Val (10) | Wide_Character ' Val (13) => Done := True; when Wide_Character ' Val (27) => New_Line(2); return; when Wide_Character ' Val (127) | Wide_Character ' Val (8) => Target(Last) := Wide_Character ' Val (32); Last := Last - 1; Put(Ansi_TTY_Control.Clear_Screen); if Os_Lib.Is_Regular_File(Menu_Filename) then W_Io.Open(Menu_File, W_Io.In_File, Menu_Filename, Form => "WCEM=8"); else New_Line(2); return; end if; File_Index := 0; if not W_Io.End_Of_File(Menu_File) then begin Input_Line := new String ' (handling.To_String(W_Io.Get_Line(Menu_File))); Put_Line(Input_Line.all); Os_Lib.Free(Input_Line); Input_Line := new String ' (handling.To_String(W_Io.Get_Line(Menu_File))); Put_Line(Input_Line.all); Os_Lib.Free(Input_Line); Input_Line := new String ' (handling.To_String(W_Io.Get_Line(Menu_File))); Put_Line(Input_Line.all); Os_Lib.Free(Input_Line); exception when others => Put_Line("Error during reading menu file."); New_Line(2); return; end; end if; for Item in Menu_24 ' Range loop if not W_Io.End_Of_File(Menu_File) then Input_Line := new String ' (handling.To_String(W_Io.Get_Line(Menu_File))); Put_Line(Input_Line.all); Os_Lib.Free(Menu_24(Item)); Name_Index := Fixed.Index(Input_Line.all, Character'Val(27) & "", Top_Name); Menu_24(Item) := new String ' (Input_Line(Top_Name..Name_Index-1)); Os_Lib.Free(Input_Line); File_Index := File_Index + 1; end if; end loop; if not W_Io.End_Of_File(Menu_File) then begin Input_Line := new String ' (handling.To_String(W_Io.Get_Line(Menu_File))); Put_Line(Input_Line.all); Os_Lib.Free(Input_Line); Input_Line := new String ' (handling.To_String(W_Io.Get_Line(Menu_File))); Put_Line(Input_Line.all); Os_Lib.Free(Input_Line); Input_Line := new String ' (handling.To_String(W_Io.Get_Line(Menu_File))); Put_Line(Input_Line.all); Os_Lib.Free(Input_Line); exception when others => Put_Line("Error during reading menu file."); New_Line(2); return; end; end if; W_Io.Close(Menu_File); when others => null; end case; else Target(Last + 1) := Wchar; Last := Last + 1; end if; if Done then begin Program_Name := new String ' (Handling.To_String(Target(Target'First..Last))); if Program_Name = null or else Program_Name'Length = 0 then raise End_Error; elsif Program_Name(Fixed.Index_Non_Blank(Program_Name.all)..Fixed.Index_Non_Blank(Program_Name.all, Backward)) = "exit" then New_Line(2); return; end if; Done := False; for Name in Menu_24'Range loop if Menu_24(Name).all = Program_Name(Fixed.Index_Non_Blank(Program_Name.all)..Fixed.Index_Non_Blank(Program_Name.all, Backward)) then Done := True; exit Menu; elsif Menu_24(Name).all = Program_Name(Fixed.Index_Non_Blank(Program_Name.all)..Fixed.Index(Program_Name.all, " ") - 1) then Args_Index := Fixed.Index(Program_Name.all, " "); Done := True; exit Menu; end if; end loop; exception when W_Io.End_Error => Target := (others => Wide_Character ' Val (32)) ; Last := 0; Put(Ansi_TTY_Control.Position(Entry_Line, 4) & Fixed."*"(64, Character ' Val (32))); Put(Ansi_TTY_Control.Position(Entry_Line, 4) & "Error : presse ENTER to continue."); W_Io.Get_Immediate(Wchar); Put(Ansi_TTY_Control.Position(Entry_Line, 4) & Fixed."*"(64, Character ' Val (32))); for Old in Menu_24 ' range loop Os_Lib.Free(Menu_24(Old)); end loop; Done := False; exit; end; end if; end loop Menu; if not Done then File_Index := 0; Put(Ansi_TTY_Control.Clear_Screen); if Os_Lib.Is_Regular_File(Menu_Filename) then W_Io.Open(Menu_File, W_Io.In_File, Menu_Filename, Form => "WCEM=8"); else New_Line(2); return; end if; if not W_Io.End_Of_File(Menu_File) then begin Input_Line := new String ' (handling.To_String(W_Io.Get_Line(Menu_File))); Put_Line(Input_Line.all); Os_Lib.Free(Input_Line); Input_Line := new String ' (handling.To_String(W_Io.Get_Line(Menu_File))); Put_Line(Input_Line.all); Os_Lib.Free(Input_Line); Input_Line := new String ' (handling.To_String(W_Io.Get_Line(Menu_File))); Put_Line(Input_Line.all); Os_Lib.Free(Input_Line); exception when others => Put_Line("Error during reading menu file."); New_Line(2); return; end; end if; for Item in Menu_24 ' Range loop if not W_Io.End_Of_File(Menu_File) then Input_Line := new String ' (handling.To_String(W_Io.Get_Line(Menu_File))); Put_Line(Input_Line.all); Os_Lib.Free(Menu_24(Item)); Name_Index := Fixed.Index(Input_Line.all, Character'Val(27) & "", Top_Name); Menu_24(Item) := new String ' (Input_Line(Top_Name..Name_Index-1)); Os_Lib.Free(Input_Line); File_Index := File_Index + 1; end if; end loop; if not W_Io.End_Of_File(Menu_File) then begin Input_Line := new String ' (handling.To_String(W_Io.Get_Line(Menu_File))); Put_Line(Input_Line.all); Os_Lib.Free(Input_Line); Input_Line := new String ' (handling.To_String(W_Io.Get_Line(Menu_File))); Put_Line(Input_Line.all); Os_Lib.Free(Input_Line); Input_Line := new String ' (handling.To_String(W_Io.Get_Line(Menu_File))); Put_Line(Input_Line.all); Os_Lib.Free(Input_Line); exception when others => Put_Line("Error during reading menu file."); New_Line(2); return; end; end if; W_Io.Close(Menu_File); end if; exit; exception when others => null; end; end loop Main; if Args_Index /= 0 then Args := Argument_String_To_List(Program_Name(Args_Index + 1 .. Fixed.Index_Non_Blank(Program_Name.all, Backward))); New_Line(2); Spawn(Locate_Exec_On_Path(Handling.To_Lower(Program_Name(Fixed.Index_Non_Blank(Program_Name.all)..Args_Index-1))).all, Args.all, Success); Free(Program_Name); if Success then Target := (others => Wide_Character ' Val (32)); Last := 0; end if; elsif Fixed.Index_Non_Blank(Program_Name.all) /= 0 then Args := new Argument_List(1..0); New_Line(2); Spawn(Locate_Exec_On_Path(Handling.To_Lower(Program_Name(Fixed.Index_Non_Blank(Program_Name.all)..Fixed.Index_Non_Blank(Program_Name.all, Backward)))).all, Args.all, Success); Free(Program_Name); if Success then Target := (others => Wide_Character ' Val (32)); Last := 0; end if; else Target := (others => Wide_Character ' Val (32)); Free(Program_Name); Last := 0; end if; end loop; end Tmenu ;