diff options
| author | Tomas Bzatek <tbzatek@redhat.com> | 2025-11-27 21:37:04 +0100 |
|---|---|---|
| committer | Tomas Bzatek <tbzatek@redhat.com> | 2025-11-27 21:43:01 +0100 |
| commit | 0ea64a41e1499d25296bdcc69fe207e20e545efd (patch) | |
| tree | 7967ec49a0cfa1a92cec0501ada90ae7c2d4d5e2 | |
| parent | 2af0113561115645809b19e5200d433fe13199a1 (diff) | |
| download | tuxcmd-0ea64a41e1499d25296bdcc69fe207e20e545efd.tar.xz | |
Port to GOptionContext commandline argument parser
+ rework GTK initialization
| -rw-r--r-- | UConfig.pas | 150 | ||||
| -rw-r--r-- | UCoreUtils.pas | 2 | ||||
| -rw-r--r-- | UCoreWorkers.pas | 4 | ||||
| -rw-r--r-- | UGnome.pas | 10 | ||||
| -rw-r--r-- | libgtk_kylix/GTKForms.pas | 115 |
5 files changed, 118 insertions, 163 deletions
diff --git a/UConfig.pas b/UConfig.pas index 836c107..6e33947 100644 --- a/UConfig.pas +++ b/UConfig.pas @@ -88,7 +88,7 @@ var ConfPanelSep, ConfRowHeight, ConfRowHeightReal, ConfNumHistoryItems, ConfDiffCommand, ConfDiffDirCommand: string; ParamDebug, ConfShowDotFiles, ConfClearReadOnlyAttr, ConfDisableMouseRename, ConfUseSystemFont, ConfUseFileTypeIcons, - ConfFocusRefresh, ConfNewStyleAltO, ConfDirsInBold, ConfDisableDirectoryBrackets, ParamDisableGnome, + ConfFocusRefresh, ConfNewStyleAltO, ConfDirsInBold, ConfDisableDirectoryBrackets, ConfUseLibcSystem, ConfUseInternalViewer, ParamDisablePlugins: boolean; ConfNormalItemDefaultColors, ConfCursorDefaultColors, ConfInactiveItemDefaultColors, ConfSelectedItemDefaultColors, ConfLinkItemDefaultColors, ConfDotFileItemDefaultColors, ConfLynxLikeMotion, ConfSizeGroupRequestZeroDigits, @@ -136,9 +136,9 @@ function CheckConfFilesMod(var ChangedMainGUI, ChangedAssoc, ChangedBookmarks, C implementation -uses ULibc, lazglib2, SysUtils, UCoreUtils, UCore, UFileAssoc, UCoreClasses, UGnome, UVFSCore; +uses ULibc, lazglib2, lazgtk3, SysUtils, UCoreUtils, UCore, UFileAssoc, UCoreClasses, UVFSCore, GTKForms; -var InternalQuickExit, InternalDeleteHistory: boolean; +var InternalDeleteHistory: boolean; InternalMainGUIConfmtime, InternalBookmarksConfmtime, InternalFAssocConfmtime, InternalMounterConfmtime, InternalConnMgrConfmtime: Longint; @@ -155,7 +155,6 @@ begin InternalFAssocConfmtime := -1; InternalMounterConfmtime := -1; InternalConnMgrConfmtime := -1; - InternalQuickExit := False; ConfPanelSep := 50; ConfLeftPath := '/'; ConfRightPath := '/'; @@ -212,7 +211,6 @@ begin ConfNewStyleAltO := True; ConfDirsInBold := False; ConfDisableDirectoryBrackets := False; - ParamDisableGnome := False; ConfDisableFileTips := False; ConfInsMoveDown := True; ConfSpaceMovesDown := False; @@ -366,7 +364,6 @@ var s: string; IniFile: TMyIniFile; i: integer; begin - if InternalQuickExit then Exit; ConfLeftPath := LeftLocalEngine.Path; ConfRightPath := RightLocalEngine.Path; try @@ -539,7 +536,6 @@ procedure WriteMainGUISettings; var s: string; IniFile: TMyIniFile; begin - if InternalQuickExit then Exit; try s := IncludeTrailingPathDelimiter(GetHomePath) + ConfDefaultSettingsDir; if not DirectoryExists(s) then @@ -707,7 +703,6 @@ var i, j: integer; IniFile: TMyIniFile; s, SectionTitle: string; begin - if InternalQuickExit then Exit; try s := IncludeTrailingPathDelimiter(GetHomePath) + ConfDefaultSettingsDir; if not DirectoryExists(s) then @@ -771,7 +766,6 @@ procedure WriteBookmarks; var s: string; i: integer; begin - if InternalQuickExit then Exit; try s := IncludeTrailingPathDelimiter(IncludeTrailingPathDelimiter(GetHomePath) + ConfDefaultSettingsDir) + 'bookmarks'; if Bookmarks.Count > 0 then @@ -841,7 +835,6 @@ var i: integer; IniFile: TMyIniFile; s, SectionTitle: string; begin - if InternalQuickExit then Exit; try s := IncludeTrailingPathDelimiter(GetHomePath) + ConfDefaultSettingsDir; if not DirectoryExists(s) then @@ -929,7 +922,6 @@ var s, Section: string; IniFile: TMyIniFile; i: integer; begin - if InternalQuickExit then Exit; try s := IncludeTrailingPathDelimiter(GetHomePath) + ConfDefaultSettingsDir; if not DirectoryExists(s) then @@ -1033,7 +1025,6 @@ var i: integer; IniFile: TMyIniFile; s, SectionTitle: string; begin - if InternalQuickExit then Exit; try s := IncludeTrailingPathDelimiter(GetHomePath) + ConfDefaultSettingsDir; if not DirectoryExists(s) then @@ -1138,11 +1129,11 @@ begin ChangedMounter := (GetFileTime(s + 'mounter') > 0) and (GetFileTime(s + 'mounter') > InternalMounterConfmtime); ChangedConnections := (GetFileTime(s + 'connmgr') > 0) and (GetFileTime(s + 'connmgr') > InternalConnMgrConfmtime); Result := ChangedMainGUI or ChangedAssoc or ChangedBookmarks or ChangedMounter or ChangedConnections; - InternalMainGUIConfmtime := GetFileTime(s + 'gui'); - InternalFAssocConfmtime := GetFileTime(s + 'filetypes'); - InternalBookmarksConfmtime := GetFileTime(s + 'bookmarks'); - InternalMounterConfmtime := GetFileTime(s + 'mounter'); - InternalConnMgrConfmtime := GetFileTime(s + 'connmgr'); + InternalMainGUIConfmtime := LongInt(GetFileTime(s + 'gui')); + InternalFAssocConfmtime := LongInt(GetFileTime(s + 'filetypes')); + InternalBookmarksConfmtime := LongInt(GetFileTime(s + 'bookmarks')); + InternalMounterConfmtime := LongInt(GetFileTime(s + 'mounter')); + InternalConnMgrConfmtime := LongInt(GetFileTime(s + 'connmgr')); end; (********************************************************************************************************************************) @@ -1175,47 +1166,93 @@ end; (********************************************************************************************************************************) (********************************************************************************************************************************) +var arg_profile_name: Pgchar = nil; + arg_left_path: Pgchar = nil; + arg_right_path: Pgchar = nil; + arg_lang: Pgchar = nil; + procedure ParseCMDLine; -var i: integer; +var xargc: LongInt; + xargv: PPChar; s: string; + error: PGError; + + OptionEntries: array[0..7] of TGOptionEntry = ( + ( + long_name: 'debug'; + short_name: #0; flags: 0; arg: G_OPTION_ARG_NONE; + arg_data: @ParamDebug; + description: 'Enable debug messages'; + arg_description: nil; + ), + ( + long_name: 'profile'; + short_name: #0; flags: 0; arg: G_OPTION_ARG_STRING; + arg_data: @arg_profile_name; + description: 'Use different configuration profile'; + arg_description: 'profilename'; + ), + ( + long_name: 'delete-history'; + short_name: #0; flags: 0; arg: G_OPTION_ARG_NONE; + arg_data: @InternalDeleteHistory; + description: 'Delete commandline, selection and search history (use in case of locale problems)'; + arg_description: nil; + ), + ( + long_name: 'disable-plugins'; + short_name: #0; flags: 0; arg: G_OPTION_ARG_NONE; + arg_data: @ParamDisablePlugins; + description: 'Don''t load VFS modules'; + arg_description: nil; + ), + ( + long_name: 'left'; + short_name: #0; flags: 0; arg: G_OPTION_ARG_STRING; + arg_data: @arg_left_path; + description: 'Start left panel at <path>'; + arg_description: 'path'; + ), + ( + long_name: 'right'; + short_name: #0; flags: 0; arg: G_OPTION_ARG_STRING; + arg_data: @arg_left_path; + description: 'Start right panel at <path>'; + arg_description: 'path'; + ), + ( + long_name: 'lang'; + short_name: #0; flags: 0; arg: G_OPTION_ARG_STRING; + arg_data: @arg_lang; + description: 'Force specific GUI language (where <language> is a standard two-char language id)'; + arg_description: 'language'; + ), + { NULL sentinel } + ( long_name: nil; short_name: #0; flags: 0; arg: G_OPTION_ARG_NONE; arg_data: nil; description: nil; arg_description: nil; ) + ); + begin - if ParamCount > 0 then - for i := 1 to ParamCount do begin - s := UpperCase(ParamStr(i)); - if s = '--DEBUG' then ParamDebug := True else - if s = '--DISABLE-GNOME' then ParamDisableGnome := True else - if s = '--DELETE-HISTORY' then InternalDeleteHistory := True else - if s = '--ENABLE-URI' then ConfUseURI := True else - if s = '--DISABLE-PLUGINS' then ParamDisablePlugins := True else - if Pos('--PROFILE=', s) = 1 then begin - ConfProfileName := 'Profile_' + Trim(Copy(ParamStr(i), 11, Length(s) - 10)); - if ConfProfileName = '' then ConfProfileName := 'Default'; - end else - if Pos('--LEFT=', s) = 1 then ParamLeftDir := Copy(ParamStr(i), 8, Length(s) - 7) else - if Pos('--RIGHT=', s) = 1 then ParamRightDir := Copy(ParamStr(i), 9, Length(s) - 8) else - if Pos('--LANG=', s) = 1 then ConfParamForceLang := Copy(ParamStr(i), 8, Length(s) - 7) else - if (s = '--HELP') or (s = '-H') then begin - WriteLn('Tux Commander v', ConstAboutVersion, ' [built ', ConstAboutBuildDate, ']'); - WriteLn('Copyright (c) 2002-2024 Tomas Bzatek'); - WriteLn('Website: tuxcmd.sourceforge.net'); - WriteLn; - WriteLn('Usage: tuxcmd [options...]'); - WriteLn; - WriteLn('Options:'); - WriteLn(' --debug Enable debug messages'); - WriteLn(' --profile=<profilename> Use different configuration profile'); - WriteLn(' --delete-history Delete command-line, selection and search history'); - WriteLn(' (use in case of locale problems)'); - WriteLn(' --disable-gnome Don''t load GNOME libraries'); - WriteLn(' --disable-plugins Don''t load VFS modules'); - WriteLn(' --left=<path> Start left panel at <path>'); - WriteLn(' --right=<path> Start right panel at <path>'); - WriteLn(' --lang=<language> Force GUI language (the string <language> is'); - WriteLn(' standard two-char language id)'); - InternalQuickExit := True; - Halt(1); - end else WriteLn('tuxcmd: Unknown commandline option: ', ParamStr(i)); - end; + xargc := argc; + xargv := g_strdupv(argv); + + s := 'Tux Commander v' + ConstAboutVersion + ' [built ' + ConstAboutBuildDate + ']'; + error := nil; + if not gtk_init_with_args(@xargc, @xargv, PChar(s), @OptionEntries, nil, @error) then begin + WriteLn(xargv[0], ': ', error^.message); + g_error_free(error); + Halt(1); + end; + + if Assigned(arg_profile_name) then ConfProfileName := 'Profile_' + String(arg_profile_name); + if Assigned(arg_left_path) then ParamLeftDir := String(arg_left_path); + if Assigned(arg_right_path) then ParamRightDir := String(arg_right_path); + if Assigned(arg_lang) then ConfParamForceLang := String(arg_lang); + + g_free(arg_profile_name); + g_free(arg_left_path); + g_free(arg_right_path); + g_free(arg_lang); + g_strfreev(xargv); end; @@ -1229,8 +1266,7 @@ initialization {$IFDEF CPU64} {$IFDEF ENDIAN_LITTLE}'x86_64'{$ELSE}'ppc64'{$ENDIF} {$ELSE} {$IFNDEF CPUPOWERPC}'i386'{$ELSE}'ppc' {$ENDIF} {$ENDIF}, ', compiled on ', ConstFPCCompilerOSString, '/', ConstFPCCompilerHostProcessorString, ' for ', ConstFPCTargetOSString, '/', ConstFPCTargetProcessorString, ')']); - // Load GNOME libs - if not ParamDisableGnome then LoadGnomeLibs; + InitGTK(); // Create basic objects CommandLineHistory := TStringList.Create; CommandLineHistory.CaseSensitive := True; diff --git a/UCoreUtils.pas b/UCoreUtils.pas index 8949ed6..97777dc 100644 --- a/UCoreUtils.pas +++ b/UCoreUtils.pas @@ -27,6 +27,8 @@ type PIntArray = ^TIntArray; TIntArray = array[0..1023] of LongWord; + PCharArray = array[0..0] of PChar; + TOpenStringArray = array of string; TOpenPCharArray = array of PChar; diff --git a/UCoreWorkers.pas b/UCoreWorkers.pas index 4bbe8c6..cbf5124 100644 --- a/UCoreWorkers.pas +++ b/UCoreWorkers.pas @@ -20,7 +20,7 @@ unit UCoreWorkers; interface -uses lazglib2, lazgobject2, lazgtk3, SyncObjs, Classes, GTKForms, ULibc, UEngines, UCoreUtils, UVFSCore, uVFSprototypes, UCore, UDirDelete; +uses lazglib2, lazgobject2, lazgtk3, SyncObjs, Classes, UnixType, GTKForms, ULibc, UEngines, UCoreUtils, UVFSCore, uVFSprototypes, UCore, UDirDelete; type TWorkerThreadJobType = (WORKER_JOB_DUMMY, WORKER_JOB_DELETE, WORKER_JOB_COPY, WORKER_JOB_MOVE, WORKER_JOB_EXTRACT_TO_TEMP, @@ -28,7 +28,7 @@ type TWorkerThreadJobType = (WORKER_JOB_DUMMY, WORKER_JOB_DELETE, WORKER_JOB_COP type TVFSCallbackThread = class(TThread) private - FPThreadID: __pthread_t; + FPThreadID: pthread_t; FFinished: boolean; VFSCallbackEvent: TSimpleEvent; @@ -166,9 +166,6 @@ var gnome_date_edit_get_time: function (gde: PGnomeDateEdit): time_t; cdecl; - -procedure LoadGnomeLibs; - implementation uses SysUtils, DateUtils, UCoreUtils, ULocale, UFileAssoc; @@ -1467,9 +1464,7 @@ end; (********************************************************************************************************************************) (********************************************************************************************************************************) -procedure LoadGnomeLibs; -begin - // Set default values +initialization gnome_icon_entry_new := nil; gnome_icon_entry_set_pixmap_subdir := nil; gnome_icon_entry_get_filename := nil; @@ -1477,8 +1472,5 @@ begin gnome_date_edit_new := nil; gnome_date_edit_set_time := nil; gnome_date_edit_get_time := nil; -end; - - end. diff --git a/libgtk_kylix/GTKForms.pas b/libgtk_kylix/GTKForms.pas index 7c01b58..ad6e335 100644 --- a/libgtk_kylix/GTKForms.pas +++ b/libgtk_kylix/GTKForms.pas @@ -23,13 +23,9 @@ unit GTKForms; interface -uses lazglib2, lazgobject2, lazgdk3, lazgtk3, Classes, SysUtils, GTKControls, GTKConsts; - -type // Some basic types - PCharArray = array[0..0] of PChar; - - __pthread_t = {$ifdef cpu64}QWord{$else}DWord{$endif}; +uses lazglib2, lazgobject2, lazgdk3, lazgtk3, Classes, SysUtils, UnixType, GTKControls, GTKConsts; +type TCustomGTKForm = class; (****************************************** TGDKSCREEN **************************************************************************) @@ -174,18 +170,14 @@ type // Some basic types FOnException: TExceptionEvent; FMainForm: TCustomGTKForm; FMainFormSet: Boolean; - FThreadID: __pthread_t; + FThreadID: pthread_t; procedure Quit; - protected - procedure CreateHandle; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure ControlDestroyed(Control: TGTKControl); procedure CreateForm(InstanceClass: TComponentClass; var Reference); // procedure HandleException(Sender: TObject); - procedure HandleMessage; - procedure HookSynchronizeWakeup; procedure Initialize; function MessageBox(const Text: string; Buttons: TMessageButtons = [mbOK]; Style: TMessageStyle = mbInfo; Default: TMessageButton = mbNone; Escape: TMessageButton = mbNone): TMessageButton; overload; @@ -195,23 +187,22 @@ type // Some basic types procedure Run; // procedure ShowException(E: Exception); procedure Terminate; - procedure UnhookSynchronizeWakeup; property MainForm: TCustomGTKForm read FMainForm; property Terminated: Boolean read FTerminated; property OnException: TExceptionEvent read FOnException write FOnException; published - property ThreadID: __pthread_t read FThreadID; + property ThreadID: pthread_t read FThreadID; end; { Global objects } -var Application: TGTKApplication; - Screen: TGDKScreen; +var Application: TGTKApplication = nil; + Screen: TGDKScreen = nil; function GetParentForm(Control: TGTKControl): TCustomGTKForm; - - +procedure InitGTK(); + (********************************************************************************************************************************) (********************************************************************************************************************************) (********************************************************************************************************************************) @@ -348,7 +339,7 @@ end; procedure TCustomGTKForm.FormCreate(Sender: TObject); begin - // Dummy procedure, override it in ordinary instance if needed + inherited; end; procedure TCustomGTKForm.SetCaption(Value: string); @@ -522,29 +513,9 @@ begin Classes.ApplicationHandleException := @HandleException; if not Assigned(Classes.ApplicationShowException) then Classes.ApplicationShowException := @ShowException;} - CreateHandle; - HookSynchronizeWakeup; FThreadID := 0; end; -procedure TGTKApplication.CreateHandle; -var argc: gint; - argv: PPgchar; - i: Integer; -begin - argc := ParamCount; - argv := g_malloc0(argc * sizeof(Pointer)); - for i := 0 to argc - 1 do - argv[i] := g_strdup(PChar(ParamStr(i))); - - // Initialize the widget set - gtk_init(@argc, @argv); - - for i := 0 to argc - 1 do - g_free(argv[i]); - g_free(argv); -end; - destructor TGTKApplication.Destroy; type TExceptionEvent = procedure (E: Exception) of object; @@ -552,7 +523,7 @@ var P: TNotifyEvent; E: TExceptionEvent; begin -{ UnhookSynchronizeWakeup; +{ P := @HandleException; if @P = @Classes.ApplicationHandleException then Classes.ApplicationHandleException := nil; @@ -563,22 +534,6 @@ begin inherited Destroy; end; -procedure TGTKApplication.HookSynchronizeWakeup; -begin -{ if not Assigned(Classes.WakeMainThread) then - Classes.WakeMainThread := WakeMainThread; } -end; - -procedure TGTKApplication.UnhookSynchronizeWakeup; -var - P: TNotifyEvent; -begin -{ P := WakeMainThread; - if @P = @Classes.WakeMainThread then - Classes.WakeMainThread := nil; -} -end; - { procedure TGTKApplication.HandleException(Sender: TObject); begin @@ -613,7 +568,6 @@ begin // a splash screen. This allows applications that don't use CreateForm to // still have a main form but preserve the semantics the first CreateForm // being the main form. -{ TCustomGTKForm(Instance).HandleNeeded; } FMainForm := TCustomGTKForm(Instance); { if TForm(Instance).ActiveControl = nil then TForm(Instance).SetFocusedControl(TForm(Instance));} @@ -631,46 +585,14 @@ procedure TGTKApplication.Initialize; begin end; -// function GetCurrentThreadID: Integer; external 'libpthread.so.0' name 'pthread_self'; - procedure TGTKApplication.ProcessMessages; begin while WordBool(gtk_events_pending) do gtk_main_iteration; - // QApplication_processEvents(Handle); -{ if GetCurrentThreadID = Integer(MainThreadID) then - CheckSynchronize; } end; -procedure TGTKApplication.HandleMessage; -begin -// QApplication_processOneEvent(Handle); -{ if GetCurrentThreadID = Integer(MainThreadID) then - CheckSynchronize; } -end; - -procedure _exit(status: longint); cdecl; external 'libc.so.6' name '_exit'; -function __pthread_self: __pthread_t; cdecl; external 'libpthread.so.0' name 'pthread_self'; - procedure TGTKApplication.Run; begin - gtk_main(); - -{ repeat - try -// gdk_threads_enter; - FThreadID := __pthread_self(); - gtk_main(); -// gdk_threads_leave; - except - on E : Exception do - if E is EControlC then begin - WriteLn('*** Exception: ', E.Message); - _exit(1); - Exit; - end else HandleException(E); - end; - until Terminated; - } + gtk_main(); end; function TGTKApplication_MessageBox_key_press_event(widget: PGtkWidget; event: PGdkEventKey; user_data : gpointer): gboolean; cdecl; @@ -736,8 +658,6 @@ end; procedure TGTKApplication.Quit; begin gtk_main_quit(); -{ // The user lost interest - gtk_exit(0); } end; (********************************************************************************************************************************) @@ -838,13 +758,18 @@ begin Result := nil; end; +procedure InitGTK(); +begin + Screen := TGDKScreen.Create(nil); + Application := TGTKApplication.Create(Screen); +end; + initialization // Mask FPU exceptions that are redefined by Gtk+ // https://wiki.freepascal.org/SetExceptionMask + g_type_init(); SetExceptionMask([exInvalidOp, exDenormalized, exZeroDivide, exOverflow, exUnderflow, exPrecision]); - Screen := TGDKScreen.Create(nil); - Application := TGTKApplication.Create(Screen); finalization - Application.Free; - Screen.Free; + if Assigned(Application) then Application.Free; + if Assigned(Screen) then Screen.Free; end. |
