-------------------------------------
-- To Call "man" command by spawn. --
-------------------------------------
with Ada.Text_Io;
use Ada;
with Gnat.Os_Lib;
use Gnat;
with Gnat.Command_Line;
use Gnat.Command_Line;
with Ada.Strings.Unbounded;
with Ada.Strings.Fixed;
use Ada.Strings;
--------------------------------------------
-- To create dialog window with Textview. --
--------------------------------------------
with Gtk.Frame; use Gtk.Frame;
with Gtk.Box; use Gtk.Box;
with Gtk.Text_Tag_Table; use Gtk.Text_Tag_Table;
with Gtk.Text_Tag; use Gtk.Text_Tag;
with Gtk.Text_Iter; use Gtk.Text_Iter;
with Gtk.Text_Buffer; use Gtk.Text_Buffer;
with Gtk.Text_View; use Gtk.Text_View;
with Gtk.Dialog; use Gtk.Dialog;
with Gtk.Scrolled_Window; use Gtk.Scrolled_Window;
with Gtk.Widget; use Gtk.Widget;
with Gtk.Window; use Gtk.Window;
with Gtk.Enums; use Gtk.Enums;
with Gtk.Main;
with Glib.Error; use Glib.Error;
with Glib.Convert;
use Glib;
----------------------------------------------------------------------
-- To Convert absolut path to accepted Parse function command line. --
----------------------------------------------------------------------
with Gnat.Directory_Operations;
with Gnat.Directory_Operations.Iteration;
use Gnat.Directory_Operations;
--------------------------------
-- To print some information. --
--------------------------------
with Ada.Text_Io;
----------------
-- Main unit. --
----------------
procedure Manpages_To_Gtkada is
----------------------------------------------------------------------------
-- Search the absolut path of man page from section number and page name. --
----------------------------------------------------------------------------
-- for "man 1 ls" return "man [option] /usr/share/man/man1/ls.1.gz". --
----------------------------------------------------------------------------
function Parse_Man_Command (Man : in String) return String is
Man_Line : access String;
begin
if Fixed.Index(Man(Fixed.Index_Non_Blank(Man)..Man'Last), " " ) /= 0 and then
Fixed.Index_Non_Blank(Man, Backward) /=
Fixed.Index(Man(Fixed.Index_Non_Blank(Man)..Man'Last), " " ) then
begin
declare
Line : constant String := Man(Fixed.Index
(Man(Fixed.Index_Non_Blank
(Man)..Man'Last),
" " )+1..Fixed.Index_Non_Blank(Man, Backward));
begin
if Fixed.Index(Line(Fixed.Index_Non_Blank(Line)..Line'Last), " " ) /= 0 and then
Fixed.Index_Non_Blank(Line, Backward) /=
Fixed.Index(Line(Fixed.Index_Non_Blank(Line)..Line'Last), " " ) then
begin
declare
Section : constant String := Line(Line'First..Line'First);
Manual : constant String := "/usr/share/man/man" &
Section & '/' & line(Fixed.Index
(Line, " ", Backward)+1..Fixed.Index_Non_Blank(line, Backward)) & '.' & Section & ".gz";
begin
Man_Line := New String ' ("man -l -t -Tlatin1 -Eutf8 " & Manual);
end;
end;
else
return "";
end if;
end;
end;
else
return "";
end if;
return Man_Line.all;
end Parse_Man_Command;
-------------------------------------------------------------------------
-- To Call "man" command by spawn. --
-------------------------------------------------------------------------
subtype U_String is Ada.Strings.Unbounded.Unbounded_String;
use type U_String;
function "+"(S: String) return U_String
renames Ada.Strings.Unbounded.To_Unbounded_String;
function "-"(U: U_String) return String
renames Ada.Strings.Unbounded.To_String;
type Variadic_Array is array(Positive range <> ) of U_String;
type Variadic_Access is access Variadic_Array;
type Spawn_Result_Type is
record
Process_Id : Gnat.Os_Lib.Process_Id;
Program_Name : U_String;
Args : Os_Lib.Argument_List_Access;
Output_File : U_String;
Success : Boolean := False;
Return_Code : Integer := 0;
Err_To_Out : Boolean := False;
File_Content : Variadic_Access;
end record;
use Os_Lib;
use type U_String;
function Spawn(Line : in String) return Spawn_Result_Type is
Command : Gnat.Command_Line.Command_Line;
Spawn_Result : Spawn_Result_Type;
Buffer_args, Arguments_List : Os_Lib.Argument_List_Access;
File : Text_Io.File_Type;
Deleted : Boolean := False;
Exec_Path : Os_Lib.String_Access;
begin
Set_Command_Line(Command, Line);
Gnat.Command_Line.Build(Command, Arguments_List, True);
if Arguments_List(1) /= null and then Arguments_List(1).all /= "" then
if Arguments_List'length > 1 then
Buffer_Args := new Argument_List(1..Arguments_List'Last - 1);
for I in 1..Arguments_List'Last - 1 loop
Buffer_Args(I) := new String ' (Arguments_List(I+1).all);
end loop;
Spawn_Result := (
Process_Id => Invalid_Pid,
Program_Name => +Arguments_List(1).all,
Args => Buffer_Args,
Output_File => +"out_file.txt",
Success => False,
Return_Code => 0,
Err_To_Out => True,
File_content => null
);
else
Spawn_Result := (
Process_Id => Invalid_Pid,
Program_Name => +Arguments_List(1).all,
Args => new Argument_List ' (1..0 => new String ' ("" & Character'Val(0))),
Output_File => +"out_file.txt",
Success => False,
Return_Code => 0,
Err_To_Out => True,
File_content => null
);
end if;
if Locate_Exec_On_Path(Arguments_List(1).all) /= null then
Exec_Path := new String ' (Locate_Exec_On_Path(Arguments_List(1).all).all);
if Is_Executable_File(Exec_Path.all) then
Os_Lib.Normalize_Arguments(Arguments_List.all);
Spawn_Result.Process_Id :=
Non_Blocking_Spawn(Program_Name => Exec_Path.all,
Args => Spawn_Result.Args.all,
Output_File => (-Spawn_Result.Output_File),
Err_To_Out => Spawn_Result.Err_To_out
);
if Spawn_Result.Process_Id /= Gnat.Os_Lib.Invalid_Pid then
Gnat.Os_Lib.Wait_Process(Spawn_Result.Process_Id, Spawn_Result.Success);
end if;
Spawn_Result.File_Content := new Variadic_Array(1..1);
Text_Io.Open(File, Text_Io.In_File, (-Spawn_Result.Output_File));
while not Text_Io.End_Of_File(File) loop
declare
Line : constant String := Text_Io.Get_Line(File);
Buffer : Variadic_Array(1..Spawn_Result.File_Content'Length+1);
begin
if Spawn_Result.File_Content /= null then
Buffer(Buffer'First..Buffer'Last-1) := Spawn_Result.File_Content.all;
end if;
Buffer(Buffer'Last) := (+Line);
Spawn_Result.File_Content := new Variadic_Array ' (Buffer);
end;
end loop;
Text_Io.Close(File);
Delete_File (Name => (-Spawn_Result.Output_File), Success => deleted);
if not Spawn_Result.Success then
Spawn_Result.Return_Code := Gnat.Os_Lib.Errno;
end if;
else
Spawn_Result.File_Content := new Variadic_Array ' (1 => (+(Arguments_List(1).all & " : command not found." )));
Spawn_Result.Return_Code := 127;
end if;
else
Spawn_Result.File_Content := new Variadic_Array ' (1 => (+(Arguments_List(1).all & " : command not found." )));
Spawn_Result.Return_Code := 127;
end if;
else
Spawn_Result.File_Content := new Variadic_Array ' (1 => (+(Arguments_List(1).all & " : command not found." )));
Spawn_Result.Return_Code := 127;
end if;
return Spawn_Result;
end Spawn;
-------------------------------------------------------------------------
-- Window [just dialog] --
-------------------------------------------------------------------------
procedure Insert_With_Tag
(Buffer : access Gtk_Text_Buffer_Record'Class;
Tag : String;
Text : String)
is
T : Gtk_Text_Tag;
Iter, Start_Iter : Gtk_Text_Iter;
Table : Gtk_Text_Tag_Table;
Result : Boolean;
pragma Warnings (Off, Result);
begin
Get_End_Iter (Buffer, Iter);
if Tag = "" then
Insert (Buffer, Iter, Text & ASCII.LF);
else
Table := Get_Tag_Table (Buffer);
T := Lookup (Table, Tag);
Insert (Buffer, Iter, Text & ASCII.LF);
Copy (Source => Iter, Dest => Start_Iter);
Backward_Chars (Start_Iter, Text'Length + 1, Result);
Apply_Tag (Buffer, T, Start_Iter, Iter);
end if;
end Insert_With_Tag;
Page_Frame : Gtk_Frame;
Buffer : Gtk_Text_Buffer;
Tags : Gtk_Text_Tag_Table;
Tag : Gtk_Text_Tag;
View : Gtk_Text_View;
Scrolled : Gtk_Scrolled_Window;
Man_Dialog : Gtk.Dialog.Gtk_Dialog;
Link : constant String := "/usr/share/man/man1/ls.1.gz";
Extension : constant String := File_Extension(Base_Name(Link, ".gz" ));
Section : constant String := Extension(Extension'Last..Extension'Last);
Spawn_Result : Spawn_Result_Type := Spawn(Parse_Man_Command("man " & section & ' ' & Base_Name(Link, '.' & Section & ".gz" )));
Response : Gtk_Response_Type;
Vbox : Gtk_Vbox;
Widget : Gtk_Widget;
begin
Gtk.Main.Init;
Text_Io.Put_Line ("Link_Button clicked: " & Link);
Gtk_New (Tags);
Gtk_New (Buffer, Tags);
Gtk_New (View, Buffer);
Gtk_New(Page_Frame);
Set_Label (Page_Frame, Link);
Gtk.Dialog.Gtk_New(Man_Dialog, Link, null, No_separator);
Gtk.Window.Set_Default_Size(Gtk_Window(Man_Dialog), 640, 400);
if Spawn_Result.File_Content /= null then
Print_Loop:
for I in 1..Spawn_Result.File_Content'Length loop
declare
Line : constant String := (-Spawn_Result.File_Content(I));
begin
if Line'Length > 0 then
Insert_With_Tag
(Buffer, "", Line);
else
Insert_With_Tag
(Buffer, "", "" );
end if;
end;
end loop Print_Loop;
else
Insert_With_Tag
(Buffer, "", "Spawn failure or Empry file." );
end if;
Gtk_New (Scrolled);
Set_Policy (Scrolled, Policy_Always, Policy_Always);
Add (Scrolled, View);
Show_All (Scrolled);
Add (Page_Frame, Scrolled);
Vbox := Get_Vbox(Man_Dialog);
Pack_Start(vbox, Page_Frame, True, True);
Show_All(Vbox);
Widget := Add_Button(Man_Dialog, "Close", Gtk_Response_Close);
Response := Run(Man_Dialog);
Destroy(Man_Dialog);
Gtk.Main.Main;
end Manpages_To_Gtkada;