diff --git a/Lgi.xml b/Lgi.xml --- a/Lgi.xml +++ b/Lgi.xml @@ -1,635 +1,636 @@ - - + + + linux/Makefile.linux win\Makefile.windows mac/Makefile.mac haiku/Makefile.haiku gcc 0 ./include ./private/common ./include ./private/common ./include/lgi/linux ./include/lgi/linux/Gtk ./private/linux /usr/include/libayatana-appindicator3-0.1 ./include/lgi/linux ./include/lgi/linux/Gtk ./private/linux /usr/include/libayatana-appindicator3-0.1 ./include/lgi/win ./private/win ./include/lgi/win ./private/win ./include/lgi/haiku ./private/haiku ./include/lgi/haiku ./private/haiku libappindicator3-0.1 `pkg-config --cflags gtk+-3.0` `pkg-config --cflags gstreamer-1.0` libappindicator3-0.1 `pkg-config --cflags gtk+-3.0` `pkg-config --cflags gstreamer-1.0` ../../../../system/develop/headers ../../../../system/develop/headers magic appindicator3 crypt gstreamer-1.0 `pkg-config --libs gtk+-3.0` magic appindicator3 crypt gstreamer-1.0 `pkg-config --libs gtk+-3.0` -static-libgcc gnu network be -static-libgcc gnu network be lgi-gtk3 lgi-gtk3 DynamicLibrary LGI_LIBRARY LGI_UNIT_TESTS LGI_LIBRARY LGI_UNIT_TESTS POSIX _GNU_SOURCE POSIX _GNU_SOURCE -Wno-format-truncation -Wno-format-truncation diff --git a/ide/linux/Makefile.linux b/ide/linux/Makefile.linux --- a/ide/linux/Makefile.linux +++ b/ide/linux/Makefile.linux @@ -1,430 +1,430 @@ #!/usr/bin/make # # This makefile generated by LgiIde # http://www.memecode.com/lgi.php # .SILENT : CC = gcc CPP = g++ Target = ./lgiide ifndef Build Build = Debug endif MakeDir := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) BuildDir = $(Build) CFlags = -MMD -MP -fPIC -fno-inline CppFlags = $(CFlags) -fpermissive -std=c++14 ifeq ($(Build),Debug) CFlags += -g CppFlags += -g Tag = d Defs = -D_DEBUG -DLINUX -D_REENTRANT -D_FILE_OFFSET_BITS=64 -DPOSIX Libs = \ -lmagic \ -lpthread \ `pkg-config --libs gtk+-3.0` \ -llgi-gtk3$(Tag) \ -L../$(BuildDir) Inc = \ `pkg-config --cflags gtk+-3.0` \ -I./src \ -I./resources \ -I../private/common \ -I../include/lgi/linux/Gtk \ -I../include/lgi/linux \ - -I../include \ - -I../../../../codelib/openssl/include + -I../include else CFlags += -s -Os CppFlags += -s -Os Defs = -DLINUX -D_REENTRANT -D_FILE_OFFSET_BITS=64 -DPOSIX Libs = \ -lmagic \ -lpthread \ `pkg-config --libs gtk+-3.0` \ -llgi-gtk3$(Tag) \ -L../$(BuildDir) Inc = \ `pkg-config --cflags gtk+-3.0` \ -I./src \ -I./resources \ -I../private/common \ -I../include/lgi/linux/Gtk \ -I../include/lgi/linux \ - -I../include \ - -I../../../../codelib/openssl/include + -I../include endif # Dependencies Source = src/WebFldDlg.cpp \ src/SysCharSupport.cpp \ src/SpaceTabConv.cpp \ src/SimpleCppParser.cpp \ src/PythonParser.cpp \ src/ProjectNode.cpp \ src/NewProjectFromTemplate.cpp \ src/MissingFiles.cpp \ src/MemDumpViewer.cpp \ src/LgiUtils.cpp \ src/LgiIde.cpp \ src/JavascriptParser.cpp \ src/IdeProjectSettings.cpp \ src/IdeProject.cpp \ src/IdeFindInFiles.cpp \ src/IdeDoc.cpp \ src/IdeCommon.cpp \ src/History.cpp \ src/FtpThread.cpp \ src/FindSymbol.cpp \ src/DocEditStyling.cpp \ src/DocEdit.cpp \ src/Debugger.cpp \ src/DebugContext.cpp \ src/AddFtpFile.cpp \ ../src/common/Text/TextView4.cpp \ ../src/common/Text/TextConvert.cpp \ ../src/common/Text/HtmlParser.cpp \ ../src/common/Text/HtmlCommon.cpp \ ../src/common/Text/Html.cpp \ ../src/common/Text/Homoglyphs/HomoglyphsTable.cpp \ ../src/common/Text/Homoglyphs/Homoglyphs.cpp \ ../src/common/Text/DocView.cpp \ ../src/common/Net/OpenSSLSocket.cpp \ ../src/common/Net/Http.cpp \ ../src/common/Net/Ftp.cpp \ ../src/common/Lgi/Mdi.cpp \ ../src/common/Lgi/LgiMain.cpp \ ../src/common/Lgi/About.cpp \ ../src/common/Gdc2/Filters/Png.cpp \ ../src/common/Coding/ParseCpp.cpp \ ../src/common/Coding/LexCpp.cpp SourceC := $(filter %.c,$(Source)) ObjectsC := $(SourceC:.c=.o) SourceCpp := $(filter %.cpp,$(Source)) ObjectsCpp := $(SourceCpp:.cpp=.o) Objects := $(notdir $(ObjectsC) $(ObjectsCpp)) Objects := $(addprefix $(BuildDir)/,$(Objects)) Deps := $(patsubst %.o,%.d,$(Objects)) $(BuildDir)/%.o: %.c mkdir -p $(@D) echo $(notdir $<) [$(Build)] $(CC) $(Inc) $(CFlags) $(Defs) -c $< -o $@ $(BuildDir)/%.o: %.cpp mkdir -p $(@D) echo $(notdir $<) [$(Build)] $(CPP) $(Inc) $(CppFlags) $(Defs) -c $< -o $@ # Target # Executable target $(Target) : ../$(BuildDir)/liblgi-gtk3$(Tag).so $(Objects) mkdir -p $(BuildDir) @echo Linking $(Target) [$(Build)]... $(CPP) -Wl,-export-dynamic,-R. -o \ $(Target) $(Objects) $(Libs) @echo Done. ../$(BuildDir)/liblgi-gtk3$(Tag).so : ../include/lgi/common/App.h \ ../include/lgi/common/Array.h \ ../include/lgi/common/AutoPtr.h \ ../include/lgi/common/Base64.h \ ../include/lgi/common/Bitmap.h \ ../include/lgi/common/Box.h \ ../include/lgi/common/Button.h \ ../include/lgi/common/CairoSurface.h \ ../include/lgi/common/Cancel.h \ ../include/lgi/common/Capabilities.h \ ../include/lgi/common/Charset.h \ ../include/lgi/common/CheckBox.h \ ../include/lgi/common/ClipBoard.h \ ../include/lgi/common/Colour.h \ ../include/lgi/common/ColourSpace.h \ ../include/lgi/common/Com.h \ ../include/lgi/common/Combo.h \ ../include/lgi/common/Containers.h \ ../include/lgi/common/Core.h \ ../include/lgi/common/Css.h \ ../include/lgi/common/CssTools.h \ ../include/lgi/common/CurrentTime.h \ ../include/lgi/common/DataDlg.h \ ../include/lgi/common/DateTime.h \ ../include/lgi/common/Dialog.h \ ../include/lgi/common/DisplayString.h \ ../include/lgi/common/DocView.h \ ../include/lgi/common/Dom.h \ ../include/lgi/common/DomFields.h \ ../include/lgi/common/DragAndDrop.h \ ../include/lgi/common/DropFiles.h \ ../include/lgi/common/Edit.h \ ../include/lgi/common/Emoji.h \ ../include/lgi/common/Error.h \ ../include/lgi/common/EventTargetThread.h \ ../include/lgi/common/File.h \ ../include/lgi/common/FileSelect.h \ ../include/lgi/common/Filter.h \ ../include/lgi/common/FindReplaceDlg.h \ ../include/lgi/common/Font.h \ ../include/lgi/common/FontCache.h \ ../include/lgi/common/FontSelect.h \ ../include/lgi/common/Gdc2.h \ ../include/lgi/common/GdcTools.h \ ../include/lgi/common/GdiLeak.h \ ../include/lgi/common/HashTable.h \ ../include/lgi/common/ImageList.h \ ../include/lgi/common/Input.h \ ../include/lgi/common/ItemContainer.h \ ../include/lgi/common/Json.h \ ../include/lgi/common/Layout.h \ ../include/lgi/common/Lgi.h \ ../include/lgi/common/LgiClasses.h \ ../include/lgi/common/LgiCommon.h \ ../include/lgi/common/LgiDefs.h \ ../include/lgi/common/LgiInc.h \ ../include/lgi/common/LgiInterfaces.h \ ../include/lgi/common/LgiMsgs.h \ ../include/lgi/common/LgiRes.h \ ../include/lgi/common/LgiString.h \ ../include/lgi/common/LgiUiBase.h \ ../include/lgi/common/Library.h \ ../include/lgi/common/LibraryUtils.h \ ../include/lgi/common/List.h \ ../include/lgi/common/ListItemCheckBox.h \ ../include/lgi/common/ListItemRadioBtn.h \ ../include/lgi/common/LMallocArray.h \ ../include/lgi/common/Mail.h \ ../include/lgi/common/Matrix.h \ ../include/lgi/common/Mem.h \ ../include/lgi/common/Menu.h \ ../include/lgi/common/Message.h \ ../include/lgi/common/Mime.h \ ../include/lgi/common/Mru.h \ ../include/lgi/common/Mutex.h \ ../include/lgi/common/Net.h \ ../include/lgi/common/Notifications.h \ ../include/lgi/common/OAuth2.h \ ../include/lgi/common/OptionsFile.h \ ../include/lgi/common/Palette.h \ ../include/lgi/common/Panel.h \ ../include/lgi/common/Password.h \ ../include/lgi/common/Path.h \ ../include/lgi/common/PixelRops.h \ ../include/lgi/common/Point.h \ ../include/lgi/common/Popup.h \ ../include/lgi/common/PopupList.h \ ../include/lgi/common/PopupNotification.h \ ../include/lgi/common/Printer.h \ ../include/lgi/common/Profile.h \ ../include/lgi/common/Progress.h \ ../include/lgi/common/ProgressDlg.h \ ../include/lgi/common/ProgressView.h \ ../include/lgi/common/Properties.h \ ../include/lgi/common/RadioGroup.h \ ../include/lgi/common/Range.h \ ../include/lgi/common/Rect.h \ ../include/lgi/common/RectF.h \ ../include/lgi/common/RefCount.h \ ../include/lgi/common/RegKey.h \ ../include/lgi/common/Res.h \ ../include/lgi/common/Rops.h \ ../include/lgi/common/ScrollBar.h \ ../include/lgi/common/SkinEngine.h \ ../include/lgi/common/Slider.h \ ../include/lgi/common/Splitter.h \ ../include/lgi/common/Stat.h \ ../include/lgi/common/StatusBar.h \ ../include/lgi/common/Store3Defs.h \ ../include/lgi/common/Stream.h \ ../include/lgi/common/StringClass.h \ ../include/lgi/common/StringLayout.h \ ../include/lgi/common/StructuredIo.h \ ../include/lgi/common/StructuredLog.h \ ../include/lgi/common/SubProcess.h \ ../include/lgi/common/TableLayout.h \ ../include/lgi/common/TabView.h \ ../include/lgi/common/TextConvert.h \ ../include/lgi/common/TextFile.h \ ../include/lgi/common/TextLabel.h \ ../include/lgi/common/TextLog.h \ ../include/lgi/common/TextView3.h \ ../include/lgi/common/Thread.h \ ../include/lgi/common/ThreadEvent.h \ ../include/lgi/common/TimeZoneInfo.h \ ../include/lgi/common/Token.h \ ../include/lgi/common/ToolBar.h \ ../include/lgi/common/ToolTip.h \ ../include/lgi/common/TrayIcon.h \ ../include/lgi/common/Tree.h \ ../include/lgi/common/TypeToString.h \ ../include/lgi/common/Undo.h \ ../include/lgi/common/Unicode.h \ ../include/lgi/common/UnicodeString.h \ ../include/lgi/common/UnrolledList.h \ ../include/lgi/common/Uri.h \ ../include/lgi/common/Variant.h \ ../include/lgi/common/View.h \ ../include/lgi/common/Widgets.h \ ../include/lgi/common/Window.h \ ../include/lgi/common/XmlTree.h \ ../include/lgi/linux/Gtk/LgiOsClasses.h \ ../include/lgi/linux/Gtk/LgiOsDefs.h \ ../include/lgi/linux/Gtk/LgiWidget.h \ ../include/lgi/linux/Gtk/LgiWinManGlue.h \ ../include/lgi/mac/cocoa/LCocoaView.h \ ../include/lgi/mac/cocoa/LgiMac.h \ ../include/lgi/mac/cocoa/LgiOs.h \ ../include/lgi/mac/cocoa/LgiOsClasses.h \ ../include/lgi/mac/cocoa/LgiOsDefs.h \ ../include/lgi/mac/cocoa/ObjCWrapper.h \ ../include/lgi/mac/cocoa/SymLookup.h \ ../private/common/FontPriv.h \ ../private/common/ViewPriv.h \ ../private/linux/AppPriv.h \ ../src/common/Gdc2/15Bit.cpp \ ../src/common/Gdc2/16Bit.cpp \ ../src/common/Gdc2/24Bit.cpp \ ../src/common/Gdc2/32Bit.cpp \ ../src/common/Gdc2/8Bit.cpp \ ../src/common/Gdc2/Alpha.cpp \ ../src/common/Gdc2/Colour.cpp \ ../src/common/Gdc2/Filters/Filter.cpp \ ../src/common/Gdc2/Font/Charset.cpp \ ../src/common/Gdc2/Font/DisplayString.cpp \ ../src/common/Gdc2/Font/Font.cpp \ ../src/common/Gdc2/Font/FontSystem.cpp \ ../src/common/Gdc2/Font/FontType.cpp \ ../src/common/Gdc2/Font/StringLayout.cpp \ ../src/common/Gdc2/Font/TypeFace.cpp \ ../src/common/Gdc2/GdcCommon.cpp \ ../src/common/Gdc2/Path/Path.cpp \ ../src/common/Gdc2/Rect.cpp \ ../src/common/Gdc2/RopsCases.cpp \ ../src/common/Gdc2/Surface.cpp \ ../src/common/Gdc2/Tools/ColourReduce.cpp \ ../src/common/Gdc2/Tools/GdcTools.cpp \ ../src/common/General/Containers.cpp \ ../src/common/General/DateTime.cpp \ ../src/common/General/ExeCheck.cpp \ ../src/common/General/FileCommon.cpp \ ../src/common/General/Password.cpp \ ../src/common/General/Properties.cpp \ + ../src/common/General/TimeZone.cpp \ ../src/common/Hash/md5/md5.c \ ../src/common/Hash/md5/md5.h \ ../src/common/Hash/sha1/sha1.c \ ../src/common/Hash/sha1/sha1.h \ ../src/common/Lgi/Alert.cpp \ ../src/common/Lgi/AppCommon.cpp \ ../src/common/Lgi/ClipBoardCommon.cpp \ ../src/common/Lgi/Css.cpp \ ../src/common/Lgi/CssTools.cpp \ ../src/common/Lgi/DataDlg.cpp \ ../src/common/Lgi/DragAndDropCommon.cpp \ ../src/common/Lgi/FileSelect.cpp \ ../src/common/Lgi/FindReplace.cpp \ ../src/common/Lgi/FontSelect.cpp \ ../src/common/Lgi/GuiUtils.cpp \ ../src/common/Lgi/Input.cpp \ ../src/common/Lgi/LgiCommon.cpp \ ../src/common/Lgi/Library.cpp \ ../src/common/Lgi/LMsg.cpp \ ../src/common/Lgi/MemStream.cpp \ ../src/common/Lgi/MenuCommon.cpp \ ../src/common/Lgi/Mru.cpp \ ../src/common/Lgi/Mutex.cpp \ ../src/common/Lgi/Object.cpp \ ../src/common/Lgi/OptionsFile.cpp \ ../src/common/Lgi/Rand.cpp \ ../src/common/Lgi/Stream.cpp \ ../src/common/Lgi/ThreadCommon.cpp \ ../src/common/Lgi/ThreadEvent.cpp \ ../src/common/Lgi/ToolTip.cpp \ ../src/common/Lgi/TrayIcon.cpp \ ../src/common/Lgi/Variant.cpp \ ../src/common/Lgi/ViewCommon.cpp \ ../src/common/Lgi/WindowCommon.cpp \ ../src/common/Net/Base64.cpp \ ../src/common/Net/MDStringToDigest.cpp \ ../src/common/Net/Net.cpp \ ../src/common/Net/Uri.cpp \ ../src/common/Resource/LgiRes.cpp \ ../src/common/Resource/Res.cpp \ ../src/common/Skins/Gel/Gel.cpp \ ../src/common/Text/DocView.cpp \ ../src/common/Text/String.cpp \ ../src/common/Text/TextConvert.cpp \ ../src/common/Text/TextView3.cpp \ ../src/common/Text/Token.cpp \ ../src/common/Text/Unicode.cpp \ ../src/common/Text/Utf8.cpp \ ../src/common/Text/XmlTree.cpp \ ../src/common/Widgets/Bitmap.cpp \ ../src/common/Widgets/Box.cpp \ ../src/common/Widgets/Button.cpp \ ../src/common/Widgets/CheckBox.cpp \ ../src/common/Widgets/Combo.cpp \ ../src/common/Widgets/Edit.cpp \ ../src/common/Widgets/ItemContainer.cpp \ ../src/common/Widgets/List.cpp \ ../src/common/Widgets/Panel.cpp \ ../src/common/Widgets/Popup.cpp \ ../src/common/Widgets/Progress.cpp \ ../src/common/Widgets/ProgressDlg.cpp \ ../src/common/Widgets/RadioGroup.cpp \ ../src/common/Widgets/ScrollBar.cpp \ ../src/common/Widgets/Slider.cpp \ ../src/common/Widgets/Splitter.cpp \ ../src/common/Widgets/StatusBar.cpp \ ../src/common/Widgets/TableLayout.cpp \ ../src/common/Widgets/TabView.cpp \ ../src/common/Widgets/TextLabel.cpp \ ../src/common/Widgets/ToolBar.cpp \ ../src/common/Widgets/Tree.cpp \ ../src/linux/General/File.cpp \ ../src/linux/General/Mem.cpp \ ../src/linux/General/ShowFileProp_Linux.cpp \ ../src/linux/Gtk/Gdc2.cpp \ ../src/linux/Gtk/LgiWidget.cpp \ ../src/linux/Gtk/MemDC.cpp \ ../src/linux/Gtk/PrintDC.cpp \ ../src/linux/Gtk/ScreenDC.cpp \ ../src/linux/Lgi/App.cpp \ ../src/linux/Lgi/ClipBoard.cpp \ ../src/linux/Lgi/Dialog.cpp \ ../src/linux/Lgi/DragAndDrop.cpp \ ../src/linux/Lgi/General.cpp \ ../src/linux/Lgi/Layout.cpp \ ../src/linux/Lgi/Menu.cpp \ ../src/linux/Lgi/Printer.cpp \ ../src/linux/Lgi/Thread.cpp \ ../src/linux/Lgi/View.cpp \ ../src/linux/Lgi/Window.cpp \ - ../src/posix/SubProcess.cpp + ../src/posix/SubProcess.cpp \ + ../../../../../../usr/include/libayatana-appindicator3-0.1/libayatana-appindicator/app-indicator.h export Build=$(Build); \ $(MAKE) -C ../ -f ./linux/Makefile.linux -include $(Objects:.o=.d) # Clean just this target clean : rm -rf $(BuildDir) $(Target) @echo Cleaned $(BuildDir) $(Target) # Clean all targets cleanall : rm -rf $(BuildDir) $(Target) @echo Cleaned $(BuildDir) $(Target) +make -C "../" -f ./linux/Makefile.linux clean VPATH=$(BuildDir) \ ../src/common/Text/Homoglyphs \ ../src/common/Text \ ../src/common/Net \ ../src/common/Lgi \ ../src/common/Gdc2/Filters \ ../src/common/Coding \ ./src diff --git a/linux/Makefile.linux b/linux/Makefile.linux --- a/linux/Makefile.linux +++ b/linux/Makefile.linux @@ -1,235 +1,236 @@ #!/usr/bin/make # # This makefile generated by LgiIde # http://www.memecode.com/lgi.php # .SILENT : CC = gcc CPP = g++ Target = lgi-gtk3 ifndef Build Build = Debug endif MakeDir := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) BuildDir = $(Build) CFlags = -MMD -MP -fPIC -fno-inline CppFlags = $(CFlags) -fpermissive -std=c++14 ifeq ($(Build),Debug) CFlags += -g -Wno-format-truncation CppFlags += -g -Wno-format-truncation Tag = d Defs = -D_DEBUG -DLINUX -D_REENTRANT -D_FILE_OFFSET_BITS=64 -DPOSIX -DLGI_LIBRARY -DLGI_UNIT_TESTS Libs = \ -lmagic \ -lappindicator3 \ -lcrypt \ -lgstreamer-1.0 \ `pkg-config --libs gtk+-3.0` Inc = \ `pkg-config --cflags gtk+-3.0` \ `pkg-config --cflags gstreamer-1.0` \ -I../../../../../usr/include/libayatana-appindicator3-0.1 \ -I./private/linux \ -I./private/common \ -I./include/lgi/linux/Gtk \ -I./include/lgi/linux \ -I./include else CFlags += -s -Os -Wno-format-truncation CppFlags += -s -Os -Wno-format-truncation Defs = -DLINUX -D_REENTRANT -D_FILE_OFFSET_BITS=64 -DPOSIX -DLGI_LIBRARY -DLGI_UNIT_TESTS Libs = \ -lmagic \ -lappindicator3 \ -lcrypt \ -lgstreamer-1.0 \ `pkg-config --libs gtk+-3.0` Inc = \ `pkg-config --cflags gtk+-3.0` \ `pkg-config --cflags gstreamer-1.0` \ -I../../../../../usr/include/libayatana-appindicator3-0.1 \ -I./private/linux \ -I./private/common \ -I./include/lgi/linux/Gtk \ -I./include/lgi/linux \ -I./include endif # Dependencies Source = src/posix/SubProcess.cpp \ src/linux/Lgi/Window.cpp \ src/linux/Lgi/View.cpp \ src/linux/Lgi/Thread.cpp \ src/linux/Lgi/Printer.cpp \ src/linux/Lgi/Menu.cpp \ src/linux/Lgi/Layout.cpp \ src/linux/Lgi/General.cpp \ src/linux/Lgi/DragAndDrop.cpp \ src/linux/Lgi/Dialog.cpp \ src/linux/Lgi/ClipBoard.cpp \ src/linux/Lgi/App.cpp \ src/linux/Gtk/ScreenDC.cpp \ src/linux/Gtk/PrintDC.cpp \ src/linux/Gtk/MemDC.cpp \ src/linux/Gtk/LgiWidget.cpp \ src/linux/Gtk/Gdc2.cpp \ src/linux/General/ShowFileProp_Linux.cpp \ src/linux/General/Mem.cpp \ src/linux/General/File.cpp \ src/common/Widgets/Tree.cpp \ src/common/Widgets/ToolBar.cpp \ src/common/Widgets/TextLabel.cpp \ src/common/Widgets/TabView.cpp \ src/common/Widgets/TableLayout.cpp \ src/common/Widgets/StatusBar.cpp \ src/common/Widgets/Splitter.cpp \ src/common/Widgets/Slider.cpp \ src/common/Widgets/ScrollBar.cpp \ src/common/Widgets/RadioGroup.cpp \ src/common/Widgets/ProgressDlg.cpp \ src/common/Widgets/Progress.cpp \ src/common/Widgets/Popup.cpp \ src/common/Widgets/Panel.cpp \ src/common/Widgets/List.cpp \ src/common/Widgets/ItemContainer.cpp \ src/common/Widgets/Edit.cpp \ src/common/Widgets/Combo.cpp \ src/common/Widgets/CheckBox.cpp \ src/common/Widgets/Button.cpp \ src/common/Widgets/Box.cpp \ src/common/Widgets/Bitmap.cpp \ src/common/Text/XmlTree.cpp \ src/common/Text/Utf8.cpp \ src/common/Text/Unicode.cpp \ src/common/Text/Token.cpp \ src/common/Text/TextView3.cpp \ src/common/Text/TextConvert.cpp \ src/common/Text/String.cpp \ src/common/Text/DocView.cpp \ src/common/Skins/Gel/Gel.cpp \ src/common/Resource/Res.cpp \ src/common/Resource/LgiRes.cpp \ src/common/Net/Uri.cpp \ src/common/Net/Net.cpp \ src/common/Net/MDStringToDigest.cpp \ src/common/Net/Base64.cpp \ src/common/Lgi/WindowCommon.cpp \ src/common/Lgi/ViewCommon.cpp \ src/common/Lgi/Variant.cpp \ src/common/Lgi/TrayIcon.cpp \ src/common/Lgi/ToolTip.cpp \ src/common/Lgi/ThreadEvent.cpp \ src/common/Lgi/ThreadCommon.cpp \ src/common/Lgi/Stream.cpp \ src/common/Lgi/Rand.cpp \ src/common/Lgi/OptionsFile.cpp \ src/common/Lgi/Object.cpp \ src/common/Lgi/Mutex.cpp \ src/common/Lgi/Mru.cpp \ src/common/Lgi/MenuCommon.cpp \ src/common/Lgi/MemStream.cpp \ src/common/Lgi/LMsg.cpp \ src/common/Lgi/Library.cpp \ src/common/Lgi/LgiCommon.cpp \ src/common/Lgi/Input.cpp \ src/common/Lgi/GuiUtils.cpp \ src/common/Lgi/FontSelect.cpp \ src/common/Lgi/FindReplace.cpp \ src/common/Lgi/FileSelect.cpp \ src/common/Lgi/DragAndDropCommon.cpp \ src/common/Lgi/DataDlg.cpp \ src/common/Lgi/CssTools.cpp \ src/common/Lgi/Css.cpp \ src/common/Lgi/ClipBoardCommon.cpp \ src/common/Lgi/AppCommon.cpp \ src/common/Lgi/Alert.cpp \ src/common/Hash/sha1/sha1.c \ src/common/Hash/md5/md5.c \ + src/common/General/TimeZone.cpp \ src/common/General/Properties.cpp \ src/common/General/Password.cpp \ src/common/General/FileCommon.cpp \ src/common/General/ExeCheck.cpp \ src/common/General/DateTime.cpp \ src/common/General/Containers.cpp \ src/common/Gdc2/Tools/GdcTools.cpp \ src/common/Gdc2/Tools/ColourReduce.cpp \ src/common/Gdc2/Surface.cpp \ src/common/Gdc2/Rect.cpp \ src/common/Gdc2/Path/Path.cpp \ src/common/Gdc2/GdcCommon.cpp \ src/common/Gdc2/Font/TypeFace.cpp \ src/common/Gdc2/Font/StringLayout.cpp \ src/common/Gdc2/Font/FontType.cpp \ src/common/Gdc2/Font/FontSystem.cpp \ src/common/Gdc2/Font/Font.cpp \ src/common/Gdc2/Font/DisplayString.cpp \ src/common/Gdc2/Font/Charset.cpp \ src/common/Gdc2/Filters/Filter.cpp \ src/common/Gdc2/Colour.cpp \ src/common/Gdc2/Alpha.cpp \ src/common/Gdc2/8Bit.cpp \ src/common/Gdc2/32Bit.cpp \ src/common/Gdc2/24Bit.cpp \ src/common/Gdc2/16Bit.cpp \ src/common/Gdc2/15Bit.cpp SourceC := $(filter %.c,$(Source)) ObjectsC := $(SourceC:.c=.o) SourceCpp := $(filter %.cpp,$(Source)) ObjectsCpp := $(SourceCpp:.cpp=.o) Objects := $(notdir $(ObjectsC) $(ObjectsCpp)) Objects := $(addprefix $(BuildDir)/,$(Objects)) Deps := $(patsubst %.o,%.d,$(Objects)) $(BuildDir)/%.o: %.c mkdir -p $(@D) echo $(notdir $<) [$(Build)] $(CC) $(Inc) $(CFlags) $(Defs) -c $< -o $@ $(BuildDir)/%.o: %.cpp mkdir -p $(@D) echo $(notdir $<) [$(Build)] $(CPP) $(Inc) $(CppFlags) $(Defs) -c $< -o $@ # Target TargetFile = lib$(Target)$(Tag).so $(TargetFile) : $(Objects) mkdir -p $(BuildDir) @echo Linking $(TargetFile) [$(Build)]... $(CPP)$s -shared \ \ -o $(BuildDir)/$(TargetFile) \ $(Objects) \ $(Libs) @echo Done. -include $(Objects:.o=.d) # Clean out targets clean : rm -rf $(BuildDir) @echo Cleaned $(BuildDir) VPATH=$(BuildDir) \ ./src/posix \ ./src/linux/Lgi \ ./src/linux/Gtk \ ./src/linux/General \ ./src/common/Widgets \ ./src/common/Text \ ./src/common/Skins/Gel \ ./src/common/Resource \ ./src/common/Net \ ./src/common/Lgi \ ./src/common/Hash/sha1 \ ./src/common/Hash/md5 \ ./src/common/General \ ./src/common/Gdc2/Tools \ ./src/common/Gdc2/Path \ ./src/common/Gdc2/Font \ ./src/common/Gdc2/Filters \ ./src/common/Gdc2 diff --git a/src/linux/General/File.cpp b/src/linux/General/File.cpp --- a/src/linux/General/File.cpp +++ b/src/linux/General/File.cpp @@ -1,1727 +1,1727 @@ /*hdr ** FILE: File.cpp ** AUTHOR: Matthew Allen ** DATE: 8/10/2000 ** DESCRIPTION: The new file subsystem ** ** Copyright (C) 2000, Matthew Allen ** fret@memecode.com */ /****************************** Includes **********************************/ #include #include #include #include #include #include #include #include #ifndef _MSC_VER #include #endif #include "lgi/common/LgiDefs.h" #include "lgi/common/File.h" #include "lgi/common/Containers.h" #include "lgi/common/Token.h" #include "lgi/common/Gdc2.h" #include "lgi/common/LgiCommon.h" #include "lgi/common/LgiString.h" #include "lgi/common/DateTime.h" #if defined(WIN32) #include "errno.h" #endif /****************************** Defines ***********************************/ // #define FILEDEBUG #define FLOPPY_360K 0x0001 #define FLOPPY_720K 0x0002 #define FLOPPY_1_2M 0x0004 #define FLOPPY_1_4M 0x0008 #define FLOPPY_5_25 (FLOPPY_360K | FLOPPY_1_2M) #define FLOPPY_3_5 (FLOPPY_720K | FLOPPY_1_4M) /****************************** Globals ***********************************/ LString LFile::Path::Sep(DIR_STR); struct ErrorCodeType { const char *Name; int Code; const char *Desc; } ErrorCodes[] = { #if defined(WIN32) {"EPERM", 1, "Not owner"}, {"ENOENT", 2, "No such file"}, {"ESRCH", 3, "No such process"}, {"EINTR", 4, "Interrupted system"}, {"EIO", 5, "I/O error"}, {"ENXIO", 6, "No such device"}, {"E2BIG", 7, "Argument list too long"}, {"ENOEXEC", 8, "Exec format error"}, {"EBADF", 9, "Bad file number"}, {"ECHILD", 10, "No children"}, {"EAGAIN", 11, "No more processes"}, {"ENOMEM", 12, "Not enough core"}, {"EACCES", 13, "Permission denied"}, {"EFAULT", 14, "Bad address"}, {"ENOTBLK", 15, "Block device required"}, {"EBUSY", 16, "Mount device busy"}, {"EEXIST", 17, "File exists"}, {"EXDEV", 18, "Cross-device link"}, {"ENODEV", 19, "No such device"}, {"ENOTDIR", 20, "Not a directory"}, {"EISDIR", 21, "Is a directory"}, {"EINVAL", 22, "Invalid argument"}, {"ENFILE", 23, "File table overflow"}, {"EMFILE", 24, "Too many open file"}, {"ENOTTY", 25, "Not a typewriter"}, {"ETXTBSY", 26, "Text file busy"}, {"EFBIG", 27, "File too large"}, {"ENOSPC", 28, "No space left on"}, {"ESPIPE", 29, "Illegal seek"}, {"EROFS", 30, "Read-only file system"}, {"EMLINK", 31, "Too many links"}, {"EPIPE", 32, "Broken pipe"}, {"EWOULDBLOCK", 35, "Operation would block"}, {"EINPROGRESS", 36, "Operation now in progress"}, {"EALREADY", 37, "Operation already in progress"}, {"ENOTSOCK", 38, "Socket operation on"}, {"EDESTADDRREQ", 39, "Destination address required"}, {"EMSGSIZE", 40, "Message too long"}, {"EPROTOTYPE", 41, "Protocol wrong type"}, {"ENOPROTOOPT", 42, "Protocol not available"}, {"EPROTONOSUPPORT", 43, "Protocol not supported"}, {"ESOCKTNOSUPPORT", 44, "Socket type not supported"}, {"EOPNOTSUPP", 45, "Operation not supported"}, {"EPFNOSUPPORT", 46, "Protocol family not supported"}, {"EAFNOSUPPORT", 47, "Address family not supported"}, {"EADDRINUSE", 48, "Address already in use"}, {"EADDRNOTAVAIL", 49, "Can't assign requested address"}, {"ENETDOWN", 50, "Network is down"}, {"ENETUNREACH", 51, "Network is unreachable"}, {"ENETRESET", 52, "Network dropped connection"}, {"ECONNABORTED", 53, "Software caused connection"}, {"ECONNRESET", 54, "Connection reset by peer"}, {"ENOBUFS", 55, "No buffer space available"}, {"EISCONN", 56, "Socket is already connected"}, {"ENOTCONN", 57, "Socket is not connected" }, {"ESHUTDOWN", 58, "Can't send after shutdown"}, {"ETOOMANYREFS", 59, "Too many references"}, {"ETIMEDOUT", 60, "Connection timed out"}, {"ECONNREFUSED", 61, "Connection refused"}, {"ELOOP", 62, "Too many levels of nesting"}, {"ENAMETOOLONG", 63, "File name too long" }, {"EHOSTDOWN", 64, "Host is down"}, {"EHOSTUNREACH", 65, "No route to host"}, {"ENOTEMPTY", 66, "Directory not empty"}, {"EPROCLIM", 67, "Too many processes"}, {"EUSERS", 68, "Too many users"}, {"EDQUOT", 69, "Disc quota exceeded"}, {"ESTALE", 70, "Stale NFS file handle"}, {"EREMOTE", 71, "Too many levels of remote in the path"}, {"ENOSTR", 72, "Device is not a stream"}, {"ETIME", 73, "Timer expired"}, {"ENOSR", 74, "Out of streams resources"}, {"ENOMSG", 75, "No message"}, {"EBADMSG", 76, "Trying to read unreadable message"}, {"EIDRM", 77, "Identifier removed"}, {"EDEADLK", 78, "Deadlock condition"}, {"ENOLCK", 79, "No record locks available"}, {"ENONET", 80, "Machine is not on network"}, {"ERREMOTE", 81, "Object is remote"}, {"ENOLINK", 82, "The link has been severed"}, {"EADV", 83, "ADVERTISE error"}, {"ESRMNT", 84, "SRMOUNT error"}, {"ECOMM", 85, "Communication error"}, {"EPROTO", 86, "Protocol error"}, {"EMULTIHOP", 87, "Multihop attempted"}, {"EDOTDOT", 88, "Cross mount point"}, {"EREMCHG", 89, "Remote address change"}, #elif defined(LINUX) || defined(__GTK_H__) {"EPERM", EPERM, "Operation not permitted"}, {"ENOENT", ENOENT, "No such file or directory"}, {"ESRCH", ESRCH, "No such process"}, {"EINTR", EINTR, "Interrupted system call"}, {"EIO", EIO, "I/O error"}, {"ENXIO", ENXIO, "No such device or address"}, {"E2BIG", E2BIG, "Argument list too long"}, {"ENOEXEC", ENOEXEC, "Exec format error"}, {"EBADF", EBADF, "Bad file number"}, {"ECHILD", ECHILD, "No child processes"}, {"EAGAIN", EAGAIN, "Try again"}, {"ENOMEM", ENOMEM, "Out of memory"}, {"EACCES", EACCES, "Permission denied"}, {"EFAULT", EFAULT, "Bad address"}, {"ENOTBLK", ENOTBLK, "Block device required"}, {"EBUSY", EBUSY, "Device or resource busy"}, {"EEXIST", EEXIST, "File exists"}, {"EXDEV", EXDEV, "Cross-device link"}, {"ENODEV", ENODEV, "No such device"}, {"ENOTDIR", ENOTDIR, "Not a directory"}, {"EISDIR", EISDIR, "Is a directory"}, {"EINVAL", EINVAL, "Invalid argument"}, {"ENFILE", ENFILE, "File table overflow"}, {"EMFILE", EMFILE, "Too many open files"}, {"ENOTTY", ENOTTY, "Not a typewriter"}, {"ETXTBSY", ETXTBSY, "Text file busy"}, {"EFBIG", EFBIG, "File too large"}, {"ENOSPC", ENOSPC, "No space left on device"}, {"ESPIPE", ESPIPE, "Illegal seek"}, {"EROFS", EROFS, "Read-only file system"}, {"EMLINK", EMLINK, "Too many links"}, {"EPIPE", EPIPE, "Broken pipe"}, {"EDOM", EDOM, "Math argument out of domain of func"}, {"ERANGE", ERANGE, "Math result not representable"}, {"EDEADLK", EDEADLK, "Resource deadlock would occur"}, {"ENAMETOOLONG", ENAMETOOLONG, "File name too long"}, {"ENOLCK", ENOLCK, "No record locks available"}, {"ENOSYS", ENOSYS, "Function not implemented"}, {"ENOTEMPTY", ENOTEMPTY, "Directory not empty"}, {"ELOOP", ELOOP, "Too many symbolic links encountered"}, {"EWOULDBLOCK", EWOULDBLOCK, "Operation would block"}, {"ENOMSG", ENOMSG, "No message of desired type"}, {"EIDRM", EIDRM, "Identifier removed"}, {"EREMOTE", EREMOTE, "Object is remote"}, {"ENOLINK", ENOLINK, "Link has been severed"}, {"ENOSTR", ENOSTR, "Device not a stream"}, {"ENODATA", ENODATA, "No data available"}, {"ETIME", ETIME, "Timer expired"}, {"ENOSR", ENOSR, "Out of streams resources"}, {"EPROTO", EPROTO, "Protocol error"}, {"EMULTIHOP", EMULTIHOP, "Multihop attempted"}, {"EBADMSG", EBADMSG, "Not a data message"}, {"EOVERFLOW", EOVERFLOW, "Value too large for defined data type"}, {"EILSEQ", EILSEQ, "Illegal byte sequence"}, {"EUSERS", EUSERS, "Too many users"}, {"ENOTSOCK", ENOTSOCK, "Socket operation on non-socket"}, {"EDESTADDRREQ", EDESTADDRREQ, "Destination address required"}, {"EMSGSIZE", EMSGSIZE, "Message too long"}, {"EPROTOTYPE", EPROTOTYPE, "Protocol wrong type for socket"}, {"ENOPROTOOPT", ENOPROTOOPT, "Protocol not available"}, {"EPROTONOSUPPORT", EPROTONOSUPPORT, "Protocol not supported"}, {"ESOCKTNOSUPPORT", ESOCKTNOSUPPORT, "Socket type not supported"}, {"EOPNOTSUPP", EOPNOTSUPP, "Operation not supported on transport endpoint"}, {"EPFNOSUPPORT", EPFNOSUPPORT, "Protocol family not supported"}, {"EAFNOSUPPORT", EAFNOSUPPORT, "Address family not supported by protocol"}, {"EADDRINUSE", EADDRINUSE, "Address already in use"}, {"EADDRNOTAVAIL", EADDRNOTAVAIL, "Cannot assign requested address"}, {"ENETDOWN", ENETDOWN, "Network is down"}, {"ENETUNREACH", ENETUNREACH, "Network is unreachable"}, {"ENETRESET", ENETRESET, "Network dropped connection because of reset"}, {"ECONNABORTED", ECONNABORTED, "Software caused connection abort"}, {"ECONNRESET", ECONNRESET, "Connection reset by peer"}, {"ENOBUFS", ENOBUFS, "No buffer space available"}, {"EISCONN", EISCONN, "Transport endpoint is already connected"}, {"ENOTCONN", ENOTCONN, "Transport endpoint is not connected"}, {"ESHUTDOWN", ESHUTDOWN, "Cannot send after transport endpoint shutdown"}, {"ETOOMANYREFS", ETOOMANYREFS, "Too many references: cannot splice"}, {"ETIMEDOUT", ETIMEDOUT, "Connection timed out"}, {"ECONNREFUSED", ECONNREFUSED, "Connection refused"}, {"EHOSTDOWN", EHOSTDOWN, "Host is down"}, {"EHOSTUNREACH", EHOSTUNREACH, "No route to host"}, {"EALREADY", EALREADY, "Operation already in progress"}, {"EINPROGRESS", EINPROGRESS, "Operation now in progress"}, {"ESTALE", ESTALE, "Stale NFS file handle"}, #ifndef __GTK_H__ {"EDQUOT", EDQUOT, "Quota exceeded"}, {"ENOMEDIUM", ENOMEDIUM, "No medium found"}, {"EMEDIUMTYPE", EMEDIUMTYPE, "Wrong medium type"}, {"EUCLEAN", EUCLEAN, "Structure needs cleaning"}, {"ENOTNAM", ENOTNAM, "Not a XENIX named type file"}, {"ENAVAIL", ENAVAIL, "No XENIX semaphores available"}, {"EISNAM", EISNAM, "Is a named type file"}, {"EREMOTEIO", EREMOTEIO, "Remote I/O error"}, {"ERESTART", ERESTART, "Interrupted system call should be restarted"}, {"ESTRPIPE", ESTRPIPE, "Streams pipe error"}, {"ECOMM", ECOMM, "Communication error on send"}, {"EDOTDOT", EDOTDOT, "RFS specific error"}, {"ENOTUNIQ", ENOTUNIQ, "Name not unique on network"}, {"EBADFD", EBADFD, "File descriptor in bad state"}, {"EREMCHG", EREMCHG, "Remote address changed"}, {"ELIBACC", ELIBACC, "Can not access a needed shared library"}, {"ELIBBAD", ELIBBAD, "Accessing a corrupted shared library"}, {"ELIBSCN", ELIBSCN, ".lib section in a.out corrupted"}, {"ELIBMAX", ELIBMAX, "Attempting to link in too many shared libraries"}, {"ELIBEXEC", ELIBEXEC, "Cannot exec a shared library directly"}, {"ECHRNG", ECHRNG, "Channel number out of range"}, {"EL2NSYNC", EL2NSYNC, "Level 2 not synchronized"}, {"EL3HLT", EL3HLT, "Level 3 halted"}, {"EL3RST", EL3RST, "Level 3 reset"}, {"ELNRNG", ELNRNG, "Link number out of range"}, {"EUNATCH", EUNATCH, "Protocol driver not attached"}, {"ENOCSI", ENOCSI, "No CSI structure available"}, {"EL2HLT", EL2HLT, "Level 2 halted"}, {"EBADE", EBADE, "Invalid exchange"}, {"EBADR", EBADR, "Invalid request descriptor"}, {"EXFULL", EXFULL, "Exchange full"}, {"ENOANO", ENOANO, "No anode"}, {"EBADRQC", EBADRQC, "Invalid request code"}, {"EBADSLT", EBADSLT, "Invalid slot"}, {"EBFONT", EBFONT, "Bad font file format"}, {"EADV", EADV, "Advertise error"}, {"ESRMNT", ESRMNT, "Srmount error"}, {"ENONET", ENONET, "Machine is not on the network"}, {"ENOPKG", ENOPKG, "Package not installed"}, #endif #endif {"NONE", 0, "No error"}, }; const char *GetErrorName(int e) { for (ErrorCodeType *c=ErrorCodes; c->Code; c++) { if (e == c->Code) { return c->Name; } } static char s[32]; sprintf(s, "Unknown(%i)", e); return s; } const char *GetErrorDesc(int e) { for (ErrorCodeType *c=ErrorCodes; c->Code; c++) { if (e == c->Code) return c->Desc; } return 0; } /****************************** Helper Functions **************************/ int64 LFileSize(const char *FileName) { struct stat64 s; if (FileName && stat64(FileName, &s) == 0) { return s.st_size; } return 0; } bool LDirExists(const char *FileName, char *CorrectCase) { bool Status = false; if (FileName) { struct stat s; // Check for exact match... int r = lstat(FileName, &s); if (r == 0) { Status = S_ISDIR(s.st_mode) || S_ISLNK(s.st_mode); // printf("DirStatus(%s) lstat = %i, %i\n", FileName, Status, s.st_mode); } else { r = stat(FileName, &s); if (r == 0) { Status = S_ISDIR(s.st_mode) || S_ISLNK(s.st_mode); // printf("DirStatus(%s) stat ok = %i, %i\n", FileName, Status, s.st_mode); } else { // printf("DirStatus(%s) lstat and stat failed, r=%i, errno=%i\n", FileName, r, errno); } } } return Status; } bool LFileExists(const char *FileName, char *CorrectCase) { bool Status = false; if (FileName) { struct stat s; // Check for exact match... if (stat(FileName, &s) == 0) { Status = !S_ISDIR(s.st_mode); } else if (CorrectCase) { // Look for altenate case by enumerating the directory char d[256]; strcpy(d, FileName); char *e = strrchr(d, DIR_CHAR); if (e) { *e++ = 0; DIR *Dir = opendir(d); if (Dir) { dirent *De; while ((De = readdir(Dir))) { if (De->d_type != DT_DIR && stricmp(De->d_name, e) == 0) { try { // Tell the calling program the actual case of the file... e = (char*) strrchr(FileName, DIR_CHAR); // If this crashes because the argument is read only then we get caught by the try catch strcpy(e+1, De->d_name); // It worked! Status = true; } catch (...) { // It didn't work :( #ifdef _DEBUG printf("%s,%i - LFileExists(%s) found an alternate case version but couldn't return it to the caller.\n", __FILE__, __LINE__, FileName); #endif } break; } } closedir(Dir); } } } } return Status; } bool LResolveShortcut(const char *LinkFile, char *Path, ssize_t Len) { if (!LinkFile || !Path || Len <= 0) return false; ssize_t r = readlink(LinkFile, Path, Len); return r > 0; } void WriteStr(LFile &f, const char *s) { uint32_t Len = (s) ? strlen(s) : 0; f << Len; if (Len > 0) { f.Write(s, Len); } } char *ReadStr(LFile &f DeclDebugArgs) { char *s = 0; // read the strings length... uint32_t Len; f >> Len; if (Len > 0) { // 16mb sanity check.... anything over this // is _probably_ an error if (Len >= (16 << 20)) { // LAssert(0); return 0; } // allocate the memory buffer #if defined(_DEBUG) && defined MEMORY_DEBUG s = new(_file, _line) char[Len+1]; #else s = new char[Len+1]; #endif if (s) { // read the bytes from disk f.Read(s, Len); s[Len] = 0; } else { // memory allocation error, skip the data // on disk so the caller is where they think // they are in the file. f.Seek(Len, SEEK_CUR); } } return s; } ssize_t SizeofStr(const char *s) { return sizeof(ulong) + ((s) ? strlen(s) : 0); } bool LGetDriveInfo ( char *Path, uint64 *Free, uint64 *Size, uint64 *Available ) { bool Status = false; if (Path) { struct stat s; if (lstat(Path, &s) == 0) { // printf("LGetDriveInfo dev=%i\n", s.st_dev); } } return Status; } ///////////////////////////////////////////////////////////////////////// #include #include #include struct LVolumePriv { LVolume *Owner = NULL; int64 Size = 0, Free = 0; LVolumeTypes Type = VT_NONE; int Flags = 0; LSystemPath SysPath = LSP_ROOT; LString Name, Path; LVolume *NextVol = NULL, *ChildVol = NULL; LVolumePriv(LVolume *owner, const char *path) : Owner(owner) { Path = path; Name = LGetLeaf(path); Type = VT_FOLDER; } LVolumePriv(LVolume *owner, LSystemPath sys, const char *name) : Owner(owner) { SysPath = sys; Name = name; if (SysPath == LSP_ROOT) Path = "/"; else Path = LGetSystemPath(SysPath); if (Path) Type = sys == LSP_DESKTOP ? VT_DESKTOP : VT_FOLDER; if (sys == LSP_ROOT) { struct statvfs s = {0}; int r = statvfs(Path, &s); if (r) LgiTrace("%s:%i - statvfs failed with %i\n", _FL, r); else { Size = (uint64_t) s.f_blocks * s.f_frsize; Free = (uint64_t) s.f_bfree * s.f_frsize; } } } ~LVolumePriv() { DeleteObj(NextVol); DeleteObj(ChildVol); } void Insert(LVolume *vol, LVolume *newVol) { if (!vol || !newVol) return; if (vol->d->ChildVol) { for (auto v = vol->d->ChildVol; v; v = v->d->NextVol) { if (!v->d->NextVol) { LAssert(newVol != v->d->Owner); v->d->NextVol = newVol; // printf("Insert %p:%s into %p:%s\n", newVol, newVol->Name(), vol, vol->Name()); break; } } } else { LAssert(newVol != vol->d->Owner); vol->d->ChildVol = newVol; // printf("Insert %p:%s into %p:%s\n", newVol, newVol->Name(), vol, vol->Name()); } } LVolume *First() { if (SysPath == LSP_DESKTOP && !ChildVol) { // Get various shortcuts to points of interest Insert(Owner, new LVolume(LSP_ROOT, "Root")); struct passwd *pw = getpwuid(getuid()); if (pw) Insert(Owner, new LVolume(LSP_HOME, "Home")); LSystemPath p[] = { LSP_USER_DOCUMENTS, LSP_USER_MUSIC, LSP_USER_VIDEO, LSP_USER_DOWNLOADS, LSP_USER_PICTURES }; for (int i=0; id->Path = Path; v->d->Name = *Parts.rbegin(); v->d->Type = VT_FOLDER; Insert(Owner, v); } } } return ChildVol; } LVolume *Next() { if (SysPath == LSP_DESKTOP && !NextVol) { NextVol = new LVolume(LSP_MOUNT_POINT, "Mounts"); // Get mount list // this is just a hack at this stage to establish some base // functionality. I would appreciate someone telling me how // to do this properly. Till then... LFile f; if (f.Open("/etc/fstab", O_READ)) { auto Buf= f.Read(); f.Close(); auto Lines = Buf.SplitDelimit("\r\n"); for (auto ln: Lines) { auto M = ln.Strip().SplitDelimit(" \t"); if (M[0](0) != '#' && M.Length() > 2) { auto &Device = M[0]; auto &Mount = M[1]; auto &FileSys = M[2]; if ( (Device.Find("/dev/") == 0 || Mount.Find("/mnt/") == 0) && Device.Lower().Find("/by-uuid/") < 0 && Mount.Length() > 1 && !FileSys.Equals("swap") ) { auto v = new LVolume(0); if (v) { char *MountName = strrchr(Mount, '/'); v->d->Name = (MountName ? MountName + 1 : Mount.Get()); v->d->Path = Mount; v->d->Type = VT_HARDDISK; struct statvfs s = {0}; int r = statvfs(Mount, &s); if (r) { LgiTrace("%s:%i - statvfs(%s) failed.\n", _FL, Mount); } else { v->d->Size = (uint64_t) s.f_blocks * s.f_frsize; v->d->Free = (uint64_t) s.f_bfree * s.f_frsize; } char *Device = M[0]; if (stristr(Device, "fd")) v->d->Type = VT_FLOPPY; else if (stristr(Device, "cdrom")) v->d->Type = VT_CDROM; Insert(NextVol, v); } } } } } } return NextVol; } }; LVolume::LVolume(const char *Path) { d = new LVolumePriv(this, Path); } LVolume::LVolume(LSystemPath SysPath, const char *Name) { d = new LVolumePriv(this, SysPath, Name); } LVolume::~LVolume() { DeleteObj(d); } const char *LVolume::Name() const { return d->Name; } const char *LVolume::Path() const { return d->Path; } LVolumeTypes LVolume::Type() const { return d->Type; } int LVolume::Flags() const { return d->Flags; } uint64 LVolume::Size() const { return d->Size; } uint64 LVolume::Free() const { return d->Free; } LSurface *LVolume::Icon() const { return NULL; } bool LVolume::IsMounted() const { return true; } bool LVolume::SetMounted(bool Mount) { return Mount; } LVolume *LVolume::First() { return d->First(); } LVolume *LVolume::Next() { return d->Next(); } void LVolume::Insert(LAutoPtr v) { d->Insert(this, v.Release()); } LDirectory *LVolume::GetContents() { LDirectory *Dir = 0; if (d->Path) { Dir = new LDirectory; if (Dir && !Dir->First(d->Path)) DeleteObj(Dir); } return Dir; } /////////////////////////////////////////////////////////////////////////////// LFileSystem::LFileSystem() { Instance = this; Root = 0; } LFileSystem::~LFileSystem() { DeleteObj(Root); } bool LFileSystem::Copy(const char *From, const char *To, LError *Status, std::function callback) { LArray Buf; if (Status) *Status = 0; if (Buf.Length(2 << 20)) { LFile In, Out; if (!In.Open(From, O_READ)) { if (Status) *Status = In.GetError(); return false; } if (!Out.Open(To, O_WRITE)) { if (Status) *Status = Out.GetError(); return false; } int64 Size = In.GetSize(), Done = 0; for (int64 i=0; i 0) { int w = Out.Write(&Buf[0], r); if (w <= 0) break; r -= w; Done += w; if (callback) callback(Done, Size); } if (r > 0) break; } return Done == Size; } return false; } bool LFileSystem::Delete(LArray &Files, LArray *Status, bool ToTrash) { bool Error = false; if (ToTrash) { char p[MAX_PATH_LEN]; if (LGetSystemPath(LSP_TRASH, p, sizeof(p))) { for (int i=0; iFirst(PathName)) { do { char Str[256]; Dir->Path(Str, sizeof(Str)); if (Dir->IsDir()) { RemoveFolder(Str, Recurse); } else { LError err; Delete(Str, &err, false); } } while (Dir->Next()); } DeleteObj(Dir); } return rmdir(PathName) == 0; } bool LFileSystem::Move(const char *OldName, const char *NewName, LError *Err) { if (rename(OldName, NewName)) { printf("%s:%i - rename(%s,%s) error: %s(%i)\n", _FL, OldName, NewName, GetErrorName(errno), errno); return false; } return true; } short DaysInMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int LeapYear(int year) { if (year & 3) return 0; if ((year % 100 == 0) && !(year % 400 == 0)) return 0; return 1; } ///////////////////////////////////////////////////////////////////////////////// struct LDirectoryPriv { char path[MAX_PATH_LEN] = {}; char *end = NULL; DIR *dir = NULL; struct dirent *entry = NULL; struct stat stat; LString pattern; bool Ignore() { return entry && ( strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0 || ( pattern && !MatchStr(pattern, entry->d_name) ) ); } }; LDirectory::LDirectory() { d = new LDirectoryPriv; } LDirectory::~LDirectory() { Close(); DeleteObj(d); } LDirectory *LDirectory::Clone() { return new LDirectory; } int LDirectory::First(const char *Name, const char *Pattern) { Close(); if (!Name) return 0; strcpy_s(d->path, sizeof(d->path), Name); if (!Pattern || stricmp(Pattern, LGI_ALL_FILES) == 0) { struct stat S; if (lstat(Name, &S) == 0) { if (S_ISREG(S.st_mode)) // If it's a file... { auto Dir = strrchr(d->path, DIR_CHAR); if (Dir) { *Dir++ = 0; // Go up one level and make the file name d->pattern = Dir; // The search pattern. } } } } else { d->pattern = Pattern; } d->end = d->path + strlen(d->path); d->dir = opendir(d->path); if (d->dir) { d->entry = readdir(d->dir); if (d->entry) { char s[MaxPathLen]; LMakePath(s, sizeof(s), d->path, GetName()); lstat(s, &d->stat); if (d->Ignore() && !Next()) return false; } } return d->dir != NULL && d->entry != NULL; } int LDirectory::Next() { int Status = false; while (d->dir && d->entry) { if ((d->entry = readdir(d->dir))) { char s[MaxPathLen]; LMakePath(s, sizeof(s), d->path, GetName()); lstat(s, &d->stat); if (!d->Ignore()) { Status = true; break; } } } return Status; } int LDirectory::Close() { if (d->dir) { closedir(d->dir); d->dir = NULL; } d->entry = NULL; return true; } const char *LDirectory::FullPath() { if (!d->entry || !d->end) { LAssert(!"missing param."); return NULL; } auto e = d->end; if (e[-1] != DIR_CHAR) *e++ = DIR_CHAR; auto remainingBuf = sizeof(d->path) - (e - d->path) - 1; strcpy_s(e, remainingBuf, d->entry->d_name); return d->path; } LString LDirectory::FileName() const { return GetName(); } bool LDirectory::Path(char *s, int BufLen) const { if (!s || BufLen <= 4) return false; // We could just do LMakePath, but then it'll expand '~' names. Which // would break things. // return LMakePath(s, BufLen, d->BasePath, GetName()); auto end = s + BufLen; strcpy_s(s, BufLen, d->path); auto c = s + strlen(s); if (c > s && c[-1] != DIR_CHAR) *c++ = DIR_CHAR; strcpy_s(c, end - c, GetName()); return true; } LVolumeTypes LDirectory::GetType() const { return IsDir() ? VT_FOLDER : VT_FILE; } int LDirectory::GetUser(bool Group) const { if (Group) { return d->stat.st_gid; } else { return d->stat.st_uid; } } bool LDirectory::IsReadOnly() const { if (getuid() == d->stat.st_uid) { // Check user perms return !TestFlag(GetAttributes(), S_IWUSR); } else if (getgid() == d->stat.st_gid) { // Check group perms return !TestFlag(GetAttributes(), S_IWGRP); } // Check global perms return !TestFlag(GetAttributes(), S_IWOTH); } bool LDirectory::IsHidden() const { return GetName() && GetName()[0] == '.'; } bool LDirectory::IsDir() const { int a = GetAttributes(); return !S_ISLNK(a) && S_ISDIR(a); } bool LDirectory::IsSymLink() const { int a = GetAttributes(); return S_ISLNK(a); } long LDirectory::GetAttributes() const { return d->stat.st_mode; } const char *LDirectory::GetName() const { return d->entry ? d->entry->d_name : NULL; } #define UNIX_TO_LGI(unixTs) \ (((uint64) unixTs + LDateTime::Offset1800) * LDateTime::Second64Bit) #define LGI_TO_UNIX(lgiTs) \ (((uint64) lgiTs / LDateTime::Second64Bit) - LDateTime::Offset1800) uint64 LDirectory::GetCreationTime() const { return UNIX_TO_LGI(d->stat.st_ctime); } uint64 LDirectory::GetLastAccessTime() const { return UNIX_TO_LGI(d->stat.st_atime); } uint64 LDirectory::GetLastWriteTime() const { return UNIX_TO_LGI(d->stat.st_mtime); } uint64 LDirectory::GetSize() const { return d->stat.st_size; } int64 LDirectory::GetSizeOnDisk() { return d->stat.st_size; } int64_t LDirectory::TsToUnix(uint64_t timeStamp) { return LGI_TO_UNIX(timeStamp); } LDateTime LDirectory::TsToDateTime(uint64_t timeStamp, bool convertToLocalTz) { LDateTime dt; dt.SetTimeZone(0, false); // UTC dt.Set(timeStamp); - LArray dst; + LArray dst; if (convertToLocalTz && - LDateTime::GetDaylightSavingsInfo(dst, dt)) + LTimeZone::GetDaylightSavingsInfo(dst, dt)) { // Convert to local using the timezone in effect at 'dt' - LDateTime::DstToLocal(dst, dt); + LTimeZone::DstToLocal(dst, dt); } else { // Without knowing the timezone at 'dt' just leave it as UTC... // The caller will have to figure it out. } return dt; } ///////////////////////////////////////////////////////////////////////////////// //////////////////////////// File /////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////// class LFilePrivate { public: int hFile; char *Name; bool Swap; int Status; int Attributes; int ErrorCode; LFilePrivate() { hFile = INVALID_HANDLE; Name = 0; Swap = false; Status = true; Attributes = 0; ErrorCode = 0; } ~LFilePrivate() { DeleteArray(Name); } }; LFile::LFile(const char *Path, int Mode) { d = new LFilePrivate; if (Path) Open(Path, Mode); } LFile::~LFile() { if (d && ValidHandle(d->hFile)) { Close(); } DeleteObj(d); } OsFile LFile::Handle() { return d->hFile; } int LFile::GetError() { return d->ErrorCode; } bool LFile::IsOpen() { return d && ValidHandle(d->hFile); } #define DEBUG_OPEN_FILES 0 #if DEBUG_OPEN_FILES LMutex Lck; LArray OpenFiles; #endif int LFile::Open(const char *File, int Mode) { int Status = false; if (File) { if (TestFlag(Mode, O_WRITE) || TestFlag(Mode, O_READWRITE)) { Mode |= O_CREAT; } Close(); d->hFile = open(File, Mode #ifdef O_LARGEFILE | O_LARGEFILE #endif , S_IRUSR | S_IWUSR); if (ValidHandle(d->hFile)) { d->Attributes = Mode; d->Name = new char[strlen(File)+1]; if (d->Name) { strcpy(d->Name, File); } Status = true; d->Status = true; #if DEBUG_OPEN_FILES if (Lck.Lock(_FL)) { if (!OpenFiles.HasItem(this)) OpenFiles.Add(this); Lck.Unlock(); } #endif } else { d->ErrorCode = errno; #if DEBUG_OPEN_FILES if (Lck.Lock(_FL)) { for (unsigned i=0; iGetName()); Lck.Unlock(); } #endif if (onErrorCb) { LError err(d->ErrorCode); onErrorCb(err); } else { printf("LFile::Open failed\n\topen(%s,%8.8x) = %i\n\terrno=%s (%s)\n", File, Mode, d->hFile, GetErrorName(d->ErrorCode), GetErrorDesc(d->ErrorCode)); } } } return Status; } int LFile::Close() { if (ValidHandle(d->hFile)) { close(d->hFile); d->hFile = INVALID_HANDLE; DeleteArray(d->Name); #if DEBUG_OPEN_FILES if (Lck.Lock(_FL)) { OpenFiles.Delete(this); Lck.Unlock(); } #endif } return true; } uint64_t LFile::GetModifiedTime() { struct stat s; stat(d->Name, &s); return s.st_mtime; } bool LFile::SetModifiedTime(uint64_t dt) { struct stat s; stat(d->Name, &s); struct timeval times[2] = {}; times[0].tv_sec = s.st_atime; times[1].tv_sec = dt; int r = utimes(d->Name, times); return r == 0; } void LFile::ChangeThread() { } #define CHUNK 0xFFF0 ssize_t LFile::Read(void *Buffer, ssize_t Size, int Flags) { int Red = 0; if (Buffer && Size > 0) { Red = read(d->hFile, Buffer, Size); } d->Status = Red == Size; return MAX(Red, 0); } ssize_t LFile::Write(const void *Buffer, ssize_t Size, int Flags) { int Written = 0; if (Buffer && Size > 0) { Written = write(d->hFile, Buffer, Size); } d->Status = Written == Size; return MAX(Written, 0); } #ifdef LINUX #define LINUX64 1 #endif int64 LFile::Seek(int64 To, int Whence) { #if LINUX64 return lseek64(d->hFile, To, Whence); // If this doesn't compile, switch off LINUX64 #else return lseek(d->hFile, To, Whence); #endif } int64 LFile::SetPos(int64 Pos) { #if LINUX64 int64 p = lseek64(d->hFile, Pos, SEEK_SET); if (p < 0) { int e = errno; printf("%s:%i - lseek64(" LPrintfHex64 ") failed (error %i: %s).\n", __FILE__, __LINE__, Pos, e, GetErrorName(e)); } return p; #else return lseek(d->hFile, Pos, SEEK_SET); #endif } int64 LFile::GetPos() { #if LINUX64 int64 p = lseek64(d->hFile, 0, SEEK_CUR); if (p < 0) { int e = errno; printf("%s:%i - lseek64 failed (error %i: %s).\n", __FILE__, __LINE__, e, GetErrorName(e)); } return p; #else return lseek(d->hFile, 0, SEEK_CUR); #endif } int64 LFile::GetSize() { int64 Here = GetPos(); #if LINUX64 int64 Ret = lseek64(d->hFile, 0, SEEK_END); #else int64 Ret = lseek(d->hFile, 0, SEEK_END); #endif SetPos(Here); return Ret; } int64 LFile::SetSize(int64 Size) { if (ValidHandle(d->hFile)) { int64 Pos = GetPos(); if ( #if LINUX64 ftruncate64(d->hFile, Size) #else ftruncate(d->hFile, Size) #endif ) LgiTrace("%s:%i - ftruncate64 failed: %i\n", _FL, d->ErrorCode = errno); else if (d->hFile) SetPos(Pos); } return GetSize(); } bool LFile::Eof() { return GetPos() >= GetSize(); } ssize_t LFile::SwapRead(uchar *Buf, ssize_t Size) { ssize_t i = 0; ssize_t r = 0; Buf = &Buf[Size-1]; while (Size--) { r = read(d->hFile, Buf--, 1); i += r; } return i; } ssize_t LFile::SwapWrite(uchar *Buf, ssize_t Size) { ssize_t i = 0; ssize_t w = 0; Buf = &Buf[Size-1]; while (Size--) { w = write(d->hFile, Buf--, 1); i += w; } return i; } ssize_t LFile::ReadStr(char *Buf, ssize_t Size) { ssize_t i = 0; ssize_t r = 0; if (Buf && Size > 0) { char c; Size--; do { r = read(d->hFile, &c, 1); if (Eof()) { break; } *Buf++ = c; i++; } while (i < Size - 1 && c != '\n'); *Buf = 0; } return i; } ssize_t LFile::WriteStr(char *Buf, ssize_t Size) { ssize_t i = 0; ssize_t w; while (i <= Size) { w = write(d->hFile, Buf, 1); Buf++; i++; if (*Buf == '\n') break; } return i; } void LFile::SetStatus(bool s) { d->Status = s; } bool LFile::GetStatus() { return d->Status; } void LFile::SetSwap(bool s) { d->Swap = s; } bool LFile::GetSwap() { return d->Swap; } int LFile::GetOpenMode() { return d->Attributes; } const char *LFile::GetName() { return d->Name; } #define GFileOp(type) LFile &LFile::operator >> (type &i) { d->Status |= ((d->Swap) ? SwapRead((uchar*) &i, sizeof(i)) : Read(&i, sizeof(i))) != sizeof(i); return *this; } GFileOps(); #undef GFileOp #define GFileOp(type) LFile &LFile::operator << (type i) { d->Status |= ((d->Swap) ? SwapWrite((uchar*) &i, sizeof(i)) : Write(&i, sizeof(i))) != sizeof(i); return *this; } GFileOps(); #undef GFileOp ////////////////////////////////////////////////////////////////////////////// bool LFile::Path::FixCase() { LString Prev; bool Changed = false; // printf("FixCase '%s'\n", GetFull().Get()); for (size_t i=0; i %s\n", part.Get(), name); Part = Name; Next = (Prev ? Prev : "") + Sep + Part; Changed = true; } } } Prev = Next; } return Changed; }