Merge branch 'develop'
This commit is contained in:
commit
aaf6fe8944
24
.clang-format
Normal file
24
.clang-format
Normal file
@ -0,0 +1,24 @@
|
||||
UseTab: true
|
||||
IndentWidth: 4
|
||||
TabWidth: 4
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
AccessModifierOffset: -4
|
||||
IndentCaseLabels: false
|
||||
IndentFunctionDeclarationAfterType: false
|
||||
NamespaceIndentation: None
|
||||
|
||||
BreakBeforeBraces: Allman
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
ColumnLimit: 96
|
||||
MaxEmptyLinesToKeep: 1
|
||||
|
||||
Standard: Cpp11
|
||||
Cpp11BracedListStyle: true
|
||||
|
||||
SpacesInParentheses: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpaceAfterControlStatementKeyword: true
|
||||
|
||||
AlignTrailingComments: true
|
||||
SpacesBeforeTrailingComments: 1
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,6 +4,7 @@ MultiMC5.kdev4
|
||||
MultiMC.pro.user
|
||||
CMakeLists.txt.user
|
||||
.user
|
||||
.directory
|
||||
build
|
||||
resources/CMakeFiles
|
||||
resources/MultiMCLauncher.jar
|
||||
|
115
BUILD.md
Normal file
115
BUILD.md
Normal file
@ -0,0 +1,115 @@
|
||||
Build Instructions
|
||||
==================
|
||||
|
||||
# Contents
|
||||
* [Linux](#linux)
|
||||
* [Windows](#windows)
|
||||
* [OS X](#os-x)
|
||||
|
||||
# Linux
|
||||
|
||||
## Dependencies
|
||||
|
||||
* Qt 5.1.1+ Development tools (http://qt-project.org/downloads)
|
||||
* cmake
|
||||
* ccmake
|
||||
* make
|
||||
* g++
|
||||
* A copy of the MultiMC source (clone it with git)
|
||||
|
||||
## Getting set up
|
||||
|
||||
```bash
|
||||
git clone git@github.com:MultiMC/MultiMC5.git # get the code
|
||||
cd MultiMC5
|
||||
git checkout develop
|
||||
```
|
||||
|
||||
once that is done, do these commands:
|
||||
|
||||
```bash
|
||||
mkdir build
|
||||
cd build
|
||||
ccmake ..
|
||||
```
|
||||
|
||||
A GUI will pop up. press the c key. now set the build prefix. if you are in /home/username/code/MultiMC5/build then put /home/username/code/MultiMC5/build/run as build prefix. if you want you can choose whatever dir you want, but then you need to adjust the path when running it. to edit the value use the up/down keys to select it and hit return to edit it. after you are done hit return again.
|
||||
Also adjust the paths to your qt install.
|
||||
|
||||
Then hit c and g. If the window stays open (and g has no effect) retry c followed by g. sometimes you need to use c twice.
|
||||
If you get an error make sure you have all dependencies installed and configured the paths properly
|
||||
|
||||
continue with the following commands:
|
||||
|
||||
```bash
|
||||
cmake ..
|
||||
make
|
||||
make translations_target # compiles localization files. you may leave this out if your language is english
|
||||
make install
|
||||
```
|
||||
now you compiled it (hupefully) successfully.
|
||||
|
||||
to launch it:
|
||||
|
||||
```bash
|
||||
cd run # or whereever its stored
|
||||
./MultiMC5
|
||||
```
|
||||
|
||||
Congrats. Your MMC5 should run
|
||||
|
||||
# Windows
|
||||
|
||||
Getting the project to build and run on Windows is easy if you use Qt's IDE, Qt Creator. The project will simply not compile using VC's build tools as it uses some C++11 features that aren't implemented in it at the time of writing.
|
||||
|
||||
## Dependencies
|
||||
* Qt 5.1.1+ Development tools (http://qt-project.org/downloads) ("Qt Online Installer for Windows")
|
||||
* OpenSSL (http://slproweb.com/products/Win32OpenSSL.html) ("Win32 OpenSSL v1.0.1e Light")
|
||||
- Microsoft Visual C++ 2008 Redist. is required for this, there's a link on the OpenSSL download page above next to the main download.
|
||||
* CMake (http://www.cmake.org/cmake/resources/software.html) ("Windows (Win32 Installer)")
|
||||
* A copy of the MultiMC source (clone it with git)
|
||||
|
||||
## Getting set up
|
||||
|
||||
### Installing Qt
|
||||
1. Run the Qt installer
|
||||
2. Choose a place to install Qt (C:\Qt is the default),
|
||||
3. Choose the components you want to install
|
||||
- You need Qt 5.1.1/MinGW 4.8 (32 bit) ticked,
|
||||
- You need Tools/Qt Creator ticked,
|
||||
- Other components are selected by default, you can untick them if you don't need them.
|
||||
4. Accept the license agreements,
|
||||
5. Double check the install details and then click "Install"
|
||||
- Installation can take a very long time, go grab a cup of tea or something and let it work.
|
||||
|
||||
### Installing OpenSSL
|
||||
1. Run the OpenSSL installer,
|
||||
2. It's best to choose the option to copy OpenSSL DLLs to the /bin directory
|
||||
- If you do this you'll need to add that directory (the default being C:\OpenSSL-Win32\bin) to your PATH system variable (Google how to do this, or use this guide for Java: http://www.java.com/en/download/help/path.xml).
|
||||
|
||||
### Installing CMake
|
||||
1. Run the CMake installer,
|
||||
2. It's easiest if you choose to add CMake to the PATH for all users,
|
||||
- If you don't choose to do this, remember where you installed CMake.
|
||||
|
||||
### Loading the project
|
||||
1. Open Qt Creator,
|
||||
2. Choose File->Open File or Project,
|
||||
3. Navigate to the MultiMC5 source folder you cloned and choose CMakeLists.txt,
|
||||
4. Read the instructions that just popped up about a build location and choose one,
|
||||
5. If you chose not to add CMake to the system PATH, tell Qt Creator where you installed it,
|
||||
- Otherwise you can skip this step.
|
||||
6. You should see "Run CMake" in the window,
|
||||
- Make sure that Generator is set to "MinGW Generator (Desktop Qt 5.1.1 MinGW 32bit)",
|
||||
- Hit the "Run CMake" button,
|
||||
- You'll see warnings and it might not be clear that it succeeded until you scroll to the bottom of the window.
|
||||
- Hit "Finish" if CMake ran successfully.
|
||||
7. Cross your fingers and press the Run button (bottom left of Qt Creator)!
|
||||
- If the project builds successfully it will run and the MultiMC5 window will pop up,
|
||||
- Test OpenSSL by making an instance and trying to log in. If Qt Creator couldn't find OpenSSL during the CMake stage, login will fail and you'll get an error.
|
||||
|
||||
*These build instructions worked for me (Drayshak) on a fresh Windows 8 x64 Professional install. If they don't work for you, let us know on IRC (Esper/#MultiMC)!*
|
||||
|
||||
# OS X
|
||||
|
||||
*There are no build instructions for OS X yet. If you can help with this section please contact us on IRC (Esper/#MultiMC)!*
|
300
CMakeLists.txt
300
CMakeLists.txt
@ -1,9 +1,16 @@
|
||||
cmake_minimum_required(VERSION 2.8.9)
|
||||
|
||||
IF(WIN32)
|
||||
# In Qt 5.1+ we have our own main() function, don't autolink to qtmain on Windows
|
||||
cmake_policy(SET CMP0020 OLD)
|
||||
ENDIF()
|
||||
|
||||
project(MultiMC)
|
||||
|
||||
######## Set CMake options ########
|
||||
SET(CMAKE_AUTOMOC ON)
|
||||
SET(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
SET(FILES_TO_TRANSLATE )
|
||||
|
||||
# Output all executables and shared libs in the main build folder, not in subfolders.
|
||||
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
|
||||
@ -32,6 +39,7 @@ ENDIF()
|
||||
# Find the required Qt parts
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
find_package(Qt5Network REQUIRED)
|
||||
find_package(Qt5LinguistTools REQUIRED)
|
||||
|
||||
include_directories(${Qt5Widgets_INCLUDE_DIRS})
|
||||
|
||||
@ -44,6 +52,14 @@ include_directories(depends/quazip)
|
||||
# Add the java launcher
|
||||
add_subdirectory(depends/launcher)
|
||||
|
||||
# Add xz decompression
|
||||
add_subdirectory(depends/xz-embedded)
|
||||
include_directories(${XZ_INCLUDE_DIR})
|
||||
|
||||
# Add pack200 decompression
|
||||
add_subdirectory(depends/pack200)
|
||||
include_directories(${PACK200_INCLUDE_DIR})
|
||||
|
||||
######## MultiMC Libs ########
|
||||
|
||||
# Add the util library.
|
||||
@ -58,7 +74,6 @@ include_directories(${LIBSETTINGS_INCLUDE_DIR})
|
||||
add_subdirectory(depends/groupview)
|
||||
include_directories(${LIBGROUPVIEW_INCLUDE_DIR})
|
||||
|
||||
|
||||
################################ SET UP BUILD OPTIONS ################################
|
||||
|
||||
######## Check endianness ########
|
||||
@ -78,10 +93,13 @@ SET(MultiMC_VERSION_MAJOR 5)
|
||||
SET(MultiMC_VERSION_MINOR 0)
|
||||
SET(MultiMC_VERSION_REV 0)
|
||||
|
||||
# Jenkins build number
|
||||
# Build number
|
||||
SET(MultiMC_VERSION_BUILD 0 CACHE STRING "Build number.")
|
||||
MESSAGE(STATUS "MultiMC build #${MultiMC_VERSION_BUILD}")
|
||||
|
||||
# Custom target to just print the version.
|
||||
ADD_CUSTOM_TARGET(version echo "Version: ${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_REV}.${MultiMC_VERSION_BUILD}")
|
||||
|
||||
# Check the current Git commit
|
||||
execute_process(COMMAND git rev-parse HEAD
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
@ -145,141 +163,161 @@ ADD_DEFINITIONS(-DLIBGROUPVIEW_STATIC)
|
||||
|
||||
################################ FILES ################################
|
||||
|
||||
######## Headers ########
|
||||
SET(MULTIMC_HEADERS
|
||||
######## Sources and headers ########
|
||||
SET(MULTIMC_SOURCES
|
||||
# Application base
|
||||
MultiMC.h
|
||||
MultiMC.cpp
|
||||
MultiMCVersion.h
|
||||
|
||||
# Logging
|
||||
logger/QsDebugOutput.cpp
|
||||
logger/QsDebugOutput.h
|
||||
logger/QsLog.cpp
|
||||
logger/QsLog.h
|
||||
logger/QsLogDest.cpp
|
||||
logger/QsLogDest.h
|
||||
|
||||
# GUI
|
||||
gui/mainwindow.h
|
||||
gui/mainwindow.cpp
|
||||
gui/settingsdialog.h
|
||||
gui/settingsdialog.cpp
|
||||
gui/newinstancedialog.h
|
||||
gui/newinstancedialog.cpp
|
||||
gui/logindialog.h
|
||||
gui/taskdialog.h
|
||||
gui/logindialog.cpp
|
||||
gui/ProgressDialog.h
|
||||
gui/ProgressDialog.cpp
|
||||
gui/aboutdialog.h
|
||||
gui/aboutdialog.cpp
|
||||
gui/consolewindow.h
|
||||
gui/consolewindow.cpp
|
||||
gui/instancedelegate.h
|
||||
gui/instancedelegate.cpp
|
||||
gui/versionselectdialog.h
|
||||
gui/versionselectdialog.cpp
|
||||
gui/lwjglselectdialog.h
|
||||
gui/lwjglselectdialog.cpp
|
||||
gui/instancesettings.h
|
||||
gui/instancesettings.cpp
|
||||
gui/IconPickerDialog.h
|
||||
gui/IconPickerDialog.cpp
|
||||
gui/LegacyModEditDialog.h
|
||||
gui/LegacyModEditDialog.cpp
|
||||
gui/OneSixModEditDialog.h
|
||||
gui/OneSixModEditDialog.cpp
|
||||
gui/ModEditDialogCommon.h
|
||||
gui/ModEditDialogCommon.cpp
|
||||
gui/ModListView.h
|
||||
gui/ModListView.cpp
|
||||
gui/LabeledToolButton.h
|
||||
gui/LabeledToolButton.cpp
|
||||
gui/EditNotesDialog.h
|
||||
gui/EditNotesDialog.cpp
|
||||
gui/MCModInfoFrame.h
|
||||
gui/MCModInfoFrame.cpp
|
||||
|
||||
# Base classes and infrastructure
|
||||
logic/InstanceVersion.h
|
||||
logic/BaseVersion.h
|
||||
logic/MinecraftVersion.h
|
||||
logic/InstanceFactory.h
|
||||
logic/BaseUpdate.h
|
||||
logic/BaseInstance.h
|
||||
logic/BaseInstance_p.h
|
||||
logic/MinecraftProcess.h
|
||||
logic/Mod.h
|
||||
logic/ModList.h
|
||||
|
||||
# Basic instance launcher for starting from terminal
|
||||
logic/InstanceLauncher.h
|
||||
|
||||
# network stuffs
|
||||
logic/net/DownloadJob.h
|
||||
logic/net/HttpMetaCache.h
|
||||
|
||||
# legacy instances
|
||||
logic/LegacyInstance.h
|
||||
logic/LegacyInstance_p.h
|
||||
logic/LegacyUpdate.h
|
||||
logic/LegacyForge.h
|
||||
|
||||
# 1.6 instances
|
||||
logic/OneSixAssets.h
|
||||
logic/OneSixInstance.h
|
||||
logic/OneSixInstance_p.h
|
||||
logic/OneSixUpdate.h
|
||||
logic/OneSixVersion.h
|
||||
logic/VersionFactory.h
|
||||
|
||||
# Nostalgia
|
||||
logic/NostalgiaInstance.h
|
||||
|
||||
# Lists
|
||||
logic/lists/InstanceList.h
|
||||
logic/lists/InstVersionList.h
|
||||
logic/lists/MinecraftVersionList.h
|
||||
logic/lists/LwjglVersionList.h
|
||||
logic/lists/IconList.h
|
||||
|
||||
# Tasks
|
||||
logic/tasks/Task.h
|
||||
logic/tasks/LoginTask.h
|
||||
)
|
||||
|
||||
|
||||
######## Sources ########
|
||||
SET(MULTIMC_SOURCES
|
||||
MultiMC.cpp
|
||||
|
||||
gui/mainwindow.cpp
|
||||
gui/settingsdialog.cpp
|
||||
gui/newinstancedialog.cpp
|
||||
gui/logindialog.cpp
|
||||
gui/taskdialog.cpp
|
||||
gui/aboutdialog.cpp
|
||||
gui/consolewindow.cpp
|
||||
gui/instancedelegate.cpp
|
||||
gui/versionselectdialog.cpp
|
||||
gui/lwjglselectdialog.cpp
|
||||
gui/instancesettings.cpp
|
||||
gui/IconPickerDialog.cpp
|
||||
gui/LegacyModEditDialog.cpp
|
||||
gui/OneSixModEditDialog.cpp
|
||||
gui/ModEditDialogCommon.cpp
|
||||
gui/ModListView.cpp
|
||||
gui/LabeledToolButton.cpp
|
||||
gui/EditNotesDialog.cpp
|
||||
|
||||
# Base classes and infrastructure
|
||||
logic/InstanceFactory.cpp
|
||||
logic/BaseUpdate.h
|
||||
logic/BaseUpdate.cpp
|
||||
logic/BaseInstance.h
|
||||
logic/BaseInstance.cpp
|
||||
logic/BaseInstance_p.h
|
||||
|
||||
logic/MinecraftProcess.h
|
||||
logic/MinecraftProcess.cpp
|
||||
logic/Mod.h
|
||||
logic/Mod.cpp
|
||||
logic/ModList.h
|
||||
logic/ModList.cpp
|
||||
|
||||
# Basic instance launcher for starting from terminal
|
||||
logic/InstanceLauncher.h
|
||||
logic/InstanceLauncher.cpp
|
||||
|
||||
# network stuffs - to be moved into a depend lib ~_~
|
||||
# network stuffs
|
||||
logic/net/Download.h
|
||||
logic/net/FileDownload.h
|
||||
logic/net/FileDownload.cpp
|
||||
logic/net/ByteArrayDownload.h
|
||||
logic/net/ByteArrayDownload.cpp
|
||||
logic/net/CacheDownload.h
|
||||
logic/net/CacheDownload.cpp
|
||||
logic/net/ForgeXzDownload.h
|
||||
logic/net/ForgeXzDownload.cpp
|
||||
logic/net/DownloadJob.h
|
||||
logic/net/DownloadJob.cpp
|
||||
logic/net/HttpMetaCache.h
|
||||
logic/net/HttpMetaCache.cpp
|
||||
logic/net/LoginTask.h
|
||||
logic/net/LoginTask.cpp
|
||||
|
||||
# legacy instances
|
||||
logic/LegacyInstance.h
|
||||
logic/LegacyInstance.cpp
|
||||
logic/LegacyInstance_p.h
|
||||
logic/LegacyUpdate.h
|
||||
logic/LegacyUpdate.cpp
|
||||
logic/LegacyForge.h
|
||||
logic/LegacyForge.cpp
|
||||
|
||||
# 1.6 instances
|
||||
logic/OneSixAssets.h
|
||||
logic/OneSixAssets.cpp
|
||||
logic/OneSixInstance.h
|
||||
logic/OneSixInstance.cpp
|
||||
logic/OneSixVersion.cpp
|
||||
logic/OneSixInstance_p.h
|
||||
logic/OneSixUpdate.h
|
||||
logic/OneSixUpdate.cpp
|
||||
logic/VersionFactory.cpp
|
||||
logic/OneSixVersion.h
|
||||
logic/OneSixVersion.cpp
|
||||
logic/OneSixLibrary.h
|
||||
logic/OneSixLibrary.cpp
|
||||
logic/OneSixRule.h
|
||||
logic/OneSixRule.cpp
|
||||
logic/OpSys.h
|
||||
logic/OpSys.cpp
|
||||
logic/ForgeInstaller.h
|
||||
logic/ForgeInstaller.cpp
|
||||
|
||||
# Nostalgia
|
||||
logic/NostalgiaInstance.h
|
||||
logic/NostalgiaInstance.cpp
|
||||
|
||||
# Lists
|
||||
logic/lists/InstanceList.h
|
||||
logic/lists/InstanceList.cpp
|
||||
logic/lists/InstVersionList.cpp
|
||||
logic/lists/MinecraftVersionList.cpp
|
||||
logic/lists/LwjglVersionList.cpp
|
||||
logic/lists/IconList.h
|
||||
logic/lists/IconList.cpp
|
||||
logic/lists/BaseVersionList.h
|
||||
logic/lists/BaseVersionList.cpp
|
||||
logic/lists/MinecraftVersionList.h
|
||||
logic/lists/MinecraftVersionList.cpp
|
||||
logic/lists/LwjglVersionList.h
|
||||
logic/lists/LwjglVersionList.cpp
|
||||
logic/lists/ForgeVersionList.h
|
||||
logic/lists/ForgeVersionList.cpp
|
||||
logic/lists/JavaVersionList.h
|
||||
logic/lists/JavaVersionList.cpp
|
||||
|
||||
# misc model/view
|
||||
logic/EnabledItemFilter.h
|
||||
logic/EnabledItemFilter.cpp
|
||||
|
||||
# Tasks
|
||||
logic/tasks/ProgressProvider.h
|
||||
logic/tasks/Task.h
|
||||
logic/tasks/Task.cpp
|
||||
logic/tasks/LoginTask.cpp
|
||||
|
||||
# Utilities
|
||||
logic/JavaUtils.h
|
||||
logic/JavaUtils.cpp
|
||||
|
||||
)
|
||||
|
||||
|
||||
@ -289,24 +327,38 @@ gui/mainwindow.ui
|
||||
gui/settingsdialog.ui
|
||||
gui/newinstancedialog.ui
|
||||
gui/logindialog.ui
|
||||
gui/taskdialog.ui
|
||||
gui/aboutdialog.ui
|
||||
gui/consolewindow.ui
|
||||
gui/versionselectdialog.ui
|
||||
gui/lwjglselectdialog.ui
|
||||
gui/instancesettings.ui
|
||||
|
||||
gui/ProgressDialog.ui
|
||||
gui/IconPickerDialog.ui
|
||||
gui/LegacyModEditDialog.ui
|
||||
gui/OneSixModEditDialog.ui
|
||||
gui/EditNotesDialog.ui
|
||||
|
||||
gui/MCModInfoFrame.ui
|
||||
)
|
||||
|
||||
set (FILES_TO_TRANSLATE ${FILES_TO_TRANSLATE} ${MULTIMC_SOURCES} ${MULTIMC_UIS})
|
||||
|
||||
|
||||
######## Windows resource files ########
|
||||
IF(WIN32)
|
||||
SET(MULTIMC_RCS multimc.rc)
|
||||
ENDIF()
|
||||
|
||||
####### X11 Stuff #######
|
||||
IF(UNIX AND NOT APPLE)
|
||||
SET(MultiMC_QT_ADDITIONAL_MODULES ${MultiMC_QT_ADDITIONAL_MODULES} X11Extras)
|
||||
SET(MultiMC_LINK_ADDITIONAL_LIBS ${MultiMC_LINK_ADDITIONAL_LIBS} xcb)
|
||||
LIST(APPEND MULTIMC_SOURCES gui/platform_x11.cpp)
|
||||
ELSE()
|
||||
LIST(APPEND MULTIMC_SOURCES gui/platform_other.cpp)
|
||||
ENDIF()
|
||||
|
||||
|
||||
################################ COMPILE ################################
|
||||
|
||||
@ -333,13 +385,12 @@ QT5_ADD_RESOURCES(MULTIMC_QRC multimc.qrc)
|
||||
|
||||
# Add executable
|
||||
ADD_EXECUTABLE(MultiMC MACOSX_BUNDLE WIN32
|
||||
${MULTIMC_SOURCES} ${MULTIMC_HEADERS} ${MULTIMC_UI} ${MULTIMC_QRC} ${MULTIMC_RCS})
|
||||
${MULTIMC_SOURCES} ${MULTIMC_UI} ${MULTIMC_QRC} ${MULTIMC_RCS})
|
||||
|
||||
# Link
|
||||
QT5_USE_MODULES(MultiMC Widgets Network Xml)
|
||||
TARGET_LINK_LIBRARIES(MultiMC quazip libUtil libSettings libGroupView ${MultiMC_LINK_ADDITIONAL_LIBS})
|
||||
ADD_DEPENDENCIES(MultiMC MultiMCLauncher libUtil libSettings libGroupView)
|
||||
|
||||
TARGET_LINK_LIBRARIES(MultiMC xz-embedded unpack200 quazip libUtil libSettings libGroupView ${MultiMC_LINK_ADDITIONAL_LIBS})
|
||||
QT5_USE_MODULES(MultiMC Core Widgets Network Xml ${MultiMC_QT_ADDITIONAL_MODULES})
|
||||
ADD_DEPENDENCIES(MultiMC MultiMCLauncher)
|
||||
|
||||
option(BUILD_KEYRING_TEST "Build the simple keyring test binary" OFF)
|
||||
IF(BUILD_KEYRING_TEST)
|
||||
@ -357,9 +408,9 @@ ENDIF()
|
||||
|
||||
######## Plugin and library folders ########
|
||||
|
||||
SET(PLUGIN_DEST_DIR bin)
|
||||
SET(QTCONF_DEST_DIR bin)
|
||||
SET(APPS "\${CMAKE_INSTALL_PREFIX}/bin/MultiMC")
|
||||
SET(PLUGIN_DEST_DIR plugins)
|
||||
SET(QTCONF_DEST_DIR .)
|
||||
SET(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC")
|
||||
|
||||
IF(WIN32)
|
||||
SET(PLUGIN_DEST_DIR .)
|
||||
@ -367,10 +418,14 @@ IF(WIN32)
|
||||
SET(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC.exe")
|
||||
ENDIF()
|
||||
|
||||
IF(UNIX)
|
||||
IF(APPLE)
|
||||
SET(PLUGIN_DEST_DIR MultiMC.app/Contents/MacOS)
|
||||
SET(QTCONF_DEST_DIR MultiMC.app/Contents/Resources)
|
||||
SET(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC.app")
|
||||
ELSE()
|
||||
SET(APPS "\${CMAKE_INSTALL_PREFIX}/bin/MultiMC")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
SET(QT_PLUGINS_DIR ${Qt5_DIR}/plugins)
|
||||
@ -394,6 +449,7 @@ ENDIF(APPLE)
|
||||
IF(WIN32)
|
||||
INSTALL(TARGETS MultiMC
|
||||
BUNDLE DESTINATION . COMPONENT Runtime
|
||||
LIBRARY DESTINATION . COMPONENT Runtime
|
||||
RUNTIME DESTINATION . COMPONENT Runtime
|
||||
)
|
||||
ENDIF()
|
||||
@ -406,35 +462,40 @@ INSTALL(TARGETS MultiMC
|
||||
ELSE()
|
||||
INSTALL(TARGETS MultiMC
|
||||
BUNDLE DESTINATION . COMPONENT Runtime
|
||||
RUNTIME DESTINATION . COMPONENT Runtime
|
||||
RUNTIME DESTINATION bin COMPONENT Runtime
|
||||
)
|
||||
INSTALL(PROGRAMS package/linux/MultiMC DESTINATION .)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
|
||||
#### Plugins ####
|
||||
|
||||
# # Image formats
|
||||
# INSTALL(DIRECTORY "${QT_PLUGINS_DIR}/imageformats" DESTINATION ${PLUGIN_DEST_DIR} COMPONENT Runtime)
|
||||
#
|
||||
# # Platform plugins
|
||||
# INSTALL(DIRECTORY "${QT_PLUGINS_DIR}/platforms" DESTINATION ${PLUGIN_DEST_DIR} COMPONENT Runtime)
|
||||
#
|
||||
# # qtconf
|
||||
# INSTALL(CODE "
|
||||
# FILE(WRITE \"\${CMAKE_INSTALL_PREFIX}/${QTCONF_DEST_DIR}/qt.conf\" \"\")
|
||||
# " COMPONENT Runtime)
|
||||
#
|
||||
#
|
||||
# # Dirs to look for dependencies.
|
||||
# SET(DIRS "${QT_LIBRARY_DIRS}")
|
||||
#
|
||||
# INSTALL(CODE "
|
||||
# file(GLOB_RECURSE QTPLUGINS
|
||||
# \"\${CMAKE_INSTALL_PREFIX}/${PLUGIN_DEST_DIR}/plugins/*${CMAKE_SHARED_LIBRARY_SUFFIX}\")
|
||||
# include(BundleUtilities)
|
||||
# fixup_bundle(\"${APPS}\" \"\${QTPLUGINS}\" \"${DIRS}\")
|
||||
# " COMPONENT Runtime)
|
||||
OPTION(MultiMC_INSTALL_SHARED_LIBS "if set, Qt's shared libraries will be copied to the installation directory on install")
|
||||
|
||||
IF (MultiMC_INSTALL_SHARED_LIBS)
|
||||
# Image formats
|
||||
INSTALL(DIRECTORY "${QT_PLUGINS_DIR}/imageformats" DESTINATION ${PLUGIN_DEST_DIR} COMPONENT Runtime)
|
||||
|
||||
# Platform plugins
|
||||
INSTALL(DIRECTORY "${QT_PLUGINS_DIR}/platforms" DESTINATION ${PLUGIN_DEST_DIR} COMPONENT Runtime)
|
||||
|
||||
# qtconf
|
||||
INSTALL(CODE "
|
||||
FILE(WRITE \"\${CMAKE_INSTALL_PREFIX}/${QTCONF_DEST_DIR}/qt.conf\" \"\")
|
||||
" COMPONENT Runtime)
|
||||
|
||||
|
||||
# Dirs to look for dependencies.
|
||||
SET(DIRS "${QT_LIBRARY_DIRS}")
|
||||
|
||||
INSTALL(CODE "
|
||||
file(GLOB_RECURSE QTPLUGINS
|
||||
\"\${CMAKE_INSTALL_PREFIX}/${PLUGIN_DEST_DIR}/plugins/*${CMAKE_SHARED_LIBRARY_SUFFIX}\")
|
||||
include(BundleUtilities)
|
||||
fixup_bundle(\"${APPS}\" \"\${QTPLUGINS}\" \"${DIRS}\")
|
||||
" COMPONENT Runtime)
|
||||
ENDIF()
|
||||
|
||||
|
||||
######## Package ########
|
||||
@ -472,3 +533,18 @@ ENDIF()
|
||||
INCLUDE(CPack)
|
||||
|
||||
include_directories(${PROJECT_BINARY_DIR}/include)
|
||||
|
||||
### translation stuff
|
||||
|
||||
file (GLOB TRANSLATIONS_FILES translations/*.ts)
|
||||
|
||||
option (UPDATE_TRANSLATIONS "Update source translation translations/*.ts files (WARNING: make clean will delete the source .ts files! Danger!)")
|
||||
if (UPDATE_TRANSLATIONS)
|
||||
qt5_create_translation(QM_FILES ${FILES_TO_TRANSLATE} ${TRANSLATIONS_FILES})
|
||||
else (UPDATE_TRANSLATIONS)
|
||||
qt5_add_translation(QM_FILES ${TRANSLATIONS_FILES})
|
||||
endif (UPDATE_TRANSLATIONS)
|
||||
|
||||
add_custom_target (translations DEPENDS ${QM_FILES})
|
||||
|
||||
install(FILES ${QM_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/translations)
|
||||
|
202
MultiMC.cpp
202
MultiMC.cpp
@ -3,26 +3,39 @@
|
||||
#include <iostream>
|
||||
#include <QDir>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QTranslator>
|
||||
#include <QLibraryInfo>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "gui/mainwindow.h"
|
||||
#include "gui/versionselectdialog.h"
|
||||
#include "logic/lists/InstanceList.h"
|
||||
#include "logic/lists/IconList.h"
|
||||
#include "logic/InstanceLauncher.h"
|
||||
#include "logic/lists/LwjglVersionList.h"
|
||||
#include "logic/lists/MinecraftVersionList.h"
|
||||
#include "logic/lists/ForgeVersionList.h"
|
||||
|
||||
#include "logic/InstanceLauncher.h"
|
||||
#include "logic/net/HttpMetaCache.h"
|
||||
|
||||
#include "logic/JavaUtils.h"
|
||||
|
||||
#include "pathutils.h"
|
||||
#include "cmdutils.h"
|
||||
#include <inisettingsobject.h>
|
||||
#include <setting.h>
|
||||
#include <logger/QsLog.h>
|
||||
#include <logger/QsLogDest.h>
|
||||
|
||||
#include "config.h"
|
||||
using namespace Util::Commandline;
|
||||
|
||||
MultiMC::MultiMC ( int& argc, char** argv )
|
||||
:QApplication ( argc, argv )
|
||||
MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
|
||||
{
|
||||
setOrganizationName("Forkk");
|
||||
setApplicationName("MultiMC 5");
|
||||
setOrganizationName("MultiMC");
|
||||
setApplicationName("MultiMC5");
|
||||
|
||||
initTranslations();
|
||||
|
||||
// Print app header
|
||||
std::cout << "MultiMC 5" << std::endl;
|
||||
@ -44,15 +57,18 @@ MultiMC::MultiMC ( int& argc, char** argv )
|
||||
// --dir
|
||||
parser.addOption("dir", applicationDirPath());
|
||||
parser.addShortOpt("dir", 'd');
|
||||
parser.addDocumentation("dir", "use the supplied directory as MultiMC root instead of the binary location (use '.' for current)");
|
||||
parser.addDocumentation("dir", "use the supplied directory as MultiMC root instead of "
|
||||
"the binary location (use '.' for current)");
|
||||
// --update
|
||||
parser.addOption("update");
|
||||
parser.addShortOpt("update", 'u');
|
||||
parser.addDocumentation("update", "replaces the given file with the running executable", "<path>");
|
||||
parser.addDocumentation("update", "replaces the given file with the running executable",
|
||||
"<path>");
|
||||
// --quietupdate
|
||||
parser.addSwitch("quietupdate");
|
||||
parser.addShortOpt("quietupdate", 'U');
|
||||
parser.addDocumentation("quietupdate", "doesn't restart MultiMC after installing updates");
|
||||
parser.addDocumentation("quietupdate",
|
||||
"doesn't restart MultiMC after installing updates");
|
||||
// --launch
|
||||
parser.addOption("launch");
|
||||
parser.addShortOpt("launch", 'l');
|
||||
@ -63,10 +79,11 @@ MultiMC::MultiMC ( int& argc, char** argv )
|
||||
{
|
||||
args = parser.parse(arguments());
|
||||
}
|
||||
catch(ParsingError e)
|
||||
catch (ParsingError e)
|
||||
{
|
||||
std::cerr << "CommandLineError: " << e.what() << std::endl;
|
||||
std::cerr << "Try '%1 -h' to get help on MultiMC's command line parameters." << std::endl;
|
||||
std::cerr << "Try '%1 -h' to get help on MultiMC's command line parameters."
|
||||
<< std::endl;
|
||||
m_status = MultiMC::Failed;
|
||||
return;
|
||||
}
|
||||
@ -84,7 +101,8 @@ MultiMC::MultiMC ( int& argc, char** argv )
|
||||
{
|
||||
std::cout << "Version " << VERSION_STR << std::endl;
|
||||
std::cout << "Git " << GIT_COMMIT << std::endl;
|
||||
std::cout << "Tag: " << JENKINS_BUILD_TAG << " " << (ARCH==x64?"x86_64":"x86") << std::endl;
|
||||
std::cout << "Tag: " << JENKINS_BUILD_TAG << " " << (ARCH == x64 ? "x86_64" : "x86")
|
||||
<< std::endl;
|
||||
m_status = MultiMC::Succeeded;
|
||||
return;
|
||||
}
|
||||
@ -93,12 +111,13 @@ MultiMC::MultiMC ( int& argc, char** argv )
|
||||
// Note: cwd is always the current executable path!
|
||||
if (!args["update"].isNull())
|
||||
{
|
||||
std::cout << "Performing MultiMC update: " << qPrintable(args["update"].toString()) << std::endl;
|
||||
std::cout << "Performing MultiMC update: " << qPrintable(args["update"].toString())
|
||||
<< std::endl;
|
||||
QString cwd = QDir::currentPath();
|
||||
QDir::setCurrent(applicationDirPath());
|
||||
QFile file(applicationFilePath());
|
||||
file.copy(args["update"].toString());
|
||||
if(args["quietupdate"].toBool())
|
||||
if (args["quietupdate"].toBool())
|
||||
{
|
||||
m_status = MultiMC::Succeeded;
|
||||
return;
|
||||
@ -110,14 +129,22 @@ MultiMC::MultiMC ( int& argc, char** argv )
|
||||
// change directory
|
||||
QDir::setCurrent(args["dir"].toString());
|
||||
|
||||
// init the logger
|
||||
initLogger();
|
||||
|
||||
// load settings
|
||||
initGlobalSettings();
|
||||
|
||||
// and instances
|
||||
m_instances = new InstanceList(m_settings->get("InstanceDir").toString(),this);
|
||||
std::cout << "Loading Instances..." << std::endl;
|
||||
m_instances.reset(new InstanceList(m_settings->get("InstanceDir").toString(), this));
|
||||
QLOG_INFO() << "Loading Instances...";
|
||||
m_instances->loadList();
|
||||
// network manager
|
||||
m_qnam = new QNetworkAccessManager(this);
|
||||
|
||||
// init the http meta cache
|
||||
initHttpMetaCache();
|
||||
|
||||
// create the global network manager
|
||||
m_qnam.reset(new QNetworkAccessManager(this));
|
||||
|
||||
// Register meta types.
|
||||
qRegisterMetaType<LoginResponse>("LoginResponse");
|
||||
@ -125,7 +152,7 @@ MultiMC::MultiMC ( int& argc, char** argv )
|
||||
// launch instance, if that's what should be done
|
||||
if (!args["launch"].isNull())
|
||||
{
|
||||
if(InstanceLauncher(args["launch"].toString()).launch())
|
||||
if (InstanceLauncher(args["launch"].toString()).launch())
|
||||
m_status = MultiMC::Succeeded;
|
||||
else
|
||||
m_status = MultiMC::Failed;
|
||||
@ -136,12 +163,71 @@ MultiMC::MultiMC ( int& argc, char** argv )
|
||||
|
||||
MultiMC::~MultiMC()
|
||||
{
|
||||
delete m_settings;
|
||||
if (m_mmc_translator)
|
||||
{
|
||||
removeTranslator(m_mmc_translator.get());
|
||||
}
|
||||
if (m_qt_translator)
|
||||
{
|
||||
removeTranslator(m_qt_translator.get());
|
||||
}
|
||||
}
|
||||
|
||||
void MultiMC::initTranslations()
|
||||
{
|
||||
m_qt_translator.reset(new QTranslator());
|
||||
if (m_qt_translator->load("qt_" + QLocale::system().name(),
|
||||
QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
|
||||
{
|
||||
std::cout << "Loading Qt Language File for "
|
||||
<< QLocale::system().name().toLocal8Bit().constData() << "...";
|
||||
if (!installTranslator(m_qt_translator.get()))
|
||||
{
|
||||
std::cout << " failed.";
|
||||
m_qt_translator.reset();
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_qt_translator.reset();
|
||||
}
|
||||
|
||||
m_mmc_translator.reset(new QTranslator());
|
||||
if (m_mmc_translator->load("mmc_" + QLocale::system().name(),
|
||||
QDir("translations").absolutePath()))
|
||||
{
|
||||
std::cout << "Loading MMC Language File for "
|
||||
<< QLocale::system().name().toLocal8Bit().constData() << "...";
|
||||
if (!installTranslator(m_mmc_translator.get()))
|
||||
{
|
||||
std::cout << " failed.";
|
||||
m_mmc_translator.reset();
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_mmc_translator.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void MultiMC::initLogger()
|
||||
{
|
||||
// init the logging mechanism
|
||||
QsLogging::Logger &logger = QsLogging::Logger::instance();
|
||||
logger.setLoggingLevel(QsLogging::TraceLevel);
|
||||
m_fileDestination = QsLogging::DestinationFactory::MakeFileDestination("MultiMC.log");
|
||||
m_debugDestination = QsLogging::DestinationFactory::MakeDebugOutputDestination();
|
||||
logger.addDestination(m_fileDestination.get());
|
||||
logger.addDestination(m_debugDestination.get());
|
||||
// log all the things
|
||||
logger.setLoggingLevel(QsLogging::TraceLevel);
|
||||
}
|
||||
|
||||
void MultiMC::initGlobalSettings()
|
||||
{
|
||||
m_settings = new INISettingsObject(applicationDirPath() + "/multimc.cfg", this);
|
||||
m_settings.reset(new INISettingsObject("multimc.cfg", this));
|
||||
// Updates
|
||||
m_settings->registerSetting(new Setting("UseDevBuilds", false));
|
||||
m_settings->registerSetting(new Setting("AutoUpdate", true));
|
||||
@ -160,9 +246,9 @@ void MultiMC::initGlobalSettings()
|
||||
m_settings->registerSetting(new Setting("InstanceToolbarPosition", QPoint()));
|
||||
|
||||
// Console Colors
|
||||
// m_settings->registerSetting(new Setting("SysMessageColor", QColor(Qt::blue)));
|
||||
// m_settings->registerSetting(new Setting("StdOutColor", QColor(Qt::black)));
|
||||
// m_settings->registerSetting(new Setting("StdErrColor", QColor(Qt::red)));
|
||||
// m_settings->registerSetting(new Setting("SysMessageColor", QColor(Qt::blue)));
|
||||
// m_settings->registerSetting(new Setting("StdOutColor", QColor(Qt::black)));
|
||||
// m_settings->registerSetting(new Setting("StdErrColor", QColor(Qt::red)));
|
||||
|
||||
// Window Size
|
||||
m_settings->registerSetting(new Setting("LaunchMaximized", false));
|
||||
@ -178,7 +264,8 @@ void MultiMC::initGlobalSettings()
|
||||
m_settings->registerSetting(new Setting("PermGen", 64));
|
||||
|
||||
// Java Settings
|
||||
m_settings->registerSetting(new Setting("JavaPath", "java"));
|
||||
m_settings->registerSetting(new Setting("JavaPath", ""));
|
||||
m_settings->registerSetting(new Setting("LastHostname", ""));
|
||||
m_settings->registerSetting(new Setting("JvmArgs", ""));
|
||||
|
||||
// Custom Commands
|
||||
@ -187,17 +274,75 @@ void MultiMC::initGlobalSettings()
|
||||
|
||||
// The cat
|
||||
m_settings->registerSetting(new Setting("TheCat", false));
|
||||
|
||||
// Shall the main window hide on instance launch
|
||||
m_settings->registerSetting(new Setting("NoHide", false));
|
||||
|
||||
// Persistent value for the client ID
|
||||
m_settings->registerSetting(new Setting("YggdrasilClientToken", ""));
|
||||
QString currentYggID = m_settings->get("YggdrasilClientToken").toString();
|
||||
if (currentYggID.isEmpty())
|
||||
{
|
||||
QUuid uuid = QUuid::createUuid();
|
||||
m_settings->set("YggdrasilClientToken", uuid.toString());
|
||||
}
|
||||
}
|
||||
|
||||
IconList* MultiMC::icons()
|
||||
void MultiMC::initHttpMetaCache()
|
||||
{
|
||||
if ( !m_icons )
|
||||
m_metacache.reset(new HttpMetaCache("metacache"));
|
||||
m_metacache->addBase("assets", QDir("assets").absolutePath());
|
||||
m_metacache->addBase("versions", QDir("versions").absolutePath());
|
||||
m_metacache->addBase("libraries", QDir("libraries").absolutePath());
|
||||
m_metacache->addBase("minecraftforge", QDir("mods/minecraftforge").absolutePath());
|
||||
m_metacache->addBase("skins", QDir("accounts/skins").absolutePath());
|
||||
m_metacache->Load();
|
||||
}
|
||||
|
||||
std::shared_ptr<IconList> MultiMC::icons()
|
||||
{
|
||||
if (!m_icons)
|
||||
{
|
||||
m_icons = new IconList;
|
||||
m_icons.reset(new IconList);
|
||||
}
|
||||
return m_icons;
|
||||
}
|
||||
|
||||
std::shared_ptr<LWJGLVersionList> MultiMC::lwjgllist()
|
||||
{
|
||||
if (!m_lwjgllist)
|
||||
{
|
||||
m_lwjgllist.reset(new LWJGLVersionList());
|
||||
}
|
||||
return m_lwjgllist;
|
||||
}
|
||||
|
||||
std::shared_ptr<ForgeVersionList> MultiMC::forgelist()
|
||||
{
|
||||
if (!m_forgelist)
|
||||
{
|
||||
m_forgelist.reset(new ForgeVersionList());
|
||||
}
|
||||
return m_forgelist;
|
||||
}
|
||||
|
||||
std::shared_ptr<MinecraftVersionList> MultiMC::minecraftlist()
|
||||
{
|
||||
if (!m_minecraftlist)
|
||||
{
|
||||
m_minecraftlist.reset(new MinecraftVersionList());
|
||||
}
|
||||
return m_minecraftlist;
|
||||
}
|
||||
|
||||
std::shared_ptr<JavaVersionList> MultiMC::javalist()
|
||||
{
|
||||
if (!m_javalist)
|
||||
{
|
||||
m_javalist.reset(new JavaVersionList());
|
||||
}
|
||||
return m_javalist;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
@ -207,8 +352,9 @@ int main(int argc, char *argv[])
|
||||
// show main window
|
||||
MainWindow mainWin;
|
||||
mainWin.show();
|
||||
mainWin.checkSetDefaultJava();
|
||||
|
||||
switch(app.status())
|
||||
switch (app.status())
|
||||
{
|
||||
case MultiMC::Initialized:
|
||||
return app.exec();
|
||||
|
65
MultiMC.h
65
MultiMC.h
@ -3,11 +3,20 @@
|
||||
#include <QApplication>
|
||||
#include "MultiMCVersion.h"
|
||||
#include "config.h"
|
||||
#include <memory>
|
||||
#include "logger/QsLog.h"
|
||||
#include "logger/QsLogDest.h"
|
||||
|
||||
|
||||
class MinecraftVersionList;
|
||||
class LWJGLVersionList;
|
||||
class HttpMetaCache;
|
||||
class SettingsObject;
|
||||
class InstanceList;
|
||||
class IconList;
|
||||
class QNetworkAccessManager;
|
||||
class ForgeVersionList;
|
||||
class JavaVersionList;
|
||||
|
||||
#if defined(MMC)
|
||||
#undef MMC
|
||||
@ -26,20 +35,20 @@ public:
|
||||
};
|
||||
|
||||
public:
|
||||
MultiMC ( int& argc, char** argv );
|
||||
MultiMC(int &argc, char **argv);
|
||||
virtual ~MultiMC();
|
||||
|
||||
SettingsObject * settings()
|
||||
std::shared_ptr<SettingsObject> settings()
|
||||
{
|
||||
return m_settings;
|
||||
};
|
||||
}
|
||||
|
||||
InstanceList * instances()
|
||||
std::shared_ptr<InstanceList> instances()
|
||||
{
|
||||
return m_instances;
|
||||
};
|
||||
}
|
||||
|
||||
IconList * icons();
|
||||
std::shared_ptr<IconList> icons();
|
||||
|
||||
Status status()
|
||||
{
|
||||
@ -51,18 +60,48 @@ public:
|
||||
return m_version;
|
||||
}
|
||||
|
||||
QNetworkAccessManager * qnam()
|
||||
std::shared_ptr<QNetworkAccessManager> qnam()
|
||||
{
|
||||
return m_qnam;
|
||||
}
|
||||
private:
|
||||
void initGlobalSettings();
|
||||
|
||||
std::shared_ptr<HttpMetaCache> metacache()
|
||||
{
|
||||
return m_metacache;
|
||||
}
|
||||
|
||||
std::shared_ptr<LWJGLVersionList> lwjgllist();
|
||||
|
||||
std::shared_ptr<ForgeVersionList> forgelist();
|
||||
|
||||
std::shared_ptr<MinecraftVersionList> minecraftlist();
|
||||
|
||||
std::shared_ptr<JavaVersionList> javalist();
|
||||
|
||||
private:
|
||||
SettingsObject * m_settings = nullptr;
|
||||
InstanceList * m_instances = nullptr;
|
||||
IconList * m_icons = nullptr;
|
||||
QNetworkAccessManager * m_qnam = nullptr;
|
||||
void initLogger();
|
||||
|
||||
void initGlobalSettings();
|
||||
|
||||
void initHttpMetaCache();
|
||||
|
||||
void initTranslations();
|
||||
|
||||
private:
|
||||
std::shared_ptr<QTranslator> m_qt_translator;
|
||||
std::shared_ptr<QTranslator> m_mmc_translator;
|
||||
std::shared_ptr<SettingsObject> m_settings;
|
||||
std::shared_ptr<InstanceList> m_instances;
|
||||
std::shared_ptr<IconList> m_icons;
|
||||
std::shared_ptr<QNetworkAccessManager> m_qnam;
|
||||
std::shared_ptr<HttpMetaCache> m_metacache;
|
||||
std::shared_ptr<LWJGLVersionList> m_lwjgllist;
|
||||
std::shared_ptr<ForgeVersionList> m_forgelist;
|
||||
std::shared_ptr<MinecraftVersionList> m_minecraftlist;
|
||||
std::shared_ptr<JavaVersionList> m_javalist;
|
||||
QsLogging::DestinationPtr m_fileDestination;
|
||||
QsLogging::DestinationPtr m_debugDestination;
|
||||
|
||||
Status m_status = MultiMC::Failed;
|
||||
MultiMCVersion m_version = {VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD};
|
||||
};
|
23
README.md
23
README.md
@ -1,8 +1,19 @@
|
||||
![MultiMC](http://i.imgur.com/QJXbz.png)
|
||||
<h1>MultiMC 5</h1>
|
||||
<p>MultiMC is a custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once. It also allows you to easily install and remove mods by simply dragging and dropping.</p>
|
||||
|
||||
<h3>License</h3>
|
||||
<p>Copyright © 2013 MultiMC Contributors</p>
|
||||
<p>Licensed under the Apache License, Version 2.0 (the "License"); you may not use this program except in compliance with the License. You may obtain a copy of the License at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>.</p>
|
||||
<p>Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.</p>
|
||||
MultiMC 5
|
||||
=========
|
||||
|
||||
MultiMC is a custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once. It also allows you to easily install and remove mods by simply dragging and dropping.
|
||||
|
||||
## Building
|
||||
Check [BUILD.md](BUILD.md) for build instructions.
|
||||
|
||||
## Contributing
|
||||
The repository is currently managed by @peterix and @drayshak - we're the ones likely to review pull requests. If you'd like to contribute to the project please talk to us on IRC (Esper/#MultiMC) first! This helps us organise ideas and keep in contact with you, and we're unlikely to accept anything blindly.
|
||||
|
||||
## License
|
||||
Copyright © 2013 MultiMC Contributors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this program except in compliance with the License. You may obtain a copy of the License at [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0).
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
||||
|
59
depends/pack200/CMakeLists.txt
Normal file
59
depends/pack200/CMakeLists.txt
Normal file
@ -0,0 +1,59 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||
|
||||
IF(WIN32)
|
||||
# In Qt 5.1+ we have our own main() function, don't autolink to qtmain on Windows
|
||||
cmake_policy(SET CMP0020 OLD)
|
||||
ENDIF()
|
||||
|
||||
project(unpack200)
|
||||
|
||||
# Find ZLIB for quazip
|
||||
# Use system zlib on unix and Qt ZLIB on Windows
|
||||
IF(UNIX)
|
||||
find_package(ZLIB REQUIRED)
|
||||
ELSE(UNIX)
|
||||
get_filename_component (ZLIB_FOUND_DIR "${Qt5Core_DIR}/../../../include/QtZlib" ABSOLUTE)
|
||||
SET(ZLIB_INCLUDE_DIRS ${ZLIB_FOUND_DIR} CACHE PATH "Path to ZLIB headers of Qt")
|
||||
SET(ZLIB_LIBRARIES "")
|
||||
IF(NOT EXISTS "${ZLIB_INCLUDE_DIRS}/zlib.h")
|
||||
MESSAGE("Please specify a valid zlib include dir")
|
||||
ENDIF(NOT EXISTS "${ZLIB_INCLUDE_DIRS}/zlib.h")
|
||||
ENDIF(UNIX)
|
||||
|
||||
SET(PACK200_SRC
|
||||
include/unpack200.h
|
||||
src/bands.cpp
|
||||
src/bands.h
|
||||
src/bytes.cpp
|
||||
src/bytes.h
|
||||
src/coding.cpp
|
||||
src/coding.h
|
||||
src/constants.h
|
||||
src/defines.h
|
||||
src/unpack200.cpp
|
||||
src/unpack.cpp
|
||||
src/unpack.h
|
||||
src/utils.cpp
|
||||
src/utils.h
|
||||
src/zip.cpp
|
||||
src/zip.h
|
||||
)
|
||||
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
SET(PACK200_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include" PARENT_SCOPE)
|
||||
include_directories(
|
||||
include
|
||||
${ZLIB_INCLUDE_DIRS}
|
||||
)
|
||||
add_library(unpack200 STATIC ${PACK200_SRC})
|
||||
|
||||
IF(UNIX)
|
||||
target_link_libraries(unpack200 ${ZLIB_LIBRARIES})
|
||||
ELSE()
|
||||
# zlib is part of Qt on windows. use it.
|
||||
QT5_USE_MODULES(unpack200 Core)
|
||||
ENDIF()
|
||||
|
||||
add_executable(anti200 anti200.cpp)
|
||||
target_link_libraries(anti200 unpack200)
|
347
depends/pack200/LICENSE
Normal file
347
depends/pack200/LICENSE
Normal file
@ -0,0 +1,347 @@
|
||||
The GNU General Public License (GPL)
|
||||
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this license
|
||||
document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your freedom to share
|
||||
and change it. By contrast, the GNU General Public License is intended to
|
||||
guarantee your freedom to share and change free software--to make sure the
|
||||
software is free for all its users. This General Public License applies to
|
||||
most of the Free Software Foundation's software and to any other program whose
|
||||
authors commit to using it. (Some other Free Software Foundation software is
|
||||
covered by the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not price. Our
|
||||
General Public Licenses are designed to make sure that you have the freedom to
|
||||
distribute copies of free software (and charge for this service if you wish),
|
||||
that you receive source code or can get it if you want it, that you can change
|
||||
the software or use pieces of it in new free programs; and that you know you
|
||||
can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid anyone to deny
|
||||
you these rights or to ask you to surrender the rights. These restrictions
|
||||
translate to certain responsibilities for you if you distribute copies of the
|
||||
software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether gratis or for
|
||||
a fee, you must give the recipients all the rights that you have. You must
|
||||
make sure that they, too, receive or can get the source code. And you must
|
||||
show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and (2)
|
||||
offer you this license which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain that
|
||||
everyone understands that there is no warranty for this free software. If the
|
||||
software is modified by someone else and passed on, we want its recipients to
|
||||
know that what they have is not the original, so that any problems introduced
|
||||
by others will not reflect on the original authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software patents. We
|
||||
wish to avoid the danger that redistributors of a free program will
|
||||
individually obtain patent licenses, in effect making the program proprietary.
|
||||
To prevent this, we have made it clear that any patent must be licensed for
|
||||
everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and modification
|
||||
follow.
|
||||
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains a notice
|
||||
placed by the copyright holder saying it may be distributed under the terms of
|
||||
this General Public License. The "Program", below, refers to any such program
|
||||
or work, and a "work based on the Program" means either the Program or any
|
||||
derivative work under copyright law: that is to say, a work containing the
|
||||
Program or a portion of it, either verbatim or with modifications and/or
|
||||
translated into another language. (Hereinafter, translation is included
|
||||
without limitation in the term "modification".) Each licensee is addressed as
|
||||
"you".
|
||||
|
||||
Activities other than copying, distribution and modification are not covered by
|
||||
this License; they are outside its scope. The act of running the Program is
|
||||
not restricted, and the output from the Program is covered only if its contents
|
||||
constitute a work based on the Program (independent of having been made by
|
||||
running the Program). Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's source code as
|
||||
you receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice and
|
||||
disclaimer of warranty; keep intact all the notices that refer to this License
|
||||
and to the absence of any warranty; and give any other recipients of the
|
||||
Program a copy of this License along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and you may
|
||||
at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion of it, thus
|
||||
forming a work based on the Program, and copy and distribute such modifications
|
||||
or work under the terms of Section 1 above, provided that you also meet all of
|
||||
these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices stating
|
||||
that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in whole or
|
||||
in part contains or is derived from the Program or any part thereof, to be
|
||||
licensed as a whole at no charge to all third parties under the terms of
|
||||
this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively when run,
|
||||
you must cause it, when started running for such interactive use in the
|
||||
most ordinary way, to print or display an announcement including an
|
||||
appropriate copyright notice and a notice that there is no warranty (or
|
||||
else, saying that you provide a warranty) and that users may redistribute
|
||||
the program under these conditions, and telling the user how to view a copy
|
||||
of this License. (Exception: if the Program itself is interactive but does
|
||||
not normally print such an announcement, your work based on the Program is
|
||||
not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If identifiable
|
||||
sections of that work are not derived from the Program, and can be reasonably
|
||||
considered independent and separate works in themselves, then this License, and
|
||||
its terms, do not apply to those sections when you distribute them as separate
|
||||
works. But when you distribute the same sections as part of a whole which is a
|
||||
work based on the Program, the distribution of the whole must be on the terms
|
||||
of this License, whose permissions for other licensees extend to the entire
|
||||
whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest your
|
||||
rights to work written entirely by you; rather, the intent is to exercise the
|
||||
right to control the distribution of derivative or collective works based on
|
||||
the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program with the
|
||||
Program (or with a work based on the Program) on a volume of a storage or
|
||||
distribution medium does not bring the other work under the scope of this
|
||||
License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it, under
|
||||
Section 2) in object code or executable form under the terms of Sections 1 and
|
||||
2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable source
|
||||
code, which must be distributed under the terms of Sections 1 and 2 above
|
||||
on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three years, to
|
||||
give any third party, for a charge no more than your cost of physically
|
||||
performing source distribution, a complete machine-readable copy of the
|
||||
corresponding source code, to be distributed under the terms of Sections 1
|
||||
and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer to
|
||||
distribute corresponding source code. (This alternative is allowed only
|
||||
for noncommercial distribution and only if you received the program in
|
||||
object code or executable form with such an offer, in accord with
|
||||
Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for making
|
||||
modifications to it. For an executable work, complete source code means all
|
||||
the source code for all modules it contains, plus any associated interface
|
||||
definition files, plus the scripts used to control compilation and installation
|
||||
of the executable. However, as a special exception, the source code
|
||||
distributed need not include anything that is normally distributed (in either
|
||||
source or binary form) with the major components (compiler, kernel, and so on)
|
||||
of the operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the source
|
||||
code from the same place counts as distribution of the source code, even though
|
||||
third parties are not compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program except as
|
||||
expressly provided under this License. Any attempt otherwise to copy, modify,
|
||||
sublicense or distribute the Program is void, and will automatically terminate
|
||||
your rights under this License. However, parties who have received copies, or
|
||||
rights, from you under this License will not have their licenses terminated so
|
||||
long as such parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not signed it.
|
||||
However, nothing else grants you permission to modify or distribute the Program
|
||||
or its derivative works. These actions are prohibited by law if you do not
|
||||
accept this License. Therefore, by modifying or distributing the Program (or
|
||||
any work based on the Program), you indicate your acceptance of this License to
|
||||
do so, and all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the Program),
|
||||
the recipient automatically receives a license from the original licensor to
|
||||
copy, distribute or modify the Program subject to these terms and conditions.
|
||||
You may not impose any further restrictions on the recipients' exercise of the
|
||||
rights granted herein. You are not responsible for enforcing compliance by
|
||||
third parties to this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues), conditions
|
||||
are imposed on you (whether by court order, agreement or otherwise) that
|
||||
contradict the conditions of this License, they do not excuse you from the
|
||||
conditions of this License. If you cannot distribute so as to satisfy
|
||||
simultaneously your obligations under this License and any other pertinent
|
||||
obligations, then as a consequence you may not distribute the Program at all.
|
||||
For example, if a patent license would not permit royalty-free redistribution
|
||||
of the Program by all those who receive copies directly or indirectly through
|
||||
you, then the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply and
|
||||
the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any patents or
|
||||
other property right claims or to contest validity of any such claims; this
|
||||
section has the sole purpose of protecting the integrity of the free software
|
||||
distribution system, which is implemented by public license practices. Many
|
||||
people have made generous contributions to the wide range of software
|
||||
distributed through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing to
|
||||
distribute software through any other system and a licensee cannot impose that
|
||||
choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to be a
|
||||
consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in certain
|
||||
countries either by patents or by copyrighted interfaces, the original
|
||||
copyright holder who places the Program under this License may add an explicit
|
||||
geographical distribution limitation excluding those countries, so that
|
||||
distribution is permitted only in or among countries not thus excluded. In
|
||||
such case, this License incorporates the limitation as if written in the body
|
||||
of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions of the
|
||||
General Public License from time to time. Such new versions will be similar in
|
||||
spirit to the present version, but may differ in detail to address new problems
|
||||
or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any later
|
||||
version", you have the option of following the terms and conditions either of
|
||||
that version or of any later version published by the Free Software Foundation.
|
||||
If the Program does not specify a version number of this License, you may
|
||||
choose any version ever published by the Free Software Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free programs
|
||||
whose distribution conditions are different, write to the author to ask for
|
||||
permission. For software which is copyrighted by the Free Software Foundation,
|
||||
write to the Free Software Foundation; we sometimes make exceptions for this.
|
||||
Our decision will be guided by the two goals of preserving the free status of
|
||||
all derivatives of our free software and of promoting the sharing and reuse of
|
||||
software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
|
||||
THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
|
||||
STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
|
||||
PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
|
||||
PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE,
|
||||
YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
|
||||
ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE
|
||||
PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
|
||||
INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
|
||||
BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER
|
||||
OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest possible
|
||||
use to the public, the best way to achieve this is to make it free software
|
||||
which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest to attach
|
||||
them to the start of each source file to most effectively convey the exclusion
|
||||
of warranty; and each file should have at least the "copyright" line and a
|
||||
pointer to where the full notice is found.
|
||||
|
||||
One line to give the program's name and a brief idea of what it does.
|
||||
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this when it
|
||||
starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author Gnomovision comes
|
||||
with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free
|
||||
software, and you are welcome to redistribute it under certain conditions;
|
||||
type 'show c' for details.
|
||||
|
||||
The hypothetical commands 'show w' and 'show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may be
|
||||
called something other than 'show w' and 'show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary. Here
|
||||
is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
'Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
signature of Ty Coon, 1 April 1989
|
||||
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General Public
|
||||
License instead of this License.
|
||||
|
||||
|
||||
"CLASSPATH" EXCEPTION TO THE GPL
|
||||
|
||||
Certain source files distributed by Oracle America and/or its affiliates are
|
||||
subject to the following clarification and special exception to the GPL, but
|
||||
only where Oracle has expressly included in the particular source file's header
|
||||
the words "Oracle designates this particular file as subject to the "Classpath"
|
||||
exception as provided by Oracle in the LICENSE file that accompanied this code."
|
||||
|
||||
Linking this library statically or dynamically with other modules is making
|
||||
a combined work based on this library. Thus, the terms and conditions of
|
||||
the GNU General Public License cover the whole combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent modules,
|
||||
and to copy and distribute the resulting executable under terms of your
|
||||
choice, provided that you also meet, for each linked independent module,
|
||||
the terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library. If
|
||||
you modify this library, you may extend this exception to your version of
|
||||
the library, but you are not obligated to do so. If you do not wish to do
|
||||
so, delete this exception statement from your version.
|
28
depends/pack200/anti200.cpp
Normal file
28
depends/pack200/anti200.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* This is trivial. Do what thou wilt with it. Public domain.
|
||||
*/
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
#include "unpack200.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc == 3)
|
||||
{
|
||||
try
|
||||
{
|
||||
unpack_200(argv[1], argv[2]);
|
||||
}
|
||||
catch (std::runtime_error &e)
|
||||
{
|
||||
std::cerr << "Bad things happened: " << e.what() << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
else
|
||||
std::cerr << "Simple pack200 unpacker!" << std::endl << "Run like this:" << std::endl
|
||||
<< " " << argv[0] << " input.jar.lzma output.jar" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
37
depends/pack200/include/unpack200.h
Normal file
37
depends/pack200/include/unpack200.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* @brief Unpack a PACK200 file
|
||||
*
|
||||
* @param input_path Path to the input file in PACK200 format. System native string encoding.
|
||||
* @param output_path Path to the output file in PACK200 format. System native string encoding.
|
||||
* @return void
|
||||
* @throw std::runtime_error for any error encountered
|
||||
*/
|
||||
void unpack_200(std::string input_path, std::string output_path);
|
425
depends/pack200/src/bands.cpp
Normal file
425
depends/pack200/src/bands.cpp
Normal file
@ -0,0 +1,425 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// -*- C++ -*-
|
||||
// Small program for unpacking specially compressed Java packages.
|
||||
// John R. Rose
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "defines.h"
|
||||
#include "bytes.h"
|
||||
#include "utils.h"
|
||||
#include "coding.h"
|
||||
#include "bands.h"
|
||||
|
||||
#include "constants.h"
|
||||
#include "unpack.h"
|
||||
|
||||
void band::readData(int expectedLength)
|
||||
{
|
||||
assert(expectedLength >= 0);
|
||||
assert(vs[0].cmk == cmk_ERROR);
|
||||
if (expectedLength != 0)
|
||||
{
|
||||
assert(length == 0);
|
||||
length = expectedLength;
|
||||
}
|
||||
if (length == 0)
|
||||
{
|
||||
assert((rplimit = cm.vs0.rp = u->rp) != nullptr);
|
||||
return;
|
||||
}
|
||||
assert(length > 0);
|
||||
|
||||
bool is_BYTE1 = (defc->spec == BYTE1_spec);
|
||||
|
||||
if (is_BYTE1)
|
||||
{
|
||||
// No possibility of coding change. Sizing is exact.
|
||||
u->ensure_input(length);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make a conservatively generous estimate of band size in bytes.
|
||||
// Assume B == 5 everywhere.
|
||||
// Assume awkward pop with all {U} values (2*5 per value)
|
||||
int64_t generous = (int64_t)length * (B_MAX * 3 + 1) + C_SLOP;
|
||||
u->ensure_input(generous);
|
||||
}
|
||||
|
||||
// Read one value to see what it might be.
|
||||
int XB = _meta_default;
|
||||
int cp1 = 0, cp2 = 0;
|
||||
if (!is_BYTE1)
|
||||
{
|
||||
// must be a variable-length coding
|
||||
assert(defc->B() > 1 && defc->L() > 0);
|
||||
|
||||
value_stream xvs;
|
||||
coding *valc = defc;
|
||||
if (valc->D() != 0)
|
||||
{
|
||||
valc = coding::findBySpec(defc->B(), defc->H(), defc->S());
|
||||
assert(!valc->isMalloc);
|
||||
}
|
||||
xvs.init(u->rp, u->rplimit, valc);
|
||||
int X = xvs.getInt();
|
||||
if (valc->S() != 0)
|
||||
{
|
||||
assert(valc->min <= -256);
|
||||
XB = -1 - X;
|
||||
}
|
||||
else
|
||||
{
|
||||
int L = valc->L();
|
||||
assert(valc->max >= L + 255);
|
||||
XB = X - L;
|
||||
}
|
||||
if (0 <= XB && XB < 256)
|
||||
{
|
||||
// Skip over the escape value.
|
||||
u->rp = xvs.rp;
|
||||
cp1 = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No, it's still default.
|
||||
XB = _meta_default;
|
||||
}
|
||||
}
|
||||
|
||||
if (XB <= _meta_canon_max)
|
||||
{
|
||||
byte XB_byte = (byte)XB;
|
||||
byte *XB_ptr = &XB_byte;
|
||||
cm.init(u->rp, u->rplimit, XB_ptr, 0, defc, length, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(u->meta_rp != nullptr);
|
||||
// Scribble the initial byte onto the band.
|
||||
byte *save_meta_rp = --u->meta_rp;
|
||||
byte save_meta_xb = (*save_meta_rp);
|
||||
(*save_meta_rp) = (byte)XB;
|
||||
cm.init(u->rp, u->rplimit, u->meta_rp, 0, defc, length, nullptr);
|
||||
(*save_meta_rp) = save_meta_xb; // put it back, just to be tidy
|
||||
}
|
||||
rplimit = u->rp;
|
||||
|
||||
rewind();
|
||||
}
|
||||
|
||||
void band::setIndex(cpindex *ix_)
|
||||
{
|
||||
assert(ix_ == nullptr || ixTag == ix_->ixTag);
|
||||
ix = ix_;
|
||||
}
|
||||
void band::setIndexByTag(byte tag)
|
||||
{
|
||||
setIndex(u->cp.getIndex(tag));
|
||||
}
|
||||
|
||||
entry *band::getRefCommon(cpindex *ix_, bool nullOKwithCaller)
|
||||
{
|
||||
assert(ix_->ixTag == ixTag ||
|
||||
(ixTag == CONSTANT_Literal && ix_->ixTag >= CONSTANT_Integer &&
|
||||
ix_->ixTag <= CONSTANT_String));
|
||||
int n = vs[0].getInt() - nullOK;
|
||||
// Note: band-local nullOK means nullptr encodes as 0.
|
||||
// But nullOKwithCaller means caller is willing to tolerate a nullptr.
|
||||
entry *ref = ix_->get(n);
|
||||
if (ref == nullptr && !(nullOKwithCaller && n == -1))
|
||||
unpack_abort(n == -1 ? "nullptr ref" : "bad ref");
|
||||
return ref;
|
||||
}
|
||||
|
||||
int64_t band::getLong(band &lo_band, bool have_hi)
|
||||
{
|
||||
band &hi_band = (*this);
|
||||
assert(lo_band.bn == hi_band.bn + 1);
|
||||
uint32_t lo = lo_band.getInt();
|
||||
if (!have_hi)
|
||||
{
|
||||
assert(hi_band.length == 0);
|
||||
return makeLong(0, lo);
|
||||
}
|
||||
uint32_t hi = hi_band.getInt();
|
||||
return makeLong(hi, lo);
|
||||
}
|
||||
|
||||
int band::getIntTotal()
|
||||
{
|
||||
if (length == 0)
|
||||
return 0;
|
||||
if (total_memo > 0)
|
||||
return total_memo - 1;
|
||||
int total = getInt();
|
||||
// overflow checks require that none of the addends are <0,
|
||||
// and that the partial sums never overflow (wrap negative)
|
||||
if (total < 0)
|
||||
{
|
||||
unpack_abort("overflow detected");
|
||||
}
|
||||
for (int k = length - 1; k > 0; k--)
|
||||
{
|
||||
int prev_total = total;
|
||||
total += vs[0].getInt();
|
||||
if (total < prev_total)
|
||||
{
|
||||
unpack_abort("overflow detected");
|
||||
}
|
||||
}
|
||||
rewind();
|
||||
total_memo = total + 1;
|
||||
return total;
|
||||
}
|
||||
|
||||
int band::getIntCount(int tag)
|
||||
{
|
||||
if (length == 0)
|
||||
return 0;
|
||||
if (tag >= HIST0_MIN && tag <= HIST0_MAX)
|
||||
{
|
||||
if (hist0 == nullptr)
|
||||
{
|
||||
// Lazily calculate an approximate histogram.
|
||||
hist0 = U_NEW(int, (HIST0_MAX - HIST0_MIN) + 1);
|
||||
for (int k = length; k > 0; k--)
|
||||
{
|
||||
int x = vs[0].getInt();
|
||||
if (x >= HIST0_MIN && x <= HIST0_MAX)
|
||||
hist0[x - HIST0_MIN] += 1;
|
||||
}
|
||||
rewind();
|
||||
}
|
||||
return hist0[tag - HIST0_MIN];
|
||||
}
|
||||
int total = 0;
|
||||
for (int k = length; k > 0; k--)
|
||||
{
|
||||
total += (vs[0].getInt() == tag) ? 1 : 0;
|
||||
}
|
||||
rewind();
|
||||
return total;
|
||||
}
|
||||
|
||||
#define INDEX_INIT(tag, nullOK, subindex) ((tag) + (subindex) * SUBINDEX_BIT + (nullOK) * 256)
|
||||
|
||||
#define INDEX(tag) INDEX_INIT(tag, 0, 0)
|
||||
#define NULL_OR_INDEX(tag) INDEX_INIT(tag, 1, 0)
|
||||
#define SUB_INDEX(tag) INDEX_INIT(tag, 0, 1)
|
||||
#define NO_INDEX 0
|
||||
|
||||
struct band_init
|
||||
{
|
||||
int defc;
|
||||
int index;
|
||||
};
|
||||
|
||||
#define BAND_INIT(name, cspec, ix) \
|
||||
{ \
|
||||
cspec, ix \
|
||||
}
|
||||
|
||||
const band_init all_band_inits[] =
|
||||
{
|
||||
// BAND_INIT(archive_magic, BYTE1_spec, 0),
|
||||
// BAND_INIT(archive_header, UNSIGNED5_spec, 0),
|
||||
// BAND_INIT(band_headers, BYTE1_spec, 0),
|
||||
BAND_INIT(cp_Utf8_prefix, DELTA5_spec, 0), BAND_INIT(cp_Utf8_suffix, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(cp_Utf8_chars, CHAR3_spec, 0), BAND_INIT(cp_Utf8_big_suffix, DELTA5_spec, 0),
|
||||
BAND_INIT(cp_Utf8_big_chars, DELTA5_spec, 0), BAND_INIT(cp_Int, UDELTA5_spec, 0),
|
||||
BAND_INIT(cp_Float, UDELTA5_spec, 0), BAND_INIT(cp_Long_hi, UDELTA5_spec, 0),
|
||||
BAND_INIT(cp_Long_lo, DELTA5_spec, 0), BAND_INIT(cp_Double_hi, UDELTA5_spec, 0),
|
||||
BAND_INIT(cp_Double_lo, DELTA5_spec, 0),
|
||||
BAND_INIT(cp_String, UDELTA5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(cp_Class, UDELTA5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(cp_Signature_form, DELTA5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(cp_Signature_classes, UDELTA5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(cp_Descr_name, DELTA5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(cp_Descr_type, UDELTA5_spec, INDEX(CONSTANT_Signature)),
|
||||
BAND_INIT(cp_Field_class, DELTA5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(cp_Field_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
|
||||
BAND_INIT(cp_Method_class, DELTA5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(cp_Method_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
|
||||
BAND_INIT(cp_Imethod_class, DELTA5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(cp_Imethod_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
|
||||
BAND_INIT(attr_definition_headers, BYTE1_spec, 0),
|
||||
BAND_INIT(attr_definition_name, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(attr_definition_layout, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(ic_this_class, UDELTA5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(ic_flags, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(ic_outer_class, DELTA5_spec, NULL_OR_INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(ic_name, DELTA5_spec, NULL_OR_INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(class_this, DELTA5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(class_super, DELTA5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(class_interface_count, DELTA5_spec, 0),
|
||||
BAND_INIT(class_interface, DELTA5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(class_field_count, DELTA5_spec, 0),
|
||||
BAND_INIT(class_method_count, DELTA5_spec, 0),
|
||||
BAND_INIT(field_descr, DELTA5_spec, INDEX(CONSTANT_NameandType)),
|
||||
BAND_INIT(field_flags_hi, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(field_flags_lo, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(field_attr_count, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(field_attr_indexes, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(field_attr_calls, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(field_ConstantValue_KQ, UNSIGNED5_spec, INDEX(CONSTANT_Literal)),
|
||||
BAND_INIT(field_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
|
||||
BAND_INIT(field_metadata_bands, -1, -1), BAND_INIT(field_attr_bands, -1, -1),
|
||||
BAND_INIT(method_descr, MDELTA5_spec, INDEX(CONSTANT_NameandType)),
|
||||
BAND_INIT(method_flags_hi, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(method_flags_lo, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(method_attr_count, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(method_attr_indexes, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(method_attr_calls, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(method_Exceptions_N, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(method_Exceptions_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(method_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
|
||||
BAND_INIT(method_metadata_bands, -1, -1), BAND_INIT(method_attr_bands, -1, -1),
|
||||
BAND_INIT(class_flags_hi, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_flags_lo, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_attr_count, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_attr_indexes, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_attr_calls, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_SourceFile_RUN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(class_EnclosingMethod_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(class_EnclosingMethod_RDN, UNSIGNED5_spec,
|
||||
NULL_OR_INDEX(CONSTANT_NameandType)),
|
||||
BAND_INIT(class_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
|
||||
BAND_INIT(class_metadata_bands, -1, -1),
|
||||
BAND_INIT(class_InnerClasses_N, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_InnerClasses_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(class_InnerClasses_F, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_InnerClasses_outer_RCN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(class_InnerClasses_name_RUN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(class_ClassFile_version_minor_H, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_ClassFile_version_major_H, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_attr_bands, -1, -1), BAND_INIT(code_headers, BYTE1_spec, 0),
|
||||
BAND_INIT(code_max_stack, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_max_na_locals, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_handler_count, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_handler_start_P, BCI5_spec, 0),
|
||||
BAND_INIT(code_handler_end_PO, BRANCH5_spec, 0),
|
||||
BAND_INIT(code_handler_catch_PO, BRANCH5_spec, 0),
|
||||
BAND_INIT(code_handler_class_RCN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(code_flags_hi, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_flags_lo, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_attr_count, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_attr_indexes, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_attr_calls, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_StackMapTable_N, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_StackMapTable_frame_T, BYTE1_spec, 0),
|
||||
BAND_INIT(code_StackMapTable_local_N, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_StackMapTable_stack_N, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_StackMapTable_offset, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_StackMapTable_T, BYTE1_spec, 0),
|
||||
BAND_INIT(code_StackMapTable_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(code_StackMapTable_P, BCI5_spec, 0),
|
||||
BAND_INIT(code_LineNumberTable_N, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_LineNumberTable_bci_P, BCI5_spec, 0),
|
||||
BAND_INIT(code_LineNumberTable_line, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_LocalVariableTable_N, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_LocalVariableTable_bci_P, BCI5_spec, 0),
|
||||
BAND_INIT(code_LocalVariableTable_span_O, BRANCH5_spec, 0),
|
||||
BAND_INIT(code_LocalVariableTable_name_RU, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(code_LocalVariableTable_type_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
|
||||
BAND_INIT(code_LocalVariableTable_slot, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_LocalVariableTypeTable_N, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_LocalVariableTypeTable_bci_P, BCI5_spec, 0),
|
||||
BAND_INIT(code_LocalVariableTypeTable_span_O, BRANCH5_spec, 0),
|
||||
BAND_INIT(code_LocalVariableTypeTable_name_RU, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(code_LocalVariableTypeTable_type_RS, UNSIGNED5_spec,
|
||||
INDEX(CONSTANT_Signature)),
|
||||
BAND_INIT(code_LocalVariableTypeTable_slot, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_attr_bands, -1, -1), BAND_INIT(bc_codes, BYTE1_spec, 0),
|
||||
BAND_INIT(bc_case_count, UNSIGNED5_spec, 0), BAND_INIT(bc_case_value, DELTA5_spec, 0),
|
||||
BAND_INIT(bc_byte, BYTE1_spec, 0), BAND_INIT(bc_short, DELTA5_spec, 0),
|
||||
BAND_INIT(bc_local, UNSIGNED5_spec, 0), BAND_INIT(bc_label, BRANCH5_spec, 0),
|
||||
BAND_INIT(bc_intref, DELTA5_spec, INDEX(CONSTANT_Integer)),
|
||||
BAND_INIT(bc_floatref, DELTA5_spec, INDEX(CONSTANT_Float)),
|
||||
BAND_INIT(bc_longref, DELTA5_spec, INDEX(CONSTANT_Long)),
|
||||
BAND_INIT(bc_doubleref, DELTA5_spec, INDEX(CONSTANT_Double)),
|
||||
BAND_INIT(bc_stringref, DELTA5_spec, INDEX(CONSTANT_String)),
|
||||
BAND_INIT(bc_classref, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(bc_fieldref, DELTA5_spec, INDEX(CONSTANT_Fieldref)),
|
||||
BAND_INIT(bc_methodref, UNSIGNED5_spec, INDEX(CONSTANT_Methodref)),
|
||||
BAND_INIT(bc_imethodref, DELTA5_spec, INDEX(CONSTANT_InterfaceMethodref)),
|
||||
BAND_INIT(bc_thisfield, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Fieldref)),
|
||||
BAND_INIT(bc_superfield, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Fieldref)),
|
||||
BAND_INIT(bc_thismethod, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)),
|
||||
BAND_INIT(bc_supermethod, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)),
|
||||
BAND_INIT(bc_initref, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)),
|
||||
BAND_INIT(bc_escref, UNSIGNED5_spec, INDEX(CONSTANT_All)),
|
||||
BAND_INIT(bc_escrefsize, UNSIGNED5_spec, 0), BAND_INIT(bc_escsize, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(bc_escbyte, BYTE1_spec, 0),
|
||||
BAND_INIT(file_name, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(file_size_hi, UNSIGNED5_spec, 0), BAND_INIT(file_size_lo, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(file_modtime, DELTA5_spec, 0), BAND_INIT(file_options, UNSIGNED5_spec, 0),
|
||||
// BAND_INIT(file_bits, BYTE1_spec, 0),
|
||||
{0, 0}};
|
||||
|
||||
band *band::makeBands(unpacker *u)
|
||||
{
|
||||
band *tmp_all_bands = U_NEW(band, BAND_LIMIT);
|
||||
for (int i = 0; i < BAND_LIMIT; i++)
|
||||
{
|
||||
assert((byte *)&all_band_inits[i + 1] <
|
||||
(byte *)all_band_inits + sizeof(all_band_inits));
|
||||
const band_init &bi = all_band_inits[i];
|
||||
band &b = tmp_all_bands[i];
|
||||
coding *defc = coding::findBySpec(bi.defc);
|
||||
assert((defc == nullptr) == (bi.defc == -1)); // no garbage, please
|
||||
assert(defc == nullptr || !defc->isMalloc);
|
||||
b.init(u, i, defc);
|
||||
if (bi.index > 0)
|
||||
{
|
||||
b.nullOK = ((bi.index >> 8) & 1);
|
||||
b.ixTag = (bi.index & 0xFF);
|
||||
}
|
||||
}
|
||||
return tmp_all_bands;
|
||||
}
|
||||
|
||||
void band::initIndexes(unpacker *u)
|
||||
{
|
||||
band *tmp_all_bands = u->all_bands;
|
||||
for (int i = 0; i < BAND_LIMIT; i++)
|
||||
{
|
||||
band *scan = &tmp_all_bands[i];
|
||||
uint32_t tag = scan->ixTag; // Cf. #define INDEX(tag) above
|
||||
if (tag != 0 && tag != CONSTANT_Literal && (tag & SUBINDEX_BIT) == 0)
|
||||
{
|
||||
scan->setIndex(u->cp.getIndex(tag));
|
||||
}
|
||||
}
|
||||
}
|
489
depends/pack200/src/bands.h
Normal file
489
depends/pack200/src/bands.h
Normal file
@ -0,0 +1,489 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// -*- C++ -*-
|
||||
struct entry;
|
||||
struct cpindex;
|
||||
struct unpacker;
|
||||
|
||||
struct band
|
||||
{
|
||||
int bn; // band_number of this band
|
||||
coding *defc; // default coding method
|
||||
cpindex *ix; // CP entry mapping, if CPRefBand
|
||||
byte ixTag; // 0 or 1; nullptr is coded as (nullOK?0:-1)
|
||||
byte nullOK; // 0 or 1; nullptr is coded as (nullOK?0:-1)
|
||||
int length; // expected # values
|
||||
unpacker *u; // back pointer
|
||||
|
||||
value_stream vs[2]; // source of values
|
||||
coding_method cm; // method used for initial state of vs[0]
|
||||
byte *rplimit; // end of band (encoded, transmitted)
|
||||
|
||||
int total_memo; // cached value of getIntTotal, or -1
|
||||
int *hist0; // approximate. histogram
|
||||
enum
|
||||
{
|
||||
HIST0_MIN = 0,
|
||||
HIST0_MAX = 255
|
||||
}; // catches the usual cases
|
||||
|
||||
// properties for attribute layout elements:
|
||||
byte le_kind; // EK_XXX
|
||||
byte le_bci; // 0,EK_BCI,EK_BCD,EK_BCO
|
||||
byte le_back; // ==EF_BACK
|
||||
byte le_len; // 0,1,2,4 (size in classfile), or call addr
|
||||
band **le_body; // body of repl, union, call (nullptr-terminated)
|
||||
// Note: EK_CASE elements use hist0 to record union tags.
|
||||
#define le_casetags hist0
|
||||
|
||||
band &nextBand()
|
||||
{
|
||||
return this[1];
|
||||
}
|
||||
band &prevBand()
|
||||
{
|
||||
return this[-1];
|
||||
}
|
||||
|
||||
void init(unpacker *u_, int bn_, coding *defc_)
|
||||
{
|
||||
u = u_;
|
||||
cm.u = u_;
|
||||
bn = bn_;
|
||||
defc = defc_;
|
||||
}
|
||||
void init(unpacker *u_, int bn_, int defcSpec)
|
||||
{
|
||||
init(u_, bn_, coding::findBySpec(defcSpec));
|
||||
}
|
||||
void initRef(int ixTag_ = 0, bool nullOK_ = false)
|
||||
{
|
||||
ixTag = ixTag_;
|
||||
nullOK = nullOK_;
|
||||
setIndexByTag(ixTag);
|
||||
}
|
||||
|
||||
void expectMoreLength(int l)
|
||||
{
|
||||
assert(length >= 0); // able to accept a length
|
||||
assert((int)l >= 0); // no overflow
|
||||
assert(rplimit == nullptr); // readData not yet called
|
||||
length += l;
|
||||
assert(length >= l); // no overflow
|
||||
}
|
||||
|
||||
void setIndex(cpindex *ix_);
|
||||
void setIndexByTag(byte tag);
|
||||
|
||||
// Parse the band and its meta-coding header.
|
||||
void readData(int expectedLength = 0);
|
||||
|
||||
// Reset the band for another pass (Cf. Java Band.resetForSecondPass.)
|
||||
void rewind()
|
||||
{
|
||||
cm.reset(&vs[0]);
|
||||
}
|
||||
|
||||
byte *&curRP()
|
||||
{
|
||||
return vs[0].rp;
|
||||
}
|
||||
byte *minRP()
|
||||
{
|
||||
return cm.vs0.rp;
|
||||
}
|
||||
byte *maxRP()
|
||||
{
|
||||
return rplimit;
|
||||
}
|
||||
size_t size()
|
||||
{
|
||||
return maxRP() - minRP();
|
||||
}
|
||||
|
||||
int getByte()
|
||||
{
|
||||
assert(ix == nullptr);
|
||||
return vs[0].getByte();
|
||||
}
|
||||
int getInt()
|
||||
{
|
||||
assert(ix == nullptr);
|
||||
return vs[0].getInt();
|
||||
}
|
||||
entry *getRefN()
|
||||
{
|
||||
assert(ix != nullptr);
|
||||
return getRefCommon(ix, true);
|
||||
}
|
||||
entry *getRef()
|
||||
{
|
||||
assert(ix != nullptr);
|
||||
return getRefCommon(ix, false);
|
||||
}
|
||||
entry *getRefUsing(cpindex *ix2)
|
||||
{
|
||||
assert(ix == nullptr);
|
||||
return getRefCommon(ix2, true);
|
||||
}
|
||||
entry *getRefCommon(cpindex *ix, bool nullOK);
|
||||
int64_t getLong(band &lo_band, bool have_hi);
|
||||
|
||||
static int64_t makeLong(uint32_t hi, uint32_t lo)
|
||||
{
|
||||
return ((uint64_t)hi << 32) + (((uint64_t)lo << 32) >> 32);
|
||||
}
|
||||
|
||||
int getIntTotal();
|
||||
int getIntCount(int tag);
|
||||
|
||||
static band *makeBands(unpacker *u);
|
||||
static void initIndexes(unpacker *u);
|
||||
};
|
||||
|
||||
extern band all_bands[];
|
||||
|
||||
#define BAND_LOCAL /* \
|
||||
band* band_temp = all_bands; \
|
||||
band* all_bands = band_temp */
|
||||
|
||||
// Band schema:
|
||||
enum band_number
|
||||
{
|
||||
// e_archive_magic,
|
||||
// e_archive_header,
|
||||
// e_band_headers,
|
||||
|
||||
// constant pool contents
|
||||
e_cp_Utf8_prefix,
|
||||
e_cp_Utf8_suffix,
|
||||
e_cp_Utf8_chars,
|
||||
e_cp_Utf8_big_suffix,
|
||||
e_cp_Utf8_big_chars,
|
||||
e_cp_Int,
|
||||
e_cp_Float,
|
||||
e_cp_Long_hi,
|
||||
e_cp_Long_lo,
|
||||
e_cp_Double_hi,
|
||||
e_cp_Double_lo,
|
||||
e_cp_String,
|
||||
e_cp_Class,
|
||||
e_cp_Signature_form,
|
||||
e_cp_Signature_classes,
|
||||
e_cp_Descr_name,
|
||||
e_cp_Descr_type,
|
||||
e_cp_Field_class,
|
||||
e_cp_Field_desc,
|
||||
e_cp_Method_class,
|
||||
e_cp_Method_desc,
|
||||
e_cp_Imethod_class,
|
||||
e_cp_Imethod_desc,
|
||||
|
||||
// bands which define transmission of attributes
|
||||
e_attr_definition_headers,
|
||||
e_attr_definition_name,
|
||||
e_attr_definition_layout,
|
||||
|
||||
// band for hardwired InnerClasses attribute (shared across the package)
|
||||
e_ic_this_class,
|
||||
e_ic_flags,
|
||||
// These bands contain data only where flags sets ACC_IC_LONG_FORM:
|
||||
e_ic_outer_class,
|
||||
e_ic_name,
|
||||
|
||||
// bands for carrying class schema information:
|
||||
e_class_this,
|
||||
e_class_super,
|
||||
e_class_interface_count,
|
||||
e_class_interface,
|
||||
|
||||
// bands for class members
|
||||
e_class_field_count,
|
||||
e_class_method_count,
|
||||
e_field_descr,
|
||||
e_field_flags_hi,
|
||||
e_field_flags_lo,
|
||||
e_field_attr_count,
|
||||
e_field_attr_indexes,
|
||||
e_field_attr_calls,
|
||||
e_field_ConstantValue_KQ,
|
||||
e_field_Signature_RS,
|
||||
e_field_metadata_bands,
|
||||
e_field_attr_bands,
|
||||
e_method_descr,
|
||||
e_method_flags_hi,
|
||||
e_method_flags_lo,
|
||||
e_method_attr_count,
|
||||
e_method_attr_indexes,
|
||||
e_method_attr_calls,
|
||||
e_method_Exceptions_N,
|
||||
e_method_Exceptions_RC,
|
||||
e_method_Signature_RS,
|
||||
e_method_metadata_bands,
|
||||
e_method_attr_bands,
|
||||
e_class_flags_hi,
|
||||
e_class_flags_lo,
|
||||
e_class_attr_count,
|
||||
e_class_attr_indexes,
|
||||
e_class_attr_calls,
|
||||
e_class_SourceFile_RUN,
|
||||
e_class_EnclosingMethod_RC,
|
||||
e_class_EnclosingMethod_RDN,
|
||||
e_class_Signature_RS,
|
||||
e_class_metadata_bands,
|
||||
e_class_InnerClasses_N,
|
||||
e_class_InnerClasses_RC,
|
||||
e_class_InnerClasses_F,
|
||||
e_class_InnerClasses_outer_RCN,
|
||||
e_class_InnerClasses_name_RUN,
|
||||
e_class_ClassFile_version_minor_H,
|
||||
e_class_ClassFile_version_major_H,
|
||||
e_class_attr_bands,
|
||||
e_code_headers,
|
||||
e_code_max_stack,
|
||||
e_code_max_na_locals,
|
||||
e_code_handler_count,
|
||||
e_code_handler_start_P,
|
||||
e_code_handler_end_PO,
|
||||
e_code_handler_catch_PO,
|
||||
e_code_handler_class_RCN,
|
||||
|
||||
// code attributes
|
||||
e_code_flags_hi,
|
||||
e_code_flags_lo,
|
||||
e_code_attr_count,
|
||||
e_code_attr_indexes,
|
||||
e_code_attr_calls,
|
||||
e_code_StackMapTable_N,
|
||||
e_code_StackMapTable_frame_T,
|
||||
e_code_StackMapTable_local_N,
|
||||
e_code_StackMapTable_stack_N,
|
||||
e_code_StackMapTable_offset,
|
||||
e_code_StackMapTable_T,
|
||||
e_code_StackMapTable_RC,
|
||||
e_code_StackMapTable_P,
|
||||
e_code_LineNumberTable_N,
|
||||
e_code_LineNumberTable_bci_P,
|
||||
e_code_LineNumberTable_line,
|
||||
e_code_LocalVariableTable_N,
|
||||
e_code_LocalVariableTable_bci_P,
|
||||
e_code_LocalVariableTable_span_O,
|
||||
e_code_LocalVariableTable_name_RU,
|
||||
e_code_LocalVariableTable_type_RS,
|
||||
e_code_LocalVariableTable_slot,
|
||||
e_code_LocalVariableTypeTable_N,
|
||||
e_code_LocalVariableTypeTable_bci_P,
|
||||
e_code_LocalVariableTypeTable_span_O,
|
||||
e_code_LocalVariableTypeTable_name_RU,
|
||||
e_code_LocalVariableTypeTable_type_RS,
|
||||
e_code_LocalVariableTypeTable_slot,
|
||||
e_code_attr_bands,
|
||||
|
||||
// bands for bytecodes
|
||||
e_bc_codes,
|
||||
// remaining bands provide typed opcode fields required by the bc_codes
|
||||
e_bc_case_count,
|
||||
e_bc_case_value,
|
||||
e_bc_byte,
|
||||
e_bc_short,
|
||||
e_bc_local,
|
||||
e_bc_label,
|
||||
|
||||
// ldc* operands:
|
||||
e_bc_intref,
|
||||
e_bc_floatref,
|
||||
e_bc_longref,
|
||||
e_bc_doubleref,
|
||||
e_bc_stringref,
|
||||
e_bc_classref,
|
||||
e_bc_fieldref,
|
||||
e_bc_methodref,
|
||||
e_bc_imethodref,
|
||||
|
||||
// _self_linker_op family
|
||||
e_bc_thisfield,
|
||||
e_bc_superfield,
|
||||
e_bc_thismethod,
|
||||
e_bc_supermethod,
|
||||
|
||||
// bc_invokeinit family:
|
||||
e_bc_initref,
|
||||
|
||||
// bytecode escape sequences
|
||||
e_bc_escref,
|
||||
e_bc_escrefsize,
|
||||
e_bc_escsize,
|
||||
e_bc_escbyte,
|
||||
|
||||
// file attributes and contents
|
||||
e_file_name,
|
||||
e_file_size_hi,
|
||||
e_file_size_lo,
|
||||
e_file_modtime,
|
||||
e_file_options,
|
||||
// e_file_bits, // handled specially as an appendix
|
||||
BAND_LIMIT
|
||||
};
|
||||
|
||||
// Symbolic names for bands, as if in a giant global struct:
|
||||
//#define archive_magic all_bands[e_archive_magic]
|
||||
//#define archive_header all_bands[e_archive_header]
|
||||
//#define band_headers all_bands[e_band_headers]
|
||||
#define cp_Utf8_prefix all_bands[e_cp_Utf8_prefix]
|
||||
#define cp_Utf8_suffix all_bands[e_cp_Utf8_suffix]
|
||||
#define cp_Utf8_chars all_bands[e_cp_Utf8_chars]
|
||||
#define cp_Utf8_big_suffix all_bands[e_cp_Utf8_big_suffix]
|
||||
#define cp_Utf8_big_chars all_bands[e_cp_Utf8_big_chars]
|
||||
#define cp_Int all_bands[e_cp_Int]
|
||||
#define cp_Float all_bands[e_cp_Float]
|
||||
#define cp_Long_hi all_bands[e_cp_Long_hi]
|
||||
#define cp_Long_lo all_bands[e_cp_Long_lo]
|
||||
#define cp_Double_hi all_bands[e_cp_Double_hi]
|
||||
#define cp_Double_lo all_bands[e_cp_Double_lo]
|
||||
#define cp_String all_bands[e_cp_String]
|
||||
#define cp_Class all_bands[e_cp_Class]
|
||||
#define cp_Signature_form all_bands[e_cp_Signature_form]
|
||||
#define cp_Signature_classes all_bands[e_cp_Signature_classes]
|
||||
#define cp_Descr_name all_bands[e_cp_Descr_name]
|
||||
#define cp_Descr_type all_bands[e_cp_Descr_type]
|
||||
#define cp_Field_class all_bands[e_cp_Field_class]
|
||||
#define cp_Field_desc all_bands[e_cp_Field_desc]
|
||||
#define cp_Method_class all_bands[e_cp_Method_class]
|
||||
#define cp_Method_desc all_bands[e_cp_Method_desc]
|
||||
#define cp_Imethod_class all_bands[e_cp_Imethod_class]
|
||||
#define cp_Imethod_desc all_bands[e_cp_Imethod_desc]
|
||||
#define attr_definition_headers all_bands[e_attr_definition_headers]
|
||||
#define attr_definition_name all_bands[e_attr_definition_name]
|
||||
#define attr_definition_layout all_bands[e_attr_definition_layout]
|
||||
#define ic_this_class all_bands[e_ic_this_class]
|
||||
#define ic_flags all_bands[e_ic_flags]
|
||||
#define ic_outer_class all_bands[e_ic_outer_class]
|
||||
#define ic_name all_bands[e_ic_name]
|
||||
#define class_this all_bands[e_class_this]
|
||||
#define class_super all_bands[e_class_super]
|
||||
#define class_interface_count all_bands[e_class_interface_count]
|
||||
#define class_interface all_bands[e_class_interface]
|
||||
#define class_field_count all_bands[e_class_field_count]
|
||||
#define class_method_count all_bands[e_class_method_count]
|
||||
#define field_descr all_bands[e_field_descr]
|
||||
#define field_flags_hi all_bands[e_field_flags_hi]
|
||||
#define field_flags_lo all_bands[e_field_flags_lo]
|
||||
#define field_attr_count all_bands[e_field_attr_count]
|
||||
#define field_attr_indexes all_bands[e_field_attr_indexes]
|
||||
#define field_ConstantValue_KQ all_bands[e_field_ConstantValue_KQ]
|
||||
#define field_Signature_RS all_bands[e_field_Signature_RS]
|
||||
#define field_attr_bands all_bands[e_field_attr_bands]
|
||||
#define method_descr all_bands[e_method_descr]
|
||||
#define method_flags_hi all_bands[e_method_flags_hi]
|
||||
#define method_flags_lo all_bands[e_method_flags_lo]
|
||||
#define method_attr_count all_bands[e_method_attr_count]
|
||||
#define method_attr_indexes all_bands[e_method_attr_indexes]
|
||||
#define method_Exceptions_N all_bands[e_method_Exceptions_N]
|
||||
#define method_Exceptions_RC all_bands[e_method_Exceptions_RC]
|
||||
#define method_Signature_RS all_bands[e_method_Signature_RS]
|
||||
#define method_attr_bands all_bands[e_method_attr_bands]
|
||||
#define class_flags_hi all_bands[e_class_flags_hi]
|
||||
#define class_flags_lo all_bands[e_class_flags_lo]
|
||||
#define class_attr_count all_bands[e_class_attr_count]
|
||||
#define class_attr_indexes all_bands[e_class_attr_indexes]
|
||||
#define class_SourceFile_RUN all_bands[e_class_SourceFile_RUN]
|
||||
#define class_EnclosingMethod_RC all_bands[e_class_EnclosingMethod_RC]
|
||||
#define class_EnclosingMethod_RDN all_bands[e_class_EnclosingMethod_RDN]
|
||||
#define class_Signature_RS all_bands[e_class_Signature_RS]
|
||||
#define class_InnerClasses_N all_bands[e_class_InnerClasses_N]
|
||||
#define class_InnerClasses_RC all_bands[e_class_InnerClasses_RC]
|
||||
#define class_InnerClasses_F all_bands[e_class_InnerClasses_F]
|
||||
#define class_InnerClasses_outer_RCN all_bands[e_class_InnerClasses_outer_RCN]
|
||||
#define class_InnerClasses_name_RUN all_bands[e_class_InnerClasses_name_RUN]
|
||||
#define class_ClassFile_version_minor_H all_bands[e_class_ClassFile_version_minor_H]
|
||||
#define class_ClassFile_version_major_H all_bands[e_class_ClassFile_version_major_H]
|
||||
#define class_attr_bands all_bands[e_class_attr_bands]
|
||||
#define code_headers all_bands[e_code_headers]
|
||||
#define code_max_stack all_bands[e_code_max_stack]
|
||||
#define code_max_na_locals all_bands[e_code_max_na_locals]
|
||||
#define code_handler_count all_bands[e_code_handler_count]
|
||||
#define code_handler_start_P all_bands[e_code_handler_start_P]
|
||||
#define code_handler_end_PO all_bands[e_code_handler_end_PO]
|
||||
#define code_handler_catch_PO all_bands[e_code_handler_catch_PO]
|
||||
#define code_handler_class_RCN all_bands[e_code_handler_class_RCN]
|
||||
#define code_flags_hi all_bands[e_code_flags_hi]
|
||||
#define code_flags_lo all_bands[e_code_flags_lo]
|
||||
#define code_attr_count all_bands[e_code_attr_count]
|
||||
#define code_attr_indexes all_bands[e_code_attr_indexes]
|
||||
#define code_StackMapTable_N all_bands[e_code_StackMapTable_N]
|
||||
#define code_StackMapTable_frame_T all_bands[e_code_StackMapTable_frame_T]
|
||||
#define code_StackMapTable_local_N all_bands[e_code_StackMapTable_local_N]
|
||||
#define code_StackMapTable_stack_N all_bands[e_code_StackMapTable_stack_N]
|
||||
#define code_StackMapTable_offset all_bands[e_code_StackMapTable_offset]
|
||||
#define code_StackMapTable_T all_bands[e_code_StackMapTable_T]
|
||||
#define code_StackMapTable_RC all_bands[e_code_StackMapTable_RC]
|
||||
#define code_StackMapTable_P all_bands[e_code_StackMapTable_P]
|
||||
#define code_LineNumberTable_N all_bands[e_code_LineNumberTable_N]
|
||||
#define code_LineNumberTable_bci_P all_bands[e_code_LineNumberTable_bci_P]
|
||||
#define code_LineNumberTable_line all_bands[e_code_LineNumberTable_line]
|
||||
#define code_LocalVariableTable_N all_bands[e_code_LocalVariableTable_N]
|
||||
#define code_LocalVariableTable_bci_P all_bands[e_code_LocalVariableTable_bci_P]
|
||||
#define code_LocalVariableTable_span_O all_bands[e_code_LocalVariableTable_span_O]
|
||||
#define code_LocalVariableTable_name_RU all_bands[e_code_LocalVariableTable_name_RU]
|
||||
#define code_LocalVariableTable_type_RS all_bands[e_code_LocalVariableTable_type_RS]
|
||||
#define code_LocalVariableTable_slot all_bands[e_code_LocalVariableTable_slot]
|
||||
#define code_LocalVariableTypeTable_N all_bands[e_code_LocalVariableTypeTable_N]
|
||||
#define code_LocalVariableTypeTable_bci_P all_bands[e_code_LocalVariableTypeTable_bci_P]
|
||||
#define code_LocalVariableTypeTable_span_O all_bands[e_code_LocalVariableTypeTable_span_O]
|
||||
#define code_LocalVariableTypeTable_name_RU all_bands[e_code_LocalVariableTypeTable_name_RU]
|
||||
#define code_LocalVariableTypeTable_type_RS all_bands[e_code_LocalVariableTypeTable_type_RS]
|
||||
#define code_LocalVariableTypeTable_slot all_bands[e_code_LocalVariableTypeTable_slot]
|
||||
#define code_attr_bands all_bands[e_code_attr_bands]
|
||||
#define bc_codes all_bands[e_bc_codes]
|
||||
#define bc_case_count all_bands[e_bc_case_count]
|
||||
#define bc_case_value all_bands[e_bc_case_value]
|
||||
#define bc_byte all_bands[e_bc_byte]
|
||||
#define bc_short all_bands[e_bc_short]
|
||||
#define bc_local all_bands[e_bc_local]
|
||||
#define bc_label all_bands[e_bc_label]
|
||||
#define bc_intref all_bands[e_bc_intref]
|
||||
#define bc_floatref all_bands[e_bc_floatref]
|
||||
#define bc_longref all_bands[e_bc_longref]
|
||||
#define bc_doubleref all_bands[e_bc_doubleref]
|
||||
#define bc_stringref all_bands[e_bc_stringref]
|
||||
#define bc_classref all_bands[e_bc_classref]
|
||||
#define bc_fieldref all_bands[e_bc_fieldref]
|
||||
#define bc_methodref all_bands[e_bc_methodref]
|
||||
#define bc_imethodref all_bands[e_bc_imethodref]
|
||||
#define bc_thisfield all_bands[e_bc_thisfield]
|
||||
#define bc_superfield all_bands[e_bc_superfield]
|
||||
#define bc_thismethod all_bands[e_bc_thismethod]
|
||||
#define bc_supermethod all_bands[e_bc_supermethod]
|
||||
#define bc_initref all_bands[e_bc_initref]
|
||||
#define bc_escref all_bands[e_bc_escref]
|
||||
#define bc_escrefsize all_bands[e_bc_escrefsize]
|
||||
#define bc_escsize all_bands[e_bc_escsize]
|
||||
#define bc_escbyte all_bands[e_bc_escbyte]
|
||||
#define file_name all_bands[e_file_name]
|
||||
#define file_size_hi all_bands[e_file_size_hi]
|
||||
#define file_size_lo all_bands[e_file_size_lo]
|
||||
#define file_modtime all_bands[e_file_modtime]
|
||||
#define file_options all_bands[e_file_options]
|
217
depends/pack200/src/bytes.cpp
Normal file
217
depends/pack200/src/bytes.cpp
Normal file
@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include "defines.h"
|
||||
#include "bytes.h"
|
||||
#include "utils.h"
|
||||
|
||||
static byte dummy[1 << 10];
|
||||
|
||||
bool bytes::inBounds(const void *p)
|
||||
{
|
||||
return p >= ptr && p < limit();
|
||||
}
|
||||
|
||||
void bytes::malloc(size_t len_)
|
||||
{
|
||||
len = len_;
|
||||
ptr = NEW(byte, add_size(len_, 1)); // add trailing zero byte always
|
||||
if (ptr == nullptr)
|
||||
{
|
||||
// set ptr to some victim memory, to ease escape
|
||||
set(dummy, sizeof(dummy) - 1);
|
||||
unpack_abort(ERROR_ENOMEM);
|
||||
}
|
||||
}
|
||||
|
||||
void bytes::realloc(size_t len_)
|
||||
{
|
||||
if (len == len_)
|
||||
return; // nothing to do
|
||||
if (ptr == dummy)
|
||||
return; // escaping from an error
|
||||
if (ptr == nullptr)
|
||||
{
|
||||
malloc(len_);
|
||||
return;
|
||||
}
|
||||
byte *oldptr = ptr;
|
||||
ptr = (len_ >= PSIZE_MAX) ? nullptr : (byte *)::realloc(ptr, add_size(len_, 1));
|
||||
if (ptr != nullptr)
|
||||
{
|
||||
if (len < len_)
|
||||
memset(ptr + len, 0, len_ - len);
|
||||
ptr[len_] = 0;
|
||||
len = len_;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = oldptr; // ease our escape
|
||||
unpack_abort(ERROR_ENOMEM);
|
||||
}
|
||||
}
|
||||
|
||||
void bytes::free()
|
||||
{
|
||||
if (ptr == dummy)
|
||||
return; // escaping from an error
|
||||
if (ptr != nullptr)
|
||||
{
|
||||
::free(ptr);
|
||||
}
|
||||
len = 0;
|
||||
ptr = 0;
|
||||
}
|
||||
|
||||
int bytes::indexOf(byte c)
|
||||
{
|
||||
byte *p = (byte *)memchr(ptr, c, len);
|
||||
return (p == 0) ? -1 : (int)(p - ptr);
|
||||
}
|
||||
|
||||
byte *bytes::writeTo(byte *bp)
|
||||
{
|
||||
memcpy(bp, ptr, len);
|
||||
return bp + len;
|
||||
}
|
||||
|
||||
int bytes::compareTo(bytes &other)
|
||||
{
|
||||
size_t l1 = len;
|
||||
size_t l2 = other.len;
|
||||
int cmp = memcmp(ptr, other.ptr, (l1 < l2) ? l1 : l2);
|
||||
if (cmp != 0)
|
||||
return cmp;
|
||||
return (l1 < l2) ? -1 : (l1 > l2) ? 1 : 0;
|
||||
}
|
||||
|
||||
void bytes::saveFrom(const void *ptr_, size_t len_)
|
||||
{
|
||||
malloc(len_);
|
||||
// Save as much as possible.
|
||||
if (len_ > len)
|
||||
{
|
||||
assert(ptr == dummy); // error recovery
|
||||
len_ = len;
|
||||
}
|
||||
copyFrom(ptr_, len_);
|
||||
}
|
||||
|
||||
//#TODO: Need to fix for exception handling
|
||||
void bytes::copyFrom(const void *ptr_, size_t len_, size_t offset)
|
||||
{
|
||||
assert(len_ == 0 || inBounds(ptr + offset));
|
||||
assert(len_ == 0 || inBounds(ptr + offset + len_ - 1));
|
||||
memcpy(ptr + offset, ptr_, len_);
|
||||
}
|
||||
|
||||
// Make sure there are 'o' bytes beyond the fill pointer,
|
||||
// advance the fill pointer, and return the old fill pointer.
|
||||
byte *fillbytes::grow(size_t s)
|
||||
{
|
||||
size_t nlen = add_size(b.len, s);
|
||||
if (nlen <= allocated)
|
||||
{
|
||||
b.len = nlen;
|
||||
return limit() - s;
|
||||
}
|
||||
size_t maxlen = nlen;
|
||||
if (maxlen < 128)
|
||||
maxlen = 128;
|
||||
if (maxlen < allocated * 2)
|
||||
maxlen = allocated * 2;
|
||||
if (allocated == 0)
|
||||
{
|
||||
// Initial buffer was not malloced. Do not reallocate it.
|
||||
bytes old = b;
|
||||
b.malloc(maxlen);
|
||||
if (b.len == maxlen)
|
||||
old.writeTo(b.ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
b.realloc(maxlen);
|
||||
}
|
||||
allocated = b.len;
|
||||
if (allocated != maxlen)
|
||||
{
|
||||
b.len = nlen - s; // back up
|
||||
return dummy; // scribble during error recov.
|
||||
}
|
||||
// after realloc, recompute pointers
|
||||
b.len = nlen;
|
||||
assert(b.len <= allocated);
|
||||
return limit() - s;
|
||||
}
|
||||
|
||||
void fillbytes::ensureSize(size_t s)
|
||||
{
|
||||
if (allocated >= s)
|
||||
return;
|
||||
size_t len0 = b.len;
|
||||
grow(s - size());
|
||||
b.len = len0; // put it back
|
||||
}
|
||||
|
||||
int ptrlist::indexOf(const void *x)
|
||||
{
|
||||
int len = length();
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
if (get(i) == x)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ptrlist::freeAll()
|
||||
{
|
||||
int len = length();
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
void *p = (void *)get(i);
|
||||
if (p != nullptr)
|
||||
{
|
||||
::free(p);
|
||||
}
|
||||
}
|
||||
free();
|
||||
}
|
||||
|
||||
int intlist::indexOf(int x)
|
||||
{
|
||||
int len = length();
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
if (get(i) == x)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
284
depends/pack200/src/bytes.h
Normal file
284
depends/pack200/src/bytes.h
Normal file
@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
struct bytes
|
||||
{
|
||||
int8_t *ptr;
|
||||
size_t len;
|
||||
int8_t *limit()
|
||||
{
|
||||
return ptr + len;
|
||||
}
|
||||
|
||||
void set(int8_t *ptr_, size_t len_)
|
||||
{
|
||||
ptr = ptr_;
|
||||
len = len_;
|
||||
}
|
||||
void set(const char *str)
|
||||
{
|
||||
ptr = (int8_t *)str;
|
||||
len = strlen(str);
|
||||
}
|
||||
bool inBounds(const void *p); // p in [ptr, limit)
|
||||
void malloc(size_t len_);
|
||||
void realloc(size_t len_);
|
||||
void free();
|
||||
void copyFrom(const void *ptr_, size_t len_, size_t offset = 0);
|
||||
void saveFrom(const void *ptr_, size_t len_);
|
||||
void saveFrom(const char *str)
|
||||
{
|
||||
saveFrom(str, strlen(str));
|
||||
}
|
||||
void copyFrom(bytes &other, size_t offset = 0)
|
||||
{
|
||||
copyFrom(other.ptr, other.len, offset);
|
||||
}
|
||||
void saveFrom(bytes &other)
|
||||
{
|
||||
saveFrom(other.ptr, other.len);
|
||||
}
|
||||
void clear(int fill_byte = 0)
|
||||
{
|
||||
memset(ptr, fill_byte, len);
|
||||
}
|
||||
int8_t *writeTo(int8_t *bp);
|
||||
bool equals(bytes &other)
|
||||
{
|
||||
return 0 == compareTo(other);
|
||||
}
|
||||
int compareTo(bytes &other);
|
||||
bool contains(int8_t c)
|
||||
{
|
||||
return indexOf(c) >= 0;
|
||||
}
|
||||
int indexOf(int8_t c);
|
||||
// substrings:
|
||||
static bytes of(int8_t *ptr, size_t len)
|
||||
{
|
||||
bytes res;
|
||||
res.set(ptr, len);
|
||||
return res;
|
||||
}
|
||||
bytes slice(size_t beg, size_t end)
|
||||
{
|
||||
bytes res;
|
||||
res.ptr = ptr + beg;
|
||||
res.len = end - beg;
|
||||
assert(res.len == 0 || inBounds(res.ptr) && inBounds(res.limit() - 1));
|
||||
return res;
|
||||
}
|
||||
// building C strings inside byte buffers:
|
||||
bytes &strcat(const char *str)
|
||||
{
|
||||
::strcat((char *)ptr, str);
|
||||
return *this;
|
||||
}
|
||||
bytes &strcat(bytes &other)
|
||||
{
|
||||
::strncat((char *)ptr, (char *)other.ptr, other.len);
|
||||
return *this;
|
||||
}
|
||||
char *strval()
|
||||
{
|
||||
assert(strlen((char *)ptr) == len);
|
||||
return (char *)ptr;
|
||||
}
|
||||
};
|
||||
#define BYTES_OF(var) (bytes::of((int8_t *)&(var), sizeof(var)))
|
||||
|
||||
struct fillbytes
|
||||
{
|
||||
bytes b;
|
||||
size_t allocated;
|
||||
|
||||
int8_t *base()
|
||||
{
|
||||
return b.ptr;
|
||||
}
|
||||
size_t size()
|
||||
{
|
||||
return b.len;
|
||||
}
|
||||
int8_t *limit()
|
||||
{
|
||||
return b.limit();
|
||||
} // logical limit
|
||||
void setLimit(int8_t *lp)
|
||||
{
|
||||
assert(isAllocated(lp));
|
||||
b.len = lp - b.ptr;
|
||||
}
|
||||
int8_t *end()
|
||||
{
|
||||
return b.ptr + allocated;
|
||||
} // physical limit
|
||||
int8_t *loc(size_t o)
|
||||
{
|
||||
assert(o < b.len);
|
||||
return b.ptr + o;
|
||||
}
|
||||
void init()
|
||||
{
|
||||
allocated = 0;
|
||||
b.set(nullptr, 0);
|
||||
}
|
||||
void init(size_t s)
|
||||
{
|
||||
init();
|
||||
ensureSize(s);
|
||||
}
|
||||
void free()
|
||||
{
|
||||
if (allocated != 0)
|
||||
b.free();
|
||||
allocated = 0;
|
||||
}
|
||||
void empty()
|
||||
{
|
||||
b.len = 0;
|
||||
}
|
||||
int8_t *grow(size_t s); // grow so that limit() += s
|
||||
int getByte(uint32_t i)
|
||||
{
|
||||
return *loc(i) & 0xFF;
|
||||
}
|
||||
void addByte(int8_t x)
|
||||
{
|
||||
*grow(1) = x;
|
||||
}
|
||||
void ensureSize(size_t s); // make sure allocated >= s
|
||||
void trimToSize()
|
||||
{
|
||||
if (allocated > size())
|
||||
b.realloc(allocated = size());
|
||||
}
|
||||
bool canAppend(size_t s)
|
||||
{
|
||||
return allocated > b.len + s;
|
||||
}
|
||||
bool isAllocated(int8_t *p)
|
||||
{
|
||||
return p >= base() && p <= end();
|
||||
} // asserts
|
||||
void set(bytes &src)
|
||||
{
|
||||
set(src.ptr, src.len);
|
||||
}
|
||||
|
||||
void set(int8_t *ptr, size_t len)
|
||||
{
|
||||
b.set(ptr, len);
|
||||
allocated = 0; // mark as not reallocatable
|
||||
}
|
||||
|
||||
// block operations on resizing byte buffer:
|
||||
fillbytes &append(const void *ptr_, size_t len_)
|
||||
{
|
||||
memcpy(grow(len_), ptr_, len_);
|
||||
return (*this);
|
||||
}
|
||||
fillbytes &append(bytes &other)
|
||||
{
|
||||
return append(other.ptr, other.len);
|
||||
}
|
||||
fillbytes &append(const char *str)
|
||||
{
|
||||
return append(str, strlen(str));
|
||||
}
|
||||
};
|
||||
|
||||
struct ptrlist : fillbytes
|
||||
{
|
||||
typedef const void *cvptr;
|
||||
int length()
|
||||
{
|
||||
return (int)(size() / sizeof(cvptr));
|
||||
}
|
||||
cvptr *base()
|
||||
{
|
||||
return (cvptr *)fillbytes::base();
|
||||
}
|
||||
cvptr &get(int i)
|
||||
{
|
||||
return *(cvptr *)loc(i * sizeof(cvptr));
|
||||
}
|
||||
cvptr *limit()
|
||||
{
|
||||
return (cvptr *)fillbytes::limit();
|
||||
}
|
||||
void add(cvptr x)
|
||||
{
|
||||
*(cvptr *)grow(sizeof(x)) = x;
|
||||
}
|
||||
void popTo(int l)
|
||||
{
|
||||
assert(l <= length());
|
||||
b.len = l * sizeof(cvptr);
|
||||
}
|
||||
int indexOf(cvptr x);
|
||||
bool contains(cvptr x)
|
||||
{
|
||||
return indexOf(x) >= 0;
|
||||
}
|
||||
void freeAll(); // frees every ptr on the list, plus the list itself
|
||||
};
|
||||
// Use a macro rather than mess with subtle mismatches
|
||||
// between member and non-member function pointers.
|
||||
#define PTRLIST_QSORT(ptrls, fn) ::qsort((ptrls).base(), (ptrls).length(), sizeof(void *), fn)
|
||||
|
||||
struct intlist : fillbytes
|
||||
{
|
||||
int length()
|
||||
{
|
||||
return (int)(size() / sizeof(int));
|
||||
}
|
||||
int *base()
|
||||
{
|
||||
return (int *)fillbytes::base();
|
||||
}
|
||||
int &get(int i)
|
||||
{
|
||||
return *(int *)loc(i * sizeof(int));
|
||||
}
|
||||
int *limit()
|
||||
{
|
||||
return (int *)fillbytes::limit();
|
||||
}
|
||||
void add(int x)
|
||||
{
|
||||
*(int *)grow(sizeof(x)) = x;
|
||||
}
|
||||
void popTo(int l)
|
||||
{
|
||||
assert(l <= length());
|
||||
b.len = l * sizeof(int);
|
||||
}
|
||||
int indexOf(int x);
|
||||
bool contains(int x)
|
||||
{
|
||||
return indexOf(x) >= 0;
|
||||
}
|
||||
};
|
1042
depends/pack200/src/coding.cpp
Normal file
1042
depends/pack200/src/coding.cpp
Normal file
File diff suppressed because it is too large
Load Diff
247
depends/pack200/src/coding.h
Normal file
247
depends/pack200/src/coding.h
Normal file
@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
struct unpacker;
|
||||
|
||||
#define INT_MAX_VALUE ((int)0x7FFFFFFF)
|
||||
#define INT_MIN_VALUE ((int)0x80000000)
|
||||
|
||||
#define CODING_SPEC(B, H, S, D) ((B) << 20 | (H) << 8 | (S) << 4 | (D) << 0)
|
||||
#define CODING_B(x) ((x) >> 20 & 0xF)
|
||||
#define CODING_H(x) ((x) >> 8 & 0xFFF)
|
||||
#define CODING_S(x) ((x) >> 4 & 0xF)
|
||||
#define CODING_D(x) ((x) >> 0 & 0xF)
|
||||
|
||||
#define CODING_INIT(B, H, S, D) \
|
||||
{ \
|
||||
CODING_SPEC(B, H, S, D), 0, 0, 0, 0, 0, 0, 0, 0 \
|
||||
}
|
||||
|
||||
// For debugging purposes, some compilers do not like this and will complain.
|
||||
// #define long do_not_use_C_long_types_use_jlong_or_int
|
||||
// Use of the type "long" is problematic, do not use it.
|
||||
|
||||
struct coding
|
||||
{
|
||||
int spec; // B,H,S,D
|
||||
|
||||
// Handy values derived from the spec:
|
||||
int B()
|
||||
{
|
||||
return CODING_B(spec);
|
||||
}
|
||||
int H()
|
||||
{
|
||||
return CODING_H(spec);
|
||||
}
|
||||
int S()
|
||||
{
|
||||
return CODING_S(spec);
|
||||
}
|
||||
int D()
|
||||
{
|
||||
return CODING_D(spec);
|
||||
}
|
||||
int L()
|
||||
{
|
||||
return 256 - CODING_H(spec);
|
||||
}
|
||||
int min, max;
|
||||
int umin, umax;
|
||||
char isSigned, isSubrange, isFullRange, isMalloc;
|
||||
|
||||
coding *init(); // returns self or nullptr if error
|
||||
coding *initFrom(int spec_)
|
||||
{
|
||||
assert(this->spec == 0);
|
||||
this->spec = spec_;
|
||||
return init();
|
||||
}
|
||||
|
||||
static coding *findBySpec(int spec);
|
||||
static coding *findBySpec(int B, int H, int S = 0, int D = 0);
|
||||
static coding *findByIndex(int irregularCodingIndex);
|
||||
|
||||
static uint32_t parse(byte *&rp, int B, int H);
|
||||
static uint32_t parse_lgH(byte *&rp, int B, int H, int lgH);
|
||||
static void parseMultiple(byte *&rp, int N, byte *limit, int B, int H);
|
||||
|
||||
uint32_t parse(byte *&rp)
|
||||
{
|
||||
return parse(rp, CODING_B(spec), CODING_H(spec));
|
||||
}
|
||||
void parseMultiple(byte *&rp, int N, byte *limit)
|
||||
{
|
||||
parseMultiple(rp, N, limit, CODING_B(spec), CODING_H(spec));
|
||||
}
|
||||
|
||||
bool canRepresent(int x)
|
||||
{
|
||||
return (x >= min && x <= max);
|
||||
}
|
||||
bool canRepresentUnsigned(int x)
|
||||
{
|
||||
return (x >= umin && x <= umax);
|
||||
}
|
||||
|
||||
int sumInUnsignedRange(int x, int y);
|
||||
|
||||
int readFrom(byte *&rpVar, int *dbase);
|
||||
void readArrayFrom(byte *&rpVar, int *dbase, int length, int *values);
|
||||
void skipArrayFrom(byte *&rpVar, int length)
|
||||
{
|
||||
readArrayFrom(rpVar, (int *)NULL, length, (int *)NULL);
|
||||
}
|
||||
|
||||
void free(); // free self if isMalloc
|
||||
};
|
||||
|
||||
enum coding_method_kind
|
||||
{
|
||||
cmk_ERROR,
|
||||
cmk_BHS,
|
||||
cmk_BHS0,
|
||||
cmk_BHS1,
|
||||
cmk_BHSD1,
|
||||
cmk_BHS1D1full, // isFullRange
|
||||
cmk_BHS1D1sub, // isSubRange
|
||||
|
||||
// special cases hand-optimized (~50% of all decoded values)
|
||||
cmk_BYTE1, //(1,256) 6%
|
||||
cmk_CHAR3, //(3,128) 7%
|
||||
cmk_UNSIGNED5, //(5,64) 13%
|
||||
cmk_DELTA5, //(5,64,1,1) 5%
|
||||
cmk_BCI5, //(5,4) 18%
|
||||
cmk_BRANCH5, //(5,4,2) 4%
|
||||
// cmk_UNSIGNED5H16, //(5,16) 5%
|
||||
// cmk_UNSIGNED2H4, //(2,4) 6%
|
||||
// cmk_DELTA4H8, //(4,8,1,1) 10%
|
||||
// cmk_DELTA3H16, //(3,16,1,1) 9%
|
||||
cmk_BHS_LIMIT,
|
||||
cmk_pop,
|
||||
cmk_pop_BHS0,
|
||||
cmk_pop_BYTE1,
|
||||
cmk_pop_LIMIT,
|
||||
cmk_LIMIT
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
BYTE1_spec = CODING_SPEC(1, 256, 0, 0),
|
||||
CHAR3_spec = CODING_SPEC(3, 128, 0, 0),
|
||||
UNSIGNED4_spec = CODING_SPEC(4, 256, 0, 0),
|
||||
UNSIGNED5_spec = CODING_SPEC(5, 64, 0, 0),
|
||||
SIGNED5_spec = CODING_SPEC(5, 64, 1, 0),
|
||||
DELTA5_spec = CODING_SPEC(5, 64, 1, 1),
|
||||
UDELTA5_spec = CODING_SPEC(5, 64, 0, 1),
|
||||
MDELTA5_spec = CODING_SPEC(5, 64, 2, 1),
|
||||
BCI5_spec = CODING_SPEC(5, 4, 0, 0),
|
||||
BRANCH5_spec = CODING_SPEC(5, 4, 2, 0)
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
B_MAX = 5,
|
||||
C_SLOP = B_MAX * 10
|
||||
};
|
||||
|
||||
struct coding_method;
|
||||
|
||||
// iterator under the control of a meta-coding
|
||||
struct value_stream
|
||||
{
|
||||
// current coding of values or values
|
||||
coding c; // B,H,S,D,etc.
|
||||
coding_method_kind cmk; // type of decoding needed
|
||||
byte *rp; // read pointer
|
||||
byte *rplimit; // final value of read pointer
|
||||
int sum; // partial sum of all values so far (D=1 only)
|
||||
coding_method *cm; // coding method that defines this stream
|
||||
|
||||
void init(byte *band_rp, byte *band_limit, coding *defc);
|
||||
void init(byte *band_rp, byte *band_limit, int spec)
|
||||
{
|
||||
init(band_rp, band_limit, coding::findBySpec(spec));
|
||||
}
|
||||
|
||||
void setCoding(coding *c);
|
||||
void setCoding(int spec)
|
||||
{
|
||||
setCoding(coding::findBySpec(spec));
|
||||
}
|
||||
|
||||
// Parse and decode a single value.
|
||||
int getInt();
|
||||
|
||||
// Parse and decode a single byte, with no error checks.
|
||||
int getByte()
|
||||
{
|
||||
assert(cmk == cmk_BYTE1);
|
||||
assert(rp < rplimit);
|
||||
return *rp++ & 0xFF;
|
||||
}
|
||||
|
||||
// Used only for asserts.
|
||||
bool hasValue();
|
||||
|
||||
void done()
|
||||
{
|
||||
assert(!hasValue());
|
||||
}
|
||||
|
||||
// Sometimes a value stream has an auxiliary (but there are never two).
|
||||
value_stream *helper()
|
||||
{
|
||||
assert(hasHelper());
|
||||
return this + 1;
|
||||
}
|
||||
bool hasHelper();
|
||||
};
|
||||
|
||||
struct coding_method
|
||||
{
|
||||
value_stream vs0; // initial state snapshot (vs.meta==this)
|
||||
|
||||
coding_method *next; // what to do when we run out of bytes
|
||||
|
||||
// these fields are used for pop codes only:
|
||||
int *fValues; // favored value array
|
||||
int fVlength; // maximum favored value token
|
||||
coding_method *uValues; // unfavored value stream
|
||||
|
||||
// pointer to outer unpacker, for error checks etc.
|
||||
unpacker *u;
|
||||
|
||||
// Initialize a value stream.
|
||||
void reset(value_stream *state);
|
||||
|
||||
// Parse a band header, size a band, and initialize for further action.
|
||||
// band_rp advances (but not past band_limit), and meta_rp advances.
|
||||
// The mode gives context, such as "inside a pop".
|
||||
// The defc and N are the incoming parameters to a meta-coding.
|
||||
// The value sink is used to collect output values, when desired.
|
||||
void init(byte *&band_rp, byte *band_limit, byte *&meta_rp, int mode, coding *defc, int N,
|
||||
intlist *valueSink);
|
||||
};
|
442
depends/pack200/src/constants.h
Normal file
442
depends/pack200/src/constants.h
Normal file
@ -0,0 +1,442 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
Java Class Version numbers history
|
||||
1.0 to 1.3.X 45,3
|
||||
1.4 to 1.4.X 46,0
|
||||
1.5 to 1.5.X 49,0
|
||||
1.6 to 1.5.x 50,0 NOTE Assumed for now
|
||||
*/
|
||||
|
||||
// classfile constants
|
||||
#define JAVA_MAGIC 0xCAFEBABE
|
||||
#define JAVA_MIN_MAJOR_VERSION 45
|
||||
#define JAVA_MIN_MINOR_VERSION 3
|
||||
#define JAVA5_MAX_MAJOR_VERSION 49
|
||||
#define JAVA5_MAX_MINOR_VERSION 0
|
||||
// NOTE: Assume for now
|
||||
#define JAVA6_MAX_MAJOR_VERSION 50
|
||||
#define JAVA6_MAX_MINOR_VERSION 0
|
||||
|
||||
// package file constants
|
||||
#define JAVA_PACKAGE_MAGIC 0xCAFED00D
|
||||
#define JAVA5_PACKAGE_MAJOR_VERSION 150
|
||||
#define JAVA5_PACKAGE_MINOR_VERSION 7
|
||||
|
||||
#define JAVA6_PACKAGE_MAJOR_VERSION 160
|
||||
#define JAVA6_PACKAGE_MINOR_VERSION 1
|
||||
|
||||
// magic number for gzip streams (for processing pack200-gzip data)
|
||||
#define GZIP_MAGIC 0x1F8B0800
|
||||
#define GZIP_MAGIC_MASK 0xFFFFFF00 // last \bchar\b is variable "flg" field
|
||||
|
||||
enum
|
||||
{
|
||||
CONSTANT_None,
|
||||
CONSTANT_Utf8,
|
||||
CONSTANT_unused2, /* unused, was Unicode */
|
||||
CONSTANT_Integer,
|
||||
CONSTANT_Float,
|
||||
CONSTANT_Long,
|
||||
CONSTANT_Double,
|
||||
CONSTANT_Class,
|
||||
CONSTANT_String,
|
||||
CONSTANT_Fieldref,
|
||||
CONSTANT_Methodref,
|
||||
CONSTANT_InterfaceMethodref,
|
||||
CONSTANT_NameandType,
|
||||
CONSTANT_Signature = 13,
|
||||
CONSTANT_All = 14,
|
||||
CONSTANT_Limit = 15,
|
||||
CONSTANT_NONE = 0,
|
||||
CONSTANT_Literal = 20, // pseudo-tag for debugging
|
||||
CONSTANT_Member = 21, // pseudo-tag for debugging
|
||||
SUBINDEX_BIT = 64, // combined with CONSTANT_xxx for ixTag
|
||||
ACC_STATIC = 0x0008,
|
||||
ACC_IC_LONG_FORM = (1 << 16), // for ic_flags
|
||||
CLASS_ATTR_SourceFile = 17,
|
||||
CLASS_ATTR_EnclosingMethod = 18,
|
||||
CLASS_ATTR_InnerClasses = 23,
|
||||
CLASS_ATTR_ClassFile_version = 24,
|
||||
FIELD_ATTR_ConstantValue = 17,
|
||||
METHOD_ATTR_Code = 17,
|
||||
METHOD_ATTR_Exceptions = 18,
|
||||
METHOD_ATTR_RuntimeVisibleParameterAnnotations = 23,
|
||||
METHOD_ATTR_RuntimeInvisibleParameterAnnotations = 24,
|
||||
METHOD_ATTR_AnnotationDefault = 25,
|
||||
CODE_ATTR_StackMapTable = 0,
|
||||
CODE_ATTR_LineNumberTable = 1,
|
||||
CODE_ATTR_LocalVariableTable = 2,
|
||||
CODE_ATTR_LocalVariableTypeTable = 3,
|
||||
// X_ATTR_Synthetic = 12, // ACC_SYNTHETIC; not predefined
|
||||
X_ATTR_Signature = 19,
|
||||
X_ATTR_Deprecated = 20,
|
||||
X_ATTR_RuntimeVisibleAnnotations = 21,
|
||||
X_ATTR_RuntimeInvisibleAnnotations = 22,
|
||||
X_ATTR_OVERFLOW = 16,
|
||||
X_ATTR_LIMIT_NO_FLAGS_HI = 32,
|
||||
X_ATTR_LIMIT_FLAGS_HI = 63,
|
||||
|
||||
#define O_ATTR_DO(F) \
|
||||
F(X_ATTR_OVERFLOW, 01) \
|
||||
/*(end)*/
|
||||
#define X_ATTR_DO(F) \
|
||||
O_ATTR_DO(F) F(X_ATTR_Signature, Signature) F(X_ATTR_Deprecated, Deprecated) \
|
||||
F(X_ATTR_RuntimeVisibleAnnotations, RuntimeVisibleAnnotations) \
|
||||
F(X_ATTR_RuntimeInvisibleAnnotations, RuntimeInvisibleAnnotations) \
|
||||
/*F(X_ATTR_Synthetic,Synthetic)*/ \
|
||||
/*(end)*/
|
||||
#define CLASS_ATTR_DO(F) \
|
||||
F(CLASS_ATTR_SourceFile, SourceFile) F(CLASS_ATTR_InnerClasses, InnerClasses) \
|
||||
F(CLASS_ATTR_EnclosingMethod, EnclosingMethod) F(CLASS_ATTR_ClassFile_version, 02) \
|
||||
/*(end)*/
|
||||
#define FIELD_ATTR_DO(F) \
|
||||
F(FIELD_ATTR_ConstantValue, ConstantValue) \
|
||||
/*(end)*/
|
||||
#define METHOD_ATTR_DO(F) \
|
||||
F(METHOD_ATTR_Code, Code) F(METHOD_ATTR_Exceptions, Exceptions) \
|
||||
F(METHOD_ATTR_RuntimeVisibleParameterAnnotations, RuntimeVisibleParameterAnnotations) \
|
||||
F(METHOD_ATTR_RuntimeInvisibleParameterAnnotations, \
|
||||
RuntimeInvisibleParameterAnnotations) \
|
||||
F(METHOD_ATTR_AnnotationDefault, AnnotationDefault) \
|
||||
/*(end)*/
|
||||
#define CODE_ATTR_DO(F) \
|
||||
F(CODE_ATTR_StackMapTable, StackMapTable) F(CODE_ATTR_LineNumberTable, LineNumberTable) \
|
||||
F(CODE_ATTR_LocalVariableTable, LocalVariableTable) \
|
||||
F(CODE_ATTR_LocalVariableTypeTable, LocalVariableTypeTable) \
|
||||
/*(end)*/
|
||||
#define ALL_ATTR_DO(F) \
|
||||
X_ATTR_DO(F) CLASS_ATTR_DO(F) FIELD_ATTR_DO(F) METHOD_ATTR_DO(F) CODE_ATTR_DO(F) \
|
||||
/*(end)*/
|
||||
|
||||
// attribute "context types"
|
||||
ATTR_CONTEXT_CLASS = 0,
|
||||
ATTR_CONTEXT_FIELD = 1,
|
||||
ATTR_CONTEXT_METHOD = 2,
|
||||
ATTR_CONTEXT_CODE = 3,
|
||||
ATTR_CONTEXT_LIMIT = 4,
|
||||
|
||||
// constants for parsed layouts (stored in band::le_kind)
|
||||
EK_NONE = 0, // not a layout element
|
||||
EK_INT = 'I', // B H I SH etc., also FH etc.
|
||||
EK_BCI = 'P', // PH etc.
|
||||
EK_BCID = 'Q', // POH etc.
|
||||
EK_BCO = 'O', // OH etc.
|
||||
EK_REPL = 'N', // NH[...] etc.
|
||||
EK_REF = 'R', // RUH, RUNH, KQH, etc.
|
||||
EK_UN = 'T', // TB(...)[...] etc.
|
||||
EK_CASE = 'K', // (...)[...] etc.
|
||||
EK_CALL = '(', // (0), (1), etc.
|
||||
EK_CBLE = '[', // [...][...] etc.
|
||||
NO_BAND_INDEX = -1,
|
||||
|
||||
// File option bits, from LSB in ascending bit position.
|
||||
FO_DEFLATE_HINT = 1 << 0,
|
||||
FO_IS_CLASS_STUB = 1 << 1,
|
||||
|
||||
// Archive option bits, from LSB in ascending bit position:
|
||||
AO_HAVE_SPECIAL_FORMATS = 1 << 0,
|
||||
AO_HAVE_CP_NUMBERS = 1 << 1,
|
||||
AO_HAVE_ALL_CODE_FLAGS = 1 << 2,
|
||||
AO_3_UNUSED_MBZ = 1 << 3,
|
||||
AO_HAVE_FILE_HEADERS = 1 << 4,
|
||||
AO_DEFLATE_HINT = 1 << 5,
|
||||
AO_HAVE_FILE_MODTIME = 1 << 6,
|
||||
AO_HAVE_FILE_OPTIONS = 1 << 7,
|
||||
AO_HAVE_FILE_SIZE_HI = 1 << 8,
|
||||
AO_HAVE_CLASS_FLAGS_HI = 1 << 9,
|
||||
AO_HAVE_FIELD_FLAGS_HI = 1 << 10,
|
||||
AO_HAVE_METHOD_FLAGS_HI = 1 << 11,
|
||||
AO_HAVE_CODE_FLAGS_HI = 1 << 12,
|
||||
#define ARCHIVE_BIT_DO(F) \
|
||||
F(AO_HAVE_SPECIAL_FORMATS) F(AO_HAVE_CP_NUMBERS) F(AO_HAVE_ALL_CODE_FLAGS) \
|
||||
/*F(AO_3_UNUSED_MBZ)*/ \
|
||||
F(AO_HAVE_FILE_HEADERS) F(AO_DEFLATE_HINT) F(AO_HAVE_FILE_MODTIME) \
|
||||
F(AO_HAVE_FILE_OPTIONS) F(AO_HAVE_FILE_SIZE_HI) F(AO_HAVE_CLASS_FLAGS_HI) \
|
||||
F(AO_HAVE_FIELD_FLAGS_HI) F(AO_HAVE_METHOD_FLAGS_HI) F(AO_HAVE_CODE_FLAGS_HI) \
|
||||
/*(end)*/
|
||||
|
||||
// Constants for decoding attribute definition header bytes.
|
||||
ADH_CONTEXT_MASK = 0x3, // (hdr & ADH_CONTEXT_MASK)
|
||||
ADH_BIT_SHIFT = 0x2, // (hdr >> ADH_BIT_SHIFT)
|
||||
ADH_BIT_IS_LSB = 1, // (hdr >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB
|
||||
#define ADH_BYTE(context, index) ((((index) + ADH_BIT_IS_LSB) << ADH_BIT_SHIFT) + (context))
|
||||
#define ADH_BYTE_CONTEXT(adhb) ((adhb) & ADH_CONTEXT_MASK)
|
||||
#define ADH_BYTE_INDEX(adhb) (((adhb) >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB)
|
||||
NO_MODTIME = 0, // nullptr modtime value
|
||||
|
||||
// meta-coding
|
||||
_meta_default = 0,
|
||||
_meta_canon_min = 1,
|
||||
_meta_canon_max = 115,
|
||||
_meta_arb = 116,
|
||||
_meta_run = 117,
|
||||
_meta_pop = 141,
|
||||
_meta_limit = 189,
|
||||
_meta_error = 255,
|
||||
_xxx_1_end
|
||||
};
|
||||
|
||||
// Bytecodes.
|
||||
|
||||
enum
|
||||
{
|
||||
bc_nop = 0, // 0x00
|
||||
bc_aconst_null = 1, // 0x01
|
||||
bc_iconst_m1 = 2, // 0x02
|
||||
bc_iconst_0 = 3, // 0x03
|
||||
bc_iconst_1 = 4, // 0x04
|
||||
bc_iconst_2 = 5, // 0x05
|
||||
bc_iconst_3 = 6, // 0x06
|
||||
bc_iconst_4 = 7, // 0x07
|
||||
bc_iconst_5 = 8, // 0x08
|
||||
bc_lconst_0 = 9, // 0x09
|
||||
bc_lconst_1 = 10, // 0x0a
|
||||
bc_fconst_0 = 11, // 0x0b
|
||||
bc_fconst_1 = 12, // 0x0c
|
||||
bc_fconst_2 = 13, // 0x0d
|
||||
bc_dconst_0 = 14, // 0x0e
|
||||
bc_dconst_1 = 15, // 0x0f
|
||||
bc_bipush = 16, // 0x10
|
||||
bc_sipush = 17, // 0x11
|
||||
bc_ldc = 18, // 0x12
|
||||
bc_ldc_w = 19, // 0x13
|
||||
bc_ldc2_w = 20, // 0x14
|
||||
bc_iload = 21, // 0x15
|
||||
bc_lload = 22, // 0x16
|
||||
bc_fload = 23, // 0x17
|
||||
bc_dload = 24, // 0x18
|
||||
bc_aload = 25, // 0x19
|
||||
bc_iload_0 = 26, // 0x1a
|
||||
bc_iload_1 = 27, // 0x1b
|
||||
bc_iload_2 = 28, // 0x1c
|
||||
bc_iload_3 = 29, // 0x1d
|
||||
bc_lload_0 = 30, // 0x1e
|
||||
bc_lload_1 = 31, // 0x1f
|
||||
bc_lload_2 = 32, // 0x20
|
||||
bc_lload_3 = 33, // 0x21
|
||||
bc_fload_0 = 34, // 0x22
|
||||
bc_fload_1 = 35, // 0x23
|
||||
bc_fload_2 = 36, // 0x24
|
||||
bc_fload_3 = 37, // 0x25
|
||||
bc_dload_0 = 38, // 0x26
|
||||
bc_dload_1 = 39, // 0x27
|
||||
bc_dload_2 = 40, // 0x28
|
||||
bc_dload_3 = 41, // 0x29
|
||||
bc_aload_0 = 42, // 0x2a
|
||||
bc_aload_1 = 43, // 0x2b
|
||||
bc_aload_2 = 44, // 0x2c
|
||||
bc_aload_3 = 45, // 0x2d
|
||||
bc_iaload = 46, // 0x2e
|
||||
bc_laload = 47, // 0x2f
|
||||
bc_faload = 48, // 0x30
|
||||
bc_daload = 49, // 0x31
|
||||
bc_aaload = 50, // 0x32
|
||||
bc_baload = 51, // 0x33
|
||||
bc_caload = 52, // 0x34
|
||||
bc_saload = 53, // 0x35
|
||||
bc_istore = 54, // 0x36
|
||||
bc_lstore = 55, // 0x37
|
||||
bc_fstore = 56, // 0x38
|
||||
bc_dstore = 57, // 0x39
|
||||
bc_astore = 58, // 0x3a
|
||||
bc_istore_0 = 59, // 0x3b
|
||||
bc_istore_1 = 60, // 0x3c
|
||||
bc_istore_2 = 61, // 0x3d
|
||||
bc_istore_3 = 62, // 0x3e
|
||||
bc_lstore_0 = 63, // 0x3f
|
||||
bc_lstore_1 = 64, // 0x40
|
||||
bc_lstore_2 = 65, // 0x41
|
||||
bc_lstore_3 = 66, // 0x42
|
||||
bc_fstore_0 = 67, // 0x43
|
||||
bc_fstore_1 = 68, // 0x44
|
||||
bc_fstore_2 = 69, // 0x45
|
||||
bc_fstore_3 = 70, // 0x46
|
||||
bc_dstore_0 = 71, // 0x47
|
||||
bc_dstore_1 = 72, // 0x48
|
||||
bc_dstore_2 = 73, // 0x49
|
||||
bc_dstore_3 = 74, // 0x4a
|
||||
bc_astore_0 = 75, // 0x4b
|
||||
bc_astore_1 = 76, // 0x4c
|
||||
bc_astore_2 = 77, // 0x4d
|
||||
bc_astore_3 = 78, // 0x4e
|
||||
bc_iastore = 79, // 0x4f
|
||||
bc_lastore = 80, // 0x50
|
||||
bc_fastore = 81, // 0x51
|
||||
bc_dastore = 82, // 0x52
|
||||
bc_aastore = 83, // 0x53
|
||||
bc_bastore = 84, // 0x54
|
||||
bc_castore = 85, // 0x55
|
||||
bc_sastore = 86, // 0x56
|
||||
bc_pop = 87, // 0x57
|
||||
bc_pop2 = 88, // 0x58
|
||||
bc_dup = 89, // 0x59
|
||||
bc_dup_x1 = 90, // 0x5a
|
||||
bc_dup_x2 = 91, // 0x5b
|
||||
bc_dup2 = 92, // 0x5c
|
||||
bc_dup2_x1 = 93, // 0x5d
|
||||
bc_dup2_x2 = 94, // 0x5e
|
||||
bc_swap = 95, // 0x5f
|
||||
bc_iadd = 96, // 0x60
|
||||
bc_ladd = 97, // 0x61
|
||||
bc_fadd = 98, // 0x62
|
||||
bc_dadd = 99, // 0x63
|
||||
bc_isub = 100, // 0x64
|
||||
bc_lsub = 101, // 0x65
|
||||
bc_fsub = 102, // 0x66
|
||||
bc_dsub = 103, // 0x67
|
||||
bc_imul = 104, // 0x68
|
||||
bc_lmul = 105, // 0x69
|
||||
bc_fmul = 106, // 0x6a
|
||||
bc_dmul = 107, // 0x6b
|
||||
bc_idiv = 108, // 0x6c
|
||||
bc_ldiv = 109, // 0x6d
|
||||
bc_fdiv = 110, // 0x6e
|
||||
bc_ddiv = 111, // 0x6f
|
||||
bc_irem = 112, // 0x70
|
||||
bc_lrem = 113, // 0x71
|
||||
bc_frem = 114, // 0x72
|
||||
bc_drem = 115, // 0x73
|
||||
bc_ineg = 116, // 0x74
|
||||
bc_lneg = 117, // 0x75
|
||||
bc_fneg = 118, // 0x76
|
||||
bc_dneg = 119, // 0x77
|
||||
bc_ishl = 120, // 0x78
|
||||
bc_lshl = 121, // 0x79
|
||||
bc_ishr = 122, // 0x7a
|
||||
bc_lshr = 123, // 0x7b
|
||||
bc_iushr = 124, // 0x7c
|
||||
bc_lushr = 125, // 0x7d
|
||||
bc_iand = 126, // 0x7e
|
||||
bc_land = 127, // 0x7f
|
||||
bc_ior = 128, // 0x80
|
||||
bc_lor = 129, // 0x81
|
||||
bc_ixor = 130, // 0x82
|
||||
bc_lxor = 131, // 0x83
|
||||
bc_iinc = 132, // 0x84
|
||||
bc_i2l = 133, // 0x85
|
||||
bc_i2f = 134, // 0x86
|
||||
bc_i2d = 135, // 0x87
|
||||
bc_l2i = 136, // 0x88
|
||||
bc_l2f = 137, // 0x89
|
||||
bc_l2d = 138, // 0x8a
|
||||
bc_f2i = 139, // 0x8b
|
||||
bc_f2l = 140, // 0x8c
|
||||
bc_f2d = 141, // 0x8d
|
||||
bc_d2i = 142, // 0x8e
|
||||
bc_d2l = 143, // 0x8f
|
||||
bc_d2f = 144, // 0x90
|
||||
bc_i2b = 145, // 0x91
|
||||
bc_i2c = 146, // 0x92
|
||||
bc_i2s = 147, // 0x93
|
||||
bc_lcmp = 148, // 0x94
|
||||
bc_fcmpl = 149, // 0x95
|
||||
bc_fcmpg = 150, // 0x96
|
||||
bc_dcmpl = 151, // 0x97
|
||||
bc_dcmpg = 152, // 0x98
|
||||
bc_ifeq = 153, // 0x99
|
||||
bc_ifne = 154, // 0x9a
|
||||
bc_iflt = 155, // 0x9b
|
||||
bc_ifge = 156, // 0x9c
|
||||
bc_ifgt = 157, // 0x9d
|
||||
bc_ifle = 158, // 0x9e
|
||||
bc_if_icmpeq = 159, // 0x9f
|
||||
bc_if_icmpne = 160, // 0xa0
|
||||
bc_if_icmplt = 161, // 0xa1
|
||||
bc_if_icmpge = 162, // 0xa2
|
||||
bc_if_icmpgt = 163, // 0xa3
|
||||
bc_if_icmple = 164, // 0xa4
|
||||
bc_if_acmpeq = 165, // 0xa5
|
||||
bc_if_acmpne = 166, // 0xa6
|
||||
bc_goto = 167, // 0xa7
|
||||
bc_jsr = 168, // 0xa8
|
||||
bc_ret = 169, // 0xa9
|
||||
bc_tableswitch = 170, // 0xaa
|
||||
bc_lookupswitch = 171, // 0xab
|
||||
bc_ireturn = 172, // 0xac
|
||||
bc_lreturn = 173, // 0xad
|
||||
bc_freturn = 174, // 0xae
|
||||
bc_dreturn = 175, // 0xaf
|
||||
bc_areturn = 176, // 0xb0
|
||||
bc_return = 177, // 0xb1
|
||||
bc_getstatic = 178, // 0xb2
|
||||
bc_putstatic = 179, // 0xb3
|
||||
bc_getfield = 180, // 0xb4
|
||||
bc_putfield = 181, // 0xb5
|
||||
bc_invokevirtual = 182, // 0xb6
|
||||
bc_invokespecial = 183, // 0xb7
|
||||
bc_invokestatic = 184, // 0xb8
|
||||
bc_invokeinterface = 185, // 0xb9
|
||||
bc_xxxunusedxxx = 186, // 0xba
|
||||
bc_new = 187, // 0xbb
|
||||
bc_newarray = 188, // 0xbc
|
||||
bc_anewarray = 189, // 0xbd
|
||||
bc_arraylength = 190, // 0xbe
|
||||
bc_athrow = 191, // 0xbf
|
||||
bc_checkcast = 192, // 0xc0
|
||||
bc_instanceof = 193, // 0xc1
|
||||
bc_monitorenter = 194, // 0xc2
|
||||
bc_monitorexit = 195, // 0xc3
|
||||
bc_wide = 196, // 0xc4
|
||||
bc_multianewarray = 197, // 0xc5
|
||||
bc_ifnull = 198, // 0xc6
|
||||
bc_ifnonnull = 199, // 0xc7
|
||||
bc_goto_w = 200, // 0xc8
|
||||
bc_jsr_w = 201, // 0xc9
|
||||
bc_bytecode_limit = 202 // 0xca
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
bc_end_marker = 255,
|
||||
bc_byte_escape = 254,
|
||||
bc_ref_escape = 253,
|
||||
_first_linker_op = bc_getstatic,
|
||||
_last_linker_op = bc_invokestatic,
|
||||
_num_linker_ops = (_last_linker_op - _first_linker_op) + 1,
|
||||
_self_linker_op = bc_bytecode_limit,
|
||||
_self_linker_aload_flag = 1 * _num_linker_ops,
|
||||
_self_linker_super_flag = 2 * _num_linker_ops,
|
||||
_self_linker_limit = _self_linker_op + 4 * _num_linker_ops,
|
||||
_invokeinit_op = _self_linker_limit,
|
||||
_invokeinit_self_option = 0,
|
||||
_invokeinit_super_option = 1,
|
||||
_invokeinit_new_option = 2,
|
||||
_invokeinit_limit = _invokeinit_op + 3,
|
||||
_xldc_op = _invokeinit_limit,
|
||||
bc_aldc = bc_ldc,
|
||||
bc_cldc = _xldc_op + 0,
|
||||
bc_ildc = _xldc_op + 1,
|
||||
bc_fldc = _xldc_op + 2,
|
||||
bc_aldc_w = bc_ldc_w,
|
||||
bc_cldc_w = _xldc_op + 3,
|
||||
bc_ildc_w = _xldc_op + 4,
|
||||
bc_fldc_w = _xldc_op + 5,
|
||||
bc_lldc2_w = bc_ldc2_w,
|
||||
bc_dldc2_w = _xldc_op + 6,
|
||||
_xldc_limit = _xldc_op + 7,
|
||||
_xxx_3_end
|
||||
};
|
65
depends/pack200/src/defines.h
Normal file
65
depends/pack200/src/defines.h
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// random definitions
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <windows.h>
|
||||
#include <winuser.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
// Error messages that we have
|
||||
#define ERROR_ENOMEM "Memory allocation failed"
|
||||
#define ERROR_FORMAT "Corrupted pack file"
|
||||
#define ERROR_RESOURCE "Cannot extract resource file"
|
||||
#define ERROR_OVERFLOW "Internal buffer overflow"
|
||||
#define ERROR_INTERNAL "Internal error"
|
||||
|
||||
#define lengthof(array) (sizeof(array) / sizeof(array[0]))
|
||||
|
||||
#define NEW(T, n) (T *) must_malloc((int)(scale_size(n, sizeof(T))))
|
||||
#define U_NEW(T, n) (T *) u->alloc(scale_size(n, sizeof(T)))
|
||||
#define T_NEW(T, n) (T *) u->temp_alloc(scale_size(n, sizeof(T)))
|
||||
|
||||
typedef signed char byte;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define MKDIR(dir) mkdir(dir)
|
||||
#define getpid() _getpid()
|
||||
#define PATH_MAX MAX_PATH
|
||||
#define dup2(a, b) _dup2(a, b)
|
||||
#define strcasecmp(s1, s2) _stricmp(s1, s2)
|
||||
#define tempname _tempname
|
||||
#define sleep Sleep
|
||||
#else
|
||||
#define MKDIR(dir) mkdir(dir, 0777);
|
||||
#endif
|
||||
|
||||
/* Must cast to void *, then size_t, then int. */
|
||||
#define ptrlowbits(x) ((int)(size_t)(void *)(x))
|
||||
|
||||
#define DEFAULT_ARCHIVE_MODTIME 1060000000 // Aug 04, 2003 5:26 PM PDT
|
4806
depends/pack200/src/unpack.cpp
Normal file
4806
depends/pack200/src/unpack.cpp
Normal file
File diff suppressed because it is too large
Load Diff
547
depends/pack200/src/unpack.h
Normal file
547
depends/pack200/src/unpack.h
Normal file
@ -0,0 +1,547 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// Global Structures
|
||||
struct jar;
|
||||
struct gunzip;
|
||||
struct band;
|
||||
struct constant_pool;
|
||||
struct entry;
|
||||
struct cpindex;
|
||||
struct inner_class;
|
||||
struct value_stream;
|
||||
|
||||
struct cpindex
|
||||
{
|
||||
uint32_t len;
|
||||
entry *base1; // base of primary index
|
||||
entry **base2; // base of secondary index
|
||||
byte ixTag; // type of entries (!= CONSTANT_None), plus 64 if sub-index
|
||||
enum
|
||||
{
|
||||
SUB_TAG = 64
|
||||
};
|
||||
|
||||
entry *get(uint32_t i);
|
||||
|
||||
void init(int len_, entry *base1_, int ixTag_)
|
||||
{
|
||||
len = len_;
|
||||
base1 = base1_;
|
||||
base2 = nullptr;
|
||||
ixTag = ixTag_;
|
||||
}
|
||||
void init(int len_, entry **base2_, int ixTag_)
|
||||
{
|
||||
len = len_;
|
||||
base1 = nullptr;
|
||||
base2 = base2_;
|
||||
ixTag = ixTag_;
|
||||
}
|
||||
};
|
||||
|
||||
struct constant_pool
|
||||
{
|
||||
uint32_t nentries;
|
||||
entry *entries;
|
||||
entry *first_extra_entry;
|
||||
uint32_t maxentries; // total allocated size of entries
|
||||
|
||||
// Position and size of each homogeneous subrange:
|
||||
int tag_count[CONSTANT_Limit];
|
||||
int tag_base[CONSTANT_Limit];
|
||||
cpindex tag_index[CONSTANT_Limit];
|
||||
ptrlist tag_extras[CONSTANT_Limit];
|
||||
|
||||
cpindex *member_indexes; // indexed by 2*CONSTANT_Class.inord
|
||||
cpindex *getFieldIndex(entry *classRef);
|
||||
cpindex *getMethodIndex(entry *classRef);
|
||||
|
||||
inner_class **ic_index;
|
||||
inner_class **ic_child_index;
|
||||
inner_class *getIC(entry *inner);
|
||||
inner_class *getFirstChildIC(entry *outer);
|
||||
inner_class *getNextChildIC(inner_class *child);
|
||||
|
||||
int outputIndexLimit; // index limit after renumbering
|
||||
ptrlist outputEntries; // list of entry* needing output idx assigned
|
||||
|
||||
entry **hashTab;
|
||||
uint32_t hashTabLength;
|
||||
entry *&hashTabRef(byte tag, bytes &b);
|
||||
entry *ensureUtf8(bytes &b);
|
||||
entry *ensureClass(bytes &b);
|
||||
|
||||
// Well-known Utf8 symbols.
|
||||
enum
|
||||
{
|
||||
#define SNAME(n, s) s_##s,
|
||||
ALL_ATTR_DO(SNAME)
|
||||
#undef SNAME
|
||||
s_lt_init_gt, // <init>
|
||||
s_LIMIT
|
||||
};
|
||||
entry *sym[s_LIMIT];
|
||||
|
||||
// read counts from hdr, allocate main arrays
|
||||
enum
|
||||
{
|
||||
NUM_COUNTS = 12
|
||||
};
|
||||
void init(unpacker *u, int counts[NUM_COUNTS]);
|
||||
|
||||
// pointer to outer unpacker, for error checks etc.
|
||||
unpacker *u;
|
||||
|
||||
int getCount(byte tag)
|
||||
{
|
||||
assert((uint32_t)tag < CONSTANT_Limit);
|
||||
return tag_count[tag];
|
||||
}
|
||||
cpindex *getIndex(byte tag)
|
||||
{
|
||||
assert((uint32_t)tag < CONSTANT_Limit);
|
||||
return &tag_index[tag];
|
||||
}
|
||||
cpindex *getKQIndex(); // uses cur_descr
|
||||
|
||||
void expandSignatures();
|
||||
void initMemberIndexes();
|
||||
|
||||
void computeOutputOrder();
|
||||
void computeOutputIndexes();
|
||||
void resetOutputIndexes();
|
||||
};
|
||||
|
||||
/*
|
||||
* The unpacker provides the entry points to the unpack engine,
|
||||
* as well as maintains the state of the engine.
|
||||
*/
|
||||
struct unpacker
|
||||
{
|
||||
// One element of the resulting JAR.
|
||||
struct file
|
||||
{
|
||||
const char *name;
|
||||
uint64_t size;
|
||||
int modtime;
|
||||
int options;
|
||||
bytes data[2];
|
||||
// Note: If Sum(data[*].len) < size,
|
||||
// remaining bytes must be read directly from the input stream.
|
||||
bool deflate_hint()
|
||||
{
|
||||
return ((options & FO_DEFLATE_HINT) != 0);
|
||||
}
|
||||
};
|
||||
|
||||
// if running Unix-style, here are the inputs and outputs
|
||||
FILE *infileptr; // buffered
|
||||
bytes inbytes; // direct
|
||||
gunzip *gzin; // gunzip filter, if any
|
||||
jar *jarout; // output JAR file
|
||||
|
||||
// pointer to self, for U_NEW macro
|
||||
unpacker *u;
|
||||
|
||||
ptrlist mallocs; // list of guys to free when we are all done
|
||||
ptrlist tmallocs; // list of guys to free on next client request
|
||||
fillbytes smallbuf; // supplies small alloc requests
|
||||
fillbytes tsmallbuf; // supplies temporary small alloc requests
|
||||
|
||||
// option management members
|
||||
int verbose; // verbose level, 0 means no output
|
||||
int deflate_hint_or_zero; // ==0 means not set, otherwise -1 or 1
|
||||
int modification_time_or_zero;
|
||||
|
||||
// input stream
|
||||
fillbytes input; // the whole block (size is predicted, has slop too)
|
||||
bool live_input; // is the data in this block live?
|
||||
bool free_input; // must the input buffer be freed?
|
||||
byte *rp; // read pointer (< rplimit <= input.limit())
|
||||
byte *rplimit; // how much of the input block has been read?
|
||||
uint64_t bytes_read;
|
||||
int unsized_bytes_read;
|
||||
|
||||
// callback to read at least one byte, up to available input
|
||||
typedef int64_t (*read_input_fn_t)(unpacker *self, void *buf, int64_t minlen,
|
||||
int64_t maxlen);
|
||||
read_input_fn_t read_input_fn;
|
||||
|
||||
// archive header fields
|
||||
int magic, minver, majver;
|
||||
size_t archive_size;
|
||||
int archive_next_count, archive_options, archive_modtime;
|
||||
int band_headers_size;
|
||||
int file_count, attr_definition_count, ic_count, class_count;
|
||||
int default_class_minver, default_class_majver;
|
||||
int default_file_options, suppress_file_options; // not header fields
|
||||
int default_archive_modtime, default_file_modtime; // not header fields
|
||||
int code_count; // not a header field
|
||||
int files_remaining; // not a header field
|
||||
|
||||
// engine state
|
||||
band *all_bands; // indexed by band_number
|
||||
byte *meta_rp; // read-pointer into (copy of) band_headers
|
||||
constant_pool cp; // all constant pool information
|
||||
inner_class *ics; // InnerClasses
|
||||
|
||||
// output stream
|
||||
bytes output; // output block (either classfile head or tail)
|
||||
byte *wp; // write pointer (< wplimit == output.limit())
|
||||
byte *wpbase; // write pointer starting address (<= wp)
|
||||
byte *wplimit; // how much of the output block has been written?
|
||||
|
||||
// output state
|
||||
file cur_file;
|
||||
entry *cur_class; // CONSTANT_Class entry
|
||||
entry *cur_super; // CONSTANT_Class entry or nullptr
|
||||
entry *cur_descr; // CONSTANT_NameandType entry
|
||||
int cur_descr_flags; // flags corresponding to cur_descr
|
||||
int cur_class_minver, cur_class_majver;
|
||||
bool cur_class_has_local_ics;
|
||||
fillbytes cur_classfile_head;
|
||||
fillbytes cur_classfile_tail;
|
||||
int files_written; // also tells which file we're working on
|
||||
int classes_written; // also tells which class we're working on
|
||||
uint64_t bytes_written;
|
||||
intlist bcimap;
|
||||
fillbytes class_fixup_type;
|
||||
intlist class_fixup_offset;
|
||||
ptrlist class_fixup_ref;
|
||||
fillbytes code_fixup_type; // which format of branch operand?
|
||||
intlist code_fixup_offset; // location of operand needing fixup
|
||||
intlist code_fixup_source; // encoded ID of branch insn
|
||||
ptrlist requested_ics; // which ics need output?
|
||||
|
||||
// stats pertaining to multiple segments (updated on reset)
|
||||
uint64_t bytes_read_before_reset;
|
||||
uint64_t bytes_written_before_reset;
|
||||
int files_written_before_reset;
|
||||
int classes_written_before_reset;
|
||||
int segments_read_before_reset;
|
||||
|
||||
// attribute state
|
||||
struct layout_definition
|
||||
{
|
||||
uint32_t idx; // index (0..31...) which identifies this layout
|
||||
const char *name; // name of layout
|
||||
entry *nameEntry;
|
||||
const char *layout; // string of layout (not yet parsed)
|
||||
band **elems; // array of top-level layout elems (or callables)
|
||||
|
||||
bool hasCallables()
|
||||
{
|
||||
return layout[0] == '[';
|
||||
}
|
||||
band **bands()
|
||||
{
|
||||
assert(elems != nullptr);
|
||||
return elems;
|
||||
}
|
||||
};
|
||||
struct attr_definitions
|
||||
{
|
||||
unpacker *u; // pointer to self, for U_NEW macro
|
||||
int xxx_flags_hi_bn; // locator for flags, count, indexes, calls bands
|
||||
int attrc; // ATTR_CONTEXT_CLASS, etc.
|
||||
uint32_t flag_limit; // 32 or 63, depending on archive_options bit
|
||||
uint64_t predef; // mask of built-in definitions
|
||||
uint64_t redef; // mask of local flag definitions or redefinitions
|
||||
ptrlist layouts; // local (compressor-defined) defs, in index order
|
||||
int flag_count[X_ATTR_LIMIT_FLAGS_HI];
|
||||
intlist overflow_count;
|
||||
ptrlist strip_names; // what attribute names are being stripped?
|
||||
ptrlist band_stack; // Temp., used during layout parsing.
|
||||
ptrlist calls_to_link; // (ditto)
|
||||
int bands_made; // (ditto)
|
||||
|
||||
void free()
|
||||
{
|
||||
layouts.free();
|
||||
overflow_count.free();
|
||||
strip_names.free();
|
||||
band_stack.free();
|
||||
calls_to_link.free();
|
||||
}
|
||||
|
||||
// Locate the five fixed bands.
|
||||
band &xxx_flags_hi();
|
||||
band &xxx_flags_lo();
|
||||
band &xxx_attr_count();
|
||||
band &xxx_attr_indexes();
|
||||
band &xxx_attr_calls();
|
||||
band &fixed_band(int e_class_xxx);
|
||||
|
||||
// Register a new layout, and make bands for it.
|
||||
layout_definition *defineLayout(int idx, const char *name, const char *layout);
|
||||
layout_definition *defineLayout(int idx, entry *nameEntry, const char *layout);
|
||||
band **buildBands(layout_definition *lo);
|
||||
|
||||
// Parse a layout string or part of one, recursively if necessary.
|
||||
const char *parseLayout(const char *lp, band **&res, int curCble);
|
||||
const char *parseNumeral(const char *lp, int &res);
|
||||
const char *parseIntLayout(const char *lp, band *&res, byte le_kind,
|
||||
bool can_be_signed = false);
|
||||
band **popBody(int band_stack_base); // pops a body off band_stack
|
||||
|
||||
// Read data into the bands of the idx-th layout.
|
||||
void readBandData(int idx); // parse layout, make bands, read data
|
||||
void readBandData(band **body, uint32_t count); // recursive helper
|
||||
|
||||
layout_definition *getLayout(uint32_t idx)
|
||||
{
|
||||
if (idx >= (uint32_t)layouts.length())
|
||||
return nullptr;
|
||||
return (layout_definition *)layouts.get(idx);
|
||||
}
|
||||
|
||||
void setHaveLongFlags(bool z)
|
||||
{
|
||||
assert(flag_limit == 0); // not set up yet
|
||||
flag_limit = (z ? X_ATTR_LIMIT_FLAGS_HI : X_ATTR_LIMIT_NO_FLAGS_HI);
|
||||
}
|
||||
bool haveLongFlags()
|
||||
{
|
||||
assert(flag_limit == X_ATTR_LIMIT_NO_FLAGS_HI ||
|
||||
flag_limit == X_ATTR_LIMIT_FLAGS_HI);
|
||||
return flag_limit == X_ATTR_LIMIT_FLAGS_HI;
|
||||
}
|
||||
|
||||
// Return flag_count if idx is predef and not redef, else zero.
|
||||
int predefCount(uint32_t idx);
|
||||
|
||||
bool isRedefined(uint32_t idx)
|
||||
{
|
||||
if (idx >= flag_limit)
|
||||
return false;
|
||||
return (bool)((redef >> idx) & 1);
|
||||
}
|
||||
bool isPredefined(uint32_t idx)
|
||||
{
|
||||
if (idx >= flag_limit)
|
||||
return false;
|
||||
return (bool)(((predef & ~redef) >> idx) & 1);
|
||||
}
|
||||
uint64_t flagIndexMask()
|
||||
{
|
||||
return (predef | redef);
|
||||
}
|
||||
bool isIndex(uint32_t idx)
|
||||
{
|
||||
assert(flag_limit != 0); // must be set up already
|
||||
if (idx < flag_limit)
|
||||
return (bool)(((predef | redef) >> idx) & 1);
|
||||
else
|
||||
return (idx - flag_limit < (uint32_t)overflow_count.length());
|
||||
}
|
||||
int &getCount(uint32_t idx)
|
||||
{
|
||||
assert(isIndex(idx));
|
||||
if (idx < flag_limit)
|
||||
return flag_count[idx];
|
||||
else
|
||||
return overflow_count.get(idx - flag_limit);
|
||||
}
|
||||
};
|
||||
|
||||
attr_definitions attr_defs[ATTR_CONTEXT_LIMIT];
|
||||
|
||||
// Initialization
|
||||
void init(read_input_fn_t input_fn = nullptr);
|
||||
// Resets to a known sane state
|
||||
void reset();
|
||||
// Deallocates all storage.
|
||||
void free();
|
||||
// Deallocates temporary storage (volatile after next client call).
|
||||
void free_temps()
|
||||
{
|
||||
tsmallbuf.init();
|
||||
tmallocs.freeAll();
|
||||
}
|
||||
|
||||
// Option management methods
|
||||
bool set_option(const char *option, const char *value);
|
||||
const char *get_option(const char *option);
|
||||
|
||||
// Fetching input.
|
||||
bool ensure_input(int64_t more);
|
||||
byte *input_scan()
|
||||
{
|
||||
return rp;
|
||||
}
|
||||
size_t input_remaining()
|
||||
{
|
||||
return rplimit - rp;
|
||||
}
|
||||
size_t input_consumed()
|
||||
{
|
||||
return rp - input.base();
|
||||
}
|
||||
|
||||
// Entry points to the unpack engine
|
||||
static int run(int argc, char **argv); // Unix-style entry point.
|
||||
void check_options();
|
||||
void start(void *packptr = nullptr, size_t len = 0);
|
||||
void write_file_to_jar(file *f);
|
||||
void finish();
|
||||
|
||||
// Public post unpack methods
|
||||
int get_files_remaining()
|
||||
{
|
||||
return files_remaining;
|
||||
}
|
||||
int get_segments_remaining()
|
||||
{
|
||||
return archive_next_count;
|
||||
}
|
||||
file *get_next_file(); // returns nullptr on last file
|
||||
|
||||
// General purpose methods
|
||||
void *alloc(size_t size)
|
||||
{
|
||||
return alloc_heap(size, true);
|
||||
}
|
||||
void *temp_alloc(size_t size)
|
||||
{
|
||||
return alloc_heap(size, true, true);
|
||||
}
|
||||
void *alloc_heap(size_t size, bool smallOK = false, bool temp = false);
|
||||
void saveTo(bytes &b, const char *str)
|
||||
{
|
||||
saveTo(b, (byte *)str, strlen(str));
|
||||
}
|
||||
void saveTo(bytes &b, bytes &data)
|
||||
{
|
||||
saveTo(b, data.ptr, data.len);
|
||||
}
|
||||
void saveTo(bytes &b, byte *ptr, size_t len); //{ b.ptr = U_NEW...}
|
||||
const char *saveStr(const char *str)
|
||||
{
|
||||
bytes buf;
|
||||
saveTo(buf, str);
|
||||
return buf.strval();
|
||||
}
|
||||
const char *saveIntStr(int num)
|
||||
{
|
||||
char buf[30];
|
||||
sprintf(buf, "%d", num);
|
||||
return saveStr(buf);
|
||||
}
|
||||
static unpacker *current(); // find current instance
|
||||
|
||||
// Output management
|
||||
void set_output(fillbytes *which)
|
||||
{
|
||||
assert(wp == nullptr);
|
||||
which->ensureSize(1 << 12); // covers the average classfile
|
||||
wpbase = which->base();
|
||||
wp = which->limit();
|
||||
wplimit = which->end();
|
||||
}
|
||||
fillbytes *close_output(fillbytes *which = nullptr); // inverse of set_output
|
||||
|
||||
// These take an implicit parameter of wp/wplimit, and resize as necessary:
|
||||
byte *put_space(size_t len); // allocates space at wp, returns pointer
|
||||
size_t put_empty(size_t s)
|
||||
{
|
||||
byte *p = put_space(s);
|
||||
return p - wpbase;
|
||||
}
|
||||
void ensure_put_space(size_t len);
|
||||
void put_bytes(bytes &b)
|
||||
{
|
||||
b.writeTo(put_space(b.len));
|
||||
}
|
||||
void putu1(int n)
|
||||
{
|
||||
putu1_at(put_space(1), n);
|
||||
}
|
||||
void putu1_fast(int n)
|
||||
{
|
||||
putu1_at(wp++, n);
|
||||
}
|
||||
void putu2(int n); // { putu2_at(put_space(2), n); }
|
||||
void putu4(int n); // { putu4_at(put_space(4), n); }
|
||||
void putu8(int64_t n); // { putu8_at(put_space(8), n); }
|
||||
void putref(entry *e); // { putu2_at(put_space(2), putref_index(e, 2)); }
|
||||
void putu1ref(entry *e); // { putu1_at(put_space(1), putref_index(e, 1)); }
|
||||
int putref_index(entry *e, int size); // size in [1..2]
|
||||
void put_label(int curIP, int size); // size in {2,4}
|
||||
void putlayout(band **body);
|
||||
void put_stackmap_type();
|
||||
|
||||
size_t wpoffset()
|
||||
{
|
||||
return (size_t)(wp - wpbase);
|
||||
} // (unvariant across overflow)
|
||||
byte *wp_at(size_t offset)
|
||||
{
|
||||
return wpbase + offset;
|
||||
}
|
||||
uint32_t to_bci(uint32_t bii);
|
||||
void get_code_header(int &max_stack, int &max_na_locals, int &handler_count, int &cflags);
|
||||
band *ref_band_for_self_op(int bc, bool &isAloadVar, int &origBCVar);
|
||||
band *ref_band_for_op(int bc);
|
||||
|
||||
// Definitions of standard classfile int formats:
|
||||
static void putu1_at(byte *wp, int n)
|
||||
{
|
||||
assert(n == (n & 0xFF));
|
||||
wp[0] = n;
|
||||
}
|
||||
static void putu2_at(byte *wp, int n);
|
||||
static void putu4_at(byte *wp, int n);
|
||||
static void putu8_at(byte *wp, int64_t n);
|
||||
|
||||
// Private stuff
|
||||
void reset_cur_classfile();
|
||||
void write_classfile_tail();
|
||||
void write_classfile_head();
|
||||
void write_code();
|
||||
void write_bc_ops();
|
||||
void write_members(int num, int attrc); // attrc=ATTR_CONTEXT_FIELD/METHOD
|
||||
int write_attrs(int attrc, uint64_t indexBits);
|
||||
|
||||
// The readers
|
||||
void read_bands();
|
||||
void read_file_header();
|
||||
void read_cp();
|
||||
void read_cp_counts(value_stream &hdr);
|
||||
void read_attr_defs();
|
||||
void read_ics();
|
||||
void read_attrs(int attrc, int obj_count);
|
||||
void read_classes();
|
||||
void read_code_headers();
|
||||
void read_bcs();
|
||||
void read_bc_ops();
|
||||
void read_files();
|
||||
void read_Utf8_values(entry *cpMap, int len);
|
||||
void read_single_words(band &cp_band, entry *cpMap, int len);
|
||||
void read_double_words(band &cp_bands, entry *cpMap, int len);
|
||||
void read_single_refs(band &cp_band, byte refTag, entry *cpMap, int len);
|
||||
void read_double_refs(band &cp_band, byte ref1Tag, byte ref2Tag, entry *cpMap, int len);
|
||||
void read_signature_values(entry *cpMap, int len);
|
||||
};
|
175
depends/pack200/src/unpack200.cpp
Normal file
175
depends/pack200/src/unpack200.cpp
Normal file
@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "constants.h"
|
||||
#include "utils.h"
|
||||
#include "defines.h"
|
||||
#include "bytes.h"
|
||||
#include "coding.h"
|
||||
#include "unpack200.h"
|
||||
#include "unpack.h"
|
||||
#include "zip.h"
|
||||
|
||||
// Callback for fetching data, Unix style.
|
||||
static int64_t read_input_via_stdio(unpacker *u, void *buf, int64_t minlen, int64_t maxlen)
|
||||
{
|
||||
assert(u->infileptr != nullptr);
|
||||
assert(minlen <= maxlen); // don't talk nonsense
|
||||
int64_t numread = 0;
|
||||
char *bufptr = (char *)buf;
|
||||
while (numread < minlen)
|
||||
{
|
||||
// read available input, up to buf.length or maxlen
|
||||
int readlen = (1 << 16);
|
||||
if (readlen > (maxlen - numread))
|
||||
readlen = (int)(maxlen - numread);
|
||||
int nr = 0;
|
||||
|
||||
nr = (int)fread(bufptr, 1, readlen, u->infileptr);
|
||||
if (nr <= 0)
|
||||
{
|
||||
if (errno != EINTR)
|
||||
break;
|
||||
nr = 0;
|
||||
}
|
||||
numread += nr;
|
||||
bufptr += nr;
|
||||
assert(numread <= maxlen);
|
||||
}
|
||||
return numread;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
EOF_MAGIC = 0,
|
||||
BAD_MAGIC = -1
|
||||
};
|
||||
|
||||
static int read_magic(unpacker *u, char peek[], int peeklen)
|
||||
{
|
||||
assert(peeklen == 4); // magic numbers are always 4 bytes
|
||||
int64_t nr = (u->read_input_fn)(u, peek, peeklen, peeklen);
|
||||
if (nr != peeklen)
|
||||
{
|
||||
return (nr == 0) ? EOF_MAGIC : BAD_MAGIC;
|
||||
}
|
||||
int magic = 0;
|
||||
for (int i = 0; i < peeklen; i++)
|
||||
{
|
||||
magic <<= 8;
|
||||
magic += peek[i] & 0xFF;
|
||||
}
|
||||
return magic;
|
||||
}
|
||||
|
||||
void unpack_200(std::string input_path, std::string output_path)
|
||||
{
|
||||
unpacker u;
|
||||
int status = 0;
|
||||
|
||||
FILE *input = fopen(input_path.c_str(), "rb");
|
||||
if (!input)
|
||||
{
|
||||
throw std::runtime_error("Can't open input file" + input_path);
|
||||
}
|
||||
FILE *output = fopen(output_path.c_str(), "wb");
|
||||
if (!output)
|
||||
{
|
||||
fclose(output);
|
||||
throw std::runtime_error("Can't open output file" + output_path);
|
||||
}
|
||||
u.init(read_input_via_stdio);
|
||||
|
||||
// initialize jar output
|
||||
// the output takes ownership of the file handle
|
||||
jar jarout;
|
||||
jarout.init(&u);
|
||||
jarout.jarfp = output;
|
||||
|
||||
// the input doesn't
|
||||
u.infileptr = input;
|
||||
|
||||
// read the magic!
|
||||
char peek[4];
|
||||
int magic;
|
||||
magic = read_magic(&u, peek, (int)sizeof(peek));
|
||||
|
||||
// if it is a gzip encoded file, we need an extra gzip input filter
|
||||
if ((magic & GZIP_MAGIC_MASK) == GZIP_MAGIC)
|
||||
{
|
||||
gunzip *gzin = NEW(gunzip, 1);
|
||||
gzin->init(&u);
|
||||
// FIXME: why the side effects? WHY?
|
||||
u.gzin->start(magic);
|
||||
u.start();
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise, feed the bytes to the unpacker directly
|
||||
u.start(peek, sizeof(peek));
|
||||
}
|
||||
|
||||
// Note: The checks to u.aborting() are necessary to gracefully
|
||||
// terminate processing when the first segment throws an error.
|
||||
for (;;)
|
||||
{
|
||||
// Each trip through this loop unpacks one segment
|
||||
// and then resets the unpacker.
|
||||
for (unpacker::file *filep; (filep = u.get_next_file()) != nullptr;)
|
||||
{
|
||||
u.write_file_to_jar(filep);
|
||||
}
|
||||
|
||||
// Peek ahead for more data.
|
||||
magic = read_magic(&u, peek, (int)sizeof(peek));
|
||||
if (magic != (int)JAVA_PACKAGE_MAGIC)
|
||||
{
|
||||
// we do not feel strongly about this kind of thing...
|
||||
/*
|
||||
if (magic != EOF_MAGIC)
|
||||
unpack_abort("garbage after end of pack archive");
|
||||
*/
|
||||
break; // all done
|
||||
}
|
||||
|
||||
// Release all storage from parsing the old segment.
|
||||
u.reset();
|
||||
// Restart, beginning with the peek-ahead.
|
||||
u.start(peek, sizeof(peek));
|
||||
}
|
||||
u.finish();
|
||||
u.free(); // tidy up malloc blocks
|
||||
fclose(input);
|
||||
}
|
71
depends/pack200/src/utils.cpp
Normal file
71
depends/pack200/src/utils.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#include <process.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "constants.h"
|
||||
#include "defines.h"
|
||||
#include "bytes.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "unpack.h"
|
||||
|
||||
void *must_malloc(size_t size)
|
||||
{
|
||||
size_t msize = size;
|
||||
void *ptr = (msize > PSIZE_MAX) ? nullptr : malloc(msize);
|
||||
if (ptr != nullptr)
|
||||
{
|
||||
memset(ptr, 0, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error(ERROR_ENOMEM);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void unpack_abort(const char *msg)
|
||||
{
|
||||
if (msg == nullptr)
|
||||
msg = "corrupt pack file or internal error";
|
||||
throw std::runtime_error(msg);
|
||||
}
|
53
depends/pack200/src/utils.h
Normal file
53
depends/pack200/src/utils.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// Definitions of our util functions
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
void *must_malloc(size_t size);
|
||||
|
||||
// overflow management
|
||||
#define OVERFLOW ((size_t) - 1)
|
||||
#define PSIZE_MAX (OVERFLOW / 2) /* normal size limit */
|
||||
|
||||
inline size_t scale_size(size_t size, size_t scale)
|
||||
{
|
||||
return (size > PSIZE_MAX / scale) ? OVERFLOW : size * scale;
|
||||
}
|
||||
|
||||
inline size_t add_size(size_t size1, size_t size2)
|
||||
{
|
||||
return ((size1 | size2 | (size1 + size2)) > PSIZE_MAX) ? OVERFLOW : size1 + size2;
|
||||
}
|
||||
|
||||
inline size_t add_size(size_t size1, size_t size2, int size3)
|
||||
{
|
||||
return add_size(add_size(size1, size2), size3);
|
||||
}
|
||||
|
||||
struct unpacker;
|
||||
/// This throws an exception!
|
||||
extern void unpack_abort(const char *msg = nullptr);
|
589
depends/pack200/src/zip.cpp
Normal file
589
depends/pack200/src/zip.cpp
Normal file
@ -0,0 +1,589 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Note: Lifted from uncrunch.c from jdk sources
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#include "defines.h"
|
||||
#include "bytes.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "constants.h"
|
||||
#include "unpack.h"
|
||||
|
||||
#include "zip.h"
|
||||
|
||||
#include "zlib.h"
|
||||
|
||||
inline uint32_t jar::get_crc32(uint32_t c, uchar *ptr, uint32_t len)
|
||||
{
|
||||
return crc32(c, ptr, len);
|
||||
}
|
||||
|
||||
// FIXME: this is bullshit. Do real endianness detection.
|
||||
#ifdef sparc
|
||||
#define SWAP_BYTES(a) ((((a) << 8) & 0xff00) | 0x00ff) & (((a) >> 8) | 0xff00)
|
||||
#else
|
||||
#define SWAP_BYTES(a) (a)
|
||||
#endif
|
||||
|
||||
#define GET_INT_LO(a) SWAP_BYTES(a & 0xFFFF)
|
||||
|
||||
#define GET_INT_HI(a) SWAP_BYTES((a >> 16) & 0xFFFF);
|
||||
|
||||
void jar::init(unpacker *u_)
|
||||
{
|
||||
BYTES_OF(*this).clear();
|
||||
u = u_;
|
||||
u->jarout = this;
|
||||
}
|
||||
|
||||
// Write data to the ZIP output stream.
|
||||
void jar::write_data(void *buff, int len)
|
||||
{
|
||||
while (len > 0)
|
||||
{
|
||||
int rc = (int)fwrite(buff, 1, len, jarfp);
|
||||
if (rc <= 0)
|
||||
{
|
||||
fprintf(stderr, "Error: write on output file failed err=%d\n", errno);
|
||||
exit(1); // Called only from the native standalone unpacker
|
||||
}
|
||||
output_file_offset += rc;
|
||||
buff = ((char *)buff) + rc;
|
||||
len -= rc;
|
||||
}
|
||||
}
|
||||
|
||||
void jar::add_to_jar_directory(const char *fname, bool store, int modtime, int len, int clen,
|
||||
uint32_t crc)
|
||||
{
|
||||
uint32_t fname_length = (uint32_t)strlen(fname);
|
||||
ushort header[23];
|
||||
if (modtime == 0)
|
||||
modtime = default_modtime;
|
||||
uint32_t dostime = get_dostime(modtime);
|
||||
|
||||
header[0] = (ushort)SWAP_BYTES(0x4B50);
|
||||
header[1] = (ushort)SWAP_BYTES(0x0201);
|
||||
header[2] = (ushort)SWAP_BYTES(0xA);
|
||||
|
||||
// required version
|
||||
header[3] = (ushort)SWAP_BYTES(0xA);
|
||||
|
||||
// flags 02 = maximum sub-compression flag
|
||||
header[4] = (store) ? 0x0 : SWAP_BYTES(0x2);
|
||||
|
||||
// Compression method 8=deflate.
|
||||
header[5] = (store) ? 0x0 : SWAP_BYTES(0x08);
|
||||
|
||||
// Last modified date and time.
|
||||
header[6] = (ushort)GET_INT_LO(dostime);
|
||||
header[7] = (ushort)GET_INT_HI(dostime);
|
||||
|
||||
// CRC
|
||||
header[8] = (ushort)GET_INT_LO(crc);
|
||||
header[9] = (ushort)GET_INT_HI(crc);
|
||||
|
||||
// Compressed length:
|
||||
header[10] = (ushort)GET_INT_LO(clen);
|
||||
header[11] = (ushort)GET_INT_HI(clen);
|
||||
|
||||
// Uncompressed length.
|
||||
header[12] = (ushort)GET_INT_LO(len);
|
||||
header[13] = (ushort)GET_INT_HI(len);
|
||||
|
||||
// Filename length
|
||||
header[14] = (ushort)SWAP_BYTES(fname_length);
|
||||
// So called "extra field" length.
|
||||
header[15] = 0;
|
||||
// So called "comment" length.
|
||||
header[16] = 0;
|
||||
// Disk number start
|
||||
header[17] = 0;
|
||||
// File flags => binary
|
||||
header[18] = 0;
|
||||
// More file flags
|
||||
header[19] = 0;
|
||||
header[20] = 0;
|
||||
// Offset within ZIP file.
|
||||
header[21] = (ushort)GET_INT_LO(output_file_offset);
|
||||
header[22] = (ushort)GET_INT_HI(output_file_offset);
|
||||
|
||||
// Copy the whole thing into the central directory.
|
||||
central_directory.append(header, sizeof(header));
|
||||
|
||||
// Copy the fname to the header.
|
||||
central_directory.append(fname, fname_length);
|
||||
|
||||
central_directory_count++;
|
||||
}
|
||||
|
||||
void jar::write_jar_header(const char *fname, bool store, int modtime, int len, int clen,
|
||||
uint32_t crc)
|
||||
{
|
||||
uint32_t fname_length = (uint32_t)strlen(fname);
|
||||
ushort header[15];
|
||||
if (modtime == 0)
|
||||
modtime = default_modtime;
|
||||
uint32_t dostime = get_dostime(modtime);
|
||||
|
||||
// ZIP LOC magic.
|
||||
header[0] = (ushort)SWAP_BYTES(0x4B50);
|
||||
header[1] = (ushort)SWAP_BYTES(0x0403);
|
||||
|
||||
// Version
|
||||
header[2] = (ushort)SWAP_BYTES(0xA);
|
||||
|
||||
// flags 02 = maximum sub-compression flag
|
||||
header[3] = (store) ? 0x0 : SWAP_BYTES(0x2);
|
||||
|
||||
// Compression method = deflate
|
||||
header[4] = (store) ? 0x0 : SWAP_BYTES(0x08);
|
||||
|
||||
// Last modified date and time.
|
||||
header[5] = (ushort)GET_INT_LO(dostime);
|
||||
header[6] = (ushort)GET_INT_HI(dostime);
|
||||
|
||||
// CRC
|
||||
header[7] = (ushort)GET_INT_LO(crc);
|
||||
header[8] = (ushort)GET_INT_HI(crc);
|
||||
|
||||
// Compressed length:
|
||||
header[9] = (ushort)GET_INT_LO(clen);
|
||||
header[10] = (ushort)GET_INT_HI(clen);
|
||||
|
||||
// Uncompressed length.
|
||||
header[11] = (ushort)GET_INT_LO(len);
|
||||
header[12] = (ushort)GET_INT_HI(len);
|
||||
|
||||
// Filename length
|
||||
header[13] = (ushort)SWAP_BYTES(fname_length);
|
||||
// So called "extra field" length.
|
||||
header[14] = 0;
|
||||
|
||||
// Write the LOC header to the output file.
|
||||
write_data(header, (int)sizeof(header));
|
||||
|
||||
// Copy the fname to the header.
|
||||
write_data((char *)fname, (int)fname_length);
|
||||
}
|
||||
|
||||
void jar::write_central_directory()
|
||||
{
|
||||
bytes mc;
|
||||
mc.set("PACK200");
|
||||
|
||||
ushort header[11];
|
||||
|
||||
// Create the End of Central Directory structure.
|
||||
header[0] = (ushort)SWAP_BYTES(0x4B50);
|
||||
header[1] = (ushort)SWAP_BYTES(0x0605);
|
||||
// disk numbers
|
||||
header[2] = 0;
|
||||
header[3] = 0;
|
||||
// Number of entries in central directory.
|
||||
header[4] = (ushort)SWAP_BYTES(central_directory_count);
|
||||
header[5] = (ushort)SWAP_BYTES(central_directory_count);
|
||||
// Size of the central directory}
|
||||
header[6] = (ushort)GET_INT_LO((int)central_directory.size());
|
||||
header[7] = (ushort)GET_INT_HI((int)central_directory.size());
|
||||
// Offset of central directory within disk.
|
||||
header[8] = (ushort)GET_INT_LO(output_file_offset);
|
||||
header[9] = (ushort)GET_INT_HI(output_file_offset);
|
||||
// zipfile comment length;
|
||||
header[10] = (ushort)SWAP_BYTES((int)mc.len);
|
||||
|
||||
// Write the central directory.
|
||||
write_data(central_directory.b);
|
||||
|
||||
// Write the End of Central Directory structure.
|
||||
write_data(header, (int)sizeof(header));
|
||||
|
||||
// Write the comment.
|
||||
write_data(mc);
|
||||
}
|
||||
|
||||
// Public API
|
||||
|
||||
// Open a Jar file and initialize.
|
||||
void jar::openJarFile(const char *fname)
|
||||
{
|
||||
if (!jarfp)
|
||||
{
|
||||
jarfp = fopen(fname, "wb");
|
||||
if (!jarfp)
|
||||
{
|
||||
fprintf(stderr, "Error: Could not open jar file: %s\n", fname);
|
||||
exit(3); // Called only from the native standalone unpacker
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add a ZIP entry and copy the file data
|
||||
void jar::addJarEntry(const char *fname, bool deflate_hint, int modtime, bytes &head,
|
||||
bytes &tail)
|
||||
{
|
||||
int len = (int)(head.len + tail.len);
|
||||
int clen = 0;
|
||||
|
||||
uint32_t crc = get_crc32(0, Z_NULL, 0);
|
||||
if (head.len != 0)
|
||||
crc = get_crc32(crc, (uchar *)head.ptr, (uint32_t)head.len);
|
||||
if (tail.len != 0)
|
||||
crc = get_crc32(crc, (uchar *)tail.ptr, (uint32_t)tail.len);
|
||||
|
||||
bool deflate = (deflate_hint && len > 0);
|
||||
|
||||
if (deflate)
|
||||
{
|
||||
if (deflate_bytes(head, tail) == false)
|
||||
{
|
||||
deflate = false;
|
||||
}
|
||||
}
|
||||
clen = (int)((deflate) ? deflated.size() : len);
|
||||
add_to_jar_directory(fname, !deflate, modtime, len, clen, crc);
|
||||
write_jar_header(fname, !deflate, modtime, len, clen, crc);
|
||||
|
||||
if (deflate)
|
||||
{
|
||||
write_data(deflated.b);
|
||||
}
|
||||
else
|
||||
{
|
||||
write_data(head);
|
||||
write_data(tail);
|
||||
}
|
||||
}
|
||||
|
||||
// Add a ZIP entry for a directory name no data
|
||||
void jar::addDirectoryToJarFile(const char *dir_name)
|
||||
{
|
||||
bool store = true;
|
||||
add_to_jar_directory((const char *)dir_name, store, default_modtime, 0, 0, 0);
|
||||
write_jar_header((const char *)dir_name, store, default_modtime, 0, 0, 0);
|
||||
}
|
||||
|
||||
// Write out the central directory and close the jar file.
|
||||
void jar::closeJarFile(bool central)
|
||||
{
|
||||
if (jarfp)
|
||||
{
|
||||
fflush(jarfp);
|
||||
if (central)
|
||||
write_central_directory();
|
||||
fflush(jarfp);
|
||||
fclose(jarfp);
|
||||
}
|
||||
reset();
|
||||
}
|
||||
|
||||
/* Convert the date y/n/d and time h:m:s to a four byte DOS date and
|
||||
* time (date in high two bytes, time in low two bytes allowing magnitude
|
||||
* comparison).
|
||||
*/
|
||||
inline uint32_t jar::dostime(int y, int n, int d, int h, int m, int s)
|
||||
{
|
||||
return y < 1980 ? dostime(1980, 1, 1, 0, 0, 0)
|
||||
: (((uint32_t)y - 1980) << 25) | ((uint32_t)n << 21) | ((uint32_t)d << 16) |
|
||||
((uint32_t)h << 11) | ((uint32_t)m << 5) | ((uint32_t)s >> 1);
|
||||
}
|
||||
/*
|
||||
#ifdef _REENTRANT // solaris
|
||||
extern "C" struct tm *gmtime_r(const time_t *, struct tm *);
|
||||
#else
|
||||
#define gmtime_r(t, s) gmtime(t)
|
||||
#endif
|
||||
*/
|
||||
/*
|
||||
* Return the Unix time in DOS format
|
||||
*/
|
||||
uint32_t jar::get_dostime(int modtime)
|
||||
{
|
||||
// see defines.h
|
||||
if (modtime != 0 && modtime == modtime_cache)
|
||||
return dostime_cache;
|
||||
if (modtime != 0 && default_modtime == 0)
|
||||
default_modtime = modtime; // catch a reasonable default
|
||||
time_t t = modtime;
|
||||
struct tm sbuf;
|
||||
(void)memset((void *)&sbuf, 0, sizeof(sbuf));
|
||||
struct tm *s = gmtime_r(&t, &sbuf);
|
||||
modtime_cache = modtime;
|
||||
dostime_cache =
|
||||
dostime(s->tm_year + 1900, s->tm_mon + 1, s->tm_mday, s->tm_hour, s->tm_min, s->tm_sec);
|
||||
// printf("modtime %d => %d\n", modtime_cache, dostime_cache);
|
||||
return dostime_cache;
|
||||
}
|
||||
|
||||
/* Returns true on success, and will set the clen to the compressed
|
||||
length, the caller should verify if true and clen less than the
|
||||
input data
|
||||
*/
|
||||
bool jar::deflate_bytes(bytes &head, bytes &tail)
|
||||
{
|
||||
int len = (int)(head.len + tail.len);
|
||||
|
||||
z_stream zs;
|
||||
BYTES_OF(zs).clear();
|
||||
|
||||
// NOTE: the window size should always be -MAX_WBITS normally -15.
|
||||
// unzip/zipup.c and java/Deflater.c
|
||||
|
||||
int error =
|
||||
deflateInit2(&zs, Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
|
||||
if (error != Z_OK)
|
||||
{
|
||||
/*
|
||||
switch (error)
|
||||
{
|
||||
case Z_MEM_ERROR:
|
||||
PRINTCR((2, "Error: deflate error : Out of memory \n"));
|
||||
break;
|
||||
case Z_STREAM_ERROR:
|
||||
PRINTCR((2, "Error: deflate error : Invalid compression level \n"));
|
||||
break;
|
||||
case Z_VERSION_ERROR:
|
||||
PRINTCR((2, "Error: deflate error : Invalid version\n"));
|
||||
break;
|
||||
default:
|
||||
PRINTCR((2, "Error: Internal deflate error error = %d\n", error));
|
||||
}
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
deflated.empty();
|
||||
zs.next_out = (uchar *)deflated.grow(len + (len / 2));
|
||||
zs.avail_out = (int)deflated.size();
|
||||
|
||||
zs.next_in = (uchar *)head.ptr;
|
||||
zs.avail_in = (int)head.len;
|
||||
|
||||
bytes *first = &head;
|
||||
bytes *last = &tail;
|
||||
if (last->len == 0)
|
||||
{
|
||||
first = nullptr;
|
||||
last = &head;
|
||||
}
|
||||
else if (first->len == 0)
|
||||
{
|
||||
first = nullptr;
|
||||
}
|
||||
|
||||
if (first != nullptr && error == Z_OK)
|
||||
{
|
||||
zs.next_in = (uchar *)first->ptr;
|
||||
zs.avail_in = (int)first->len;
|
||||
error = deflate(&zs, Z_NO_FLUSH);
|
||||
}
|
||||
if (error == Z_OK)
|
||||
{
|
||||
zs.next_in = (uchar *)last->ptr;
|
||||
zs.avail_in = (int)last->len;
|
||||
error = deflate(&zs, Z_FINISH);
|
||||
}
|
||||
if (error == Z_STREAM_END)
|
||||
{
|
||||
if (len > (int)zs.total_out)
|
||||
{
|
||||
deflated.b.len = zs.total_out;
|
||||
deflateEnd(&zs);
|
||||
return true;
|
||||
}
|
||||
deflateEnd(&zs);
|
||||
return false;
|
||||
}
|
||||
|
||||
deflateEnd(&zs);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Callback for fetching data from a GZIP input stream
|
||||
static int64_t read_input_via_gzip(unpacker *u, void *buf, int64_t minlen, int64_t maxlen)
|
||||
{
|
||||
assert(minlen <= maxlen); // don't talk nonsense
|
||||
int64_t numread = 0;
|
||||
char *bufptr = (char *)buf;
|
||||
char *inbuf = u->gzin->inbuf;
|
||||
size_t inbuflen = sizeof(u->gzin->inbuf);
|
||||
unpacker::read_input_fn_t read_gzin_fn = (unpacker::read_input_fn_t)u->gzin->read_input_fn;
|
||||
z_stream &zs = *(z_stream *)u->gzin->zstream;
|
||||
while (numread < minlen)
|
||||
{
|
||||
int readlen = (1 << 16); // pretty arbitrary
|
||||
if (readlen > (maxlen - numread))
|
||||
readlen = (int)(maxlen - numread);
|
||||
zs.next_out = (uchar *)bufptr;
|
||||
zs.avail_out = readlen;
|
||||
if (zs.avail_in == 0)
|
||||
{
|
||||
zs.avail_in = (int)read_gzin_fn(u, inbuf, 1, inbuflen);
|
||||
zs.next_in = (uchar *)inbuf;
|
||||
}
|
||||
int error = inflate(&zs, Z_NO_FLUSH);
|
||||
if (error != Z_OK && error != Z_STREAM_END)
|
||||
{
|
||||
unpack_abort("error inflating input");
|
||||
break;
|
||||
}
|
||||
int nr = readlen - zs.avail_out;
|
||||
numread += nr;
|
||||
bufptr += nr;
|
||||
assert(numread <= maxlen);
|
||||
if (error == Z_STREAM_END)
|
||||
{
|
||||
enum
|
||||
{
|
||||
TRAILER_LEN = 8
|
||||
};
|
||||
// skip 8-byte trailer
|
||||
if (zs.avail_in >= TRAILER_LEN)
|
||||
{
|
||||
zs.avail_in -= TRAILER_LEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Bug: 5023768,we read past the TRAILER_LEN to see if there is
|
||||
// any extraneous data, as we dont support concatenated .gz
|
||||
// files just yet.
|
||||
int extra = (int)read_gzin_fn(u, inbuf, 1, inbuflen);
|
||||
zs.avail_in += extra - TRAILER_LEN;
|
||||
}
|
||||
// %%% should check final CRC and length here
|
||||
// %%% should check for concatenated *.gz files here
|
||||
if (zs.avail_in > 0)
|
||||
unpack_abort("garbage after end of deflated input stream");
|
||||
// pop this filter off:
|
||||
u->gzin->free();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// fprintf(u->errstrm, "readInputFn(%d,%d) => %d (gunzip)\n",
|
||||
// (int)minlen, (int)maxlen, (int)numread);
|
||||
return numread;
|
||||
}
|
||||
|
||||
void gunzip::init(unpacker *u_)
|
||||
{
|
||||
BYTES_OF(*this).clear();
|
||||
u = u_;
|
||||
assert(u->gzin == nullptr); // once only, please
|
||||
read_input_fn = (void *)u->read_input_fn;
|
||||
zstream = NEW(z_stream, 1);
|
||||
u->gzin = this;
|
||||
u->read_input_fn = read_input_via_gzip;
|
||||
}
|
||||
|
||||
void gunzip::start(int magic)
|
||||
{
|
||||
assert((magic & GZIP_MAGIC_MASK) == GZIP_MAGIC);
|
||||
int gz_flg = (magic & 0xFF); // keep "flg", discard other 3 bytes
|
||||
enum
|
||||
{
|
||||
FHCRC = (1 << 1),
|
||||
FEXTRA = (1 << 2),
|
||||
FNAME = (1 << 3),
|
||||
FCOMMENT = (1 << 4)
|
||||
};
|
||||
char gz_mtime[4];
|
||||
char gz_xfl[1];
|
||||
char gz_os[1];
|
||||
char gz_extra_len[2];
|
||||
char gz_hcrc[2];
|
||||
char gz_ignore;
|
||||
// do not save extra, name, comment
|
||||
read_fixed_field(gz_mtime, sizeof(gz_mtime));
|
||||
read_fixed_field(gz_xfl, sizeof(gz_xfl));
|
||||
read_fixed_field(gz_os, sizeof(gz_os));
|
||||
if (gz_flg & FEXTRA)
|
||||
{
|
||||
read_fixed_field(gz_extra_len, sizeof(gz_extra_len));
|
||||
int extra_len = gz_extra_len[0] & 0xFF;
|
||||
extra_len += (gz_extra_len[1] & 0xFF) << 8;
|
||||
for (; extra_len > 0; extra_len--)
|
||||
{
|
||||
read_fixed_field(&gz_ignore, 1);
|
||||
}
|
||||
}
|
||||
int null_terms = 0;
|
||||
if (gz_flg & FNAME)
|
||||
null_terms++;
|
||||
if (gz_flg & FCOMMENT)
|
||||
null_terms++;
|
||||
for (; null_terms; null_terms--)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
gz_ignore = 0;
|
||||
read_fixed_field(&gz_ignore, 1);
|
||||
if (gz_ignore == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (gz_flg & FHCRC)
|
||||
read_fixed_field(gz_hcrc, sizeof(gz_hcrc));
|
||||
|
||||
// now the input stream is ready to read into the inflater
|
||||
int error = inflateInit2((z_stream *)zstream, -MAX_WBITS);
|
||||
if (error != Z_OK)
|
||||
{
|
||||
unpack_abort("cannot create input");
|
||||
}
|
||||
}
|
||||
|
||||
void gunzip::free()
|
||||
{
|
||||
assert(u->gzin == this);
|
||||
u->gzin = nullptr;
|
||||
u->read_input_fn = (unpacker::read_input_fn_t) this->read_input_fn;
|
||||
inflateEnd((z_stream *)zstream);
|
||||
::free(zstream);
|
||||
zstream = nullptr;
|
||||
::free(this);
|
||||
}
|
||||
|
||||
void gunzip::read_fixed_field(char *buf, size_t buflen)
|
||||
{
|
||||
int64_t nr = ((unpacker::read_input_fn_t)read_input_fn)(u, buf, buflen, buflen);
|
||||
if ((size_t)nr != buflen)
|
||||
unpack_abort("short stream header");
|
||||
}
|
110
depends/pack200/src/zip.h
Normal file
110
depends/pack200/src/zip.h
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned char uchar;
|
||||
|
||||
struct unpacker;
|
||||
|
||||
struct jar
|
||||
{
|
||||
// JAR file writer
|
||||
FILE *jarfp;
|
||||
int default_modtime;
|
||||
|
||||
// Used by unix2dostime:
|
||||
int modtime_cache;
|
||||
uint32_t dostime_cache;
|
||||
|
||||
// Private members
|
||||
fillbytes central_directory;
|
||||
ushort central_directory_count;
|
||||
uint32_t output_file_offset;
|
||||
fillbytes deflated; // temporary buffer
|
||||
|
||||
// pointer to outer unpacker, for error checks etc.
|
||||
unpacker *u;
|
||||
|
||||
// Public Methods
|
||||
void openJarFile(const char *fname);
|
||||
void addJarEntry(const char *fname, bool deflate_hint, int modtime, bytes &head,
|
||||
bytes &tail);
|
||||
void addDirectoryToJarFile(const char *dir_name);
|
||||
void closeJarFile(bool central);
|
||||
|
||||
void init(unpacker *u_);
|
||||
|
||||
void free()
|
||||
{
|
||||
central_directory.free();
|
||||
deflated.free();
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
free();
|
||||
init(u);
|
||||
}
|
||||
|
||||
// Private Methods
|
||||
void write_data(void *ptr, int len);
|
||||
void write_data(bytes &b)
|
||||
{
|
||||
write_data(b.ptr, (int)b.len);
|
||||
}
|
||||
void add_to_jar_directory(const char *fname, bool store, int modtime, int len, int clen,
|
||||
uint32_t crc);
|
||||
void write_jar_header(const char *fname, bool store, int modtime, int len, int clen,
|
||||
unsigned int crc);
|
||||
void write_central_directory();
|
||||
uint32_t dostime(int y, int n, int d, int h, int m, int s);
|
||||
uint32_t get_dostime(int modtime);
|
||||
|
||||
// The definitions of these depend on the NO_ZLIB option:
|
||||
bool deflate_bytes(bytes &head, bytes &tail);
|
||||
static uint32_t get_crc32(uint32_t c, unsigned char *ptr, uint32_t len);
|
||||
};
|
||||
|
||||
struct gunzip
|
||||
{
|
||||
// optional gzip input stream control block
|
||||
|
||||
// pointer to outer unpacker, for error checks etc.
|
||||
unpacker *u;
|
||||
|
||||
void *read_input_fn; // underlying \bchar\b stream
|
||||
void *zstream; // inflater state
|
||||
char inbuf[1 << 14]; // input buffer
|
||||
|
||||
void init(unpacker *u_); // pushes new value on u->read_input_fn
|
||||
|
||||
void free();
|
||||
|
||||
void start(int magic);
|
||||
|
||||
// private stuff
|
||||
void read_fixed_field(char *buf, size_t buflen);
|
||||
};
|
@ -5,7 +5,8 @@ project(quazip)
|
||||
IF(UNIX)
|
||||
find_package(ZLIB REQUIRED)
|
||||
ELSE(UNIX)
|
||||
SET(ZLIB_INCLUDE_DIRS "${QT_ROOT}/src/3rdparty/zlib" CACHE PATH "Path to ZLIB headers of Qt")
|
||||
get_filename_component (ZLIB_FOUND_DIR "${Qt5Core_DIR}/../../../include/QtZlib" ABSOLUTE)
|
||||
SET(ZLIB_INCLUDE_DIRS ${ZLIB_FOUND_DIR} CACHE PATH "Path to ZLIB headers of Qt")
|
||||
SET(ZLIB_LIBRARIES "")
|
||||
IF(NOT EXISTS "${ZLIB_INCLUDE_DIRS}/zlib.h")
|
||||
MESSAGE("Please specify a valid zlib include dir")
|
||||
@ -31,7 +32,7 @@ ADD_DEFINITIONS(-DQUAZIP_STATIC)
|
||||
#qt5_wrap_cpp(MOC_SRCS ${PUBLIC_HEADERS})
|
||||
#set(SRCS ${SRCS} ${MOC_SRCS})
|
||||
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
#set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
add_library(quazip STATIC ${SRCS})
|
||||
QT5_USE_MODULES(quazip Core)
|
||||
|
@ -75,7 +75,6 @@ bool ensureFilePathExists(QString filenamepath)
|
||||
QDir dir;
|
||||
QString ensuredPath = a.path();
|
||||
bool success = dir.mkpath ( ensuredPath );
|
||||
qDebug() << "ensureFilePathExists:" << success << ensuredPath << filenamepath;
|
||||
return success;
|
||||
}
|
||||
|
||||
@ -85,7 +84,6 @@ bool ensureFolderPathExists(QString foldernamepath)
|
||||
QDir dir;
|
||||
QString ensuredPath = a.filePath();
|
||||
bool success = dir.mkpath ( ensuredPath );
|
||||
qDebug() << "ensureFolderPathExists:" << success << ensuredPath << foldernamepath;
|
||||
return success;
|
||||
}
|
||||
|
||||
|
32
depends/xz-embedded/CMakeLists.txt
Normal file
32
depends/xz-embedded/CMakeLists.txt
Normal file
@ -0,0 +1,32 @@
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
project(xz-embedded)
|
||||
|
||||
option(XZ_BUILD_BCJ "Build xz-embedded with BCJ support (native binary optimization)" OFF)
|
||||
option(XZ_BUILD_CRC64 "Build xz-embedded with CRC64 checksum support" ON)
|
||||
option(XZ_BUILD_MINIDEC "Build a tiny utility that decompresses xz streams" OFF)
|
||||
|
||||
set(CMAKE_C_FLAGS "-std=c99")
|
||||
|
||||
include_directories(include)
|
||||
SET(XZ_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include" PARENT_SCOPE)
|
||||
|
||||
# See include/xz.h for manual feature configuration
|
||||
# tweak this list and xz.h to fit your needs
|
||||
|
||||
set(XZ_SOURCES
|
||||
include/xz.h
|
||||
src/xz_config.h
|
||||
src/xz_crc32.c
|
||||
src/xz_crc64.c
|
||||
src/xz_dec_lzma2.c
|
||||
src/xz_dec_stream.c
|
||||
src/xz_lzma2.h
|
||||
src/xz_private.h
|
||||
src/xz_stream.h
|
||||
# src/xz_dec_bcj.c
|
||||
)
|
||||
# TODO: look into what would be needed for plain old lzma
|
||||
|
||||
add_library(xz-embedded STATIC ${XZ_SOURCES})
|
||||
add_executable(xzminidec xzminidec.c)
|
||||
target_link_libraries(xzminidec xz-embedded)
|
319
depends/xz-embedded/include/xz.h
Normal file
319
depends/xz-embedded/include/xz.h
Normal file
@ -0,0 +1,319 @@
|
||||
/*
|
||||
* XZ decompressor
|
||||
*
|
||||
* Authors: Lasse Collin <lasse.collin@tukaani.org>
|
||||
* Igor Pavlov <http://7-zip.org/>
|
||||
*
|
||||
* This file has been put into the public domain.
|
||||
* You can do whatever you want with this file.
|
||||
*/
|
||||
|
||||
#ifndef XZ_H
|
||||
#define XZ_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
# include <linux/stddef.h>
|
||||
# include <linux/types.h>
|
||||
#else
|
||||
# include <stddef.h>
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Definitions that determine available features */
|
||||
#define XZ_DEC_ANY_CHECK 1
|
||||
#define XZ_USE_CRC64 1
|
||||
|
||||
// native machine code compression stuff
|
||||
/*
|
||||
#define XZ_DEC_X86
|
||||
#define XZ_DEC_POWERPC
|
||||
#define XZ_DEC_IA64
|
||||
#define XZ_DEC_ARM
|
||||
#define XZ_DEC_ARMTHUMB
|
||||
#define XZ_DEC_SPARC
|
||||
*/
|
||||
|
||||
|
||||
/* In Linux, this is used to make extern functions static when needed. */
|
||||
#ifndef XZ_EXTERN
|
||||
# define XZ_EXTERN extern
|
||||
#endif
|
||||
|
||||
/**
|
||||
* enum xz_mode - Operation mode
|
||||
*
|
||||
* @XZ_SINGLE: Single-call mode. This uses less RAM than
|
||||
* than multi-call modes, because the LZMA2
|
||||
* dictionary doesn't need to be allocated as
|
||||
* part of the decoder state. All required data
|
||||
* structures are allocated at initialization,
|
||||
* so xz_dec_run() cannot return XZ_MEM_ERROR.
|
||||
* @XZ_PREALLOC: Multi-call mode with preallocated LZMA2
|
||||
* dictionary buffer. All data structures are
|
||||
* allocated at initialization, so xz_dec_run()
|
||||
* cannot return XZ_MEM_ERROR.
|
||||
* @XZ_DYNALLOC: Multi-call mode. The LZMA2 dictionary is
|
||||
* allocated once the required size has been
|
||||
* parsed from the stream headers. If the
|
||||
* allocation fails, xz_dec_run() will return
|
||||
* XZ_MEM_ERROR.
|
||||
*
|
||||
* It is possible to enable support only for a subset of the above
|
||||
* modes at compile time by defining XZ_DEC_SINGLE, XZ_DEC_PREALLOC,
|
||||
* or XZ_DEC_DYNALLOC. The xz_dec kernel module is always compiled
|
||||
* with support for all operation modes, but the preboot code may
|
||||
* be built with fewer features to minimize code size.
|
||||
*/
|
||||
enum xz_mode {
|
||||
XZ_SINGLE,
|
||||
XZ_PREALLOC,
|
||||
XZ_DYNALLOC
|
||||
};
|
||||
|
||||
/**
|
||||
* enum xz_ret - Return codes
|
||||
* @XZ_OK: Everything is OK so far. More input or more
|
||||
* output space is required to continue. This
|
||||
* return code is possible only in multi-call mode
|
||||
* (XZ_PREALLOC or XZ_DYNALLOC).
|
||||
* @XZ_STREAM_END: Operation finished successfully.
|
||||
* @XZ_UNSUPPORTED_CHECK: Integrity check type is not supported. Decoding
|
||||
* is still possible in multi-call mode by simply
|
||||
* calling xz_dec_run() again.
|
||||
* Note that this return value is used only if
|
||||
* XZ_DEC_ANY_CHECK was defined at build time,
|
||||
* which is not used in the kernel. Unsupported
|
||||
* check types return XZ_OPTIONS_ERROR if
|
||||
* XZ_DEC_ANY_CHECK was not defined at build time.
|
||||
* @XZ_MEM_ERROR: Allocating memory failed. This return code is
|
||||
* possible only if the decoder was initialized
|
||||
* with XZ_DYNALLOC. The amount of memory that was
|
||||
* tried to be allocated was no more than the
|
||||
* dict_max argument given to xz_dec_init().
|
||||
* @XZ_MEMLIMIT_ERROR: A bigger LZMA2 dictionary would be needed than
|
||||
* allowed by the dict_max argument given to
|
||||
* xz_dec_init(). This return value is possible
|
||||
* only in multi-call mode (XZ_PREALLOC or
|
||||
* XZ_DYNALLOC); the single-call mode (XZ_SINGLE)
|
||||
* ignores the dict_max argument.
|
||||
* @XZ_FORMAT_ERROR: File format was not recognized (wrong magic
|
||||
* bytes).
|
||||
* @XZ_OPTIONS_ERROR: This implementation doesn't support the requested
|
||||
* compression options. In the decoder this means
|
||||
* that the header CRC32 matches, but the header
|
||||
* itself specifies something that we don't support.
|
||||
* @XZ_DATA_ERROR: Compressed data is corrupt.
|
||||
* @XZ_BUF_ERROR: Cannot make any progress. Details are slightly
|
||||
* different between multi-call and single-call
|
||||
* mode; more information below.
|
||||
*
|
||||
* In multi-call mode, XZ_BUF_ERROR is returned when two consecutive calls
|
||||
* to XZ code cannot consume any input and cannot produce any new output.
|
||||
* This happens when there is no new input available, or the output buffer
|
||||
* is full while at least one output byte is still pending. Assuming your
|
||||
* code is not buggy, you can get this error only when decoding a compressed
|
||||
* stream that is truncated or otherwise corrupt.
|
||||
*
|
||||
* In single-call mode, XZ_BUF_ERROR is returned only when the output buffer
|
||||
* is too small or the compressed input is corrupt in a way that makes the
|
||||
* decoder produce more output than the caller expected. When it is
|
||||
* (relatively) clear that the compressed input is truncated, XZ_DATA_ERROR
|
||||
* is used instead of XZ_BUF_ERROR.
|
||||
*/
|
||||
enum xz_ret {
|
||||
XZ_OK,
|
||||
XZ_STREAM_END,
|
||||
XZ_UNSUPPORTED_CHECK,
|
||||
XZ_MEM_ERROR,
|
||||
XZ_MEMLIMIT_ERROR,
|
||||
XZ_FORMAT_ERROR,
|
||||
XZ_OPTIONS_ERROR,
|
||||
XZ_DATA_ERROR,
|
||||
XZ_BUF_ERROR
|
||||
};
|
||||
|
||||
/**
|
||||
* struct xz_buf - Passing input and output buffers to XZ code
|
||||
* @in: Beginning of the input buffer. This may be NULL if and only
|
||||
* if in_pos is equal to in_size.
|
||||
* @in_pos: Current position in the input buffer. This must not exceed
|
||||
* in_size.
|
||||
* @in_size: Size of the input buffer
|
||||
* @out: Beginning of the output buffer. This may be NULL if and only
|
||||
* if out_pos is equal to out_size.
|
||||
* @out_pos: Current position in the output buffer. This must not exceed
|
||||
* out_size.
|
||||
* @out_size: Size of the output buffer
|
||||
*
|
||||
* Only the contents of the output buffer from out[out_pos] onward, and
|
||||
* the variables in_pos and out_pos are modified by the XZ code.
|
||||
*/
|
||||
struct xz_buf {
|
||||
const uint8_t *in;
|
||||
size_t in_pos;
|
||||
size_t in_size;
|
||||
|
||||
uint8_t *out;
|
||||
size_t out_pos;
|
||||
size_t out_size;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct xz_dec - Opaque type to hold the XZ decoder state
|
||||
*/
|
||||
struct xz_dec;
|
||||
|
||||
/**
|
||||
* xz_dec_init() - Allocate and initialize a XZ decoder state
|
||||
* @mode: Operation mode
|
||||
* @dict_max: Maximum size of the LZMA2 dictionary (history buffer) for
|
||||
* multi-call decoding. This is ignored in single-call mode
|
||||
* (mode == XZ_SINGLE). LZMA2 dictionary is always 2^n bytes
|
||||
* or 2^n + 2^(n-1) bytes (the latter sizes are less common
|
||||
* in practice), so other values for dict_max don't make sense.
|
||||
* In the kernel, dictionary sizes of 64 KiB, 128 KiB, 256 KiB,
|
||||
* 512 KiB, and 1 MiB are probably the only reasonable values,
|
||||
* except for kernel and initramfs images where a bigger
|
||||
* dictionary can be fine and useful.
|
||||
*
|
||||
* Single-call mode (XZ_SINGLE): xz_dec_run() decodes the whole stream at
|
||||
* once. The caller must provide enough output space or the decoding will
|
||||
* fail. The output space is used as the dictionary buffer, which is why
|
||||
* there is no need to allocate the dictionary as part of the decoder's
|
||||
* internal state.
|
||||
*
|
||||
* Because the output buffer is used as the workspace, streams encoded using
|
||||
* a big dictionary are not a problem in single-call mode. It is enough that
|
||||
* the output buffer is big enough to hold the actual uncompressed data; it
|
||||
* can be smaller than the dictionary size stored in the stream headers.
|
||||
*
|
||||
* Multi-call mode with preallocated dictionary (XZ_PREALLOC): dict_max bytes
|
||||
* of memory is preallocated for the LZMA2 dictionary. This way there is no
|
||||
* risk that xz_dec_run() could run out of memory, since xz_dec_run() will
|
||||
* never allocate any memory. Instead, if the preallocated dictionary is too
|
||||
* small for decoding the given input stream, xz_dec_run() will return
|
||||
* XZ_MEMLIMIT_ERROR. Thus, it is important to know what kind of data will be
|
||||
* decoded to avoid allocating excessive amount of memory for the dictionary.
|
||||
*
|
||||
* Multi-call mode with dynamically allocated dictionary (XZ_DYNALLOC):
|
||||
* dict_max specifies the maximum allowed dictionary size that xz_dec_run()
|
||||
* may allocate once it has parsed the dictionary size from the stream
|
||||
* headers. This way excessive allocations can be avoided while still
|
||||
* limiting the maximum memory usage to a sane value to prevent running the
|
||||
* system out of memory when decompressing streams from untrusted sources.
|
||||
*
|
||||
* On success, xz_dec_init() returns a pointer to struct xz_dec, which is
|
||||
* ready to be used with xz_dec_run(). If memory allocation fails,
|
||||
* xz_dec_init() returns NULL.
|
||||
*/
|
||||
XZ_EXTERN struct xz_dec *xz_dec_init(enum xz_mode mode, uint32_t dict_max);
|
||||
|
||||
/**
|
||||
* xz_dec_run() - Run the XZ decoder
|
||||
* @s: Decoder state allocated using xz_dec_init()
|
||||
* @b: Input and output buffers
|
||||
*
|
||||
* The possible return values depend on build options and operation mode.
|
||||
* See enum xz_ret for details.
|
||||
*
|
||||
* Note that if an error occurs in single-call mode (return value is not
|
||||
* XZ_STREAM_END), b->in_pos and b->out_pos are not modified and the
|
||||
* contents of the output buffer from b->out[b->out_pos] onward are
|
||||
* undefined. This is true even after XZ_BUF_ERROR, because with some filter
|
||||
* chains, there may be a second pass over the output buffer, and this pass
|
||||
* cannot be properly done if the output buffer is truncated. Thus, you
|
||||
* cannot give the single-call decoder a too small buffer and then expect to
|
||||
* get that amount valid data from the beginning of the stream. You must use
|
||||
* the multi-call decoder if you don't want to uncompress the whole stream.
|
||||
*/
|
||||
XZ_EXTERN enum xz_ret xz_dec_run(struct xz_dec *s, struct xz_buf *b);
|
||||
|
||||
/**
|
||||
* xz_dec_reset() - Reset an already allocated decoder state
|
||||
* @s: Decoder state allocated using xz_dec_init()
|
||||
*
|
||||
* This function can be used to reset the multi-call decoder state without
|
||||
* freeing and reallocating memory with xz_dec_end() and xz_dec_init().
|
||||
*
|
||||
* In single-call mode, xz_dec_reset() is always called in the beginning of
|
||||
* xz_dec_run(). Thus, explicit call to xz_dec_reset() is useful only in
|
||||
* multi-call mode.
|
||||
*/
|
||||
XZ_EXTERN void xz_dec_reset(struct xz_dec *s);
|
||||
|
||||
/**
|
||||
* xz_dec_end() - Free the memory allocated for the decoder state
|
||||
* @s: Decoder state allocated using xz_dec_init(). If s is NULL,
|
||||
* this function does nothing.
|
||||
*/
|
||||
XZ_EXTERN void xz_dec_end(struct xz_dec *s);
|
||||
|
||||
/*
|
||||
* Standalone build (userspace build or in-kernel build for boot time use)
|
||||
* needs a CRC32 implementation. For normal in-kernel use, kernel's own
|
||||
* CRC32 module is used instead, and users of this module don't need to
|
||||
* care about the functions below.
|
||||
*/
|
||||
#ifndef XZ_INTERNAL_CRC32
|
||||
# ifdef __KERNEL__
|
||||
# define XZ_INTERNAL_CRC32 0
|
||||
# else
|
||||
# define XZ_INTERNAL_CRC32 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If CRC64 support has been enabled with XZ_USE_CRC64, a CRC64
|
||||
* implementation is needed too.
|
||||
*/
|
||||
#ifndef XZ_USE_CRC64
|
||||
# undef XZ_INTERNAL_CRC64
|
||||
# define XZ_INTERNAL_CRC64 0
|
||||
#endif
|
||||
#ifndef XZ_INTERNAL_CRC64
|
||||
# ifdef __KERNEL__
|
||||
# error Using CRC64 in the kernel has not been implemented.
|
||||
# else
|
||||
# define XZ_INTERNAL_CRC64 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if XZ_INTERNAL_CRC32
|
||||
/*
|
||||
* This must be called before any other xz_* function to initialize
|
||||
* the CRC32 lookup table.
|
||||
*/
|
||||
XZ_EXTERN void xz_crc32_init(void);
|
||||
|
||||
/*
|
||||
* Update CRC32 value using the polynomial from IEEE-802.3. To start a new
|
||||
* calculation, the third argument must be zero. To continue the calculation,
|
||||
* the previously returned value is passed as the third argument.
|
||||
*/
|
||||
XZ_EXTERN uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc);
|
||||
#endif
|
||||
|
||||
#if XZ_INTERNAL_CRC64
|
||||
/*
|
||||
* This must be called before any other xz_* function (except xz_crc32_init())
|
||||
* to initialize the CRC64 lookup table.
|
||||
*/
|
||||
XZ_EXTERN void xz_crc64_init(void);
|
||||
|
||||
/*
|
||||
* Update CRC64 value using the polynomial from ECMA-182. To start a new
|
||||
* calculation, the third argument must be zero. To continue the calculation,
|
||||
* the previously returned value is passed as the third argument.
|
||||
*/
|
||||
XZ_EXTERN uint64_t xz_crc64(const uint8_t *buf, size_t size, uint64_t crc);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
124
depends/xz-embedded/src/xz_config.h
Normal file
124
depends/xz-embedded/src/xz_config.h
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Private includes and definitions for userspace use of XZ Embedded
|
||||
*
|
||||
* Author: Lasse Collin <lasse.collin@tukaani.org>
|
||||
*
|
||||
* This file has been put into the public domain.
|
||||
* You can do whatever you want with this file.
|
||||
*/
|
||||
|
||||
#ifndef XZ_CONFIG_H
|
||||
#define XZ_CONFIG_H
|
||||
|
||||
/* Uncomment to enable CRC64 support. */
|
||||
/* #define XZ_USE_CRC64 */
|
||||
|
||||
/* Uncomment as needed to enable BCJ filter decoders. */
|
||||
/* #define XZ_DEC_X86 */
|
||||
/* #define XZ_DEC_POWERPC */
|
||||
/* #define XZ_DEC_IA64 */
|
||||
/* #define XZ_DEC_ARM */
|
||||
/* #define XZ_DEC_ARMTHUMB */
|
||||
/* #define XZ_DEC_SPARC */
|
||||
|
||||
/*
|
||||
* MSVC doesn't support modern C but XZ Embedded is mostly C89
|
||||
* so these are enough.
|
||||
*/
|
||||
#ifdef _MSC_VER
|
||||
typedef unsigned char bool;
|
||||
# define true 1
|
||||
# define false 0
|
||||
# define inline __inline
|
||||
#else
|
||||
# include <stdbool.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "xz.h"
|
||||
|
||||
#define kmalloc(size, flags) malloc(size)
|
||||
#define kfree(ptr) free(ptr)
|
||||
#define vmalloc(size) malloc(size)
|
||||
#define vfree(ptr) free(ptr)
|
||||
|
||||
#define memeq(a, b, size) (memcmp(a, b, size) == 0)
|
||||
#define memzero(buf, size) memset(buf, 0, size)
|
||||
|
||||
#ifndef min
|
||||
# define min(x, y) ((x) < (y) ? (x) : (y))
|
||||
#endif
|
||||
#define min_t(type, x, y) min(x, y)
|
||||
|
||||
/*
|
||||
* Some functions have been marked with __always_inline to keep the
|
||||
* performance reasonable even when the compiler is optimizing for
|
||||
* small code size. You may be able to save a few bytes by #defining
|
||||
* __always_inline to plain inline, but don't complain if the code
|
||||
* becomes slow.
|
||||
*
|
||||
* NOTE: System headers on GNU/Linux may #define this macro already,
|
||||
* so if you want to change it, you need to #undef it first.
|
||||
*/
|
||||
#ifndef __always_inline
|
||||
# ifdef __GNUC__
|
||||
# define __always_inline \
|
||||
inline __attribute__((__always_inline__))
|
||||
# else
|
||||
# define __always_inline inline
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Inline functions to access unaligned unsigned 32-bit integers */
|
||||
#ifndef get_unaligned_le32
|
||||
static inline uint32_t get_unaligned_le32(const uint8_t *buf)
|
||||
{
|
||||
return (uint32_t)buf[0]
|
||||
| ((uint32_t)buf[1] << 8)
|
||||
| ((uint32_t)buf[2] << 16)
|
||||
| ((uint32_t)buf[3] << 24);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef get_unaligned_be32
|
||||
static inline uint32_t get_unaligned_be32(const uint8_t *buf)
|
||||
{
|
||||
return (uint32_t)(buf[0] << 24)
|
||||
| ((uint32_t)buf[1] << 16)
|
||||
| ((uint32_t)buf[2] << 8)
|
||||
| (uint32_t)buf[3];
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef put_unaligned_le32
|
||||
static inline void put_unaligned_le32(uint32_t val, uint8_t *buf)
|
||||
{
|
||||
buf[0] = (uint8_t)val;
|
||||
buf[1] = (uint8_t)(val >> 8);
|
||||
buf[2] = (uint8_t)(val >> 16);
|
||||
buf[3] = (uint8_t)(val >> 24);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef put_unaligned_be32
|
||||
static inline void put_unaligned_be32(uint32_t val, uint8_t *buf)
|
||||
{
|
||||
buf[0] = (uint8_t)(val >> 24);
|
||||
buf[1] = (uint8_t)(val >> 16);
|
||||
buf[2] = (uint8_t)(val >> 8);
|
||||
buf[3] = (uint8_t)val;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Use get_unaligned_le32() also for aligned access for simplicity. On
|
||||
* little endian systems, #define get_le32(ptr) (*(const uint32_t *)(ptr))
|
||||
* could save a few bytes in code size.
|
||||
*/
|
||||
#ifndef get_le32
|
||||
# define get_le32 get_unaligned_le32
|
||||
#endif
|
||||
|
||||
#endif
|
59
depends/xz-embedded/src/xz_crc32.c
Normal file
59
depends/xz-embedded/src/xz_crc32.c
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* CRC32 using the polynomial from IEEE-802.3
|
||||
*
|
||||
* Authors: Lasse Collin <lasse.collin@tukaani.org>
|
||||
* Igor Pavlov <http://7-zip.org/>
|
||||
*
|
||||
* This file has been put into the public domain.
|
||||
* You can do whatever you want with this file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is not the fastest implementation, but it is pretty compact.
|
||||
* The fastest versions of xz_crc32() on modern CPUs without hardware
|
||||
* accelerated CRC instruction are 3-5 times as fast as this version,
|
||||
* but they are bigger and use more memory for the lookup table.
|
||||
*/
|
||||
|
||||
#include "xz_private.h"
|
||||
|
||||
/*
|
||||
* STATIC_RW_DATA is used in the pre-boot environment on some architectures.
|
||||
* See <linux/decompress/mm.h> for details.
|
||||
*/
|
||||
#ifndef STATIC_RW_DATA
|
||||
# define STATIC_RW_DATA static
|
||||
#endif
|
||||
|
||||
STATIC_RW_DATA uint32_t xz_crc32_table[256];
|
||||
|
||||
XZ_EXTERN void xz_crc32_init(void)
|
||||
{
|
||||
const uint32_t poly = 0xEDB88320;
|
||||
|
||||
uint32_t i;
|
||||
uint32_t j;
|
||||
uint32_t r;
|
||||
|
||||
for (i = 0; i < 256; ++i) {
|
||||
r = i;
|
||||
for (j = 0; j < 8; ++j)
|
||||
r = (r >> 1) ^ (poly & ~((r & 1) - 1));
|
||||
|
||||
xz_crc32_table[i] = r;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
XZ_EXTERN uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc)
|
||||
{
|
||||
crc = ~crc;
|
||||
|
||||
while (size != 0) {
|
||||
crc = xz_crc32_table[*buf++ ^ (crc & 0xFF)] ^ (crc >> 8);
|
||||
--size;
|
||||
}
|
||||
|
||||
return ~crc;
|
||||
}
|
50
depends/xz-embedded/src/xz_crc64.c
Normal file
50
depends/xz-embedded/src/xz_crc64.c
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* CRC64 using the polynomial from ECMA-182
|
||||
*
|
||||
* This file is similar to xz_crc32.c. See the comments there.
|
||||
*
|
||||
* Authors: Lasse Collin <lasse.collin@tukaani.org>
|
||||
* Igor Pavlov <http://7-zip.org/>
|
||||
*
|
||||
* This file has been put into the public domain.
|
||||
* You can do whatever you want with this file.
|
||||
*/
|
||||
|
||||
#include "xz_private.h"
|
||||
|
||||
#ifndef STATIC_RW_DATA
|
||||
# define STATIC_RW_DATA static
|
||||
#endif
|
||||
|
||||
STATIC_RW_DATA uint64_t xz_crc64_table[256];
|
||||
|
||||
XZ_EXTERN void xz_crc64_init(void)
|
||||
{
|
||||
const uint64_t poly = 0xC96C5795D7870F42;
|
||||
|
||||
uint32_t i;
|
||||
uint32_t j;
|
||||
uint64_t r;
|
||||
|
||||
for (i = 0; i < 256; ++i) {
|
||||
r = i;
|
||||
for (j = 0; j < 8; ++j)
|
||||
r = (r >> 1) ^ (poly & ~((r & 1) - 1));
|
||||
|
||||
xz_crc64_table[i] = r;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
XZ_EXTERN uint64_t xz_crc64(const uint8_t *buf, size_t size, uint64_t crc)
|
||||
{
|
||||
crc = ~crc;
|
||||
|
||||
while (size != 0) {
|
||||
crc = xz_crc64_table[*buf++ ^ (crc & 0xFF)] ^ (crc >> 8);
|
||||
--size;
|
||||
}
|
||||
|
||||
return ~crc;
|
||||
}
|
574
depends/xz-embedded/src/xz_dec_bcj.c
Normal file
574
depends/xz-embedded/src/xz_dec_bcj.c
Normal file
@ -0,0 +1,574 @@
|
||||
/*
|
||||
* Branch/Call/Jump (BCJ) filter decoders
|
||||
*
|
||||
* Authors: Lasse Collin <lasse.collin@tukaani.org>
|
||||
* Igor Pavlov <http://7-zip.org/>
|
||||
*
|
||||
* This file has been put into the public domain.
|
||||
* You can do whatever you want with this file.
|
||||
*/
|
||||
|
||||
#include "xz_private.h"
|
||||
|
||||
/*
|
||||
* The rest of the file is inside this ifdef. It makes things a little more
|
||||
* convenient when building without support for any BCJ filters.
|
||||
*/
|
||||
#ifdef XZ_DEC_BCJ
|
||||
|
||||
struct xz_dec_bcj {
|
||||
/* Type of the BCJ filter being used */
|
||||
enum {
|
||||
BCJ_X86 = 4, /* x86 or x86-64 */
|
||||
BCJ_POWERPC = 5, /* Big endian only */
|
||||
BCJ_IA64 = 6, /* Big or little endian */
|
||||
BCJ_ARM = 7, /* Little endian only */
|
||||
BCJ_ARMTHUMB = 8, /* Little endian only */
|
||||
BCJ_SPARC = 9 /* Big or little endian */
|
||||
} type;
|
||||
|
||||
/*
|
||||
* Return value of the next filter in the chain. We need to preserve
|
||||
* this information across calls, because we must not call the next
|
||||
* filter anymore once it has returned XZ_STREAM_END.
|
||||
*/
|
||||
enum xz_ret ret;
|
||||
|
||||
/* True if we are operating in single-call mode. */
|
||||
bool single_call;
|
||||
|
||||
/*
|
||||
* Absolute position relative to the beginning of the uncompressed
|
||||
* data (in a single .xz Block). We care only about the lowest 32
|
||||
* bits so this doesn't need to be uint64_t even with big files.
|
||||
*/
|
||||
uint32_t pos;
|
||||
|
||||
/* x86 filter state */
|
||||
uint32_t x86_prev_mask;
|
||||
|
||||
/* Temporary space to hold the variables from struct xz_buf */
|
||||
uint8_t *out;
|
||||
size_t out_pos;
|
||||
size_t out_size;
|
||||
|
||||
struct {
|
||||
/* Amount of already filtered data in the beginning of buf */
|
||||
size_t filtered;
|
||||
|
||||
/* Total amount of data currently stored in buf */
|
||||
size_t size;
|
||||
|
||||
/*
|
||||
* Buffer to hold a mix of filtered and unfiltered data. This
|
||||
* needs to be big enough to hold Alignment + 2 * Look-ahead:
|
||||
*
|
||||
* Type Alignment Look-ahead
|
||||
* x86 1 4
|
||||
* PowerPC 4 0
|
||||
* IA-64 16 0
|
||||
* ARM 4 0
|
||||
* ARM-Thumb 2 2
|
||||
* SPARC 4 0
|
||||
*/
|
||||
uint8_t buf[16];
|
||||
} temp;
|
||||
};
|
||||
|
||||
#ifdef XZ_DEC_X86
|
||||
/*
|
||||
* This is used to test the most significant byte of a memory address
|
||||
* in an x86 instruction.
|
||||
*/
|
||||
static inline int bcj_x86_test_msbyte(uint8_t b)
|
||||
{
|
||||
return b == 0x00 || b == 0xFF;
|
||||
}
|
||||
|
||||
static size_t bcj_x86(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
|
||||
{
|
||||
static const bool mask_to_allowed_status[8]
|
||||
= { true, true, true, false, true, false, false, false };
|
||||
|
||||
static const uint8_t mask_to_bit_num[8] = { 0, 1, 2, 2, 3, 3, 3, 3 };
|
||||
|
||||
size_t i;
|
||||
size_t prev_pos = (size_t)-1;
|
||||
uint32_t prev_mask = s->x86_prev_mask;
|
||||
uint32_t src;
|
||||
uint32_t dest;
|
||||
uint32_t j;
|
||||
uint8_t b;
|
||||
|
||||
if (size <= 4)
|
||||
return 0;
|
||||
|
||||
size -= 4;
|
||||
for (i = 0; i < size; ++i) {
|
||||
if ((buf[i] & 0xFE) != 0xE8)
|
||||
continue;
|
||||
|
||||
prev_pos = i - prev_pos;
|
||||
if (prev_pos > 3) {
|
||||
prev_mask = 0;
|
||||
} else {
|
||||
prev_mask = (prev_mask << (prev_pos - 1)) & 7;
|
||||
if (prev_mask != 0) {
|
||||
b = buf[i + 4 - mask_to_bit_num[prev_mask]];
|
||||
if (!mask_to_allowed_status[prev_mask]
|
||||
|| bcj_x86_test_msbyte(b)) {
|
||||
prev_pos = i;
|
||||
prev_mask = (prev_mask << 1) | 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prev_pos = i;
|
||||
|
||||
if (bcj_x86_test_msbyte(buf[i + 4])) {
|
||||
src = get_unaligned_le32(buf + i + 1);
|
||||
while (true) {
|
||||
dest = src - (s->pos + (uint32_t)i + 5);
|
||||
if (prev_mask == 0)
|
||||
break;
|
||||
|
||||
j = mask_to_bit_num[prev_mask] * 8;
|
||||
b = (uint8_t)(dest >> (24 - j));
|
||||
if (!bcj_x86_test_msbyte(b))
|
||||
break;
|
||||
|
||||
src = dest ^ (((uint32_t)1 << (32 - j)) - 1);
|
||||
}
|
||||
|
||||
dest &= 0x01FFFFFF;
|
||||
dest |= (uint32_t)0 - (dest & 0x01000000);
|
||||
put_unaligned_le32(dest, buf + i + 1);
|
||||
i += 4;
|
||||
} else {
|
||||
prev_mask = (prev_mask << 1) | 1;
|
||||
}
|
||||
}
|
||||
|
||||
prev_pos = i - prev_pos;
|
||||
s->x86_prev_mask = prev_pos > 3 ? 0 : prev_mask << (prev_pos - 1);
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XZ_DEC_POWERPC
|
||||
static size_t bcj_powerpc(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
|
||||
{
|
||||
size_t i;
|
||||
uint32_t instr;
|
||||
|
||||
for (i = 0; i + 4 <= size; i += 4) {
|
||||
instr = get_unaligned_be32(buf + i);
|
||||
if ((instr & 0xFC000003) == 0x48000001) {
|
||||
instr &= 0x03FFFFFC;
|
||||
instr -= s->pos + (uint32_t)i;
|
||||
instr &= 0x03FFFFFC;
|
||||
instr |= 0x48000001;
|
||||
put_unaligned_be32(instr, buf + i);
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XZ_DEC_IA64
|
||||
static size_t bcj_ia64(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
|
||||
{
|
||||
static const uint8_t branch_table[32] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
4, 4, 6, 6, 0, 0, 7, 7,
|
||||
4, 4, 0, 0, 4, 4, 0, 0
|
||||
};
|
||||
|
||||
/*
|
||||
* The local variables take a little bit stack space, but it's less
|
||||
* than what LZMA2 decoder takes, so it doesn't make sense to reduce
|
||||
* stack usage here without doing that for the LZMA2 decoder too.
|
||||
*/
|
||||
|
||||
/* Loop counters */
|
||||
size_t i;
|
||||
size_t j;
|
||||
|
||||
/* Instruction slot (0, 1, or 2) in the 128-bit instruction word */
|
||||
uint32_t slot;
|
||||
|
||||
/* Bitwise offset of the instruction indicated by slot */
|
||||
uint32_t bit_pos;
|
||||
|
||||
/* bit_pos split into byte and bit parts */
|
||||
uint32_t byte_pos;
|
||||
uint32_t bit_res;
|
||||
|
||||
/* Address part of an instruction */
|
||||
uint32_t addr;
|
||||
|
||||
/* Mask used to detect which instructions to convert */
|
||||
uint32_t mask;
|
||||
|
||||
/* 41-bit instruction stored somewhere in the lowest 48 bits */
|
||||
uint64_t instr;
|
||||
|
||||
/* Instruction normalized with bit_res for easier manipulation */
|
||||
uint64_t norm;
|
||||
|
||||
for (i = 0; i + 16 <= size; i += 16) {
|
||||
mask = branch_table[buf[i] & 0x1F];
|
||||
for (slot = 0, bit_pos = 5; slot < 3; ++slot, bit_pos += 41) {
|
||||
if (((mask >> slot) & 1) == 0)
|
||||
continue;
|
||||
|
||||
byte_pos = bit_pos >> 3;
|
||||
bit_res = bit_pos & 7;
|
||||
instr = 0;
|
||||
for (j = 0; j < 6; ++j)
|
||||
instr |= (uint64_t)(buf[i + j + byte_pos])
|
||||
<< (8 * j);
|
||||
|
||||
norm = instr >> bit_res;
|
||||
|
||||
if (((norm >> 37) & 0x0F) == 0x05
|
||||
&& ((norm >> 9) & 0x07) == 0) {
|
||||
addr = (norm >> 13) & 0x0FFFFF;
|
||||
addr |= ((uint32_t)(norm >> 36) & 1) << 20;
|
||||
addr <<= 4;
|
||||
addr -= s->pos + (uint32_t)i;
|
||||
addr >>= 4;
|
||||
|
||||
norm &= ~((uint64_t)0x8FFFFF << 13);
|
||||
norm |= (uint64_t)(addr & 0x0FFFFF) << 13;
|
||||
norm |= (uint64_t)(addr & 0x100000)
|
||||
<< (36 - 20);
|
||||
|
||||
instr &= (1 << bit_res) - 1;
|
||||
instr |= norm << bit_res;
|
||||
|
||||
for (j = 0; j < 6; j++)
|
||||
buf[i + j + byte_pos]
|
||||
= (uint8_t)(instr >> (8 * j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XZ_DEC_ARM
|
||||
static size_t bcj_arm(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
|
||||
{
|
||||
size_t i;
|
||||
uint32_t addr;
|
||||
|
||||
for (i = 0; i + 4 <= size; i += 4) {
|
||||
if (buf[i + 3] == 0xEB) {
|
||||
addr = (uint32_t)buf[i] | ((uint32_t)buf[i + 1] << 8)
|
||||
| ((uint32_t)buf[i + 2] << 16);
|
||||
addr <<= 2;
|
||||
addr -= s->pos + (uint32_t)i + 8;
|
||||
addr >>= 2;
|
||||
buf[i] = (uint8_t)addr;
|
||||
buf[i + 1] = (uint8_t)(addr >> 8);
|
||||
buf[i + 2] = (uint8_t)(addr >> 16);
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XZ_DEC_ARMTHUMB
|
||||
static size_t bcj_armthumb(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
|
||||
{
|
||||
size_t i;
|
||||
uint32_t addr;
|
||||
|
||||
for (i = 0; i + 4 <= size; i += 2) {
|
||||
if ((buf[i + 1] & 0xF8) == 0xF0
|
||||
&& (buf[i + 3] & 0xF8) == 0xF8) {
|
||||
addr = (((uint32_t)buf[i + 1] & 0x07) << 19)
|
||||
| ((uint32_t)buf[i] << 11)
|
||||
| (((uint32_t)buf[i + 3] & 0x07) << 8)
|
||||
| (uint32_t)buf[i + 2];
|
||||
addr <<= 1;
|
||||
addr -= s->pos + (uint32_t)i + 4;
|
||||
addr >>= 1;
|
||||
buf[i + 1] = (uint8_t)(0xF0 | ((addr >> 19) & 0x07));
|
||||
buf[i] = (uint8_t)(addr >> 11);
|
||||
buf[i + 3] = (uint8_t)(0xF8 | ((addr >> 8) & 0x07));
|
||||
buf[i + 2] = (uint8_t)addr;
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XZ_DEC_SPARC
|
||||
static size_t bcj_sparc(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
|
||||
{
|
||||
size_t i;
|
||||
uint32_t instr;
|
||||
|
||||
for (i = 0; i + 4 <= size; i += 4) {
|
||||
instr = get_unaligned_be32(buf + i);
|
||||
if ((instr >> 22) == 0x100 || (instr >> 22) == 0x1FF) {
|
||||
instr <<= 2;
|
||||
instr -= s->pos + (uint32_t)i;
|
||||
instr >>= 2;
|
||||
instr = ((uint32_t)0x40000000 - (instr & 0x400000))
|
||||
| 0x40000000 | (instr & 0x3FFFFF);
|
||||
put_unaligned_be32(instr, buf + i);
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Apply the selected BCJ filter. Update *pos and s->pos to match the amount
|
||||
* of data that got filtered.
|
||||
*
|
||||
* NOTE: This is implemented as a switch statement to avoid using function
|
||||
* pointers, which could be problematic in the kernel boot code, which must
|
||||
* avoid pointers to static data (at least on x86).
|
||||
*/
|
||||
static void bcj_apply(struct xz_dec_bcj *s,
|
||||
uint8_t *buf, size_t *pos, size_t size)
|
||||
{
|
||||
size_t filtered;
|
||||
|
||||
buf += *pos;
|
||||
size -= *pos;
|
||||
|
||||
switch (s->type) {
|
||||
#ifdef XZ_DEC_X86
|
||||
case BCJ_X86:
|
||||
filtered = bcj_x86(s, buf, size);
|
||||
break;
|
||||
#endif
|
||||
#ifdef XZ_DEC_POWERPC
|
||||
case BCJ_POWERPC:
|
||||
filtered = bcj_powerpc(s, buf, size);
|
||||
break;
|
||||
#endif
|
||||
#ifdef XZ_DEC_IA64
|
||||
case BCJ_IA64:
|
||||
filtered = bcj_ia64(s, buf, size);
|
||||
break;
|
||||
#endif
|
||||
#ifdef XZ_DEC_ARM
|
||||
case BCJ_ARM:
|
||||
filtered = bcj_arm(s, buf, size);
|
||||
break;
|
||||
#endif
|
||||
#ifdef XZ_DEC_ARMTHUMB
|
||||
case BCJ_ARMTHUMB:
|
||||
filtered = bcj_armthumb(s, buf, size);
|
||||
break;
|
||||
#endif
|
||||
#ifdef XZ_DEC_SPARC
|
||||
case BCJ_SPARC:
|
||||
filtered = bcj_sparc(s, buf, size);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
/* Never reached but silence compiler warnings. */
|
||||
filtered = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
*pos += filtered;
|
||||
s->pos += filtered;
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush pending filtered data from temp to the output buffer.
|
||||
* Move the remaining mixture of possibly filtered and unfiltered
|
||||
* data to the beginning of temp.
|
||||
*/
|
||||
static void bcj_flush(struct xz_dec_bcj *s, struct xz_buf *b)
|
||||
{
|
||||
size_t copy_size;
|
||||
|
||||
copy_size = min_t(size_t, s->temp.filtered, b->out_size - b->out_pos);
|
||||
memcpy(b->out + b->out_pos, s->temp.buf, copy_size);
|
||||
b->out_pos += copy_size;
|
||||
|
||||
s->temp.filtered -= copy_size;
|
||||
s->temp.size -= copy_size;
|
||||
memmove(s->temp.buf, s->temp.buf + copy_size, s->temp.size);
|
||||
}
|
||||
|
||||
/*
|
||||
* The BCJ filter functions are primitive in sense that they process the
|
||||
* data in chunks of 1-16 bytes. To hide this issue, this function does
|
||||
* some buffering.
|
||||
*/
|
||||
XZ_EXTERN enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s,
|
||||
struct xz_dec_lzma2 *lzma2,
|
||||
struct xz_buf *b)
|
||||
{
|
||||
size_t out_start;
|
||||
|
||||
/*
|
||||
* Flush pending already filtered data to the output buffer. Return
|
||||
* immediatelly if we couldn't flush everything, or if the next
|
||||
* filter in the chain had already returned XZ_STREAM_END.
|
||||
*/
|
||||
if (s->temp.filtered > 0) {
|
||||
bcj_flush(s, b);
|
||||
if (s->temp.filtered > 0)
|
||||
return XZ_OK;
|
||||
|
||||
if (s->ret == XZ_STREAM_END)
|
||||
return XZ_STREAM_END;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have more output space than what is currently pending in
|
||||
* temp, copy the unfiltered data from temp to the output buffer
|
||||
* and try to fill the output buffer by decoding more data from the
|
||||
* next filter in the chain. Apply the BCJ filter on the new data
|
||||
* in the output buffer. If everything cannot be filtered, copy it
|
||||
* to temp and rewind the output buffer position accordingly.
|
||||
*
|
||||
* This needs to be always run when temp.size == 0 to handle a special
|
||||
* case where the output buffer is full and the next filter has no
|
||||
* more output coming but hasn't returned XZ_STREAM_END yet.
|
||||
*/
|
||||
if (s->temp.size < b->out_size - b->out_pos || s->temp.size == 0) {
|
||||
out_start = b->out_pos;
|
||||
memcpy(b->out + b->out_pos, s->temp.buf, s->temp.size);
|
||||
b->out_pos += s->temp.size;
|
||||
|
||||
s->ret = xz_dec_lzma2_run(lzma2, b);
|
||||
if (s->ret != XZ_STREAM_END
|
||||
&& (s->ret != XZ_OK || s->single_call))
|
||||
return s->ret;
|
||||
|
||||
bcj_apply(s, b->out, &out_start, b->out_pos);
|
||||
|
||||
/*
|
||||
* As an exception, if the next filter returned XZ_STREAM_END,
|
||||
* we can do that too, since the last few bytes that remain
|
||||
* unfiltered are meant to remain unfiltered.
|
||||
*/
|
||||
if (s->ret == XZ_STREAM_END)
|
||||
return XZ_STREAM_END;
|
||||
|
||||
s->temp.size = b->out_pos - out_start;
|
||||
b->out_pos -= s->temp.size;
|
||||
memcpy(s->temp.buf, b->out + b->out_pos, s->temp.size);
|
||||
|
||||
/*
|
||||
* If there wasn't enough input to the next filter to fill
|
||||
* the output buffer with unfiltered data, there's no point
|
||||
* to try decoding more data to temp.
|
||||
*/
|
||||
if (b->out_pos + s->temp.size < b->out_size)
|
||||
return XZ_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* We have unfiltered data in temp. If the output buffer isn't full
|
||||
* yet, try to fill the temp buffer by decoding more data from the
|
||||
* next filter. Apply the BCJ filter on temp. Then we hopefully can
|
||||
* fill the actual output buffer by copying filtered data from temp.
|
||||
* A mix of filtered and unfiltered data may be left in temp; it will
|
||||
* be taken care on the next call to this function.
|
||||
*/
|
||||
if (b->out_pos < b->out_size) {
|
||||
/* Make b->out{,_pos,_size} temporarily point to s->temp. */
|
||||
s->out = b->out;
|
||||
s->out_pos = b->out_pos;
|
||||
s->out_size = b->out_size;
|
||||
b->out = s->temp.buf;
|
||||
b->out_pos = s->temp.size;
|
||||
b->out_size = sizeof(s->temp.buf);
|
||||
|
||||
s->ret = xz_dec_lzma2_run(lzma2, b);
|
||||
|
||||
s->temp.size = b->out_pos;
|
||||
b->out = s->out;
|
||||
b->out_pos = s->out_pos;
|
||||
b->out_size = s->out_size;
|
||||
|
||||
if (s->ret != XZ_OK && s->ret != XZ_STREAM_END)
|
||||
return s->ret;
|
||||
|
||||
bcj_apply(s, s->temp.buf, &s->temp.filtered, s->temp.size);
|
||||
|
||||
/*
|
||||
* If the next filter returned XZ_STREAM_END, we mark that
|
||||
* everything is filtered, since the last unfiltered bytes
|
||||
* of the stream are meant to be left as is.
|
||||
*/
|
||||
if (s->ret == XZ_STREAM_END)
|
||||
s->temp.filtered = s->temp.size;
|
||||
|
||||
bcj_flush(s, b);
|
||||
if (s->temp.filtered > 0)
|
||||
return XZ_OK;
|
||||
}
|
||||
|
||||
return s->ret;
|
||||
}
|
||||
|
||||
XZ_EXTERN struct xz_dec_bcj *xz_dec_bcj_create(bool single_call)
|
||||
{
|
||||
struct xz_dec_bcj *s = kmalloc(sizeof(*s), GFP_KERNEL);
|
||||
if (s != NULL)
|
||||
s->single_call = single_call;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
XZ_EXTERN enum xz_ret xz_dec_bcj_reset(struct xz_dec_bcj *s, uint8_t id)
|
||||
{
|
||||
switch (id) {
|
||||
#ifdef XZ_DEC_X86
|
||||
case BCJ_X86:
|
||||
#endif
|
||||
#ifdef XZ_DEC_POWERPC
|
||||
case BCJ_POWERPC:
|
||||
#endif
|
||||
#ifdef XZ_DEC_IA64
|
||||
case BCJ_IA64:
|
||||
#endif
|
||||
#ifdef XZ_DEC_ARM
|
||||
case BCJ_ARM:
|
||||
#endif
|
||||
#ifdef XZ_DEC_ARMTHUMB
|
||||
case BCJ_ARMTHUMB:
|
||||
#endif
|
||||
#ifdef XZ_DEC_SPARC
|
||||
case BCJ_SPARC:
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Unsupported Filter ID */
|
||||
return XZ_OPTIONS_ERROR;
|
||||
}
|
||||
|
||||
s->type = id;
|
||||
s->ret = XZ_OK;
|
||||
s->pos = 0;
|
||||
s->x86_prev_mask = 0;
|
||||
s->temp.filtered = 0;
|
||||
s->temp.size = 0;
|
||||
|
||||
return XZ_OK;
|
||||
}
|
||||
|
||||
#endif
|
1171
depends/xz-embedded/src/xz_dec_lzma2.c
Normal file
1171
depends/xz-embedded/src/xz_dec_lzma2.c
Normal file
File diff suppressed because it is too large
Load Diff
847
depends/xz-embedded/src/xz_dec_stream.c
Normal file
847
depends/xz-embedded/src/xz_dec_stream.c
Normal file
@ -0,0 +1,847 @@
|
||||
/*
|
||||
* .xz Stream decoder
|
||||
*
|
||||
* Author: Lasse Collin <lasse.collin@tukaani.org>
|
||||
*
|
||||
* This file has been put into the public domain.
|
||||
* You can do whatever you want with this file.
|
||||
*/
|
||||
|
||||
#include "xz_private.h"
|
||||
#include "xz_stream.h"
|
||||
|
||||
#ifdef XZ_USE_CRC64
|
||||
# define IS_CRC64(check_type) ((check_type) == XZ_CHECK_CRC64)
|
||||
#else
|
||||
# define IS_CRC64(check_type) false
|
||||
#endif
|
||||
|
||||
/* Hash used to validate the Index field */
|
||||
struct xz_dec_hash {
|
||||
vli_type unpadded;
|
||||
vli_type uncompressed;
|
||||
uint32_t crc32;
|
||||
};
|
||||
|
||||
struct xz_dec {
|
||||
/* Position in dec_main() */
|
||||
enum {
|
||||
SEQ_STREAM_HEADER,
|
||||
SEQ_BLOCK_START,
|
||||
SEQ_BLOCK_HEADER,
|
||||
SEQ_BLOCK_UNCOMPRESS,
|
||||
SEQ_BLOCK_PADDING,
|
||||
SEQ_BLOCK_CHECK,
|
||||
SEQ_INDEX,
|
||||
SEQ_INDEX_PADDING,
|
||||
SEQ_INDEX_CRC32,
|
||||
SEQ_STREAM_FOOTER
|
||||
} sequence;
|
||||
|
||||
/* Position in variable-length integers and Check fields */
|
||||
uint32_t pos;
|
||||
|
||||
/* Variable-length integer decoded by dec_vli() */
|
||||
vli_type vli;
|
||||
|
||||
/* Saved in_pos and out_pos */
|
||||
size_t in_start;
|
||||
size_t out_start;
|
||||
|
||||
#ifdef XZ_USE_CRC64
|
||||
/* CRC32 or CRC64 value in Block or CRC32 value in Index */
|
||||
uint64_t crc;
|
||||
#else
|
||||
/* CRC32 value in Block or Index */
|
||||
uint32_t crc;
|
||||
#endif
|
||||
|
||||
/* Type of the integrity check calculated from uncompressed data */
|
||||
enum xz_check check_type;
|
||||
|
||||
/* Operation mode */
|
||||
enum xz_mode mode;
|
||||
|
||||
/*
|
||||
* True if the next call to xz_dec_run() is allowed to return
|
||||
* XZ_BUF_ERROR.
|
||||
*/
|
||||
bool allow_buf_error;
|
||||
|
||||
/* Information stored in Block Header */
|
||||
struct {
|
||||
/*
|
||||
* Value stored in the Compressed Size field, or
|
||||
* VLI_UNKNOWN if Compressed Size is not present.
|
||||
*/
|
||||
vli_type compressed;
|
||||
|
||||
/*
|
||||
* Value stored in the Uncompressed Size field, or
|
||||
* VLI_UNKNOWN if Uncompressed Size is not present.
|
||||
*/
|
||||
vli_type uncompressed;
|
||||
|
||||
/* Size of the Block Header field */
|
||||
uint32_t size;
|
||||
} block_header;
|
||||
|
||||
/* Information collected when decoding Blocks */
|
||||
struct {
|
||||
/* Observed compressed size of the current Block */
|
||||
vli_type compressed;
|
||||
|
||||
/* Observed uncompressed size of the current Block */
|
||||
vli_type uncompressed;
|
||||
|
||||
/* Number of Blocks decoded so far */
|
||||
vli_type count;
|
||||
|
||||
/*
|
||||
* Hash calculated from the Block sizes. This is used to
|
||||
* validate the Index field.
|
||||
*/
|
||||
struct xz_dec_hash hash;
|
||||
} block;
|
||||
|
||||
/* Variables needed when verifying the Index field */
|
||||
struct {
|
||||
/* Position in dec_index() */
|
||||
enum {
|
||||
SEQ_INDEX_COUNT,
|
||||
SEQ_INDEX_UNPADDED,
|
||||
SEQ_INDEX_UNCOMPRESSED
|
||||
} sequence;
|
||||
|
||||
/* Size of the Index in bytes */
|
||||
vli_type size;
|
||||
|
||||
/* Number of Records (matches block.count in valid files) */
|
||||
vli_type count;
|
||||
|
||||
/*
|
||||
* Hash calculated from the Records (matches block.hash in
|
||||
* valid files).
|
||||
*/
|
||||
struct xz_dec_hash hash;
|
||||
} index;
|
||||
|
||||
/*
|
||||
* Temporary buffer needed to hold Stream Header, Block Header,
|
||||
* and Stream Footer. The Block Header is the biggest (1 KiB)
|
||||
* so we reserve space according to that. buf[] has to be aligned
|
||||
* to a multiple of four bytes; the size_t variables before it
|
||||
* should guarantee this.
|
||||
*/
|
||||
struct {
|
||||
size_t pos;
|
||||
size_t size;
|
||||
uint8_t buf[1024];
|
||||
} temp;
|
||||
|
||||
struct xz_dec_lzma2 *lzma2;
|
||||
|
||||
#ifdef XZ_DEC_BCJ
|
||||
struct xz_dec_bcj *bcj;
|
||||
bool bcj_active;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef XZ_DEC_ANY_CHECK
|
||||
/* Sizes of the Check field with different Check IDs */
|
||||
static const uint8_t check_sizes[16] = {
|
||||
0,
|
||||
4, 4, 4,
|
||||
8, 8, 8,
|
||||
16, 16, 16,
|
||||
32, 32, 32,
|
||||
64, 64, 64
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Fill s->temp by copying data starting from b->in[b->in_pos]. Caller
|
||||
* must have set s->temp.pos to indicate how much data we are supposed
|
||||
* to copy into s->temp.buf. Return true once s->temp.pos has reached
|
||||
* s->temp.size.
|
||||
*/
|
||||
static bool fill_temp(struct xz_dec *s, struct xz_buf *b)
|
||||
{
|
||||
size_t copy_size = min_t(size_t,
|
||||
b->in_size - b->in_pos, s->temp.size - s->temp.pos);
|
||||
|
||||
memcpy(s->temp.buf + s->temp.pos, b->in + b->in_pos, copy_size);
|
||||
b->in_pos += copy_size;
|
||||
s->temp.pos += copy_size;
|
||||
|
||||
if (s->temp.pos == s->temp.size) {
|
||||
s->temp.pos = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Decode a variable-length integer (little-endian base-128 encoding) */
|
||||
static enum xz_ret dec_vli(struct xz_dec *s, const uint8_t *in,
|
||||
size_t *in_pos, size_t in_size)
|
||||
{
|
||||
uint8_t byte;
|
||||
|
||||
if (s->pos == 0)
|
||||
s->vli = 0;
|
||||
|
||||
while (*in_pos < in_size) {
|
||||
byte = in[*in_pos];
|
||||
++*in_pos;
|
||||
|
||||
s->vli |= (vli_type)(byte & 0x7F) << s->pos;
|
||||
|
||||
if ((byte & 0x80) == 0) {
|
||||
/* Don't allow non-minimal encodings. */
|
||||
if (byte == 0 && s->pos != 0)
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
s->pos = 0;
|
||||
return XZ_STREAM_END;
|
||||
}
|
||||
|
||||
s->pos += 7;
|
||||
if (s->pos == 7 * VLI_BYTES_MAX)
|
||||
return XZ_DATA_ERROR;
|
||||
}
|
||||
|
||||
return XZ_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode the Compressed Data field from a Block. Update and validate
|
||||
* the observed compressed and uncompressed sizes of the Block so that
|
||||
* they don't exceed the values possibly stored in the Block Header
|
||||
* (validation assumes that no integer overflow occurs, since vli_type
|
||||
* is normally uint64_t). Update the CRC32 or CRC64 value if presence of
|
||||
* the CRC32 or CRC64 field was indicated in Stream Header.
|
||||
*
|
||||
* Once the decoding is finished, validate that the observed sizes match
|
||||
* the sizes possibly stored in the Block Header. Update the hash and
|
||||
* Block count, which are later used to validate the Index field.
|
||||
*/
|
||||
static enum xz_ret dec_block(struct xz_dec *s, struct xz_buf *b)
|
||||
{
|
||||
enum xz_ret ret;
|
||||
|
||||
s->in_start = b->in_pos;
|
||||
s->out_start = b->out_pos;
|
||||
|
||||
#ifdef XZ_DEC_BCJ
|
||||
if (s->bcj_active)
|
||||
ret = xz_dec_bcj_run(s->bcj, s->lzma2, b);
|
||||
else
|
||||
#endif
|
||||
ret = xz_dec_lzma2_run(s->lzma2, b);
|
||||
|
||||
s->block.compressed += b->in_pos - s->in_start;
|
||||
s->block.uncompressed += b->out_pos - s->out_start;
|
||||
|
||||
/*
|
||||
* There is no need to separately check for VLI_UNKNOWN, since
|
||||
* the observed sizes are always smaller than VLI_UNKNOWN.
|
||||
*/
|
||||
if (s->block.compressed > s->block_header.compressed
|
||||
|| s->block.uncompressed
|
||||
> s->block_header.uncompressed)
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
if (s->check_type == XZ_CHECK_CRC32)
|
||||
s->crc = xz_crc32(b->out + s->out_start,
|
||||
b->out_pos - s->out_start, s->crc);
|
||||
#ifdef XZ_USE_CRC64
|
||||
else if (s->check_type == XZ_CHECK_CRC64)
|
||||
s->crc = xz_crc64(b->out + s->out_start,
|
||||
b->out_pos - s->out_start, s->crc);
|
||||
#endif
|
||||
|
||||
if (ret == XZ_STREAM_END) {
|
||||
if (s->block_header.compressed != VLI_UNKNOWN
|
||||
&& s->block_header.compressed
|
||||
!= s->block.compressed)
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
if (s->block_header.uncompressed != VLI_UNKNOWN
|
||||
&& s->block_header.uncompressed
|
||||
!= s->block.uncompressed)
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
s->block.hash.unpadded += s->block_header.size
|
||||
+ s->block.compressed;
|
||||
|
||||
#ifdef XZ_DEC_ANY_CHECK
|
||||
s->block.hash.unpadded += check_sizes[s->check_type];
|
||||
#else
|
||||
if (s->check_type == XZ_CHECK_CRC32)
|
||||
s->block.hash.unpadded += 4;
|
||||
else if (IS_CRC64(s->check_type))
|
||||
s->block.hash.unpadded += 8;
|
||||
#endif
|
||||
|
||||
s->block.hash.uncompressed += s->block.uncompressed;
|
||||
s->block.hash.crc32 = xz_crc32(
|
||||
(const uint8_t *)&s->block.hash,
|
||||
sizeof(s->block.hash), s->block.hash.crc32);
|
||||
|
||||
++s->block.count;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Update the Index size and the CRC32 value. */
|
||||
static void index_update(struct xz_dec *s, const struct xz_buf *b)
|
||||
{
|
||||
size_t in_used = b->in_pos - s->in_start;
|
||||
s->index.size += in_used;
|
||||
s->crc = xz_crc32(b->in + s->in_start, in_used, s->crc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode the Number of Records, Unpadded Size, and Uncompressed Size
|
||||
* fields from the Index field. That is, Index Padding and CRC32 are not
|
||||
* decoded by this function.
|
||||
*
|
||||
* This can return XZ_OK (more input needed), XZ_STREAM_END (everything
|
||||
* successfully decoded), or XZ_DATA_ERROR (input is corrupt).
|
||||
*/
|
||||
static enum xz_ret dec_index(struct xz_dec *s, struct xz_buf *b)
|
||||
{
|
||||
enum xz_ret ret;
|
||||
|
||||
do {
|
||||
ret = dec_vli(s, b->in, &b->in_pos, b->in_size);
|
||||
if (ret != XZ_STREAM_END) {
|
||||
index_update(s, b);
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (s->index.sequence) {
|
||||
case SEQ_INDEX_COUNT:
|
||||
s->index.count = s->vli;
|
||||
|
||||
/*
|
||||
* Validate that the Number of Records field
|
||||
* indicates the same number of Records as
|
||||
* there were Blocks in the Stream.
|
||||
*/
|
||||
if (s->index.count != s->block.count)
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
s->index.sequence = SEQ_INDEX_UNPADDED;
|
||||
break;
|
||||
|
||||
case SEQ_INDEX_UNPADDED:
|
||||
s->index.hash.unpadded += s->vli;
|
||||
s->index.sequence = SEQ_INDEX_UNCOMPRESSED;
|
||||
break;
|
||||
|
||||
case SEQ_INDEX_UNCOMPRESSED:
|
||||
s->index.hash.uncompressed += s->vli;
|
||||
s->index.hash.crc32 = xz_crc32(
|
||||
(const uint8_t *)&s->index.hash,
|
||||
sizeof(s->index.hash),
|
||||
s->index.hash.crc32);
|
||||
--s->index.count;
|
||||
s->index.sequence = SEQ_INDEX_UNPADDED;
|
||||
break;
|
||||
}
|
||||
} while (s->index.count > 0);
|
||||
|
||||
return XZ_STREAM_END;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate that the next four or eight input bytes match the value
|
||||
* of s->crc. s->pos must be zero when starting to validate the first byte.
|
||||
* The "bits" argument allows using the same code for both CRC32 and CRC64.
|
||||
*/
|
||||
static enum xz_ret crc_validate(struct xz_dec *s, struct xz_buf *b,
|
||||
uint32_t bits)
|
||||
{
|
||||
do {
|
||||
if (b->in_pos == b->in_size)
|
||||
return XZ_OK;
|
||||
|
||||
if (((s->crc >> s->pos) & 0xFF) != b->in[b->in_pos++])
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
s->pos += 8;
|
||||
|
||||
} while (s->pos < bits);
|
||||
|
||||
s->crc = 0;
|
||||
s->pos = 0;
|
||||
|
||||
return XZ_STREAM_END;
|
||||
}
|
||||
|
||||
#ifdef XZ_DEC_ANY_CHECK
|
||||
/*
|
||||
* Skip over the Check field when the Check ID is not supported.
|
||||
* Returns true once the whole Check field has been skipped over.
|
||||
*/
|
||||
static bool check_skip(struct xz_dec *s, struct xz_buf *b)
|
||||
{
|
||||
while (s->pos < check_sizes[s->check_type]) {
|
||||
if (b->in_pos == b->in_size)
|
||||
return false;
|
||||
|
||||
++b->in_pos;
|
||||
++s->pos;
|
||||
}
|
||||
|
||||
s->pos = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Decode the Stream Header field (the first 12 bytes of the .xz Stream). */
|
||||
static enum xz_ret dec_stream_header(struct xz_dec *s)
|
||||
{
|
||||
if (!memeq(s->temp.buf, HEADER_MAGIC, HEADER_MAGIC_SIZE))
|
||||
return XZ_FORMAT_ERROR;
|
||||
|
||||
if (xz_crc32(s->temp.buf + HEADER_MAGIC_SIZE, 2, 0)
|
||||
!= get_le32(s->temp.buf + HEADER_MAGIC_SIZE + 2))
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
if (s->temp.buf[HEADER_MAGIC_SIZE] != 0)
|
||||
return XZ_OPTIONS_ERROR;
|
||||
|
||||
/*
|
||||
* Of integrity checks, we support none (Check ID = 0),
|
||||
* CRC32 (Check ID = 1), and optionally CRC64 (Check ID = 4).
|
||||
* However, if XZ_DEC_ANY_CHECK is defined, we will accept other
|
||||
* check types too, but then the check won't be verified and
|
||||
* a warning (XZ_UNSUPPORTED_CHECK) will be given.
|
||||
*/
|
||||
s->check_type = s->temp.buf[HEADER_MAGIC_SIZE + 1];
|
||||
|
||||
#ifdef XZ_DEC_ANY_CHECK
|
||||
if (s->check_type > XZ_CHECK_MAX)
|
||||
return XZ_OPTIONS_ERROR;
|
||||
|
||||
if (s->check_type > XZ_CHECK_CRC32 && !IS_CRC64(s->check_type))
|
||||
return XZ_UNSUPPORTED_CHECK;
|
||||
#else
|
||||
if (s->check_type > XZ_CHECK_CRC32 && !IS_CRC64(s->check_type))
|
||||
return XZ_OPTIONS_ERROR;
|
||||
#endif
|
||||
|
||||
return XZ_OK;
|
||||
}
|
||||
|
||||
/* Decode the Stream Footer field (the last 12 bytes of the .xz Stream) */
|
||||
static enum xz_ret dec_stream_footer(struct xz_dec *s)
|
||||
{
|
||||
if (!memeq(s->temp.buf + 10, FOOTER_MAGIC, FOOTER_MAGIC_SIZE))
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
if (xz_crc32(s->temp.buf + 4, 6, 0) != get_le32(s->temp.buf))
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
/*
|
||||
* Validate Backward Size. Note that we never added the size of the
|
||||
* Index CRC32 field to s->index.size, thus we use s->index.size / 4
|
||||
* instead of s->index.size / 4 - 1.
|
||||
*/
|
||||
if ((s->index.size >> 2) != get_le32(s->temp.buf + 4))
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
if (s->temp.buf[8] != 0 || s->temp.buf[9] != s->check_type)
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
/*
|
||||
* Use XZ_STREAM_END instead of XZ_OK to be more convenient
|
||||
* for the caller.
|
||||
*/
|
||||
return XZ_STREAM_END;
|
||||
}
|
||||
|
||||
/* Decode the Block Header and initialize the filter chain. */
|
||||
static enum xz_ret dec_block_header(struct xz_dec *s)
|
||||
{
|
||||
enum xz_ret ret;
|
||||
|
||||
/*
|
||||
* Validate the CRC32. We know that the temp buffer is at least
|
||||
* eight bytes so this is safe.
|
||||
*/
|
||||
s->temp.size -= 4;
|
||||
if (xz_crc32(s->temp.buf, s->temp.size, 0)
|
||||
!= get_le32(s->temp.buf + s->temp.size))
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
s->temp.pos = 2;
|
||||
|
||||
/*
|
||||
* Catch unsupported Block Flags. We support only one or two filters
|
||||
* in the chain, so we catch that with the same test.
|
||||
*/
|
||||
#ifdef XZ_DEC_BCJ
|
||||
if (s->temp.buf[1] & 0x3E)
|
||||
#else
|
||||
if (s->temp.buf[1] & 0x3F)
|
||||
#endif
|
||||
return XZ_OPTIONS_ERROR;
|
||||
|
||||
/* Compressed Size */
|
||||
if (s->temp.buf[1] & 0x40) {
|
||||
if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size)
|
||||
!= XZ_STREAM_END)
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
s->block_header.compressed = s->vli;
|
||||
} else {
|
||||
s->block_header.compressed = VLI_UNKNOWN;
|
||||
}
|
||||
|
||||
/* Uncompressed Size */
|
||||
if (s->temp.buf[1] & 0x80) {
|
||||
if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size)
|
||||
!= XZ_STREAM_END)
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
s->block_header.uncompressed = s->vli;
|
||||
} else {
|
||||
s->block_header.uncompressed = VLI_UNKNOWN;
|
||||
}
|
||||
|
||||
#ifdef XZ_DEC_BCJ
|
||||
/* If there are two filters, the first one must be a BCJ filter. */
|
||||
s->bcj_active = s->temp.buf[1] & 0x01;
|
||||
if (s->bcj_active) {
|
||||
if (s->temp.size - s->temp.pos < 2)
|
||||
return XZ_OPTIONS_ERROR;
|
||||
|
||||
ret = xz_dec_bcj_reset(s->bcj, s->temp.buf[s->temp.pos++]);
|
||||
if (ret != XZ_OK)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* We don't support custom start offset,
|
||||
* so Size of Properties must be zero.
|
||||
*/
|
||||
if (s->temp.buf[s->temp.pos++] != 0x00)
|
||||
return XZ_OPTIONS_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Valid Filter Flags always take at least two bytes. */
|
||||
if (s->temp.size - s->temp.pos < 2)
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
/* Filter ID = LZMA2 */
|
||||
if (s->temp.buf[s->temp.pos++] != 0x21)
|
||||
return XZ_OPTIONS_ERROR;
|
||||
|
||||
/* Size of Properties = 1-byte Filter Properties */
|
||||
if (s->temp.buf[s->temp.pos++] != 0x01)
|
||||
return XZ_OPTIONS_ERROR;
|
||||
|
||||
/* Filter Properties contains LZMA2 dictionary size. */
|
||||
if (s->temp.size - s->temp.pos < 1)
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
ret = xz_dec_lzma2_reset(s->lzma2, s->temp.buf[s->temp.pos++]);
|
||||
if (ret != XZ_OK)
|
||||
return ret;
|
||||
|
||||
/* The rest must be Header Padding. */
|
||||
while (s->temp.pos < s->temp.size)
|
||||
if (s->temp.buf[s->temp.pos++] != 0x00)
|
||||
return XZ_OPTIONS_ERROR;
|
||||
|
||||
s->temp.pos = 0;
|
||||
s->block.compressed = 0;
|
||||
s->block.uncompressed = 0;
|
||||
|
||||
return XZ_OK;
|
||||
}
|
||||
|
||||
static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b)
|
||||
{
|
||||
enum xz_ret ret;
|
||||
|
||||
/*
|
||||
* Store the start position for the case when we are in the middle
|
||||
* of the Index field.
|
||||
*/
|
||||
s->in_start = b->in_pos;
|
||||
|
||||
while (true) {
|
||||
switch (s->sequence) {
|
||||
case SEQ_STREAM_HEADER:
|
||||
/*
|
||||
* Stream Header is copied to s->temp, and then
|
||||
* decoded from there. This way if the caller
|
||||
* gives us only little input at a time, we can
|
||||
* still keep the Stream Header decoding code
|
||||
* simple. Similar approach is used in many places
|
||||
* in this file.
|
||||
*/
|
||||
if (!fill_temp(s, b))
|
||||
return XZ_OK;
|
||||
|
||||
/*
|
||||
* If dec_stream_header() returns
|
||||
* XZ_UNSUPPORTED_CHECK, it is still possible
|
||||
* to continue decoding if working in multi-call
|
||||
* mode. Thus, update s->sequence before calling
|
||||
* dec_stream_header().
|
||||
*/
|
||||
s->sequence = SEQ_BLOCK_START;
|
||||
|
||||
ret = dec_stream_header(s);
|
||||
if (ret != XZ_OK)
|
||||
return ret;
|
||||
|
||||
case SEQ_BLOCK_START:
|
||||
/* We need one byte of input to continue. */
|
||||
if (b->in_pos == b->in_size)
|
||||
return XZ_OK;
|
||||
|
||||
/* See if this is the beginning of the Index field. */
|
||||
if (b->in[b->in_pos] == 0) {
|
||||
s->in_start = b->in_pos++;
|
||||
s->sequence = SEQ_INDEX;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the size of the Block Header and
|
||||
* prepare to decode it.
|
||||
*/
|
||||
s->block_header.size
|
||||
= ((uint32_t)b->in[b->in_pos] + 1) * 4;
|
||||
|
||||
s->temp.size = s->block_header.size;
|
||||
s->temp.pos = 0;
|
||||
s->sequence = SEQ_BLOCK_HEADER;
|
||||
|
||||
case SEQ_BLOCK_HEADER:
|
||||
if (!fill_temp(s, b))
|
||||
return XZ_OK;
|
||||
|
||||
ret = dec_block_header(s);
|
||||
if (ret != XZ_OK)
|
||||
return ret;
|
||||
|
||||
s->sequence = SEQ_BLOCK_UNCOMPRESS;
|
||||
|
||||
case SEQ_BLOCK_UNCOMPRESS:
|
||||
ret = dec_block(s, b);
|
||||
if (ret != XZ_STREAM_END)
|
||||
return ret;
|
||||
|
||||
s->sequence = SEQ_BLOCK_PADDING;
|
||||
|
||||
case SEQ_BLOCK_PADDING:
|
||||
/*
|
||||
* Size of Compressed Data + Block Padding
|
||||
* must be a multiple of four. We don't need
|
||||
* s->block.compressed for anything else
|
||||
* anymore, so we use it here to test the size
|
||||
* of the Block Padding field.
|
||||
*/
|
||||
while (s->block.compressed & 3) {
|
||||
if (b->in_pos == b->in_size)
|
||||
return XZ_OK;
|
||||
|
||||
if (b->in[b->in_pos++] != 0)
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
++s->block.compressed;
|
||||
}
|
||||
|
||||
s->sequence = SEQ_BLOCK_CHECK;
|
||||
|
||||
case SEQ_BLOCK_CHECK:
|
||||
if (s->check_type == XZ_CHECK_CRC32) {
|
||||
ret = crc_validate(s, b, 32);
|
||||
if (ret != XZ_STREAM_END)
|
||||
return ret;
|
||||
}
|
||||
else if (IS_CRC64(s->check_type)) {
|
||||
ret = crc_validate(s, b, 64);
|
||||
if (ret != XZ_STREAM_END)
|
||||
return ret;
|
||||
}
|
||||
#ifdef XZ_DEC_ANY_CHECK
|
||||
else if (!check_skip(s, b)) {
|
||||
return XZ_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
s->sequence = SEQ_BLOCK_START;
|
||||
break;
|
||||
|
||||
case SEQ_INDEX:
|
||||
ret = dec_index(s, b);
|
||||
if (ret != XZ_STREAM_END)
|
||||
return ret;
|
||||
|
||||
s->sequence = SEQ_INDEX_PADDING;
|
||||
|
||||
case SEQ_INDEX_PADDING:
|
||||
while ((s->index.size + (b->in_pos - s->in_start))
|
||||
& 3) {
|
||||
if (b->in_pos == b->in_size) {
|
||||
index_update(s, b);
|
||||
return XZ_OK;
|
||||
}
|
||||
|
||||
if (b->in[b->in_pos++] != 0)
|
||||
return XZ_DATA_ERROR;
|
||||
}
|
||||
|
||||
/* Finish the CRC32 value and Index size. */
|
||||
index_update(s, b);
|
||||
|
||||
/* Compare the hashes to validate the Index field. */
|
||||
if (!memeq(&s->block.hash, &s->index.hash,
|
||||
sizeof(s->block.hash)))
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
s->sequence = SEQ_INDEX_CRC32;
|
||||
|
||||
case SEQ_INDEX_CRC32:
|
||||
ret = crc_validate(s, b, 32);
|
||||
if (ret != XZ_STREAM_END)
|
||||
return ret;
|
||||
|
||||
s->temp.size = STREAM_HEADER_SIZE;
|
||||
s->sequence = SEQ_STREAM_FOOTER;
|
||||
|
||||
case SEQ_STREAM_FOOTER:
|
||||
if (!fill_temp(s, b))
|
||||
return XZ_OK;
|
||||
|
||||
return dec_stream_footer(s);
|
||||
}
|
||||
}
|
||||
|
||||
/* Never reached */
|
||||
}
|
||||
|
||||
/*
|
||||
* xz_dec_run() is a wrapper for dec_main() to handle some special cases in
|
||||
* multi-call and single-call decoding.
|
||||
*
|
||||
* In multi-call mode, we must return XZ_BUF_ERROR when it seems clear that we
|
||||
* are not going to make any progress anymore. This is to prevent the caller
|
||||
* from calling us infinitely when the input file is truncated or otherwise
|
||||
* corrupt. Since zlib-style API allows that the caller fills the input buffer
|
||||
* only when the decoder doesn't produce any new output, we have to be careful
|
||||
* to avoid returning XZ_BUF_ERROR too easily: XZ_BUF_ERROR is returned only
|
||||
* after the second consecutive call to xz_dec_run() that makes no progress.
|
||||
*
|
||||
* In single-call mode, if we couldn't decode everything and no error
|
||||
* occurred, either the input is truncated or the output buffer is too small.
|
||||
* Since we know that the last input byte never produces any output, we know
|
||||
* that if all the input was consumed and decoding wasn't finished, the file
|
||||
* must be corrupt. Otherwise the output buffer has to be too small or the
|
||||
* file is corrupt in a way that decoding it produces too big output.
|
||||
*
|
||||
* If single-call decoding fails, we reset b->in_pos and b->out_pos back to
|
||||
* their original values. This is because with some filter chains there won't
|
||||
* be any valid uncompressed data in the output buffer unless the decoding
|
||||
* actually succeeds (that's the price to pay of using the output buffer as
|
||||
* the workspace).
|
||||
*/
|
||||
XZ_EXTERN enum xz_ret xz_dec_run(struct xz_dec *s, struct xz_buf *b)
|
||||
{
|
||||
size_t in_start;
|
||||
size_t out_start;
|
||||
enum xz_ret ret;
|
||||
|
||||
if (DEC_IS_SINGLE(s->mode))
|
||||
xz_dec_reset(s);
|
||||
|
||||
in_start = b->in_pos;
|
||||
out_start = b->out_pos;
|
||||
ret = dec_main(s, b);
|
||||
|
||||
if (DEC_IS_SINGLE(s->mode)) {
|
||||
if (ret == XZ_OK)
|
||||
ret = b->in_pos == b->in_size
|
||||
? XZ_DATA_ERROR : XZ_BUF_ERROR;
|
||||
|
||||
if (ret != XZ_STREAM_END) {
|
||||
b->in_pos = in_start;
|
||||
b->out_pos = out_start;
|
||||
}
|
||||
|
||||
} else if (ret == XZ_OK && in_start == b->in_pos
|
||||
&& out_start == b->out_pos) {
|
||||
if (s->allow_buf_error)
|
||||
ret = XZ_BUF_ERROR;
|
||||
|
||||
s->allow_buf_error = true;
|
||||
} else {
|
||||
s->allow_buf_error = false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
XZ_EXTERN struct xz_dec *xz_dec_init(enum xz_mode mode, uint32_t dict_max)
|
||||
{
|
||||
struct xz_dec *s = kmalloc(sizeof(*s), GFP_KERNEL);
|
||||
if (s == NULL)
|
||||
return NULL;
|
||||
|
||||
s->mode = mode;
|
||||
|
||||
#ifdef XZ_DEC_BCJ
|
||||
s->bcj = xz_dec_bcj_create(DEC_IS_SINGLE(mode));
|
||||
if (s->bcj == NULL)
|
||||
goto error_bcj;
|
||||
#endif
|
||||
|
||||
s->lzma2 = xz_dec_lzma2_create(mode, dict_max);
|
||||
if (s->lzma2 == NULL)
|
||||
goto error_lzma2;
|
||||
|
||||
xz_dec_reset(s);
|
||||
return s;
|
||||
|
||||
error_lzma2:
|
||||
#ifdef XZ_DEC_BCJ
|
||||
xz_dec_bcj_end(s->bcj);
|
||||
error_bcj:
|
||||
#endif
|
||||
kfree(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
XZ_EXTERN void xz_dec_reset(struct xz_dec *s)
|
||||
{
|
||||
s->sequence = SEQ_STREAM_HEADER;
|
||||
s->allow_buf_error = false;
|
||||
s->pos = 0;
|
||||
s->crc = 0;
|
||||
memzero(&s->block, sizeof(s->block));
|
||||
memzero(&s->index, sizeof(s->index));
|
||||
s->temp.pos = 0;
|
||||
s->temp.size = STREAM_HEADER_SIZE;
|
||||
}
|
||||
|
||||
XZ_EXTERN void xz_dec_end(struct xz_dec *s)
|
||||
{
|
||||
if (s != NULL) {
|
||||
xz_dec_lzma2_end(s->lzma2);
|
||||
#ifdef XZ_DEC_BCJ
|
||||
xz_dec_bcj_end(s->bcj);
|
||||
#endif
|
||||
kfree(s);
|
||||
}
|
||||
}
|
204
depends/xz-embedded/src/xz_lzma2.h
Normal file
204
depends/xz-embedded/src/xz_lzma2.h
Normal file
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* LZMA2 definitions
|
||||
*
|
||||
* Authors: Lasse Collin <lasse.collin@tukaani.org>
|
||||
* Igor Pavlov <http://7-zip.org/>
|
||||
*
|
||||
* This file has been put into the public domain.
|
||||
* You can do whatever you want with this file.
|
||||
*/
|
||||
|
||||
#ifndef XZ_LZMA2_H
|
||||
#define XZ_LZMA2_H
|
||||
|
||||
/* Range coder constants */
|
||||
#define RC_SHIFT_BITS 8
|
||||
#define RC_TOP_BITS 24
|
||||
#define RC_TOP_VALUE (1 << RC_TOP_BITS)
|
||||
#define RC_BIT_MODEL_TOTAL_BITS 11
|
||||
#define RC_BIT_MODEL_TOTAL (1 << RC_BIT_MODEL_TOTAL_BITS)
|
||||
#define RC_MOVE_BITS 5
|
||||
|
||||
/*
|
||||
* Maximum number of position states. A position state is the lowest pb
|
||||
* number of bits of the current uncompressed offset. In some places there
|
||||
* are different sets of probabilities for different position states.
|
||||
*/
|
||||
#define POS_STATES_MAX (1 << 4)
|
||||
|
||||
/*
|
||||
* This enum is used to track which LZMA symbols have occurred most recently
|
||||
* and in which order. This information is used to predict the next symbol.
|
||||
*
|
||||
* Symbols:
|
||||
* - Literal: One 8-bit byte
|
||||
* - Match: Repeat a chunk of data at some distance
|
||||
* - Long repeat: Multi-byte match at a recently seen distance
|
||||
* - Short repeat: One-byte repeat at a recently seen distance
|
||||
*
|
||||
* The symbol names are in from STATE_oldest_older_previous. REP means
|
||||
* either short or long repeated match, and NONLIT means any non-literal.
|
||||
*/
|
||||
enum lzma_state {
|
||||
STATE_LIT_LIT,
|
||||
STATE_MATCH_LIT_LIT,
|
||||
STATE_REP_LIT_LIT,
|
||||
STATE_SHORTREP_LIT_LIT,
|
||||
STATE_MATCH_LIT,
|
||||
STATE_REP_LIT,
|
||||
STATE_SHORTREP_LIT,
|
||||
STATE_LIT_MATCH,
|
||||
STATE_LIT_LONGREP,
|
||||
STATE_LIT_SHORTREP,
|
||||
STATE_NONLIT_MATCH,
|
||||
STATE_NONLIT_REP
|
||||
};
|
||||
|
||||
/* Total number of states */
|
||||
#define STATES 12
|
||||
|
||||
/* The lowest 7 states indicate that the previous state was a literal. */
|
||||
#define LIT_STATES 7
|
||||
|
||||
/* Indicate that the latest symbol was a literal. */
|
||||
static inline void lzma_state_literal(enum lzma_state *state)
|
||||
{
|
||||
if (*state <= STATE_SHORTREP_LIT_LIT)
|
||||
*state = STATE_LIT_LIT;
|
||||
else if (*state <= STATE_LIT_SHORTREP)
|
||||
*state -= 3;
|
||||
else
|
||||
*state -= 6;
|
||||
}
|
||||
|
||||
/* Indicate that the latest symbol was a match. */
|
||||
static inline void lzma_state_match(enum lzma_state *state)
|
||||
{
|
||||
*state = *state < LIT_STATES ? STATE_LIT_MATCH : STATE_NONLIT_MATCH;
|
||||
}
|
||||
|
||||
/* Indicate that the latest state was a long repeated match. */
|
||||
static inline void lzma_state_long_rep(enum lzma_state *state)
|
||||
{
|
||||
*state = *state < LIT_STATES ? STATE_LIT_LONGREP : STATE_NONLIT_REP;
|
||||
}
|
||||
|
||||
/* Indicate that the latest symbol was a short match. */
|
||||
static inline void lzma_state_short_rep(enum lzma_state *state)
|
||||
{
|
||||
*state = *state < LIT_STATES ? STATE_LIT_SHORTREP : STATE_NONLIT_REP;
|
||||
}
|
||||
|
||||
/* Test if the previous symbol was a literal. */
|
||||
static inline bool lzma_state_is_literal(enum lzma_state state)
|
||||
{
|
||||
return state < LIT_STATES;
|
||||
}
|
||||
|
||||
/* Each literal coder is divided in three sections:
|
||||
* - 0x001-0x0FF: Without match byte
|
||||
* - 0x101-0x1FF: With match byte; match bit is 0
|
||||
* - 0x201-0x2FF: With match byte; match bit is 1
|
||||
*
|
||||
* Match byte is used when the previous LZMA symbol was something else than
|
||||
* a literal (that is, it was some kind of match).
|
||||
*/
|
||||
#define LITERAL_CODER_SIZE 0x300
|
||||
|
||||
/* Maximum number of literal coders */
|
||||
#define LITERAL_CODERS_MAX (1 << 4)
|
||||
|
||||
/* Minimum length of a match is two bytes. */
|
||||
#define MATCH_LEN_MIN 2
|
||||
|
||||
/* Match length is encoded with 4, 5, or 10 bits.
|
||||
*
|
||||
* Length Bits
|
||||
* 2-9 4 = Choice=0 + 3 bits
|
||||
* 10-17 5 = Choice=1 + Choice2=0 + 3 bits
|
||||
* 18-273 10 = Choice=1 + Choice2=1 + 8 bits
|
||||
*/
|
||||
#define LEN_LOW_BITS 3
|
||||
#define LEN_LOW_SYMBOLS (1 << LEN_LOW_BITS)
|
||||
#define LEN_MID_BITS 3
|
||||
#define LEN_MID_SYMBOLS (1 << LEN_MID_BITS)
|
||||
#define LEN_HIGH_BITS 8
|
||||
#define LEN_HIGH_SYMBOLS (1 << LEN_HIGH_BITS)
|
||||
#define LEN_SYMBOLS (LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS + LEN_HIGH_SYMBOLS)
|
||||
|
||||
/*
|
||||
* Maximum length of a match is 273 which is a result of the encoding
|
||||
* described above.
|
||||
*/
|
||||
#define MATCH_LEN_MAX (MATCH_LEN_MIN + LEN_SYMBOLS - 1)
|
||||
|
||||
/*
|
||||
* Different sets of probabilities are used for match distances that have
|
||||
* very short match length: Lengths of 2, 3, and 4 bytes have a separate
|
||||
* set of probabilities for each length. The matches with longer length
|
||||
* use a shared set of probabilities.
|
||||
*/
|
||||
#define DIST_STATES 4
|
||||
|
||||
/*
|
||||
* Get the index of the appropriate probability array for decoding
|
||||
* the distance slot.
|
||||
*/
|
||||
static inline uint32_t lzma_get_dist_state(uint32_t len)
|
||||
{
|
||||
return len < DIST_STATES + MATCH_LEN_MIN
|
||||
? len - MATCH_LEN_MIN : DIST_STATES - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The highest two bits of a 32-bit match distance are encoded using six bits.
|
||||
* This six-bit value is called a distance slot. This way encoding a 32-bit
|
||||
* value takes 6-36 bits, larger values taking more bits.
|
||||
*/
|
||||
#define DIST_SLOT_BITS 6
|
||||
#define DIST_SLOTS (1 << DIST_SLOT_BITS)
|
||||
|
||||
/* Match distances up to 127 are fully encoded using probabilities. Since
|
||||
* the highest two bits (distance slot) are always encoded using six bits,
|
||||
* the distances 0-3 don't need any additional bits to encode, since the
|
||||
* distance slot itself is the same as the actual distance. DIST_MODEL_START
|
||||
* indicates the first distance slot where at least one additional bit is
|
||||
* needed.
|
||||
*/
|
||||
#define DIST_MODEL_START 4
|
||||
|
||||
/*
|
||||
* Match distances greater than 127 are encoded in three pieces:
|
||||
* - distance slot: the highest two bits
|
||||
* - direct bits: 2-26 bits below the highest two bits
|
||||
* - alignment bits: four lowest bits
|
||||
*
|
||||
* Direct bits don't use any probabilities.
|
||||
*
|
||||
* The distance slot value of 14 is for distances 128-191.
|
||||
*/
|
||||
#define DIST_MODEL_END 14
|
||||
|
||||
/* Distance slots that indicate a distance <= 127. */
|
||||
#define FULL_DISTANCES_BITS (DIST_MODEL_END / 2)
|
||||
#define FULL_DISTANCES (1 << FULL_DISTANCES_BITS)
|
||||
|
||||
/*
|
||||
* For match distances greater than 127, only the highest two bits and the
|
||||
* lowest four bits (alignment) is encoded using probabilities.
|
||||
*/
|
||||
#define ALIGN_BITS 4
|
||||
#define ALIGN_SIZE (1 << ALIGN_BITS)
|
||||
#define ALIGN_MASK (ALIGN_SIZE - 1)
|
||||
|
||||
/* Total number of all probability variables */
|
||||
#define PROBS_TOTAL (1846 + LITERAL_CODERS_MAX * LITERAL_CODER_SIZE)
|
||||
|
||||
/*
|
||||
* LZMA remembers the four most recent match distances. Reusing these
|
||||
* distances tends to take less space than re-encoding the actual
|
||||
* distance value.
|
||||
*/
|
||||
#define REPS 4
|
||||
|
||||
#endif
|
156
depends/xz-embedded/src/xz_private.h
Normal file
156
depends/xz-embedded/src/xz_private.h
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Private includes and definitions
|
||||
*
|
||||
* Author: Lasse Collin <lasse.collin@tukaani.org>
|
||||
*
|
||||
* This file has been put into the public domain.
|
||||
* You can do whatever you want with this file.
|
||||
*/
|
||||
|
||||
#ifndef XZ_PRIVATE_H
|
||||
#define XZ_PRIVATE_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
# include <linux/xz.h>
|
||||
# include <linux/kernel.h>
|
||||
# include <asm/unaligned.h>
|
||||
/* XZ_PREBOOT may be defined only via decompress_unxz.c. */
|
||||
# ifndef XZ_PREBOOT
|
||||
# include <linux/slab.h>
|
||||
# include <linux/vmalloc.h>
|
||||
# include <linux/string.h>
|
||||
# ifdef CONFIG_XZ_DEC_X86
|
||||
# define XZ_DEC_X86
|
||||
# endif
|
||||
# ifdef CONFIG_XZ_DEC_POWERPC
|
||||
# define XZ_DEC_POWERPC
|
||||
# endif
|
||||
# ifdef CONFIG_XZ_DEC_IA64
|
||||
# define XZ_DEC_IA64
|
||||
# endif
|
||||
# ifdef CONFIG_XZ_DEC_ARM
|
||||
# define XZ_DEC_ARM
|
||||
# endif
|
||||
# ifdef CONFIG_XZ_DEC_ARMTHUMB
|
||||
# define XZ_DEC_ARMTHUMB
|
||||
# endif
|
||||
# ifdef CONFIG_XZ_DEC_SPARC
|
||||
# define XZ_DEC_SPARC
|
||||
# endif
|
||||
# define memeq(a, b, size) (memcmp(a, b, size) == 0)
|
||||
# define memzero(buf, size) memset(buf, 0, size)
|
||||
# endif
|
||||
# define get_le32(p) le32_to_cpup((const uint32_t *)(p))
|
||||
#else
|
||||
/*
|
||||
* For userspace builds, use a separate header to define the required
|
||||
* macros and functions. This makes it easier to adapt the code into
|
||||
* different environments and avoids clutter in the Linux kernel tree.
|
||||
*/
|
||||
# include "xz_config.h"
|
||||
#endif
|
||||
|
||||
/* If no specific decoding mode is requested, enable support for all modes. */
|
||||
#if !defined(XZ_DEC_SINGLE) && !defined(XZ_DEC_PREALLOC) \
|
||||
&& !defined(XZ_DEC_DYNALLOC)
|
||||
# define XZ_DEC_SINGLE
|
||||
# define XZ_DEC_PREALLOC
|
||||
# define XZ_DEC_DYNALLOC
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The DEC_IS_foo(mode) macros are used in "if" statements. If only some
|
||||
* of the supported modes are enabled, these macros will evaluate to true or
|
||||
* false at compile time and thus allow the compiler to omit unneeded code.
|
||||
*/
|
||||
#ifdef XZ_DEC_SINGLE
|
||||
# define DEC_IS_SINGLE(mode) ((mode) == XZ_SINGLE)
|
||||
#else
|
||||
# define DEC_IS_SINGLE(mode) (false)
|
||||
#endif
|
||||
|
||||
#ifdef XZ_DEC_PREALLOC
|
||||
# define DEC_IS_PREALLOC(mode) ((mode) == XZ_PREALLOC)
|
||||
#else
|
||||
# define DEC_IS_PREALLOC(mode) (false)
|
||||
#endif
|
||||
|
||||
#ifdef XZ_DEC_DYNALLOC
|
||||
# define DEC_IS_DYNALLOC(mode) ((mode) == XZ_DYNALLOC)
|
||||
#else
|
||||
# define DEC_IS_DYNALLOC(mode) (false)
|
||||
#endif
|
||||
|
||||
#if !defined(XZ_DEC_SINGLE)
|
||||
# define DEC_IS_MULTI(mode) (true)
|
||||
#elif defined(XZ_DEC_PREALLOC) || defined(XZ_DEC_DYNALLOC)
|
||||
# define DEC_IS_MULTI(mode) ((mode) != XZ_SINGLE)
|
||||
#else
|
||||
# define DEC_IS_MULTI(mode) (false)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If any of the BCJ filter decoders are wanted, define XZ_DEC_BCJ.
|
||||
* XZ_DEC_BCJ is used to enable generic support for BCJ decoders.
|
||||
*/
|
||||
#ifndef XZ_DEC_BCJ
|
||||
# if defined(XZ_DEC_X86) || defined(XZ_DEC_POWERPC) \
|
||||
|| defined(XZ_DEC_IA64) || defined(XZ_DEC_ARM) \
|
||||
|| defined(XZ_DEC_ARM) || defined(XZ_DEC_ARMTHUMB) \
|
||||
|| defined(XZ_DEC_SPARC)
|
||||
# define XZ_DEC_BCJ
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Allocate memory for LZMA2 decoder. xz_dec_lzma2_reset() must be used
|
||||
* before calling xz_dec_lzma2_run().
|
||||
*/
|
||||
XZ_EXTERN struct xz_dec_lzma2 *xz_dec_lzma2_create(enum xz_mode mode,
|
||||
uint32_t dict_max);
|
||||
|
||||
/*
|
||||
* Decode the LZMA2 properties (one byte) and reset the decoder. Return
|
||||
* XZ_OK on success, XZ_MEMLIMIT_ERROR if the preallocated dictionary is not
|
||||
* big enough, and XZ_OPTIONS_ERROR if props indicates something that this
|
||||
* decoder doesn't support.
|
||||
*/
|
||||
XZ_EXTERN enum xz_ret xz_dec_lzma2_reset(struct xz_dec_lzma2 *s,
|
||||
uint8_t props);
|
||||
|
||||
/* Decode raw LZMA2 stream from b->in to b->out. */
|
||||
XZ_EXTERN enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s,
|
||||
struct xz_buf *b);
|
||||
|
||||
/* Free the memory allocated for the LZMA2 decoder. */
|
||||
XZ_EXTERN void xz_dec_lzma2_end(struct xz_dec_lzma2 *s);
|
||||
|
||||
#ifdef XZ_DEC_BCJ
|
||||
/*
|
||||
* Allocate memory for BCJ decoders. xz_dec_bcj_reset() must be used before
|
||||
* calling xz_dec_bcj_run().
|
||||
*/
|
||||
XZ_EXTERN struct xz_dec_bcj *xz_dec_bcj_create(bool single_call);
|
||||
|
||||
/*
|
||||
* Decode the Filter ID of a BCJ filter. This implementation doesn't
|
||||
* support custom start offsets, so no decoding of Filter Properties
|
||||
* is needed. Returns XZ_OK if the given Filter ID is supported.
|
||||
* Otherwise XZ_OPTIONS_ERROR is returned.
|
||||
*/
|
||||
XZ_EXTERN enum xz_ret xz_dec_bcj_reset(struct xz_dec_bcj *s, uint8_t id);
|
||||
|
||||
/*
|
||||
* Decode raw BCJ + LZMA2 stream. This must be used only if there actually is
|
||||
* a BCJ filter in the chain. If the chain has only LZMA2, xz_dec_lzma2_run()
|
||||
* must be called directly.
|
||||
*/
|
||||
XZ_EXTERN enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s,
|
||||
struct xz_dec_lzma2 *lzma2,
|
||||
struct xz_buf *b);
|
||||
|
||||
/* Free the memory allocated for the BCJ filters. */
|
||||
#define xz_dec_bcj_end(s) kfree(s)
|
||||
#endif
|
||||
|
||||
#endif
|
62
depends/xz-embedded/src/xz_stream.h
Normal file
62
depends/xz-embedded/src/xz_stream.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Definitions for handling the .xz file format
|
||||
*
|
||||
* Author: Lasse Collin <lasse.collin@tukaani.org>
|
||||
*
|
||||
* This file has been put into the public domain.
|
||||
* You can do whatever you want with this file.
|
||||
*/
|
||||
|
||||
#ifndef XZ_STREAM_H
|
||||
#define XZ_STREAM_H
|
||||
|
||||
#if defined(__KERNEL__) && !XZ_INTERNAL_CRC32
|
||||
# include <linux/crc32.h>
|
||||
# undef crc32
|
||||
# define xz_crc32(buf, size, crc) \
|
||||
(~crc32_le(~(uint32_t)(crc), buf, size))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* See the .xz file format specification at
|
||||
* http://tukaani.org/xz/xz-file-format.txt
|
||||
* to understand the container format.
|
||||
*/
|
||||
|
||||
#define STREAM_HEADER_SIZE 12
|
||||
|
||||
#define HEADER_MAGIC "\3757zXZ"
|
||||
#define HEADER_MAGIC_SIZE 6
|
||||
|
||||
#define FOOTER_MAGIC "YZ"
|
||||
#define FOOTER_MAGIC_SIZE 2
|
||||
|
||||
/*
|
||||
* Variable-length integer can hold a 63-bit unsigned integer or a special
|
||||
* value indicating that the value is unknown.
|
||||
*
|
||||
* Experimental: vli_type can be defined to uint32_t to save a few bytes
|
||||
* in code size (no effect on speed). Doing so limits the uncompressed and
|
||||
* compressed size of the file to less than 256 MiB and may also weaken
|
||||
* error detection slightly.
|
||||
*/
|
||||
typedef uint64_t vli_type;
|
||||
|
||||
#define VLI_MAX ((vli_type)-1 / 2)
|
||||
#define VLI_UNKNOWN ((vli_type)-1)
|
||||
|
||||
/* Maximum encoded size of a VLI */
|
||||
#define VLI_BYTES_MAX (sizeof(vli_type) * 8 / 7)
|
||||
|
||||
/* Integrity Check types */
|
||||
enum xz_check {
|
||||
XZ_CHECK_NONE = 0,
|
||||
XZ_CHECK_CRC32 = 1,
|
||||
XZ_CHECK_CRC64 = 4,
|
||||
XZ_CHECK_SHA256 = 10
|
||||
};
|
||||
|
||||
/* Maximum possible Check ID */
|
||||
#define XZ_CHECK_MAX 15
|
||||
|
||||
#endif
|
135
depends/xz-embedded/xzminidec.c
Normal file
135
depends/xz-embedded/xzminidec.c
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Simple XZ decoder command line tool
|
||||
*
|
||||
* Author: Lasse Collin <lasse.collin@tukaani.org>
|
||||
*
|
||||
* This file has been put into the public domain.
|
||||
* You can do whatever you want with this file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is really limited: Not all filters from .xz format are supported,
|
||||
* only CRC32 is supported as the integrity check, and decoding of
|
||||
* concatenated .xz streams is not supported. Thus, you may want to look
|
||||
* at xzdec from XZ Utils if a few KiB bigger tool is not a problem.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "xz.h"
|
||||
|
||||
static uint8_t in[BUFSIZ];
|
||||
static uint8_t out[BUFSIZ];
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct xz_buf b;
|
||||
struct xz_dec *s;
|
||||
enum xz_ret ret;
|
||||
const char *msg;
|
||||
|
||||
if (argc >= 2 && strcmp(argv[1], "--help") == 0) {
|
||||
fputs("Uncompress a .xz file from stdin to stdout.\n"
|
||||
"Arguments other than `--help' are ignored.\n",
|
||||
stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
xz_crc32_init();
|
||||
#ifdef XZ_USE_CRC64
|
||||
xz_crc64_init();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Support up to 64 MiB dictionary. The actually needed memory
|
||||
* is allocated once the headers have been parsed.
|
||||
*/
|
||||
s = xz_dec_init(XZ_DYNALLOC, 1 << 26);
|
||||
if (s == NULL) {
|
||||
msg = "Memory allocation failed\n";
|
||||
goto error;
|
||||
}
|
||||
|
||||
b.in = in;
|
||||
b.in_pos = 0;
|
||||
b.in_size = 0;
|
||||
b.out = out;
|
||||
b.out_pos = 0;
|
||||
b.out_size = BUFSIZ;
|
||||
|
||||
while (true) {
|
||||
if (b.in_pos == b.in_size) {
|
||||
b.in_size = fread(in, 1, sizeof(in), stdin);
|
||||
b.in_pos = 0;
|
||||
}
|
||||
|
||||
ret = xz_dec_run(s, &b);
|
||||
|
||||
if (b.out_pos == sizeof(out)) {
|
||||
if (fwrite(out, 1, b.out_pos, stdout) != b.out_pos) {
|
||||
msg = "Write error\n";
|
||||
goto error;
|
||||
}
|
||||
|
||||
b.out_pos = 0;
|
||||
}
|
||||
|
||||
if (ret == XZ_OK)
|
||||
continue;
|
||||
|
||||
#ifdef XZ_DEC_ANY_CHECK
|
||||
if (ret == XZ_UNSUPPORTED_CHECK) {
|
||||
fputs(argv[0], stderr);
|
||||
fputs(": ", stderr);
|
||||
fputs("Unsupported check; not verifying "
|
||||
"file integrity\n", stderr);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (fwrite(out, 1, b.out_pos, stdout) != b.out_pos
|
||||
|| fclose(stdout)) {
|
||||
msg = "Write error\n";
|
||||
goto error;
|
||||
}
|
||||
|
||||
switch (ret) {
|
||||
case XZ_STREAM_END:
|
||||
xz_dec_end(s);
|
||||
return 0;
|
||||
|
||||
case XZ_MEM_ERROR:
|
||||
msg = "Memory allocation failed\n";
|
||||
goto error;
|
||||
|
||||
case XZ_MEMLIMIT_ERROR:
|
||||
msg = "Memory usage limit reached\n";
|
||||
goto error;
|
||||
|
||||
case XZ_FORMAT_ERROR:
|
||||
msg = "Not a .xz file\n";
|
||||
goto error;
|
||||
|
||||
case XZ_OPTIONS_ERROR:
|
||||
msg = "Unsupported options in the .xz headers\n";
|
||||
goto error;
|
||||
|
||||
case XZ_DATA_ERROR:
|
||||
case XZ_BUF_ERROR:
|
||||
msg = "File is corrupt\n";
|
||||
goto error;
|
||||
|
||||
default:
|
||||
msg = "Bug!\n";
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
error:
|
||||
xz_dec_end(s);
|
||||
fputs(argv[0], stderr);
|
||||
fputs(": ", stderr);
|
||||
fputs(msg, stderr);
|
||||
return 1;
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
#include "EditNotesDialog.h"
|
||||
#include "ui_EditNotesDialog.h"
|
||||
#include "gui/platform.h"
|
||||
|
||||
#include <QIcon>
|
||||
#include <QApplication>
|
||||
@ -10,9 +11,10 @@ EditNotesDialog::EditNotesDialog( QString notes, QString name, QWidget* parent )
|
||||
QDialog(parent),
|
||||
ui(new Ui::EditNotesDialog)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
ui->setupUi(this);
|
||||
ui->noteEditor->setText(notes);
|
||||
setWindowTitle("Edit notes of " + m_instance_name);
|
||||
setWindowTitle(tr("Edit notes of %1").arg(m_instance_name));
|
||||
//connect(ui->closeButton, SIGNAL(clicked()), SLOT(close()));
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "instancedelegate.h"
|
||||
#include "ui_IconPickerDialog.h"
|
||||
#include "logic/lists/IconList.h"
|
||||
#include "gui/platform.h"
|
||||
#include <QKeyEvent>
|
||||
#include <QPushButton>
|
||||
#include <QFileDialog>
|
||||
@ -11,6 +12,7 @@ IconPickerDialog::IconPickerDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::IconPickerDialog)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
ui->setupUi(this);
|
||||
setWindowModality(Qt::WindowModal);
|
||||
|
||||
@ -39,10 +41,10 @@ IconPickerDialog::IconPickerDialog(QWidget *parent) :
|
||||
|
||||
contentsWidget->installEventFilter(this);
|
||||
|
||||
contentsWidget->setModel(MMC->icons());
|
||||
contentsWidget->setModel(MMC->icons().get());
|
||||
|
||||
auto buttonAdd = ui->buttonBox->addButton("Add Icon",QDialogButtonBox::ResetRole);
|
||||
auto buttonRemove = ui->buttonBox->addButton("Remove Icon",QDialogButtonBox::ResetRole);
|
||||
auto buttonAdd = ui->buttonBox->addButton(tr("Add Icon"),QDialogButtonBox::ResetRole);
|
||||
auto buttonRemove = ui->buttonBox->addButton(tr("Remove Icon"),QDialogButtonBox::ResetRole);
|
||||
|
||||
|
||||
connect(buttonAdd,SIGNAL(clicked(bool)),SLOT(addNewIcon()));
|
||||
@ -87,7 +89,10 @@ bool IconPickerDialog::eventFilter ( QObject* obj, QEvent* evt)
|
||||
|
||||
void IconPickerDialog::addNewIcon()
|
||||
{
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(this, "Select Icons", QString(), "Icons (*.png *.jpg *.jpeg)");
|
||||
//: The title of the select icons open file dialog
|
||||
QString selectIcons = tr("Select Icons");
|
||||
//: The type of icon files
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(this, selectIcons, QString(), tr("Icons") + "(*.png *.jpg *.jpeg)");
|
||||
MMC->icons()->installIcons(fileNames);
|
||||
}
|
||||
|
||||
@ -116,7 +121,7 @@ void IconPickerDialog::selectionChanged ( QItemSelection selected, QItemSelectio
|
||||
|
||||
int IconPickerDialog::exec ( QString selection )
|
||||
{
|
||||
IconList * list = MMC->icons();
|
||||
auto list = MMC->icons();
|
||||
auto contentsWidget = ui->iconView;
|
||||
selectedIconKey = selection;
|
||||
|
||||
|
@ -13,59 +13,74 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "MultiMC.h"
|
||||
#include "LegacyModEditDialog.h"
|
||||
#include "ModEditDialogCommon.h"
|
||||
#include "versionselectdialog.h"
|
||||
#include "ProgressDialog.h"
|
||||
#include "ui_LegacyModEditDialog.h"
|
||||
#include <logic/ModList.h>
|
||||
#include "logic/ModList.h"
|
||||
#include "logic/lists/ForgeVersionList.h"
|
||||
#include "gui/platform.h"
|
||||
|
||||
#include <pathutils.h>
|
||||
#include <QFileDialog>
|
||||
//#include <QMessageBox>
|
||||
#include <QDebug>
|
||||
#include <QEvent>
|
||||
#include <QKeyEvent>
|
||||
|
||||
LegacyModEditDialog::LegacyModEditDialog( LegacyInstance* inst, QWidget* parent ) :
|
||||
m_inst(inst),
|
||||
QDialog(parent),
|
||||
ui(new Ui::LegacyModEditDialog)
|
||||
LegacyModEditDialog::LegacyModEditDialog(LegacyInstance *inst, QWidget *parent)
|
||||
: m_inst(inst), QDialog(parent), ui(new Ui::LegacyModEditDialog)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
ui->setupUi(this);
|
||||
|
||||
// Jar mods
|
||||
{
|
||||
ensureFolderPathExists(m_inst->jarModsDir());
|
||||
m_jarmods = m_inst->jarModList();
|
||||
ui->jarModsTreeView->setModel(m_jarmods.data());
|
||||
ui->jarModsTreeView->setModel(m_jarmods.get());
|
||||
#ifndef Q_OS_LINUX
|
||||
// FIXME: internal DnD causes segfaults later
|
||||
ui->jarModsTreeView->setDragDropMode(QAbstractItemView::DragDrop);
|
||||
// FIXME: DnD is glitched with contiguous (we move only first item in selection)
|
||||
ui->jarModsTreeView->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
#endif
|
||||
ui->jarModsTreeView->installEventFilter( this );
|
||||
ui->jarModsTreeView->installEventFilter(this);
|
||||
m_jarmods->startWatching();
|
||||
auto smodel = ui->jarModsTreeView->selectionModel();
|
||||
connect(smodel, SIGNAL(currentChanged(QModelIndex, QModelIndex)),
|
||||
SLOT(jarCurrent(QModelIndex, QModelIndex)));
|
||||
}
|
||||
// Core mods
|
||||
{
|
||||
ensureFolderPathExists(m_inst->coreModsDir());
|
||||
m_coremods = m_inst->coreModList();
|
||||
ui->coreModsTreeView->setModel(m_coremods.data());
|
||||
ui->coreModsTreeView->installEventFilter( this );
|
||||
ui->coreModsTreeView->setModel(m_coremods.get());
|
||||
ui->coreModsTreeView->installEventFilter(this);
|
||||
m_coremods->startWatching();
|
||||
auto smodel = ui->coreModsTreeView->selectionModel();
|
||||
connect(smodel, SIGNAL(currentChanged(QModelIndex, QModelIndex)),
|
||||
SLOT(coreCurrent(QModelIndex, QModelIndex)));
|
||||
}
|
||||
// Loader mods
|
||||
{
|
||||
ensureFolderPathExists(m_inst->loaderModsDir());
|
||||
m_mods = m_inst->loaderModList();
|
||||
ui->loaderModTreeView->setModel(m_mods.data());
|
||||
ui->loaderModTreeView->installEventFilter( this );
|
||||
ui->loaderModTreeView->setModel(m_mods.get());
|
||||
ui->loaderModTreeView->installEventFilter(this);
|
||||
m_mods->startWatching();
|
||||
auto smodel = ui->loaderModTreeView->selectionModel();
|
||||
connect(smodel, SIGNAL(currentChanged(QModelIndex, QModelIndex)),
|
||||
SLOT(loaderCurrent(QModelIndex, QModelIndex)));
|
||||
}
|
||||
// texture packs
|
||||
{
|
||||
ensureFolderPathExists(m_inst->texturePacksDir());
|
||||
m_texturepacks = m_inst->texturePackList();
|
||||
ui->texPackTreeView->setModel(m_texturepacks.data());
|
||||
ui->texPackTreeView->installEventFilter( this );
|
||||
ui->texPackTreeView->setModel(m_texturepacks.get());
|
||||
ui->texPackTreeView->installEventFilter(this);
|
||||
m_texturepacks->startWatching();
|
||||
}
|
||||
}
|
||||
@ -79,9 +94,9 @@ LegacyModEditDialog::~LegacyModEditDialog()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool LegacyModEditDialog::coreListFilter ( QKeyEvent* keyEvent )
|
||||
bool LegacyModEditDialog::coreListFilter(QKeyEvent *keyEvent)
|
||||
{
|
||||
switch(keyEvent->key())
|
||||
switch (keyEvent->key())
|
||||
{
|
||||
case Qt::Key_Delete:
|
||||
on_rmCoreBtn_clicked();
|
||||
@ -92,16 +107,16 @@ bool LegacyModEditDialog::coreListFilter ( QKeyEvent* keyEvent )
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QDialog::eventFilter( ui->coreModsTreeView, keyEvent );
|
||||
return QDialog::eventFilter(ui->coreModsTreeView, keyEvent);
|
||||
}
|
||||
|
||||
bool LegacyModEditDialog::jarListFilter ( QKeyEvent* keyEvent )
|
||||
bool LegacyModEditDialog::jarListFilter(QKeyEvent *keyEvent)
|
||||
{
|
||||
switch(keyEvent->key())
|
||||
switch (keyEvent->key())
|
||||
{
|
||||
case Qt::Key_Up:
|
||||
{
|
||||
if(keyEvent->modifiers() & Qt::ControlModifier)
|
||||
if (keyEvent->modifiers() & Qt::ControlModifier)
|
||||
{
|
||||
on_moveJarUpBtn_clicked();
|
||||
return true;
|
||||
@ -110,7 +125,7 @@ bool LegacyModEditDialog::jarListFilter ( QKeyEvent* keyEvent )
|
||||
}
|
||||
case Qt::Key_Down:
|
||||
{
|
||||
if(keyEvent->modifiers() & Qt::ControlModifier)
|
||||
if (keyEvent->modifiers() & Qt::ControlModifier)
|
||||
{
|
||||
on_moveJarDownBtn_clicked();
|
||||
return true;
|
||||
@ -126,12 +141,12 @@ bool LegacyModEditDialog::jarListFilter ( QKeyEvent* keyEvent )
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QDialog::eventFilter( ui->jarModsTreeView, keyEvent );
|
||||
return QDialog::eventFilter(ui->jarModsTreeView, keyEvent);
|
||||
}
|
||||
|
||||
bool LegacyModEditDialog::loaderListFilter ( QKeyEvent* keyEvent )
|
||||
bool LegacyModEditDialog::loaderListFilter(QKeyEvent *keyEvent)
|
||||
{
|
||||
switch(keyEvent->key())
|
||||
switch (keyEvent->key())
|
||||
{
|
||||
case Qt::Key_Delete:
|
||||
on_rmModBtn_clicked();
|
||||
@ -142,12 +157,12 @@ bool LegacyModEditDialog::loaderListFilter ( QKeyEvent* keyEvent )
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QDialog::eventFilter( ui->loaderModTreeView, keyEvent );
|
||||
return QDialog::eventFilter(ui->loaderModTreeView, keyEvent);
|
||||
}
|
||||
|
||||
bool LegacyModEditDialog::texturePackListFilter ( QKeyEvent* keyEvent )
|
||||
bool LegacyModEditDialog::texturePackListFilter(QKeyEvent *keyEvent)
|
||||
{
|
||||
switch(keyEvent->key())
|
||||
switch (keyEvent->key())
|
||||
{
|
||||
case Qt::Key_Delete:
|
||||
on_rmTexPackBtn_clicked();
|
||||
@ -158,33 +173,32 @@ bool LegacyModEditDialog::texturePackListFilter ( QKeyEvent* keyEvent )
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QDialog::eventFilter( ui->texPackTreeView, keyEvent );
|
||||
return QDialog::eventFilter(ui->texPackTreeView, keyEvent);
|
||||
}
|
||||
|
||||
|
||||
bool LegacyModEditDialog::eventFilter ( QObject* obj, QEvent* ev )
|
||||
bool LegacyModEditDialog::eventFilter(QObject *obj, QEvent *ev)
|
||||
{
|
||||
if (ev->type() != QEvent::KeyPress)
|
||||
{
|
||||
return QDialog::eventFilter( obj, ev );
|
||||
return QDialog::eventFilter(obj, ev);
|
||||
}
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(ev);
|
||||
if(obj == ui->jarModsTreeView)
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev);
|
||||
if (obj == ui->jarModsTreeView)
|
||||
return jarListFilter(keyEvent);
|
||||
if(obj == ui->coreModsTreeView)
|
||||
if (obj == ui->coreModsTreeView)
|
||||
return coreListFilter(keyEvent);
|
||||
if(obj == ui->loaderModTreeView)
|
||||
if (obj == ui->loaderModTreeView)
|
||||
return loaderListFilter(keyEvent);
|
||||
if(obj == ui->texPackTreeView)
|
||||
if (obj == ui->texPackTreeView)
|
||||
return texturePackListFilter(keyEvent);
|
||||
return QDialog::eventFilter( obj, ev );
|
||||
return QDialog::eventFilter(obj, ev);
|
||||
}
|
||||
|
||||
|
||||
void LegacyModEditDialog::on_addCoreBtn_clicked()
|
||||
{
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(this, "Select Core Mods");
|
||||
for(auto filename:fileNames)
|
||||
//: Title of core mod selection dialog
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Select Core Mods"));
|
||||
for (auto filename : fileNames)
|
||||
{
|
||||
m_coremods->stopWatching();
|
||||
m_coremods->installMod(QFileInfo(filename));
|
||||
@ -193,12 +207,45 @@ void LegacyModEditDialog::on_addCoreBtn_clicked()
|
||||
}
|
||||
void LegacyModEditDialog::on_addForgeBtn_clicked()
|
||||
{
|
||||
|
||||
VersionSelectDialog vselect(MMC->forgelist().get(), tr("Select Forge version"), this);
|
||||
vselect.setFilter(1, m_inst->intendedVersionId());
|
||||
if (vselect.exec() && vselect.selectedVersion())
|
||||
{
|
||||
ForgeVersionPtr forge =
|
||||
std::dynamic_pointer_cast<ForgeVersion>(vselect.selectedVersion());
|
||||
if (!forge)
|
||||
return;
|
||||
auto entry = MMC->metacache()->resolveEntry("minecraftforge", forge->filename);
|
||||
if (entry->stale)
|
||||
{
|
||||
DownloadJob *fjob = new DownloadJob("Forge download");
|
||||
fjob->addCacheDownload(forge->universal_url, entry);
|
||||
ProgressDialog dlg(this);
|
||||
dlg.exec(fjob);
|
||||
if (dlg.result() == QDialog::Accepted)
|
||||
{
|
||||
m_jarmods->stopWatching();
|
||||
m_jarmods->installMod(QFileInfo(entry->getFullPath()));
|
||||
m_jarmods->startWatching();
|
||||
}
|
||||
else
|
||||
{
|
||||
// failed to download forge :/
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_jarmods->stopWatching();
|
||||
m_jarmods->installMod(QFileInfo(entry->getFullPath()));
|
||||
m_jarmods->startWatching();
|
||||
}
|
||||
}
|
||||
}
|
||||
void LegacyModEditDialog::on_addJarBtn_clicked()
|
||||
{
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(this, "Select Jar Mods");
|
||||
for(auto filename:fileNames)
|
||||
//: Title of jar mod selection dialog
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Select Jar Mods"));
|
||||
for (auto filename : fileNames)
|
||||
{
|
||||
m_jarmods->stopWatching();
|
||||
m_jarmods->installMod(QFileInfo(filename));
|
||||
@ -207,8 +254,9 @@ void LegacyModEditDialog::on_addJarBtn_clicked()
|
||||
}
|
||||
void LegacyModEditDialog::on_addModBtn_clicked()
|
||||
{
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(this, "Select Loader Mods");
|
||||
for(auto filename:fileNames)
|
||||
//: Title of regular mod selection dialog
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Select Loader Mods"));
|
||||
for (auto filename : fileNames)
|
||||
{
|
||||
m_mods->stopWatching();
|
||||
m_mods->installMod(QFileInfo(filename));
|
||||
@ -217,8 +265,9 @@ void LegacyModEditDialog::on_addModBtn_clicked()
|
||||
}
|
||||
void LegacyModEditDialog::on_addTexPackBtn_clicked()
|
||||
{
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(this, "Select Texture Packs");
|
||||
for(auto filename:fileNames)
|
||||
//: Title of texture pack selection dialog
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Select Texture Packs"));
|
||||
for (auto filename : fileNames)
|
||||
{
|
||||
m_texturepacks->stopWatching();
|
||||
m_texturepacks->installMod(QFileInfo(filename));
|
||||
@ -231,7 +280,7 @@ void LegacyModEditDialog::on_moveJarDownBtn_clicked()
|
||||
int first, last;
|
||||
auto list = ui->jarModsTreeView->selectionModel()->selectedRows();
|
||||
|
||||
if(!lastfirst(list, first, last))
|
||||
if (!lastfirst(list, first, last))
|
||||
return;
|
||||
|
||||
m_jarmods->moveModsDown(first, last);
|
||||
@ -241,7 +290,7 @@ void LegacyModEditDialog::on_moveJarUpBtn_clicked()
|
||||
int first, last;
|
||||
auto list = ui->jarModsTreeView->selectionModel()->selectedRows();
|
||||
|
||||
if(!lastfirst(list, first, last))
|
||||
if (!lastfirst(list, first, last))
|
||||
return;
|
||||
m_jarmods->moveModsUp(first, last);
|
||||
}
|
||||
@ -250,7 +299,7 @@ void LegacyModEditDialog::on_rmCoreBtn_clicked()
|
||||
int first, last;
|
||||
auto list = ui->coreModsTreeView->selectionModel()->selectedRows();
|
||||
|
||||
if(!lastfirst(list, first, last))
|
||||
if (!lastfirst(list, first, last))
|
||||
return;
|
||||
m_coremods->stopWatching();
|
||||
m_coremods->deleteMods(first, last);
|
||||
@ -261,7 +310,7 @@ void LegacyModEditDialog::on_rmJarBtn_clicked()
|
||||
int first, last;
|
||||
auto list = ui->jarModsTreeView->selectionModel()->selectedRows();
|
||||
|
||||
if(!lastfirst(list, first, last))
|
||||
if (!lastfirst(list, first, last))
|
||||
return;
|
||||
m_jarmods->stopWatching();
|
||||
m_jarmods->deleteMods(first, last);
|
||||
@ -272,7 +321,7 @@ void LegacyModEditDialog::on_rmModBtn_clicked()
|
||||
int first, last;
|
||||
auto list = ui->loaderModTreeView->selectionModel()->selectedRows();
|
||||
|
||||
if(!lastfirst(list, first, last))
|
||||
if (!lastfirst(list, first, last))
|
||||
return;
|
||||
m_mods->stopWatching();
|
||||
m_mods->deleteMods(first, last);
|
||||
@ -283,7 +332,7 @@ void LegacyModEditDialog::on_rmTexPackBtn_clicked()
|
||||
int first, last;
|
||||
auto list = ui->texPackTreeView->selectionModel()->selectedRows();
|
||||
|
||||
if(!lastfirst(list, first, last))
|
||||
if (!lastfirst(list, first, last))
|
||||
return;
|
||||
m_texturepacks->stopWatching();
|
||||
m_texturepacks->deleteMods(first, last);
|
||||
@ -302,8 +351,43 @@ void LegacyModEditDialog::on_viewTexPackBtn_clicked()
|
||||
openDirInDefaultProgram(m_inst->texturePacksDir(), true);
|
||||
}
|
||||
|
||||
|
||||
void LegacyModEditDialog::on_buttonBox_rejected()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
void LegacyModEditDialog::jarCurrent(QModelIndex current, QModelIndex previous)
|
||||
{
|
||||
if(!current.isValid())
|
||||
{
|
||||
ui->jarMIFrame->clear();
|
||||
return;
|
||||
}
|
||||
int row = current.row();
|
||||
Mod &m = m_jarmods->operator[](row);
|
||||
ui->jarMIFrame->updateWithMod(m);
|
||||
}
|
||||
|
||||
void LegacyModEditDialog::coreCurrent(QModelIndex current, QModelIndex previous)
|
||||
{
|
||||
if(!current.isValid())
|
||||
{
|
||||
ui->coreMIFrame->clear();
|
||||
return;
|
||||
}
|
||||
int row = current.row();
|
||||
Mod &m = m_coremods->operator[](row);
|
||||
ui->coreMIFrame->updateWithMod(m);
|
||||
}
|
||||
|
||||
void LegacyModEditDialog::loaderCurrent(QModelIndex current, QModelIndex previous)
|
||||
{
|
||||
if(!current.isValid())
|
||||
{
|
||||
ui->loaderMIFrame->clear();
|
||||
return;
|
||||
}
|
||||
int row = current.row();
|
||||
Mod &m = m_mods->operator[](row);
|
||||
ui->loaderMIFrame->updateWithMod(m);
|
||||
}
|
||||
|
@ -17,8 +17,10 @@
|
||||
|
||||
#include <QDialog>
|
||||
#include "logic/LegacyInstance.h"
|
||||
#include <logic/net/DownloadJob.h>
|
||||
|
||||
namespace Ui {
|
||||
namespace Ui
|
||||
{
|
||||
class LegacyModEditDialog;
|
||||
}
|
||||
|
||||
@ -27,10 +29,11 @@ class LegacyModEditDialog : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LegacyModEditDialog(LegacyInstance* inst, QWidget *parent = 0);
|
||||
explicit LegacyModEditDialog(LegacyInstance *inst, QWidget *parent = 0);
|
||||
~LegacyModEditDialog();
|
||||
|
||||
private slots:
|
||||
private
|
||||
slots:
|
||||
|
||||
void on_addJarBtn_clicked();
|
||||
void on_rmJarBtn_clicked();
|
||||
@ -49,19 +52,27 @@ private slots:
|
||||
void on_addTexPackBtn_clicked();
|
||||
void on_rmTexPackBtn_clicked();
|
||||
void on_viewTexPackBtn_clicked();
|
||||
|
||||
// Questionable: SettingsDialog doesn't need this for some reason?
|
||||
void on_buttonBox_rejected();
|
||||
|
||||
void jarCurrent(QModelIndex current, QModelIndex previous);
|
||||
void coreCurrent(QModelIndex current, QModelIndex previous);
|
||||
void loaderCurrent(QModelIndex current, QModelIndex previous);
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *ev);
|
||||
bool jarListFilter( QKeyEvent* ev );
|
||||
bool coreListFilter( QKeyEvent* ev );
|
||||
bool loaderListFilter( QKeyEvent* ev );
|
||||
bool texturePackListFilter( QKeyEvent* ev );
|
||||
bool jarListFilter(QKeyEvent *ev);
|
||||
bool coreListFilter(QKeyEvent *ev);
|
||||
bool loaderListFilter(QKeyEvent *ev);
|
||||
bool texturePackListFilter(QKeyEvent *ev);
|
||||
|
||||
private:
|
||||
Ui::LegacyModEditDialog *ui;
|
||||
QSharedPointer<ModList> m_mods;
|
||||
QSharedPointer<ModList> m_coremods;
|
||||
QSharedPointer<ModList> m_jarmods;
|
||||
QSharedPointer<ModList> m_texturepacks;
|
||||
LegacyInstance * m_inst;
|
||||
std::shared_ptr<ModList> m_mods;
|
||||
std::shared_ptr<ModList> m_coremods;
|
||||
std::shared_ptr<ModList> m_jarmods;
|
||||
std::shared_ptr<ModList> m_texturepacks;
|
||||
LegacyInstance *m_inst;
|
||||
DownloadJobPtr forgeJob;
|
||||
};
|
||||
|
@ -23,6 +23,8 @@
|
||||
<attribute name="title">
|
||||
<string>Jar Mods</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="ModListView" name="jarModsTreeView">
|
||||
@ -52,9 +54,6 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="addForgeBtn">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>MCForge</string>
|
||||
</property>
|
||||
@ -90,11 +89,22 @@
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="MCModInfoFrame" name="jarMIFrame">
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="coreTab">
|
||||
<attribute name="title">
|
||||
<string>Core Mods</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="ModListView" name="coreModsTreeView">
|
||||
@ -142,11 +152,25 @@
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="MCModInfoFrame" name="coreMIFrame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="modTab">
|
||||
<attribute name="title">
|
||||
<string>Loader Mods</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="ModListView" name="loaderModTreeView">
|
||||
@ -197,6 +221,18 @@
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="MCModInfoFrame" name="loaderMIFrame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="texPackTab">
|
||||
<property name="acceptDrops">
|
||||
@ -273,6 +309,12 @@
|
||||
<extends>QTreeView</extends>
|
||||
<header>gui/ModListView.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>MCModInfoFrame</class>
|
||||
<extends>QFrame</extends>
|
||||
<header>gui/MCModInfoFrame.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
110
gui/MCModInfoFrame.cpp
Normal file
110
gui/MCModInfoFrame.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "MCModInfoFrame.h"
|
||||
#include "ui_MCModInfoFrame.h"
|
||||
#include <QMessageBox>
|
||||
#include <QtGui>
|
||||
void MCModInfoFrame::updateWithMod(Mod &m)
|
||||
{
|
||||
if(m.type() == m.MOD_FOLDER)
|
||||
{
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
|
||||
QString text = "";
|
||||
QString name = "";
|
||||
if(m.name().isEmpty()) name = m.id();
|
||||
else name = m.name();
|
||||
|
||||
if(m.homeurl().isEmpty()) text = name;
|
||||
else text = "<a href=\"" + m.homeurl() + "\">" + name + "</a>";
|
||||
if(!m.authors().isEmpty()) text += " by " + m.authors();
|
||||
|
||||
setModText(text);
|
||||
|
||||
if(m.description().isEmpty())
|
||||
{
|
||||
setModDescription(tr("No description provided in mcmod.info"));
|
||||
}
|
||||
else
|
||||
{
|
||||
setModDescription(m.description());
|
||||
}
|
||||
}
|
||||
|
||||
void MCModInfoFrame::clear()
|
||||
{
|
||||
setModText(tr("Select a mod to view title and authors..."));
|
||||
setModDescription(tr("Select a mod to view description..."));
|
||||
}
|
||||
|
||||
MCModInfoFrame::MCModInfoFrame(QWidget *parent) :
|
||||
QFrame(parent),
|
||||
ui(new Ui::MCModInfoFrame)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
MCModInfoFrame::~MCModInfoFrame()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void MCModInfoFrame::setModText(QString text)
|
||||
{
|
||||
ui->label_ModText->setText(text);
|
||||
}
|
||||
|
||||
void MCModInfoFrame::setModDescription(QString text)
|
||||
{
|
||||
ui->label_ModDescription->setToolTip("");
|
||||
QString intermediatetext = text.trimmed();
|
||||
bool prev(false);
|
||||
QChar rem('\n');
|
||||
QString finaltext;
|
||||
finaltext.reserve(intermediatetext.size());
|
||||
foreach(const QChar& c, intermediatetext)
|
||||
{
|
||||
if(c == rem && prev){
|
||||
continue;
|
||||
}
|
||||
prev = c == rem;
|
||||
finaltext += c;
|
||||
}
|
||||
QString labeltext;
|
||||
labeltext.reserve(300);
|
||||
if(finaltext.length() > 290)
|
||||
{
|
||||
ui->label_ModDescription->setOpenExternalLinks(false);
|
||||
ui->label_ModDescription->setTextFormat(Qt::TextFormat::RichText);
|
||||
desc = text;
|
||||
labeltext.append("<html><body>" + finaltext.left(287) + "<a href=\"#mod_desc\">...</a></body></html>");
|
||||
QObject::connect(ui->label_ModDescription, &QLabel::linkActivated, this, &MCModInfoFrame::modDescEllipsisHandler);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->label_ModDescription->setTextFormat(Qt::TextFormat::PlainText);
|
||||
labeltext.append(finaltext);
|
||||
}
|
||||
ui->label_ModDescription->setText(labeltext);
|
||||
}
|
||||
void MCModInfoFrame::modDescEllipsisHandler(const QString &link)
|
||||
{
|
||||
QMessageBox msgbox;
|
||||
msgbox.setText(desc);
|
||||
msgbox.exec();
|
||||
}
|
46
gui/MCModInfoFrame.h
Normal file
46
gui/MCModInfoFrame.h
Normal file
@ -0,0 +1,46 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QFrame>
|
||||
#include "logic/Mod.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class MCModInfoFrame;
|
||||
}
|
||||
|
||||
class MCModInfoFrame : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MCModInfoFrame(QWidget *parent = 0);
|
||||
~MCModInfoFrame();
|
||||
|
||||
void setModText(QString text);
|
||||
void setModDescription(QString text);
|
||||
|
||||
void updateWithMod(Mod &m);
|
||||
void clear();
|
||||
|
||||
public slots:
|
||||
void modDescEllipsisHandler(const QString& link );
|
||||
|
||||
private:
|
||||
Ui::MCModInfoFrame *ui;
|
||||
QString desc;
|
||||
};
|
68
gui/MCModInfoFrame.ui
Normal file
68
gui/MCModInfoFrame.ui
Normal file
@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MCModInfoFrame</class>
|
||||
<widget class="QFrame" name="MCModInfoFrame">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>527</width>
|
||||
<height>113</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>120</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Frame</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_ModText">
|
||||
<property name="text">
|
||||
<string>Select a mod to view title and authors...</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_ModDescription">
|
||||
<property name="text">
|
||||
<string>Select a mod to view description...</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -1,17 +1,40 @@
|
||||
#include "ModEditDialogCommon.h"
|
||||
|
||||
bool lastfirst (QModelIndexList & list, int & first, int & last)
|
||||
#include <QDesktopServices>
|
||||
#include <QMessageBox>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
bool lastfirst(QModelIndexList &list, int &first, int &last)
|
||||
{
|
||||
if(!list.size())
|
||||
if (!list.size())
|
||||
return false;
|
||||
first = last = list[0].row();
|
||||
for(auto item: list)
|
||||
for (auto item : list)
|
||||
{
|
||||
int row = item.row();
|
||||
if(row < first)
|
||||
if (row < first)
|
||||
first = row;
|
||||
if(row > last)
|
||||
if (row > last)
|
||||
last = row;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void showWebsiteForMod(QWidget *parentDlg, Mod &m)
|
||||
{
|
||||
QString url = m.homeurl();
|
||||
if (url.size())
|
||||
{
|
||||
// catch the cases where the protocol is missing
|
||||
if(!url.startsWith("http"))
|
||||
{
|
||||
url = "http://" + url;
|
||||
}
|
||||
QDesktopServices::openUrl(url);
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::warning(
|
||||
parentDlg, parentDlg->tr("How sad!"),
|
||||
parentDlg->tr("The mod author didn't provide a website link for this mod."));
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,7 @@
|
||||
#pragma once
|
||||
#include <QAbstractItemModel>
|
||||
#include <logic/Mod.h>
|
||||
|
||||
bool lastfirst (QModelIndexList & list, int & first, int & last);
|
||||
|
||||
void showWebsiteForMod(QWidget * parentDlg, Mod& m);
|
@ -30,6 +30,7 @@ void ModListView::setModel ( QAbstractItemModel* model )
|
||||
auto head = header();
|
||||
head->setStretchLastSection(false);
|
||||
head->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
head->setSectionResizeMode(1, QHeaderView::ResizeToContents);
|
||||
for(int i = 1; i < head->count(); i++)
|
||||
head->setSectionResizeMode(i, QHeaderView::ResizeToContents);
|
||||
dropIndicatorPosition();
|
||||
}
|
||||
|
@ -9,4 +9,5 @@ class ModListView: public QTreeView
|
||||
public:
|
||||
explicit ModListView ( QWidget* parent = 0 );
|
||||
virtual void setModel ( QAbstractItemModel* model );
|
||||
|
||||
};
|
@ -12,41 +12,66 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "MultiMC.h"
|
||||
#include "OneSixModEditDialog.h"
|
||||
#include "ModEditDialogCommon.h"
|
||||
#include "ui_OneSixModEditDialog.h"
|
||||
#include <logic/ModList.h>
|
||||
#include "logic/ModList.h"
|
||||
#include "logic/OneSixVersion.h"
|
||||
#include "logic/EnabledItemFilter.h"
|
||||
#include "logic/lists/ForgeVersionList.h"
|
||||
#include "logic/ForgeInstaller.h"
|
||||
#include "gui/versionselectdialog.h"
|
||||
#include "gui/platform.h"
|
||||
#include "ProgressDialog.h"
|
||||
|
||||
#include <pathutils.h>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QDebug>
|
||||
#include <QEvent>
|
||||
#include <QKeyEvent>
|
||||
#include <QDesktopServices>
|
||||
|
||||
OneSixModEditDialog::OneSixModEditDialog(OneSixInstance * inst, QWidget *parent):
|
||||
m_inst(inst),
|
||||
QDialog(parent),
|
||||
ui(new Ui::OneSixModEditDialog)
|
||||
OneSixModEditDialog::OneSixModEditDialog(OneSixInstance *inst, QWidget *parent)
|
||||
: m_inst(inst), QDialog(parent), ui(new Ui::OneSixModEditDialog)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
ui->setupUi(this);
|
||||
//TODO: libraries!
|
||||
// libraries!
|
||||
|
||||
m_version = m_inst->getFullVersion();
|
||||
if (m_version)
|
||||
{
|
||||
// yeah... here be the real dragons.
|
||||
main_model = new EnabledItemFilter(this);
|
||||
main_model->setActive(true);
|
||||
main_model->setSourceModel(m_version.get());
|
||||
ui->libraryTreeView->setModel(main_model);
|
||||
ui->libraryTreeView->installEventFilter(this);
|
||||
ui->mainClassEdit->setText(m_version->mainClass);
|
||||
updateVersionControls();
|
||||
}
|
||||
else
|
||||
{
|
||||
disableVersionControls();
|
||||
}
|
||||
// Loader mods
|
||||
{
|
||||
ensureFolderPathExists(m_inst->loaderModsDir());
|
||||
m_mods = m_inst->loaderModList();
|
||||
ui->loaderModTreeView->setModel(m_mods.data());
|
||||
ui->loaderModTreeView->installEventFilter( this );
|
||||
ui->loaderModTreeView->setModel(m_mods.get());
|
||||
ui->loaderModTreeView->installEventFilter(this);
|
||||
m_mods->startWatching();
|
||||
auto smodel = ui->loaderModTreeView->selectionModel();
|
||||
connect(smodel, SIGNAL(currentChanged(QModelIndex, QModelIndex)),
|
||||
SLOT(loaderCurrent(QModelIndex,QModelIndex)));
|
||||
}
|
||||
// resource packs
|
||||
{
|
||||
ensureFolderPathExists(m_inst->resourcePacksDir());
|
||||
m_resourcepacks = m_inst->resourcePackList();
|
||||
ui->resPackTreeView->setModel(m_resourcepacks.data());
|
||||
ui->resPackTreeView->installEventFilter( this );
|
||||
ui->resPackTreeView->setModel(m_resourcepacks.get());
|
||||
ui->resPackTreeView->installEventFilter(this);
|
||||
m_resourcepacks->startWatching();
|
||||
}
|
||||
}
|
||||
@ -58,9 +83,124 @@ OneSixModEditDialog::~OneSixModEditDialog()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool OneSixModEditDialog::loaderListFilter ( QKeyEvent* keyEvent )
|
||||
void OneSixModEditDialog::updateVersionControls()
|
||||
{
|
||||
switch(keyEvent->key())
|
||||
bool customVersion = m_inst->versionIsCustom();
|
||||
ui->customizeBtn->setEnabled(!customVersion);
|
||||
ui->revertBtn->setEnabled(customVersion);
|
||||
ui->forgeBtn->setEnabled(true);
|
||||
}
|
||||
|
||||
void OneSixModEditDialog::disableVersionControls()
|
||||
{
|
||||
ui->customizeBtn->setEnabled(false);
|
||||
ui->revertBtn->setEnabled(false);
|
||||
ui->forgeBtn->setEnabled(false);
|
||||
}
|
||||
|
||||
void OneSixModEditDialog::on_customizeBtn_clicked()
|
||||
{
|
||||
if (m_inst->customizeVersion())
|
||||
{
|
||||
m_version = m_inst->getFullVersion();
|
||||
main_model->setSourceModel(m_version.get());
|
||||
updateVersionControls();
|
||||
}
|
||||
}
|
||||
|
||||
void OneSixModEditDialog::on_revertBtn_clicked()
|
||||
{
|
||||
auto reply = QMessageBox::question(
|
||||
this, tr("Revert?"), tr("Do you want to revert the "
|
||||
"version of this instance to its original configuration?"),
|
||||
QMessageBox::Yes | QMessageBox::No);
|
||||
if (reply == QMessageBox::Yes)
|
||||
{
|
||||
if (m_inst->revertCustomVersion())
|
||||
{
|
||||
m_version = m_inst->getFullVersion();
|
||||
main_model->setSourceModel(m_version.get());
|
||||
updateVersionControls();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OneSixModEditDialog::on_forgeBtn_clicked()
|
||||
{
|
||||
VersionSelectDialog vselect(MMC->forgelist().get(), tr("Select Forge version"), this);
|
||||
vselect.setFilter(1, m_inst->currentVersionId());
|
||||
if (vselect.exec() && vselect.selectedVersion())
|
||||
{
|
||||
if (m_inst->versionIsCustom())
|
||||
{
|
||||
auto reply = QMessageBox::question(
|
||||
this, tr("Revert?"),
|
||||
tr("This will revert any "
|
||||
"changes you did to the version up to this point. Is that "
|
||||
"OK?"),
|
||||
QMessageBox::Yes | QMessageBox::No);
|
||||
if (reply == QMessageBox::Yes)
|
||||
{
|
||||
m_inst->revertCustomVersion();
|
||||
m_inst->customizeVersion();
|
||||
{
|
||||
m_version = m_inst->getFullVersion();
|
||||
main_model->setSourceModel(m_version.get());
|
||||
updateVersionControls();
|
||||
}
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_inst->customizeVersion();
|
||||
m_version = m_inst->getFullVersion();
|
||||
main_model->setSourceModel(m_version.get());
|
||||
updateVersionControls();
|
||||
}
|
||||
ForgeVersionPtr forgeVersion =
|
||||
std::dynamic_pointer_cast<ForgeVersion>(vselect.selectedVersion());
|
||||
if (!forgeVersion)
|
||||
return;
|
||||
auto entry = MMC->metacache()->resolveEntry("minecraftforge", forgeVersion->filename);
|
||||
if (entry->stale)
|
||||
{
|
||||
DownloadJob *fjob = new DownloadJob("Forge download");
|
||||
fjob->addCacheDownload(forgeVersion->installer_url, entry);
|
||||
ProgressDialog dlg(this);
|
||||
dlg.exec(fjob);
|
||||
if (dlg.result() == QDialog::Accepted)
|
||||
{
|
||||
// install
|
||||
QString forgePath = entry->getFullPath();
|
||||
ForgeInstaller forge(forgePath, forgeVersion->universal_url);
|
||||
if (!forge.apply(m_version))
|
||||
{
|
||||
// failure notice
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// failed to download forge :/
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// install
|
||||
QString forgePath = entry->getFullPath();
|
||||
ForgeInstaller forge(forgePath, forgeVersion->universal_url);
|
||||
if (!forge.apply(m_version))
|
||||
{
|
||||
// failure notice
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool OneSixModEditDialog::loaderListFilter(QKeyEvent *keyEvent)
|
||||
{
|
||||
switch (keyEvent->key())
|
||||
{
|
||||
case Qt::Key_Delete:
|
||||
on_rmModBtn_clicked();
|
||||
@ -71,12 +211,12 @@ bool OneSixModEditDialog::loaderListFilter ( QKeyEvent* keyEvent )
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QDialog::eventFilter( ui->loaderModTreeView, keyEvent );
|
||||
return QDialog::eventFilter(ui->loaderModTreeView, keyEvent);
|
||||
}
|
||||
|
||||
bool OneSixModEditDialog::resourcePackListFilter ( QKeyEvent* keyEvent )
|
||||
bool OneSixModEditDialog::resourcePackListFilter(QKeyEvent *keyEvent)
|
||||
{
|
||||
switch(keyEvent->key())
|
||||
switch (keyEvent->key())
|
||||
{
|
||||
case Qt::Key_Delete:
|
||||
on_rmResPackBtn_clicked();
|
||||
@ -87,22 +227,21 @@ bool OneSixModEditDialog::resourcePackListFilter ( QKeyEvent* keyEvent )
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QDialog::eventFilter( ui->resPackTreeView, keyEvent );
|
||||
return QDialog::eventFilter(ui->resPackTreeView, keyEvent);
|
||||
}
|
||||
|
||||
|
||||
bool OneSixModEditDialog::eventFilter ( QObject* obj, QEvent* ev )
|
||||
bool OneSixModEditDialog::eventFilter(QObject *obj, QEvent *ev)
|
||||
{
|
||||
if (ev->type() != QEvent::KeyPress)
|
||||
{
|
||||
return QDialog::eventFilter( obj, ev );
|
||||
return QDialog::eventFilter(obj, ev);
|
||||
}
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(ev);
|
||||
if(obj == ui->loaderModTreeView)
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev);
|
||||
if (obj == ui->loaderModTreeView)
|
||||
return loaderListFilter(keyEvent);
|
||||
if(obj == ui->resPackTreeView)
|
||||
if (obj == ui->resPackTreeView)
|
||||
return resourcePackListFilter(keyEvent);
|
||||
return QDialog::eventFilter( obj, ev );
|
||||
return QDialog::eventFilter(obj, ev);
|
||||
}
|
||||
|
||||
void OneSixModEditDialog::on_buttonBox_rejected()
|
||||
@ -112,8 +251,9 @@ void OneSixModEditDialog::on_buttonBox_rejected()
|
||||
|
||||
void OneSixModEditDialog::on_addModBtn_clicked()
|
||||
{
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(this, "Select Loader Mods");
|
||||
for(auto filename:fileNames)
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(
|
||||
this, QApplication::translate("LegacyModEditDialog", "Select Loader Mods"));
|
||||
for (auto filename : fileNames)
|
||||
{
|
||||
m_mods->stopWatching();
|
||||
m_mods->installMod(QFileInfo(filename));
|
||||
@ -125,7 +265,7 @@ void OneSixModEditDialog::on_rmModBtn_clicked()
|
||||
int first, last;
|
||||
auto list = ui->loaderModTreeView->selectionModel()->selectedRows();
|
||||
|
||||
if(!lastfirst(list, first, last))
|
||||
if (!lastfirst(list, first, last))
|
||||
return;
|
||||
m_mods->stopWatching();
|
||||
m_mods->deleteMods(first, last);
|
||||
@ -136,11 +276,11 @@ void OneSixModEditDialog::on_viewModBtn_clicked()
|
||||
openDirInDefaultProgram(m_inst->loaderModsDir(), true);
|
||||
}
|
||||
|
||||
|
||||
void OneSixModEditDialog::on_addResPackBtn_clicked()
|
||||
{
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(this, "Select Resource Packs");
|
||||
for(auto filename:fileNames)
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(
|
||||
this, QApplication::translate("LegacyModEditDialog", "Select Resource Packs"));
|
||||
for (auto filename : fileNames)
|
||||
{
|
||||
m_resourcepacks->stopWatching();
|
||||
m_resourcepacks->installMod(QFileInfo(filename));
|
||||
@ -152,7 +292,7 @@ void OneSixModEditDialog::on_rmResPackBtn_clicked()
|
||||
int first, last;
|
||||
auto list = ui->resPackTreeView->selectionModel()->selectedRows();
|
||||
|
||||
if(!lastfirst(list, first, last))
|
||||
if (!lastfirst(list, first, last))
|
||||
return;
|
||||
m_resourcepacks->stopWatching();
|
||||
m_resourcepacks->deleteMods(first, last);
|
||||
@ -163,3 +303,14 @@ void OneSixModEditDialog::on_viewResPackBtn_clicked()
|
||||
openDirInDefaultProgram(m_inst->resourcePacksDir(), true);
|
||||
}
|
||||
|
||||
void OneSixModEditDialog::loaderCurrent(QModelIndex current, QModelIndex previous)
|
||||
{
|
||||
if(!current.isValid())
|
||||
{
|
||||
ui->frame->clear();
|
||||
return;
|
||||
}
|
||||
int row = current.row();
|
||||
Mod &m = m_mods->operator[](row);
|
||||
ui->frame->updateWithMod(m);
|
||||
}
|
||||
|
@ -18,8 +18,10 @@
|
||||
|
||||
#include <logic/OneSixInstance.h>
|
||||
|
||||
namespace Ui {
|
||||
class OneSixModEditDialog;
|
||||
class EnabledItemFilter;
|
||||
namespace Ui
|
||||
{
|
||||
class OneSixModEditDialog;
|
||||
}
|
||||
|
||||
class OneSixModEditDialog : public QDialog
|
||||
@ -27,10 +29,11 @@ class OneSixModEditDialog : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit OneSixModEditDialog(OneSixInstance* inst, QWidget *parent = 0);
|
||||
explicit OneSixModEditDialog(OneSixInstance *inst, QWidget *parent = 0);
|
||||
virtual ~OneSixModEditDialog();
|
||||
|
||||
private slots:
|
||||
private
|
||||
slots:
|
||||
void on_addModBtn_clicked();
|
||||
void on_rmModBtn_clicked();
|
||||
void on_viewModBtn_clicked();
|
||||
@ -40,13 +43,25 @@ private slots:
|
||||
void on_viewResPackBtn_clicked();
|
||||
// Questionable: SettingsDialog doesn't need this for some reason?
|
||||
void on_buttonBox_rejected();
|
||||
void on_forgeBtn_clicked();
|
||||
void on_customizeBtn_clicked();
|
||||
void on_revertBtn_clicked();
|
||||
void updateVersionControls();
|
||||
void disableVersionControls();
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *ev);
|
||||
bool loaderListFilter( QKeyEvent* ev );
|
||||
bool resourcePackListFilter( QKeyEvent* ev );
|
||||
bool loaderListFilter(QKeyEvent *ev);
|
||||
bool resourcePackListFilter(QKeyEvent *ev);
|
||||
|
||||
private:
|
||||
Ui::OneSixModEditDialog *ui;
|
||||
QSharedPointer<ModList> m_mods;
|
||||
QSharedPointer<ModList> m_resourcepacks;
|
||||
OneSixInstance * m_inst;
|
||||
std::shared_ptr<OneSixVersion> m_version;
|
||||
std::shared_ptr<ModList> m_mods;
|
||||
std::shared_ptr<ModList> m_resourcepacks;
|
||||
EnabledItemFilter *main_model;
|
||||
OneSixInstance *m_inst;
|
||||
public
|
||||
slots:
|
||||
void loaderCurrent(QModelIndex current, QModelIndex previous);
|
||||
};
|
||||
|
@ -6,15 +6,15 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>543</width>
|
||||
<height>423</height>
|
||||
<width>555</width>
|
||||
<height>463</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
@ -26,21 +26,17 @@
|
||||
</size>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="elideMode">
|
||||
<enum>Qt::ElideNone</enum>
|
||||
</property>
|
||||
<property name="tabsClosable">
|
||||
<bool>false</bool>
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="libTab">
|
||||
<attribute name="title">
|
||||
<string>Library</string>
|
||||
<string>Version</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="ModListView" name="jarModsTreeView">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||
<item>
|
||||
<widget class="ModListView" name="libraryTreeView">
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOn</enum>
|
||||
</property>
|
||||
@ -49,15 +45,131 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Main Class:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="mainClassEdit">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QPushButton" name="forgeBtn">
|
||||
<property name="toolTip">
|
||||
<string>Replace any current custom version with Minecraft Forge</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Install Forge</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="customizeBtn">
|
||||
<property name="toolTip">
|
||||
<string>Create an customized copy of the base version</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Customize</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="revertBtn">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Revert to original base version</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Revert</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="addLibraryBtn">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Add new libraries</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Add</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="removeLibraryBtn">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Remove selected libraries</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Remove</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="modTab">
|
||||
<attribute name="title">
|
||||
<string>Loader Mods</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="ModListView" name="loaderModTreeView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="acceptDrops">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@ -66,6 +178,8 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
@ -105,6 +219,18 @@
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="MCModInfoFrame" name="frame">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="resPackTab">
|
||||
<attribute name="title">
|
||||
@ -163,7 +289,7 @@
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
@ -181,6 +307,12 @@
|
||||
<extends>QTreeView</extends>
|
||||
<header>gui/ModListView.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>MCModInfoFrame</class>
|
||||
<extends>QFrame</extends>
|
||||
<header>gui/MCModInfoFrame.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
@ -13,88 +13,91 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "taskdialog.h"
|
||||
#include "ui_taskdialog.h"
|
||||
#include "ProgressDialog.h"
|
||||
#include "ui_ProgressDialog.h"
|
||||
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include "logic/tasks/Task.h"
|
||||
#include "gui/platform.h"
|
||||
|
||||
TaskDialog::TaskDialog(QWidget *parent) :
|
||||
ProgressDialog::ProgressDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::TaskDialog)
|
||||
ui(new Ui::ProgressDialog)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
ui->setupUi(this);
|
||||
updateSize();
|
||||
|
||||
changeProgress(0);
|
||||
changeProgress(0,100);
|
||||
}
|
||||
|
||||
TaskDialog::~TaskDialog()
|
||||
ProgressDialog::~ProgressDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void TaskDialog::updateSize()
|
||||
void ProgressDialog::updateSize()
|
||||
{
|
||||
resize(QSize(480, minimumSizeHint().height()));
|
||||
}
|
||||
|
||||
void TaskDialog::exec(Task *task)
|
||||
int ProgressDialog::exec(ProgressProvider *task)
|
||||
{
|
||||
this->task = task;
|
||||
|
||||
// Connect signals.
|
||||
connect(task, SIGNAL(started()), SLOT(onTaskStarted()));
|
||||
connect(task, SIGNAL(failed(QString)), SLOT(onTaskEnded()));
|
||||
connect(task, SIGNAL(succeeded()), SLOT(onTaskEnded()));
|
||||
connect(task, SIGNAL(statusChanged(const QString&)), SLOT(changeStatus(const QString&)));
|
||||
connect(task, SIGNAL(progressChanged(int)), SLOT(changeProgress(int)));
|
||||
connect(task, SIGNAL(failed(QString)), SLOT(onTaskFailed(QString)));
|
||||
connect(task, SIGNAL(succeeded()), SLOT(onTaskSucceeded()));
|
||||
connect(task, SIGNAL(status(QString)), SLOT(changeStatus(const QString&)));
|
||||
connect(task, SIGNAL(progress(qint64,qint64)), SLOT(changeProgress(qint64,qint64)));
|
||||
|
||||
// this makes sure that the task is started after the dialog is created
|
||||
QMetaObject::invokeMethod(task, "startTask", Qt::QueuedConnection);
|
||||
QDialog::exec();
|
||||
QMetaObject::invokeMethod(task, "start", Qt::QueuedConnection);
|
||||
return QDialog::exec();
|
||||
}
|
||||
|
||||
Task* TaskDialog::getTask()
|
||||
ProgressProvider* ProgressDialog::getTask()
|
||||
{
|
||||
return task;
|
||||
}
|
||||
|
||||
void TaskDialog::onTaskStarted()
|
||||
void ProgressDialog::onTaskStarted()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void TaskDialog::onTaskEnded()
|
||||
void ProgressDialog::onTaskFailed(QString failure)
|
||||
{
|
||||
close();
|
||||
reject();
|
||||
}
|
||||
|
||||
void TaskDialog::changeStatus(const QString &status)
|
||||
void ProgressDialog::onTaskSucceeded()
|
||||
{
|
||||
accept();
|
||||
}
|
||||
|
||||
void ProgressDialog::changeStatus(const QString &status)
|
||||
{
|
||||
ui->statusLabel->setText(status);
|
||||
updateSize();
|
||||
}
|
||||
|
||||
void TaskDialog::changeProgress(int progress)
|
||||
void ProgressDialog::changeProgress(qint64 current, qint64 total)
|
||||
{
|
||||
if (progress < 0)
|
||||
progress = 0;
|
||||
else if (progress > 100)
|
||||
progress = 100;
|
||||
|
||||
ui->taskProgressBar->setValue(progress);
|
||||
ui->taskProgressBar->setMaximum(total);
|
||||
ui->taskProgressBar->setValue(current);
|
||||
}
|
||||
|
||||
void TaskDialog::keyPressEvent(QKeyEvent* e)
|
||||
void ProgressDialog::keyPressEvent(QKeyEvent* e)
|
||||
{
|
||||
if (e->key() == Qt::Key_Escape)
|
||||
return;
|
||||
QDialog::keyPressEvent(e);
|
||||
}
|
||||
|
||||
void TaskDialog::closeEvent(QCloseEvent* e)
|
||||
void ProgressDialog::closeEvent(QCloseEvent* e)
|
||||
{
|
||||
if (task && task->isRunning())
|
||||
{
|
@ -18,32 +18,33 @@
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
class Task;
|
||||
class ProgressProvider;
|
||||
|
||||
namespace Ui {
|
||||
class TaskDialog;
|
||||
class ProgressDialog;
|
||||
}
|
||||
|
||||
class TaskDialog : public QDialog
|
||||
class ProgressDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TaskDialog(QWidget *parent = 0);
|
||||
~TaskDialog();
|
||||
explicit ProgressDialog(QWidget *parent = 0);
|
||||
~ProgressDialog();
|
||||
|
||||
void updateSize();
|
||||
|
||||
void exec(Task* task);
|
||||
int exec(ProgressProvider* task);
|
||||
|
||||
Task* getTask();
|
||||
ProgressProvider* getTask();
|
||||
|
||||
public slots:
|
||||
void onTaskStarted();
|
||||
void onTaskEnded();
|
||||
void onTaskFailed(QString failure);
|
||||
void onTaskSucceeded();
|
||||
|
||||
void changeStatus(const QString& status);
|
||||
void changeProgress(int progress);
|
||||
void changeProgress(qint64 current, qint64 total);
|
||||
|
||||
signals:
|
||||
|
||||
@ -53,9 +54,9 @@ protected:
|
||||
virtual void closeEvent(QCloseEvent* e);
|
||||
|
||||
private:
|
||||
Ui::TaskDialog *ui;
|
||||
Ui::ProgressDialog *ui;
|
||||
|
||||
Task* task;
|
||||
ProgressProvider* task;
|
||||
};
|
||||
|
||||
#endif // TASKDIALOG_H
|
@ -1,13 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TaskDialog</class>
|
||||
<widget class="QDialog" name="TaskDialog">
|
||||
<class>ProgressDialog</class>
|
||||
<widget class="QDialog" name="ProgressDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>58</height>
|
||||
<height>68</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
@ -2,11 +2,13 @@
|
||||
#include "ui_aboutdialog.h"
|
||||
#include <QIcon>
|
||||
#include <MultiMC.h>
|
||||
#include "gui/platform.h"
|
||||
|
||||
AboutDialog::AboutDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::AboutDialog)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->icon->setPixmap(QIcon(":/icons/multimc/scalable/apps/multimc.svg").pixmap(64));
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>450</width>
|
||||
<height>400</height>
|
||||
<height>429</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
@ -58,6 +58,9 @@
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../multimc.qrc">:/icons/multimc/scalable/apps/multimc.svg</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@ -92,16 +95,13 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolBox" name="toolBox">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="aboutPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>432</width>
|
||||
<height>153</height>
|
||||
<height>191</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
@ -111,7 +111,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="aboutLabel">
|
||||
<property name="text">
|
||||
<string>MultiMC is a custom launcher that makes managing Minecraft easier by allowing you to have multiple installations of Minecraft at once.</string>
|
||||
<string><html><head/><body><p>MultiMC is a custom launcher that makes managing Minecraft easier by allowing you to have multiple instances of Minecraft at once.</p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
@ -145,7 +145,7 @@
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><a href="http://github.com/Forkk/MultiMC5"><span style=" text-decoration: underline; color:#0000ff;">http://github.com/Forkk/MultiMC5</span></a></p></body></html></string>
|
||||
<string><html><head/><body><p><a href="http://github.com/Forkk/MultiMC5"><span style=" text-decoration: underline; color:#0000ff;">http://github.com/MultiMC/MultiMC5</span></a></p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
@ -160,7 +160,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>432</width>
|
||||
<height>153</height>
|
||||
<height>191</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
@ -176,16 +176,37 @@
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Andrew Okin &lt;<a href="mailto:forkk@forkk.net"><span style=" text-decoration: underline; color:#0000ff;">forkk@forkk.net</span></a>&gt;</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Petr Mrázek &lt;<a href="mailto:peterix@gmail.com"><span style=" text-decoration: underline; color:#0000ff;">peterix@gmail.com</span></a>&gt;</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Orochimarufan &lt;<a href="mailto:orochimarufan.x3@gmail.com"><span style=" text-decoration: underline; color:#0000ff;">orochimarufan.x3@gmail.com</span></a>&gt;</p></body></html></string>
|
||||
</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Andrew Okin &lt;</span><a href="mailto:forkk@forkk.net"><span style=" font-family:'Ubuntu'; font-size:11pt; text-decoration: underline; color:#0000ff;">forkk@forkk.net</span></a><span style=" font-family:'Ubuntu'; font-size:11pt;">&gt;</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Petr Mrázek &lt;</span><a href="mailto:peterix@gmail.com"><span style=" font-family:'Ubuntu'; font-size:11pt; text-decoration: underline; color:#0000ff;">peterix@gmail.com</span></a><span style=" font-family:'Ubuntu'; font-size:11pt;">&gt;</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Orochimarufan &lt;</span><a href="mailto:orochimarufan.x3@gmail.com"><span style=" font-family:'Ubuntu'; font-size:11pt; text-decoration: underline; color:#0000ff;">orochimarufan.x3@gmail.com</span></a><span style=" font-family:'Ubuntu'; font-size:11pt;">&gt;</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">TakSuyu &lt;</span><a href="mailto:taksuyu@gmail.com"><span style=" font-family:'Ubuntu'; font-size:11pt; text-decoration: underline; color:#0000ff;">taksuyu@gmail.com</span></a><span style=" font-family:'Ubuntu'; font-size:11pt;">&gt;</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Sky Welch &lt;</span><span style=" font-family:'Ubuntu'; font-size:11pt; text-decoration: underline; color:#0000ff;">multimc@bunnies.cc</span><span style=" font-family:'Ubuntu'; font-size:11pt;">&gt;</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Kilobyte &lt;</span><a href="mailto:stiepen22@gmx.de"><span style=" font-family:'Ubuntu'; font-size:11pt; text-decoration: underline; color:#0000ff;">stiepen22@gmx.de</span></a><span style=" font-family:'Ubuntu'; font-size:11pt;">&gt;</span></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="translationInfo">
|
||||
<property name="text">
|
||||
<string extracomment="Hey, Translator, feel free to put credit to you here">No Language file loaded.</string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="licensePage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>432</width>
|
||||
<height>191</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
<string>License</string>
|
||||
</attribute>
|
||||
@ -205,44 +226,45 @@ p, li { white-space: pre-wrap; }
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Copyright 2012 MultiMC Contributors</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">you may not use this file except in compliance with the License.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">You may obtain a copy of the License at</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> http://www.apache.org/licenses/LICENSE-2.0</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Unless required by applicable law or agreed to in writing, software</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">distributed under the License is distributed on an &quot;AS IS&quot; BASIS,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">See the License for the specific language governing permissions and</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">limitations under the License.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">MultiMC uses bspatch, </span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Copyright 2003-2005 Colin Percival</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">All rights reserved</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Redistribution and use in source and binary forms, with or without</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">modification, are permitted providing that the following conditions</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">are met: </span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">1. Redistributions of source code must retain the above copyright</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> notice, this list of conditions and the following disclaimer.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">2. Redistributions in binary form must reproduce the above copyright</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> notice, this list of conditions and the following disclaimer in the</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> documentation and/or other materials provided with the distribution.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">POSSIBILITY OF SUCH DAMAGE.</span></p></body></html></string>
|
||||
</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">Copyright 2012 MultiMC Contributors</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">you may not use this file except in compliance with the License.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">You may obtain a copy of the License at</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:10pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;"> http://www.apache.org/licenses/LICENSE-2.0</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:10pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">Unless required by applicable law or agreed to in writing, software</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">distributed under the License is distributed on an &quot;AS IS&quot; BASIS,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">See the License for the specific language governing permissions and</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">limitations under the License.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:10pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">MultiMC uses QSLog, </span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">Copyright (c) 2010, Razvan Petru</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">All rights reserved.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:10pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">Redistribution and use in source and binary forms, with or without modification,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">are permitted provided that the following conditions are met:</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:10pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">* Redistributions of source code must retain the above copyright notice, this</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;"> list of conditions and the following disclaimer.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">* Redistributions in binary form must reproduce the above copyright notice, this</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;"> list of conditions and the following disclaimer in the documentation and/or other</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;"> materials provided with the distribution.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">* The name of the contributors may not be used to endorse or promote products</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;"> derived from this software without specific prior written permission.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:10pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS IS&quot; AND</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">OF THE POSSIBILITY OF SUCH DAMAGE.</span></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -254,6 +276,9 @@ p, li { white-space: pre-wrap; }
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QPushButton" name="aboutQt">
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>About Qt</string>
|
||||
</property>
|
||||
@ -283,6 +308,8 @@ p, li { white-space: pre-wrap; }
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<resources>
|
||||
<include location="../multimc.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
@ -2,13 +2,19 @@
|
||||
#include "ui_consolewindow.h"
|
||||
|
||||
#include <QScrollBar>
|
||||
#include <QMessageBox>
|
||||
|
||||
ConsoleWindow::ConsoleWindow(QWidget *parent) :
|
||||
#include <gui/platform.h>
|
||||
|
||||
ConsoleWindow::ConsoleWindow(MinecraftProcess *mcproc, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::ConsoleWindow),
|
||||
m_mayclose(true)
|
||||
m_mayclose(true),
|
||||
proc(mcproc)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
ui->setupUi(this);
|
||||
connect(mcproc, SIGNAL(ended()), this, SLOT(onEnded()));
|
||||
}
|
||||
|
||||
ConsoleWindow::~ConsoleWindow()
|
||||
@ -20,7 +26,7 @@ void ConsoleWindow::writeColor(QString text, const char *color)
|
||||
{
|
||||
// append a paragraph
|
||||
if (color != nullptr)
|
||||
ui->text->appendHtml(QString("<font color=%1>%2</font>").arg(color).arg(text));
|
||||
ui->text->appendHtml(QString("<font color=\"%1\">%2</font>").arg(color).arg(text));
|
||||
else
|
||||
ui->text->appendPlainText(text);
|
||||
// scroll down
|
||||
@ -33,6 +39,11 @@ void ConsoleWindow::write(QString data, MessageLevel::Enum mode)
|
||||
if (data.endsWith('\n'))
|
||||
data = data.left(data.length()-1);
|
||||
QStringList paragraphs = data.split('\n');
|
||||
for(QString ¶graph : paragraphs)
|
||||
{
|
||||
paragraph = paragraph.trimmed();
|
||||
}
|
||||
|
||||
QListIterator<QString> iter(paragraphs);
|
||||
if (mode == MessageLevel::MultiMC)
|
||||
while(iter.hasNext())
|
||||
@ -40,6 +51,15 @@ void ConsoleWindow::write(QString data, MessageLevel::Enum mode)
|
||||
else if (mode == MessageLevel::Error)
|
||||
while(iter.hasNext())
|
||||
writeColor(iter.next(), "red");
|
||||
else if (mode == MessageLevel::Warning)
|
||||
while(iter.hasNext())
|
||||
writeColor(iter.next(), "orange");
|
||||
else if (mode == MessageLevel::Fatal)
|
||||
while(iter.hasNext())
|
||||
writeColor(iter.next(), "pink");
|
||||
else if (mode == MessageLevel::Debug)
|
||||
while(iter.hasNext())
|
||||
writeColor(iter.next(), "green");
|
||||
// TODO: implement other MessageLevels
|
||||
else
|
||||
while(iter.hasNext())
|
||||
@ -72,3 +92,26 @@ void ConsoleWindow::closeEvent(QCloseEvent * event)
|
||||
else
|
||||
QDialog::closeEvent(event);
|
||||
}
|
||||
|
||||
void ConsoleWindow::on_btnKillMinecraft_clicked()
|
||||
{
|
||||
ui->btnKillMinecraft->setEnabled(false);
|
||||
QMessageBox r_u_sure;
|
||||
//: Main question of the kill confirmation dialog
|
||||
r_u_sure.setText(tr("Kill Minecraft?"));
|
||||
r_u_sure.setInformativeText(tr("This can cause the instance to get corrupted and should only be used if Minecraft is frozen for some reason"));
|
||||
r_u_sure.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
||||
r_u_sure.setDefaultButton(QMessageBox::Yes);
|
||||
if (r_u_sure.exec() == QMessageBox::Yes)
|
||||
proc->killMinecraft();
|
||||
else
|
||||
ui->btnKillMinecraft->setEnabled(true);
|
||||
r_u_sure.close();
|
||||
}
|
||||
|
||||
void ConsoleWindow::onEnded()
|
||||
{
|
||||
ui->btnKillMinecraft->setEnabled(false);
|
||||
// TODO: Check why this doesn't work
|
||||
if (!proc->exitCode()) this->close();
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ class ConsoleWindow : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConsoleWindow(QWidget *parent = 0);
|
||||
explicit ConsoleWindow(MinecraftProcess *proc, QWidget *parent = 0);
|
||||
~ConsoleWindow();
|
||||
|
||||
/**
|
||||
@ -48,12 +48,15 @@ public slots:
|
||||
|
||||
private slots:
|
||||
void on_closeButton_clicked();
|
||||
void on_btnKillMinecraft_clicked();
|
||||
void onEnded();
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *);
|
||||
|
||||
private:
|
||||
Ui::ConsoleWindow *ui;
|
||||
MinecraftProcess *proc;
|
||||
bool m_mayclose;
|
||||
};
|
||||
|
||||
|
@ -62,6 +62,13 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnKillMinecraft">
|
||||
<property name="text">
|
||||
<string>Kill Minecraft</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="closeButton">
|
||||
<property name="text">
|
||||
|
@ -19,12 +19,14 @@
|
||||
|
||||
#include "instancesettings.h"
|
||||
#include "ui_instancesettings.h"
|
||||
#include "gui/platform.h"
|
||||
|
||||
InstanceSettings::InstanceSettings( SettingsObject * obj, QWidget *parent) :
|
||||
m_obj(obj),
|
||||
QDialog(parent),
|
||||
ui(new Ui::InstanceSettings)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
ui->setupUi(this);
|
||||
loadSettings();
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>477</width>
|
||||
<width>526</width>
|
||||
<height>590</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -249,7 +249,7 @@
|
||||
<number>64</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>512</number>
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>8</number>
|
||||
@ -395,6 +395,7 @@
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>settingsTabs</tabstop>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
<tabstop>windowSizeGroupBox</tabstop>
|
||||
<tabstop>maximizedCheckBox</tabstop>
|
||||
<tabstop>windowWidthSpinBox</tabstop>
|
||||
@ -407,6 +408,7 @@
|
||||
<tabstop>memoryGroupBox</tabstop>
|
||||
<tabstop>minMemSpinBox</tabstop>
|
||||
<tabstop>maxMemSpinBox</tabstop>
|
||||
<tabstop>permGenSpinBox</tabstop>
|
||||
<tabstop>javaSettingsGroupBox</tabstop>
|
||||
<tabstop>javaPathTextBox</tabstop>
|
||||
<tabstop>pushButton</tabstop>
|
||||
@ -414,7 +416,6 @@
|
||||
<tabstop>customCommandsGroupBox</tabstop>
|
||||
<tabstop>preLaunchCmdTextBox</tabstop>
|
||||
<tabstop>postExitCmdTextBox</tabstop>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
@ -16,16 +16,25 @@
|
||||
#include "logindialog.h"
|
||||
#include "ui_logindialog.h"
|
||||
#include "keyring.h"
|
||||
#include <QDebug>
|
||||
#include "gui/platform.h"
|
||||
#include "MultiMC.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonParseError>
|
||||
#include "logic/net/HttpMetaCache.h"
|
||||
#include <logger/QsLog.h>
|
||||
|
||||
LoginDialog::LoginDialog(QWidget *parent, const QString& loginErrMsg) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::LoginDialog)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
ui->setupUi(this);
|
||||
|
||||
//TODO: make translateable
|
||||
offlineButton = new QPushButton("Offline Once");
|
||||
//: Use offline mode one time
|
||||
offlineButton = new QPushButton(tr("Offline Once"));
|
||||
|
||||
ui->loginButtonBox->addButton(offlineButton, QDialogButtonBox::ActionRole);
|
||||
|
||||
@ -33,8 +42,8 @@ LoginDialog::LoginDialog(QWidget *parent, const QString& loginErrMsg) :
|
||||
isOnline_ = true;
|
||||
onlineForced = false;
|
||||
|
||||
//FIXME: translateable?
|
||||
ui->usernameTextBox->lineEdit()->setPlaceholderText(QApplication::translate("LoginDialog", "Name", 0));
|
||||
//: The username during login (placeholder)
|
||||
ui->usernameTextBox->lineEdit()->setPlaceholderText(tr("Name"));
|
||||
|
||||
connect(ui->usernameTextBox, SIGNAL(currentTextChanged(QString)), this, SLOT(userTextChanged(QString)));
|
||||
connect(ui->forgetButton, SIGNAL(clicked(bool)), this, SLOT(forgetCurrentUser()));
|
||||
@ -49,6 +58,8 @@ LoginDialog::LoginDialog(QWidget *parent, const QString& loginErrMsg) :
|
||||
arg(loginErrMsg));
|
||||
}
|
||||
|
||||
ui->lblFace->setVisible(false);
|
||||
|
||||
resize(minimumSizeHint());
|
||||
layout()->setSizeConstraint(QLayout::SetFixedSize);
|
||||
Keyring * k = Keyring::instance();
|
||||
@ -109,7 +120,7 @@ void LoginDialog::passwordToggled ( bool state )
|
||||
blockToggles = true;
|
||||
if(!state)
|
||||
{
|
||||
qDebug() << "password disabled";
|
||||
QLOG_DEBUG() << "password disabled";
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -117,7 +128,7 @@ void LoginDialog::passwordToggled ( bool state )
|
||||
{
|
||||
ui->rememberUsernameCheckbox->setChecked(true);
|
||||
}
|
||||
qDebug() << "password enabled";
|
||||
QLOG_DEBUG() << "password enabled";
|
||||
}
|
||||
blockToggles = false;
|
||||
}
|
||||
@ -134,11 +145,11 @@ void LoginDialog::usernameToggled ( bool state )
|
||||
{
|
||||
ui->rememberPasswordCheckbox->setChecked(false);
|
||||
}
|
||||
qDebug() << "username disabled";
|
||||
QLOG_DEBUG() << "username disabled";
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "username enabled";
|
||||
QLOG_DEBUG() << "username enabled";
|
||||
}
|
||||
blockToggles = false;
|
||||
}
|
||||
@ -149,13 +160,53 @@ void LoginDialog::userTextChanged ( const QString& user )
|
||||
blockToggles = true;
|
||||
Keyring * k = Keyring::instance();
|
||||
QStringList sl = k->getStoredAccounts("minecraft");
|
||||
bool gotFace = false;
|
||||
|
||||
if(sl.contains(user))
|
||||
{
|
||||
ui->rememberUsernameCheckbox->setChecked(true);
|
||||
QString passwd = k->getPassword("minecraft",user);
|
||||
ui->rememberPasswordCheckbox->setChecked(!passwd.isEmpty());
|
||||
ui->passwordTextBox->setText(passwd);
|
||||
|
||||
QByteArray data;
|
||||
{
|
||||
auto filename = MMC->metacache()->resolveEntry("skins", "skins.json")->getFullPath();
|
||||
QFile listFile(filename);
|
||||
if(!listFile.open(QIODevice::ReadOnly))
|
||||
return;
|
||||
data = listFile.readAll();
|
||||
}
|
||||
|
||||
QJsonParseError jsonError;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError);
|
||||
QJsonObject root = jsonDoc.object();
|
||||
QJsonObject mappings = root.value("mappings").toObject();
|
||||
|
||||
if(!mappings[user].isUndefined())
|
||||
{
|
||||
QJsonArray usernames = mappings.value(user).toArray();
|
||||
if(!usernames.isEmpty())
|
||||
{
|
||||
QString mapped_username = usernames[0].toString();
|
||||
|
||||
if(!mapped_username.isEmpty())
|
||||
{
|
||||
QFile fskin(MMC->metacache()->resolveEntry("skins", mapped_username + ".png")->getFullPath());
|
||||
if(fskin.exists())
|
||||
{
|
||||
QPixmap skin(MMC->metacache()->resolveEntry("skins", mapped_username + ".png")->getFullPath());
|
||||
QPixmap face = skin.copy(8, 8, 8, 8).scaled(48, 48, Qt::KeepAspectRatio);
|
||||
|
||||
ui->lblFace->setPixmap(face);
|
||||
gotFace = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui->lblFace->setVisible(gotFace);
|
||||
blockToggles = false;
|
||||
}
|
||||
|
||||
|
@ -23,10 +23,34 @@
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="usernameLabel">
|
||||
<item row="0" column="4" rowspan="2">
|
||||
<widget class="QLabel" name="lblFace">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="sizeIncrement">
|
||||
<size>
|
||||
<width>1</width>
|
||||
<height>1</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Username:</string>
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../multimc.qrc">:/icons/instances/steve</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -37,6 +61,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="usernameLabel">
|
||||
<property name="text">
|
||||
<string>Username:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="passwordLabel">
|
||||
<property name="text">
|
||||
@ -54,7 +85,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" rowspan="2">
|
||||
<item row="0" column="5" rowspan="2">
|
||||
<widget class="QPushButton" name="forgetButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
@ -111,7 +142,9 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<resources>
|
||||
<include location="../multimc.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>loginButtonBox</sender>
|
||||
|
@ -13,8 +13,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "MultiMC.h"
|
||||
#include "lwjglselectdialog.h"
|
||||
#include "ui_lwjglselectdialog.h"
|
||||
#include "gui/platform.h"
|
||||
|
||||
#include "logic/lists/LwjglVersionList.h"
|
||||
|
||||
@ -22,13 +24,15 @@ LWJGLSelectDialog::LWJGLSelectDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::LWJGLSelectDialog)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
ui->setupUi(this);
|
||||
ui->labelStatus->setVisible(false);
|
||||
ui->lwjglListView->setModel(&LWJGLVersionList::get());
|
||||
auto lwjgllist = MMC->lwjgllist();
|
||||
ui->lwjglListView->setModel(lwjgllist.get());
|
||||
|
||||
connect(&LWJGLVersionList::get(), SIGNAL(loadingStateUpdated(bool)), SLOT(loadingStateUpdated(bool)));
|
||||
connect(&LWJGLVersionList::get(), SIGNAL(loadListFailed(QString)), SLOT(loadingFailed(QString)));
|
||||
loadingStateUpdated(LWJGLVersionList::get().isLoading());
|
||||
connect(lwjgllist.get(), SIGNAL(loadingStateUpdated(bool)), SLOT(loadingStateUpdated(bool)));
|
||||
connect(lwjgllist.get(), SIGNAL(loadListFailed(QString)), SLOT(loadingFailed(QString)));
|
||||
loadingStateUpdated(lwjgllist->isLoading());
|
||||
}
|
||||
|
||||
LWJGLSelectDialog::~LWJGLSelectDialog()
|
||||
@ -38,15 +42,15 @@ LWJGLSelectDialog::~LWJGLSelectDialog()
|
||||
|
||||
QString LWJGLSelectDialog::selectedVersion() const
|
||||
{
|
||||
return LWJGLVersionList::get().data(
|
||||
return MMC->lwjgllist()->data(
|
||||
ui->lwjglListView->selectionModel()->currentIndex(),
|
||||
Qt::DisplayRole).toString();
|
||||
}
|
||||
|
||||
void LWJGLSelectDialog::on_refreshButton_clicked()
|
||||
{
|
||||
if (!LWJGLVersionList::get().isLoading())
|
||||
LWJGLVersionList::get().loadList();
|
||||
if (!MMC->lwjgllist()->isLoading())
|
||||
MMC->lwjgllist()->loadList();
|
||||
}
|
||||
|
||||
void LWJGLSelectDialog::loadingStateUpdated(bool loading)
|
||||
@ -54,7 +58,7 @@ void LWJGLSelectDialog::loadingStateUpdated(bool loading)
|
||||
setEnabled(!loading);
|
||||
if (loading)
|
||||
{
|
||||
ui->labelStatus->setText("Loading LWJGL version list...");
|
||||
ui->labelStatus->setText(tr("Loading LWJGL version list..."));
|
||||
ui->labelStatus->setStyleSheet("QLabel { color: black; }");
|
||||
}
|
||||
ui->labelStatus->setVisible(loading);
|
||||
|
@ -42,24 +42,28 @@
|
||||
#include "gui/settingsdialog.h"
|
||||
#include "gui/newinstancedialog.h"
|
||||
#include "gui/logindialog.h"
|
||||
#include "gui/taskdialog.h"
|
||||
#include "gui/ProgressDialog.h"
|
||||
#include "gui/aboutdialog.h"
|
||||
#include "gui/versionselectdialog.h"
|
||||
#include "gui/lwjglselectdialog.h"
|
||||
#include "gui/consolewindow.h"
|
||||
#include "gui/instancesettings.h"
|
||||
#include "gui/platform.h"
|
||||
|
||||
#include "logic/lists/InstanceList.h"
|
||||
#include "logic/lists/MinecraftVersionList.h"
|
||||
#include "logic/lists/LwjglVersionList.h"
|
||||
#include "logic/lists/IconList.h"
|
||||
#include "logic/lists/JavaVersionList.h"
|
||||
|
||||
#include "logic/net/LoginTask.h"
|
||||
|
||||
#include "logic/tasks/LoginTask.h"
|
||||
#include "logic/BaseInstance.h"
|
||||
#include "logic/InstanceFactory.h"
|
||||
#include "logic/MinecraftProcess.h"
|
||||
#include "logic/OneSixAssets.h"
|
||||
#include "logic/OneSixUpdate.h"
|
||||
#include "logic/JavaUtils.h"
|
||||
|
||||
#include "logic/LegacyInstance.h"
|
||||
|
||||
@ -68,11 +72,11 @@
|
||||
#include "LabeledToolButton.h"
|
||||
#include "EditNotesDialog.h"
|
||||
|
||||
MainWindow::MainWindow ( QWidget *parent )
|
||||
:QMainWindow ( parent ), ui ( new Ui::MainWindow )
|
||||
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
|
||||
{
|
||||
ui->setupUi ( this );
|
||||
setWindowTitle ( QString ( "MultiMC %1" ).arg ( MMC->version().toString() ) );
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
ui->setupUi(this);
|
||||
setWindowTitle(QString("MultiMC %1").arg(MMC->version().toString()));
|
||||
|
||||
// Set the selected instance to null
|
||||
m_selectedInstance = nullptr;
|
||||
@ -92,22 +96,22 @@ MainWindow::MainWindow ( QWidget *parent )
|
||||
connect(renameButton, SIGNAL(clicked(bool)), SLOT(on_actionRenameInstance_triggered()));
|
||||
ui->instanceToolBar->insertWidget(ui->actionLaunchInstance, renameButton);
|
||||
ui->instanceToolBar->insertSeparator(ui->actionLaunchInstance);
|
||||
renameButton->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred);
|
||||
renameButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
}
|
||||
|
||||
// Create the instance list widget
|
||||
{
|
||||
view = new KCategorizedView ( ui->centralWidget );
|
||||
drawer = new KCategoryDrawer ( view );
|
||||
view = new KCategorizedView(ui->centralWidget);
|
||||
drawer = new KCategoryDrawer(view);
|
||||
|
||||
view->setSelectionMode ( QAbstractItemView::SingleSelection );
|
||||
view->setCategoryDrawer ( drawer );
|
||||
view->setCollapsibleBlocks ( true );
|
||||
view->setViewMode ( QListView::IconMode );
|
||||
view->setFlow ( QListView::LeftToRight );
|
||||
view->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
view->setCategoryDrawer(drawer);
|
||||
view->setCollapsibleBlocks(true);
|
||||
view->setViewMode(QListView::IconMode);
|
||||
view->setFlow(QListView::LeftToRight);
|
||||
view->setWordWrap(true);
|
||||
view->setMouseTracking ( true );
|
||||
view->viewport()->setAttribute ( Qt::WA_Hover );
|
||||
view->setMouseTracking(true);
|
||||
view->viewport()->setAttribute(Qt::WA_Hover);
|
||||
auto delegate = new ListViewDelegate();
|
||||
view->setItemDelegate(delegate);
|
||||
view->setSpacing(10);
|
||||
@ -118,18 +122,19 @@ MainWindow::MainWindow ( QWidget *parent )
|
||||
|
||||
view->installEventFilter(this);
|
||||
|
||||
proxymodel = new InstanceProxyModel ( this );
|
||||
proxymodel->setSortRole ( KCategorizedSortFilterProxyModel::CategorySortRole );
|
||||
proxymodel->setFilterRole ( KCategorizedSortFilterProxyModel::CategorySortRole );
|
||||
//proxymodel->setDynamicSortFilter ( true );
|
||||
proxymodel = new InstanceProxyModel(this);
|
||||
proxymodel->setSortRole(KCategorizedSortFilterProxyModel::CategorySortRole);
|
||||
proxymodel->setFilterRole(KCategorizedSortFilterProxyModel::CategorySortRole);
|
||||
// proxymodel->setDynamicSortFilter ( true );
|
||||
|
||||
// FIXME: instList should be global-ish, or at least not tied to the main window... maybe the application itself?
|
||||
proxymodel->setSourceModel ( MMC->instances() );
|
||||
proxymodel->sort ( 0 );
|
||||
view->setFrameShape ( QFrame::NoFrame );
|
||||
view->setModel ( proxymodel );
|
||||
// FIXME: instList should be global-ish, or at least not tied to the main window...
|
||||
// maybe the application itself?
|
||||
proxymodel->setSourceModel(MMC->instances().get());
|
||||
proxymodel->sort(0);
|
||||
view->setFrameShape(QFrame::NoFrame);
|
||||
view->setModel(proxymodel);
|
||||
|
||||
ui->horizontalLayout->addWidget ( view );
|
||||
ui->horizontalLayout->addWidget(view);
|
||||
}
|
||||
// The cat background
|
||||
{
|
||||
@ -139,29 +144,27 @@ MainWindow::MainWindow ( QWidget *parent )
|
||||
setCatBackground(cat_enable);
|
||||
}
|
||||
// start instance when double-clicked
|
||||
connect(view, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(instanceActivated(const QModelIndex &)));
|
||||
connect(view, SIGNAL(doubleClicked(const QModelIndex &)), this,
|
||||
SLOT(instanceActivated(const QModelIndex &)));
|
||||
// track the selection -- update the instance toolbar
|
||||
connect(
|
||||
view->selectionModel(),
|
||||
SIGNAL(currentChanged(const QModelIndex &,const QModelIndex &)),
|
||||
this,
|
||||
SLOT(instanceChanged(const QModelIndex &,const QModelIndex &))
|
||||
);
|
||||
connect(view->selectionModel(),
|
||||
SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), this,
|
||||
SLOT(instanceChanged(const QModelIndex &, const QModelIndex &)));
|
||||
// model reset -> selection is invalid. All the instance pointers are wrong.
|
||||
// FIXME: stop using POINTERS everywhere
|
||||
connect(MMC->instances() ,SIGNAL(dataIsInvalid()),SLOT(selectionBad()));
|
||||
connect(MMC->instances().get(), SIGNAL(dataIsInvalid()), SLOT(selectionBad()));
|
||||
|
||||
// run the things that load and download other things... FIXME: this is NOT the place
|
||||
// FIXME: invisible actions in the background = NOPE.
|
||||
{
|
||||
if (!MinecraftVersionList::getMainList().isLoaded())
|
||||
if (!MMC->minecraftlist()->isLoaded())
|
||||
{
|
||||
m_versionLoadTask = MinecraftVersionList::getMainList().getLoadTask();
|
||||
m_versionLoadTask = MMC->minecraftlist()->getLoadTask();
|
||||
startTask(m_versionLoadTask);
|
||||
}
|
||||
if (!LWJGLVersionList::get().isLoaded())
|
||||
if (!MMC->lwjgllist()->isLoaded())
|
||||
{
|
||||
LWJGLVersionList::get().loadList();
|
||||
MMC->lwjgllist()->loadList();
|
||||
}
|
||||
assets_downloader = new OneSixAssets();
|
||||
assets_downloader->start();
|
||||
@ -176,14 +179,14 @@ MainWindow::~MainWindow()
|
||||
delete assets_downloader;
|
||||
}
|
||||
|
||||
bool MainWindow::eventFilter ( QObject* obj, QEvent* ev )
|
||||
bool MainWindow::eventFilter(QObject *obj, QEvent *ev)
|
||||
{
|
||||
if(obj == view)
|
||||
if (obj == view)
|
||||
{
|
||||
if (ev->type() == QEvent::KeyPress)
|
||||
{
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(ev);
|
||||
switch(keyEvent->key())
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev);
|
||||
switch (keyEvent->key())
|
||||
{
|
||||
case Qt::Key_Enter:
|
||||
case Qt::Key_Return:
|
||||
@ -203,21 +206,20 @@ bool MainWindow::eventFilter ( QObject* obj, QEvent* ev )
|
||||
}
|
||||
}
|
||||
}
|
||||
return QMainWindow::eventFilter ( obj, ev );
|
||||
return QMainWindow::eventFilter(obj, ev);
|
||||
}
|
||||
|
||||
void MainWindow::onCatToggled ( bool state )
|
||||
void MainWindow::onCatToggled(bool state)
|
||||
{
|
||||
setCatBackground(state);
|
||||
MMC->settings()->set("TheCat", state);
|
||||
}
|
||||
|
||||
void MainWindow::setCatBackground ( bool enabled )
|
||||
void MainWindow::setCatBackground(bool enabled)
|
||||
{
|
||||
if(enabled)
|
||||
if (enabled)
|
||||
{
|
||||
view->setStyleSheet(
|
||||
"QListView"
|
||||
view->setStyleSheet("QListView"
|
||||
"{"
|
||||
"background-image: url(:/backgrounds/kitteh);"
|
||||
"background-attachment: fixed;"
|
||||
@ -225,8 +227,7 @@ void MainWindow::setCatBackground ( bool enabled )
|
||||
"background-position: top right;"
|
||||
"background-repeat: none;"
|
||||
"background-color:palette(base);"
|
||||
"}"
|
||||
);
|
||||
"}");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -234,19 +235,19 @@ void MainWindow::setCatBackground ( bool enabled )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::instanceActivated ( QModelIndex index )
|
||||
void MainWindow::instanceActivated(QModelIndex index)
|
||||
{
|
||||
if(!index.isValid())
|
||||
if (!index.isValid())
|
||||
return;
|
||||
BaseInstance * inst = (BaseInstance *) index.data(InstanceList::InstancePointerRole).value<void *>();
|
||||
BaseInstance *inst =
|
||||
(BaseInstance *)index.data(InstanceList::InstancePointerRole).value<void *>();
|
||||
doLogin();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionAddInstance_triggered()
|
||||
{
|
||||
if (!MinecraftVersionList::getMainList().isLoaded() &&
|
||||
m_versionLoadTask && m_versionLoadTask->isRunning())
|
||||
if (!MMC->minecraftlist()->isLoaded() && m_versionLoadTask &&
|
||||
m_versionLoadTask->isRunning())
|
||||
{
|
||||
QEventLoop waitLoop;
|
||||
waitLoop.connect(m_versionLoadTask, SIGNAL(failed(QString)), SLOT(quit()));
|
||||
@ -254,7 +255,7 @@ void MainWindow::on_actionAddInstance_triggered()
|
||||
waitLoop.exec();
|
||||
}
|
||||
|
||||
NewInstanceDialog newInstDlg( this );
|
||||
NewInstanceDialog newInstDlg(this);
|
||||
if (!newInstDlg.exec())
|
||||
return;
|
||||
|
||||
@ -294,12 +295,12 @@ void MainWindow::on_actionAddInstance_triggered()
|
||||
|
||||
void MainWindow::on_actionChangeInstIcon_triggered()
|
||||
{
|
||||
if(!m_selectedInstance)
|
||||
if (!m_selectedInstance)
|
||||
return;
|
||||
|
||||
IconPickerDialog dlg(this);
|
||||
dlg.exec(m_selectedInstance->iconKey());
|
||||
if(dlg.result() == QDialog::Accepted)
|
||||
if (dlg.result() == QDialog::Accepted)
|
||||
{
|
||||
m_selectedInstance->setIconKey(dlg.selectedIconKey);
|
||||
auto ico = MMC->icons()->getIcon(dlg.selectedIconKey);
|
||||
@ -307,25 +308,23 @@ void MainWindow::on_actionChangeInstIcon_triggered()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_actionChangeInstGroup_triggered()
|
||||
{
|
||||
if(!m_selectedInstance)
|
||||
if (!m_selectedInstance)
|
||||
return;
|
||||
|
||||
bool ok = false;
|
||||
QString name ( m_selectedInstance->group() );
|
||||
name = QInputDialog::getText ( this, tr ( "Group name" ), tr ( "Enter a new group name." ),
|
||||
QLineEdit::Normal, name, &ok );
|
||||
if(ok)
|
||||
QString name(m_selectedInstance->group());
|
||||
name = QInputDialog::getText(this, tr("Group name"), tr("Enter a new group name."),
|
||||
QLineEdit::Normal, name, &ok);
|
||||
if (ok)
|
||||
m_selectedInstance->setGroupPost(name);
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_actionViewInstanceFolder_triggered()
|
||||
{
|
||||
QString str = MMC->settings()->get ( "InstanceDir" ).toString();
|
||||
openDirInDefaultProgram ( str );
|
||||
QString str = MMC->settings()->get("InstanceDir").toString();
|
||||
openDirInDefaultProgram(str);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionRefresh_triggered()
|
||||
@ -335,59 +334,58 @@ void MainWindow::on_actionRefresh_triggered()
|
||||
|
||||
void MainWindow::on_actionViewCentralModsFolder_triggered()
|
||||
{
|
||||
openDirInDefaultProgram ( MMC->settings()->get ( "CentralModsDir" ).toString() , true);
|
||||
openDirInDefaultProgram(MMC->settings()->get("CentralModsDir").toString(), true);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionConfig_Folder_triggered()
|
||||
{
|
||||
if(m_selectedInstance)
|
||||
if (m_selectedInstance)
|
||||
{
|
||||
QString str = m_selectedInstance->instanceConfigFolder();
|
||||
openDirInDefaultProgram ( QDir(str).absolutePath() );
|
||||
openDirInDefaultProgram(QDir(str).absolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_actionCheckUpdate_triggered()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::on_actionSettings_triggered()
|
||||
{
|
||||
SettingsDialog dialog ( this );
|
||||
SettingsDialog dialog(this);
|
||||
dialog.exec();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionReportBug_triggered()
|
||||
{
|
||||
openWebPage ( QUrl ( "http://jira.forkk.net/browse/MMC" ) );
|
||||
openWebPage(QUrl("http://multimc.myjetbrains.com/youtrack/dashboard#newissue=yes"));
|
||||
}
|
||||
|
||||
void MainWindow::on_actionNews_triggered()
|
||||
{
|
||||
openWebPage ( QUrl ( "http://forkk.net/tag/multimc.html" ) );
|
||||
openWebPage(QUrl("http://multimc.org/posts.html"));
|
||||
}
|
||||
|
||||
void MainWindow::on_actionAbout_triggered()
|
||||
{
|
||||
AboutDialog dialog ( this );
|
||||
AboutDialog dialog(this);
|
||||
dialog.exec();
|
||||
}
|
||||
|
||||
void MainWindow::on_mainToolBar_visibilityChanged ( bool )
|
||||
void MainWindow::on_mainToolBar_visibilityChanged(bool)
|
||||
{
|
||||
// Don't allow hiding the main toolbar.
|
||||
// This is the only way I could find to prevent it... :/
|
||||
ui->mainToolBar->setVisible ( true );
|
||||
ui->mainToolBar->setVisible(true);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionDeleteInstance_triggered()
|
||||
{
|
||||
if (m_selectedInstance)
|
||||
{
|
||||
int response = QMessageBox::question(this, "CAREFUL",
|
||||
QString("This is permanent! Are you sure?\nAbout to delete: ") + m_selectedInstance->name());
|
||||
int response = QMessageBox::question(
|
||||
this, "CAREFUL", QString("This is permanent! Are you sure?\nAbout to delete: ") +
|
||||
m_selectedInstance->name());
|
||||
if (response == QMessageBox::Yes)
|
||||
{
|
||||
m_selectedInstance->nuke();
|
||||
@ -397,31 +395,31 @@ void MainWindow::on_actionDeleteInstance_triggered()
|
||||
|
||||
void MainWindow::on_actionRenameInstance_triggered()
|
||||
{
|
||||
if(m_selectedInstance)
|
||||
if (m_selectedInstance)
|
||||
{
|
||||
bool ok = false;
|
||||
QString name ( m_selectedInstance->name() );
|
||||
name = QInputDialog::getText ( this, tr ( "Instance name" ), tr ( "Enter a new instance name." ),
|
||||
QLineEdit::Normal, name, &ok );
|
||||
QString name(m_selectedInstance->name());
|
||||
name =
|
||||
QInputDialog::getText(this, tr("Instance name"), tr("Enter a new instance name."),
|
||||
QLineEdit::Normal, name, &ok);
|
||||
|
||||
if (name.length() > 0)
|
||||
{
|
||||
if(ok && name.length())
|
||||
if (ok && name.length())
|
||||
{
|
||||
m_selectedInstance->setName(name);
|
||||
renameButton->setText(name);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionViewSelectedInstFolder_triggered()
|
||||
{
|
||||
if(m_selectedInstance)
|
||||
if (m_selectedInstance)
|
||||
{
|
||||
QString str = m_selectedInstance->instanceRoot();
|
||||
openDirInDefaultProgram ( QDir(str).absolutePath() );
|
||||
openDirInDefaultProgram(QDir(str).absolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
@ -430,65 +428,70 @@ void MainWindow::on_actionEditInstMods_triggered()
|
||||
if (m_selectedInstance)
|
||||
{
|
||||
auto dialog = m_selectedInstance->createModEditDialog(this);
|
||||
if(dialog)
|
||||
if (dialog)
|
||||
dialog->exec();
|
||||
dialog->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::closeEvent ( QCloseEvent *event )
|
||||
void MainWindow::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
// Save the window state and geometry.
|
||||
// TODO: Make this work with the new settings system.
|
||||
// settings->getConfig().setValue("MainWindowGeometry", saveGeometry());
|
||||
// settings->getConfig().setValue("MainWindowState", saveState());
|
||||
QMainWindow::closeEvent ( event );
|
||||
// settings->getConfig().setValue("MainWindowGeometry", saveGeometry());
|
||||
// settings->getConfig().setValue("MainWindowState", saveState());
|
||||
QMainWindow::closeEvent(event);
|
||||
}
|
||||
|
||||
void MainWindow::on_instanceView_customContextMenuRequested ( const QPoint &pos )
|
||||
/*
|
||||
void MainWindow::on_instanceView_customContextMenuRequested(const QPoint &pos)
|
||||
{
|
||||
QMenu *instContextMenu = new QMenu ( "Instance", this );
|
||||
QMenu *instContextMenu = new QMenu("Instance", this);
|
||||
|
||||
// Add the actions from the toolbar to the context menu.
|
||||
instContextMenu->addActions ( ui->instanceToolBar->actions() );
|
||||
instContextMenu->addActions(ui->instanceToolBar->actions());
|
||||
|
||||
instContextMenu->exec ( view->mapToGlobal ( pos ) );
|
||||
instContextMenu->exec(view->mapToGlobal(pos));
|
||||
}
|
||||
|
||||
*/
|
||||
void MainWindow::on_actionLaunchInstance_triggered()
|
||||
{
|
||||
if(m_selectedInstance)
|
||||
if (m_selectedInstance)
|
||||
{
|
||||
doLogin();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::doLogin(const QString& errorMsg)
|
||||
void MainWindow::doLogin(const QString &errorMsg)
|
||||
{
|
||||
if (!m_selectedInstance)
|
||||
return;
|
||||
|
||||
LoginDialog* loginDlg = new LoginDialog(this, errorMsg);
|
||||
LoginDialog *loginDlg = new LoginDialog(this, errorMsg);
|
||||
if (!m_selectedInstance->lastLaunch())
|
||||
loginDlg->forceOnline();
|
||||
|
||||
loginDlg->exec();
|
||||
if(loginDlg->result() == QDialog::Accepted)
|
||||
if (loginDlg->result() == QDialog::Accepted)
|
||||
{
|
||||
if (loginDlg->isOnline())
|
||||
{
|
||||
UserInfo uInfo{loginDlg->getUsername(), loginDlg->getPassword()};
|
||||
|
||||
TaskDialog* tDialog = new TaskDialog(this);
|
||||
LoginTask* loginTask = new LoginTask(uInfo, tDialog);
|
||||
connect(loginTask, SIGNAL(succeeded()),SLOT(onLoginComplete()), Qt::QueuedConnection);
|
||||
connect(loginTask, SIGNAL(failed(QString)), SLOT(doLogin(QString)), Qt::QueuedConnection);
|
||||
ProgressDialog *tDialog = new ProgressDialog(this);
|
||||
LoginTask *loginTask = new LoginTask(uInfo, tDialog);
|
||||
connect(loginTask, SIGNAL(succeeded()), SLOT(onLoginComplete()),
|
||||
Qt::QueuedConnection);
|
||||
connect(loginTask, SIGNAL(failed(QString)), SLOT(doLogin(QString)),
|
||||
Qt::QueuedConnection);
|
||||
m_activeInst = m_selectedInstance;
|
||||
tDialog->exec(loginTask);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_activeLogin = {loginDlg->getUsername(), QString("Offline"), qint64(-1)};
|
||||
QString user = loginDlg->getUsername();
|
||||
if (user.length() == 0)
|
||||
user = QString("Player");
|
||||
m_activeLogin = {user, QString("Offline"), user, QString()};
|
||||
m_activeInst = m_selectedInstance;
|
||||
launchInstance(m_activeInst, m_activeLogin);
|
||||
}
|
||||
@ -497,22 +500,63 @@ void MainWindow::doLogin(const QString& errorMsg)
|
||||
|
||||
void MainWindow::onLoginComplete()
|
||||
{
|
||||
if(!m_activeInst)
|
||||
if (!m_activeInst)
|
||||
return;
|
||||
LoginTask * task = (LoginTask *) QObject::sender();
|
||||
LoginTask *task = (LoginTask *)QObject::sender();
|
||||
m_activeLogin = task->getResult();
|
||||
|
||||
BaseUpdate *updateTask = m_activeInst->doUpdate();
|
||||
if(!updateTask)
|
||||
if (!updateTask)
|
||||
{
|
||||
launchInstance(m_activeInst, m_activeLogin);
|
||||
}
|
||||
else
|
||||
{
|
||||
TaskDialog *tDialog = new TaskDialog(this);
|
||||
connect(updateTask, SIGNAL(succeeded()),SLOT(onGameUpdateComplete()));
|
||||
ProgressDialog tDialog(this);
|
||||
connect(updateTask, SIGNAL(succeeded()), SLOT(onGameUpdateComplete()));
|
||||
connect(updateTask, SIGNAL(failed(QString)), SLOT(onGameUpdateError(QString)));
|
||||
tDialog->exec(updateTask);
|
||||
tDialog.exec(updateTask);
|
||||
delete updateTask;
|
||||
}
|
||||
|
||||
auto job = new DownloadJob("Player skin: " + m_activeLogin.player_name);
|
||||
|
||||
auto meta = MMC->metacache()->resolveEntry("skins", m_activeLogin.player_name + ".png");
|
||||
job->addCacheDownload(QUrl("http://skins.minecraft.net/MinecraftSkins/" + m_activeLogin.player_name + ".png"), meta);
|
||||
meta->stale = true;
|
||||
|
||||
job->start();
|
||||
auto filename = MMC->metacache()->resolveEntry("skins", "skins.json")->getFullPath();
|
||||
QFile listFile(filename);
|
||||
|
||||
// Add skin mapping
|
||||
QByteArray data;
|
||||
{
|
||||
if(!listFile.open(QIODevice::ReadWrite))
|
||||
{
|
||||
QLOG_ERROR() << "Failed to open/make skins list JSON";
|
||||
return;
|
||||
}
|
||||
|
||||
data = listFile.readAll();
|
||||
}
|
||||
|
||||
QJsonParseError jsonError;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError);
|
||||
QJsonObject root = jsonDoc.object();
|
||||
QJsonObject mappings = root.value("mappings").toObject();
|
||||
QJsonArray usernames = mappings.value(m_activeLogin.username).toArray();
|
||||
|
||||
if(!usernames.contains(m_activeLogin.player_name))
|
||||
{
|
||||
usernames.prepend(m_activeLogin.player_name);
|
||||
mappings[m_activeLogin.username] = usernames;
|
||||
root["mappings"] = mappings;
|
||||
jsonDoc.setObject(root);
|
||||
|
||||
// QJson hack - shouldn't have to clear the file every time a save happens
|
||||
listFile.resize(0);
|
||||
listFile.write(jsonDoc.toJson());
|
||||
}
|
||||
}
|
||||
|
||||
@ -530,14 +574,26 @@ void MainWindow::launchInstance(BaseInstance *instance, LoginResponse response)
|
||||
{
|
||||
Q_ASSERT_X(instance != NULL, "launchInstance", "instance is NULL");
|
||||
|
||||
proc = instance->prepareForLaunch(response.username, response.sessionID);
|
||||
if(!proc)
|
||||
proc = instance->prepareForLaunch(response);
|
||||
if (!proc)
|
||||
return;
|
||||
|
||||
console = new ConsoleWindow();
|
||||
// Prepare GUI: If it shall stay open disable the required parts
|
||||
if (MMC->settings()->get("NoHide").toBool())
|
||||
{
|
||||
ui->actionLaunchInstance->setEnabled(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->hide();
|
||||
}
|
||||
|
||||
console = new ConsoleWindow(proc);
|
||||
console->show();
|
||||
connect(proc, SIGNAL(log(QString, MessageLevel::Enum)),
|
||||
console, SLOT(write(QString, MessageLevel::Enum)));
|
||||
connect(proc, SIGNAL(log(QString, MessageLevel::Enum)), console,
|
||||
SLOT(write(QString, MessageLevel::Enum)));
|
||||
connect(proc, SIGNAL(ended()), this, SLOT(instanceEnded()));
|
||||
proc->setLogin(response.username, response.session_id);
|
||||
proc->launch();
|
||||
}
|
||||
|
||||
@ -560,23 +616,27 @@ void MainWindow::startTask(Task *task)
|
||||
connect(task, SIGNAL(started()), SLOT(taskStart()));
|
||||
connect(task, SIGNAL(succeeded()), SLOT(taskEnd()));
|
||||
connect(task, SIGNAL(failed(QString)), SLOT(taskEnd()));
|
||||
task->startTask();
|
||||
task->start();
|
||||
}
|
||||
|
||||
|
||||
// Create A Desktop Shortcut
|
||||
void MainWindow::on_actionMakeDesktopShortcut_triggered()
|
||||
{
|
||||
QString name ( "Test" );
|
||||
name = QInputDialog::getText ( this, tr ( "MultiMC Shortcut" ), tr ( "Enter a Shortcut Name." ), QLineEdit::Normal, name );
|
||||
QString name("Test");
|
||||
name = QInputDialog::getText(this, tr("MultiMC Shortcut"), tr("Enter a Shortcut Name."),
|
||||
QLineEdit::Normal, name);
|
||||
|
||||
Util::createShortCut ( Util::getDesktopDir(), QApplication::instance()->applicationFilePath(), QStringList() << "-dl" << QDir::currentPath() << "test", name, "application-x-octet-stream" );
|
||||
Util::createShortCut(Util::getDesktopDir(), QApplication::instance()->applicationFilePath(),
|
||||
QStringList() << "-dl" << QDir::currentPath() << "test", name,
|
||||
"application-x-octet-stream");
|
||||
|
||||
QMessageBox::warning ( this, "Not useful", "A Dummy Shortcut was created. it will not do anything productive" );
|
||||
QMessageBox::warning(
|
||||
this, tr("Not useful"),
|
||||
tr("A Dummy Shortcut was created. it will not do anything productive"));
|
||||
}
|
||||
|
||||
// BrowserDialog
|
||||
void MainWindow::openWebPage ( QUrl url )
|
||||
void MainWindow::openWebPage(QUrl url)
|
||||
{
|
||||
QDesktopServices::openUrl(url);
|
||||
}
|
||||
@ -586,10 +646,22 @@ void MainWindow::on_actionChangeInstMCVersion_triggered()
|
||||
if (view->selectionModel()->selectedIndexes().count() < 1)
|
||||
return;
|
||||
|
||||
VersionSelectDialog vselect(m_selectedInstance->versionList(), this);
|
||||
VersionSelectDialog vselect(m_selectedInstance->versionList().get(),
|
||||
tr("Change Minecraft version"), this);
|
||||
vselect.setFilter(1, "OneSix");
|
||||
if (vselect.exec() && vselect.selectedVersion())
|
||||
{
|
||||
m_selectedInstance->setIntendedVersionId(vselect.selectedVersion()->descriptor);
|
||||
if (m_selectedInstance->versionIsCustom())
|
||||
{
|
||||
auto result = QMessageBox::warning(
|
||||
this, tr("Are you sure?"),
|
||||
tr("This will remove any library/version customization you did previously. "
|
||||
"This includes things like Forge install and similar."),
|
||||
QMessageBox::Ok, QMessageBox::Abort);
|
||||
if (result != QMessageBox::Ok)
|
||||
return;
|
||||
}
|
||||
m_selectedInstance->setIntendedVersionId(vselect.selectedVersion()->descriptor());
|
||||
}
|
||||
}
|
||||
|
||||
@ -602,7 +674,7 @@ void MainWindow::on_actionChangeInstLWJGLVersion_triggered()
|
||||
lselect.exec();
|
||||
if (lselect.result() == QDialog::Accepted)
|
||||
{
|
||||
LegacyInstance * linst = (LegacyInstance *) m_selectedInstance;
|
||||
LegacyInstance *linst = (LegacyInstance *)m_selectedInstance;
|
||||
linst->setLWJGLVersion(lselect.selectedVersion());
|
||||
}
|
||||
}
|
||||
@ -617,18 +689,25 @@ void MainWindow::on_actionInstanceSettings_triggered()
|
||||
settings.exec();
|
||||
}
|
||||
|
||||
void MainWindow::instanceChanged( const QModelIndex& current, const QModelIndex& previous )
|
||||
void MainWindow::instanceChanged(const QModelIndex ¤t, const QModelIndex &previous)
|
||||
{
|
||||
if(current.isValid() && nullptr != (m_selectedInstance = (BaseInstance *) current.data(InstanceList::InstancePointerRole).value<void *>()))
|
||||
if (current.isValid() &&
|
||||
nullptr != (m_selectedInstance =
|
||||
(BaseInstance *)current.data(InstanceList::InstancePointerRole)
|
||||
.value<void *>()))
|
||||
{
|
||||
ui->instanceToolBar->setEnabled(true);
|
||||
QString iconKey = m_selectedInstance->iconKey();
|
||||
renameButton->setText(m_selectedInstance->name());
|
||||
ui->actionChangeInstLWJGLVersion->setEnabled(m_selectedInstance->menuActionEnabled("actionChangeInstLWJGLVersion"));
|
||||
ui->actionEditInstMods->setEnabled(m_selectedInstance->menuActionEnabled("actionEditInstMods"));
|
||||
ui->actionChangeInstLWJGLVersion->setEnabled(
|
||||
m_selectedInstance->menuActionEnabled("actionChangeInstLWJGLVersion"));
|
||||
ui->actionEditInstMods->setEnabled(
|
||||
m_selectedInstance->menuActionEnabled("actionEditInstMods"));
|
||||
ui->actionChangeInstMCVersion->setEnabled(
|
||||
m_selectedInstance->menuActionEnabled("actionChangeInstMCVersion"));
|
||||
statusBar()->clearMessage();
|
||||
statusBar()->showMessage(m_selectedInstance->getStatusbarDescription());
|
||||
auto ico =MMC->icons()->getIcon(iconKey);
|
||||
auto ico = MMC->icons()->getIcon(iconKey);
|
||||
ui->actionChangeInstIcon->setIcon(ico);
|
||||
}
|
||||
else
|
||||
@ -643,18 +722,16 @@ void MainWindow::selectionBad()
|
||||
QString iconKey = "infinity";
|
||||
statusBar()->clearMessage();
|
||||
ui->instanceToolBar->setEnabled(false);
|
||||
renameButton->setText("Rename Instance");
|
||||
renameButton->setText(tr("Rename Instance"));
|
||||
auto ico = MMC->icons()->getIcon(iconKey);
|
||||
ui->actionChangeInstIcon->setIcon(ico);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MainWindow::on_actionEditInstNotes_triggered()
|
||||
{
|
||||
if (!m_selectedInstance)
|
||||
return;
|
||||
LegacyInstance * linst = (LegacyInstance *) m_selectedInstance;
|
||||
LegacyInstance *linst = (LegacyInstance *)m_selectedInstance;
|
||||
|
||||
EditNotesDialog noteedit(linst->notes(), linst->name(), this);
|
||||
noteedit.exec();
|
||||
@ -664,3 +741,57 @@ void MainWindow::on_actionEditInstNotes_triggered()
|
||||
linst->setNotes(noteedit.getText());
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::instanceEnded()
|
||||
{
|
||||
this->show();
|
||||
ui->actionLaunchInstance->setEnabled(m_selectedInstance);
|
||||
}
|
||||
|
||||
void MainWindow::checkSetDefaultJava()
|
||||
{
|
||||
bool askForJava = false;
|
||||
{
|
||||
QString currentHostName = QHostInfo::localHostName();
|
||||
QString oldHostName = MMC->settings()->get("LastHostname").toString();
|
||||
if (currentHostName != oldHostName)
|
||||
{
|
||||
MMC->settings()->set("LastHostname", currentHostName);
|
||||
askForJava = true;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
QString currentJavaPath = MMC->settings()->get("JavaPath").toString();
|
||||
if (currentJavaPath.isEmpty())
|
||||
{
|
||||
askForJava = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (askForJava)
|
||||
{
|
||||
QLOG_DEBUG() << "Java path needs resetting, showing Java selection dialog...";
|
||||
|
||||
JavaVersionPtr java;
|
||||
|
||||
VersionSelectDialog vselect(MMC->javalist().get(), tr("Select a Java version"), this,
|
||||
false);
|
||||
vselect.setResizeOn(2);
|
||||
vselect.exec();
|
||||
|
||||
if (!vselect.selectedVersion())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Invalid version selected"),
|
||||
tr("You didn't select a valid Java version, so MultiMC will "
|
||||
"select the default. "
|
||||
"You can change this in the settings dialog."));
|
||||
|
||||
JavaUtils ju;
|
||||
java = ju.GetDefaultJava();
|
||||
}
|
||||
|
||||
java = std::dynamic_pointer_cast<JavaVersion>(vselect.selectedVersion());
|
||||
MMC->settings()->set("JavaPath", java->path);
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include <QMainWindow>
|
||||
|
||||
#include "logic/lists/InstanceList.h"
|
||||
#include "logic/tasks/LoginTask.h"
|
||||
#include "logic/net/LoginTask.h"
|
||||
#include "logic/BaseInstance.h"
|
||||
|
||||
class LabeledToolButton;
|
||||
@ -49,6 +49,7 @@ public:
|
||||
// Browser Dialog
|
||||
void openWebPage(QUrl url);
|
||||
|
||||
void checkSetDefaultJava();
|
||||
|
||||
private slots:
|
||||
void onCatToggled(bool);
|
||||
@ -81,7 +82,7 @@ private slots:
|
||||
|
||||
void on_mainToolBar_visibilityChanged(bool);
|
||||
|
||||
void on_instanceView_customContextMenuRequested(const QPoint &pos);
|
||||
// void on_instanceView_customContextMenuRequested(const QPoint &pos);
|
||||
|
||||
void on_actionLaunchInstance_triggered();
|
||||
|
||||
@ -97,12 +98,10 @@ private slots:
|
||||
|
||||
void on_actionEditInstNotes_triggered();
|
||||
|
||||
void doLogin(const QString& errorMsg = "");
|
||||
|
||||
void doLogin(const QString &errorMsg = "");
|
||||
|
||||
void onLoginComplete();
|
||||
|
||||
|
||||
void onGameUpdateComplete();
|
||||
void onGameUpdateError(QString error);
|
||||
|
||||
@ -111,12 +110,14 @@ private slots:
|
||||
|
||||
void on_actionChangeInstLWJGLVersion_triggered();
|
||||
|
||||
void instanceEnded();
|
||||
|
||||
void on_actionInstanceSettings_triggered();
|
||||
|
||||
public slots:
|
||||
void instanceActivated ( QModelIndex );
|
||||
void instanceActivated(QModelIndex);
|
||||
|
||||
void instanceChanged (const QModelIndex & current,const QModelIndex & previous);
|
||||
void instanceChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
||||
|
||||
void selectionBad();
|
||||
|
||||
@ -127,15 +128,16 @@ public slots:
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *ev);
|
||||
void setCatBackground(bool enabled);
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
KCategoryDrawer * drawer;
|
||||
KCategorizedView * view;
|
||||
InstanceProxyModel * proxymodel;
|
||||
KCategoryDrawer *drawer;
|
||||
KCategorizedView *view;
|
||||
InstanceProxyModel *proxymodel;
|
||||
MinecraftProcess *proc;
|
||||
ConsoleWindow *console;
|
||||
OneSixAssets *assets_downloader;
|
||||
LabeledToolButton * renameButton;
|
||||
LabeledToolButton *renameButton;
|
||||
|
||||
BaseInstance *m_selectedInstance;
|
||||
|
||||
|
@ -13,6 +13,10 @@
|
||||
<property name="windowTitle">
|
||||
<string>MultiMC 5</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="../multimc.qrc">
|
||||
<normaloff>:/icons/multimc/scalable/apps/multimc.svg</normaloff>:/icons/multimc/scalable/apps/multimc.svg</iconset>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
@ -107,6 +111,7 @@
|
||||
<addaction name="actionChangeInstGroup"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionInstanceSettings"/>
|
||||
<addaction name="actionChangeInstMCVersion"/>
|
||||
<addaction name="actionChangeInstLWJGLVersion"/>
|
||||
<addaction name="actionEditInstMods"/>
|
||||
<addaction name="actionViewSelectedInstFolder"/>
|
||||
@ -371,9 +376,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionChangeInstMCVersion">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Change Version</string>
|
||||
</property>
|
||||
@ -440,7 +442,7 @@
|
||||
<string>Meow</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p align="center"><span style=" font-weight:600; color:#ff0004;">Catnatok!</span></p><p align="center">Or just a cat with a ball of yarn?</p><p align="center"><span style=" font-style:italic;">WHO KNOWS?!</span></p><p align="center"><img src=":/icons/instances/tnt"/></p></body></html></string>
|
||||
<string><html><head/><body><p align="center"><span style=" font-weight:600; color:#ff0004;">Catnarok!</span></p><p align="center">Or just a cat with a ball of yarn?</p><p align="center"><span style=" font-style:italic;">WHO KNOWS?!</span></p><p align="center"><img src=":/icons/instances/tnt"/></p></body></html></string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
|
@ -18,24 +18,23 @@
|
||||
#include "ui_newinstancedialog.h"
|
||||
|
||||
#include "logic/InstanceFactory.h"
|
||||
#include "logic/InstanceVersion.h"
|
||||
#include "logic/BaseVersion.h"
|
||||
#include "logic/lists/IconList.h"
|
||||
#include "logic/lists/MinecraftVersionList.h"
|
||||
#include "logic/tasks/Task.h"
|
||||
|
||||
#include "gui/platform.h"
|
||||
#include "versionselectdialog.h"
|
||||
#include "taskdialog.h"
|
||||
#include "ProgressDialog.h"
|
||||
#include "IconPickerDialog.h"
|
||||
|
||||
#include <QLayout>
|
||||
#include <QPushButton>
|
||||
|
||||
|
||||
|
||||
NewInstanceDialog::NewInstanceDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::NewInstanceDialog)
|
||||
NewInstanceDialog::NewInstanceDialog(QWidget *parent)
|
||||
: QDialog(parent), ui(new Ui::NewInstanceDialog)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
ui->setupUi(this);
|
||||
resize(minimumSizeHint());
|
||||
layout()->setSizeConstraint(QLayout::SetFixedSize);
|
||||
@ -48,7 +47,7 @@ NewInstanceDialog::NewInstanceDialog(QWidget *parent) :
|
||||
taskDlg->exec(loadTask);
|
||||
}
|
||||
*/
|
||||
setSelectedVersion(MinecraftVersionList::getMainList().getLatestStable());
|
||||
setSelectedVersion(MMC->minecraftlist()->getLatestStable());
|
||||
InstIconKey = "infinity";
|
||||
ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey));
|
||||
}
|
||||
@ -60,16 +59,17 @@ NewInstanceDialog::~NewInstanceDialog()
|
||||
|
||||
void NewInstanceDialog::updateDialogState()
|
||||
{
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!instName().isEmpty() && m_selectedVersion);
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)
|
||||
->setEnabled(!instName().isEmpty() && m_selectedVersion);
|
||||
}
|
||||
|
||||
void NewInstanceDialog::setSelectedVersion(InstVersionPtr version)
|
||||
void NewInstanceDialog::setSelectedVersion(BaseVersionPtr version)
|
||||
{
|
||||
m_selectedVersion = version;
|
||||
|
||||
if (m_selectedVersion)
|
||||
{
|
||||
ui->versionTextBox->setText(version->name);
|
||||
ui->versionTextBox->setText(version->name());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -89,18 +89,19 @@ QString NewInstanceDialog::iconKey() const
|
||||
return InstIconKey;
|
||||
}
|
||||
|
||||
InstVersionPtr NewInstanceDialog::selectedVersion() const
|
||||
BaseVersionPtr NewInstanceDialog::selectedVersion() const
|
||||
{
|
||||
return m_selectedVersion;
|
||||
}
|
||||
|
||||
void NewInstanceDialog::on_btnChangeVersion_clicked()
|
||||
{
|
||||
VersionSelectDialog vselect(&MinecraftVersionList::getMainList(), this);
|
||||
VersionSelectDialog vselect(MMC->minecraftlist().get(), tr("Change Minecraft version"),
|
||||
this);
|
||||
vselect.exec();
|
||||
if (vselect.result() == QDialog::Accepted)
|
||||
{
|
||||
InstVersionPtr version = vselect.selectedVersion();
|
||||
BaseVersionPtr version = vselect.selectedVersion();
|
||||
if (version)
|
||||
setSelectedVersion(version);
|
||||
}
|
||||
@ -111,7 +112,7 @@ void NewInstanceDialog::on_iconButton_clicked()
|
||||
IconPickerDialog dlg(this);
|
||||
dlg.exec(InstIconKey);
|
||||
|
||||
if(dlg.result() == QDialog::Accepted)
|
||||
if (dlg.result() == QDialog::Accepted)
|
||||
{
|
||||
InstIconKey = dlg.selectedIconKey;
|
||||
ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey));
|
||||
|
@ -17,7 +17,7 @@
|
||||
#define NEWINSTANCEDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include "logic/InstanceVersion.h"
|
||||
#include "logic/BaseVersion.h"
|
||||
|
||||
namespace Ui {
|
||||
class NewInstanceDialog;
|
||||
@ -33,13 +33,13 @@ public:
|
||||
|
||||
void updateDialogState();
|
||||
|
||||
void setSelectedVersion(InstVersionPtr version);
|
||||
void setSelectedVersion(BaseVersionPtr version);
|
||||
|
||||
void loadVersionList();
|
||||
|
||||
QString instName() const;
|
||||
QString iconKey() const;
|
||||
InstVersionPtr selectedVersion() const;
|
||||
BaseVersionPtr selectedVersion() const;
|
||||
|
||||
private slots:
|
||||
void on_btnChangeVersion_clicked();
|
||||
@ -49,7 +49,7 @@ private slots:
|
||||
private:
|
||||
Ui::NewInstanceDialog *ui;
|
||||
|
||||
InstVersionPtr m_selectedVersion;
|
||||
BaseVersionPtr m_selectedVersion;
|
||||
QString InstIconKey;
|
||||
};
|
||||
|
||||
|
35
gui/platform.h
Normal file
35
gui/platform.h
Normal file
@ -0,0 +1,35 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
*
|
||||
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_H
|
||||
#define PLATFORM_H
|
||||
|
||||
/**
|
||||
* @file platform.h
|
||||
* This file contains platform-specific functions, tweaks and fixes.
|
||||
*/
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class MultiMCPlatform
|
||||
{
|
||||
public:
|
||||
// X11 WM_CLASS
|
||||
static void fixWM_CLASS(QWidget *widget);
|
||||
};
|
||||
|
||||
#endif // PLATFORM_H
|
27
gui/platform_other.cpp
Normal file
27
gui/platform_other.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
*
|
||||
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <gui/platform.h>
|
||||
/**
|
||||
* Stub for non-X11 platforms
|
||||
* @brief MultiMCPlatform::fixWM_CLASS
|
||||
* @param widget
|
||||
*/
|
||||
void MultiMCPlatform::fixWM_CLASS(QWidget *widget)
|
||||
{
|
||||
Q_UNUSED(widget);
|
||||
}
|
62
gui/platform_x11.cpp
Normal file
62
gui/platform_x11.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
*
|
||||
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <gui/platform.h>
|
||||
#include <QtX11Extras/QX11Info>
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
static QByteArray WM_CLASS = "MultiMC5\0MultiMC5";
|
||||
|
||||
template <typename... ArgTypes, typename... ArgTypes2>
|
||||
static inline unsigned int XcbCallVoid(xcb_void_cookie_t (*func)(xcb_connection_t *, ArgTypes...), ArgTypes2... args...)
|
||||
{
|
||||
return func(QX11Info::connection(), args...).sequence;
|
||||
}
|
||||
|
||||
static void getAtoms(size_t n, xcb_atom_t *atoms, const char *const names[], bool create)
|
||||
{
|
||||
xcb_connection_t *conn = QX11Info::connection();
|
||||
xcb_intern_atom_cookie_t *cookies = (xcb_intern_atom_cookie_t *)malloc(sizeof(xcb_intern_atom_cookie_t) * 2);
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
cookies[i] = xcb_intern_atom(conn, create, strlen(names[i]), names[i]);
|
||||
memset(atoms, 0, sizeof(xcb_atom_t) * n);
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
{
|
||||
xcb_intern_atom_reply_t *r = xcb_intern_atom_reply(conn, cookies[i], 0);
|
||||
if (r)
|
||||
{
|
||||
atoms[i] = r->atom;
|
||||
free(r);
|
||||
}
|
||||
}
|
||||
free(cookies);
|
||||
}
|
||||
|
||||
static inline xcb_atom_t getAtom(const char *name, bool create=false)
|
||||
{
|
||||
xcb_atom_t atom;
|
||||
getAtoms(1, &atom, &name, create);
|
||||
return atom;
|
||||
}
|
||||
|
||||
void MultiMCPlatform::fixWM_CLASS(QWidget *widget)
|
||||
{
|
||||
static const xcb_atom_t atom = getAtom("WM_CLASS");
|
||||
XcbCallVoid(xcb_change_property, XCB_PROP_MODE_REPLACE,
|
||||
widget->winId(), atom, XCB_ATOM_STRING, 8, WM_CLASS.count(),
|
||||
WM_CLASS.constData());
|
||||
}
|
@ -13,10 +13,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <MultiMC.h>
|
||||
#include "settingsdialog.h"
|
||||
#include "ui_settingsdialog.h"
|
||||
#include "logic/JavaUtils.h"
|
||||
#include "gui/versionselectdialog.h"
|
||||
#include "gui/platform.h"
|
||||
#include "logic/lists/JavaVersionList.h"
|
||||
|
||||
#include <MultiMC.h>
|
||||
#include <settingsobject.h>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
@ -25,9 +29,10 @@ SettingsDialog::SettingsDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::SettingsDialog)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
ui->setupUi(this);
|
||||
|
||||
loadSettings(MMC->settings());
|
||||
loadSettings(MMC->settings().get());
|
||||
updateCheckboxStuff();
|
||||
}
|
||||
|
||||
@ -49,7 +54,7 @@ void SettingsDialog::updateCheckboxStuff()
|
||||
|
||||
void SettingsDialog::on_instDirBrowseBtn_clicked()
|
||||
{
|
||||
QString dir = QFileDialog::getExistingDirectory(this, "Instance Directory",
|
||||
QString dir = QFileDialog::getExistingDirectory(this, tr("Instance Directory"),
|
||||
ui->instDirTextBox->text());
|
||||
if (!dir.isEmpty())
|
||||
ui->instDirTextBox->setText(dir);
|
||||
@ -57,7 +62,7 @@ void SettingsDialog::on_instDirBrowseBtn_clicked()
|
||||
|
||||
void SettingsDialog::on_modsDirBrowseBtn_clicked()
|
||||
{
|
||||
QString dir = QFileDialog::getExistingDirectory(this, "Mods Directory",
|
||||
QString dir = QFileDialog::getExistingDirectory(this, tr("Mods Directory"),
|
||||
ui->modsDirTextBox->text());
|
||||
if (!dir.isEmpty())
|
||||
ui->modsDirTextBox->setText(dir);
|
||||
@ -65,7 +70,7 @@ void SettingsDialog::on_modsDirBrowseBtn_clicked()
|
||||
|
||||
void SettingsDialog::on_lwjglDirBrowseBtn_clicked()
|
||||
{
|
||||
QString dir = QFileDialog::getExistingDirectory(this, "LWJGL Directory",
|
||||
QString dir = QFileDialog::getExistingDirectory(this, tr("LWJGL Directory"),
|
||||
ui->lwjglDirTextBox->text());
|
||||
if (!dir.isEmpty())
|
||||
ui->lwjglDirTextBox->setText(dir);
|
||||
@ -85,7 +90,7 @@ void SettingsDialog::on_maximizedCheckBox_clicked(bool checked)
|
||||
|
||||
void SettingsDialog::on_buttonBox_accepted()
|
||||
{
|
||||
applySettings(MMC->settings());
|
||||
applySettings(MMC->settings().get());
|
||||
}
|
||||
|
||||
void SettingsDialog::applySettings(SettingsObject *s)
|
||||
@ -99,9 +104,9 @@ void SettingsDialog::applySettings(SettingsObject *s)
|
||||
}
|
||||
else if (!s->get("UseDevBuilds").toBool())
|
||||
{
|
||||
int response = QMessageBox::question(this, "Development builds",
|
||||
"Development builds contain experimental features "
|
||||
"and may be unstable. Are you sure you want to enable them?");
|
||||
int response = QMessageBox::question(this, tr("Development builds"),
|
||||
tr("Development builds contain experimental features "
|
||||
"and may be unstable. Are you sure you want to enable them?"));
|
||||
if (response == QMessageBox::Yes)
|
||||
{
|
||||
s->set("UseDevBuilds", true);
|
||||
@ -180,3 +185,27 @@ void SettingsDialog::loadSettings(SettingsObject *s)
|
||||
ui->preLaunchCmdTextBox->setText(s->get("PreLaunchCommand").toString());
|
||||
ui->postExitCmdTextBox->setText(s->get("PostExitCommand").toString());
|
||||
}
|
||||
|
||||
void SettingsDialog::on_pushButton_clicked()
|
||||
{
|
||||
JavaVersionPtr java;
|
||||
|
||||
VersionSelectDialog vselect(MMC->javalist().get(), tr("Select a Java version"), this, true);
|
||||
vselect.setResizeOn(2);
|
||||
vselect.exec();
|
||||
|
||||
if (vselect.result() == QDialog::Accepted && vselect.selectedVersion())
|
||||
{
|
||||
java = std::dynamic_pointer_cast<JavaVersion>(vselect.selectedVersion());
|
||||
ui->javaPathTextBox->setText(java->path);
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsDialog::on_btnBrowse_clicked()
|
||||
{
|
||||
QString dir = QFileDialog::getOpenFileName(this, tr("Find Java executable"));
|
||||
if(!dir.isNull())
|
||||
{
|
||||
ui->javaPathTextBox->setText(dir);
|
||||
}
|
||||
}
|
||||
|
@ -53,6 +53,10 @@ private slots:
|
||||
|
||||
void on_buttonBox_accepted();
|
||||
|
||||
void on_pushButton_clicked();
|
||||
|
||||
void on_btnBrowse_clicked();
|
||||
|
||||
private:
|
||||
Ui::SettingsDialog *ui;
|
||||
};
|
||||
|
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>453</width>
|
||||
<height>550</height>
|
||||
<width>502</width>
|
||||
<height>599</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -353,7 +353,7 @@
|
||||
<number>64</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>512</number>
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>8</number>
|
||||
@ -374,29 +374,60 @@
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelJavaPath">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Java path:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="javaPathTextBox"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelJVMArgs">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>JVM arguments:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<item row="1" column="3">
|
||||
<widget class="QPushButton" name="btnBrowse">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Auto-detect</string>
|
||||
<string>Browse...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="2">
|
||||
<item row="0" column="1" colspan="3">
|
||||
<widget class="QLineEdit" name="javaPathTextBox"/>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Auto-detect...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="3">
|
||||
<widget class="QLineEdit" name="jvmArgsTextBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
@ -466,6 +497,35 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>settingsTabs</tabstop>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
<tabstop>sortLastLaunchedBtn</tabstop>
|
||||
<tabstop>sortByNameBtn</tabstop>
|
||||
<tabstop>devBuildsCheckBox</tabstop>
|
||||
<tabstop>autoUpdateCheckBox</tabstop>
|
||||
<tabstop>instDirTextBox</tabstop>
|
||||
<tabstop>modsDirTextBox</tabstop>
|
||||
<tabstop>lwjglDirTextBox</tabstop>
|
||||
<tabstop>instDirBrowseBtn</tabstop>
|
||||
<tabstop>modsDirBrowseBtn</tabstop>
|
||||
<tabstop>lwjglDirBrowseBtn</tabstop>
|
||||
<tabstop>maximizedCheckBox</tabstop>
|
||||
<tabstop>windowWidthSpinBox</tabstop>
|
||||
<tabstop>windowHeightSpinBox</tabstop>
|
||||
<tabstop>showConsoleCheck</tabstop>
|
||||
<tabstop>autoCloseConsoleCheck</tabstop>
|
||||
<tabstop>autoLoginCheckBox</tabstop>
|
||||
<tabstop>minMemSpinBox</tabstop>
|
||||
<tabstop>maxMemSpinBox</tabstop>
|
||||
<tabstop>permGenSpinBox</tabstop>
|
||||
<tabstop>javaPathTextBox</tabstop>
|
||||
<tabstop>pushButton</tabstop>
|
||||
<tabstop>btnBrowse</tabstop>
|
||||
<tabstop>jvmArgsTextBox</tabstop>
|
||||
<tabstop>preLaunchCmdTextBox</tabstop>
|
||||
<tabstop>postExitCmdTextBox</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../multimc.qrc"/>
|
||||
</resources>
|
||||
|
@ -20,18 +20,20 @@
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <gui/taskdialog.h>
|
||||
#include <gui/ProgressDialog.h>
|
||||
#include "gui/platform.h"
|
||||
|
||||
#include <logic/InstanceVersion.h>
|
||||
#include <logic/lists/InstVersionList.h>
|
||||
#include <logic/BaseVersion.h>
|
||||
#include <logic/lists/BaseVersionList.h>
|
||||
#include <logic/tasks/Task.h>
|
||||
|
||||
VersionSelectDialog::VersionSelectDialog(InstVersionList *vlist, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::VersionSelectDialog)
|
||||
VersionSelectDialog::VersionSelectDialog(BaseVersionList *vlist, QString title, QWidget *parent, bool cancelable)
|
||||
: QDialog(parent), ui(new Ui::VersionSelectDialog)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
ui->setupUi(this);
|
||||
setWindowModality(Qt::WindowModal);
|
||||
setWindowTitle(title);
|
||||
|
||||
m_vlist = vlist;
|
||||
|
||||
@ -40,12 +42,12 @@ VersionSelectDialog::VersionSelectDialog(InstVersionList *vlist, QWidget *parent
|
||||
|
||||
ui->listView->setModel(m_proxyModel);
|
||||
ui->listView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
ui->listView->header()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
ui->listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::Stretch);
|
||||
|
||||
connect(ui->filterSnapshotsCheckbox, SIGNAL(clicked()), SLOT(updateFilterState()));
|
||||
connect(ui->filterMCNostalgiaCheckbox, SIGNAL(clicked()), SLOT(updateFilterState()));
|
||||
|
||||
updateFilterState();
|
||||
if(!cancelable)
|
||||
{
|
||||
ui->buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
VersionSelectDialog::~VersionSelectDialog()
|
||||
@ -53,6 +55,13 @@ VersionSelectDialog::~VersionSelectDialog()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void VersionSelectDialog::setResizeOn(int column)
|
||||
{
|
||||
ui->listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::ResizeToContents);
|
||||
resizeOnColumn = column;
|
||||
ui->listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::Stretch);
|
||||
}
|
||||
|
||||
int VersionSelectDialog::exec()
|
||||
{
|
||||
QDialog::open();
|
||||
@ -63,17 +72,17 @@ int VersionSelectDialog::exec()
|
||||
|
||||
void VersionSelectDialog::loadList()
|
||||
{
|
||||
TaskDialog *taskDlg = new TaskDialog(this);
|
||||
ProgressDialog *taskDlg = new ProgressDialog(this);
|
||||
Task *loadTask = m_vlist->getLoadTask();
|
||||
loadTask->setParent(taskDlg);
|
||||
taskDlg->exec(loadTask);
|
||||
}
|
||||
|
||||
InstVersionPtr VersionSelectDialog::selectedVersion() const
|
||||
BaseVersionPtr VersionSelectDialog::selectedVersion() const
|
||||
{
|
||||
auto currentIndex = ui->listView->selectionModel()->currentIndex();
|
||||
auto variant = m_proxyModel->data(currentIndex, InstVersionList::VersionPointerRole);
|
||||
return variant.value<InstVersionPtr>();
|
||||
auto variant = m_proxyModel->data(currentIndex, BaseVersionList::VersionPointerRole);
|
||||
return variant.value<BaseVersionPtr>();
|
||||
}
|
||||
|
||||
void VersionSelectDialog::on_refreshButton_clicked()
|
||||
@ -81,10 +90,11 @@ void VersionSelectDialog::on_refreshButton_clicked()
|
||||
loadList();
|
||||
}
|
||||
|
||||
void VersionSelectDialog::updateFilterState()
|
||||
void VersionSelectDialog::setFilter(int column, QString filter)
|
||||
{
|
||||
m_proxyModel->setFilterKeyColumn(InstVersionList::TypeColumn);
|
||||
|
||||
m_proxyModel->setFilterKeyColumn(column);
|
||||
m_proxyModel->setFilterFixedString(filter);
|
||||
/*
|
||||
QStringList filteredTypes;
|
||||
if (!ui->filterSnapshotsCheckbox->isChecked())
|
||||
filteredTypes += "Snapshot";
|
||||
@ -95,7 +105,6 @@ void VersionSelectDialog::updateFilterState()
|
||||
if (filteredTypes.length() > 0)
|
||||
regexStr = QString("^((?!%1).)*$").arg(filteredTypes.join('|'));
|
||||
|
||||
qDebug() << "Filter:" << regexStr;
|
||||
|
||||
m_proxyModel->setFilterRegExp(regexStr);
|
||||
QLOG_DEBUG() << "Filter:" << regexStr;
|
||||
*/
|
||||
}
|
||||
|
@ -19,9 +19,9 @@
|
||||
#include <QDialog>
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
#include "logic/InstanceVersion.h"
|
||||
#include "logic/BaseVersion.h"
|
||||
|
||||
class InstVersionList;
|
||||
class BaseVersionList;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
@ -33,7 +33,7 @@ class VersionSelectDialog : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit VersionSelectDialog(InstVersionList *vlist, QWidget *parent = 0);
|
||||
explicit VersionSelectDialog(BaseVersionList *vlist, QString title, QWidget *parent = 0, bool cancelable = true);
|
||||
~VersionSelectDialog();
|
||||
|
||||
virtual int exec();
|
||||
@ -41,19 +41,21 @@ public:
|
||||
//! Starts a task that loads the list.
|
||||
void loadList();
|
||||
|
||||
InstVersionPtr selectedVersion() const;
|
||||
BaseVersionPtr selectedVersion() const;
|
||||
|
||||
void setFilter(int column, QString filter);
|
||||
void setResizeOn(int column);
|
||||
|
||||
private slots:
|
||||
void on_refreshButton_clicked();
|
||||
|
||||
void updateFilterState();
|
||||
|
||||
private:
|
||||
Ui::VersionSelectDialog *ui;
|
||||
|
||||
InstVersionList *m_vlist;
|
||||
BaseVersionList *m_vlist;
|
||||
|
||||
QSortFilterProxyModel *m_proxyModel;
|
||||
|
||||
int resizeOnColumn = 0;
|
||||
};
|
||||
|
||||
#endif // VERSIONSELECTDIALOG_H
|
||||
|
@ -39,75 +39,6 @@
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="filterCheckboxLayout1">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="filterSnapshotsCheckbox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show &snapshots?</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="filterMCNostalgiaCheckbox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show &Nostalgia?</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
|
52
logger/QsDebugOutput.cpp
Normal file
52
logger/QsDebugOutput.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright (c) 2010, Razvan Petru
|
||||
// All rights reserved.
|
||||
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
|
||||
// * Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice, this
|
||||
// list of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
// * The name of the contributors may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
// OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "QsDebugOutput.h"
|
||||
#include <QString>
|
||||
#include <QtGlobal>
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
void QsDebugOutput::output(const QString &message)
|
||||
{
|
||||
OutputDebugStringW(reinterpret_cast<const WCHAR *>(message.utf16()));
|
||||
OutputDebugStringW(L"\n");
|
||||
}
|
||||
#elif defined(Q_OS_SYMBIAN)
|
||||
#include <e32debug.h>
|
||||
void QsDebugOutput::output(const QString &message)
|
||||
{
|
||||
TPtrC8 symbianMessage(reinterpret_cast<const TUint8 *>(qPrintable(message)));
|
||||
RDebug::RawPrint(symbianMessage);
|
||||
}
|
||||
#elif defined(Q_OS_UNIX)
|
||||
#include <cstdio>
|
||||
void QsDebugOutput::output(const QString &message)
|
||||
{
|
||||
fprintf(stderr, "%s\n", qPrintable(message));
|
||||
fflush(stderr);
|
||||
}
|
||||
#endif
|
34
logger/QsDebugOutput.h
Normal file
34
logger/QsDebugOutput.h
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2010, Razvan Petru
|
||||
// All rights reserved.
|
||||
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
|
||||
// * Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice, this
|
||||
// list of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
// * The name of the contributors may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
// OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
|
||||
class QString;
|
||||
|
||||
class QsDebugOutput
|
||||
{
|
||||
public:
|
||||
static void output(const QString &a_message);
|
||||
};
|
137
logger/QsLog.cpp
Normal file
137
logger/QsLog.cpp
Normal file
@ -0,0 +1,137 @@
|
||||
// Copyright (c) 2010, Razvan Petru
|
||||
// All rights reserved.
|
||||
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
|
||||
// * Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice, this
|
||||
// list of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
// * The name of the contributors may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
// OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "QsLog.h"
|
||||
#include "QsLogDest.h"
|
||||
#include <QMutex>
|
||||
#include <QList>
|
||||
#include <QDateTime>
|
||||
#include <QtGlobal>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace QsLogging
|
||||
{
|
||||
typedef QList<Destination *> DestinationList;
|
||||
|
||||
static const char *LevelStrings[] = {"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"
|
||||
"UNKNOWN"};
|
||||
|
||||
// not using Qt::ISODate because we need the milliseconds too
|
||||
static const QString fmtDateTime("hhhh:mm:ss.zzz");
|
||||
|
||||
static const char *LevelToText(Level theLevel)
|
||||
{
|
||||
if (theLevel > FatalLevel)
|
||||
{
|
||||
assert(!"bad log level");
|
||||
return LevelStrings[UnknownLevel];
|
||||
}
|
||||
return LevelStrings[theLevel];
|
||||
}
|
||||
|
||||
class LoggerImpl
|
||||
{
|
||||
public:
|
||||
LoggerImpl() : level(InfoLevel)
|
||||
{
|
||||
}
|
||||
QMutex logMutex;
|
||||
Level level;
|
||||
DestinationList destList;
|
||||
};
|
||||
|
||||
Logger::Logger() : d(new LoggerImpl)
|
||||
{
|
||||
}
|
||||
|
||||
Logger::~Logger()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
void Logger::addDestination(Destination *destination)
|
||||
{
|
||||
assert(destination);
|
||||
d->destList.push_back(destination);
|
||||
}
|
||||
|
||||
void Logger::setLoggingLevel(Level newLevel)
|
||||
{
|
||||
d->level = newLevel;
|
||||
}
|
||||
|
||||
Level Logger::loggingLevel() const
|
||||
{
|
||||
return d->level;
|
||||
}
|
||||
|
||||
//! creates the complete log message and passes it to the logger
|
||||
void Logger::Helper::writeToLog()
|
||||
{
|
||||
const char *const levelName = LevelToText(level);
|
||||
const QString completeMessage(QString("%1\t%2").arg(levelName, 5).arg(buffer));
|
||||
|
||||
Logger &logger = Logger::instance();
|
||||
QMutexLocker lock(&logger.d->logMutex);
|
||||
logger.write(completeMessage);
|
||||
}
|
||||
|
||||
Logger::Helper::Helper(Level logLevel) : level(logLevel), qtDebug(&buffer)
|
||||
{
|
||||
}
|
||||
|
||||
Logger::Helper::~Helper()
|
||||
{
|
||||
try
|
||||
{
|
||||
writeToLog();
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
// you shouldn't throw exceptions from a sink
|
||||
Q_UNUSED(e);
|
||||
assert(!"exception in logger helper destructor");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
//! sends the message to all the destinations
|
||||
void Logger::write(const QString &message)
|
||||
{
|
||||
for (DestinationList::iterator it = d->destList.begin(), endIt = d->destList.end();
|
||||
it != endIt; ++it)
|
||||
{
|
||||
if (!(*it))
|
||||
{
|
||||
assert(!"null log destination");
|
||||
continue;
|
||||
}
|
||||
(*it)->write(message);
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace
|
130
logger/QsLog.h
Normal file
130
logger/QsLog.h
Normal file
@ -0,0 +1,130 @@
|
||||
// Copyright (c) 2010, Razvan Petru
|
||||
// All rights reserved.
|
||||
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
|
||||
// * Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice, this
|
||||
// list of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
// * The name of the contributors may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
// OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QDebug>
|
||||
#include <QString>
|
||||
|
||||
namespace QsLogging
|
||||
{
|
||||
class Destination;
|
||||
enum Level
|
||||
{
|
||||
TraceLevel = 0,
|
||||
DebugLevel,
|
||||
InfoLevel,
|
||||
WarnLevel,
|
||||
ErrorLevel,
|
||||
FatalLevel,
|
||||
UnknownLevel
|
||||
};
|
||||
|
||||
class LoggerImpl; // d pointer
|
||||
class Logger
|
||||
{
|
||||
public:
|
||||
static Logger &instance()
|
||||
{
|
||||
static Logger staticLog;
|
||||
return staticLog;
|
||||
}
|
||||
|
||||
//! Adds a log message destination. Don't add null destinations.
|
||||
void addDestination(Destination *destination);
|
||||
//! Logging at a level < 'newLevel' will be ignored
|
||||
void setLoggingLevel(Level newLevel);
|
||||
//! The default level is INFO
|
||||
Level loggingLevel() const;
|
||||
|
||||
//! The helper forwards the streaming to QDebug and builds the final
|
||||
//! log message.
|
||||
class Helper
|
||||
{
|
||||
public:
|
||||
explicit Helper(Level logLevel);
|
||||
~Helper();
|
||||
QDebug &stream()
|
||||
{
|
||||
return qtDebug;
|
||||
}
|
||||
|
||||
private:
|
||||
void writeToLog();
|
||||
|
||||
Level level;
|
||||
QString buffer;
|
||||
QDebug qtDebug;
|
||||
};
|
||||
|
||||
private:
|
||||
Logger();
|
||||
Logger(const Logger &);
|
||||
Logger &operator=(const Logger &);
|
||||
~Logger();
|
||||
|
||||
void write(const QString &message);
|
||||
|
||||
LoggerImpl *d;
|
||||
};
|
||||
|
||||
} // end namespace
|
||||
|
||||
#define QLOG_TRACE() \
|
||||
if (QsLogging::Logger::instance().loggingLevel() <= QsLogging::TraceLevel) \
|
||||
QsLogging::Logger::Helper(QsLogging::TraceLevel).stream()
|
||||
#define QLOG_DEBUG() \
|
||||
if (QsLogging::Logger::instance().loggingLevel() <= QsLogging::DebugLevel) \
|
||||
QsLogging::Logger::Helper(QsLogging::DebugLevel).stream()
|
||||
#define QLOG_INFO() \
|
||||
if (QsLogging::Logger::instance().loggingLevel() <= QsLogging::InfoLevel) \
|
||||
QsLogging::Logger::Helper(QsLogging::InfoLevel).stream()
|
||||
#define QLOG_WARN() \
|
||||
if (QsLogging::Logger::instance().loggingLevel() <= QsLogging::WarnLevel) \
|
||||
QsLogging::Logger::Helper(QsLogging::WarnLevel).stream()
|
||||
#define QLOG_ERROR() \
|
||||
if (QsLogging::Logger::instance().loggingLevel() <= QsLogging::ErrorLevel) \
|
||||
QsLogging::Logger::Helper(QsLogging::ErrorLevel).stream()
|
||||
#define QLOG_FATAL() QsLogging::Logger::Helper(QsLogging::FatalLevel).stream()
|
||||
|
||||
/*
|
||||
#define QLOG_TRACE() \
|
||||
if (QsLogging::Logger::instance().loggingLevel() <= QsLogging::TraceLevel) \
|
||||
QsLogging::Logger::Helper(QsLogging::TraceLevel).stream() << __FILE__ << '@' << __LINE__
|
||||
#define QLOG_DEBUG() \
|
||||
if (QsLogging::Logger::instance().loggingLevel() <= QsLogging::DebugLevel) \
|
||||
QsLogging::Logger::Helper(QsLogging::DebugLevel).stream() << __FILE__ << '@' << __LINE__
|
||||
#define QLOG_INFO() \
|
||||
if (QsLogging::Logger::instance().loggingLevel() <= QsLogging::InfoLevel) \
|
||||
QsLogging::Logger::Helper(QsLogging::InfoLevel).stream() << __FILE__ << '@' << __LINE__
|
||||
#define QLOG_WARN() \
|
||||
if (QsLogging::Logger::instance().loggingLevel() <= QsLogging::WarnLevel) \
|
||||
QsLogging::Logger::Helper(QsLogging::WarnLevel).stream() << __FILE__ << '@' << __LINE__
|
||||
#define QLOG_ERROR() \
|
||||
if (QsLogging::Logger::instance().loggingLevel() <= QsLogging::ErrorLevel) \
|
||||
QsLogging::Logger::Helper(QsLogging::ErrorLevel).stream() << __FILE__ << '@' << __LINE__
|
||||
#define QLOG_FATAL() \
|
||||
QsLogging::Logger::Helper(QsLogging::FatalLevel).stream() << __FILE__ << '@' << __LINE__
|
||||
*/
|
83
logger/QsLogDest.cpp
Normal file
83
logger/QsLogDest.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
// Copyright (c) 2010, Razvan Petru
|
||||
// All rights reserved.
|
||||
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
|
||||
// * Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice, this
|
||||
// list of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
// * The name of the contributors may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
// OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "QsLogDest.h"
|
||||
#include "QsDebugOutput.h"
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
#include <QString>
|
||||
|
||||
namespace QsLogging
|
||||
{
|
||||
|
||||
//! file message sink
|
||||
class FileDestination : public Destination
|
||||
{
|
||||
public:
|
||||
FileDestination(const QString &filePath);
|
||||
virtual void write(const QString &message);
|
||||
|
||||
private:
|
||||
QFile mFile;
|
||||
QTextStream mOutputStream;
|
||||
};
|
||||
|
||||
FileDestination::FileDestination(const QString &filePath)
|
||||
{
|
||||
mFile.setFileName(filePath);
|
||||
mFile.open(QFile::WriteOnly | QFile::Text |
|
||||
QFile::Truncate); // fixme: should throw on failure
|
||||
mOutputStream.setDevice(&mFile);
|
||||
}
|
||||
|
||||
void FileDestination::write(const QString &message)
|
||||
{
|
||||
mOutputStream << message << endl;
|
||||
mOutputStream.flush();
|
||||
}
|
||||
|
||||
//! debugger sink
|
||||
class DebugOutputDestination : public Destination
|
||||
{
|
||||
public:
|
||||
virtual void write(const QString &message);
|
||||
};
|
||||
|
||||
void DebugOutputDestination::write(const QString &message)
|
||||
{
|
||||
QsDebugOutput::output(message);
|
||||
}
|
||||
|
||||
DestinationPtr DestinationFactory::MakeFileDestination(const QString &filePath)
|
||||
{
|
||||
return DestinationPtr(new FileDestination(filePath));
|
||||
}
|
||||
|
||||
DestinationPtr DestinationFactory::MakeDebugOutputDestination()
|
||||
{
|
||||
return DestinationPtr(new DebugOutputDestination);
|
||||
}
|
||||
|
||||
} // end namespace
|
53
logger/QsLogDest.h
Normal file
53
logger/QsLogDest.h
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright (c) 2010, Razvan Petru
|
||||
// All rights reserved.
|
||||
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
|
||||
// * Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice, this
|
||||
// list of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
// * The name of the contributors may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
// OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
class QString;
|
||||
|
||||
namespace QsLogging
|
||||
{
|
||||
|
||||
class Destination
|
||||
{
|
||||
public:
|
||||
virtual ~Destination()
|
||||
{
|
||||
}
|
||||
virtual void write(const QString &message) = 0;
|
||||
};
|
||||
typedef std::shared_ptr<Destination> DestinationPtr;
|
||||
|
||||
//! Creates logging destinations/sinks. The caller will have ownership of
|
||||
//! the newly created destinations.
|
||||
class DestinationFactory
|
||||
{
|
||||
public:
|
||||
static DestinationPtr MakeFileDestination(const QString &filePath);
|
||||
static DestinationPtr MakeDebugOutputDestination();
|
||||
};
|
||||
|
||||
} // end namespace
|
@ -13,6 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "MultiMC.h"
|
||||
#include "BaseInstance.h"
|
||||
#include "BaseInstance_p.h"
|
||||
|
||||
@ -131,9 +132,9 @@ InstanceList *BaseInstance::instList() const
|
||||
return NULL;
|
||||
}
|
||||
|
||||
InstVersionList *BaseInstance::versionList() const
|
||||
std::shared_ptr<BaseVersionList> BaseInstance::versionList() const
|
||||
{
|
||||
return &MinecraftVersionList::getMainList();
|
||||
return MMC->minecraftlist();
|
||||
}
|
||||
|
||||
SettingsObject &BaseInstance::settings() const
|
||||
|
@ -21,7 +21,8 @@
|
||||
#include <settingsobject.h>
|
||||
|
||||
#include "inifile.h"
|
||||
#include "lists/InstVersionList.h"
|
||||
#include "lists/BaseVersionList.h"
|
||||
#include "net/LoginTask.h"
|
||||
|
||||
class QDialog;
|
||||
class BaseUpdate;
|
||||
@ -43,15 +44,19 @@ class BaseInstance : public QObject
|
||||
Q_OBJECT
|
||||
protected:
|
||||
/// no-touchy!
|
||||
BaseInstance(BaseInstancePrivate * d, const QString &rootDir, SettingsObject * settings, QObject *parent = 0);
|
||||
BaseInstance(BaseInstancePrivate *d, const QString &rootDir, SettingsObject *settings,
|
||||
QObject *parent = 0);
|
||||
|
||||
public:
|
||||
/// virtual destructor to make sure the destruction is COMPLETE
|
||||
virtual ~BaseInstance() {};
|
||||
|
||||
/// nuke thoroughly - deletes the instance contents, notifies the list/model which is responsible of cleaning up the husk
|
||||
/// nuke thoroughly - deletes the instance contents, notifies the list/model which is
|
||||
/// responsible of cleaning up the husk
|
||||
void nuke();
|
||||
|
||||
/// The instance's ID. The ID SHALL be determined by MMC internally. The ID IS guaranteed to be unique.
|
||||
/// The instance's ID. The ID SHALL be determined by MMC internally. The ID IS guaranteed to
|
||||
/// be unique.
|
||||
QString id() const;
|
||||
|
||||
/// get the type of this instance
|
||||
@ -76,10 +81,11 @@ public:
|
||||
void setGroupInitial(QString val);
|
||||
void setGroupPost(QString val);
|
||||
|
||||
|
||||
virtual QString intendedVersionId() const = 0;
|
||||
virtual bool setIntendedVersionId(QString version) = 0;
|
||||
|
||||
virtual bool versionIsCustom() = 0;
|
||||
|
||||
/*!
|
||||
* The instance's current version.
|
||||
* This value represents the instance's current version. If this value is
|
||||
@ -87,7 +93,7 @@ public:
|
||||
* \warning Don't change this value unless you know what you're doing.
|
||||
*/
|
||||
virtual QString currentVersionId() const = 0;
|
||||
//virtual void setCurrentVersionId(QString val) = 0;
|
||||
// virtual void setCurrentVersionId(QString val) = 0;
|
||||
|
||||
/*!
|
||||
* Whether or not Minecraft should be downloaded when the instance is launched.
|
||||
@ -95,7 +101,8 @@ public:
|
||||
virtual bool shouldUpdate() const = 0;
|
||||
virtual void setShouldUpdate(bool val) = 0;
|
||||
|
||||
/// Get the curent base jar of this instance. By default, it's the versions/$version/$version.jar
|
||||
/// Get the curent base jar of this instance. By default, it's the
|
||||
/// versions/$version/$version.jar
|
||||
QString baseJar() const;
|
||||
|
||||
/// the default base jar of this instance
|
||||
@ -134,7 +141,7 @@ public:
|
||||
* \brief Gets a pointer to this instance's version list.
|
||||
* \return A pointer to the available version list for this instance.
|
||||
*/
|
||||
virtual InstVersionList *versionList() const;
|
||||
virtual std::shared_ptr<BaseVersionList> versionList() const;
|
||||
|
||||
/*!
|
||||
* \brief Gets this instance's settings object.
|
||||
@ -144,16 +151,17 @@ public:
|
||||
virtual SettingsObject &settings() const;
|
||||
|
||||
/// returns a valid update task if update is needed, NULL otherwise
|
||||
virtual BaseUpdate* doUpdate() = 0;
|
||||
virtual BaseUpdate *doUpdate() = 0;
|
||||
|
||||
/// returns a valid minecraft process, ready for launch
|
||||
virtual MinecraftProcess* prepareForLaunch(QString user, QString session) = 0;
|
||||
virtual MinecraftProcess *prepareForLaunch(LoginResponse response) = 0;
|
||||
|
||||
/// do any necessary cleanups after the instance finishes. also runs before 'prepareForLaunch'
|
||||
/// do any necessary cleanups after the instance finishes. also runs before
|
||||
/// 'prepareForLaunch'
|
||||
virtual void cleanupAfterRun() = 0;
|
||||
|
||||
/// create a mod edit dialog for the instance
|
||||
virtual QDialog * createModEditDialog ( QWidget* parent ) = 0;
|
||||
virtual QDialog *createModEditDialog(QWidget *parent) = 0;
|
||||
|
||||
/// is a particular action enabled with this instance selected?
|
||||
virtual bool menuActionEnabled(QString action_name) const = 0;
|
||||
@ -167,7 +175,7 @@ signals:
|
||||
/*!
|
||||
* \brief Signal emitted when properties relevant to the instance view change
|
||||
*/
|
||||
void propertiesChanged(BaseInstance * inst);
|
||||
void propertiesChanged(BaseInstance *inst);
|
||||
/*!
|
||||
* \brief Signal emitted when groups are affected in any way
|
||||
*/
|
||||
@ -175,12 +183,11 @@ signals:
|
||||
/*!
|
||||
* \brief The instance just got nuked. Hurray!
|
||||
*/
|
||||
void nuked(BaseInstance * inst);
|
||||
void nuked(BaseInstance *inst);
|
||||
|
||||
protected:
|
||||
QSharedPointer<BaseInstancePrivate> inst_d;
|
||||
std::shared_ptr<BaseInstancePrivate> inst_d;
|
||||
};
|
||||
|
||||
// pointer for lazy people
|
||||
typedef QSharedPointer<BaseInstance> InstancePtr;
|
||||
|
||||
typedef std::shared_ptr<BaseInstance> InstancePtr;
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
class BaseInstance;
|
||||
|
||||
#define I_D(Class) Class##Private * const d = (Class##Private * const) inst_d.data()
|
||||
#define I_D(Class) Class##Private * const d = (Class##Private * const) inst_d.get()
|
||||
|
||||
struct BaseInstancePrivate
|
||||
{
|
||||
|
@ -7,7 +7,5 @@ BaseUpdate::BaseUpdate ( BaseInstance* inst, QObject* parent ) : Task ( parent )
|
||||
|
||||
void BaseUpdate::updateDownloadProgress(qint64 current, qint64 total)
|
||||
{
|
||||
// The progress on the current file is current / total
|
||||
float currentDLProgress = (float) current / (float) total;
|
||||
setProgress((int)(currentDLProgress * 100)); // convert to percentage
|
||||
emit progress(current, total);
|
||||
}
|
45
logic/BaseVersion.h
Normal file
45
logic/BaseVersion.h
Normal file
@ -0,0 +1,45 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <memory>
|
||||
|
||||
/*!
|
||||
* An abstract base class for versions.
|
||||
*/
|
||||
struct BaseVersion
|
||||
{
|
||||
/*!
|
||||
* A string used to identify this version in config files.
|
||||
* This should be unique within the version list or shenanigans will occur.
|
||||
*/
|
||||
virtual QString descriptor() = 0;
|
||||
|
||||
/*!
|
||||
* The name of this version as it is displayed to the user.
|
||||
* For example: "1.5.1"
|
||||
*/
|
||||
virtual QString name() = 0;
|
||||
|
||||
/*!
|
||||
* This should return a string that describes
|
||||
* the kind of version this is (Stable, Beta, Snapshot, whatever)
|
||||
*/
|
||||
virtual QString typeString() const = 0;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<BaseVersion> BaseVersionPtr;
|
||||
|
||||
Q_DECLARE_METATYPE( BaseVersionPtr )
|
30
logic/EnabledItemFilter.cpp
Normal file
30
logic/EnabledItemFilter.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
#include "EnabledItemFilter.h"
|
||||
|
||||
EnabledItemFilter::EnabledItemFilter(QObject* parent)
|
||||
:QSortFilterProxyModel(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void EnabledItemFilter::setActive(bool active)
|
||||
{
|
||||
m_active = active;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
bool EnabledItemFilter::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
||||
{
|
||||
if(!m_active)
|
||||
return true;
|
||||
QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
|
||||
if(sourceModel()->flags(index) & Qt::ItemIsEnabled)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EnabledItemFilter::lessThan(const QModelIndex& left, const QModelIndex& right) const
|
||||
{
|
||||
return QSortFilterProxyModel::lessThan(left, right);
|
||||
}
|
16
logic/EnabledItemFilter.h
Normal file
16
logic/EnabledItemFilter.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
class EnabledItemFilter : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
EnabledItemFilter(QObject *parent = 0);
|
||||
void setActive(bool active);
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
|
||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
|
||||
private:
|
||||
bool m_active = false;
|
||||
};
|
140
logic/ForgeInstaller.cpp
Normal file
140
logic/ForgeInstaller.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
#include "ForgeInstaller.h"
|
||||
#include "OneSixVersion.h"
|
||||
#include "OneSixLibrary.h"
|
||||
#include "net/HttpMetaCache.h"
|
||||
#include <quazip.h>
|
||||
#include <quazipfile.h>
|
||||
#include <pathutils.h>
|
||||
#include <QStringList>
|
||||
#include "MultiMC.h"
|
||||
|
||||
ForgeInstaller::ForgeInstaller(QString filename, QString universal_url)
|
||||
{
|
||||
std::shared_ptr<OneSixVersion> newVersion;
|
||||
m_universal_url = universal_url;
|
||||
|
||||
QuaZip zip(filename);
|
||||
if (!zip.open(QuaZip::mdUnzip))
|
||||
return;
|
||||
|
||||
QuaZipFile file(&zip);
|
||||
|
||||
// read the install profile
|
||||
if (!zip.setCurrentFile("install_profile.json"))
|
||||
return;
|
||||
|
||||
QJsonParseError jsonError;
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
return;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(file.readAll(), &jsonError);
|
||||
file.close();
|
||||
if (jsonError.error != QJsonParseError::NoError)
|
||||
return;
|
||||
|
||||
if (!jsonDoc.isObject())
|
||||
return;
|
||||
|
||||
QJsonObject root = jsonDoc.object();
|
||||
|
||||
auto installVal = root.value("install");
|
||||
auto versionInfoVal = root.value("versionInfo");
|
||||
if (!installVal.isObject() || !versionInfoVal.isObject())
|
||||
return;
|
||||
|
||||
// read the forge version info
|
||||
{
|
||||
newVersion = OneSixVersion::fromJson(versionInfoVal.toObject());
|
||||
if (!newVersion)
|
||||
return;
|
||||
}
|
||||
|
||||
QJsonObject installObj = installVal.toObject();
|
||||
QString libraryName = installObj.value("path").toString();
|
||||
internalPath = installObj.value("filePath").toString();
|
||||
|
||||
// where do we put the library? decode the mojang path
|
||||
OneSixLibrary lib(libraryName);
|
||||
lib.finalize();
|
||||
|
||||
auto cacheentry = MMC->metacache()->resolveEntry("libraries", lib.storagePath());
|
||||
finalPath = "libraries/" + lib.storagePath();
|
||||
if (!ensureFilePathExists(finalPath))
|
||||
return;
|
||||
|
||||
if (!zip.setCurrentFile(internalPath))
|
||||
return;
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
return;
|
||||
{
|
||||
QByteArray data = file.readAll();
|
||||
// extract file
|
||||
QSaveFile extraction(finalPath);
|
||||
if (!extraction.open(QIODevice::WriteOnly))
|
||||
return;
|
||||
if (extraction.write(data) != data.size())
|
||||
return;
|
||||
if (!extraction.commit())
|
||||
return;
|
||||
QCryptographicHash md5sum(QCryptographicHash::Md5);
|
||||
md5sum.addData(data);
|
||||
|
||||
cacheentry->stale = false;
|
||||
cacheentry->md5sum = md5sum.result().toHex().constData();
|
||||
MMC->metacache()->updateEntry(cacheentry);
|
||||
}
|
||||
file.close();
|
||||
|
||||
m_forge_version = newVersion;
|
||||
realVersionId = m_forge_version->id = installObj.value("minecraft").toString();
|
||||
}
|
||||
|
||||
bool ForgeInstaller::apply(std::shared_ptr<OneSixVersion> to)
|
||||
{
|
||||
if (!m_forge_version)
|
||||
return false;
|
||||
to->externalUpdateStart();
|
||||
int sliding_insert_window = 0;
|
||||
{
|
||||
// for each library in the version we are adding (except for the blacklisted)
|
||||
QSet<QString> blacklist{"lwjgl", "lwjgl_util", "lwjgl-platform"};
|
||||
for (auto lib : m_forge_version->libraries)
|
||||
{
|
||||
QString libName = lib->name();
|
||||
// WARNING: This could actually break.
|
||||
// if this is the actual forge lib, set an absolute url for the download
|
||||
if (libName.contains("minecraftforge"))
|
||||
{
|
||||
lib->setAbsoluteUrl(m_universal_url);
|
||||
}
|
||||
else if (libName.contains("scala"))
|
||||
{
|
||||
lib->setHint("forge-pack-xz");
|
||||
}
|
||||
if (blacklist.contains(libName))
|
||||
continue;
|
||||
|
||||
// find an entry that matches this one
|
||||
bool found = false;
|
||||
for (auto tolib : to->libraries)
|
||||
{
|
||||
if (tolib->name() != libName)
|
||||
continue;
|
||||
found = true;
|
||||
// replace lib
|
||||
tolib = lib;
|
||||
break;
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
// add lib
|
||||
to->libraries.insert(sliding_insert_window, lib);
|
||||
sliding_insert_window++;
|
||||
}
|
||||
}
|
||||
to->mainClass = m_forge_version->mainClass;
|
||||
to->minecraftArguments = m_forge_version->minecraftArguments;
|
||||
to->processArguments = m_forge_version->processArguments;
|
||||
}
|
||||
to->externalUpdateFinish();
|
||||
return to->toOriginalFile();
|
||||
}
|
25
logic/ForgeInstaller.h
Normal file
25
logic/ForgeInstaller.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include <QString>
|
||||
#include <memory>
|
||||
|
||||
class OneSixVersion;
|
||||
|
||||
class ForgeInstaller
|
||||
{
|
||||
public:
|
||||
ForgeInstaller(QString filename, QString universal_url);
|
||||
|
||||
bool apply(std::shared_ptr<OneSixVersion> to);
|
||||
|
||||
private:
|
||||
// the version, read from the installer
|
||||
std::shared_ptr<OneSixVersion> m_forge_version;
|
||||
QString internalPath;
|
||||
QString finalPath;
|
||||
QString realVersionId;
|
||||
QString m_universal_url;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include "LegacyInstance.h"
|
||||
#include "OneSixInstance.h"
|
||||
#include "NostalgiaInstance.h"
|
||||
#include "InstanceVersion.h"
|
||||
#include "BaseVersion.h"
|
||||
#include "MinecraftVersion.h"
|
||||
|
||||
#include "inifile.h"
|
||||
@ -30,6 +30,7 @@
|
||||
#include <setting.h>
|
||||
|
||||
#include "pathutils.h"
|
||||
#include <logger/QsLog.h>
|
||||
|
||||
InstanceFactory InstanceFactory::loader;
|
||||
|
||||
@ -68,16 +69,16 @@ InstanceFactory::InstLoadError InstanceFactory::loadInstance(BaseInstance *&inst
|
||||
}
|
||||
|
||||
|
||||
InstanceFactory::InstCreateError InstanceFactory::createInstance( BaseInstance*& inst, InstVersionPtr version, const QString& instDir )
|
||||
InstanceFactory::InstCreateError InstanceFactory::createInstance( BaseInstance*& inst, BaseVersionPtr version, const QString& instDir )
|
||||
{
|
||||
QDir rootDir(instDir);
|
||||
|
||||
qDebug(instDir.toUtf8());
|
||||
QLOG_DEBUG() << instDir.toUtf8();
|
||||
if (!rootDir.exists() && !rootDir.mkpath("."))
|
||||
{
|
||||
return InstanceFactory::CantCreateDir;
|
||||
}
|
||||
auto mcVer = version.dynamicCast<MinecraftVersion>();
|
||||
auto mcVer = std::dynamic_pointer_cast<MinecraftVersion>(version);
|
||||
if(!mcVer)
|
||||
return InstanceFactory::NoSuchVersion;
|
||||
|
||||
@ -89,19 +90,19 @@ InstanceFactory::InstCreateError InstanceFactory::createInstance( BaseInstance*&
|
||||
case MinecraftVersion::Legacy:
|
||||
m_settings->set("InstanceType", "Legacy");
|
||||
inst = new LegacyInstance(instDir, m_settings, this);
|
||||
inst->setIntendedVersionId(version->descriptor);
|
||||
inst->setIntendedVersionId(version->descriptor());
|
||||
inst->setShouldUseCustomBaseJar(false);
|
||||
break;
|
||||
case MinecraftVersion::OneSix:
|
||||
m_settings->set("InstanceType", "OneSix");
|
||||
inst = new OneSixInstance(instDir, m_settings, this);
|
||||
inst->setIntendedVersionId(version->descriptor);
|
||||
inst->setIntendedVersionId(version->descriptor());
|
||||
inst->setShouldUseCustomBaseJar(false);
|
||||
break;
|
||||
case MinecraftVersion::Nostalgia:
|
||||
m_settings->set("InstanceType", "Nostalgia");
|
||||
inst = new NostalgiaInstance(instDir, m_settings, this);
|
||||
inst->setIntendedVersionId(version->descriptor);
|
||||
inst->setIntendedVersionId(version->descriptor());
|
||||
inst->setShouldUseCustomBaseJar(false);
|
||||
break;
|
||||
default:
|
||||
|
@ -19,9 +19,9 @@
|
||||
#include <QMap>
|
||||
#include <QList>
|
||||
|
||||
#include "InstanceVersion.h"
|
||||
#include "BaseVersion.h"
|
||||
|
||||
class InstVersion;
|
||||
class BaseVersion;
|
||||
class BaseInstance;
|
||||
|
||||
/*!
|
||||
@ -61,7 +61,7 @@ public:
|
||||
* - InstExists if the given instance directory is already an instance.
|
||||
* - CantCreateDir if the given instance directory cannot be created.
|
||||
*/
|
||||
InstCreateError createInstance(BaseInstance *&inst, InstVersionPtr version, const QString &instDir);
|
||||
InstCreateError createInstance(BaseInstance *&inst, BaseVersionPtr version, const QString &instDir);
|
||||
|
||||
/*!
|
||||
* \brief Loads an instance from the given directory.
|
||||
|
@ -3,9 +3,9 @@
|
||||
|
||||
#include <iostream>
|
||||
#include "gui/logindialog.h"
|
||||
#include "gui/taskdialog.h"
|
||||
#include "gui/ProgressDialog.h"
|
||||
#include "gui/consolewindow.h"
|
||||
#include "logic/tasks/LoginTask.h"
|
||||
#include "logic/net/LoginTask.h"
|
||||
#include "logic/MinecraftProcess.h"
|
||||
#include "lists/InstanceList.h"
|
||||
|
||||
@ -25,13 +25,13 @@ void InstanceLauncher::onLoginComplete()
|
||||
LoginTask * task = ( LoginTask * ) QObject::sender();
|
||||
auto result = task->getResult();
|
||||
auto instance = MMC->instances()->getInstanceById(instId);
|
||||
proc = instance->prepareForLaunch ( result.username, result.sessionID );
|
||||
proc = instance->prepareForLaunch ( result );
|
||||
if ( !proc )
|
||||
{
|
||||
//FIXME: report error
|
||||
return;
|
||||
}
|
||||
console = new ConsoleWindow();
|
||||
console = new ConsoleWindow(proc);
|
||||
console->show();
|
||||
|
||||
connect ( proc, SIGNAL ( ended() ), SLOT ( onTerminated() ) );
|
||||
@ -48,7 +48,7 @@ void InstanceLauncher::doLogin ( const QString& errorMsg )
|
||||
{
|
||||
UserInfo uInfo {loginDlg->getUsername(), loginDlg->getPassword() };
|
||||
|
||||
TaskDialog* tDialog = new TaskDialog ( nullptr );
|
||||
ProgressDialog* tDialog = new ProgressDialog ( nullptr );
|
||||
LoginTask* loginTask = new LoginTask ( uInfo, tDialog );
|
||||
connect ( loginTask, SIGNAL ( succeeded() ),SLOT ( onLoginComplete() ), Qt::QueuedConnection );
|
||||
connect ( loginTask, SIGNAL ( failed ( QString ) ),SLOT ( doLogin ( QString ) ), Qt::QueuedConnection );
|
||||
@ -61,7 +61,7 @@ int InstanceLauncher::launch()
|
||||
{
|
||||
std::cout << "Launching Instance '" << qPrintable ( instId ) << "'" << std::endl;
|
||||
auto instance = MMC->instances()->getInstanceById(instId);
|
||||
if ( instance.isNull() )
|
||||
if ( !instance )
|
||||
{
|
||||
std::cout << "Could not find instance requested. note that you have to specify the ID, not the NAME" << std::endl;
|
||||
return 1;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user