Compare commits
No commits in common. "master" and "patch-1" have entirely different histories.
917 changed files with 4757 additions and 314076 deletions
43
.gitignore
vendored
43
.gitignore
vendored
|
@ -1,35 +1,10 @@
|
|||
*.pb.cc
|
||||
*.pb.h
|
||||
plugin/python/protocol_pb2.py
|
||||
Makefile
|
||||
*.cmake
|
||||
*.so
|
||||
*.so.*
|
||||
*.log
|
||||
libtransport_test
|
||||
CMakeFiles
|
||||
spectrum2
|
||||
transport_config.h
|
||||
Doxyfile
|
||||
moc_*
|
||||
CMakeCache.txt
|
||||
*.patch
|
||||
*.orig
|
||||
spectrum2_manager
|
||||
dfrotz
|
||||
spectrum2_frotz_backend
|
||||
spectrum2_libcommuni_backend
|
||||
spectrum2_libpurple_backend
|
||||
spectrum2_skype_backend
|
||||
spectrum2_smstools3_backend
|
||||
spectrum2_swiften_backend
|
||||
spectrum2_template_backend
|
||||
spectrum2_twitter_backend
|
||||
install_manifest.txt
|
||||
slack.cfg
|
||||
*.sqlite
|
||||
localhost.port
|
||||
*.a
|
||||
core.*
|
||||
*.pyc
|
||||
_site/*
|
||||
_theme_packages/*
|
||||
|
||||
Thumbs.db
|
||||
.DS_Store
|
||||
|
||||
!.gitkeep
|
||||
|
||||
.rbenv-version
|
||||
.rvmrc
|
||||
|
|
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -1,3 +0,0 @@
|
|||
[submodule "msvc-deps/curl"]
|
||||
path = msvc-deps/curl
|
||||
url = https://github.com/bagder/curl.git
|
49
.travis.yml
49
.travis.yml
|
@ -1,49 +0,0 @@
|
|||
language: cpp
|
||||
python:
|
||||
- "2.7_with_system_site_packages"
|
||||
virtualenv:
|
||||
system_site_packages: true
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
dist: trusty
|
||||
sudo: required
|
||||
- os: osx
|
||||
allow_failures:
|
||||
- os: osx
|
||||
before_script:
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
||||
export DEBIAN_FRONTEND=noninteractive;
|
||||
export APT_LISTCHANGES_FRONTEND=none;
|
||||
echo force-confold | sudo tee -a /etc/dpkg/dpkg.cfg;
|
||||
curl -k https://swift.im/keys/packages.key | sudo apt-key add -;
|
||||
echo 'deb http://us.archive.ubuntu.com/ubuntu xenial main restricted universe multiverse' | sudo tee /etc/apt/sources.list.d/xenial.list > /dev/null;
|
||||
echo 'deb http://us.archive.ubuntu.com/ubuntu xenial-backports main restricted universe multiverse' | sudo tee -a /etc/apt/sources.list.d/xenial.list > /dev/null;
|
||||
echo 'deb http://us.archive.ubuntu.com/ubuntu xenial-security main restricted universe multiverse' | sudo tee -a /etc/apt/sources.list.d/xenial.list > /dev/null;
|
||||
echo 'deb http://us.archive.ubuntu.com/ubuntu xenial-updates main restricted universe multiverse' | sudo tee -a /etc/apt/sources.list.d/xenial.list > /dev/null;
|
||||
echo "deb http://packages.spectrum.im/spectrum2/ xenial main" | sudo tee -a /etc/apt/sources.list;
|
||||
echo "deb http://swift.im/packages/ubuntu/xenial beta main" | sudo tee -a /etc/apt/sources.list;
|
||||
echo "deb http://packages.prosody.im/debian $(lsb_release -sc) main" | sudo tee -a /etc/apt/sources.list;
|
||||
sudo apt-get update -qq;
|
||||
sudo apt-get purge chromium-browser;
|
||||
sudo apt-get install -y --force-yes build-essential prosody ngircd python-sleekxmpp libswiften-dev libprotobuf-dev protobuf-compiler libpurple-dev libglib2.0-dev libdbus-glib-1-dev liblog4cxx10-dev libpopt-dev libboost-dev libboost-signals-dev libboost-system-dev libboost-thread-dev libboost-locale-dev libboost-filesystem-dev libboost-program-options-dev libboost-regex-dev libboost-date-time-dev libcppunit-dev libcommuni-dev libminiupnpc-dev libnatpmp-dev;
|
||||
sudo killall lua5.1;
|
||||
else
|
||||
brew update;
|
||||
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/e6e43cf6a3%5E/Formula/cppunit.rb;
|
||||
brew install protobuf log4cxx popt boost;
|
||||
travis_wait 30 brew install -s libswiften;
|
||||
fi
|
||||
install:
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
||||
pip install --user sleekxmpp;
|
||||
fi
|
||||
script:
|
||||
- cmake -DCMAKE_BUILD_TYPE=Debug -DENABLE_TESTS=ON . && make
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
||||
make extended_test;
|
||||
else
|
||||
make test;
|
||||
fi
|
||||
notifications:
|
||||
slack: spectrum2:CIlYHtxGMAaxs3qVHfwBzCuy
|
1
404.html
Normal file
1
404.html
Normal file
|
@ -0,0 +1 @@
|
|||
Sorry this page does not exist =(
|
475
CMakeLists.txt
475
CMakeLists.txt
|
@ -1,475 +0,0 @@
|
|||
cmake_minimum_required(VERSION 2.6)
|
||||
project(libtransport)
|
||||
if(${CMAKE_MAJOR_VERSION} GREATER 2)
|
||||
cmake_policy(SET CMP0037 OLD)
|
||||
endif()
|
||||
include(CPack)
|
||||
message(STATUS "Variables to override default places where to find libraries:")
|
||||
message(STATUS "|- cppunit : -DCPPUNIT_INCLUDE_DIR, -DCPPUNIT_LIBRARY")
|
||||
message(STATUS "|- swiften : -DSWIFTEN_INCLUDE_DIR, -DSWIFTEN_LIBRARY")
|
||||
message(STATUS " |- zlib : -DZLIB_LIBRARY")
|
||||
message(STATUS " |- expat : -DEXPAT_LIBRARY")
|
||||
message(STATUS " |-libidn : -DLIBIDN_LIBRARY")
|
||||
message(STATUS " |-libxml : -DLIBXML_LIBRARY")
|
||||
message(STATUS "|- boost : -DBOOST_INCLUDEDIR, -DBOOST_LIBRARYDIR")
|
||||
message(STATUS "|- protobuf: -DPROTOBUF_INCLUDE_DIR, -DPROTOBUF_LIBRARY")
|
||||
message(STATUS " : -DPROTOBUF_PROTOC_EXECUTABLE")
|
||||
message(STATUS "|- log4cxx : -DLOG4CXX_INCLUDE_DIR, -DLOG4CXX_LIBRARY")
|
||||
message(STATUS "|- purple : -DPURPLE_INCLUDE_DIR, -DPURPLE_LIBRARY")
|
||||
message(STATUS " : -DPURPLE_NOT_RUNTIME - enables compilation with libpurple.lib")
|
||||
|
||||
option(ENABLE_SQLITE3 "Build with SQLite3 support" ON)
|
||||
option(ENABLE_MYSQL "Build with MySQL support" ON)
|
||||
option(ENABLE_PQXX "Build with Postgres supoort" ON)
|
||||
|
||||
option(ENABLE_FROTZ "Build Frotz plugin" ON)
|
||||
option(ENABLE_IRC "Build IRC plugin" ON)
|
||||
option(ENABLE_PURPLE "Build Libpurple plugin" ON)
|
||||
option(ENABLE_SMSTOOLS3 "Build SMSTools3 plugin" ON)
|
||||
option(ENABLE_XMPP "Build XMPP plugin" ON)
|
||||
option(ENABLE_TWITTER "Build Twitter plugin" ON)
|
||||
|
||||
option(ENABLE_DOCS "Build Docs" ON)
|
||||
# option(ENABLE_LOG "Build with logging using Log4cxx" ON)
|
||||
option(ENABLE_TESTS "Build Tests using CppUnit" OFF)
|
||||
|
||||
MACRO(LIST_CONTAINS var value)
|
||||
SET(${var})
|
||||
FOREACH (value2 ${ARGN})
|
||||
IF (${value} STREQUAL ${value2})
|
||||
SET(${var} TRUE)
|
||||
ENDIF (${value} STREQUAL ${value2})
|
||||
ENDFOREACH (value2)
|
||||
ENDMACRO(LIST_CONTAINS)
|
||||
|
||||
if(NOT LIB_INSTALL_DIR)
|
||||
set(LIB_INSTALL_DIR "lib")
|
||||
endif()
|
||||
|
||||
set(CMAKE_MODULE_PATH "cmake_modules")
|
||||
|
||||
###### Prerequisites ######
|
||||
|
||||
|
||||
# FIND SWIFTEN
|
||||
|
||||
set(Swiften_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
||||
find_package(Swiften)
|
||||
|
||||
if(NOT SWIFTEN_FOUND)
|
||||
if (ZLIB_LIBRARY)
|
||||
set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} ${ZLIB_LIBRARY})
|
||||
endif()
|
||||
if (EXPAT_LIBRARY)
|
||||
set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} ${EXPAT_LIBRARY})
|
||||
endif()
|
||||
if (LIBIDN_LIBRARY)
|
||||
set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} ${LIBIDN_LIBRARY})
|
||||
endif()
|
||||
if (LIBXML_LIBRARY)
|
||||
set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} ${LIBXML_LIBRARY})
|
||||
endif()
|
||||
set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} "Dnsapi")
|
||||
set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} "Crypt32")
|
||||
set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} "Secur32")
|
||||
set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} "Iphlpapi")
|
||||
set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} "Winscard")
|
||||
message(STATUS "XXXUsing swiften: ${SWIFTEN_INCLUDE_DIR} ${SWIFTEN_LIBRARY}
|
||||
Version: ${SWIFTEN_VERSION}")
|
||||
endif()
|
||||
|
||||
# FIND BOOST
|
||||
if (WIN32)
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
set(Boost_USE_MULTITHREADED ON)
|
||||
set(Boost_USE_STATIC_RUNTIME OFF)
|
||||
endif(WIN32)
|
||||
set(Boost_FIND_QUIETLY ON)
|
||||
find_package(Boost COMPONENTS program_options date_time system filesystem regex thread signals locale REQUIRED)
|
||||
|
||||
message( STATUS "Found Boost: ${Boost_VERSION}, ${Boost_LIBRARIES}, ${Boost_INCLUDE_DIR}")
|
||||
|
||||
if (${Boost_VERSION} GREATER 104999)
|
||||
message( STATUS "Using BOOST_FILESYSTEM_VERSION=3")
|
||||
add_definitions(-DBOOST_FILESYSTEM_VERSION=3)
|
||||
endif()
|
||||
|
||||
# FIND POPT
|
||||
if (NOT WIN32)
|
||||
set(popt_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
||||
find_package(popt REQUIRED)
|
||||
endif()
|
||||
|
||||
###### Database ######
|
||||
|
||||
# FIND SQLITE3
|
||||
if (ENABLE_SQLITE3)
|
||||
if (MSVC)
|
||||
set(SQLITE3_FOUND 1)
|
||||
ADD_SUBDIRECTORY(${CMAKE_SOURCE_DIR}/msvc-deps)
|
||||
else()
|
||||
if (WIN32)
|
||||
ADD_SUBDIRECTORY(${CMAKE_SOURCE_DIR}/msvc-deps/sqlite3)
|
||||
else()
|
||||
set(sqlite3_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
||||
find_package(sqlite3)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# FIND MYSQL
|
||||
if(ENABLE_MYSQL)
|
||||
set(mysql_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
||||
find_package(mysql)
|
||||
endif()
|
||||
|
||||
# FIND PQXX
|
||||
if(ENABLE_PQXX)
|
||||
set(pqxx_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
||||
find_package(pqxx)
|
||||
endif()
|
||||
|
||||
###### Plugins ######
|
||||
|
||||
# FIND LIBPURPLE
|
||||
if(ENABLE_PURPLE)
|
||||
set(purple_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
||||
find_package(purple)
|
||||
|
||||
if (WIN32)
|
||||
if (PURPLE_NOT_RUNTIME)
|
||||
add_definitions(-DPURPLE_RUNTIME=0)
|
||||
else(PURPLE_NOT_RUNTIME)
|
||||
add_definitions(-DPURPLE_RUNTIME=1)
|
||||
endif(PURPLE_NOT_RUNTIME)
|
||||
else()
|
||||
add_definitions(-DPURPLE_RUNTIME=0)
|
||||
endif()
|
||||
|
||||
# FIND LIBEVENT
|
||||
set(event_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
||||
find_package(event)
|
||||
endif()
|
||||
|
||||
# FIND GLIB
|
||||
if(ENABLE_PURPLE)
|
||||
# if (GLIB2_INCLUDE_DIR AND GLIB2_LIBRARIES)
|
||||
# set(GLIB2_FOUND TRUE)
|
||||
# else()
|
||||
set(glib_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
||||
find_package(glib)
|
||||
# endif()
|
||||
endif()
|
||||
|
||||
# FIND LIBXML2
|
||||
# set(libxml2_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
||||
# find_package(libxml2)
|
||||
|
||||
# FIND PROTOBUF
|
||||
set(Protobuf_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
||||
find_package(Protobuf REQUIRED)
|
||||
|
||||
if (NOT PROTOBUF_FOUND AND PROTOBUF_INCLUDE_DIR AND PROTOBUF_LIBRARY)
|
||||
set(PROTOBUF_FOUND 1)
|
||||
set(PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIR})
|
||||
if (PROTOBUF_PROTOC_EXECUTABLE)
|
||||
else()
|
||||
set(PROTOBUF_PROTOC_EXECUTABLE protoc)
|
||||
endif()
|
||||
message(STATUS "Using protobuf: ${PROTOBUF_INCLUDE_DIRS} ${PROTOBUF_LIBRARY}")
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
add_definitions(-DSWIFTEN_STATIC=1)
|
||||
ADD_DEFINITIONS(-D_UNICODE)
|
||||
ADD_DEFINITIONS(-DUNICODE)
|
||||
endif()
|
||||
|
||||
|
||||
if (CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(openssl_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
||||
find_package(openssl)
|
||||
endif()
|
||||
|
||||
if(ENABLE_IRC)
|
||||
set(Communi_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
||||
find_package(Communi)
|
||||
|
||||
INCLUDE(FindQt4)
|
||||
FIND_PACKAGE(Qt4 COMPONENTS QtCore QtNetwork)
|
||||
# ADD_DEFINITIONS(${SWIFTEN_CFLAGS})
|
||||
ADD_DEFINITIONS(-DSUPPORT_LEGACY_CAPS)
|
||||
# ADD_DEFINITIONS(-DBOOST_FILESYSTEM_VERSION=2)
|
||||
endif()
|
||||
|
||||
set(event_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
||||
find_package(event)
|
||||
|
||||
|
||||
####### Miscallanous ######
|
||||
|
||||
if(ENABLE_DOCS)
|
||||
find_package(Doxygen)
|
||||
endif()
|
||||
|
||||
# if(ENABLE_LOG)
|
||||
if(LOG4CXX_INCLUDE_DIR AND LOG4CXX_LIBRARY)
|
||||
set(LOG4CXX_LIBRARIES ${LOG4CXX_LIBRARY})
|
||||
set(LOG4CXX_FOUND 1)
|
||||
message(STATUS "Using log4cxx: ${CPPUNIT_INCLUDE_DIR} ${LOG4CXX_INCLUDE_DIR}")
|
||||
else()
|
||||
set(log4cxx_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
||||
find_package(log4cxx)
|
||||
endif()
|
||||
# endif()
|
||||
|
||||
# FIND CPPUNIT
|
||||
if(ENABLE_TESTS)
|
||||
set(cppunit_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
||||
find_package(cppunit)
|
||||
|
||||
if(NOT CPPUNIT_FOUND AND CPPUNIT_INCLUDE_DIR AND CPPUNIT_LIBRARY)
|
||||
set(CCPUNIT_LIBRARIES ${CPPUNIT_LIBRARY})
|
||||
set(CPPUNIT_FOUND 1)
|
||||
message(STATUS "Using cppunit: ${CPPUNIT_INCLUDE_DIR} ${CPPUNIT_LIBRARIES}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
message(" Supported features")
|
||||
message("-----------------------")
|
||||
|
||||
if (SPECTRUM_VERSION)
|
||||
ADD_DEFINITIONS(-DSPECTRUM_VERSION="${SPECTRUM_VERSION}")
|
||||
else (SPECTRUM_VERSION)
|
||||
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
|
||||
if (NOT GIT_EXECUTABLE)
|
||||
set (GIT_EXECUTABLE git)
|
||||
endif()
|
||||
execute_process(COMMAND ${GIT_EXECUTABLE} "--git-dir=${CMAKE_CURRENT_SOURCE_DIR}/.git" rev-parse --short HEAD
|
||||
OUTPUT_VARIABLE GIT_REVISION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
set(SPECTRUM_VERSION 2.0.5-git-${GIT_REVISION})
|
||||
ADD_DEFINITIONS(-DSPECTRUM_VERSION="${SPECTRUM_VERSION}")
|
||||
else (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
|
||||
set(SPECTRUM_VERSION 2.0.5)
|
||||
ADD_DEFINITIONS(-DSPECTRUM_VERSION="${SPECTRUM_VERSION}")
|
||||
endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
|
||||
endif (SPECTRUM_VERSION)
|
||||
|
||||
message("Version : " ${SPECTRUM_VERSION})
|
||||
|
||||
if (SQLITE3_FOUND)
|
||||
ADD_DEFINITIONS(-DWITH_SQLITE)
|
||||
if (WIN32)
|
||||
include_directories("${CMAKE_SOURCE_DIR}/msvc-deps/sqlite3")
|
||||
message("SQLite3 : bundled")
|
||||
else (WIN32)
|
||||
include_directories(${SQLITE3_INCLUDE_DIR})
|
||||
message("SQLite3 : yes")
|
||||
endif (WIN32)
|
||||
else (SQLITE3_FOUND)
|
||||
set(SQLITE3_LIBRARIES "")
|
||||
if(ENABLE_SQLITE3)
|
||||
message("SQLite3 : no (install sqlite3)")
|
||||
else(ENABLE_SQLITE3)
|
||||
message("SQLite3 : no (user disabled)")
|
||||
endif()
|
||||
endif (SQLITE3_FOUND)
|
||||
|
||||
if (MYSQL_FOUND)
|
||||
ADD_DEFINITIONS(-DWITH_MYSQL)
|
||||
include_directories(${MYSQL_INCLUDE_DIR})
|
||||
message("MySQL : yes")
|
||||
else (MYSQL_FOUND)
|
||||
set(MYSQL_LIBRARIES "")
|
||||
if(ENABLE_MYSQL)
|
||||
message("MySQL : no (install mysql-devel)")
|
||||
else(ENABLE_MYSQL)
|
||||
message("MySQL : no (user disabled)")
|
||||
endif()
|
||||
endif (MYSQL_FOUND)
|
||||
|
||||
if (PQXX_FOUND)
|
||||
ADD_DEFINITIONS(-DWITH_PQXX)
|
||||
include_directories(${PQXX_INCLUDE_DIR})
|
||||
message("PostgreSQL : yes")
|
||||
else (PQXX_FOUND)
|
||||
set(PQXX_LIBRARY "")
|
||||
set(PQ_LIBRARY "")
|
||||
if(ENABLE_PQXX)
|
||||
message("PostgreSQL : no (install libpqxx-devel)")
|
||||
else(ENABLE_PQXX)
|
||||
message("PostgreSQL : no (user disabled)")
|
||||
endif()
|
||||
endif (PQXX_FOUND)
|
||||
|
||||
if (PROTOBUF_FOUND)
|
||||
ADD_DEFINITIONS(-DWITH_PROTOBUF)
|
||||
include_directories(${PROTOBUF_INCLUDE_DIRS})
|
||||
message("Network plugins : yes")
|
||||
|
||||
if(PURPLE_FOUND)
|
||||
message("Libpurple plugin : yes")
|
||||
include_directories(${PURPLE_INCLUDE_DIR})
|
||||
include_directories(${GLIB2_INCLUDE_DIR})
|
||||
else()
|
||||
if(ENABLE_PURPLE)
|
||||
message("Libpurple plugin : no (install libpurple)")
|
||||
else(ENABLE_PURPLE)
|
||||
message("Libpurple plugin : no (user disabled)")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (HAVE_EVENT)
|
||||
ADD_DEFINITIONS(-DWITH_LIBEVENT)
|
||||
include_directories(${EVENT_INCLUDE_DIRS})
|
||||
message(" libev eventloop : yes")
|
||||
else()
|
||||
if(ENABLE_PURPLE)
|
||||
message(" libev eventloop : no (install libev-devel)")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(IRC_FOUND)
|
||||
ADD_DEFINITIONS(-DIRC_SHARED)
|
||||
message("IRC plugin : yes")
|
||||
include_directories(${QT_QTNETWORK_INCLUDE_DIR})
|
||||
include_directories(${IRC_INCLUDE_DIR})
|
||||
include(${QT_USE_FILE})
|
||||
else()
|
||||
if(ENABLE_IRC)
|
||||
message("IRC plugin : no (install libCommuni and libprotobuf-dev)")
|
||||
else(ENABLE_IRC)
|
||||
message("IRC plugin : no (user disabled)")
|
||||
endif()
|
||||
endif()
|
||||
if(ENABLE_TWITTER)
|
||||
message("Twitter plugin : yes")
|
||||
else(ENABLE_TWITTER)
|
||||
message("Twitter plugin : no (user disabled)")
|
||||
endif()
|
||||
if (NOT WIN32)
|
||||
if(ENABLE_FROTZ)
|
||||
message("Frotz plugin : yes")
|
||||
else()
|
||||
message("Frotz plugin : no (user disabled)")
|
||||
endif()
|
||||
if(ENABLE_SMSTOOLS3)
|
||||
message("SMSTools3 plugin : yes")
|
||||
else()
|
||||
message("SMSTools3 plugin : no (user disabled)")
|
||||
endif()
|
||||
else()
|
||||
message("Frotz plugin : no (does not run on Win32)")
|
||||
message("SMSTools3 plugin : no (does not run on Win32)")
|
||||
message("Skype plugin : no (does not run on Win32)")
|
||||
endif()
|
||||
|
||||
if(ENABLE_XMPP)
|
||||
message("Swiften plugin : yes")
|
||||
else()
|
||||
message("Swiften plugin : no (user disabled)")
|
||||
endif()
|
||||
else()
|
||||
message("Network plugins : no (install libprotobuf-dev)")
|
||||
message("Libpurple plugin : no (install libpurple and libprotobuf-dev)")
|
||||
message("IRC plugin : no (install libircclient-qt and libprotobuf-dev)")
|
||||
message("Frotz plugin : no (install libprotobuf-dev)")
|
||||
message("SMSTools3 plugin : no (install libprotobuf-dev)")
|
||||
message("Swiften plugin : no (install libprotobuf-dev)")
|
||||
message("Twitter plugin : no (install libprotobuf-dev)")
|
||||
endif()
|
||||
|
||||
if (LOG4CXX_FOUND)
|
||||
message("Log4cxx : yes")
|
||||
include_directories(${LOG4CXX_INCLUDE_DIR})
|
||||
ADD_DEFINITIONS(-DWITH_LOG4CXX)
|
||||
else()
|
||||
set(LOG4CXX_LIBRARIES "")
|
||||
if (WIN32)
|
||||
message("Log4cxx : no (install log4cxx-devel)")
|
||||
else()
|
||||
message(FATAL_ERROR "Log4cxx : no (install log4cxx-devel)")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
ADD_DEFINITIONS(-DLOG4CXX_STATIC)
|
||||
ADD_DEFINITIONS(-D_WIN32_WINNT=0x501)
|
||||
ADD_DEFINITIONS(-DWIN32_LEAN_AND_MEAN)
|
||||
ADD_DEFINITIONS(-DBOOST_USE_WINDOWS_H)
|
||||
ADD_DEFINITIONS(-DBOOST_THREAD_USE_LIB)
|
||||
endif()
|
||||
|
||||
# We cannot use boost:signals2, because Swiften does not use them,
|
||||
# for now, just ignore the deprecation warning.
|
||||
ADD_DEFINITIONS(-DBOOST_SIGNALS_NO_DEPRECATION_WARNING)
|
||||
|
||||
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
if (CMAKE_COMPILER_IS_GNUCXX)
|
||||
ADD_DEFINITIONS(-O0)
|
||||
ADD_DEFINITIONS(-ggdb)
|
||||
endif()
|
||||
ADD_DEFINITIONS(-DDEBUG)
|
||||
message("Debug : yes")
|
||||
else(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
message("Debug : no (run \"cmake . -DCMAKE_BUILD_TYPE=Debug\")")
|
||||
endif(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
|
||||
|
||||
SET(TRANSPORT_VERSION 2.0)
|
||||
SET(PROJECT_VERSION 2.0)
|
||||
include_directories(include)
|
||||
|
||||
|
||||
include_directories(${EVENT_INCLUDE_DIRS})
|
||||
include_directories(${SWIFTEN_INCLUDE_DIR})
|
||||
include_directories(${Boost_INCLUDE_DIRS})
|
||||
|
||||
if (CMAKE_COMPILER_IS_GNUCXX)
|
||||
include_directories(${OPENSSL_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
ADD_SUBDIRECTORY(libtransport)
|
||||
ADD_SUBDIRECTORY(plugin)
|
||||
ADD_SUBDIRECTORY(include)
|
||||
ADD_SUBDIRECTORY(spectrum)
|
||||
ADD_SUBDIRECTORY(backends)
|
||||
ADD_SUBDIRECTORY(tests)
|
||||
if (NOT WIN32)
|
||||
ADD_SUBDIRECTORY(spectrum_manager)
|
||||
# ADD_SUBDIRECTORY(spectrum2_send_message)
|
||||
endif()
|
||||
|
||||
if (CPPUNIT_FOUND)
|
||||
message("tests : yes")
|
||||
include_directories(${CPPUNIT_INCLUDE_DIR})
|
||||
else()
|
||||
if(ENABLE_TESTS)
|
||||
message("tests : no (install CPPUnit)")
|
||||
else(ENABLE_TESTS)
|
||||
message("tests : no (user disabled)")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(DOXYGEN_FOUND)
|
||||
message("Docs : yes")
|
||||
ADD_SUBDIRECTORY(docs)
|
||||
else(DOXYGEN_FOUND)
|
||||
if(ENABLE_DOCS)
|
||||
message("Docs : no (install doxygen)")
|
||||
else(ENABLE_DOCS)
|
||||
message("Docs : no (user disabled)")
|
||||
endif()
|
||||
endif(DOXYGEN_FOUND)
|
||||
|
||||
message("----------------------")
|
||||
|
||||
if(NOT SQLITE3_FOUND AND NOT MYSQL_FOUND AND NOT PQXX_FOUND)
|
||||
if(ENABLE_SQLITE3 OR ENABLE_MYSQL OR ENABLE_PQXX)
|
||||
message("Could not find any database - Please install at least one of sqlite3-devel, mysql-devel or pqxx-devel if you want to use transport mode.")
|
||||
else(ENABLE_SQLITE3 OR ENABLE_MYSQL OR ENABLE_PQXX)
|
||||
message("Please enable at least one of SQLITE3, MYSQL, PQXX databases to use transport mode.")
|
||||
endif()
|
||||
endif()
|
1
CNAME
Normal file
1
CNAME
Normal file
|
@ -0,0 +1 @@
|
|||
spectrum.im
|
251
ChangeLog
251
ChangeLog
|
@ -1,251 +0,0 @@
|
|||
Version 2.0.5 (2017-08-09):
|
||||
Minor bugfixes:
|
||||
* fix purple-hangouts login
|
||||
* fix Debian packages dependencies
|
||||
|
||||
Version 2.0.4 (2017-08-03):
|
||||
General:
|
||||
* Add support for Swiften 4.0rc2. Swiften 3.x and 2.x are still supported.
|
||||
* Add support for passwordless libpurple backends (e.g. purple-hangouts).
|
||||
* Partial support for groupchats with case-sensitive names (e.g. purple-telegram).
|
||||
* Various small bugfixes, see Git commit descriptions for the full list of changes.
|
||||
|
||||
Version 2.0.3 (2016-02-29):
|
||||
General:
|
||||
* Swift 3.0rc2 is now minimum Swift 3.x version needed to compile Spectrum2,
|
||||
Swith 2.x remains supported.
|
||||
* Rename user when he tries to connect to room from the second client
|
||||
with different nickname than he used with the first client.
|
||||
* Send self presence as the first presence from the MUC room.
|
||||
* Send the icon hash to the backend with other buddies information.
|
||||
* Send unavailable presence as a response to presence for exiting
|
||||
the room. Fixes room rejoin in Pidgin.
|
||||
* Fix memory leak in HTTPRequest - currently used only in Slack frontend.
|
||||
|
||||
Slack frontend:
|
||||
* For IRC allow registering without providing account name/password.
|
||||
* Do not reconnect to Slack RTM when no URL is available after disconnect.
|
||||
* Handle "account_inactive" Slack error.
|
||||
|
||||
Web interface:
|
||||
* Show warning when trying to register already registered username.
|
||||
* Allow registering with empty password for networks like IRC where
|
||||
password is not needed.
|
||||
* Allow showing examples of username or server in registration form. This
|
||||
is configured in config file.
|
||||
* Fix `service.base_location` setting for register.shtml page.
|
||||
|
||||
Libpurple backend:
|
||||
* Make the conversation active according to chatstates notifications.
|
||||
Should fix the issue with repeating messages with prpl-facebook.
|
||||
* When `service.web_directory` and `service.web_url` is set, images sent
|
||||
in messages are stored to `service.web_directory` and link is forwarded
|
||||
to the user. Tested only with prpl-facebook for now.
|
||||
* Treat empty password as fatal error - do no try to reconnect
|
||||
automatically in that case.
|
||||
|
||||
Libcommuni backend:
|
||||
* Latest libcommuni 3.4.0 is now needed.
|
||||
* Libcommuni backend has been improved to use the newest libcommuni
|
||||
features.
|
||||
* Ports can now be set in `service.irc_server` option and in the JID. When
|
||||
'+' character is used before the port number, SSL is used automatically.
|
||||
When port 6697 is used, SSL is used automatically too.
|
||||
|
||||
Swiften backend:
|
||||
* Respect the resource when connecting to 3rd-party XMPP network.
|
||||
|
||||
Version 2.0.2 (2016-02-09):
|
||||
General:
|
||||
* Fix joining the room when using JID Escaping even for '@' character.
|
||||
* Fix Raw XML mode - fixes the Swiften backend.
|
||||
* Allow backends to set avatars to buddies in room - currently no backend
|
||||
uses it.
|
||||
* Set the room list per frontend user - this fixes possible information
|
||||
for networks like Skype or Facebook where the room list is not global
|
||||
per network.
|
||||
* Support usage of aliases in the rooms, so backends can use the
|
||||
network-based UID for the buddies in the room while still setting
|
||||
user-friendly aliases to them.
|
||||
* Fix leaving the room when user is connected to transport using two
|
||||
clients, but only one of them joined the room and that one disconnects
|
||||
the transport without leaving the room (For example when he just
|
||||
quits the client).
|
||||
|
||||
XMPP frontend:
|
||||
* Handle the XMPP VCard changes - updating avatar should work now for
|
||||
backends supporting it.
|
||||
|
||||
Slack frontend:
|
||||
* Slack frontend is now completely managed by the web interface, old
|
||||
way of managing (".spectrum2 ..." commands sent to Spectrum 2 bot)
|
||||
are not supported.
|
||||
* Slack channels are now created automatically on Slack when you join them
|
||||
using web-interface. The same applies also to the Main channel.
|
||||
* Logging has been improved to show the name of Slack team for each log
|
||||
line.
|
||||
|
||||
Libpurple backend:
|
||||
* Forward the room topic to frontend.
|
||||
* Fix joining the rooms on networks when the nickname in the room cannot
|
||||
be changed (Skype or Facebook). Libpurple backend changes your nickname
|
||||
to the right one in that case.
|
||||
* Show the buddies aliases in the Facebook rooms instead of Facebook
|
||||
buddies numbers.
|
||||
|
||||
Twitter backend:
|
||||
* Fix compilation with newer gcc.
|
||||
|
||||
Swiften backend:
|
||||
* Swiften backend works as before the frontends introduction.
|
||||
|
||||
Skype backend:
|
||||
* The old skype backend has been removed. Use purple-skypeweb instead.
|
||||
|
||||
Web interface:
|
||||
* Allow setting "port" and "base_location" in the config file.
|
||||
* Allow maintaining joined rooms in the Web interface for the Slack
|
||||
frontend.
|
||||
* "[identity] name" config variables is now used as a name of the
|
||||
transport.
|
||||
|
||||
Version 2.0.1 (2016-01-25):
|
||||
General:
|
||||
* Fix wrong nickname when joining room with some backends.
|
||||
* Leave room when disconnected from 3rd-party network because of an error.
|
||||
Fixes a bug when users were not able to rejoin the room after Spectrum 2
|
||||
disconnected them from 3rd-party network.
|
||||
* Fix building on Windows.
|
||||
* Support case-sensitive buddy names transparently - boost_locale is now
|
||||
needed as a new dependency.
|
||||
|
||||
Spectrum2_manager:
|
||||
* Add simple web interface, can be tested using "spectrum2_manager server".
|
||||
|
||||
XMPP frontend:
|
||||
* Show MUC feature in room disco#info response.
|
||||
|
||||
Slack frontend:
|
||||
* Slack frontend is now working as Slack app, so you need to obtain the
|
||||
client_id and client_secret from Slack to setup your own server and to
|
||||
do the OAuth2 flow, you have to setup the Spectrum2_manager Server. Read
|
||||
the documentation for more info.
|
||||
* Fix OAuth2 registration flow.
|
||||
* Fix multiple crashes when disconnected from Slack network or from
|
||||
3rd-party network.
|
||||
* Slack frontend should still be used only for testing, it is till under
|
||||
the development.
|
||||
|
||||
Libpurple backend:
|
||||
* Forward room list to frontend.
|
||||
* Fix compatibility with latest telegram-purple - You mean need to
|
||||
unregister the transport and register it again if you experience
|
||||
compatibility problems.
|
||||
|
||||
Twitter backend:
|
||||
* Fix default value of fetch timer.
|
||||
* Disable useless Curl verbose output.
|
||||
* Fix crash when populating roster when using Swiften 3.
|
||||
* Do not set status message for buddies not in Friends list - fixes a bug
|
||||
when buddies who are not in Friends list have been added to roster.
|
||||
|
||||
Version 2.0.0 (2015-12-29):
|
||||
General:
|
||||
* Fix compilation with new versions of Spectrum 2 dependencies.
|
||||
* Added support for multiple frontends - Slack frontend is the first one.
|
||||
* Log errors related to backend spawning (Show proper log message for
|
||||
example when path to backend binary is not found).
|
||||
* Set SQLite3 as default database backend.
|
||||
* Fixed disconnecting from server caused by sending VCard response
|
||||
with bad "from" attribute.
|
||||
* Added Munin plugin (Thanks to Askovpen).
|
||||
* Added support for more admin_jid JIDs (Thanks to Askovpen).
|
||||
* Fixed allowed_servers option.
|
||||
* Options from config file can now be set also using command line like
|
||||
--service.jid=domain.tld .
|
||||
* Do not send password in IQ-get registration response.
|
||||
* Added support for AdHoc commands.
|
||||
* Do not store buddies with empty name in database.
|
||||
* Improved MySQL storage backend performance.
|
||||
* Fix crash caused by two XMPP users using single PurpleAccount instance.
|
||||
* Support for [registration] allowed_usernames.
|
||||
|
||||
Spectrum2_manager:
|
||||
* Rewritten to provide more features. Check the documentation.
|
||||
|
||||
Libpurple:
|
||||
* prpl-gg: Fetch the contact list properly (#252).
|
||||
* Added support for prpl-novell as it was in Spectrum 1.
|
||||
|
||||
Twitter:
|
||||
* Added Twitter support using Twitter backend. Thanks to Sarang and
|
||||
Google Summer of Code.
|
||||
|
||||
Skype:
|
||||
* Skype backend is now deprecated, use libpurple purple-skypeweb plugin
|
||||
as a replacement.
|
||||
|
||||
Backend API:
|
||||
* Added Python NetworkPlugin class, so it is now easier to write backends
|
||||
in Python (Thanks to Sarang).
|
||||
|
||||
Version 2.0.0-beta2 (2012-03-28):
|
||||
General:
|
||||
* Fixed bug when Roster Item Exchange and subscribe stanzas were sent
|
||||
repeatedly.
|
||||
* Backends related logs now contain the backend PID.
|
||||
* Fixed username_mask setting.
|
||||
* Added new fields into statistics (backends_crashed, messages related
|
||||
stats).
|
||||
* Chatstates are now not counted as incoming messages in stats.
|
||||
* Log4cxx is now optional dependency. Without Log4cxx, Spectrum 2 logs
|
||||
to standard output.
|
||||
* Fixed crash when Log4cxx configuration file didn't exist.
|
||||
* Admin can now see "Admin" contact in server-mode.
|
||||
|
||||
libpurple:
|
||||
* Added initial support for MUC for prpl-jabber protocol.
|
||||
|
||||
LibCommuni IRC backend:
|
||||
* Fixed sending/receiving UTF8 messages.
|
||||
* Using the [registration] auto_register=1 config option, users don't
|
||||
have to register manually when connecting IRC network.
|
||||
|
||||
Skype:
|
||||
* Memory usage statistic now includes the Skype client.
|
||||
* Fixed logging issue when the logs were not stored in the proper instance
|
||||
directory.
|
||||
* Skype backend includes also Skype client memory usage into the account.
|
||||
* Working buddies adding/removing.
|
||||
* Information about missed call is now forwarded to XMPP user.
|
||||
* Fixed bug when Skype client instance wasn't killed by backend.
|
||||
|
||||
Version 2.0.0-beta (2012-02-28):
|
||||
General:
|
||||
* Added PostreSQL support (thanks to Jadestorm).
|
||||
* Added XEP-0100 (Gateway interaction) support.
|
||||
* Send presences only "from" bare JID (fixed bug with buddies appearing
|
||||
twice in the roster and potential unregistering issues).
|
||||
* Fixed potential MySQL/SQLite3 deadlocks.
|
||||
* Fixed disconnecting in server-mode when client does not send unavailable
|
||||
presence before disconnection.
|
||||
* Fixed crash in server-mode when client send its custom jabber:iq:storage
|
||||
payload.
|
||||
* Fixed registration from Pidgin.
|
||||
* Unsubscribe presence sent to some buddy doesn't disconnect the account.
|
||||
* Remote Roster requests are not sent to resources, but to bare JID.
|
||||
* Added automatic reconnection in case of non-fatal error.
|
||||
* Added more error messages.
|
||||
|
||||
Skype:
|
||||
* Initial support for Skype added, read more on
|
||||
http://spectrum.im/projects/spectrum/wiki/Spectrum_2_Admin_-_Skype_backend
|
||||
|
||||
SMSTools3:
|
||||
* Initial support for SMSTools3, read more on
|
||||
http://spectrum.im/projects/spectrum/wiki/Spectrum_2_Admin_-_SMSTools3_backend
|
||||
|
||||
version 2.0.0 alpha (2011-12-06):
|
||||
General:
|
||||
* First Spectrum 2.0.0 alpha release, check more on
|
||||
http://spectrum.im/projects/spectrum/wiki/Spectrum_200_alpha
|
91
Dockerfile
91
Dockerfile
|
@ -1,91 +0,0 @@
|
|||
FROM fedora:23
|
||||
|
||||
EXPOSE 5222
|
||||
VOLUME ["/etc/spectrum2/transports", "/var/lib/spectrum2"]
|
||||
ARG commit=unknown
|
||||
RUN echo $commit
|
||||
|
||||
# Spectrum 2
|
||||
RUN dnf install protobuf protobuf swiften gcc gcc-c++ make libpqxx-devel libpurple-devel protobuf-devel swiften-devel rpm-build avahi-devel boost-devel cmake cppunit-devel expat-devel libcommuni-devel libidn-devel libsqlite3x-devel log4cxx-devel gettext libgcrypt-devel libwebp-devel libpurple-devel zlib-devel json-glib-devel python-pip zlib-devel libjpeg-devel python-devel mysql-devel popt-devel git libevent-devel qt-devel dbus-glib-devel libcurl-devel wget mercurial libtool libgnome-keyring-devel nss-devel -y && \
|
||||
echo "---> Installing Spectrum 2" && \
|
||||
git clone git://github.com/hanzz/spectrum2.git && \
|
||||
cd spectrum2 && \
|
||||
./packaging/fedora/build_rpm.sh && \
|
||||
rpm -U /root/rpmbuild/RPMS/x86_64/*.rpm && \
|
||||
cp ./packaging/docker/run.sh /run.sh && \
|
||||
cd .. && \
|
||||
rm -rf spectrum2 && \
|
||||
rm -rf ~/rpmbuild && \
|
||||
echo "---> Installing purple-facebook" && \
|
||||
wget https://github.com/dequis/purple-facebook/releases/download/v0.9.5-9ff9acf9fa14/purple-facebook-0.9.5-9ff9acf9fa14.tar.gz && \
|
||||
tar -xf purple-facebook-0.9.5-9ff9acf9fa14.tar.gz && \
|
||||
cd purple-facebook-0.9.5-9ff9acf9fa14 && \
|
||||
./autogen.sh && \
|
||||
./configure && \
|
||||
make && \
|
||||
make install && \
|
||||
cd .. && \
|
||||
rm -rf purple-facebook* && \
|
||||
echo "---> Installing skype4pidgin" && \
|
||||
git clone git://github.com/EionRobb/skype4pidgin.git && \
|
||||
cd skype4pidgin/skypeweb && \
|
||||
make CFLAGS=-DFEDORA=1 && \
|
||||
make install && \
|
||||
cd ../.. && \
|
||||
rm -rf skype4pidgin && \
|
||||
echo "---> Installing transwhat" && \
|
||||
pip install --pre e4u protobuf python-dateutil yowsup2 Pillow==2.9.0 &&\
|
||||
git clone git://github.com/stv0g/transwhat.git &&\
|
||||
git clone git://github.com/tgalal/yowsup.git &&\
|
||||
cd transwhat &&\
|
||||
git worktree add /opt/transwhat &&\
|
||||
cd .. &&\
|
||||
cd yowsup &&\
|
||||
cp -R yowsup /opt/transwhat/yowsup &&\
|
||||
cd .. &&\
|
||||
rm -r transwhat &&\
|
||||
rm -r yowsup &&\
|
||||
rm -rf /opt/transwhat/.git &&\
|
||||
rm -rf /opt/transwhat/.gitignore &&\
|
||||
echo "---> Installing Telegram" && \
|
||||
git clone --recursive https://github.com/majn/telegram-purple && \
|
||||
cd telegram-purple && \
|
||||
./configure && \
|
||||
make && \
|
||||
make install && \
|
||||
cd .. && \
|
||||
rm -rf telegram-purple && \
|
||||
echo "---> Install Discord" && \
|
||||
git clone https://github.com/EionRobb/purple-discord.git && \
|
||||
cd purple-discord && \
|
||||
make && \
|
||||
make install && \
|
||||
cd .. && \
|
||||
rm -rf purple-discord && \
|
||||
echo "---> Install Steam" && \
|
||||
git clone https://github.com/EionRobb/pidgin-opensteamworks.git && \
|
||||
cd pidgin-opensteamworks/steam-mobile && \
|
||||
make && \
|
||||
make install && \
|
||||
cd ../.. && \
|
||||
rm -rf pidgin-opensteamworks && \
|
||||
echo "---> cleanup" && \
|
||||
rm -rf /usr/share/locale/* && \
|
||||
rm -rf /usr/share/doc/* && \
|
||||
rm -rf /usr/share/icons/* && \
|
||||
rm -rf /usr/share/cracklib* && \
|
||||
rm -rf /usr/share/hwdata* && \
|
||||
rm -rf /usr/lib64/libQtGui* && \
|
||||
rm -rf /usr/lib64/libQtSvg* && \
|
||||
rm -rf /usr/lib64/libQtDeclarative* && \
|
||||
rm -rf /usr/lib64/libQtOpenGL* && \
|
||||
rm -rf /usr/lib64/libQtScriptTools* && \
|
||||
rm -rf /usr/lib64/libQtMultimedia* && \
|
||||
rm -rf /usr/lib64/libQtHelp* && \
|
||||
rm -rf /usr/lib64/libQtDesigner* && \
|
||||
rm -rf /usr/lib64/libQt3* && \
|
||||
dnf remove protobuf-devel swiften-devel gcc gcc-c++ libpqxx-devel libevent-devel qt-devel dbus-glib-devel libpurple-devel make rpm-build avahi-devel boost-devel cmake cppunit-devel expat-devel libcommuni-devel libidn-devel libsqlite3x-devel libgcrypt-devel libwebp-devel libpurple-devel zlib-devel json-glib-devel zlib-devel libjpeg-devel python-devel log4cxx-devel mysql-devel popt-devel libcurl-devel spectrum2-debuginfo yum perl wget -y && \
|
||||
dnf clean all -y && \
|
||||
rm -rf /var/lib/rpm/*
|
||||
|
||||
CMD "/run.sh"
|
3
Gemfile
Normal file
3
Gemfile
Normal file
|
@ -0,0 +1,3 @@
|
|||
source 'https://rubygems.org'
|
||||
gem 'github-pages', group: :jekyll_plugins
|
||||
gem 'jekyll-sitemap', group: :jekyll_plugins
|
201
Gemfile.lock
Normal file
201
Gemfile.lock
Normal file
|
@ -0,0 +1,201 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
activesupport (4.2.7)
|
||||
i18n (~> 0.7)
|
||||
json (~> 1.7, >= 1.7.7)
|
||||
minitest (~> 5.1)
|
||||
thread_safe (~> 0.3, >= 0.3.4)
|
||||
tzinfo (~> 1.1)
|
||||
addressable (2.5.1)
|
||||
public_suffix (~> 2.0, >= 2.0.2)
|
||||
coffee-script (2.4.1)
|
||||
coffee-script-source
|
||||
execjs
|
||||
coffee-script-source (1.12.2)
|
||||
colorator (1.1.0)
|
||||
ethon (0.10.1)
|
||||
ffi (>= 1.3.0)
|
||||
execjs (2.7.0)
|
||||
faraday (0.12.1)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
ffi (1.9.18)
|
||||
forwardable-extended (2.6.0)
|
||||
gemoji (3.0.0)
|
||||
github-pages (134)
|
||||
activesupport (= 4.2.7)
|
||||
github-pages-health-check (= 1.3.3)
|
||||
jekyll (= 3.4.3)
|
||||
jekyll-avatar (= 0.4.2)
|
||||
jekyll-coffeescript (= 1.0.1)
|
||||
jekyll-default-layout (= 0.1.4)
|
||||
jekyll-feed (= 0.9.2)
|
||||
jekyll-gist (= 1.4.0)
|
||||
jekyll-github-metadata (= 2.3.1)
|
||||
jekyll-mentions (= 1.2.0)
|
||||
jekyll-optional-front-matter (= 0.1.2)
|
||||
jekyll-paginate (= 1.1.0)
|
||||
jekyll-readme-index (= 0.1.0)
|
||||
jekyll-redirect-from (= 0.12.1)
|
||||
jekyll-relative-links (= 0.4.0)
|
||||
jekyll-sass-converter (= 1.5.0)
|
||||
jekyll-seo-tag (= 2.2.0)
|
||||
jekyll-sitemap (= 1.0.0)
|
||||
jekyll-swiss (= 0.4.0)
|
||||
jekyll-theme-architect (= 0.0.4)
|
||||
jekyll-theme-cayman (= 0.0.4)
|
||||
jekyll-theme-dinky (= 0.0.4)
|
||||
jekyll-theme-hacker (= 0.0.4)
|
||||
jekyll-theme-leap-day (= 0.0.4)
|
||||
jekyll-theme-merlot (= 0.0.4)
|
||||
jekyll-theme-midnight (= 0.0.4)
|
||||
jekyll-theme-minimal (= 0.0.4)
|
||||
jekyll-theme-modernist (= 0.0.4)
|
||||
jekyll-theme-primer (= 0.1.8)
|
||||
jekyll-theme-slate (= 0.0.4)
|
||||
jekyll-theme-tactile (= 0.0.4)
|
||||
jekyll-theme-time-machine (= 0.0.4)
|
||||
jekyll-titles-from-headings (= 0.1.5)
|
||||
jemoji (= 0.8.0)
|
||||
kramdown (= 1.13.2)
|
||||
liquid (= 3.0.6)
|
||||
listen (= 3.0.6)
|
||||
mercenary (~> 0.3)
|
||||
minima (= 2.0.0)
|
||||
rouge (= 1.11.1)
|
||||
terminal-table (~> 1.4)
|
||||
github-pages-health-check (1.3.3)
|
||||
addressable (~> 2.3)
|
||||
net-dns (~> 0.8)
|
||||
octokit (~> 4.0)
|
||||
public_suffix (~> 2.0)
|
||||
typhoeus (~> 0.7)
|
||||
html-pipeline (2.5.0)
|
||||
activesupport (>= 2)
|
||||
nokogiri (>= 1.4)
|
||||
i18n (0.8.1)
|
||||
jekyll (3.4.3)
|
||||
addressable (~> 2.4)
|
||||
colorator (~> 1.0)
|
||||
jekyll-sass-converter (~> 1.0)
|
||||
jekyll-watch (~> 1.1)
|
||||
kramdown (~> 1.3)
|
||||
liquid (~> 3.0)
|
||||
mercenary (~> 0.3.3)
|
||||
pathutil (~> 0.9)
|
||||
rouge (~> 1.7)
|
||||
safe_yaml (~> 1.0)
|
||||
jekyll-avatar (0.4.2)
|
||||
jekyll (~> 3.0)
|
||||
jekyll-coffeescript (1.0.1)
|
||||
coffee-script (~> 2.2)
|
||||
jekyll-default-layout (0.1.4)
|
||||
jekyll (~> 3.0)
|
||||
jekyll-feed (0.9.2)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-gist (1.4.0)
|
||||
octokit (~> 4.2)
|
||||
jekyll-github-metadata (2.3.1)
|
||||
jekyll (~> 3.1)
|
||||
octokit (~> 4.0, != 4.4.0)
|
||||
jekyll-mentions (1.2.0)
|
||||
activesupport (~> 4.0)
|
||||
html-pipeline (~> 2.3)
|
||||
jekyll (~> 3.0)
|
||||
jekyll-optional-front-matter (0.1.2)
|
||||
jekyll (~> 3.0)
|
||||
jekyll-paginate (1.1.0)
|
||||
jekyll-readme-index (0.1.0)
|
||||
jekyll (~> 3.0)
|
||||
jekyll-redirect-from (0.12.1)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-relative-links (0.4.0)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-sass-converter (1.5.0)
|
||||
sass (~> 3.4)
|
||||
jekyll-seo-tag (2.2.0)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-sitemap (1.0.0)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-swiss (0.4.0)
|
||||
jekyll-theme-architect (0.0.4)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-theme-cayman (0.0.4)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-theme-dinky (0.0.4)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-theme-hacker (0.0.4)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-theme-leap-day (0.0.4)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-theme-merlot (0.0.4)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-theme-midnight (0.0.4)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-theme-minimal (0.0.4)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-theme-modernist (0.0.4)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-theme-primer (0.1.8)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-theme-slate (0.0.4)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-theme-tactile (0.0.4)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-theme-time-machine (0.0.4)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-titles-from-headings (0.1.5)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-watch (1.5.0)
|
||||
listen (~> 3.0, < 3.1)
|
||||
jemoji (0.8.0)
|
||||
activesupport (~> 4.0)
|
||||
gemoji (~> 3.0)
|
||||
html-pipeline (~> 2.2)
|
||||
jekyll (>= 3.0)
|
||||
json (1.8.6)
|
||||
kramdown (1.13.2)
|
||||
liquid (3.0.6)
|
||||
listen (3.0.6)
|
||||
rb-fsevent (>= 0.9.3)
|
||||
rb-inotify (>= 0.9.7)
|
||||
mercenary (0.3.6)
|
||||
mini_portile2 (2.1.0)
|
||||
minima (2.0.0)
|
||||
minitest (5.10.1)
|
||||
multipart-post (2.0.0)
|
||||
net-dns (0.8.0)
|
||||
nokogiri (1.7.1)
|
||||
mini_portile2 (~> 2.1.0)
|
||||
octokit (4.7.0)
|
||||
sawyer (~> 0.8.0, >= 0.5.3)
|
||||
pathutil (0.14.0)
|
||||
forwardable-extended (~> 2.6)
|
||||
public_suffix (2.0.5)
|
||||
rb-fsevent (0.9.8)
|
||||
rb-inotify (0.9.8)
|
||||
ffi (>= 0.5.0)
|
||||
rouge (1.11.1)
|
||||
safe_yaml (1.0.4)
|
||||
sass (3.4.23)
|
||||
sawyer (0.8.1)
|
||||
addressable (>= 2.3.5, < 2.6)
|
||||
faraday (~> 0.8, < 1.0)
|
||||
terminal-table (1.7.3)
|
||||
unicode-display_width (~> 1.1.1)
|
||||
thread_safe (0.3.6)
|
||||
typhoeus (0.8.0)
|
||||
ethon (>= 0.8.0)
|
||||
tzinfo (1.2.3)
|
||||
thread_safe (~> 0.1)
|
||||
unicode-display_width (1.1.3)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
github-pages
|
||||
jekyll-sitemap
|
||||
|
||||
BUNDLED WITH
|
||||
1.15.3
|
43
README.md
43
README.md
|
@ -1,9 +1,42 @@
|
|||
[](https://travis-ci.org/SpectrumIM/spectrum2)
|
||||
# Jekyll-Bootstrap
|
||||
|
||||

|
||||
The quickest way to start and publish your Jekyll powered blog. 100% compatible with GitHub pages
|
||||
|
||||
Spectrum 2 is an open source instant messaging transport.
|
||||
## Usage
|
||||
|
||||
It allows users to chat together even when they are using different IM networks.
|
||||
For all usage and documentation please see: <http://jekyllbootstrap.com>
|
||||
|
||||
It acts as a transport layer between the users as showed in the animation above.
|
||||
## Version
|
||||
|
||||
0.2.13 - stable and versioned using [semantic versioning](http://semver.org/).
|
||||
|
||||
## Contributing
|
||||
|
||||
This repository tracks 2 projects:
|
||||
|
||||
- **Jekyll-Bootstrap Framework.**
|
||||
The framework for which users should clone and build their blog on top of is available in the master branch.
|
||||
|
||||
To contribute to the framework please make sure to checkout your branch based on `jb-development`!!
|
||||
This is very important as it allows me to accept your pull request without having to publish a public version release.
|
||||
|
||||
Small, atomic Features, bugs, etc.
|
||||
Use the `jb-development` branch but note it will likely change fast as pull requests are accepted.
|
||||
Please rebase as often as possible when working.
|
||||
Work on small, atomic features/bugs to avoid upstream commits affecting/breaking your development work.
|
||||
|
||||
For Big Features or major API extensions/edits:
|
||||
This is the one case where I'll accept pull-requests based off the master branch.
|
||||
This allows you to work in isolation but it means I'll have to manually merge your work into the next public release.
|
||||
Translation : it might take a bit longer so please be patient! (but sincerely thank you).
|
||||
|
||||
- **Jekyll-Bootstrap Documentation Website.**
|
||||
The documentation website at <http://jekyllbootstrap.com> is maintained in the gh-pages branch.
|
||||
Please fork and contribute documentation additions to this branch only.
|
||||
|
||||
The master and gh-pages branch do not share the same ancestry. Please treat them as completely separate git repositories!
|
||||
|
||||
|
||||
## License
|
||||
|
||||
[Creative Commons](http://creativecommons.org/licenses/by-nc-sa/3.0/)
|
||||
|
|
308
Rakefile
Normal file
308
Rakefile
Normal file
|
@ -0,0 +1,308 @@
|
|||
require "rubygems"
|
||||
require 'rake'
|
||||
require 'yaml'
|
||||
require 'time'
|
||||
|
||||
SOURCE = "."
|
||||
CONFIG = {
|
||||
'version' => "0.2.13",
|
||||
'themes' => File.join(SOURCE, "_includes", "themes"),
|
||||
'layouts' => File.join(SOURCE, "_layouts"),
|
||||
'posts' => File.join(SOURCE, "_posts"),
|
||||
'post_ext' => "md",
|
||||
'theme_package_version' => "0.1.0"
|
||||
}
|
||||
|
||||
# Path configuration helper
|
||||
module JB
|
||||
class Path
|
||||
SOURCE = "."
|
||||
Paths = {
|
||||
:layouts => "_layouts",
|
||||
:themes => "_includes/themes",
|
||||
:theme_assets => "assets/themes",
|
||||
:theme_packages => "_theme_packages",
|
||||
:posts => "_posts"
|
||||
}
|
||||
|
||||
def self.base
|
||||
SOURCE
|
||||
end
|
||||
|
||||
# build a path relative to configured path settings.
|
||||
def self.build(path, opts = {})
|
||||
opts[:root] ||= SOURCE
|
||||
path = "#{opts[:root]}/#{Paths[path.to_sym]}/#{opts[:node]}".split("/")
|
||||
path.compact!
|
||||
File.__send__ :join, path
|
||||
end
|
||||
|
||||
end #Path
|
||||
end #JB
|
||||
|
||||
# Usage: rake post title="A Title" [date="2012-02-09"]
|
||||
desc "Begin a new post in #{CONFIG['posts']}"
|
||||
task :post do
|
||||
abort("rake aborted: '#{CONFIG['posts']}' directory not found.") unless FileTest.directory?(CONFIG['posts'])
|
||||
title = ENV["title"] || "new-post"
|
||||
slug = title.downcase.strip.gsub(' ', '-').gsub(/[^\w-]/, '')
|
||||
begin
|
||||
date = (ENV['date'] ? Time.parse(ENV['date']) : Time.now).strftime('%Y-%m-%d')
|
||||
rescue Exception => e
|
||||
puts "Error - date format must be YYYY-MM-DD, please check you typed it correctly!"
|
||||
exit -1
|
||||
end
|
||||
filename = File.join(CONFIG['posts'], "#{date}-#{slug}.#{CONFIG['post_ext']}")
|
||||
if File.exist?(filename)
|
||||
abort("rake aborted!") if ask("#{filename} already exists. Do you want to overwrite?", ['y', 'n']) == 'n'
|
||||
end
|
||||
|
||||
puts "Creating new post: #{filename}"
|
||||
open(filename, 'w') do |post|
|
||||
post.puts "---"
|
||||
post.puts "layout: post"
|
||||
post.puts "title: \"#{title.gsub(/-/,' ')}\""
|
||||
post.puts 'description: ""'
|
||||
post.puts "category: "
|
||||
post.puts "tags: []"
|
||||
post.puts "---"
|
||||
post.puts "{% include JB/setup %}"
|
||||
end
|
||||
end # task :post
|
||||
|
||||
# Usage: rake page name="about.html"
|
||||
# You can also specify a sub-directory path.
|
||||
# If you don't specify a file extention we create an index.html at the path specified
|
||||
desc "Create a new page."
|
||||
task :page do
|
||||
name = ENV["name"] || "new-page.md"
|
||||
filename = File.join(SOURCE, "#{name}")
|
||||
filename = File.join(filename, "index.html") if File.extname(filename) == ""
|
||||
title = File.basename(filename, File.extname(filename)).gsub(/[\W\_]/, " ").gsub(/\b\w/){$&.upcase}
|
||||
if File.exist?(filename)
|
||||
abort("rake aborted!") if ask("#{filename} already exists. Do you want to overwrite?", ['y', 'n']) == 'n'
|
||||
end
|
||||
|
||||
mkdir_p File.dirname(filename)
|
||||
puts "Creating new page: #{filename}"
|
||||
open(filename, 'w') do |post|
|
||||
post.puts "---"
|
||||
post.puts "layout: page"
|
||||
post.puts "title: \"#{title}\""
|
||||
post.puts 'description: ""'
|
||||
post.puts "---"
|
||||
post.puts "{% include JB/setup %}"
|
||||
end
|
||||
end # task :page
|
||||
|
||||
desc "Launch preview environment"
|
||||
task :preview do
|
||||
system "jekyll --auto --server"
|
||||
end # task :preview
|
||||
|
||||
# Public: Alias - Maintains backwards compatability for theme switching.
|
||||
task :switch_theme => "theme:switch"
|
||||
|
||||
namespace :theme do
|
||||
|
||||
# Public: Switch from one theme to another for your blog.
|
||||
#
|
||||
# name - String, Required. name of the theme you want to switch to.
|
||||
# The the theme must be installed into your JB framework.
|
||||
#
|
||||
# Examples
|
||||
#
|
||||
# rake theme:switch name="the-program"
|
||||
#
|
||||
# Returns Success/failure messages.
|
||||
desc "Switch between Jekyll-bootstrap themes."
|
||||
task :switch do
|
||||
theme_name = ENV["name"].to_s
|
||||
theme_path = File.join(CONFIG['themes'], theme_name)
|
||||
settings_file = File.join(theme_path, "settings.yml")
|
||||
non_layout_files = ["settings.yml"]
|
||||
|
||||
abort("rake aborted: name cannot be blank") if theme_name.empty?
|
||||
abort("rake aborted: '#{theme_path}' directory not found.") unless FileTest.directory?(theme_path)
|
||||
abort("rake aborted: '#{CONFIG['layouts']}' directory not found.") unless FileTest.directory?(CONFIG['layouts'])
|
||||
|
||||
Dir.glob("#{theme_path}/*") do |filename|
|
||||
next if non_layout_files.include?(File.basename(filename).downcase)
|
||||
puts "Generating '#{theme_name}' layout: #{File.basename(filename)}"
|
||||
|
||||
open(File.join(CONFIG['layouts'], File.basename(filename)), 'w') do |page|
|
||||
if File.basename(filename, ".html").downcase == "default"
|
||||
page.puts "---"
|
||||
page.puts File.read(settings_file) if File.exist?(settings_file)
|
||||
page.puts "---"
|
||||
else
|
||||
page.puts "---"
|
||||
page.puts "layout: default"
|
||||
page.puts "---"
|
||||
end
|
||||
page.puts "{% include JB/setup %}"
|
||||
page.puts "{% include themes/#{theme_name}/#{File.basename(filename)} %}"
|
||||
end
|
||||
end
|
||||
|
||||
puts "=> Theme successfully switched!"
|
||||
puts "=> Reload your web-page to check it out =)"
|
||||
end # task :switch
|
||||
|
||||
# Public: Install a theme using the theme packager.
|
||||
# Version 0.1.0 simple 1:1 file matching.
|
||||
#
|
||||
# git - String, Optional path to the git repository of the theme to be installed.
|
||||
# name - String, Optional name of the theme you want to install.
|
||||
# Passing name requires that the theme package already exist.
|
||||
#
|
||||
# Examples
|
||||
#
|
||||
# rake theme:install git="https://github.com/jekyllbootstrap/theme-twitter.git"
|
||||
# rake theme:install name="cool-theme"
|
||||
#
|
||||
# Returns Success/failure messages.
|
||||
desc "Install theme"
|
||||
task :install do
|
||||
if ENV["git"]
|
||||
manifest = theme_from_git_url(ENV["git"])
|
||||
name = manifest["name"]
|
||||
else
|
||||
name = ENV["name"].to_s.downcase
|
||||
end
|
||||
|
||||
packaged_theme_path = JB::Path.build(:theme_packages, :node => name)
|
||||
|
||||
abort("rake aborted!
|
||||
=> ERROR: 'name' cannot be blank") if name.empty?
|
||||
abort("rake aborted!
|
||||
=> ERROR: '#{packaged_theme_path}' directory not found.
|
||||
=> Installable themes can be added via git. You can find some here: http://github.com/jekyllbootstrap
|
||||
=> To download+install run: `rake theme:install git='[PUBLIC-CLONE-URL]'`
|
||||
=> example : rake theme:install git='git@github.com:jekyllbootstrap/theme-the-program.git'
|
||||
") unless FileTest.directory?(packaged_theme_path)
|
||||
|
||||
manifest = verify_manifest(packaged_theme_path)
|
||||
|
||||
# Get relative paths to packaged theme files
|
||||
# Exclude directories as they'll be recursively created. Exclude meta-data files.
|
||||
packaged_theme_files = []
|
||||
FileUtils.cd(packaged_theme_path) {
|
||||
Dir.glob("**/*.*") { |f|
|
||||
next if ( FileTest.directory?(f) || f =~ /^(manifest|readme|packager)/i )
|
||||
packaged_theme_files << f
|
||||
}
|
||||
}
|
||||
|
||||
# Mirror each file into the framework making sure to prompt if already exists.
|
||||
packaged_theme_files.each do |filename|
|
||||
file_install_path = File.join(JB::Path.base, filename)
|
||||
if File.exist? file_install_path
|
||||
next if ask("#{file_install_path} already exists. Do you want to overwrite?", ['y', 'n']) == 'n'
|
||||
else
|
||||
mkdir_p File.dirname(file_install_path)
|
||||
cp_r File.join(packaged_theme_path, filename), file_install_path
|
||||
end
|
||||
end
|
||||
|
||||
puts "=> #{name} theme has been installed!"
|
||||
puts "=> ---"
|
||||
if ask("=> Want to switch themes now?", ['y', 'n']) == 'y'
|
||||
system("rake switch_theme name='#{name}'")
|
||||
end
|
||||
end
|
||||
|
||||
# Public: Package a theme using the theme packager.
|
||||
# The theme must be structured using valid JB API.
|
||||
# In other words packaging is essentially the reverse of installing.
|
||||
#
|
||||
# name - String, Required name of the theme you want to package.
|
||||
#
|
||||
# Examples
|
||||
#
|
||||
# rake theme:package name="twitter"
|
||||
#
|
||||
# Returns Success/failure messages.
|
||||
desc "Package theme"
|
||||
task :package do
|
||||
name = ENV["name"].to_s.downcase
|
||||
theme_path = JB::Path.build(:themes, :node => name)
|
||||
asset_path = JB::Path.build(:theme_assets, :node => name)
|
||||
|
||||
abort("rake aborted: name cannot be blank") if name.empty?
|
||||
abort("rake aborted: '#{theme_path}' directory not found.") unless FileTest.directory?(theme_path)
|
||||
abort("rake aborted: '#{asset_path}' directory not found.") unless FileTest.directory?(asset_path)
|
||||
|
||||
## Mirror theme's template directory (_includes)
|
||||
packaged_theme_path = JB::Path.build(:themes, :root => JB::Path.build(:theme_packages, :node => name))
|
||||
mkdir_p packaged_theme_path
|
||||
cp_r theme_path, packaged_theme_path
|
||||
|
||||
## Mirror theme's asset directory
|
||||
packaged_theme_assets_path = JB::Path.build(:theme_assets, :root => JB::Path.build(:theme_packages, :node => name))
|
||||
mkdir_p packaged_theme_assets_path
|
||||
cp_r asset_path, packaged_theme_assets_path
|
||||
|
||||
## Log packager version
|
||||
packager = {"packager" => {"version" => CONFIG["theme_package_version"].to_s } }
|
||||
open(JB::Path.build(:theme_packages, :node => "#{name}/packager.yml"), "w") do |page|
|
||||
page.puts packager.to_yaml
|
||||
end
|
||||
|
||||
puts "=> '#{name}' theme is packaged and available at: #{JB::Path.build(:theme_packages, :node => name)}"
|
||||
end
|
||||
|
||||
end # end namespace :theme
|
||||
|
||||
# Internal: Download and process a theme from a git url.
|
||||
# Notice we don't know the name of the theme until we look it up in the manifest.
|
||||
# So we'll have to change the folder name once we get the name.
|
||||
#
|
||||
# url - String, Required url to git repository.
|
||||
#
|
||||
# Returns theme manifest hash
|
||||
def theme_from_git_url(url)
|
||||
tmp_path = JB::Path.build(:theme_packages, :node => "_tmp")
|
||||
abort("rake aborted: system call to git clone failed") if !system("git clone #{url} #{tmp_path}")
|
||||
manifest = verify_manifest(tmp_path)
|
||||
new_path = JB::Path.build(:theme_packages, :node => manifest["name"])
|
||||
if File.exist?(new_path) && ask("=> #{new_path} theme package already exists. Override?", ['y', 'n']) == 'n'
|
||||
remove_dir(tmp_path)
|
||||
abort("rake aborted: '#{manifest["name"]}' already exists as theme package.")
|
||||
end
|
||||
|
||||
remove_dir(new_path) if File.exist?(new_path)
|
||||
mv(tmp_path, new_path)
|
||||
manifest
|
||||
end
|
||||
|
||||
# Internal: Process theme package manifest file.
|
||||
#
|
||||
# theme_path - String, Required. File path to theme package.
|
||||
#
|
||||
# Returns theme manifest hash
|
||||
def verify_manifest(theme_path)
|
||||
manifest_path = File.join(theme_path, "manifest.yml")
|
||||
manifest_file = File.open( manifest_path )
|
||||
abort("rake aborted: repo must contain valid manifest.yml") unless File.exist? manifest_file
|
||||
manifest = YAML.load( manifest_file )
|
||||
manifest_file.close
|
||||
manifest
|
||||
end
|
||||
|
||||
def ask(message, valid_options)
|
||||
if valid_options
|
||||
answer = get_stdin("#{message} #{valid_options.to_s.gsub(/"/, '').gsub(/, /,'/')} ") while !valid_options.include?(answer)
|
||||
else
|
||||
answer = get_stdin(message)
|
||||
end
|
||||
answer
|
||||
end
|
||||
|
||||
def get_stdin(message)
|
||||
print message
|
||||
STDIN.gets.chomp
|
||||
end
|
||||
|
||||
#Load custom rake scripts
|
||||
Dir['_rake/*.rake'].each { |r| load r }
|
128
_config.yml
Normal file
128
_config.yml
Normal file
|
@ -0,0 +1,128 @@
|
|||
# This is the default format.
|
||||
# For more see: https://github.com/mojombo/jekyll/wiki/Permalinks
|
||||
#permalink: /:categories/:year/:month/:day/:title
|
||||
|
||||
exclude: [".rvmrc", ".rbenv-version", "README.md", "Rakefile", "changelog.md"]
|
||||
#highlighter: pygments
|
||||
|
||||
# Themes are encouraged to use these universal variables
|
||||
# so be sure to set them if your theme uses them.
|
||||
#
|
||||
title : Spectrum 2
|
||||
tagline: Spectrum 2 transport
|
||||
author :
|
||||
name : Jan Kaluza
|
||||
email : hanzz.k@gmail.com
|
||||
github : hanzz
|
||||
# twitter : username
|
||||
# feedburner : feedname
|
||||
|
||||
# The production_url is only used when full-domain names are needed
|
||||
# such as sitemap.txt
|
||||
# Most places will/should use BASE_PATH to make the urls
|
||||
#
|
||||
# If you have set a CNAME (pages.github.com) set your custom domain here.
|
||||
# Else if you are pushing to username.github.com, replace with your username.
|
||||
# Finally if you are pushing to a GitHub project page, include the project name at the end.
|
||||
#
|
||||
production_url : http://spectrum.im
|
||||
|
||||
# All Jekyll-Bootstrap specific configurations are namespaced into this hash
|
||||
#
|
||||
JB :
|
||||
version : 0.2.13
|
||||
|
||||
# All links will be namespaced by BASE_PATH if defined.
|
||||
# Links in your website should always be prefixed with {{BASE_PATH}}
|
||||
# however this value will be dynamically changed depending on your deployment situation.
|
||||
#
|
||||
# CNAME (http://yourcustomdomain.com)
|
||||
# DO NOT SET BASE_PATH
|
||||
# (urls will be prefixed with "/" and work relatively)
|
||||
#
|
||||
# GitHub Pages (http://username.github.com)
|
||||
# DO NOT SET BASE_PATH
|
||||
# (urls will be prefixed with "/" and work relatively)
|
||||
#
|
||||
# GitHub Project Pages (http://username.github.com/project-name)
|
||||
#
|
||||
# A GitHub Project site exists in the `gh-pages` branch of one of your repositories.
|
||||
# REQUIRED! Set BASE_PATH to: http://username.github.com/project-name
|
||||
#
|
||||
# CAUTION:
|
||||
# - When in Localhost, your site will run from root "/" regardless of BASE_PATH
|
||||
# - Only the following values are falsy: ["", null, false]
|
||||
# - When setting BASE_PATH it must be a valid url.
|
||||
# This means always setting the protocol (http|https) or prefixing with "/"
|
||||
BASE_PATH : http://spectrum.im
|
||||
|
||||
# By default, the asset_path is automatically defined relative to BASE_PATH plus the enabled theme.
|
||||
# ex: [BASE_PATH]/assets/themes/[THEME-NAME]
|
||||
#
|
||||
# Override this by defining an absolute path to assets here.
|
||||
# ex:
|
||||
# http://s3.amazonaws.com/yoursite/themes/watermelon
|
||||
# /assets
|
||||
#
|
||||
ASSET_PATH : http://spectrum.im
|
||||
|
||||
# These paths are to the main pages Jekyll-Bootstrap ships with.
|
||||
# Some JB helpers refer to these paths; change theme here if needed.
|
||||
#
|
||||
#archive_path: /archive.html
|
||||
#categories_path : /categories.html
|
||||
#tags_path : /tags.html
|
||||
|
||||
# Settings for comments helper
|
||||
# Set 'provider' to the comment provider you want to use.
|
||||
# Set 'provider' to false to turn commenting off globally.
|
||||
#
|
||||
# comments :
|
||||
# provider : disqus
|
||||
# disqus :
|
||||
# short_name : jekyllbootstrap
|
||||
# livefyre :
|
||||
# site_id : 123
|
||||
# intensedebate :
|
||||
# account : 123abc
|
||||
# facebook :
|
||||
# appid : 123
|
||||
# num_posts: 5
|
||||
# width: 580
|
||||
# colorscheme: light
|
||||
|
||||
# Settings for analytics helper
|
||||
# Set 'provider' to the analytics provider you want to use.
|
||||
# Set 'provider' to false to turn analytics off globally.
|
||||
#
|
||||
# analytics :
|
||||
# provider : google
|
||||
# google :
|
||||
# tracking_id : 'UA-123-12'
|
||||
# getclicky :
|
||||
# site_id :
|
||||
# mixpanel :
|
||||
# token : '_MIXPANEL_TOKEN_'
|
||||
|
||||
# Settings for sharing helper.
|
||||
# Sharing is for things like tweet, plusone, like, reddit buttons etc.
|
||||
# Set 'provider' to the sharing provider you want to use.
|
||||
# Set 'provider' to false to turn sharing off globally.
|
||||
#
|
||||
# sharing :
|
||||
# provider : false
|
||||
|
||||
# Settings for all other include helpers can be defined by creating
|
||||
# a hash with key named for the given helper. ex:
|
||||
#
|
||||
# pages_list :
|
||||
# provider : "custom"
|
||||
#
|
||||
# Setting any helper's provider to 'custom' will bypass the helper code
|
||||
# and include your custom code. Your custom file must be defined at:
|
||||
# ./_includes/custom/[HELPER]
|
||||
# where [HELPER] is the name of the helper you are overriding.
|
||||
|
||||
gems:
|
||||
- jekyll-redirect-from
|
||||
- jekyll-sitemap
|
14
_includes/JB/analytics
Normal file
14
_includes/JB/analytics
Normal file
|
@ -0,0 +1,14 @@
|
|||
{% if site.safe and site.JB.analytics.provider and page.JB.analytics != false %}
|
||||
|
||||
{% case site.JB.analytics.provider %}
|
||||
{% when "google" %}
|
||||
{% include JB/analytics-providers/google %}
|
||||
{% when "getclicky" %}
|
||||
{% include JB/analytics-providers/getclicky %}
|
||||
{% when "mixpanel" %}
|
||||
{% include JB/analytics-providers/mixpanel %}
|
||||
{% when "custom" %}
|
||||
{% include custom/analytics %}
|
||||
{% endcase %}
|
||||
|
||||
{% endif %}
|
12
_includes/JB/analytics-providers/getclicky
Normal file
12
_includes/JB/analytics-providers/getclicky
Normal file
|
@ -0,0 +1,12 @@
|
|||
<script type="text/javascript">
|
||||
var clicky_site_ids = clicky_site_ids || [];
|
||||
clicky_site_ids.push({{ site.JB.analytics.getclicky.site_id }});
|
||||
(function() {
|
||||
var s = document.createElement('script');
|
||||
s.type = 'text/javascript';
|
||||
s.async = true;
|
||||
s.src = '//static.getclicky.com/js';
|
||||
( document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0] ).appendChild( s );
|
||||
})();
|
||||
</script>
|
||||
<noscript><p><img alt="Clicky" width="1" height="1" src="//in.getclicky.com/{{ site.JB.analytics.getclicky.site_id }}ns.gif" /></p></noscript>
|
11
_includes/JB/analytics-providers/google
Normal file
11
_includes/JB/analytics-providers/google
Normal file
|
@ -0,0 +1,11 @@
|
|||
<script type="text/javascript">
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', '{{ site.JB.analytics.google.tracking_id }}']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
</script>
|
11
_includes/JB/analytics-providers/mixpanel
Normal file
11
_includes/JB/analytics-providers/mixpanel
Normal file
|
@ -0,0 +1,11 @@
|
|||
<script type="text/javascript">
|
||||
var mpq = [];
|
||||
mpq.push(["init", "{{ site.JB.analytics.mixpanel.token}}"]);
|
||||
(function(){var b,a,e,d,c;b=document.createElement("script");b.type="text/javascript";
|
||||
b.async=true;b.src=(document.location.protocol==="https:"?"https:":"http:")+
|
||||
"//api.mixpanel.com/site_media/js/api/mixpanel.js";a=document.getElementsByTagName("script")[0];
|
||||
a.parentNode.insertBefore(b,a);e=function(f){return function(){mpq.push(
|
||||
[f].concat(Array.prototype.slice.call(arguments,0)))}};d=["init","track","track_links",
|
||||
"track_forms","register","register_once","identify","name_tag","set_config"];for(c=0;c<
|
||||
d.length;c++){mpq[d[c]]=e(d[c])}})();
|
||||
</script>
|
37
_includes/JB/categories_list
Normal file
37
_includes/JB/categories_list
Normal file
|
@ -0,0 +1,37 @@
|
|||
{% comment %}<!--
|
||||
The categories_list include is a listing helper for categories.
|
||||
Usage:
|
||||
1) assign the 'categories_list' variable to a valid array of tags.
|
||||
2) include JB/categories_list
|
||||
example:
|
||||
<ul>
|
||||
{% assign categories_list = site.categories %}
|
||||
{% include JB/categories_list %}
|
||||
</ul>
|
||||
|
||||
Notes:
|
||||
Categories can be either a Hash of Category objects (hashes) or an Array of category-names (strings).
|
||||
The encapsulating 'if' statement checks whether categories_list is a Hash or Array.
|
||||
site.categories is a Hash while page.categories is an array.
|
||||
|
||||
This helper can be seen in use at: ../_layouts/default.html
|
||||
-->{% endcomment %}
|
||||
|
||||
{% if site.JB.categories_list.provider == "custom" %}
|
||||
{% include custom/categories_list %}
|
||||
{% else %}
|
||||
{% if categories_list.first[0] == null %}
|
||||
{% for category in categories_list %}
|
||||
<li><a href="{{ BASE_PATH }}{{ site.JB.categories_path }}#{{ category }}-ref">
|
||||
{{ category | join: "/" }} <span>{{ site.categories[category].size }}</span>
|
||||
</a></li>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% for category in categories_list %}
|
||||
<li><a href="{{ BASE_PATH }}{{ site.JB.categories_path }}#{{ category[0] }}-ref">
|
||||
{{ category[0] | join: "/" }} <span>{{ category[1].size }}</span>
|
||||
</a></li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% assign categories_list = nil %}
|
16
_includes/JB/comments
Normal file
16
_includes/JB/comments
Normal file
|
@ -0,0 +1,16 @@
|
|||
{% if site.JB.comments.provider and page.comments != false %}
|
||||
|
||||
{% case site.JB.comments.provider %}
|
||||
{% when "disqus" %}
|
||||
{% include JB/comments-providers/disqus %}
|
||||
{% when "livefyre" %}
|
||||
{% include JB/comments-providers/livefyre %}
|
||||
{% when "intensedebate" %}
|
||||
{% include JB/comments-providers/intensedebate %}
|
||||
{% when "facebook" %}
|
||||
{% include JB/comments-providers/facebook %}
|
||||
{% when "custom" %}
|
||||
{% include custom/comments %}
|
||||
{% endcase %}
|
||||
|
||||
{% endif %}
|
14
_includes/JB/comments-providers/disqus
Normal file
14
_includes/JB/comments-providers/disqus
Normal file
|
@ -0,0 +1,14 @@
|
|||
<div id="disqus_thread"></div>
|
||||
<script type="text/javascript">
|
||||
{% if site.safe == false %}var disqus_developer = 1;{% endif %}
|
||||
var disqus_shortname = '{{ site.JB.comments.disqus.short_name }}'; // required: replace example with your forum shortname
|
||||
{% if page.wordpress_id %}var disqus_identifier = '{{page.wordpress_id}} {{site.production_url}}/?p={{page.wordpress_id}}';{% endif %}
|
||||
/* * * DON'T EDIT BELOW THIS LINE * * */
|
||||
(function() {
|
||||
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
|
||||
dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
|
||||
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
|
||||
})();
|
||||
</script>
|
||||
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
|
||||
<a href="http://disqus.com" class="dsq-brlink">blog comments powered by <span class="logo-disqus">Disqus</span></a>
|
9
_includes/JB/comments-providers/facebook
Normal file
9
_includes/JB/comments-providers/facebook
Normal file
|
@ -0,0 +1,9 @@
|
|||
<div id="fb-root"></div>
|
||||
<script>(function(d, s, id) {
|
||||
var js, fjs = d.getElementsByTagName(s)[0];
|
||||
if (d.getElementById(id)) return;
|
||||
js = d.createElement(s); js.id = id;
|
||||
js.src = "//connect.facebook.net/en_US/all.js#xfbml=1&appId={{ site.JB.comments.facebook.appid }}";
|
||||
fjs.parentNode.insertBefore(js, fjs);
|
||||
}(document, 'script', 'facebook-jssdk'));</script>
|
||||
<div class="fb-comments" data-href="{{ site.production_url }}" data-num-posts="{{ site.JB.comments.facebook.num_posts }}" data-width="{{ site.JB.comments.facebook.width }}" data-colorscheme="{{ site.JB.comments.facebook.colorscheme }}"></div>
|
6
_includes/JB/comments-providers/intensedebate
Normal file
6
_includes/JB/comments-providers/intensedebate
Normal file
|
@ -0,0 +1,6 @@
|
|||
<script>
|
||||
var idcomments_acct = '{{ site.JB.comments.intensedebate.account }}';
|
||||
var idcomments_post_id;
|
||||
var idcomments_post_url;
|
||||
</script>
|
||||
<script type="text/javascript" src="http://www.intensedebate.com/js/genericLinkWrapperV2.js"></script>
|
6
_includes/JB/comments-providers/livefyre
Normal file
6
_includes/JB/comments-providers/livefyre
Normal file
|
@ -0,0 +1,6 @@
|
|||
<script type='text/javascript' src='http://zor.livefyre.com/wjs/v1.0/javascripts/livefyre_init.js'></script>
|
||||
<script type='text/javascript'>
|
||||
var fyre = LF({
|
||||
site_id: {{ site.JB.comments.livefyre.site_id }}
|
||||
});
|
||||
</script>
|
32
_includes/JB/liquid_raw
Normal file
32
_includes/JB/liquid_raw
Normal file
|
@ -0,0 +1,32 @@
|
|||
{% comment%}<!--
|
||||
The liquid_raw helper is a way to display raw liquid code, as opposed to parsing it.
|
||||
Normally you'd use Liquid's built in 'raw' tag.
|
||||
The problem is GitHub Jekyll does not support the current Liquid release.
|
||||
GitHub Jekyll supports the deprecated 'literal' tag.
|
||||
Using one will break the other if you plan to deploy to GitHub pages.
|
||||
see: https://github.com/mojombo/jekyll/issues/425
|
||||
|
||||
Since I don't want to mess with Liquid versions, I'll just rewrite the way I
|
||||
intend to give liquid examples. It's not an elegant by any means:
|
||||
|
||||
Usage:
|
||||
1) Define a 'text' variable with the block of liquid code you intend to display.
|
||||
2) Pass the text variable to include JB/liquid_raw
|
||||
|
||||
example:
|
||||
{% capture text %}|.% for tag in tags_list %.|
|
||||
<li><a href="|.{ site.var.tags_path }.||.{ tag[0] }.|-ref">|.{ tag[0] }.| <span>|.{tag[1].size}.|</span></a></li>
|
||||
|.% endfor %.|
|
||||
|
||||
|.% assign tags_list = null %.|{% endcapture %}
|
||||
{% include JB/liquid_raw %}
|
||||
|
||||
As seen here, you must use "|." and ".|" as opening and closing brackets.
|
||||
-->{% endcomment%}
|
||||
|
||||
{% if site.JB.liquid_raw.provider == "custom" %}
|
||||
{% include custom/liquid_raw %}
|
||||
{% else %}
|
||||
<pre><code>{{text | replace:"|.", "{" | replace:".|", "}" | replace:">", ">" | replace:"<", "<" }}</code></pre>
|
||||
{% endif %}
|
||||
{% assign text = nil %}
|
39
_includes/JB/pages_list
Normal file
39
_includes/JB/pages_list
Normal file
|
@ -0,0 +1,39 @@
|
|||
{% comment %}<!--
|
||||
The pages_list include is a listing helper.
|
||||
Usage:
|
||||
1) assign the 'pages_list' variable to a valid array of pages or posts.
|
||||
2) include JB/pages_list
|
||||
example:
|
||||
<ul>
|
||||
{% assign pages_list = site.pages %}
|
||||
{% include JB/pages_list %}
|
||||
</ul>
|
||||
|
||||
Grouping: (optional):
|
||||
assign the 'group' variable to constrain the list to only pages/posts
|
||||
in the given group. Note you must define the group manually in the page/post
|
||||
meta-data to use this feature.
|
||||
Grouping is mainly helpful for non-post pages.
|
||||
If you want to group posts, it's easier/better to tag them, then pass the tagged posts array.
|
||||
i.e. site.tags.cool_tag (this returns an array of posts tagged: cool_tag)
|
||||
|
||||
This helper can be seen in use at: ../_layouts/default.html
|
||||
-->{% endcomment %}
|
||||
|
||||
{% if site.JB.pages_list.provider == "custom" %}
|
||||
{% include custom/pages_list %}
|
||||
{% else %}
|
||||
{% for node in pages_list %}
|
||||
{% if node.title != null %}
|
||||
{% if group == null or group == node.group %}
|
||||
{% if page.url == node.url %}
|
||||
<li class="active"><a href="{{ BASE_PATH }}{{node.url}}" class="active">{{node.title}}</a></li>
|
||||
{% else %}
|
||||
<li><a href="{{ BASE_PATH }}{{node.url}}">{{node.title}}</a></li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% assign pages_list = nil %}
|
||||
{% assign group = nil %}
|
55
_includes/JB/posts_collate
Normal file
55
_includes/JB/posts_collate
Normal file
|
@ -0,0 +1,55 @@
|
|||
{% comment %}<!--
|
||||
Collate_posts helper. Collated posts by year and month.
|
||||
Usage:
|
||||
1) assign the 'posts_collate' variable to a valid array of posts.
|
||||
2) include JB/posts_collate
|
||||
example:
|
||||
{% assign posts_collate = site.posts %}
|
||||
{% include JB/posts_collate %}
|
||||
|
||||
Ordering:
|
||||
Posts are displayed in reverse chronological order.
|
||||
For normal chronological order:
|
||||
1) Change the for loop to this:
|
||||
=> 'for post in site.posts reversed'
|
||||
2) Next make sure to change 'post.previous.date' to:
|
||||
=> 'post.next.date'
|
||||
|
||||
-->{% endcomment %}
|
||||
|
||||
{% if site.JB.posts_collate.provider == "custom" %}
|
||||
{% include custom/posts_collate %}
|
||||
{% else %}
|
||||
{% for post in posts_collate %}
|
||||
{% capture this_year %}{{ post.date | date: "%Y" }}{% endcapture %}
|
||||
{% capture this_month %}{{ post.date | date: "%B" }}{% endcapture %}
|
||||
{% capture next_year %}{{ post.previous.date | date: "%Y" }}{% endcapture %}
|
||||
{% capture next_month %}{{ post.previous.date | date: "%B" }}{% endcapture %}
|
||||
|
||||
{% if forloop.first %}
|
||||
<h2>{{this_year}}</h2>
|
||||
<h3>{{this_month}}</h3>
|
||||
<ul>
|
||||
{% endif %}
|
||||
|
||||
<li><span>{{ post.date | date: "%B %e, %Y" }}</span> » <a href="{{ BASE_PATH }}{{ post.url }}">{{ post.title }}</a></li>
|
||||
|
||||
{% if forloop.last %}
|
||||
</ul>
|
||||
{% else %}
|
||||
{% if this_year != next_year %}
|
||||
</ul>
|
||||
<h2>{{next_year}}</h2>
|
||||
<h3>{{next_month}}</h3>
|
||||
<ul>
|
||||
{% else %}
|
||||
{% if this_month != next_month %}
|
||||
</ul>
|
||||
<h3>{{next_month}}</h3>
|
||||
<ul>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% assign posts_collate = nil %}
|
22
_includes/JB/setup
Normal file
22
_includes/JB/setup
Normal file
|
@ -0,0 +1,22 @@
|
|||
{% capture jbcache %}
|
||||
<!--
|
||||
- Dynamically set liquid variables for working with URLs/paths
|
||||
-->
|
||||
{% if site.JB.setup.provider == "custom" %}
|
||||
{% include custom/setup %}
|
||||
{% else %}
|
||||
{% if site.safe and site.JB.BASE_PATH and site.JB.BASE_PATH != '' %}
|
||||
{% assign BASE_PATH = site.JB.BASE_PATH %}
|
||||
{% assign HOME_PATH = site.JB.BASE_PATH %}
|
||||
{% else %}
|
||||
{% assign BASE_PATH = nil %}
|
||||
{% assign HOME_PATH = "/" %}
|
||||
{% endif %}
|
||||
|
||||
{% if site.JB.ASSET_PATH %}
|
||||
{% assign ASSET_PATH = site.JB.ASSET_PATH %}
|
||||
{% else %}
|
||||
{% capture ASSET_PATH %}{{ BASE_PATH }}/assets/themes/{{ layout.theme.name }}{% endcapture %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endcapture %}{% assign jbcache = nil %}
|
8
_includes/JB/sharing
Normal file
8
_includes/JB/sharing
Normal file
|
@ -0,0 +1,8 @@
|
|||
{% if site.safe and site.JB.sharing.provider and page.JB.sharing != false %}
|
||||
|
||||
{% case site.JB.sharing.provider %}
|
||||
{% when "custom" %}
|
||||
{% include custom/sharing %}
|
||||
{% endcase %}
|
||||
|
||||
{% endif %}
|
33
_includes/JB/tags_list
Normal file
33
_includes/JB/tags_list
Normal file
|
@ -0,0 +1,33 @@
|
|||
{% comment %}<!--
|
||||
The tags_list include is a listing helper for tags.
|
||||
Usage:
|
||||
1) assign the 'tags_list' variable to a valid array of tags.
|
||||
2) include JB/tags_list
|
||||
example:
|
||||
<ul>
|
||||
{% assign tags_list = site.tags %}
|
||||
{% include JB/tags_list %}
|
||||
</ul>
|
||||
|
||||
Notes:
|
||||
Tags can be either a Hash of tag objects (hashes) or an Array of tag-names (strings).
|
||||
The encapsulating 'if' statement checks whether tags_list is a Hash or Array.
|
||||
site.tags is a Hash while page.tags is an array.
|
||||
|
||||
This helper can be seen in use at: ../_layouts/default.html
|
||||
-->{% endcomment %}
|
||||
|
||||
{% if site.JB.tags_list.provider == "custom" %}
|
||||
{% include custom/tags_list %}
|
||||
{% else %}
|
||||
{% if tags_list.first[0] == null %}
|
||||
{% for tag in tags_list %}
|
||||
<li><a href="{{ BASE_PATH }}{{ site.JB.tags_path }}#{{ tag }}-ref">{{ tag }} <span>{{ site.tags[tag].size }}</span></a></li>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% for tag in tags_list %}
|
||||
<li><a href="{{ BASE_PATH }}{{ site.JB.tags_path }}#{{ tag[0] }}-ref">{{ tag[0] }} <span>{{ tag[1].size }}</span></a></li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% assign tags_list = nil %}
|
51
_includes/themes/twitter/my.html
Normal file
51
_includes/themes/twitter/my.html
Normal file
|
@ -0,0 +1,51 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset='utf-8' />
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="Spectrum 2 : Spectrum 2 IM transports" />
|
||||
|
||||
<link href="/css/style.css" rel="stylesheet" type="text/css" media="all">
|
||||
|
||||
<title>Spectrum 2</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- HEADER -->
|
||||
<div id="header_wrap" class="outer">
|
||||
<header class="inner">
|
||||
<a id="forkme_banner" href="https://github.com/SpectrumIM/spectrum2">View on GitHub</a>
|
||||
|
||||
<img id="logo" src="/logo.png" style="width:250px; margin-left: auto;margin-right: auto; display:block;"/>
|
||||
|
||||
<section id="menu" style="text-align: center;">
|
||||
<a class="menuitem" href="http://spectrum.im">About</a>
|
||||
<a class="menuitem" href="http://spectrum.im/documentation">Documentation</a>
|
||||
<a class="menuitem" href="http://spectrum.im/download">Download</a>
|
||||
<a class="menuitem" href="http://spectrum.im/discussion">Discussion</a>
|
||||
<a class="menuitem" href="https://github.com/SpectrumIM/spectrum2/issues">Issue tracker</a>
|
||||
</section>
|
||||
</header>
|
||||
</div>
|
||||
|
||||
<!-- MAIN CONTENT -->
|
||||
<div id="main_content_wrap" class="outer">
|
||||
<section id="main_content" class="inner">
|
||||
{{ content }}
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- FOOTER -->
|
||||
<div id="footer_wrap" class="outer">
|
||||
<footer class="inner">
|
||||
<p class="copyright">Spectrum 2 maintained by <a href="https://github.com/SpectrumIM">Spectrum Transports Team</a></p>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
53
_includes/themes/twitter/myconfig.html
Normal file
53
_includes/themes/twitter/myconfig.html
Normal file
|
@ -0,0 +1,53 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset='utf-8' />
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="Spectrum 2 : Spectrum 2 IM transports" />
|
||||
|
||||
<link href="/css/style_config.css" rel="stylesheet" type="text/css" media="all">
|
||||
|
||||
<title>Spectrum 2</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- HEADER -->
|
||||
<div id="header_wrap" class="outer">
|
||||
<header class="inner2">
|
||||
<a id="forkme_banner" href="https://github.com/SpectrumIM/spectrum2">View on GitHub</a>
|
||||
|
||||
<img id="logo" src="/logo.png" style="width:250px; margin-left: auto;margin-right: auto; display:block;"/>
|
||||
|
||||
<section id="menu" style="text-align: center;">
|
||||
<a class="menuitem" href="http://spectrum.im">About</a>
|
||||
<a class="menuitem" href="http://spectrum.im/documentation">Documentation</a>
|
||||
<a class="menuitem" href="http://spectrum.im/download">Download</a>
|
||||
<a class="menuitem" href="http://spectrum.im/discussion">Discussion</a>
|
||||
<a class="menuitem" href="https://github.com/SpectrumIM/spectrum2/issues">Issue tracker</a>
|
||||
</section>
|
||||
</header>
|
||||
</div>
|
||||
|
||||
<!-- MAIN CONTENT -->
|
||||
<div id="main_content_wrap" class="outer">
|
||||
<div class="preinner">
|
||||
<section id="main_content" class="inner">
|
||||
{{ content }}
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- FOOTER -->
|
||||
<div id="footer_wrap" class="outer">
|
||||
<footer class="inner">
|
||||
<p class="copyright">Spectrum 2 maintained by <a href="https://github.com/SpectrumIM">Spectrum Transports Team</a></p>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
2
_includes/themes/twitter/settings.yml
Normal file
2
_includes/themes/twitter/settings.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
theme :
|
||||
name : twitter
|
4
_layouts/config.html
Normal file
4
_layouts/config.html
Normal file
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
layout: null
|
||||
---
|
||||
{% include themes/twitter/myconfig.html %}
|
4
_layouts/page.html
Normal file
4
_layouts/page.html
Normal file
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
layout: null
|
||||
---
|
||||
{% include themes/twitter/my.html %}
|
38
_plugins/debug.rb
Normal file
38
_plugins/debug.rb
Normal file
|
@ -0,0 +1,38 @@
|
|||
# A simple way to inspect liquid template variables.
|
||||
# Usage:
|
||||
# Can be used anywhere liquid syntax is parsed (templates, includes, posts/pages)
|
||||
# {{ site | debug }}
|
||||
# {{ site.posts | debug }}
|
||||
#
|
||||
require 'pp'
|
||||
module Jekyll
|
||||
# Need to overwrite the inspect method here because the original
|
||||
# uses < > to encapsulate the psuedo post/page objects in which case
|
||||
# the output is taken for HTML tags and hidden from view.
|
||||
#
|
||||
class Post
|
||||
def inspect
|
||||
"#Jekyll:Post @id=#{self.id.inspect}"
|
||||
end
|
||||
end
|
||||
|
||||
class Page
|
||||
def inspect
|
||||
"#Jekyll:Page @name=#{self.name.inspect}"
|
||||
end
|
||||
end
|
||||
|
||||
end # Jekyll
|
||||
|
||||
module Jekyll
|
||||
module DebugFilter
|
||||
|
||||
def debug(obj, stdout=false)
|
||||
puts obj.pretty_inspect if stdout
|
||||
"<pre>#{obj.class}\n#{obj.pretty_inspect}</pre>"
|
||||
end
|
||||
|
||||
end # DebugFilter
|
||||
end # Jekyll
|
||||
|
||||
Liquid::Template.register_filter(Jekyll::DebugFilter)
|
BIN
animation.gif
Normal file
BIN
animation.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 1 MiB |
432
assets/themes/twitter/css/style.css
Normal file
432
assets/themes/twitter/css/style.css
Normal file
|
@ -0,0 +1,432 @@
|
|||
/*******************************************************************************
|
||||
Slate Theme for Github Pages
|
||||
by Jason Costello, @jsncostello
|
||||
*******************************************************************************/
|
||||
|
||||
@import url(pygment_trac.css);
|
||||
|
||||
/*******************************************************************************
|
||||
MeyerWeb Reset
|
||||
*******************************************************************************/
|
||||
|
||||
html, body, div, span, applet, object, iframe,
|
||||
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||
a, abbr, acronym, address, big, cite, code,
|
||||
del, dfn, em, img, ins, kbd, q, s, samp,
|
||||
small, strike, strong, sub, sup, tt, var,
|
||||
b, u, i, center,
|
||||
dl, dt, dd, ol, ul, li,
|
||||
fieldset, form, label, legend,
|
||||
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||
article, aside, canvas, details, embed,
|
||||
figure, figcaption, footer, header, hgroup,
|
||||
menu, nav, output, ruby, section, summary,
|
||||
time, mark, audio, video {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
font: inherit;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/* HTML5 display-role reset for older browsers */
|
||||
article, aside, details, figcaption, figure,
|
||||
footer, header, hgroup, menu, nav, section {
|
||||
display: block;
|
||||
}
|
||||
|
||||
ol, ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
blockquote, q {
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
a:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Theme Styles
|
||||
*******************************************************************************/
|
||||
|
||||
body {
|
||||
box-sizing: border-box;
|
||||
color:#373737;
|
||||
background: #212121;
|
||||
font-size: 16px;
|
||||
font-family: 'Myriad Pro', Calibri, Helvetica, Arial, sans-serif;
|
||||
line-height: 1.5;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin: 10px 0;
|
||||
font-weight: 700;
|
||||
color:#222222;
|
||||
font-family: 'Lucida Grande', 'Calibri', Helvetica, Arial, sans-serif;
|
||||
letter-spacing: -1px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 36px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
h2 {
|
||||
padding-bottom: 10px;
|
||||
font-size: 32px;
|
||||
background: url('../images/bg_hr.png') repeat-x bottom;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 21px;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 10px 0 15px 0;
|
||||
}
|
||||
|
||||
footer p {
|
||||
color: #f2f2f2;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #007edf;
|
||||
text-shadow: none;
|
||||
|
||||
transition: color 0.5s ease;
|
||||
transition: text-shadow 0.5s ease;
|
||||
-webkit-transition: color 0.5s ease;
|
||||
-webkit-transition: text-shadow 0.5s ease;
|
||||
-moz-transition: color 0.5s ease;
|
||||
-moz-transition: text-shadow 0.5s ease;
|
||||
-o-transition: color 0.5s ease;
|
||||
-o-transition: text-shadow 0.5s ease;
|
||||
-ms-transition: color 0.5s ease;
|
||||
-ms-transition: text-shadow 0.5s ease;
|
||||
}
|
||||
|
||||
#main_content a:hover {
|
||||
color: #0069ba;
|
||||
text-shadow: #0090ff 0px 0px 2px;
|
||||
}
|
||||
|
||||
footer a:hover {
|
||||
color: #43adff;
|
||||
text-shadow: #0090ff 0px 0px 2px;
|
||||
}
|
||||
|
||||
em {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
img {
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
max-width: 739px;
|
||||
padding: 5px;
|
||||
margin: 10px 0 10px 0;
|
||||
border: 1px solid #ebebeb;
|
||||
|
||||
box-shadow: 0 0 5px #ebebeb;
|
||||
-webkit-box-shadow: 0 0 5px #ebebeb;
|
||||
-moz-box-shadow: 0 0 5px #ebebeb;
|
||||
-o-box-shadow: 0 0 5px #ebebeb;
|
||||
-ms-box-shadow: 0 0 5px #ebebeb;
|
||||
}
|
||||
|
||||
pre, code {
|
||||
width: 100%;
|
||||
color: #222;
|
||||
background-color: #fff;
|
||||
|
||||
font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace;
|
||||
font-size: 14px;
|
||||
|
||||
border-radius: 2px;
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
pre {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
box-shadow: 0 0 10px rgba(0,0,0,.1);
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
code {
|
||||
padding: 3px;
|
||||
margin: 0 3px;
|
||||
box-shadow: 0 0 10px rgba(0,0,0,.1);
|
||||
}
|
||||
|
||||
pre code {
|
||||
display: block;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
color: #666;
|
||||
margin-bottom: 20px;
|
||||
padding: 0 0 0 20px;
|
||||
border-left: 3px solid #bbb;
|
||||
}
|
||||
|
||||
ul, ol, dl {
|
||||
margin-bottom: 15px
|
||||
}
|
||||
|
||||
ul li {
|
||||
list-style: inside;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
ol li {
|
||||
list-style: decimal inside;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
dl dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
dl dd {
|
||||
padding-left: 20px;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
dl p {
|
||||
padding-left: 20px;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
hr {
|
||||
height: 1px;
|
||||
margin-bottom: 5px;
|
||||
border: none;
|
||||
background: url('../images/bg_hr.png') repeat-x center;
|
||||
}
|
||||
|
||||
table {
|
||||
border: 1px solid #373737;
|
||||
margin-bottom: 20px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
th {
|
||||
font-family: 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
padding: 10px;
|
||||
background: #373737;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 10px;
|
||||
border: 1px solid #373737;
|
||||
}
|
||||
|
||||
form {
|
||||
background: #f2f2f2;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Full-Width Styles
|
||||
*******************************************************************************/
|
||||
|
||||
.outer {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.inner {
|
||||
position: relative;
|
||||
max-width: 640px;
|
||||
padding: 20px 10px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#forkme_banner {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top:0;
|
||||
right: 10px;
|
||||
z-index: 10;
|
||||
padding: 10px 50px 10px 10px;
|
||||
color: #fff;
|
||||
background: url('../images/blacktocat.png') #0090ff no-repeat 95% 50%;
|
||||
font-weight: 700;
|
||||
box-shadow: 0 0 10px rgba(0,0,0,.5);
|
||||
border-bottom-left-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
}
|
||||
|
||||
#header_wrap {
|
||||
background: #212121;
|
||||
background: -moz-linear-gradient(top, #373737, #212121);
|
||||
background: -webkit-linear-gradient(top, #373737, #212121);
|
||||
background: -ms-linear-gradient(top, #373737, #212121);
|
||||
background: -o-linear-gradient(top, #373737, #212121);
|
||||
background: linear-gradient(top, #373737, #212121);
|
||||
}
|
||||
|
||||
#header_wrap .inner {
|
||||
padding: 50px 10px 30px 10px;
|
||||
}
|
||||
|
||||
#project_title {
|
||||
margin: 0;
|
||||
color: #fff;
|
||||
font-size: 42px;
|
||||
font-weight: 700;
|
||||
text-shadow: #111 0px 0px 10px;
|
||||
}
|
||||
|
||||
#project_tagline {
|
||||
color: #fff;
|
||||
font-size: 24px;
|
||||
font-weight: 300;
|
||||
background: none;
|
||||
text-shadow: #111 0px 0px 10px;
|
||||
}
|
||||
|
||||
#downloads {
|
||||
position: absolute;
|
||||
width: 210px;
|
||||
z-index: 10;
|
||||
bottom: -40px;
|
||||
right: 0;
|
||||
height: 70px;
|
||||
background: url('../images/icon_download.png') no-repeat 0% 90%;
|
||||
}
|
||||
|
||||
.zip_download_link {
|
||||
display: block;
|
||||
float: right;
|
||||
width: 90px;
|
||||
height:70px;
|
||||
text-indent: -5000px;
|
||||
overflow: hidden;
|
||||
background: url(../images/sprite_download.png) no-repeat bottom left;
|
||||
}
|
||||
|
||||
.tar_download_link {
|
||||
display: block;
|
||||
float: right;
|
||||
width: 90px;
|
||||
height:70px;
|
||||
text-indent: -5000px;
|
||||
overflow: hidden;
|
||||
background: url(../images/sprite_download.png) no-repeat bottom right;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.zip_download_link:hover {
|
||||
background: url(../images/sprite_download.png) no-repeat top left;
|
||||
}
|
||||
|
||||
.tar_download_link:hover {
|
||||
background: url(../images/sprite_download.png) no-repeat top right;
|
||||
}
|
||||
|
||||
#main_content_wrap {
|
||||
background: #f2f2f2;
|
||||
border-top: 1px solid #111;
|
||||
border-bottom: 1px solid #111;
|
||||
}
|
||||
|
||||
#main_content {
|
||||
padding-top: 40px;
|
||||
}
|
||||
|
||||
#footer_wrap {
|
||||
background: #212121;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
Small Device Styles
|
||||
*******************************************************************************/
|
||||
|
||||
@media screen and (max-width: 480px) {
|
||||
body {
|
||||
font-size:14px;
|
||||
}
|
||||
|
||||
#downloads {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.inner {
|
||||
min-width: 320px;
|
||||
max-width: 480px;
|
||||
}
|
||||
|
||||
#project_title {
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 21px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
code, pre {
|
||||
min-width: 320px;
|
||||
max-width: 480px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
}
|
28
atom.xml
Normal file
28
atom.xml
Normal file
|
@ -0,0 +1,28 @@
|
|||
---
|
||||
layout: null
|
||||
title : Atom Feed
|
||||
---
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
|
||||
<title>{{ site.title }}</title>
|
||||
<link href="{{ site.production_url }}/atom.xml" rel="self"/>
|
||||
<link href="{{ site.production_url }}"/>
|
||||
<updated>{{ site.time | date_to_xmlschema }}</updated>
|
||||
<id>{{ site.production_url }}</id>
|
||||
<author>
|
||||
<name>{{ site.author.name }}</name>
|
||||
<email>{{ site.author.email }}</email>
|
||||
</author>
|
||||
|
||||
{% for post in site.posts %}
|
||||
<entry>
|
||||
<title>{{ post.title }}</title>
|
||||
<link href="{{ site.production_url }}{{ post.url }}"/>
|
||||
<updated>{{ post.date | date_to_xmlschema }}</updated>
|
||||
<id>{{ site.production_url }}{{ post.id }}</id>
|
||||
<content type="html">{{ post.content | xml_escape }}</content>
|
||||
</entry>
|
||||
{% endfor %}
|
||||
|
||||
</feed>
|
|
@ -1,26 +0,0 @@
|
|||
if (PROTOBUF_FOUND)
|
||||
if (PURPLE_FOUND)
|
||||
ADD_SUBDIRECTORY(libpurple)
|
||||
endif()
|
||||
|
||||
if (IRC_FOUND)
|
||||
ADD_SUBDIRECTORY(libcommuni)
|
||||
endif()
|
||||
|
||||
if (ENABLE_XMPP)
|
||||
ADD_SUBDIRECTORY(swiften)
|
||||
endif()
|
||||
|
||||
ADD_SUBDIRECTORY(template)
|
||||
if(ENABLE_TWITTER)
|
||||
ADD_SUBDIRECTORY(twitter)
|
||||
endif()
|
||||
if (NOT WIN32)
|
||||
if(ENABLE_SMSTOOLS3)
|
||||
ADD_SUBDIRECTORY(smstools3)
|
||||
endif()
|
||||
if(ENABLE_FROTZ)
|
||||
ADD_SUBDIRECTORY(frotz)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
|
@ -1,12 +0,0 @@
|
|||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
ADD_SUBDIRECTORY(dfrotz)
|
||||
|
||||
FILE(GLOB SRC *.c *.cpp)
|
||||
|
||||
ADD_EXECUTABLE(spectrum2_frotz_backend ${SRC})
|
||||
|
||||
target_link_libraries(spectrum2_frotz_backend transport pthread ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
|
||||
|
||||
INSTALL(TARGETS spectrum2_frotz_backend RUNTIME DESTINATION bin)
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
cmake_minimum_required(VERSION 2.6)
|
||||
FILE(GLOB SRC common/*.c dumb/*.c)
|
||||
|
||||
ADD_EXECUTABLE(dfrotz ${SRC})
|
||||
|
||||
# target_link_libraries(dfrotz)
|
||||
|
||||
INSTALL(TARGETS dfrotz RUNTIME DESTINATION bin)
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
This is patched version of dfrotz. frotz_backend won't work with dfrotz from
|
||||
your distribution.
|
|
@ -1,152 +0,0 @@
|
|||
/* buffer.c - Text buffering and word wrapping
|
||||
* Copyright (c) 1995-1997 Stefan Jokisch
|
||||
*
|
||||
* This file is part of Frotz.
|
||||
*
|
||||
* Frotz 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.
|
||||
*
|
||||
* Frotz 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
|
||||
*/
|
||||
|
||||
#include "frotz.h"
|
||||
|
||||
extern void stream_char (zchar);
|
||||
extern void stream_word (const zchar *);
|
||||
extern void stream_new_line (void);
|
||||
|
||||
static zchar buffer[TEXT_BUFFER_SIZE];
|
||||
static int bufpos = 0;
|
||||
|
||||
static zchar prev_c = 0;
|
||||
|
||||
/*
|
||||
* flush_buffer
|
||||
*
|
||||
* Copy the contents of the text buffer to the output streams.
|
||||
*
|
||||
*/
|
||||
|
||||
void flush_buffer (void)
|
||||
{
|
||||
static bool locked = FALSE;
|
||||
|
||||
/* Make sure we stop when flush_buffer is called from flush_buffer.
|
||||
Note that this is difficult to avoid as we might print a newline
|
||||
during flush_buffer, which might cause a newline interrupt, that
|
||||
might execute any arbitrary opcode, which might flush the buffer. */
|
||||
|
||||
if (locked || bufpos == 0)
|
||||
return;
|
||||
|
||||
/* Send the buffer to the output streams */
|
||||
|
||||
buffer[bufpos] = 0;
|
||||
|
||||
|
||||
locked = TRUE;
|
||||
|
||||
stream_word (buffer);
|
||||
|
||||
#ifdef SPEECH_OUTPUT
|
||||
os_speech_output(buffer);
|
||||
#endif
|
||||
|
||||
locked = FALSE;
|
||||
|
||||
/* Reset the buffer */
|
||||
|
||||
bufpos = 0;
|
||||
prev_c = 0;
|
||||
|
||||
}/* flush_buffer */
|
||||
|
||||
/*
|
||||
* print_char
|
||||
*
|
||||
* High level output function.
|
||||
*
|
||||
*/
|
||||
|
||||
void print_char (zchar c)
|
||||
{
|
||||
static bool flag = FALSE;
|
||||
|
||||
if (message || ostream_memory || enable_buffering) {
|
||||
|
||||
if (!flag) {
|
||||
|
||||
/* Characters 0 and ZC_RETURN are special cases */
|
||||
|
||||
if (c == ZC_RETURN)
|
||||
{ new_line (); return; }
|
||||
if (c == 0)
|
||||
return;
|
||||
|
||||
/* Flush the buffer before a whitespace or after a hyphen */
|
||||
|
||||
if (c == ' ' || c == ZC_INDENT || c == ZC_GAP || (prev_c == '-' && c != '-'))
|
||||
|
||||
|
||||
flush_buffer ();
|
||||
|
||||
/* Set the flag if this is part one of a style or font change */
|
||||
|
||||
if (c == ZC_NEW_FONT || c == ZC_NEW_STYLE)
|
||||
flag = TRUE;
|
||||
|
||||
/* Remember the current character code */
|
||||
|
||||
prev_c = c;
|
||||
|
||||
} else flag = FALSE;
|
||||
|
||||
/* Insert the character into the buffer */
|
||||
|
||||
buffer[bufpos++] = c;
|
||||
|
||||
if (bufpos == TEXT_BUFFER_SIZE)
|
||||
runtime_error (ERR_TEXT_BUF_OVF);
|
||||
|
||||
} else stream_char (c);
|
||||
|
||||
}/* print_char */
|
||||
|
||||
/*
|
||||
* new_line
|
||||
*
|
||||
* High level newline function.
|
||||
*
|
||||
*/
|
||||
|
||||
void new_line (void)
|
||||
{
|
||||
|
||||
flush_buffer (); stream_new_line ();
|
||||
|
||||
}/* new_line */
|
||||
|
||||
|
||||
/*
|
||||
* init_buffer
|
||||
*
|
||||
* Initialize buffer variables.
|
||||
*
|
||||
*/
|
||||
|
||||
void init_buffer(void)
|
||||
{
|
||||
memset(buffer, 0, sizeof (zchar) * TEXT_BUFFER_SIZE);
|
||||
bufpos = 0;
|
||||
prev_c = 0;
|
||||
}
|
||||
|
|
@ -1,154 +0,0 @@
|
|||
/* err.c - Runtime error reporting functions
|
||||
* Written by Jim Dunleavy <jim.dunleavy@erha.ie>
|
||||
*
|
||||
* This file is part of Frotz.
|
||||
*
|
||||
* Frotz 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.
|
||||
*
|
||||
* Frotz 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
|
||||
*/
|
||||
|
||||
#include "frotz.h"
|
||||
|
||||
/* Define stuff for stricter Z-code error checking, for the generic
|
||||
Unix/DOS/etc terminal-window interface. Feel free to change the way
|
||||
player prefs are specified, or replace report_zstrict_error()
|
||||
completely if you want to change the way errors are reported. */
|
||||
|
||||
/* int err_report_mode = ERR_DEFAULT_REPORT_MODE; */
|
||||
|
||||
static int error_count[ERR_NUM_ERRORS];
|
||||
|
||||
static char *err_messages[] = {
|
||||
"Text buffer overflow",
|
||||
"Store out of dynamic memory",
|
||||
"Division by zero",
|
||||
"Illegal object",
|
||||
"Illegal attribute",
|
||||
"No such property",
|
||||
"Stack overflow",
|
||||
"Call to illegal address",
|
||||
"Call to non-routine",
|
||||
"Stack underflow",
|
||||
"Illegal opcode",
|
||||
"Bad stack frame",
|
||||
"Jump to illegal address",
|
||||
"Can't save while in interrupt",
|
||||
"Nesting stream #3 too deep",
|
||||
"Illegal window",
|
||||
"Illegal window property",
|
||||
"Print at illegal address",
|
||||
"@jin called with object 0",
|
||||
"@get_child called with object 0",
|
||||
"@get_parent called with object 0",
|
||||
"@get_sibling called with object 0",
|
||||
"@get_prop_addr called with object 0",
|
||||
"@get_prop called with object 0",
|
||||
"@put_prop called with object 0",
|
||||
"@clear_attr called with object 0",
|
||||
"@set_attr called with object 0",
|
||||
"@test_attr called with object 0",
|
||||
"@move_object called moving object 0",
|
||||
"@move_object called moving into object 0",
|
||||
"@remove_object called with object 0",
|
||||
"@get_next_prop called with object 0"
|
||||
};
|
||||
|
||||
static void print_long (unsigned long value, int base);
|
||||
|
||||
/*
|
||||
* init_err
|
||||
*
|
||||
* Initialise error reporting.
|
||||
*
|
||||
*/
|
||||
|
||||
void init_err (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Initialize the counters. */
|
||||
|
||||
for (i = 0; i < ERR_NUM_ERRORS; i++)
|
||||
error_count[i] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* runtime_error
|
||||
*
|
||||
* An error has occurred. Ignore it, pass it to os_fatal or report
|
||||
* it according to err_report_mode.
|
||||
*
|
||||
* errnum : Numeric code for error (1 to ERR_NUM_ERRORS)
|
||||
*
|
||||
*/
|
||||
|
||||
void runtime_error (int errnum)
|
||||
{
|
||||
int wasfirst;
|
||||
|
||||
if (errnum <= 0 || errnum > ERR_NUM_ERRORS)
|
||||
return;
|
||||
|
||||
if (f_setup.err_report_mode == ERR_REPORT_FATAL
|
||||
|| (!f_setup.ignore_errors && errnum <= ERR_MAX_FATAL)) {
|
||||
flush_buffer ();
|
||||
os_fatal (err_messages[errnum - 1]);
|
||||
return;
|
||||
}
|
||||
|
||||
wasfirst = (error_count[errnum - 1] == 0);
|
||||
error_count[errnum - 1]++;
|
||||
|
||||
if ((f_setup.err_report_mode == ERR_REPORT_ALWAYS)
|
||||
|| (f_setup.err_report_mode == ERR_REPORT_ONCE && wasfirst)) {
|
||||
long pc;
|
||||
|
||||
GET_PC (pc);
|
||||
print_string ("Warning: ");
|
||||
print_string (err_messages[errnum - 1]);
|
||||
print_string (" (PC = ");
|
||||
print_long (pc, 16);
|
||||
print_char (')');
|
||||
|
||||
if (f_setup.err_report_mode == ERR_REPORT_ONCE) {
|
||||
print_string (" (will ignore further occurrences)");
|
||||
} else {
|
||||
print_string (" (occurence ");
|
||||
print_long (error_count[errnum - 1], 10);
|
||||
print_char (')');
|
||||
}
|
||||
new_line ();
|
||||
}
|
||||
|
||||
} /* report_error */
|
||||
|
||||
/*
|
||||
* print_long
|
||||
*
|
||||
* Print an unsigned 32bit number in decimal or hex.
|
||||
*
|
||||
*/
|
||||
|
||||
static void print_long (unsigned long value, int base)
|
||||
{
|
||||
unsigned long i;
|
||||
char c;
|
||||
|
||||
for (i = (base == 10 ? 1000000000 : 0x10000000); i != 0; i /= base)
|
||||
if (value >= i || i == 1) {
|
||||
c = (value / i) % base;
|
||||
print_char (c + (c <= 9 ? '0' : 'a' - 10));
|
||||
}
|
||||
|
||||
}/* print_long */
|
File diff suppressed because it is too large
Load diff
|
@ -1,566 +0,0 @@
|
|||
/* files.c - Transscription, recording and playback
|
||||
* Copyright (c) 1995-1997 Stefan Jokisch
|
||||
*
|
||||
* This file is part of Frotz.
|
||||
*
|
||||
* Frotz 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.
|
||||
*
|
||||
* Frotz 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
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "frotz.h"
|
||||
|
||||
#ifndef SEEK_SET
|
||||
#define SEEK_SET 0
|
||||
#define SEEK_CUR 1
|
||||
#define SEEK_END 2
|
||||
#endif
|
||||
|
||||
extern void set_more_prompts (bool);
|
||||
|
||||
extern bool is_terminator (zchar);
|
||||
|
||||
extern bool read_yes_or_no (const char *);
|
||||
|
||||
char script_name[MAX_FILE_NAME + 1] = DEFAULT_SCRIPT_NAME;
|
||||
char command_name[MAX_FILE_NAME + 1] = DEFAULT_COMMAND_NAME;
|
||||
|
||||
#ifdef __MSDOS__
|
||||
extern char latin1_to_ibm[];
|
||||
#endif
|
||||
|
||||
static int script_width = 0;
|
||||
|
||||
static FILE *sfp = NULL;
|
||||
static FILE *rfp = NULL;
|
||||
static FILE *pfp = NULL;
|
||||
|
||||
/*
|
||||
* script_open
|
||||
*
|
||||
* Open the transscript file. 'AMFV' makes this more complicated as it
|
||||
* turns transscription on/off several times to exclude some text from
|
||||
* the transscription file. This wasn't a problem for the original V4
|
||||
* interpreters which always sent transscription to the printer, but it
|
||||
* means a problem to modern interpreters that offer to open a new file
|
||||
* every time transscription is turned on. Our solution is to append to
|
||||
* the old transscription file in V1 to V4, and to ask for a new file
|
||||
* name in V5+.
|
||||
*
|
||||
*/
|
||||
|
||||
void script_open (void)
|
||||
{
|
||||
static bool script_valid = FALSE;
|
||||
|
||||
char new_name[MAX_FILE_NAME + 1];
|
||||
|
||||
h_flags &= ~SCRIPTING_FLAG;
|
||||
|
||||
if (h_version >= V5 || !script_valid) {
|
||||
|
||||
if (!os_read_file_name (new_name, script_name, FILE_SCRIPT))
|
||||
goto done;
|
||||
|
||||
strcpy (script_name, new_name);
|
||||
|
||||
}
|
||||
|
||||
/* Opening in "at" mode doesn't work for script_erase_input... */
|
||||
|
||||
if ((sfp = fopen (script_name, "r+t")) != NULL || (sfp = fopen (script_name, "w+t")) != NULL) {
|
||||
|
||||
fseek (sfp, 0, SEEK_END);
|
||||
|
||||
h_flags |= SCRIPTING_FLAG;
|
||||
|
||||
script_valid = TRUE;
|
||||
ostream_script = TRUE;
|
||||
|
||||
script_width = 0;
|
||||
|
||||
} else print_string ("Cannot open file\n");
|
||||
|
||||
done:
|
||||
|
||||
SET_WORD (H_FLAGS, h_flags)
|
||||
|
||||
}/* script_open */
|
||||
|
||||
/*
|
||||
* script_close
|
||||
*
|
||||
* Stop transscription.
|
||||
*
|
||||
*/
|
||||
|
||||
void script_close (void)
|
||||
{
|
||||
|
||||
h_flags &= ~SCRIPTING_FLAG;
|
||||
SET_WORD (H_FLAGS, h_flags)
|
||||
|
||||
fclose (sfp); ostream_script = FALSE;
|
||||
|
||||
}/* script_close */
|
||||
|
||||
/*
|
||||
* script_new_line
|
||||
*
|
||||
* Write a newline to the transscript file.
|
||||
*
|
||||
*/
|
||||
|
||||
void script_new_line (void)
|
||||
{
|
||||
|
||||
if (fputc ('\n', sfp) == EOF)
|
||||
script_close ();
|
||||
|
||||
script_width = 0;
|
||||
|
||||
}/* script_new_line */
|
||||
|
||||
/*
|
||||
* script_char
|
||||
*
|
||||
* Write a single character to the transscript file.
|
||||
*
|
||||
*/
|
||||
|
||||
void script_char (zchar c)
|
||||
{
|
||||
|
||||
if (c == ZC_INDENT && script_width != 0)
|
||||
c = ' ';
|
||||
|
||||
if (c == ZC_INDENT)
|
||||
{ script_char (' '); script_char (' '); script_char (' '); return; }
|
||||
if (c == ZC_GAP)
|
||||
{ script_char (' '); script_char (' '); return; }
|
||||
|
||||
#ifdef __MSDOS__
|
||||
if (c >= ZC_LATIN1_MIN)
|
||||
c = latin1_to_ibm[c - ZC_LATIN1_MIN];
|
||||
#endif
|
||||
|
||||
fputc (c, sfp); script_width++;
|
||||
|
||||
}/* script_char */
|
||||
|
||||
/*
|
||||
* script_word
|
||||
*
|
||||
* Write a string to the transscript file.
|
||||
*
|
||||
*/
|
||||
|
||||
void script_word (const zchar *s)
|
||||
{
|
||||
int width;
|
||||
int i;
|
||||
|
||||
if (*s == ZC_INDENT && script_width != 0)
|
||||
script_char (*s++);
|
||||
|
||||
for (i = 0, width = 0; s[i] != 0; i++)
|
||||
|
||||
if (s[i] == ZC_NEW_STYLE || s[i] == ZC_NEW_FONT)
|
||||
i++;
|
||||
else if (s[i] == ZC_GAP)
|
||||
width += 3;
|
||||
else if (s[i] == ZC_INDENT)
|
||||
width += 2;
|
||||
else
|
||||
width += 1;
|
||||
|
||||
if (f_setup.script_cols != 0 && script_width + width > f_setup.script_cols) {
|
||||
|
||||
if (*s == ' ' || *s == ZC_INDENT || *s == ZC_GAP)
|
||||
s++;
|
||||
|
||||
script_new_line ();
|
||||
|
||||
}
|
||||
|
||||
for (i = 0; s[i] != 0; i++)
|
||||
|
||||
if (s[i] == ZC_NEW_FONT || s[i] == ZC_NEW_STYLE)
|
||||
i++;
|
||||
else
|
||||
script_char (s[i]);
|
||||
|
||||
}/* script_word */
|
||||
|
||||
/*
|
||||
* script_write_input
|
||||
*
|
||||
* Send an input line to the transscript file.
|
||||
*
|
||||
*/
|
||||
|
||||
void script_write_input (const zchar *buf, zchar key)
|
||||
{
|
||||
int width;
|
||||
int i;
|
||||
|
||||
for (i = 0, width = 0; buf[i] != 0; i++)
|
||||
width++;
|
||||
|
||||
if (f_setup.script_cols != 0 && script_width + width > f_setup.script_cols)
|
||||
script_new_line ();
|
||||
|
||||
for (i = 0; buf[i] != 0; i++)
|
||||
script_char (buf[i]);
|
||||
|
||||
if (key == ZC_RETURN)
|
||||
script_new_line ();
|
||||
|
||||
}/* script_write_input */
|
||||
|
||||
/*
|
||||
* script_erase_input
|
||||
*
|
||||
* Remove an input line from the transscript file.
|
||||
*
|
||||
*/
|
||||
|
||||
void script_erase_input (const zchar *buf)
|
||||
{
|
||||
int width;
|
||||
int i;
|
||||
|
||||
for (i = 0, width = 0; buf[i] != 0; i++)
|
||||
width++;
|
||||
|
||||
fseek (sfp, -width, SEEK_CUR); script_width -= width;
|
||||
|
||||
}/* script_erase_input */
|
||||
|
||||
/*
|
||||
* script_mssg_on
|
||||
*
|
||||
* Start sending a "debugging" message to the transscript file.
|
||||
*
|
||||
*/
|
||||
|
||||
void script_mssg_on (void)
|
||||
{
|
||||
|
||||
if (script_width != 0)
|
||||
script_new_line ();
|
||||
|
||||
script_char (ZC_INDENT);
|
||||
|
||||
}/* script_mssg_on */
|
||||
|
||||
/*
|
||||
* script_mssg_off
|
||||
*
|
||||
* Stop writing a "debugging" message.
|
||||
*
|
||||
*/
|
||||
|
||||
void script_mssg_off (void)
|
||||
{
|
||||
|
||||
script_new_line ();
|
||||
|
||||
}/* script_mssg_off */
|
||||
|
||||
/*
|
||||
* record_open
|
||||
*
|
||||
* Open a file to record the player's input.
|
||||
*
|
||||
*/
|
||||
|
||||
void record_open (void)
|
||||
{
|
||||
char new_name[MAX_FILE_NAME + 1];
|
||||
|
||||
if (os_read_file_name (new_name, command_name, FILE_RECORD)) {
|
||||
|
||||
strcpy (command_name, new_name);
|
||||
|
||||
if ((rfp = fopen (new_name, "wt")) != NULL)
|
||||
ostream_record = TRUE;
|
||||
else
|
||||
print_string ("Cannot open file\n");
|
||||
|
||||
}
|
||||
|
||||
}/* record_open */
|
||||
|
||||
/*
|
||||
* record_close
|
||||
*
|
||||
* Stop recording the player's input.
|
||||
*
|
||||
*/
|
||||
|
||||
void record_close (void)
|
||||
{
|
||||
|
||||
fclose (rfp); ostream_record = FALSE;
|
||||
|
||||
}/* record_close */
|
||||
|
||||
/*
|
||||
* record_code
|
||||
*
|
||||
* Helper function for record_char.
|
||||
*
|
||||
*/
|
||||
|
||||
static void record_code (int c, bool force_encoding)
|
||||
{
|
||||
|
||||
if (force_encoding || c == '[' || c < 0x20 || c > 0x7e) {
|
||||
|
||||
int i;
|
||||
|
||||
fputc ('[', rfp);
|
||||
|
||||
for (i = 10000; i != 0; i /= 10)
|
||||
if (c >= i || i == 1)
|
||||
fputc ('0' + (c / i) % 10, rfp);
|
||||
|
||||
fputc (']', rfp);
|
||||
|
||||
} else fputc (c, rfp);
|
||||
|
||||
}/* record_code */
|
||||
|
||||
/*
|
||||
* record_char
|
||||
*
|
||||
* Write a character to the command file.
|
||||
*
|
||||
*/
|
||||
|
||||
static void record_char (zchar c)
|
||||
{
|
||||
|
||||
if (c != ZC_RETURN) {
|
||||
if (c < ZC_HKEY_MIN || c > ZC_HKEY_MAX) {
|
||||
record_code (translate_to_zscii (c), FALSE);
|
||||
if (c == ZC_SINGLE_CLICK || c == ZC_DOUBLE_CLICK) {
|
||||
record_code (mouse_x, TRUE);
|
||||
record_code (mouse_y, TRUE);
|
||||
}
|
||||
} else record_code (1000 + c - ZC_HKEY_MIN, TRUE);
|
||||
}
|
||||
|
||||
}/* record_char */
|
||||
|
||||
/*
|
||||
* record_write_key
|
||||
*
|
||||
* Copy a keystroke to the command file.
|
||||
*
|
||||
*/
|
||||
|
||||
void record_write_key (zchar key)
|
||||
{
|
||||
|
||||
record_char (key);
|
||||
|
||||
if (fputc ('\n', rfp) == EOF)
|
||||
record_close ();
|
||||
|
||||
}/* record_write_key */
|
||||
|
||||
/*
|
||||
* record_write_input
|
||||
*
|
||||
* Copy a line of input to a command file.
|
||||
*
|
||||
*/
|
||||
|
||||
void record_write_input (const zchar *buf, zchar key)
|
||||
{
|
||||
zchar c;
|
||||
|
||||
while ((c = *buf++) != 0)
|
||||
record_char (c);
|
||||
|
||||
record_char (key);
|
||||
|
||||
if (fputc ('\n', rfp) == EOF)
|
||||
record_close ();
|
||||
|
||||
}/* record_write_input */
|
||||
|
||||
/*
|
||||
* replay_open
|
||||
*
|
||||
* Open a file of commands for playback.
|
||||
*
|
||||
*/
|
||||
|
||||
void replay_open (void)
|
||||
{
|
||||
char new_name[MAX_FILE_NAME + 1];
|
||||
|
||||
if (os_read_file_name (new_name, command_name, FILE_PLAYBACK)) {
|
||||
|
||||
strcpy (command_name, new_name);
|
||||
|
||||
if ((pfp = fopen (new_name, "rt")) != NULL) {
|
||||
|
||||
set_more_prompts (read_yes_or_no ("Do you want MORE prompts"));
|
||||
|
||||
istream_replay = TRUE;
|
||||
|
||||
} else print_string ("Cannot open file\n");
|
||||
|
||||
}
|
||||
|
||||
}/* replay_open */
|
||||
|
||||
/*
|
||||
* replay_close
|
||||
*
|
||||
* Stop playback of commands.
|
||||
*
|
||||
*/
|
||||
|
||||
void replay_close (void)
|
||||
{
|
||||
|
||||
set_more_prompts (TRUE);
|
||||
|
||||
fclose (pfp); istream_replay = FALSE;
|
||||
|
||||
}/* replay_close */
|
||||
|
||||
/*
|
||||
* replay_code
|
||||
*
|
||||
* Helper function for replay_key and replay_line.
|
||||
*
|
||||
*/
|
||||
|
||||
static int replay_code (void)
|
||||
{
|
||||
int c;
|
||||
|
||||
if ((c = fgetc (pfp)) == '[') {
|
||||
|
||||
int c2;
|
||||
|
||||
c = 0;
|
||||
|
||||
while ((c2 = fgetc (pfp)) != EOF && c2 >= '0' && c2 <= '9')
|
||||
c = 10 * c + c2 - '0';
|
||||
|
||||
return (c2 == ']') ? c : EOF;
|
||||
|
||||
} else return c;
|
||||
|
||||
}/* replay_code */
|
||||
|
||||
/*
|
||||
* replay_char
|
||||
*
|
||||
* Read a character from the command file.
|
||||
*
|
||||
*/
|
||||
|
||||
static zchar replay_char (void)
|
||||
{
|
||||
int c;
|
||||
|
||||
if ((c = replay_code ()) != EOF) {
|
||||
|
||||
if (c != '\n') {
|
||||
|
||||
if (c < 1000) {
|
||||
|
||||
c = translate_from_zscii (c);
|
||||
|
||||
if (c == ZC_SINGLE_CLICK || c == ZC_DOUBLE_CLICK) {
|
||||
mouse_x = replay_code ();
|
||||
mouse_y = replay_code ();
|
||||
}
|
||||
|
||||
return c;
|
||||
|
||||
} else return ZC_HKEY_MIN + c - 1000;
|
||||
}
|
||||
|
||||
ungetc ('\n', pfp);
|
||||
|
||||
return ZC_RETURN;
|
||||
|
||||
} else return ZC_BAD;
|
||||
|
||||
}/* replay_char */
|
||||
|
||||
/*
|
||||
* replay_read_key
|
||||
*
|
||||
* Read a keystroke from a command file.
|
||||
*
|
||||
*/
|
||||
|
||||
zchar replay_read_key (void)
|
||||
{
|
||||
zchar key;
|
||||
|
||||
key = replay_char ();
|
||||
|
||||
if (fgetc (pfp) != '\n') {
|
||||
|
||||
replay_close ();
|
||||
return ZC_BAD;
|
||||
|
||||
} else return key;
|
||||
|
||||
}/* replay_read_key */
|
||||
|
||||
/*
|
||||
* replay_read_input
|
||||
*
|
||||
* Read a line of input from a command file.
|
||||
*
|
||||
*/
|
||||
|
||||
zchar replay_read_input (zchar *buf)
|
||||
{
|
||||
zchar c;
|
||||
|
||||
for (;;) {
|
||||
|
||||
c = replay_char ();
|
||||
|
||||
if (c == ZC_BAD || is_terminator (c))
|
||||
break;
|
||||
|
||||
*buf++ = c;
|
||||
|
||||
}
|
||||
|
||||
*buf = 0;
|
||||
|
||||
if (fgetc (pfp) != '\n') {
|
||||
|
||||
replay_close ();
|
||||
return ZC_BAD;
|
||||
|
||||
} else return c;
|
||||
|
||||
}/* replay_read_input */
|
|
@ -1,617 +0,0 @@
|
|||
/*
|
||||
* frotz.h
|
||||
*
|
||||
* Global declarations and definitions
|
||||
*
|
||||
*/
|
||||
|
||||
/* Unfortunately, frotz's bool definition conflicts with that of curses.
|
||||
But since no os_* function uses it, it's safe to let the frotz core see
|
||||
this definition, but have the unix port see the curses version. */
|
||||
|
||||
/* #include "../config.h" */
|
||||
|
||||
#ifndef __UNIX_PORT_FILE
|
||||
#include <signal.h>
|
||||
typedef int bool;
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#endif /* __UNIX_PORT_FILE */
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
typedef unsigned char zbyte;
|
||||
typedef unsigned short zword;
|
||||
|
||||
enum story {
|
||||
BEYOND_ZORK,
|
||||
SHERLOCK,
|
||||
ZORK_ZERO,
|
||||
SHOGUN,
|
||||
ARTHUR,
|
||||
JOURNEY,
|
||||
LURKING_HORROR,
|
||||
UNKNOWN
|
||||
};
|
||||
|
||||
typedef unsigned char zchar;
|
||||
|
||||
/*** Constants that may be set at compile time ***/
|
||||
|
||||
#ifndef MAX_UNDO_SLOTS
|
||||
#define MAX_UNDO_SLOTS 500
|
||||
#endif
|
||||
#ifndef MAX_FILE_NAME
|
||||
#define MAX_FILE_NAME 80
|
||||
#endif
|
||||
#ifndef TEXT_BUFFER_SIZE
|
||||
#define TEXT_BUFFER_SIZE 200
|
||||
#endif
|
||||
#ifndef INPUT_BUFFER_SIZE
|
||||
#define INPUT_BUFFER_SIZE 200
|
||||
#endif
|
||||
#ifndef STACK_SIZE
|
||||
#define STACK_SIZE 1024
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_SAVE_NAME
|
||||
#define DEFAULT_SAVE_NAME "story.sav"
|
||||
#endif
|
||||
#ifndef DEFAULT_SCRIPT_NAME
|
||||
#define DEFAULT_SCRIPT_NAME "story.scr"
|
||||
#endif
|
||||
#ifndef DEFAULT_COMMAND_NAME
|
||||
#define DEFAULT_COMMAND_NAME "story.rec"
|
||||
#endif
|
||||
#ifndef DEFAULT_AUXILARY_NAME
|
||||
#define DEFAULT_AUXILARY_NAME "story.aux"
|
||||
#endif
|
||||
#ifndef DEFAULT_SAVE_DIR /* DG */
|
||||
#define DEFAULT_SAVE_DIR ".frotz-saves"
|
||||
#endif
|
||||
|
||||
/*** Story file header format ***/
|
||||
|
||||
#define H_VERSION 0
|
||||
#define H_CONFIG 1
|
||||
#define H_RELEASE 2
|
||||
#define H_RESIDENT_SIZE 4
|
||||
#define H_START_PC 6
|
||||
#define H_DICTIONARY 8
|
||||
#define H_OBJECTS 10
|
||||
#define H_GLOBALS 12
|
||||
#define H_DYNAMIC_SIZE 14
|
||||
#define H_FLAGS 16
|
||||
#define H_SERIAL 18
|
||||
#define H_ABBREVIATIONS 24
|
||||
#define H_FILE_SIZE 26
|
||||
#define H_CHECKSUM 28
|
||||
#define H_INTERPRETER_NUMBER 30
|
||||
#define H_INTERPRETER_VERSION 31
|
||||
#define H_SCREEN_ROWS 32
|
||||
#define H_SCREEN_COLS 33
|
||||
#define H_SCREEN_WIDTH 34
|
||||
#define H_SCREEN_HEIGHT 36
|
||||
#define H_FONT_HEIGHT 38 /* this is the font width in V5 */
|
||||
#define H_FONT_WIDTH 39 /* this is the font height in V5 */
|
||||
#define H_FUNCTIONS_OFFSET 40
|
||||
#define H_STRINGS_OFFSET 42
|
||||
#define H_DEFAULT_BACKGROUND 44
|
||||
#define H_DEFAULT_FOREGROUND 45
|
||||
#define H_TERMINATING_KEYS 46
|
||||
#define H_LINE_WIDTH 48
|
||||
#define H_STANDARD_HIGH 50
|
||||
#define H_STANDARD_LOW 51
|
||||
#define H_ALPHABET 52
|
||||
#define H_EXTENSION_TABLE 54
|
||||
#define H_USER_NAME 56
|
||||
|
||||
#define HX_TABLE_SIZE 0
|
||||
#define HX_MOUSE_X 1
|
||||
#define HX_MOUSE_Y 2
|
||||
#define HX_UNICODE_TABLE 3
|
||||
|
||||
/*** Various Z-machine constants ***/
|
||||
|
||||
#define V1 1
|
||||
#define V2 2
|
||||
#define V3 3
|
||||
#define V4 4
|
||||
#define V5 5
|
||||
#define V6 6
|
||||
#define V7 7
|
||||
#define V8 8
|
||||
|
||||
#define CONFIG_BYTE_SWAPPED 0x01 /* Story file is byte swapped - V3 */
|
||||
#define CONFIG_TIME 0x02 /* Status line displays time - V3 */
|
||||
#define CONFIG_TWODISKS 0x04 /* Story file occupied two disks - V3 */
|
||||
#define CONFIG_TANDY 0x08 /* Tandy licensed game - V3 */
|
||||
#define CONFIG_NOSTATUSLINE 0x10 /* Interpr can't support status lines - V3 */
|
||||
#define CONFIG_SPLITSCREEN 0x20 /* Interpr supports split screen mode - V3 */
|
||||
#define CONFIG_PROPORTIONAL 0x40 /* Interpr uses proportional font - V3 */
|
||||
|
||||
#define CONFIG_COLOUR 0x01 /* Interpr supports colour - V5+ */
|
||||
#define CONFIG_PICTURES 0x02 /* Interpr supports pictures - V6 */
|
||||
#define CONFIG_BOLDFACE 0x04 /* Interpr supports boldface style - V4+ */
|
||||
#define CONFIG_EMPHASIS 0x08 /* Interpr supports emphasis style - V4+ */
|
||||
#define CONFIG_FIXED 0x10 /* Interpr supports fixed width style - V4+ */
|
||||
#define CONFIG_SOUND 0x20 /* Interpr supports sound - V6 */
|
||||
|
||||
#define CONFIG_TIMEDINPUT 0x80 /* Interpr supports timed input - V4+ */
|
||||
|
||||
#define SCRIPTING_FLAG 0x0001 /* Outputting to transscription file - V1+ */
|
||||
#define FIXED_FONT_FLAG 0x0002 /* Use fixed width font - V3+ */
|
||||
#define REFRESH_FLAG 0x0004 /* Refresh the screen - V6 */
|
||||
#define GRAPHICS_FLAG 0x0008 /* Game wants to use graphics - V5+ */
|
||||
#define OLD_SOUND_FLAG 0x0010 /* Game wants to use sound effects - V3 */
|
||||
#define UNDO_FLAG 0x0010 /* Game wants to use UNDO feature - V5+ */
|
||||
#define MOUSE_FLAG 0x0020 /* Game wants to use a mouse - V5+ */
|
||||
#define COLOUR_FLAG 0x0040 /* Game wants to use colours - V5+ */
|
||||
#define SOUND_FLAG 0x0080 /* Game wants to use sound effects - V5+ */
|
||||
#define MENU_FLAG 0x0100 /* Game wants to use menus - V6 */
|
||||
|
||||
#define INTERP_DEFAULT 0
|
||||
#define INTERP_DEC_20 1
|
||||
#define INTERP_APPLE_IIE 2
|
||||
#define INTERP_MACINTOSH 3
|
||||
#define INTERP_AMIGA 4
|
||||
#define INTERP_ATARI_ST 5
|
||||
#define INTERP_MSDOS 6
|
||||
#define INTERP_CBM_128 7
|
||||
#define INTERP_CBM_64 8
|
||||
#define INTERP_APPLE_IIC 9
|
||||
#define INTERP_APPLE_IIGS 10
|
||||
#define INTERP_TANDY 11
|
||||
|
||||
#define BLACK_COLOUR 2
|
||||
#define RED_COLOUR 3
|
||||
#define GREEN_COLOUR 4
|
||||
#define YELLOW_COLOUR 5
|
||||
#define BLUE_COLOUR 6
|
||||
#define MAGENTA_COLOUR 7
|
||||
#define CYAN_COLOUR 8
|
||||
#define WHITE_COLOUR 9
|
||||
#define GREY_COLOUR 10 /* INTERP_MSDOS only */
|
||||
#define LIGHTGREY_COLOUR 10 /* INTERP_AMIGA only */
|
||||
#define MEDIUMGREY_COLOUR 11 /* INTERP_AMIGA only */
|
||||
#define DARKGREY_COLOUR 12 /* INTERP_AMIGA only */
|
||||
|
||||
#define REVERSE_STYLE 1
|
||||
#define BOLDFACE_STYLE 2
|
||||
#define EMPHASIS_STYLE 4
|
||||
#define FIXED_WIDTH_STYLE 8
|
||||
|
||||
#define TEXT_FONT 1
|
||||
#define PICTURE_FONT 2
|
||||
#define GRAPHICS_FONT 3
|
||||
#define FIXED_WIDTH_FONT 4
|
||||
|
||||
#define BEEP_HIGH 1
|
||||
#define BEEP_LOW 2
|
||||
|
||||
/*** Constants for os_restart_game */
|
||||
|
||||
#define RESTART_BEGIN 0
|
||||
#define RESTART_WPROP_SET 1
|
||||
#define RESTART_END 2
|
||||
|
||||
/*** Character codes ***/
|
||||
|
||||
#define ZC_TIME_OUT 0x00
|
||||
#define ZC_NEW_STYLE 0x01
|
||||
#define ZC_NEW_FONT 0x02
|
||||
#define ZC_BACKSPACE 0x08
|
||||
#define ZC_INDENT 0x09
|
||||
#define ZC_GAP 0x0b
|
||||
#define ZC_RETURN 0x0d
|
||||
#define ZC_HKEY_MIN 0x0e
|
||||
#define ZC_HKEY_RECORD 0x0e
|
||||
#define ZC_HKEY_PLAYBACK 0x0f
|
||||
#define ZC_HKEY_SEED 0x10
|
||||
#define ZC_HKEY_UNDO 0x11
|
||||
#define ZC_HKEY_RESTART 0x12
|
||||
#define ZC_HKEY_QUIT 0x13
|
||||
#define ZC_HKEY_DEBUG 0x14
|
||||
#define ZC_HKEY_HELP 0x15
|
||||
#define ZC_HKEY_MAX 0x15
|
||||
#define ZC_ESCAPE 0x1b
|
||||
#define ZC_ASCII_MIN 0x20
|
||||
#define ZC_ASCII_MAX 0x7e
|
||||
#define ZC_BAD 0x7f
|
||||
#define ZC_ARROW_MIN 0x81
|
||||
#define ZC_ARROW_UP 0x81
|
||||
#define ZC_ARROW_DOWN 0x82
|
||||
#define ZC_ARROW_LEFT 0x83
|
||||
#define ZC_ARROW_RIGHT 0x84
|
||||
#define ZC_ARROW_MAX 0x84
|
||||
#define ZC_FKEY_MIN 0x85
|
||||
#define ZC_FKEY_MAX 0x90
|
||||
#define ZC_NUMPAD_MIN 0x91
|
||||
#define ZC_NUMPAD_MAX 0x9a
|
||||
#define ZC_SINGLE_CLICK 0x9b
|
||||
#define ZC_DOUBLE_CLICK 0x9c
|
||||
#define ZC_MENU_CLICK 0x9d
|
||||
#define ZC_LATIN1_MIN 0xa0
|
||||
#define ZC_LATIN1_MAX 0xff
|
||||
|
||||
/*** File types ***/
|
||||
|
||||
#define FILE_RESTORE 0
|
||||
#define FILE_SAVE 1
|
||||
#define FILE_SCRIPT 2
|
||||
#define FILE_PLAYBACK 3
|
||||
#define FILE_RECORD 4
|
||||
#define FILE_LOAD_AUX 5
|
||||
#define FILE_SAVE_AUX 6
|
||||
|
||||
/*** Data access macros ***/
|
||||
|
||||
#define SET_BYTE(addr,v) { zmp[addr] = v; }
|
||||
#define LOW_BYTE(addr,v) { v = zmp[addr]; }
|
||||
#define CODE_BYTE(v) { v = *pcp++; }
|
||||
|
||||
#if defined (AMIGA)
|
||||
|
||||
extern zbyte *pcp;
|
||||
extern zbyte *zmp;
|
||||
|
||||
#define lo(v) ((zbyte *)&v)[1]
|
||||
#define hi(v) ((zbyte *)&v)[0]
|
||||
|
||||
#define SET_WORD(addr,v) { zmp[addr] = hi(v); zmp[addr+1] = lo(v); }
|
||||
#define LOW_WORD(addr,v) { hi(v) = zmp[addr]; lo(v) = zmp[addr+1]; }
|
||||
#define HIGH_WORD(addr,v) { hi(v) = zmp[addr]; lo(v) = zmp[addr+1]; }
|
||||
#define CODE_WORD(v) { hi(v) = *pcp++; lo(v) = *pcp++; }
|
||||
#define GET_PC(v) { v = pcp - zmp; }
|
||||
#define SET_PC(v) { pcp = zmp + v; }
|
||||
|
||||
#endif
|
||||
|
||||
/* A bunch of x86 assembly code previously appeared here. */
|
||||
|
||||
#if !defined (AMIGA) && !defined (MSDOS_16BIT)
|
||||
|
||||
extern zbyte *pcp;
|
||||
extern zbyte *zmp;
|
||||
|
||||
#define lo(v) (v & 0xff)
|
||||
#define hi(v) (v >> 8)
|
||||
|
||||
#define SET_WORD(addr,v) { zmp[addr] = hi(v); zmp[addr+1] = lo(v); }
|
||||
#define LOW_WORD(addr,v) { v = ((zword) zmp[addr] << 8) | zmp[addr+1]; }
|
||||
#define HIGH_WORD(addr,v) { v = ((zword) zmp[addr] << 8) | zmp[addr+1]; }
|
||||
#define CODE_WORD(v) { v = ((zword) pcp[0] << 8) | pcp[1]; pcp += 2; }
|
||||
#define GET_PC(v) { v = pcp - zmp; }
|
||||
#define SET_PC(v) { pcp = zmp + v; }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*** Story file header data ***/
|
||||
|
||||
extern zbyte h_version;
|
||||
extern zbyte h_config;
|
||||
extern zword h_release;
|
||||
extern zword h_resident_size;
|
||||
extern zword h_start_pc;
|
||||
extern zword h_dictionary;
|
||||
extern zword h_objects;
|
||||
extern zword h_globals;
|
||||
extern zword h_dynamic_size;
|
||||
extern zword h_flags;
|
||||
extern zbyte h_serial[6];
|
||||
extern zword h_abbreviations;
|
||||
extern zword h_file_size;
|
||||
extern zword h_checksum;
|
||||
extern zbyte h_interpreter_number;
|
||||
extern zbyte h_interpreter_version;
|
||||
extern zbyte h_screen_rows;
|
||||
extern zbyte h_screen_cols;
|
||||
extern zword h_screen_width;
|
||||
extern zword h_screen_height;
|
||||
extern zbyte h_font_height;
|
||||
extern zbyte h_font_width;
|
||||
extern zword h_functions_offset;
|
||||
extern zword h_strings_offset;
|
||||
extern zbyte h_default_background;
|
||||
extern zbyte h_default_foreground;
|
||||
extern zword h_terminating_keys;
|
||||
extern zword h_line_width;
|
||||
extern zbyte h_standard_high;
|
||||
extern zbyte h_standard_low;
|
||||
extern zword h_alphabet;
|
||||
extern zword h_extension_table;
|
||||
extern zbyte h_user_name[8];
|
||||
|
||||
extern zword hx_table_size;
|
||||
extern zword hx_mouse_x;
|
||||
extern zword hx_mouse_y;
|
||||
extern zword hx_unicode_table;
|
||||
|
||||
/*** Various data ***/
|
||||
|
||||
extern char *story_name;
|
||||
|
||||
extern enum story story_id;
|
||||
extern long story_size;
|
||||
|
||||
extern zword stack[STACK_SIZE];
|
||||
extern zword *sp;
|
||||
extern zword *fp;
|
||||
extern zword frame_count;
|
||||
|
||||
extern zword zargs[8];
|
||||
extern int zargc;
|
||||
|
||||
extern bool ostream_screen;
|
||||
extern bool ostream_script;
|
||||
extern bool ostream_memory;
|
||||
extern bool ostream_record;
|
||||
extern bool istream_replay;
|
||||
extern bool message;
|
||||
|
||||
extern int cwin;
|
||||
extern int mwin;
|
||||
|
||||
extern int mouse_x;
|
||||
extern int mouse_y;
|
||||
|
||||
extern bool enable_wrapping;
|
||||
extern bool enable_scripting;
|
||||
extern bool enable_scrolling;
|
||||
extern bool enable_buffering;
|
||||
|
||||
|
||||
extern char *option_zcode_path; /* dg */
|
||||
|
||||
extern long reserve_mem;
|
||||
|
||||
|
||||
/*** Blorb stuff ***/
|
||||
/*
|
||||
bb_err_t blorb_err;
|
||||
bb_map_t *blorb_map;
|
||||
*/
|
||||
|
||||
/*** Z-machine opcodes ***/
|
||||
|
||||
void z_add (void);
|
||||
void z_and (void);
|
||||
void z_art_shift (void);
|
||||
void z_buffer_mode (void);
|
||||
void z_call_n (void);
|
||||
void z_call_s (void);
|
||||
void z_catch (void);
|
||||
void z_check_arg_count (void);
|
||||
void z_check_unicode (void);
|
||||
void z_clear_attr (void);
|
||||
void z_copy_table (void);
|
||||
void z_dec (void);
|
||||
void z_dec_chk (void);
|
||||
void z_div (void);
|
||||
void z_draw_picture (void);
|
||||
void z_encode_text (void);
|
||||
void z_erase_line (void);
|
||||
void z_erase_picture (void);
|
||||
void z_erase_window (void);
|
||||
void z_get_child (void);
|
||||
void z_get_cursor (void);
|
||||
void z_get_next_prop (void);
|
||||
void z_get_parent (void);
|
||||
void z_get_prop (void);
|
||||
void z_get_prop_addr (void);
|
||||
void z_get_prop_len (void);
|
||||
void z_get_sibling (void);
|
||||
void z_get_wind_prop (void);
|
||||
void z_inc (void);
|
||||
void z_inc_chk (void);
|
||||
void z_input_stream (void);
|
||||
void z_insert_obj (void);
|
||||
void z_je (void);
|
||||
void z_jg (void);
|
||||
void z_jin (void);
|
||||
void z_jl (void);
|
||||
void z_jump (void);
|
||||
void z_jz (void);
|
||||
void z_load (void);
|
||||
void z_loadb (void);
|
||||
void z_loadw (void);
|
||||
void z_log_shift (void);
|
||||
void z_make_menu (void);
|
||||
void z_mod (void);
|
||||
void z_mouse_window (void);
|
||||
void z_move_window (void);
|
||||
void z_mul (void);
|
||||
void z_new_line (void);
|
||||
void z_nop (void);
|
||||
void z_not (void);
|
||||
void z_or (void);
|
||||
void z_output_stream (void);
|
||||
void z_picture_data (void);
|
||||
void z_picture_table (void);
|
||||
void z_piracy (void);
|
||||
void z_pop (void);
|
||||
void z_pop_stack (void);
|
||||
void z_print (void);
|
||||
void z_print_addr (void);
|
||||
void z_print_char (void);
|
||||
void z_print_form (void);
|
||||
void z_print_num (void);
|
||||
void z_print_obj (void);
|
||||
void z_print_paddr (void);
|
||||
void z_print_ret (void);
|
||||
void z_print_table (void);
|
||||
void z_print_unicode (void);
|
||||
void z_pull (void);
|
||||
void z_push (void);
|
||||
void z_push_stack (void);
|
||||
void z_put_prop (void);
|
||||
void z_put_wind_prop (void);
|
||||
void z_quit (void);
|
||||
void z_random (void);
|
||||
void z_read (void);
|
||||
void z_read_char (void);
|
||||
void z_read_mouse (void);
|
||||
void z_remove_obj (void);
|
||||
void z_restart (void);
|
||||
void z_restore (void);
|
||||
void z_restore_undo (void);
|
||||
void z_ret (void);
|
||||
void z_ret_popped (void);
|
||||
void z_rfalse (void);
|
||||
void z_rtrue (void);
|
||||
void z_save (void);
|
||||
void z_save_undo (void);
|
||||
void z_scan_table (void);
|
||||
void z_scroll_window (void);
|
||||
void z_set_attr (void);
|
||||
void z_set_font (void);
|
||||
void z_set_colour (void);
|
||||
void z_set_cursor (void);
|
||||
void z_set_margins (void);
|
||||
void z_set_window (void);
|
||||
void z_set_text_style (void);
|
||||
void z_show_status (void);
|
||||
void z_sound_effect (void);
|
||||
void z_split_window (void);
|
||||
void z_store (void);
|
||||
void z_storeb (void);
|
||||
void z_storew (void);
|
||||
void z_sub (void);
|
||||
void z_test (void);
|
||||
void z_test_attr (void);
|
||||
void z_throw (void);
|
||||
void z_tokenise (void);
|
||||
void z_verify (void);
|
||||
void z_window_size (void);
|
||||
void z_window_style (void);
|
||||
|
||||
/* Definitions for error handling functions and error codes. */
|
||||
|
||||
/* extern int err_report_mode; */
|
||||
|
||||
void init_err (void);
|
||||
void runtime_error (int);
|
||||
|
||||
/* Error codes */
|
||||
#define ERR_TEXT_BUF_OVF 1 /* Text buffer overflow */
|
||||
#define ERR_STORE_RANGE 2 /* Store out of dynamic memory */
|
||||
#define ERR_DIV_ZERO 3 /* Division by zero */
|
||||
#define ERR_ILL_OBJ 4 /* Illegal object */
|
||||
#define ERR_ILL_ATTR 5 /* Illegal attribute */
|
||||
#define ERR_NO_PROP 6 /* No such property */
|
||||
#define ERR_STK_OVF 7 /* Stack overflow */
|
||||
#define ERR_ILL_CALL_ADDR 8 /* Call to illegal address */
|
||||
#define ERR_CALL_NON_RTN 9 /* Call to non-routine */
|
||||
#define ERR_STK_UNDF 10 /* Stack underflow */
|
||||
#define ERR_ILL_OPCODE 11 /* Illegal opcode */
|
||||
#define ERR_BAD_FRAME 12 /* Bad stack frame */
|
||||
#define ERR_ILL_JUMP_ADDR 13 /* Jump to illegal address */
|
||||
#define ERR_SAVE_IN_INTER 14 /* Can't save while in interrupt */
|
||||
#define ERR_STR3_NESTING 15 /* Nesting stream #3 too deep */
|
||||
#define ERR_ILL_WIN 16 /* Illegal window */
|
||||
#define ERR_ILL_WIN_PROP 17 /* Illegal window property */
|
||||
#define ERR_ILL_PRINT_ADDR 18 /* Print at illegal address */
|
||||
#define ERR_MAX_FATAL 18
|
||||
|
||||
/* Less serious errors */
|
||||
#define ERR_JIN_0 19 /* @jin called with object 0 */
|
||||
#define ERR_GET_CHILD_0 20 /* @get_child called with object 0 */
|
||||
#define ERR_GET_PARENT_0 21 /* @get_parent called with object 0 */
|
||||
#define ERR_GET_SIBLING_0 22 /* @get_sibling called with object 0 */
|
||||
#define ERR_GET_PROP_ADDR_0 23 /* @get_prop_addr called with object 0 */
|
||||
#define ERR_GET_PROP_0 24 /* @get_prop called with object 0 */
|
||||
#define ERR_PUT_PROP_0 25 /* @put_prop called with object 0 */
|
||||
#define ERR_CLEAR_ATTR_0 26 /* @clear_attr called with object 0 */
|
||||
#define ERR_SET_ATTR_0 27 /* @set_attr called with object 0 */
|
||||
#define ERR_TEST_ATTR_0 28 /* @test_attr called with object 0 */
|
||||
#define ERR_MOVE_OBJECT_0 29 /* @move_object called moving object 0 */
|
||||
#define ERR_MOVE_OBJECT_TO_0 30 /* @move_object called moving into object 0 */
|
||||
#define ERR_REMOVE_OBJECT_0 31 /* @remove_object called with object 0 */
|
||||
#define ERR_GET_NEXT_PROP_0 32 /* @get_next_prop called with object 0 */
|
||||
#define ERR_NUM_ERRORS (32)
|
||||
|
||||
/* There are four error reporting modes: never report errors;
|
||||
report only the first time a given error type occurs; report
|
||||
every time an error occurs; or treat all errors as fatal
|
||||
errors, killing the interpreter. I strongly recommend
|
||||
"report once" as the default. But you can compile in a
|
||||
different default by changing the definition of
|
||||
ERR_DEFAULT_REPORT_MODE. In any case, the player can
|
||||
specify a report mode on the command line by typing "-Z 0"
|
||||
through "-Z 3". */
|
||||
|
||||
#define ERR_REPORT_NEVER (0)
|
||||
#define ERR_REPORT_ONCE (1)
|
||||
#define ERR_REPORT_ALWAYS (2)
|
||||
#define ERR_REPORT_FATAL (3)
|
||||
|
||||
#define ERR_DEFAULT_REPORT_MODE ERR_REPORT_ONCE
|
||||
|
||||
|
||||
/*** Various global functions ***/
|
||||
|
||||
zchar translate_from_zscii (zbyte);
|
||||
zbyte translate_to_zscii (zchar);
|
||||
|
||||
void flush_buffer (void);
|
||||
void new_line (void);
|
||||
void print_char (zchar);
|
||||
void print_num (zword);
|
||||
void print_object (zword);
|
||||
void print_string (const char *);
|
||||
|
||||
void stream_mssg_on (void);
|
||||
void stream_mssg_off (void);
|
||||
|
||||
void ret (zword);
|
||||
void store (zword);
|
||||
void branch (bool);
|
||||
|
||||
void storeb (zword, zbyte);
|
||||
void storew (zword, zword);
|
||||
|
||||
/*** Interface functions ***/
|
||||
|
||||
void os_beep (int);
|
||||
int os_char_width (zchar);
|
||||
void os_display_char (zchar);
|
||||
void os_display_string (const zchar *);
|
||||
void os_draw_picture (int, int, int);
|
||||
void os_erase_area (int, int, int, int);
|
||||
void os_fatal (const char *);
|
||||
void os_finish_with_sample (int);
|
||||
int os_font_data (int, int *, int *);
|
||||
void os_init_screen (void);
|
||||
void os_more_prompt (void);
|
||||
int os_peek_colour (void);
|
||||
int os_picture_data (int, int *, int *);
|
||||
void os_prepare_sample (int);
|
||||
void os_process_arguments (int, char *[]);
|
||||
int os_random_seed (void);
|
||||
int os_read_file_name (char *, const char *, int);
|
||||
zchar os_read_key (int, int);
|
||||
zchar os_read_line (int, zchar *, int, int, int);
|
||||
void os_reset_screen (void);
|
||||
void os_restart_game (int);
|
||||
void os_scroll_area (int, int, int, int, int);
|
||||
void os_set_colour (int, int);
|
||||
void os_set_cursor (int, int);
|
||||
void os_set_font (int);
|
||||
void os_set_text_style (int);
|
||||
void os_start_sample (int, int, int, zword);
|
||||
void os_stop_sample (int);
|
||||
int os_string_width (const zchar *);
|
||||
void os_init_setup (void);
|
||||
int os_speech_output(const zchar *);
|
||||
|
||||
#include "setup.h"
|
|
@ -1,72 +0,0 @@
|
|||
/*
|
||||
* getopt.c
|
||||
*
|
||||
* Replacement for a Unix style getopt function
|
||||
*
|
||||
* Quick, clean, and portable to funky systems that don't have getopt()
|
||||
* for whatever reason.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef MSDOS_16BIT
|
||||
#define cdecl
|
||||
#endif
|
||||
|
||||
int optind = 1;
|
||||
int optopt = 0;
|
||||
|
||||
const char *optarg = NULL;
|
||||
|
||||
int cdecl getopt (int argc, char *argv[], const char *options)
|
||||
{
|
||||
static int pos = 1;
|
||||
|
||||
const char *p;
|
||||
|
||||
if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == 0)
|
||||
return EOF;
|
||||
|
||||
optopt = argv[optind][pos++];
|
||||
optarg = NULL;
|
||||
|
||||
if (argv[optind][pos] == 0)
|
||||
{ pos = 1; optind++; }
|
||||
|
||||
p = strchr (options, optopt);
|
||||
|
||||
if (optopt == ':' || p == NULL) {
|
||||
|
||||
fputs ("illegal option -- ", stdout);
|
||||
goto error;
|
||||
|
||||
} else if (p[1] == ':') {
|
||||
|
||||
if (optind >= argc) {
|
||||
|
||||
fputs ("option requires an argument -- ", stdout);
|
||||
goto error;
|
||||
|
||||
} else {
|
||||
|
||||
optarg = argv[optind];
|
||||
|
||||
if (pos != 1)
|
||||
optarg += pos;
|
||||
|
||||
pos = 1; optind++;
|
||||
|
||||
}
|
||||
}
|
||||
return optopt;
|
||||
|
||||
error:
|
||||
|
||||
fputc (optopt, stdout);
|
||||
fputc ('\n', stdout);
|
||||
|
||||
return '?';
|
||||
|
||||
}/* getopt */
|
|
@ -1,258 +0,0 @@
|
|||
/* hotkey.c - Hot key functions
|
||||
* Copyright (c) 1995-1997 Stefan Jokisch
|
||||
*
|
||||
* This file is part of Frotz.
|
||||
*
|
||||
* Frotz 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.
|
||||
*
|
||||
* Frotz 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
|
||||
*/
|
||||
|
||||
#include "frotz.h"
|
||||
|
||||
extern int restore_undo (void);
|
||||
|
||||
extern int read_number (void);
|
||||
|
||||
extern bool read_yes_or_no (const char *);
|
||||
|
||||
extern void replay_open (void);
|
||||
extern void replay_close (void);
|
||||
extern void record_open (void);
|
||||
extern void record_close (void);
|
||||
|
||||
extern void seed_random (int);
|
||||
|
||||
/*
|
||||
* hot_key_debugging
|
||||
*
|
||||
* ...allows user to toggle cheating options on/off.
|
||||
*
|
||||
*/
|
||||
|
||||
static bool hot_key_debugging (void)
|
||||
{
|
||||
|
||||
print_string ("Debugging options\n");
|
||||
|
||||
f_setup.attribute_assignment = read_yes_or_no ("Watch attribute assignment");
|
||||
f_setup.attribute_testing = read_yes_or_no ("Watch attribute testing");
|
||||
|
||||
f_setup.object_movement = read_yes_or_no ("Watch object movement");
|
||||
f_setup.object_locating = read_yes_or_no ("Watch object locating");
|
||||
|
||||
return FALSE;
|
||||
|
||||
}/* hot_key_debugging */
|
||||
|
||||
/*
|
||||
* hot_key_help
|
||||
*
|
||||
* ...displays a list of all hot keys.
|
||||
*
|
||||
*/
|
||||
|
||||
static bool hot_key_help (void) {
|
||||
|
||||
print_string ("Help\n");
|
||||
|
||||
print_string (
|
||||
"\n"
|
||||
"Alt-D debugging options\n"
|
||||
"Alt-H help\n"
|
||||
"Alt-N new game\n"
|
||||
"Alt-P playback on\n"
|
||||
"Alt-R recording on/off\n"
|
||||
"Alt-S seed random numbers\n"
|
||||
"Alt-U undo one turn\n"
|
||||
"Alt-X exit game\n");
|
||||
|
||||
return FALSE;
|
||||
|
||||
}/* hot_key_help */
|
||||
|
||||
/*
|
||||
* hot_key_playback
|
||||
*
|
||||
* ...allows user to turn playback on.
|
||||
*
|
||||
*/
|
||||
|
||||
static bool hot_key_playback (void)
|
||||
{
|
||||
|
||||
print_string ("Playback on\n");
|
||||
|
||||
if (!istream_replay)
|
||||
replay_open ();
|
||||
|
||||
return FALSE;
|
||||
|
||||
}/* hot_key_playback */
|
||||
|
||||
/*
|
||||
* hot_key_recording
|
||||
*
|
||||
* ...allows user to turn recording on/off.
|
||||
*
|
||||
*/
|
||||
|
||||
static bool hot_key_recording (void)
|
||||
{
|
||||
|
||||
if (istream_replay) {
|
||||
print_string ("Playback off\n");
|
||||
replay_close ();
|
||||
} else if (ostream_record) {
|
||||
print_string ("Recording off\n");
|
||||
record_close ();
|
||||
} else {
|
||||
print_string ("Recording on\n");
|
||||
record_open ();
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
||||
}/* hot_key_recording */
|
||||
|
||||
/*
|
||||
* hot_key_seed
|
||||
*
|
||||
* ...allows user to seed the random number seed.
|
||||
*
|
||||
*/
|
||||
|
||||
static bool hot_key_seed (void)
|
||||
{
|
||||
|
||||
print_string ("Seed random numbers\n");
|
||||
|
||||
print_string ("Enter seed value (or return to randomize): ");
|
||||
seed_random (read_number ());
|
||||
|
||||
return FALSE;
|
||||
|
||||
}/* hot_key_seed */
|
||||
|
||||
/*
|
||||
* hot_key_undo
|
||||
*
|
||||
* ...allows user to undo the previous turn.
|
||||
*
|
||||
*/
|
||||
|
||||
static bool hot_key_undo (void)
|
||||
{
|
||||
|
||||
print_string ("Undo one turn\n");
|
||||
|
||||
if (restore_undo ()) {
|
||||
|
||||
if (h_version >= V5) { /* for V5+ games we must */
|
||||
store (2); /* store 2 (for success) */
|
||||
return TRUE; /* and abort the input */
|
||||
}
|
||||
|
||||
if (h_version <= V3) { /* for V3- games we must */
|
||||
z_show_status (); /* draw the status line */
|
||||
return FALSE; /* and continue input */
|
||||
}
|
||||
|
||||
} else print_string ("No more undo information available.\n");
|
||||
|
||||
return FALSE;
|
||||
|
||||
}/* hot_key_undo */
|
||||
|
||||
/*
|
||||
* hot_key_restart
|
||||
*
|
||||
* ...allows user to start a new game.
|
||||
*
|
||||
*/
|
||||
|
||||
static bool hot_key_restart (void)
|
||||
{
|
||||
|
||||
print_string ("New game\n");
|
||||
|
||||
if (read_yes_or_no ("Do you wish to restart")) {
|
||||
|
||||
z_restart ();
|
||||
return TRUE;
|
||||
|
||||
} else return FALSE;
|
||||
|
||||
}/* hot_key_restart */
|
||||
|
||||
/*
|
||||
* hot_key_quit
|
||||
*
|
||||
* ...allows user to exit the game.
|
||||
*
|
||||
*/
|
||||
|
||||
static bool hot_key_quit (void)
|
||||
{
|
||||
|
||||
print_string ("Exit game\n");
|
||||
|
||||
if (read_yes_or_no ("Do you wish to quit")) {
|
||||
|
||||
z_quit ();
|
||||
return TRUE;
|
||||
|
||||
} else return FALSE;
|
||||
|
||||
}/* hot_key_quit */
|
||||
|
||||
/*
|
||||
* handle_hot_key
|
||||
*
|
||||
* Perform the action associated with a so-called hot key. Return
|
||||
* true to abort the current input action.
|
||||
*
|
||||
*/
|
||||
|
||||
bool handle_hot_key (zchar key)
|
||||
{
|
||||
|
||||
if (cwin == 0) {
|
||||
|
||||
bool aborting;
|
||||
|
||||
aborting = FALSE;
|
||||
|
||||
print_string ("\nHot key -- ");
|
||||
|
||||
switch (key) {
|
||||
case ZC_HKEY_RECORD: aborting = hot_key_recording (); break;
|
||||
case ZC_HKEY_PLAYBACK: aborting = hot_key_playback (); break;
|
||||
case ZC_HKEY_SEED: aborting = hot_key_seed (); break;
|
||||
case ZC_HKEY_UNDO: aborting = hot_key_undo (); break;
|
||||
case ZC_HKEY_RESTART: aborting = hot_key_restart (); break;
|
||||
case ZC_HKEY_QUIT: aborting = hot_key_quit (); break;
|
||||
case ZC_HKEY_DEBUG: aborting = hot_key_debugging (); break;
|
||||
case ZC_HKEY_HELP: aborting = hot_key_help (); break;
|
||||
}
|
||||
|
||||
if (aborting)
|
||||
return TRUE;
|
||||
|
||||
print_string ("\nContinue input...\n");
|
||||
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
||||
}/* handle_hot_key */
|
|
@ -1,323 +0,0 @@
|
|||
/* input.c - High level input functions
|
||||
* Copyright (c) 1995-1997 Stefan Jokisch
|
||||
*
|
||||
* This file is part of Frotz.
|
||||
*
|
||||
* Frotz 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.
|
||||
*
|
||||
* Frotz 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
|
||||
*/
|
||||
|
||||
#include "frotz.h"
|
||||
|
||||
extern int save_undo (void);
|
||||
|
||||
extern zchar stream_read_key (zword, zword, bool);
|
||||
extern zchar stream_read_input (int, zchar *, zword, zword, bool, bool);
|
||||
|
||||
extern void tokenise_line (zword, zword, zword, bool);
|
||||
|
||||
/*
|
||||
* is_terminator
|
||||
*
|
||||
* Check if the given key is an input terminator.
|
||||
*
|
||||
*/
|
||||
|
||||
bool is_terminator (zchar key)
|
||||
{
|
||||
|
||||
if (key == ZC_TIME_OUT)
|
||||
return TRUE;
|
||||
if (key == ZC_RETURN)
|
||||
return TRUE;
|
||||
if (key >= ZC_HKEY_MIN && key <= ZC_HKEY_MAX)
|
||||
return TRUE;
|
||||
|
||||
if (h_terminating_keys != 0)
|
||||
|
||||
if (key >= ZC_ARROW_MIN && key <= ZC_MENU_CLICK) {
|
||||
|
||||
zword addr = h_terminating_keys;
|
||||
zbyte c;
|
||||
|
||||
do {
|
||||
LOW_BYTE (addr, c)
|
||||
if (c == 255 || key == translate_from_zscii (c))
|
||||
return TRUE;
|
||||
addr++;
|
||||
} while (c != 0);
|
||||
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
||||
}/* is_terminator */
|
||||
|
||||
/*
|
||||
* z_make_menu, add or remove a menu and branch if successful.
|
||||
*
|
||||
* zargs[0] = number of menu
|
||||
* zargs[1] = table of menu entries or 0 to remove menu
|
||||
*
|
||||
*/
|
||||
|
||||
void z_make_menu (void)
|
||||
{
|
||||
|
||||
/* This opcode was only used for the Macintosh version of Journey.
|
||||
It controls menus with numbers greater than 2 (menus 0, 1 and 2
|
||||
are system menus). Frotz doesn't implement menus yet. */
|
||||
|
||||
branch (FALSE);
|
||||
|
||||
}/* z_make_menu */
|
||||
|
||||
/*
|
||||
* read_yes_or_no
|
||||
*
|
||||
* Ask the user a question; return true if the answer is yes.
|
||||
*
|
||||
*/
|
||||
|
||||
bool read_yes_or_no (const char *s)
|
||||
{
|
||||
zchar key;
|
||||
|
||||
print_string (s);
|
||||
print_string ("? (y/n) >");
|
||||
|
||||
key = stream_read_key (0, 0, FALSE);
|
||||
|
||||
if (key == 'y' || key == 'Y') {
|
||||
print_string ("y\n");
|
||||
return TRUE;
|
||||
} else {
|
||||
print_string ("n\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
}/* read_yes_or_no */
|
||||
|
||||
/*
|
||||
* read_string
|
||||
*
|
||||
* Read a string from the current input stream.
|
||||
*
|
||||
*/
|
||||
|
||||
void read_string (int max, zchar *buffer)
|
||||
{
|
||||
zchar key;
|
||||
|
||||
buffer[0] = 0;
|
||||
|
||||
do {
|
||||
|
||||
key = stream_read_input (max, buffer, 0, 0, FALSE, FALSE);
|
||||
|
||||
} while (key != ZC_RETURN);
|
||||
|
||||
}/* read_string */
|
||||
|
||||
/*
|
||||
* read_number
|
||||
*
|
||||
* Ask the user to type in a number and return it.
|
||||
*
|
||||
*/
|
||||
|
||||
int read_number (void)
|
||||
{
|
||||
zchar buffer[6];
|
||||
int value = 0;
|
||||
int i;
|
||||
|
||||
read_string (5, buffer);
|
||||
|
||||
for (i = 0; buffer[i] != 0; i++)
|
||||
if (buffer[i] >= '0' && buffer[i] <= '9')
|
||||
value = 10 * value + buffer[i] - '0';
|
||||
|
||||
return value;
|
||||
|
||||
}/* read_number */
|
||||
|
||||
/*
|
||||
* z_read, read a line of input and (in V5+) store the terminating key.
|
||||
*
|
||||
* zargs[0] = address of text buffer
|
||||
* zargs[1] = address of token buffer
|
||||
* zargs[2] = timeout in tenths of a second (optional)
|
||||
* zargs[3] = packed address of routine to be called on timeout
|
||||
*
|
||||
*/
|
||||
|
||||
void z_read (void)
|
||||
{
|
||||
zchar buffer[INPUT_BUFFER_SIZE];
|
||||
zword addr;
|
||||
zchar key;
|
||||
zbyte max, size;
|
||||
zbyte c;
|
||||
int i;
|
||||
|
||||
/* Supply default arguments */
|
||||
|
||||
if (zargc < 3)
|
||||
zargs[2] = 0;
|
||||
|
||||
/* Get maximum input size */
|
||||
|
||||
addr = zargs[0];
|
||||
|
||||
LOW_BYTE (addr, max)
|
||||
|
||||
if (h_version <= V4)
|
||||
max--;
|
||||
|
||||
if (max >= INPUT_BUFFER_SIZE)
|
||||
max = INPUT_BUFFER_SIZE - 1;
|
||||
|
||||
/* Get initial input size */
|
||||
|
||||
if (h_version >= V5) {
|
||||
addr++;
|
||||
LOW_BYTE (addr, size)
|
||||
} else size = 0;
|
||||
|
||||
/* Copy initial input to local buffer */
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
addr++;
|
||||
LOW_BYTE (addr, c)
|
||||
buffer[i] = translate_from_zscii (c);
|
||||
}
|
||||
|
||||
buffer[i] = 0;
|
||||
|
||||
/* Draw status line for V1 to V3 games */
|
||||
|
||||
if (h_version <= V3)
|
||||
z_show_status ();
|
||||
|
||||
/* Read input from current input stream */
|
||||
|
||||
key = stream_read_input (
|
||||
max, buffer, /* buffer and size */
|
||||
zargs[2], /* timeout value */
|
||||
zargs[3], /* timeout routine */
|
||||
TRUE, /* enable hot keys */
|
||||
h_version == V6); /* no script in V6 */
|
||||
|
||||
if (key == ZC_BAD)
|
||||
return;
|
||||
|
||||
/* Perform save_undo for V1 to V4 games */
|
||||
|
||||
if (h_version <= V4)
|
||||
save_undo ();
|
||||
|
||||
/* Copy local buffer back to dynamic memory */
|
||||
|
||||
for (i = 0; buffer[i] != 0; i++) {
|
||||
|
||||
if (key == ZC_RETURN) {
|
||||
|
||||
if (buffer[i] >= 'A' && buffer[i] <= 'Z')
|
||||
buffer[i] += 'a' - 'A';
|
||||
if (buffer[i] >= 0xc0 && buffer[i] <= 0xde && buffer[i] != 0xd7)
|
||||
buffer[i] += 0x20;
|
||||
|
||||
}
|
||||
|
||||
storeb ((zword) (zargs[0] + ((h_version <= V4) ? 1 : 2) + i), translate_to_zscii (buffer[i]));
|
||||
|
||||
}
|
||||
|
||||
/* Add null character (V1-V4) or write input length into 2nd byte */
|
||||
|
||||
if (h_version <= V4)
|
||||
storeb ((zword) (zargs[0] + 1 + i), 0);
|
||||
else
|
||||
storeb ((zword) (zargs[0] + 1), i);
|
||||
|
||||
/* Tokenise line if a token buffer is present */
|
||||
|
||||
if (key == ZC_RETURN && zargs[1] != 0)
|
||||
tokenise_line (zargs[0], zargs[1], 0, FALSE);
|
||||
|
||||
/* Store key */
|
||||
|
||||
if (h_version >= V5)
|
||||
store (translate_to_zscii (key));
|
||||
|
||||
}/* z_read */
|
||||
|
||||
/*
|
||||
* z_read_char, read and store a key.
|
||||
*
|
||||
* zargs[0] = input device (must be 1)
|
||||
* zargs[1] = timeout in tenths of a second (optional)
|
||||
* zargs[2] = packed address of routine to be called on timeout
|
||||
*
|
||||
*/
|
||||
|
||||
void z_read_char (void)
|
||||
{
|
||||
zchar key;
|
||||
|
||||
/* Supply default arguments */
|
||||
|
||||
if (zargc < 2)
|
||||
zargs[1] = 0;
|
||||
|
||||
/* Read input from the current input stream */
|
||||
|
||||
key = stream_read_key (
|
||||
zargs[1], /* timeout value */
|
||||
zargs[2], /* timeout routine */
|
||||
TRUE); /* enable hot keys */
|
||||
|
||||
if (key == ZC_BAD)
|
||||
return;
|
||||
|
||||
/* Store key */
|
||||
|
||||
store (translate_to_zscii (key));
|
||||
|
||||
}/* z_read_char */
|
||||
|
||||
/*
|
||||
* z_read_mouse, write the current mouse status into a table.
|
||||
*
|
||||
* zargs[0] = address of table
|
||||
*
|
||||
*/
|
||||
|
||||
void z_read_mouse (void)
|
||||
{
|
||||
zword btn;
|
||||
|
||||
/* Read the mouse position and which buttons are down */
|
||||
|
||||
btn = os_read_mouse ();
|
||||
hx_mouse_y = mouse_y;
|
||||
hx_mouse_x = mouse_x;
|
||||
|
||||
storew ((zword) (zargs[0] + 0), hx_mouse_y);
|
||||
storew ((zword) (zargs[0] + 2), hx_mouse_x);
|
||||
storew ((zword) (zargs[0] + 4), btn); /* mouse button bits */
|
||||
storew ((zword) (zargs[0] + 6), 0); /* menu selection */
|
||||
|
||||
}/* z_read_mouse */
|
|
@ -1,197 +0,0 @@
|
|||
/* main.c - Frotz V2.40 main function
|
||||
* Copyright (c) 1995-1997 Stefan Jokisch
|
||||
*
|
||||
* This file is part of Frotz.
|
||||
*
|
||||
* Frotz 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.
|
||||
*
|
||||
* Frotz 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is an interpreter for Infocom V1 to V6 games. It also supports
|
||||
* the recently defined V7 and V8 games. Please report bugs to
|
||||
*
|
||||
* s.jokisch@avu.de
|
||||
*
|
||||
*/
|
||||
|
||||
#include "frotz.h"
|
||||
|
||||
#ifndef MSDOS_16BIT
|
||||
#define cdecl
|
||||
#endif
|
||||
|
||||
extern void interpret (void);
|
||||
extern void init_memory (void);
|
||||
extern void init_undo (void);
|
||||
extern void reset_memory (void);
|
||||
|
||||
/* Story file name, id number and size */
|
||||
|
||||
char *story_name = 0;
|
||||
|
||||
enum story story_id = UNKNOWN;
|
||||
long story_size = 0;
|
||||
|
||||
/* Story file header data */
|
||||
|
||||
zbyte h_version = 0;
|
||||
zbyte h_config = 0;
|
||||
zword h_release = 0;
|
||||
zword h_resident_size = 0;
|
||||
zword h_start_pc = 0;
|
||||
zword h_dictionary = 0;
|
||||
zword h_objects = 0;
|
||||
zword h_globals = 0;
|
||||
zword h_dynamic_size = 0;
|
||||
zword h_flags = 0;
|
||||
zbyte h_serial[6] = { 0, 0, 0, 0, 0, 0 };
|
||||
zword h_abbreviations = 0;
|
||||
zword h_file_size = 0;
|
||||
zword h_checksum = 0;
|
||||
zbyte h_interpreter_number = 0;
|
||||
zbyte h_interpreter_version = 0;
|
||||
zbyte h_screen_rows = 0;
|
||||
zbyte h_screen_cols = 0;
|
||||
zword h_screen_width = 0;
|
||||
zword h_screen_height = 0;
|
||||
zbyte h_font_height = 1;
|
||||
zbyte h_font_width = 1;
|
||||
zword h_functions_offset = 0;
|
||||
zword h_strings_offset = 0;
|
||||
zbyte h_default_background = 0;
|
||||
zbyte h_default_foreground = 0;
|
||||
zword h_terminating_keys = 0;
|
||||
zword h_line_width = 0;
|
||||
zbyte h_standard_high = 1;
|
||||
zbyte h_standard_low = 0;
|
||||
zword h_alphabet = 0;
|
||||
zword h_extension_table = 0;
|
||||
zbyte h_user_name[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
zword hx_table_size = 0;
|
||||
zword hx_mouse_x = 0;
|
||||
zword hx_mouse_y = 0;
|
||||
zword hx_unicode_table = 0;
|
||||
|
||||
/* Stack data */
|
||||
|
||||
zword stack[STACK_SIZE];
|
||||
zword *sp = 0;
|
||||
zword *fp = 0;
|
||||
zword frame_count = 0;
|
||||
|
||||
/* IO streams */
|
||||
|
||||
bool ostream_screen = TRUE;
|
||||
bool ostream_script = FALSE;
|
||||
bool ostream_memory = FALSE;
|
||||
bool ostream_record = FALSE;
|
||||
bool istream_replay = FALSE;
|
||||
bool message = FALSE;
|
||||
|
||||
/* Current window and mouse data */
|
||||
|
||||
int cwin = 0;
|
||||
int mwin = 0;
|
||||
|
||||
int mouse_y = 0;
|
||||
int mouse_x = 0;
|
||||
|
||||
/* Window attributes */
|
||||
|
||||
bool enable_wrapping = FALSE;
|
||||
bool enable_scripting = FALSE;
|
||||
bool enable_scrolling = FALSE;
|
||||
bool enable_buffering = FALSE;
|
||||
|
||||
/* User options */
|
||||
|
||||
/*
|
||||
int option_attribute_assignment = 0;
|
||||
int option_attribute_testing = 0;
|
||||
int option_context_lines = 0;
|
||||
int option_object_locating = 0;
|
||||
int option_object_movement = 0;
|
||||
int option_left_margin = 0;
|
||||
int option_right_margin = 0;
|
||||
int option_ignore_errors = 0;
|
||||
int option_piracy = 0;
|
||||
int option_undo_slots = MAX_UNDO_SLOTS;
|
||||
int option_expand_abbreviations = 0;
|
||||
int option_script_cols = 80;
|
||||
int option_save_quetzal = 1;
|
||||
*/
|
||||
|
||||
int option_sound = 1;
|
||||
char *option_zcode_path;
|
||||
|
||||
|
||||
/* Size of memory to reserve (in bytes) */
|
||||
|
||||
long reserve_mem = 0;
|
||||
|
||||
/*
|
||||
* z_piracy, branch if the story file is a legal copy.
|
||||
*
|
||||
* no zargs used
|
||||
*
|
||||
*/
|
||||
|
||||
void z_piracy (void)
|
||||
{
|
||||
|
||||
branch (!f_setup.piracy);
|
||||
|
||||
}/* z_piracy */
|
||||
|
||||
/*
|
||||
* main
|
||||
*
|
||||
* Prepare and run the game.
|
||||
*
|
||||
*/
|
||||
|
||||
int cdecl main (int argc, char *argv[])
|
||||
{
|
||||
|
||||
os_init_setup ();
|
||||
|
||||
os_process_arguments (argc, argv);
|
||||
|
||||
init_buffer ();
|
||||
|
||||
init_err ();
|
||||
|
||||
init_memory ();
|
||||
|
||||
init_process ();
|
||||
|
||||
init_sound ();
|
||||
|
||||
os_init_screen ();
|
||||
|
||||
init_undo ();
|
||||
|
||||
z_restart ();
|
||||
|
||||
interpret ();
|
||||
|
||||
reset_memory ();
|
||||
|
||||
os_reset_screen ();
|
||||
|
||||
return 0;
|
||||
|
||||
}/* main */
|
|
@ -1,261 +0,0 @@
|
|||
/* math.c - Arithmetic, compare and logical opcodes
|
||||
* Copyright (c) 1995-1997 Stefan Jokisch
|
||||
*
|
||||
* This file is part of Frotz.
|
||||
*
|
||||
* Frotz 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.
|
||||
*
|
||||
* Frotz 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
|
||||
*/
|
||||
|
||||
#include "frotz.h"
|
||||
|
||||
/*
|
||||
* z_add, 16bit addition.
|
||||
*
|
||||
* zargs[0] = first value
|
||||
* zargs[1] = second value
|
||||
*
|
||||
*/
|
||||
|
||||
void z_add (void)
|
||||
{
|
||||
|
||||
store ((zword) ((short) zargs[0] + (short) zargs[1]));
|
||||
|
||||
}/* z_add */
|
||||
|
||||
/*
|
||||
* z_and, bitwise AND operation.
|
||||
*
|
||||
* zargs[0] = first value
|
||||
* zargs[1] = second value
|
||||
*
|
||||
*/
|
||||
|
||||
void z_and (void)
|
||||
{
|
||||
|
||||
store ((zword) (zargs[0] & zargs[1]));
|
||||
|
||||
}/* z_and */
|
||||
|
||||
/*
|
||||
* z_art_shift, arithmetic SHIFT operation.
|
||||
*
|
||||
* zargs[0] = value
|
||||
* zargs[1] = #positions to shift left (positive) or right
|
||||
*
|
||||
*/
|
||||
|
||||
void z_art_shift (void)
|
||||
{
|
||||
|
||||
if ((short) zargs[1] > 0)
|
||||
store ((zword) ((short) zargs[0] << (short) zargs[1]));
|
||||
else
|
||||
store ((zword) ((short) zargs[0] >> - (short) zargs[1]));
|
||||
|
||||
}/* z_art_shift */
|
||||
|
||||
/*
|
||||
* z_div, signed 16bit division.
|
||||
*
|
||||
* zargs[0] = first value
|
||||
* zargs[1] = second value
|
||||
*
|
||||
*/
|
||||
|
||||
void z_div (void)
|
||||
{
|
||||
|
||||
if (zargs[1] == 0)
|
||||
runtime_error (ERR_DIV_ZERO);
|
||||
|
||||
store ((zword) ((short) zargs[0] / (short) zargs[1]));
|
||||
|
||||
}/* z_div */
|
||||
|
||||
/*
|
||||
* z_je, branch if the first value equals any of the following.
|
||||
*
|
||||
* zargs[0] = first value
|
||||
* zargs[1] = second value (optional)
|
||||
* ...
|
||||
* zargs[3] = fourth value (optional)
|
||||
*
|
||||
*/
|
||||
|
||||
void z_je (void)
|
||||
{
|
||||
|
||||
branch (
|
||||
zargc > 1 && (zargs[0] == zargs[1] || (
|
||||
zargc > 2 && (zargs[0] == zargs[2] || (
|
||||
zargc > 3 && (zargs[0] == zargs[3]))))));
|
||||
|
||||
}/* z_je */
|
||||
|
||||
/*
|
||||
* z_jg, branch if the first value is greater than the second.
|
||||
*
|
||||
* zargs[0] = first value
|
||||
* zargs[1] = second value
|
||||
*
|
||||
*/
|
||||
|
||||
void z_jg (void)
|
||||
{
|
||||
|
||||
branch ((short) zargs[0] > (short) zargs[1]);
|
||||
|
||||
}/* z_jg */
|
||||
|
||||
/*
|
||||
* z_jl, branch if the first value is less than the second.
|
||||
*
|
||||
* zargs[0] = first value
|
||||
* zargs[1] = second value
|
||||
*
|
||||
*/
|
||||
|
||||
void z_jl (void)
|
||||
{
|
||||
|
||||
branch ((short) zargs[0] < (short) zargs[1]);
|
||||
|
||||
}/* z_jl */
|
||||
|
||||
/*
|
||||
* z_jz, branch if value is zero.
|
||||
*
|
||||
* zargs[0] = value
|
||||
*
|
||||
*/
|
||||
|
||||
void z_jz (void)
|
||||
{
|
||||
|
||||
branch ((short) zargs[0] == 0);
|
||||
|
||||
}/* z_jz */
|
||||
|
||||
/*
|
||||
* z_log_shift, logical SHIFT operation.
|
||||
*
|
||||
* zargs[0] = value
|
||||
* zargs[1] = #positions to shift left (positive) or right (negative)
|
||||
*
|
||||
*/
|
||||
|
||||
void z_log_shift (void)
|
||||
{
|
||||
|
||||
if ((short) zargs[1] > 0)
|
||||
store ((zword) (zargs[0] << (short) zargs[1]));
|
||||
else
|
||||
store ((zword) (zargs[0] >> - (short) zargs[1]));
|
||||
|
||||
}/* z_log_shift */
|
||||
|
||||
/*
|
||||
* z_mod, remainder after signed 16bit division.
|
||||
*
|
||||
* zargs[0] = first value
|
||||
* zargs[1] = second value
|
||||
*
|
||||
*/
|
||||
|
||||
void z_mod (void)
|
||||
{
|
||||
|
||||
if (zargs[1] == 0)
|
||||
runtime_error (ERR_DIV_ZERO);
|
||||
|
||||
store ((zword) ((short) zargs[0] % (short) zargs[1]));
|
||||
|
||||
}/* z_mod */
|
||||
|
||||
/*
|
||||
* z_mul, 16bit multiplication.
|
||||
*
|
||||
* zargs[0] = first value
|
||||
* zargs[1] = second value
|
||||
*
|
||||
*/
|
||||
|
||||
void z_mul (void)
|
||||
{
|
||||
|
||||
store ((zword) ((short) zargs[0] * (short) zargs[1]));
|
||||
|
||||
}/* z_mul */
|
||||
|
||||
/*
|
||||
* z_not, bitwise NOT operation.
|
||||
*
|
||||
* zargs[0] = value
|
||||
*
|
||||
*/
|
||||
|
||||
void z_not (void)
|
||||
{
|
||||
|
||||
store ((zword) ~zargs[0]);
|
||||
|
||||
}/* z_not */
|
||||
|
||||
/*
|
||||
* z_or, bitwise OR operation.
|
||||
*
|
||||
* zargs[0] = first value
|
||||
* zargs[1] = second value
|
||||
*
|
||||
*/
|
||||
|
||||
void z_or (void)
|
||||
{
|
||||
|
||||
store ((zword) (zargs[0] | zargs[1]));
|
||||
|
||||
}/* z_or */
|
||||
|
||||
/*
|
||||
* z_sub, 16bit substraction.
|
||||
*
|
||||
* zargs[0] = first value
|
||||
* zargs[1] = second value
|
||||
*
|
||||
*/
|
||||
|
||||
void z_sub (void)
|
||||
{
|
||||
|
||||
store ((zword) ((short) zargs[0] - (short) zargs[1]));
|
||||
|
||||
}/* z_sub */
|
||||
|
||||
/*
|
||||
* z_test, branch if all the flags of a bit mask are set in a value.
|
||||
*
|
||||
* zargs[0] = value to be examined
|
||||
* zargs[1] = bit mask
|
||||
*
|
||||
*/
|
||||
|
||||
void z_test (void)
|
||||
{
|
||||
|
||||
branch ((zargs[0] & zargs[1]) == zargs[1]);
|
||||
|
||||
}/* z_test */
|
File diff suppressed because it is too large
Load diff
|
@ -1,798 +0,0 @@
|
|||
/* process.c - Interpreter loop and program control
|
||||
* Copyright (c) 1995-1997 Stefan Jokisch
|
||||
*
|
||||
* This file is part of Frotz.
|
||||
*
|
||||
* Frotz 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.
|
||||
*
|
||||
* Frotz 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
|
||||
*/
|
||||
|
||||
#include "frotz.h"
|
||||
|
||||
#ifdef DJGPP
|
||||
#include "djfrotz.h"
|
||||
#endif
|
||||
|
||||
|
||||
zword zargs[8];
|
||||
int zargc;
|
||||
|
||||
static int finished = 0;
|
||||
|
||||
static void __extended__ (void);
|
||||
static void __illegal__ (void);
|
||||
|
||||
void (*op0_opcodes[0x10]) (void) = {
|
||||
z_rtrue,
|
||||
z_rfalse,
|
||||
z_print,
|
||||
z_print_ret,
|
||||
z_nop,
|
||||
z_save,
|
||||
z_restore,
|
||||
z_restart,
|
||||
z_ret_popped,
|
||||
z_catch,
|
||||
z_quit,
|
||||
z_new_line,
|
||||
z_show_status,
|
||||
z_verify,
|
||||
__extended__,
|
||||
z_piracy
|
||||
};
|
||||
|
||||
void (*op1_opcodes[0x10]) (void) = {
|
||||
z_jz,
|
||||
z_get_sibling,
|
||||
z_get_child,
|
||||
z_get_parent,
|
||||
z_get_prop_len,
|
||||
z_inc,
|
||||
z_dec,
|
||||
z_print_addr,
|
||||
z_call_s,
|
||||
z_remove_obj,
|
||||
z_print_obj,
|
||||
z_ret,
|
||||
z_jump,
|
||||
z_print_paddr,
|
||||
z_load,
|
||||
z_call_n
|
||||
};
|
||||
|
||||
void (*var_opcodes[0x40]) (void) = {
|
||||
__illegal__,
|
||||
z_je,
|
||||
z_jl,
|
||||
z_jg,
|
||||
z_dec_chk,
|
||||
z_inc_chk,
|
||||
z_jin,
|
||||
z_test,
|
||||
z_or,
|
||||
z_and,
|
||||
z_test_attr,
|
||||
z_set_attr,
|
||||
z_clear_attr,
|
||||
z_store,
|
||||
z_insert_obj,
|
||||
z_loadw,
|
||||
z_loadb,
|
||||
z_get_prop,
|
||||
z_get_prop_addr,
|
||||
z_get_next_prop,
|
||||
z_add,
|
||||
z_sub,
|
||||
z_mul,
|
||||
z_div,
|
||||
z_mod,
|
||||
z_call_s,
|
||||
z_call_n,
|
||||
z_set_colour,
|
||||
z_throw,
|
||||
__illegal__,
|
||||
__illegal__,
|
||||
__illegal__,
|
||||
z_call_s,
|
||||
z_storew,
|
||||
z_storeb,
|
||||
z_put_prop,
|
||||
z_read,
|
||||
z_print_char,
|
||||
z_print_num,
|
||||
z_random,
|
||||
z_push,
|
||||
z_pull,
|
||||
z_split_window,
|
||||
z_set_window,
|
||||
z_call_s,
|
||||
z_erase_window,
|
||||
z_erase_line,
|
||||
z_set_cursor,
|
||||
z_get_cursor,
|
||||
z_set_text_style,
|
||||
z_buffer_mode,
|
||||
z_output_stream,
|
||||
z_input_stream,
|
||||
z_sound_effect,
|
||||
z_read_char,
|
||||
z_scan_table,
|
||||
z_not,
|
||||
z_call_n,
|
||||
z_call_n,
|
||||
z_tokenise,
|
||||
z_encode_text,
|
||||
z_copy_table,
|
||||
z_print_table,
|
||||
z_check_arg_count
|
||||
};
|
||||
|
||||
void (*ext_opcodes[0x1d]) (void) = {
|
||||
z_save,
|
||||
z_restore,
|
||||
z_log_shift,
|
||||
z_art_shift,
|
||||
z_set_font,
|
||||
z_draw_picture,
|
||||
z_picture_data,
|
||||
z_erase_picture,
|
||||
z_set_margins,
|
||||
z_save_undo,
|
||||
z_restore_undo,
|
||||
z_print_unicode,
|
||||
z_check_unicode,
|
||||
__illegal__,
|
||||
__illegal__,
|
||||
__illegal__,
|
||||
z_move_window,
|
||||
z_window_size,
|
||||
z_window_style,
|
||||
z_get_wind_prop,
|
||||
z_scroll_window,
|
||||
z_pop_stack,
|
||||
z_read_mouse,
|
||||
z_mouse_window,
|
||||
z_push_stack,
|
||||
z_put_wind_prop,
|
||||
z_print_form,
|
||||
z_make_menu,
|
||||
z_picture_table
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* init_process
|
||||
*
|
||||
* Initialize process variables.
|
||||
*
|
||||
*/
|
||||
|
||||
void init_process (void)
|
||||
{
|
||||
finished = 0;
|
||||
} /* init_process */
|
||||
|
||||
|
||||
/*
|
||||
* load_operand
|
||||
*
|
||||
* Load an operand, either a variable or a constant.
|
||||
*
|
||||
*/
|
||||
|
||||
static void load_operand (zbyte type)
|
||||
{
|
||||
zword value;
|
||||
|
||||
if (type & 2) { /* variable */
|
||||
|
||||
zbyte variable;
|
||||
|
||||
CODE_BYTE (variable)
|
||||
|
||||
if (variable == 0)
|
||||
value = *sp++;
|
||||
else if (variable < 16)
|
||||
value = *(fp - variable);
|
||||
else {
|
||||
zword addr = h_globals + 2 * (variable - 16);
|
||||
LOW_WORD (addr, value)
|
||||
}
|
||||
|
||||
} else if (type & 1) { /* small constant */
|
||||
|
||||
zbyte bvalue;
|
||||
|
||||
CODE_BYTE (bvalue)
|
||||
value = bvalue;
|
||||
|
||||
} else CODE_WORD (value) /* large constant */
|
||||
|
||||
zargs[zargc++] = value;
|
||||
|
||||
}/* load_operand */
|
||||
|
||||
/*
|
||||
* load_all_operands
|
||||
*
|
||||
* Given the operand specifier byte, load all (up to four) operands
|
||||
* for a VAR or EXT opcode.
|
||||
*
|
||||
*/
|
||||
|
||||
static void load_all_operands (zbyte specifier)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 6; i >= 0; i -= 2) {
|
||||
|
||||
zbyte type = (specifier >> i) & 0x03;
|
||||
|
||||
if (type == 3)
|
||||
break;
|
||||
|
||||
load_operand (type);
|
||||
|
||||
}
|
||||
|
||||
}/* load_all_operands */
|
||||
|
||||
/*
|
||||
* interpret
|
||||
*
|
||||
* Z-code interpreter main loop
|
||||
*
|
||||
*/
|
||||
|
||||
void interpret (void)
|
||||
{
|
||||
|
||||
do {
|
||||
|
||||
zbyte opcode;
|
||||
|
||||
CODE_BYTE (opcode)
|
||||
|
||||
zargc = 0;
|
||||
|
||||
if (opcode < 0x80) { /* 2OP opcodes */
|
||||
|
||||
load_operand ((zbyte) (opcode & 0x40) ? 2 : 1);
|
||||
load_operand ((zbyte) (opcode & 0x20) ? 2 : 1);
|
||||
|
||||
var_opcodes[opcode & 0x1f] ();
|
||||
|
||||
} else if (opcode < 0xb0) { /* 1OP opcodes */
|
||||
|
||||
load_operand ((zbyte) (opcode >> 4));
|
||||
|
||||
op1_opcodes[opcode & 0x0f] ();
|
||||
|
||||
} else if (opcode < 0xc0) { /* 0OP opcodes */
|
||||
|
||||
op0_opcodes[opcode - 0xb0] ();
|
||||
|
||||
} else { /* VAR opcodes */
|
||||
|
||||
zbyte specifier1;
|
||||
zbyte specifier2;
|
||||
|
||||
if (opcode == 0xec || opcode == 0xfa) { /* opcodes 0xec */
|
||||
CODE_BYTE (specifier1) /* and 0xfa are */
|
||||
CODE_BYTE (specifier2) /* call opcodes */
|
||||
load_all_operands (specifier1); /* with up to 8 */
|
||||
load_all_operands (specifier2); /* arguments */
|
||||
} else {
|
||||
CODE_BYTE (specifier1)
|
||||
load_all_operands (specifier1);
|
||||
}
|
||||
|
||||
var_opcodes[opcode - 0xc0] ();
|
||||
|
||||
}
|
||||
|
||||
#if defined(DJGPP) && defined(SOUND_SUPPORT)
|
||||
if (end_of_sound_flag)
|
||||
end_of_sound ();
|
||||
#endif
|
||||
|
||||
} while (finished == 0);
|
||||
|
||||
finished--;
|
||||
|
||||
}/* interpret */
|
||||
|
||||
/*
|
||||
* call
|
||||
*
|
||||
* Call a subroutine. Save PC and FP then load new PC and initialise
|
||||
* new stack frame. Note that the caller may legally provide less or
|
||||
* more arguments than the function actually has. The call type "ct"
|
||||
* can be 0 (z_call_s), 1 (z_call_n) or 2 (direct call).
|
||||
*
|
||||
*/
|
||||
|
||||
void call (zword routine, int argc, zword *args, int ct)
|
||||
{
|
||||
long pc;
|
||||
zword value;
|
||||
zbyte count;
|
||||
int i;
|
||||
|
||||
if (sp - stack < 4)
|
||||
runtime_error (ERR_STK_OVF);
|
||||
|
||||
GET_PC (pc)
|
||||
|
||||
*--sp = (zword) (pc >> 9);
|
||||
*--sp = (zword) (pc & 0x1ff);
|
||||
*--sp = (zword) (fp - stack - 1);
|
||||
*--sp = (zword) (argc | (ct << (f_setup.save_quetzal ? 12 : 8)));
|
||||
|
||||
fp = sp;
|
||||
frame_count++;
|
||||
|
||||
/* Calculate byte address of routine */
|
||||
|
||||
if (h_version <= V3)
|
||||
pc = (long) routine << 1;
|
||||
else if (h_version <= V5)
|
||||
pc = (long) routine << 2;
|
||||
else if (h_version <= V7)
|
||||
pc = ((long) routine << 2) + ((long) h_functions_offset << 3);
|
||||
else /* h_version == V8 */
|
||||
pc = (long) routine << 3;
|
||||
|
||||
if (pc >= story_size)
|
||||
runtime_error (ERR_ILL_CALL_ADDR);
|
||||
|
||||
SET_PC (pc)
|
||||
|
||||
/* Initialise local variables */
|
||||
|
||||
CODE_BYTE (count)
|
||||
|
||||
if (count > 15)
|
||||
runtime_error (ERR_CALL_NON_RTN);
|
||||
if (sp - stack < count)
|
||||
runtime_error (ERR_STK_OVF);
|
||||
|
||||
if (f_setup.save_quetzal)
|
||||
fp[0] |= (zword) count << 8; /* Save local var count for Quetzal. */
|
||||
|
||||
value = 0;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
|
||||
if (h_version <= V4) /* V1 to V4 games provide default */
|
||||
CODE_WORD (value) /* values for all local variables */
|
||||
|
||||
*--sp = (zword) ((argc-- > 0) ? args[i] : value);
|
||||
|
||||
}
|
||||
|
||||
/* Start main loop for direct calls */
|
||||
|
||||
if (ct == 2)
|
||||
interpret ();
|
||||
|
||||
}/* call */
|
||||
|
||||
/*
|
||||
* ret
|
||||
*
|
||||
* Return from the current subroutine and restore the previous stack
|
||||
* frame. The result may be stored (0), thrown away (1) or pushed on
|
||||
* the stack (2). In the latter case a direct call has been finished
|
||||
* and we must exit the interpreter loop.
|
||||
*
|
||||
*/
|
||||
|
||||
void ret (zword value)
|
||||
{
|
||||
long pc;
|
||||
int ct;
|
||||
|
||||
if (sp > fp)
|
||||
runtime_error (ERR_STK_UNDF);
|
||||
|
||||
sp = fp;
|
||||
|
||||
ct = *sp++ >> (f_setup.save_quetzal ? 12 : 8);
|
||||
frame_count--;
|
||||
fp = stack + 1 + *sp++;
|
||||
pc = *sp++;
|
||||
pc = ((long) *sp++ << 9) | pc;
|
||||
|
||||
SET_PC (pc)
|
||||
|
||||
/* Handle resulting value */
|
||||
|
||||
if (ct == 0)
|
||||
store (value);
|
||||
if (ct == 2)
|
||||
*--sp = value;
|
||||
|
||||
/* Stop main loop for direct calls */
|
||||
|
||||
if (ct == 2)
|
||||
finished++;
|
||||
|
||||
}/* ret */
|
||||
|
||||
/*
|
||||
* branch
|
||||
*
|
||||
* Take a jump after an instruction based on the flag, either true or
|
||||
* false. The branch can be short or long; it is encoded in one or two
|
||||
* bytes respectively. When bit 7 of the first byte is set, the jump
|
||||
* takes place if the flag is true; otherwise it is taken if the flag
|
||||
* is false. When bit 6 of the first byte is set, the branch is short;
|
||||
* otherwise it is long. The offset occupies the bottom 6 bits of the
|
||||
* first byte plus all the bits in the second byte for long branches.
|
||||
* Uniquely, an offset of 0 means return false, and an offset of 1 is
|
||||
* return true.
|
||||
*
|
||||
*/
|
||||
|
||||
void branch (bool flag)
|
||||
{
|
||||
long pc;
|
||||
zword offset;
|
||||
zbyte specifier;
|
||||
zbyte off1;
|
||||
zbyte off2;
|
||||
|
||||
CODE_BYTE (specifier)
|
||||
|
||||
off1 = specifier & 0x3f;
|
||||
|
||||
if (!flag)
|
||||
specifier ^= 0x80;
|
||||
|
||||
if (!(specifier & 0x40)) { /* it's a long branch */
|
||||
|
||||
if (off1 & 0x20) /* propagate sign bit */
|
||||
off1 |= 0xc0;
|
||||
|
||||
CODE_BYTE (off2)
|
||||
|
||||
offset = (off1 << 8) | off2;
|
||||
|
||||
} else offset = off1; /* it's a short branch */
|
||||
|
||||
if (specifier & 0x80) {
|
||||
|
||||
if (offset > 1) { /* normal branch */
|
||||
|
||||
GET_PC (pc)
|
||||
pc += (short) offset - 2;
|
||||
SET_PC (pc)
|
||||
|
||||
} else ret (offset); /* special case, return 0 or 1 */
|
||||
}
|
||||
|
||||
}/* branch */
|
||||
|
||||
/*
|
||||
* store
|
||||
*
|
||||
* Store an operand, either as a variable or pushed on the stack.
|
||||
*
|
||||
*/
|
||||
|
||||
void store (zword value)
|
||||
{
|
||||
zbyte variable;
|
||||
|
||||
CODE_BYTE (variable)
|
||||
|
||||
if (variable == 0)
|
||||
*--sp = value;
|
||||
else if (variable < 16)
|
||||
*(fp - variable) = value;
|
||||
else {
|
||||
zword addr = h_globals + 2 * (variable - 16);
|
||||
SET_WORD (addr, value)
|
||||
}
|
||||
|
||||
}/* store */
|
||||
|
||||
/*
|
||||
* direct_call
|
||||
*
|
||||
* Call the interpreter loop directly. This is necessary when
|
||||
*
|
||||
* - a sound effect has been finished
|
||||
* - a read instruction has timed out
|
||||
* - a newline countdown has hit zero
|
||||
*
|
||||
* The interpreter returns the result value on the stack.
|
||||
*
|
||||
*/
|
||||
|
||||
int direct_call (zword addr)
|
||||
{
|
||||
zword saved_zargs[8];
|
||||
int saved_zargc;
|
||||
int i;
|
||||
|
||||
/* Calls to address 0 return false */
|
||||
|
||||
if (addr == 0)
|
||||
return 0;
|
||||
|
||||
/* Save operands and operand count */
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
saved_zargs[i] = zargs[i];
|
||||
|
||||
saved_zargc = zargc;
|
||||
|
||||
/* Call routine directly */
|
||||
|
||||
call (addr, 0, 0, 2);
|
||||
|
||||
/* Restore operands and operand count */
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
zargs[i] = saved_zargs[i];
|
||||
|
||||
zargc = saved_zargc;
|
||||
|
||||
/* Resulting value lies on top of the stack */
|
||||
|
||||
return (short) *sp++;
|
||||
|
||||
}/* direct_call */
|
||||
|
||||
/*
|
||||
* __extended__
|
||||
*
|
||||
* Load and execute an extended opcode.
|
||||
*
|
||||
*/
|
||||
|
||||
static void __extended__ (void)
|
||||
{
|
||||
zbyte opcode;
|
||||
zbyte specifier;
|
||||
|
||||
CODE_BYTE (opcode)
|
||||
CODE_BYTE (specifier)
|
||||
|
||||
load_all_operands (specifier);
|
||||
|
||||
if (opcode < 0x1d) /* extended opcodes from 0x1d on */
|
||||
ext_opcodes[opcode] (); /* are reserved for future spec' */
|
||||
|
||||
}/* __extended__ */
|
||||
|
||||
/*
|
||||
* __illegal__
|
||||
*
|
||||
* Exit game because an unknown opcode has been hit.
|
||||
*
|
||||
*/
|
||||
|
||||
static void __illegal__ (void)
|
||||
{
|
||||
|
||||
runtime_error (ERR_ILL_OPCODE);
|
||||
|
||||
}/* __illegal__ */
|
||||
|
||||
/*
|
||||
* z_catch, store the current stack frame for later use with z_throw.
|
||||
*
|
||||
* no zargs used
|
||||
*
|
||||
*/
|
||||
|
||||
void z_catch (void)
|
||||
{
|
||||
|
||||
store (f_setup.save_quetzal ? frame_count : (zword) (fp - stack));
|
||||
|
||||
}/* z_catch */
|
||||
|
||||
/*
|
||||
* z_throw, go back to the given stack frame and return the given value.
|
||||
*
|
||||
* zargs[0] = value to return
|
||||
* zargs[1] = stack frame
|
||||
*
|
||||
*/
|
||||
|
||||
void z_throw (void)
|
||||
{
|
||||
|
||||
if (f_setup.save_quetzal) {
|
||||
if (zargs[1] > frame_count)
|
||||
runtime_error (ERR_BAD_FRAME);
|
||||
|
||||
/* Unwind the stack a frame at a time. */
|
||||
for (; frame_count > zargs[1]; --frame_count)
|
||||
fp = stack + 1 + fp[1];
|
||||
} else {
|
||||
if (zargs[1] > STACK_SIZE)
|
||||
runtime_error (ERR_BAD_FRAME);
|
||||
|
||||
fp = stack + zargs[1];
|
||||
}
|
||||
|
||||
ret (zargs[0]);
|
||||
|
||||
}/* z_throw */
|
||||
|
||||
/*
|
||||
* z_call_n, call a subroutine and discard its result.
|
||||
*
|
||||
* zargs[0] = packed address of subroutine
|
||||
* zargs[1] = first argument (optional)
|
||||
* ...
|
||||
* zargs[7] = seventh argument (optional)
|
||||
*
|
||||
*/
|
||||
|
||||
void z_call_n (void)
|
||||
{
|
||||
|
||||
if (zargs[0] != 0)
|
||||
call (zargs[0], zargc - 1, zargs + 1, 1);
|
||||
|
||||
}/* z_call_n */
|
||||
|
||||
/*
|
||||
* z_call_s, call a subroutine and store its result.
|
||||
*
|
||||
* zargs[0] = packed address of subroutine
|
||||
* zargs[1] = first argument (optional)
|
||||
* ...
|
||||
* zargs[7] = seventh argument (optional)
|
||||
*
|
||||
*/
|
||||
|
||||
void z_call_s (void)
|
||||
{
|
||||
|
||||
if (zargs[0] != 0)
|
||||
call (zargs[0], zargc - 1, zargs + 1, 0);
|
||||
else
|
||||
store (0);
|
||||
|
||||
}/* z_call_s */
|
||||
|
||||
/*
|
||||
* z_check_arg_count, branch if subroutine was called with >= n arg's.
|
||||
*
|
||||
* zargs[0] = number of arguments
|
||||
*
|
||||
*/
|
||||
|
||||
void z_check_arg_count (void)
|
||||
{
|
||||
|
||||
if (fp == stack + STACK_SIZE)
|
||||
branch (zargs[0] == 0);
|
||||
else
|
||||
branch (zargs[0] <= (*fp & 0xff));
|
||||
|
||||
}/* z_check_arg_count */
|
||||
|
||||
/*
|
||||
* z_jump, jump unconditionally to the given address.
|
||||
*
|
||||
* zargs[0] = PC relative address
|
||||
*
|
||||
*/
|
||||
|
||||
void z_jump (void)
|
||||
{
|
||||
long pc;
|
||||
|
||||
GET_PC (pc)
|
||||
|
||||
pc += (short) zargs[0] - 2;
|
||||
|
||||
if (pc >= story_size)
|
||||
runtime_error (ERR_ILL_JUMP_ADDR);
|
||||
|
||||
SET_PC (pc)
|
||||
|
||||
}/* z_jump */
|
||||
|
||||
/*
|
||||
* z_nop, no operation.
|
||||
*
|
||||
* no zargs used
|
||||
*
|
||||
*/
|
||||
|
||||
void z_nop (void)
|
||||
{
|
||||
|
||||
/* Do nothing */
|
||||
|
||||
}/* z_nop */
|
||||
|
||||
/*
|
||||
* z_quit, stop game and exit interpreter.
|
||||
*
|
||||
* no zargs used
|
||||
*
|
||||
*/
|
||||
|
||||
void z_quit (void)
|
||||
{
|
||||
|
||||
finished = 9999;
|
||||
|
||||
}/* z_quit */
|
||||
|
||||
/*
|
||||
* z_ret, return from a subroutine with the given value.
|
||||
*
|
||||
* zargs[0] = value to return
|
||||
*
|
||||
*/
|
||||
|
||||
void z_ret (void)
|
||||
{
|
||||
|
||||
ret (zargs[0]);
|
||||
|
||||
}/* z_ret */
|
||||
|
||||
/*
|
||||
* z_ret_popped, return from a subroutine with a value popped off the stack.
|
||||
*
|
||||
* no zargs used
|
||||
*
|
||||
*/
|
||||
|
||||
void z_ret_popped (void)
|
||||
{
|
||||
|
||||
ret (*sp++);
|
||||
|
||||
}/* z_ret_popped */
|
||||
|
||||
/*
|
||||
* z_rfalse, return from a subroutine with false (0).
|
||||
*
|
||||
* no zargs used
|
||||
*
|
||||
*/
|
||||
|
||||
void z_rfalse (void)
|
||||
{
|
||||
|
||||
ret (0);
|
||||
|
||||
}/* z_rfalse */
|
||||
|
||||
/*
|
||||
* z_rtrue, return from a subroutine with true (1).
|
||||
*
|
||||
* no zargs used
|
||||
*
|
||||
*/
|
||||
|
||||
void z_rtrue (void)
|
||||
{
|
||||
|
||||
ret (1);
|
||||
|
||||
}/* z_rtrue */
|
|
@ -1,562 +0,0 @@
|
|||
/* quetzal.c - Saving and restoring of Quetzal files.
|
||||
* Written by Martin Frost <mdf@doc.ic.ac.uk>
|
||||
*
|
||||
* This file is part of Frotz.
|
||||
*
|
||||
* Frotz 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.
|
||||
*
|
||||
* Frotz 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
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "frotz.h"
|
||||
|
||||
#ifdef MSDOS_16BIT
|
||||
|
||||
#include <alloc.h>
|
||||
|
||||
#define malloc(size) farmalloc (size)
|
||||
#define realloc(size,p) farrealloc (size,p)
|
||||
#define free(size) farfree (size)
|
||||
#define memcpy(d,s,n) _fmemcpy (d,s,n)
|
||||
|
||||
#else
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef SEEK_SET
|
||||
#define SEEK_SET 0
|
||||
#define SEEK_CUR 1
|
||||
#define SEEK_END 2
|
||||
#endif
|
||||
|
||||
#define far
|
||||
|
||||
#endif
|
||||
|
||||
#define get_c fgetc
|
||||
#define put_c fputc
|
||||
|
||||
typedef unsigned long zlong;
|
||||
|
||||
/*
|
||||
* This is used only by save_quetzal. It probably should be allocated
|
||||
* dynamically rather than statically.
|
||||
*/
|
||||
|
||||
static zword frames[STACK_SIZE/4+1];
|
||||
|
||||
/*
|
||||
* ID types.
|
||||
*/
|
||||
|
||||
#define makeid(a,b,c,d) ((zlong) (((a)<<24) | ((b)<<16) | ((c)<<8) | (d)))
|
||||
|
||||
#define ID_FORM makeid ('F','O','R','M')
|
||||
#define ID_IFZS makeid ('I','F','Z','S')
|
||||
#define ID_IFhd makeid ('I','F','h','d')
|
||||
#define ID_UMem makeid ('U','M','e','m')
|
||||
#define ID_CMem makeid ('C','M','e','m')
|
||||
#define ID_Stks makeid ('S','t','k','s')
|
||||
#define ID_ANNO makeid ('A','N','N','O')
|
||||
|
||||
/*
|
||||
* Various parsing states within restoration.
|
||||
*/
|
||||
|
||||
#define GOT_HEADER 0x01
|
||||
#define GOT_STACK 0x02
|
||||
#define GOT_MEMORY 0x04
|
||||
#define GOT_NONE 0x00
|
||||
#define GOT_ALL 0x07
|
||||
#define GOT_ERROR 0x80
|
||||
|
||||
/*
|
||||
* Macros used to write the files.
|
||||
*/
|
||||
|
||||
#define write_byte(fp,b) (put_c (b, fp) != EOF)
|
||||
#define write_bytx(fp,b) write_byte (fp, (b) & 0xFF)
|
||||
#define write_word(fp,w) \
|
||||
(write_bytx (fp, (w) >> 8) && write_bytx (fp, (w)))
|
||||
#define write_long(fp,l) \
|
||||
(write_bytx (fp, (l) >> 24) && write_bytx (fp, (l) >> 16) && \
|
||||
write_bytx (fp, (l) >> 8) && write_bytx (fp, (l)))
|
||||
#define write_chnk(fp,id,len) \
|
||||
(write_long (fp, (id)) && write_long (fp, (len)))
|
||||
#define write_run(fp,run) \
|
||||
(write_byte (fp, 0) && write_byte (fp, (run)))
|
||||
|
||||
/* Read one word from file; return TRUE if OK. */
|
||||
static bool read_word (FILE *f, zword *result)
|
||||
{
|
||||
int a, b;
|
||||
|
||||
if ((a = get_c (f)) == EOF) return FALSE;
|
||||
if ((b = get_c (f)) == EOF) return FALSE;
|
||||
|
||||
*result = ((zword) a << 8) | (zword) b;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Read one long from file; return TRUE if OK. */
|
||||
static bool read_long (FILE *f, zlong *result)
|
||||
{
|
||||
int a, b, c, d;
|
||||
|
||||
if ((a = get_c (f)) == EOF) return FALSE;
|
||||
if ((b = get_c (f)) == EOF) return FALSE;
|
||||
if ((c = get_c (f)) == EOF) return FALSE;
|
||||
if ((d = get_c (f)) == EOF) return FALSE;
|
||||
|
||||
*result = ((zlong) a << 24) | ((zlong) b << 16) |
|
||||
((zlong) c << 8) | (zlong) d;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore a saved game using Quetzal format. Return 2 if OK, 0 if an error
|
||||
* occurred before any damage was done, -1 on a fatal error.
|
||||
*/
|
||||
|
||||
zword restore_quetzal (FILE *svf, FILE *stf)
|
||||
{
|
||||
zlong ifzslen, currlen, tmpl;
|
||||
zlong pc;
|
||||
zword i, tmpw;
|
||||
zword fatal = 0; /* Set to -1 when errors must be fatal. */
|
||||
zbyte skip, progress = GOT_NONE;
|
||||
int x, y;
|
||||
|
||||
/* Check it's really an `IFZS' file. */
|
||||
if (!read_long (svf, &tmpl)
|
||||
|| !read_long (svf, &ifzslen)
|
||||
|| !read_long (svf, &currlen)) return 0;
|
||||
if (tmpl != ID_FORM || currlen != ID_IFZS)
|
||||
{
|
||||
print_string ("This is not a saved game file!\n");
|
||||
return 0;
|
||||
}
|
||||
if ((ifzslen & 1) || ifzslen<4) /* Sanity checks. */ return 0;
|
||||
ifzslen -= 4;
|
||||
|
||||
/* Read each chunk and process it. */
|
||||
while (ifzslen > 0)
|
||||
{
|
||||
/* Read chunk header. */
|
||||
if (ifzslen < 8) /* Couldn't contain a chunk. */ return 0;
|
||||
if (!read_long (svf, &tmpl)
|
||||
|| !read_long (svf, &currlen)) return 0;
|
||||
ifzslen -= 8; /* Reduce remaining by size of header. */
|
||||
|
||||
/* Handle chunk body. */
|
||||
if (ifzslen < currlen) /* Chunk goes past EOF?! */ return 0;
|
||||
skip = currlen & 1;
|
||||
ifzslen -= currlen + (zlong) skip;
|
||||
|
||||
switch (tmpl)
|
||||
{
|
||||
/* `IFhd' header chunk; must be first in file. */
|
||||
case ID_IFhd:
|
||||
if (progress & GOT_HEADER)
|
||||
{
|
||||
print_string ("Save file has two IFZS chunks!\n");
|
||||
return fatal;
|
||||
}
|
||||
progress |= GOT_HEADER;
|
||||
if (currlen < 13
|
||||
|| !read_word (svf, &tmpw)) return fatal;
|
||||
if (tmpw != h_release)
|
||||
progress = GOT_ERROR;
|
||||
|
||||
for (i=H_SERIAL; i<H_SERIAL+6; ++i)
|
||||
{
|
||||
if ((x = get_c (svf)) == EOF) return fatal;
|
||||
if (x != zmp[i])
|
||||
progress = GOT_ERROR;
|
||||
}
|
||||
|
||||
if (!read_word (svf, &tmpw)) return fatal;
|
||||
if (tmpw != h_checksum)
|
||||
progress = GOT_ERROR;
|
||||
|
||||
if (progress & GOT_ERROR)
|
||||
{
|
||||
print_string ("File was not saved from this story!\n");
|
||||
return fatal;
|
||||
}
|
||||
if ((x = get_c (svf)) == EOF) return fatal;
|
||||
pc = (zlong) x << 16;
|
||||
if ((x = get_c (svf)) == EOF) return fatal;
|
||||
pc |= (zlong) x << 8;
|
||||
if ((x = get_c (svf)) == EOF) return fatal;
|
||||
pc |= (zlong) x;
|
||||
fatal = -1; /* Setting PC means errors must be fatal. */
|
||||
SET_PC (pc);
|
||||
|
||||
for (i=13; i<currlen; ++i)
|
||||
(void) get_c (svf); /* Skip rest of chunk. */
|
||||
break;
|
||||
/* `Stks' stacks chunk; restoring this is quite complex. ;) */
|
||||
case ID_Stks:
|
||||
if (progress & GOT_STACK)
|
||||
{
|
||||
print_string ("File contains two stack chunks!\n");
|
||||
break;
|
||||
}
|
||||
progress |= GOT_STACK;
|
||||
|
||||
fatal = -1; /* Setting SP means errors must be fatal. */
|
||||
sp = stack + STACK_SIZE;
|
||||
|
||||
/*
|
||||
* All versions other than V6 may use evaluation stack outside
|
||||
* any function context. As a result a faked function context
|
||||
* will be present in the file here. We skip this context, but
|
||||
* load the associated stack onto the stack proper...
|
||||
*/
|
||||
if (h_version != V6)
|
||||
{
|
||||
if (currlen < 8) return fatal;
|
||||
for (i=0; i<6; ++i)
|
||||
if (get_c (svf) != 0) return fatal;
|
||||
if (!read_word (svf, &tmpw)) return fatal;
|
||||
if (tmpw > STACK_SIZE)
|
||||
{
|
||||
print_string ("Save-file has too much stack (and I can't cope).\n");
|
||||
return fatal;
|
||||
}
|
||||
currlen -= 8;
|
||||
if (currlen < tmpw*2) return fatal;
|
||||
for (i=0; i<tmpw; ++i)
|
||||
if (!read_word (svf, --sp)) return fatal;
|
||||
currlen -= tmpw*2;
|
||||
}
|
||||
|
||||
/* We now proceed to load the main block of stack frames. */
|
||||
for (fp = stack+STACK_SIZE, frame_count = 0;
|
||||
currlen > 0;
|
||||
currlen -= 8, ++frame_count)
|
||||
{
|
||||
if (currlen < 8) return fatal;
|
||||
if (sp - stack < 4) /* No space for frame. */
|
||||
{
|
||||
print_string ("Save-file has too much stack (and I can't cope).\n");
|
||||
return fatal;
|
||||
}
|
||||
|
||||
/* Read PC, procedure flag and formal param count. */
|
||||
if (!read_long (svf, &tmpl)) return fatal;
|
||||
y = (int) (tmpl & 0x0F); /* Number of formals. */
|
||||
tmpw = y << 8;
|
||||
|
||||
/* Read result variable. */
|
||||
if ((x = get_c (svf)) == EOF) return fatal;
|
||||
|
||||
/* Check the procedure flag... */
|
||||
if (tmpl & 0x10)
|
||||
{
|
||||
tmpw |= 0x1000; /* It's a procedure. */
|
||||
tmpl >>= 8; /* Shift to get PC value. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Functions have type 0, so no need to or anything. */
|
||||
tmpl >>= 8; /* Shift to get PC value. */
|
||||
--tmpl; /* Point at result byte. */
|
||||
/* Sanity check on result variable... */
|
||||
if (zmp[tmpl] != (zbyte) x)
|
||||
{
|
||||
print_string ("Save-file has wrong variable number on stack (possibly wrong game version?)\n");
|
||||
return fatal;
|
||||
}
|
||||
}
|
||||
*--sp = (zword) (tmpl >> 9); /* High part of PC */
|
||||
*--sp = (zword) (tmpl & 0x1FF); /* Low part of PC */
|
||||
*--sp = (zword) (fp - stack - 1); /* FP */
|
||||
|
||||
/* Read and process argument mask. */
|
||||
if ((x = get_c (svf)) == EOF) return fatal;
|
||||
++x; /* Should now be a power of 2 */
|
||||
for (i=0; i<8; ++i)
|
||||
if (x & (1<<i))
|
||||
break;
|
||||
if (x ^ (1<<i)) /* Not a power of 2 */
|
||||
{
|
||||
print_string ("Save-file uses incomplete argument lists (which I can't handle)\n");
|
||||
return fatal;
|
||||
}
|
||||
*--sp = tmpw | i;
|
||||
fp = sp; /* FP for next frame. */
|
||||
|
||||
/* Read amount of eval stack used. */
|
||||
if (!read_word (svf, &tmpw)) return fatal;
|
||||
|
||||
tmpw += y; /* Amount of stack + number of locals. */
|
||||
if (sp - stack <= tmpw)
|
||||
{
|
||||
print_string ("Save-file has too much stack (and I can't cope).\n");
|
||||
return fatal;
|
||||
}
|
||||
if (currlen < tmpw*2) return fatal;
|
||||
for (i=0; i<tmpw; ++i)
|
||||
if (!read_word (svf, --sp)) return fatal;
|
||||
currlen -= tmpw*2;
|
||||
}
|
||||
/* End of `Stks' processing... */
|
||||
break;
|
||||
/* Any more special chunk types must go in HERE or ABOVE. */
|
||||
/* `CMem' compressed memory chunk; uncompress it. */
|
||||
case ID_CMem:
|
||||
if (!(progress & GOT_MEMORY)) /* Don't complain if two. */
|
||||
{
|
||||
(void) fseek (stf, 0, SEEK_SET);
|
||||
i=0; /* Bytes written to data area. */
|
||||
for (; currlen > 0; --currlen)
|
||||
{
|
||||
if ((x = get_c (svf)) == EOF) return fatal;
|
||||
if (x == 0) /* Start run. */
|
||||
{
|
||||
/* Check for bogus run. */
|
||||
if (currlen < 2)
|
||||
{
|
||||
print_string ("File contains bogus `CMem' chunk.\n");
|
||||
for (; currlen > 0; --currlen)
|
||||
(void) get_c (svf); /* Skip rest. */
|
||||
currlen = 1;
|
||||
i = 0xFFFF;
|
||||
break; /* Keep going; may be a `UMem' too. */
|
||||
}
|
||||
/* Copy story file to memory during the run. */
|
||||
--currlen;
|
||||
if ((x = get_c (svf)) == EOF) return fatal;
|
||||
for (; x >= 0 && i<h_dynamic_size; --x, ++i)
|
||||
if ((y = get_c (stf)) == EOF) return fatal;
|
||||
else
|
||||
zmp[i] = (zbyte) y;
|
||||
}
|
||||
else /* Not a run. */
|
||||
{
|
||||
if ((y = get_c (stf)) == EOF) return fatal;
|
||||
zmp[i] = (zbyte) (x ^ y);
|
||||
++i;
|
||||
}
|
||||
/* Make sure we don't load too much. */
|
||||
if (i > h_dynamic_size)
|
||||
{
|
||||
print_string ("warning: `CMem' chunk too long!\n");
|
||||
for (; currlen > 1; --currlen)
|
||||
(void) get_c (svf); /* Skip rest. */
|
||||
break; /* Keep going; there may be a `UMem' too. */
|
||||
}
|
||||
}
|
||||
/* If chunk is short, assume a run. */
|
||||
for (; i<h_dynamic_size; ++i)
|
||||
if ((y = get_c (stf)) == EOF) return fatal;
|
||||
else
|
||||
zmp[i] = (zbyte) y;
|
||||
if (currlen == 0)
|
||||
progress |= GOT_MEMORY; /* Only if succeeded. */
|
||||
break;
|
||||
}
|
||||
/* Fall right thru (to default) if already GOT_MEMORY */
|
||||
/* `UMem' uncompressed memory chunk; load it. */
|
||||
case ID_UMem:
|
||||
if (!(progress & GOT_MEMORY)) /* Don't complain if two. */
|
||||
{
|
||||
/* Must be exactly the right size. */
|
||||
if (currlen == h_dynamic_size)
|
||||
{
|
||||
if (fread (zmp, currlen, 1, svf) == 1)
|
||||
{
|
||||
progress |= GOT_MEMORY; /* Only on success. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
print_string ("`UMem' chunk wrong size!\n");
|
||||
/* Fall into default action (skip chunk) on errors. */
|
||||
}
|
||||
/* Fall thru (to default) if already GOT_MEMORY */
|
||||
/* Unrecognised chunk type; skip it. */
|
||||
default:
|
||||
(void) fseek (svf, currlen, SEEK_CUR); /* Skip chunk. */
|
||||
break;
|
||||
}
|
||||
if (skip)
|
||||
(void) get_c (svf); /* Skip pad byte. */
|
||||
}
|
||||
|
||||
/*
|
||||
* We've reached the end of the file. For the restoration to have been a
|
||||
* success, we must have had one of each of the required chunks.
|
||||
*/
|
||||
if (!(progress & GOT_HEADER))
|
||||
print_string ("error: no valid header (`IFhd') chunk in file.\n");
|
||||
if (!(progress & GOT_STACK))
|
||||
print_string ("error: no valid stack (`Stks') chunk in file.\n");
|
||||
if (!(progress & GOT_MEMORY))
|
||||
print_string ("error: no valid memory (`CMem' or `UMem') chunk in file.\n");
|
||||
|
||||
return (progress == GOT_ALL ? 2 : fatal);
|
||||
}
|
||||
|
||||
/*
|
||||
* Save a game using Quetzal format. Return 1 if OK, 0 if failed.
|
||||
*/
|
||||
|
||||
zword save_quetzal (FILE *svf, FILE *stf)
|
||||
{
|
||||
zlong ifzslen = 0, cmemlen = 0, stkslen = 0;
|
||||
zlong pc;
|
||||
zword i, j, n;
|
||||
zword nvars, nargs, nstk, *p;
|
||||
zbyte var;
|
||||
long cmempos, stkspos;
|
||||
int c;
|
||||
|
||||
/* Write `IFZS' header. */
|
||||
if (!write_chnk (svf, ID_FORM, 0)) return 0;
|
||||
if (!write_long (svf, ID_IFZS)) return 0;
|
||||
|
||||
/* Write `IFhd' chunk. */
|
||||
GET_PC (pc);
|
||||
if (!write_chnk (svf, ID_IFhd, 13)) return 0;
|
||||
if (!write_word (svf, h_release)) return 0;
|
||||
for (i=H_SERIAL; i<H_SERIAL+6; ++i)
|
||||
if (!write_byte (svf, zmp[i])) return 0;
|
||||
if (!write_word (svf, h_checksum)) return 0;
|
||||
if (!write_long (svf, pc << 8)) /* Includes pad. */ return 0;
|
||||
|
||||
/* Write `CMem' chunk. */
|
||||
if ((cmempos = ftell (svf)) < 0) return 0;
|
||||
if (!write_chnk (svf, ID_CMem, 0)) return 0;
|
||||
(void) fseek (stf, 0, SEEK_SET);
|
||||
/* j holds current run length. */
|
||||
for (i=0, j=0, cmemlen=0; i < h_dynamic_size; ++i)
|
||||
{
|
||||
if ((c = get_c (stf)) == EOF) return 0;
|
||||
c ^= (int) zmp[i];
|
||||
if (c == 0)
|
||||
++j; /* It's a run of equal bytes. */
|
||||
else
|
||||
{
|
||||
/* Write out any run there may be. */
|
||||
if (j > 0)
|
||||
{
|
||||
for (; j > 0x100; j -= 0x100)
|
||||
{
|
||||
if (!write_run (svf, 0xFF)) return 0;
|
||||
cmemlen += 2;
|
||||
}
|
||||
if (!write_run (svf, j-1)) return 0;
|
||||
cmemlen += 2;
|
||||
j = 0;
|
||||
}
|
||||
/* Any runs are now written. Write this (nonzero) byte. */
|
||||
if (!write_byte (svf, (zbyte) c)) return 0;
|
||||
++cmemlen;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Reached end of dynamic memory. We ignore any unwritten run there may be
|
||||
* at this point.
|
||||
*/
|
||||
if (cmemlen & 1) /* Chunk length must be even. */
|
||||
if (!write_byte (svf, 0)) return 0;
|
||||
|
||||
/* Write `Stks' chunk. You are not expected to understand this. ;) */
|
||||
if ((stkspos = ftell (svf)) < 0) return 0;
|
||||
if (!write_chnk (svf, ID_Stks, 0)) return 0;
|
||||
|
||||
/*
|
||||
* We construct a list of frame indices, most recent first, in `frames'.
|
||||
* These indices are the offsets into the `stack' array of the word before
|
||||
* the first word pushed in each frame.
|
||||
*/
|
||||
frames[0] = sp - stack; /* The frame we'd get by doing a call now. */
|
||||
for (i = fp - stack + 4, n=0; i < STACK_SIZE+4; i = stack[i-3] + 5)
|
||||
frames[++n] = i;
|
||||
|
||||
/*
|
||||
* All versions other than V6 can use evaluation stack outside a function
|
||||
* context. We write a faked stack frame (most fields zero) to cater for
|
||||
* this.
|
||||
*/
|
||||
if (h_version != V6)
|
||||
{
|
||||
for (i=0; i<6; ++i)
|
||||
if (!write_byte (svf, 0)) return 0;
|
||||
nstk = STACK_SIZE - frames[n];
|
||||
if (!write_word (svf, nstk)) return 0;
|
||||
for (j=STACK_SIZE-1; j >= frames[n]; --j)
|
||||
if (!write_word (svf, stack[j])) return 0;
|
||||
stkslen = 8 + 2*nstk;
|
||||
}
|
||||
|
||||
/* Write out the rest of the stack frames. */
|
||||
for (i=n; i>0; --i)
|
||||
{
|
||||
p = stack + frames[i] - 4; /* Points to call frame. */
|
||||
nvars = (p[0] & 0x0F00) >> 8;
|
||||
nargs = p[0] & 0x00FF;
|
||||
nstk = frames[i] - frames[i-1] - nvars - 4;
|
||||
pc = ((zlong) p[3] << 9) | p[2];
|
||||
|
||||
switch (p[0] & 0xF000) /* Check type of call. */
|
||||
{
|
||||
case 0x0000: /* Function. */
|
||||
var = zmp[pc];
|
||||
pc = ((pc + 1) << 8) | nvars;
|
||||
break;
|
||||
case 0x1000: /* Procedure. */
|
||||
var = 0;
|
||||
pc = (pc << 8) | 0x10 | nvars; /* Set procedure flag. */
|
||||
break;
|
||||
/* case 0x2000: */
|
||||
default:
|
||||
runtime_error (ERR_SAVE_IN_INTER);
|
||||
return 0;
|
||||
}
|
||||
if (nargs != 0)
|
||||
nargs = (1 << nargs) - 1; /* Make args into bitmap. */
|
||||
|
||||
/* Write the main part of the frame... */
|
||||
if (!write_long (svf, pc)
|
||||
|| !write_byte (svf, var)
|
||||
|| !write_byte (svf, nargs)
|
||||
|| !write_word (svf, nstk)) return 0;
|
||||
|
||||
/* Write the variables and eval stack. */
|
||||
for (j=0, ++p; j<nvars+nstk; ++j, --p)
|
||||
if (!write_word (svf, *p)) return 0;
|
||||
|
||||
/* Calculate length written thus far. */
|
||||
stkslen += 8 + 2 * (nvars + nstk);
|
||||
}
|
||||
|
||||
/* Fill in variable chunk lengths. */
|
||||
ifzslen = 3*8 + 4 + 14 + cmemlen + stkslen;
|
||||
if (cmemlen & 1)
|
||||
++ifzslen;
|
||||
(void) fseek (svf, 4, SEEK_SET);
|
||||
if (!write_long (svf, ifzslen)) return 0;
|
||||
(void) fseek (svf, cmempos+4, SEEK_SET);
|
||||
if (!write_long (svf, cmemlen)) return 0;
|
||||
(void) fseek (svf, stkspos+4, SEEK_SET);
|
||||
if (!write_long (svf, stkslen)) return 0;
|
||||
|
||||
/* After all that, still nothing went wrong! */
|
||||
return 1;
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
/* random.c - Z-machine random number generator
|
||||
* Copyright (c) 1995-1997 Stefan Jokisch
|
||||
*
|
||||
* This file is part of Frotz.
|
||||
*
|
||||
* Frotz 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.
|
||||
*
|
||||
* Frotz 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
|
||||
*/
|
||||
|
||||
#include "frotz.h"
|
||||
|
||||
static long A = 1;
|
||||
|
||||
static int interval = 0;
|
||||
static int counter = 0;
|
||||
|
||||
/*
|
||||
* seed_random
|
||||
*
|
||||
* Set the seed value for the random number generator.
|
||||
*
|
||||
*/
|
||||
|
||||
void seed_random (int value)
|
||||
{
|
||||
|
||||
if (value == 0) { /* ask interface for seed value */
|
||||
A = os_random_seed ();
|
||||
interval = 0;
|
||||
} else if (value < 1000) { /* special seed value */
|
||||
counter = 0;
|
||||
interval = value;
|
||||
} else { /* standard seed value */
|
||||
A = value;
|
||||
interval = 0;
|
||||
}
|
||||
|
||||
}/* seed_random */
|
||||
|
||||
/*
|
||||
* z_random, store a random number or set the random number seed.
|
||||
*
|
||||
* zargs[0] = range (positive) or seed value (negative)
|
||||
*
|
||||
*/
|
||||
|
||||
void z_random ()
|
||||
{
|
||||
|
||||
if ((short) zargs[0] <= 0) { /* set random seed */
|
||||
|
||||
seed_random (- (short) zargs[0]);
|
||||
store (0);
|
||||
|
||||
} else { /* generate random number */
|
||||
|
||||
zword result;
|
||||
|
||||
if (interval != 0) { /* ...in special mode */
|
||||
result = counter++;
|
||||
if (counter == interval) counter = 0;
|
||||
} else { /* ...in standard mode */
|
||||
A = 0x015a4e35L * A + 1;
|
||||
result = (A >> 16) & 0x7fff;
|
||||
}
|
||||
|
||||
store ((zword) (result % zargs[0] + 1));
|
||||
|
||||
}
|
||||
|
||||
}/* z_random */
|
|
@ -1,172 +0,0 @@
|
|||
/* redirect.c - Output redirection to Z-machine memory
|
||||
* Copyright (c) 1995-1997 Stefan Jokisch
|
||||
*
|
||||
* This file is part of Frotz.
|
||||
*
|
||||
* Frotz 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.
|
||||
*
|
||||
* Frotz 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
|
||||
*/
|
||||
|
||||
#include "frotz.h"
|
||||
|
||||
#define MAX_NESTING 16
|
||||
|
||||
extern zword get_max_width (zword);
|
||||
|
||||
static int depth = -1;
|
||||
|
||||
static struct {
|
||||
zword xsize;
|
||||
zword table;
|
||||
zword width;
|
||||
zword total;
|
||||
} redirect[MAX_NESTING];
|
||||
|
||||
/*
|
||||
* memory_open
|
||||
*
|
||||
* Begin output redirection to the memory of the Z-machine.
|
||||
*
|
||||
*/
|
||||
|
||||
void memory_open (zword table, zword xsize, bool buffering)
|
||||
{
|
||||
|
||||
if (++depth < MAX_NESTING) {
|
||||
|
||||
if (!buffering)
|
||||
xsize = 0xffff;
|
||||
if (buffering && (short) xsize <= 0)
|
||||
xsize = get_max_width ((zword) (- (short) xsize));
|
||||
|
||||
storew (table, 0);
|
||||
|
||||
redirect[depth].table = table;
|
||||
redirect[depth].width = 0;
|
||||
redirect[depth].total = 0;
|
||||
redirect[depth].xsize = xsize;
|
||||
|
||||
ostream_memory = TRUE;
|
||||
|
||||
} else runtime_error (ERR_STR3_NESTING);
|
||||
|
||||
}/* memory_open */
|
||||
|
||||
/*
|
||||
* memory_new_line
|
||||
*
|
||||
* Redirect a newline to the memory of the Z-machine.
|
||||
*
|
||||
*/
|
||||
|
||||
void memory_new_line (void)
|
||||
{
|
||||
zword size;
|
||||
zword addr;
|
||||
|
||||
redirect[depth].total += redirect[depth].width;
|
||||
redirect[depth].width = 0;
|
||||
|
||||
addr = redirect[depth].table;
|
||||
|
||||
LOW_WORD (addr, size)
|
||||
addr += 2;
|
||||
|
||||
if (redirect[depth].xsize != 0xffff) {
|
||||
|
||||
redirect[depth].table = addr + size;
|
||||
size = 0;
|
||||
|
||||
} else storeb ((zword) (addr + (size++)), 13);
|
||||
|
||||
storew (redirect[depth].table, size);
|
||||
|
||||
}/* memory_new_line */
|
||||
|
||||
/*
|
||||
* memory_word
|
||||
*
|
||||
* Redirect a string of characters to the memory of the Z-machine.
|
||||
*
|
||||
*/
|
||||
|
||||
void memory_word (const zchar *s)
|
||||
{
|
||||
zword size;
|
||||
zword addr;
|
||||
zchar c;
|
||||
|
||||
if (h_version == V6) {
|
||||
|
||||
int width = os_string_width (s);
|
||||
|
||||
if (redirect[depth].xsize != 0xffff)
|
||||
|
||||
if (redirect[depth].width + width > redirect[depth].xsize) {
|
||||
|
||||
if (*s == ' ' || *s == ZC_INDENT || *s == ZC_GAP)
|
||||
width = os_string_width (++s);
|
||||
|
||||
memory_new_line ();
|
||||
|
||||
}
|
||||
|
||||
redirect[depth].width += width;
|
||||
|
||||
}
|
||||
|
||||
addr = redirect[depth].table;
|
||||
|
||||
LOW_WORD (addr, size)
|
||||
addr += 2;
|
||||
|
||||
while ((c = *s++) != 0)
|
||||
storeb ((zword) (addr + (size++)), translate_to_zscii (c));
|
||||
|
||||
storew (redirect[depth].table, size);
|
||||
|
||||
}/* memory_word */
|
||||
|
||||
/*
|
||||
* memory_close
|
||||
*
|
||||
* End of output redirection.
|
||||
*
|
||||
*/
|
||||
|
||||
void memory_close (void)
|
||||
{
|
||||
|
||||
if (depth >= 0) {
|
||||
|
||||
if (redirect[depth].xsize != 0xffff)
|
||||
memory_new_line ();
|
||||
|
||||
if (h_version == V6) {
|
||||
|
||||
h_line_width = (redirect[depth].xsize != 0xffff) ?
|
||||
redirect[depth].total : redirect[depth].width;
|
||||
|
||||
SET_WORD (H_LINE_WIDTH, h_line_width)
|
||||
|
||||
}
|
||||
|
||||
if (depth == 0)
|
||||
ostream_memory = FALSE;
|
||||
|
||||
depth--;
|
||||
|
||||
}
|
||||
|
||||
}/* memory_close */
|
File diff suppressed because it is too large
Load diff
|
@ -1,67 +0,0 @@
|
|||
/*
|
||||
* Various status thingies for the interpreter and interface.
|
||||
*
|
||||
*/
|
||||
|
||||
typedef struct frotz_setup_struct {
|
||||
int attribute_assignment; /* done */
|
||||
int attribute_testing; /* done */
|
||||
int context_lines; /* done */
|
||||
int object_locating; /* done */
|
||||
int object_movement; /* done */
|
||||
int left_margin; /* done */
|
||||
int right_margin; /* done */
|
||||
int ignore_errors; /* done */
|
||||
int interpreter_number; /* Just dumb frotz now */
|
||||
int piracy; /* done */
|
||||
int undo_slots; /* done */
|
||||
int expand_abbreviations; /* done */
|
||||
int script_cols; /* done */
|
||||
int save_quetzal; /* done */
|
||||
int sound; /* done */
|
||||
int err_report_mode; /* done */
|
||||
} f_setup_t;
|
||||
|
||||
extern f_setup_t f_setup;
|
||||
|
||||
|
||||
typedef struct zcode_header_struct {
|
||||
zbyte h_version;
|
||||
zbyte h_config;
|
||||
zword h_release;
|
||||
zword h_resident_size;
|
||||
zword h_start_pc;
|
||||
zword h_dictionary;
|
||||
zword h_objects;
|
||||
zword h_globals;
|
||||
zword h_dynamic_size;
|
||||
zword h_flags;
|
||||
zbyte h_serial[6];
|
||||
zword h_abbreviations;
|
||||
zword h_file_size;
|
||||
zword h_checksum;
|
||||
zbyte h_interpreter_number;
|
||||
zbyte h_interpreter_version;
|
||||
zbyte h_screen_rows;
|
||||
zbyte h_screen_cols;
|
||||
zword h_screen_width;
|
||||
zword h_screen_height;
|
||||
zbyte h_font_height;
|
||||
zbyte h_font_width;
|
||||
zword h_functions_offset;
|
||||
zword h_strings_offset;
|
||||
zbyte h_default_background;
|
||||
zbyte h_default_foreground;
|
||||
zword h_terminating_keys;
|
||||
zword h_line_width;
|
||||
zbyte h_standard_high;
|
||||
zbyte h_standard_low;
|
||||
zword h_alphabet;
|
||||
zword h_extension_table;
|
||||
zbyte h_user_name[8];
|
||||
|
||||
zword hx_table_size;
|
||||
zword hx_mouse_x;
|
||||
zword hx_mouse_y;
|
||||
zword hx_unicode_table;
|
||||
} z_header_t;
|
|
@ -1,204 +0,0 @@
|
|||
/* sound.c - Sound effect function
|
||||
* Copyright (c) 1995-1997 Stefan Jokisch
|
||||
*
|
||||
* This file is part of Frotz.
|
||||
*
|
||||
* Frotz 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.
|
||||
*
|
||||
* Frotz 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
|
||||
*/
|
||||
|
||||
#include "frotz.h"
|
||||
|
||||
#ifdef DJGPP
|
||||
#include "djfrotz.h"
|
||||
#endif
|
||||
|
||||
#define EFFECT_PREPARE 1
|
||||
#define EFFECT_PLAY 2
|
||||
#define EFFECT_STOP 3
|
||||
#define EFFECT_FINISH_WITH 4
|
||||
|
||||
extern int direct_call (zword);
|
||||
|
||||
static zword routine = 0;
|
||||
|
||||
static int next_sample = 0;
|
||||
static int next_volume = 0;
|
||||
|
||||
static bool locked = FALSE;
|
||||
static bool playing = FALSE;
|
||||
|
||||
/*
|
||||
* init_sound
|
||||
*
|
||||
* Initialize sound variables.
|
||||
*
|
||||
*/
|
||||
|
||||
void init_sound (void)
|
||||
{
|
||||
locked = FALSE;
|
||||
playing = FALSE;
|
||||
} /* init_sound */
|
||||
|
||||
|
||||
/*
|
||||
* start_sample
|
||||
*
|
||||
* Call the IO interface to play a sample.
|
||||
*
|
||||
*/
|
||||
|
||||
static void start_sample (int number, int volume, int repeats, zword eos)
|
||||
{
|
||||
|
||||
static zbyte lh_repeats[] = {
|
||||
0x00, 0x00, 0x00, 0x01, 0xff,
|
||||
0x00, 0x01, 0x01, 0x01, 0x01,
|
||||
0xff, 0x01, 0x01, 0xff, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
|
||||
if (story_id == LURKING_HORROR)
|
||||
repeats = lh_repeats[number];
|
||||
|
||||
os_start_sample (number, volume, repeats, eos);
|
||||
|
||||
routine = eos;
|
||||
playing = TRUE;
|
||||
|
||||
}/* start_sample */
|
||||
|
||||
/*
|
||||
* start_next_sample
|
||||
*
|
||||
* Play a sample that has been delayed until the previous sound effect has
|
||||
* finished. This is necessary for two samples in The Lurking Horror that
|
||||
* immediately follow other samples.
|
||||
*
|
||||
*/
|
||||
|
||||
static void start_next_sample (void)
|
||||
{
|
||||
|
||||
if (next_sample != 0)
|
||||
start_sample (next_sample, next_volume, 0, 0);
|
||||
|
||||
next_sample = 0;
|
||||
next_volume = 0;
|
||||
|
||||
}/* start_next_sample */
|
||||
|
||||
/*
|
||||
* end_of_sound
|
||||
*
|
||||
* Call the Z-code routine which was given as the last parameter of
|
||||
* a sound_effect call. This function may be called from a hardware
|
||||
* interrupt (which requires extremely careful programming).
|
||||
*
|
||||
*/
|
||||
|
||||
void end_of_sound (void)
|
||||
{
|
||||
|
||||
#if defined(DJGPP) && defined(SOUND_SUPPORT)
|
||||
end_of_sound_flag = 0;
|
||||
#endif
|
||||
|
||||
playing = FALSE;
|
||||
|
||||
if (!locked) {
|
||||
|
||||
if (story_id == LURKING_HORROR)
|
||||
start_next_sample ();
|
||||
|
||||
direct_call (routine);
|
||||
|
||||
}
|
||||
|
||||
}/* end_of_sound */
|
||||
|
||||
/*
|
||||
* z_sound_effect, load / play / stop / discard a sound effect.
|
||||
*
|
||||
* zargs[0] = number of bleep (1 or 2) or sample
|
||||
* zargs[1] = operation to perform (samples only)
|
||||
* zargs[2] = repeats and volume (play sample only)
|
||||
* zargs[3] = end-of-sound routine (play sample only, optional)
|
||||
*
|
||||
* Note: Volumes range from 1 to 8, volume 255 is the default volume.
|
||||
* Repeats are stored in the high byte, 255 is infinite loop.
|
||||
*
|
||||
*/
|
||||
|
||||
void z_sound_effect (void)
|
||||
{
|
||||
zword number = zargs[0];
|
||||
zword effect = zargs[1];
|
||||
zword volume = zargs[2];
|
||||
|
||||
/* By default play sound 1 at volume 8 */
|
||||
if (zargc < 1)
|
||||
number = 1;
|
||||
if (zargc < 2)
|
||||
effect = EFFECT_PLAY;
|
||||
if (zargc < 3)
|
||||
volume = 8;
|
||||
|
||||
if (number >= 3 || number == 0) {
|
||||
|
||||
locked = TRUE;
|
||||
|
||||
if (story_id == LURKING_HORROR && (number == 9 || number == 16)) {
|
||||
|
||||
if (effect == EFFECT_PLAY) {
|
||||
|
||||
next_sample = number;
|
||||
next_volume = volume;
|
||||
|
||||
locked = FALSE;
|
||||
|
||||
if (!playing)
|
||||
start_next_sample ();
|
||||
|
||||
} else locked = FALSE;
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
playing = FALSE;
|
||||
|
||||
switch (effect) {
|
||||
|
||||
case EFFECT_PREPARE:
|
||||
os_prepare_sample (number);
|
||||
break;
|
||||
case EFFECT_PLAY:
|
||||
start_sample (number, lo (volume), hi (volume), (zargc == 4) ? zargs[3] : 0);
|
||||
break;
|
||||
case EFFECT_STOP:
|
||||
os_stop_sample (number);
|
||||
break;
|
||||
case EFFECT_FINISH_WITH:
|
||||
os_finish_with_sample (number);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
locked = FALSE;
|
||||
|
||||
} else os_beep (number);
|
||||
|
||||
}/* z_sound_effect */
|
|
@ -1,365 +0,0 @@
|
|||
/* stream.c - IO stream implementation
|
||||
* Copyright (c) 1995-1997 Stefan Jokisch
|
||||
*
|
||||
* This file is part of Frotz.
|
||||
*
|
||||
* Frotz 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.
|
||||
*
|
||||
* Frotz 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
|
||||
*/
|
||||
|
||||
#include "frotz.h"
|
||||
|
||||
extern bool handle_hot_key (zchar);
|
||||
|
||||
extern bool validate_click (void);
|
||||
|
||||
extern void replay_open (void);
|
||||
extern void replay_close (void);
|
||||
extern void memory_open (zword, zword, bool);
|
||||
extern void memory_close (void);
|
||||
extern void record_open (void);
|
||||
extern void record_close (void);
|
||||
extern void script_open (void);
|
||||
extern void script_close (void);
|
||||
|
||||
extern void memory_word (const zchar *);
|
||||
extern void memory_new_line (void);
|
||||
extern void record_write_key (zchar);
|
||||
extern void record_write_input (const zchar *, zchar);
|
||||
extern void script_char (zchar);
|
||||
extern void script_word (const zchar *);
|
||||
extern void script_new_line (void);
|
||||
extern void script_write_input (const zchar *, zchar);
|
||||
extern void script_erase_input (const zchar *);
|
||||
extern void script_mssg_on (void);
|
||||
extern void script_mssg_off (void);
|
||||
extern void screen_char (zchar);
|
||||
extern void screen_word (const zchar *);
|
||||
extern void screen_new_line (void);
|
||||
extern void screen_write_input (const zchar *, zchar);
|
||||
extern void screen_erase_input (const zchar *);
|
||||
extern void screen_mssg_on (void);
|
||||
extern void screen_mssg_off (void);
|
||||
|
||||
extern zchar replay_read_key (void);
|
||||
extern zchar replay_read_input (zchar *);
|
||||
extern zchar console_read_key (zword);
|
||||
extern zchar console_read_input (int, zchar *, zword, bool);
|
||||
|
||||
extern int direct_call (zword);
|
||||
|
||||
/*
|
||||
* stream_mssg_on
|
||||
*
|
||||
* Start printing a "debugging" message.
|
||||
*
|
||||
*/
|
||||
|
||||
void stream_mssg_on (void)
|
||||
{
|
||||
|
||||
flush_buffer ();
|
||||
|
||||
if (ostream_screen)
|
||||
screen_mssg_on ();
|
||||
if (ostream_script && enable_scripting)
|
||||
script_mssg_on ();
|
||||
|
||||
message = TRUE;
|
||||
|
||||
}/* stream_mssg_on */
|
||||
|
||||
/*
|
||||
* stream_mssg_off
|
||||
*
|
||||
* Stop printing a "debugging" message.
|
||||
*
|
||||
*/
|
||||
|
||||
void stream_mssg_off (void)
|
||||
{
|
||||
|
||||
flush_buffer ();
|
||||
|
||||
if (ostream_screen)
|
||||
screen_mssg_off ();
|
||||
if (ostream_script && enable_scripting)
|
||||
script_mssg_off ();
|
||||
|
||||
message = FALSE;
|
||||
|
||||
}/* stream_mssg_off */
|
||||
|
||||
/*
|
||||
* z_output_stream, open or close an output stream.
|
||||
*
|
||||
* zargs[0] = stream to open (positive) or close (negative)
|
||||
* zargs[1] = address to redirect output to (stream 3 only)
|
||||
* zargs[2] = width of redirected output (stream 3 only, optional)
|
||||
*
|
||||
*/
|
||||
|
||||
void z_output_stream (void)
|
||||
{
|
||||
|
||||
flush_buffer ();
|
||||
|
||||
switch ((short) zargs[0]) {
|
||||
|
||||
case 1: ostream_screen = TRUE;
|
||||
break;
|
||||
case -1: ostream_screen = FALSE;
|
||||
break;
|
||||
case 2: if (!ostream_script) script_open ();
|
||||
break;
|
||||
case -2: if (ostream_script) script_close ();
|
||||
break;
|
||||
case 3: memory_open (zargs[1], zargs[2], zargc >= 3);
|
||||
break;
|
||||
case -3: memory_close ();
|
||||
break;
|
||||
case 4: if (!ostream_record) record_open ();
|
||||
break;
|
||||
case -4: if (ostream_record) record_close ();
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}/* z_output_stream */
|
||||
|
||||
/*
|
||||
* stream_char
|
||||
*
|
||||
* Send a single character to the output stream.
|
||||
*
|
||||
*/
|
||||
|
||||
void stream_char (zchar c)
|
||||
{
|
||||
|
||||
if (ostream_screen)
|
||||
screen_char (c);
|
||||
if (ostream_script && enable_scripting)
|
||||
script_char (c);
|
||||
|
||||
}/* stream_char */
|
||||
|
||||
/*
|
||||
* stream_word
|
||||
*
|
||||
* Send a string of characters to the output streams.
|
||||
*
|
||||
*/
|
||||
|
||||
void stream_word (const zchar *s)
|
||||
{
|
||||
|
||||
if (ostream_memory && !message)
|
||||
|
||||
memory_word (s);
|
||||
|
||||
else {
|
||||
|
||||
if (ostream_screen)
|
||||
screen_word (s);
|
||||
if (ostream_script && enable_scripting)
|
||||
script_word (s);
|
||||
|
||||
}
|
||||
|
||||
}/* stream_word */
|
||||
|
||||
/*
|
||||
* stream_new_line
|
||||
*
|
||||
* Send a newline to the output streams.
|
||||
*
|
||||
*/
|
||||
|
||||
void stream_new_line (void)
|
||||
{
|
||||
|
||||
if (ostream_memory && !message)
|
||||
|
||||
memory_new_line ();
|
||||
|
||||
else {
|
||||
|
||||
if (ostream_screen)
|
||||
screen_new_line ();
|
||||
if (ostream_script && enable_scripting)
|
||||
script_new_line ();
|
||||
|
||||
}
|
||||
|
||||
}/* stream_new_line */
|
||||
|
||||
/*
|
||||
* z_input_stream, select an input stream.
|
||||
*
|
||||
* zargs[0] = input stream to be selected
|
||||
*
|
||||
*/
|
||||
|
||||
void z_input_stream (void)
|
||||
{
|
||||
|
||||
flush_buffer ();
|
||||
|
||||
if (zargs[0] == 0 && istream_replay)
|
||||
replay_close ();
|
||||
if (zargs[0] == 1 && !istream_replay)
|
||||
replay_open ();
|
||||
|
||||
}/* z_input_stream */
|
||||
|
||||
/*
|
||||
* stream_read_key
|
||||
*
|
||||
* Read a single keystroke from the current input stream.
|
||||
*
|
||||
*/
|
||||
|
||||
zchar stream_read_key ( zword timeout, zword routine,
|
||||
bool hot_keys )
|
||||
{
|
||||
zchar key = ZC_BAD;
|
||||
|
||||
flush_buffer ();
|
||||
|
||||
/* Read key from current input stream */
|
||||
|
||||
continue_input:
|
||||
|
||||
do {
|
||||
|
||||
if (istream_replay)
|
||||
key = replay_read_key ();
|
||||
else
|
||||
key = console_read_key (timeout);
|
||||
|
||||
} while (key == ZC_BAD);
|
||||
|
||||
/* Verify mouse clicks */
|
||||
|
||||
if (key == ZC_SINGLE_CLICK || key == ZC_DOUBLE_CLICK)
|
||||
if (!validate_click ())
|
||||
goto continue_input;
|
||||
|
||||
/* Copy key to the command file */
|
||||
|
||||
if (ostream_record && !istream_replay)
|
||||
record_write_key (key);
|
||||
|
||||
/* Handle timeouts */
|
||||
|
||||
if (key == ZC_TIME_OUT)
|
||||
if (direct_call (routine) == 0)
|
||||
goto continue_input;
|
||||
|
||||
/* Handle hot keys */
|
||||
|
||||
if (hot_keys && key >= ZC_HKEY_MIN && key <= ZC_HKEY_MAX) {
|
||||
|
||||
if (h_version == V4 && key == ZC_HKEY_UNDO)
|
||||
goto continue_input;
|
||||
if (!handle_hot_key (key))
|
||||
goto continue_input;
|
||||
|
||||
return ZC_BAD;
|
||||
|
||||
}
|
||||
|
||||
/* Return key */
|
||||
|
||||
return key;
|
||||
|
||||
}/* stream_read_key */
|
||||
|
||||
/*
|
||||
* stream_read_input
|
||||
*
|
||||
* Read a line of input from the current input stream.
|
||||
*
|
||||
*/
|
||||
|
||||
zchar stream_read_input ( int max, zchar *buf,
|
||||
zword timeout, zword routine,
|
||||
bool hot_keys,
|
||||
bool no_scripting )
|
||||
{
|
||||
zchar key = ZC_BAD;
|
||||
|
||||
flush_buffer ();
|
||||
|
||||
/* Remove initial input from the transscript file or from the screen */
|
||||
|
||||
if (ostream_script && enable_scripting && !no_scripting)
|
||||
script_erase_input (buf);
|
||||
if (istream_replay)
|
||||
screen_erase_input (buf);
|
||||
|
||||
/* Read input line from current input stream */
|
||||
|
||||
continue_input:
|
||||
|
||||
do {
|
||||
|
||||
if (istream_replay)
|
||||
key = replay_read_input (buf);
|
||||
else
|
||||
key = console_read_input (max, buf, timeout, key != ZC_BAD);
|
||||
|
||||
} while (key == ZC_BAD);
|
||||
|
||||
/* Verify mouse clicks */
|
||||
|
||||
if (key == ZC_SINGLE_CLICK || key == ZC_DOUBLE_CLICK)
|
||||
if (!validate_click ())
|
||||
goto continue_input;
|
||||
|
||||
/* Copy input line to the command file */
|
||||
|
||||
if (ostream_record && !istream_replay)
|
||||
record_write_input (buf, key);
|
||||
|
||||
/* Handle timeouts */
|
||||
|
||||
if (key == ZC_TIME_OUT)
|
||||
if (direct_call (routine) == 0)
|
||||
goto continue_input;
|
||||
|
||||
/* Handle hot keys */
|
||||
|
||||
if (hot_keys && key >= ZC_HKEY_MIN && key <= ZC_HKEY_MAX) {
|
||||
|
||||
if (!handle_hot_key (key))
|
||||
goto continue_input;
|
||||
|
||||
return ZC_BAD;
|
||||
|
||||
}
|
||||
|
||||
/* Copy input line to transscript file or to the screen */
|
||||
|
||||
if (ostream_script && enable_scripting && !no_scripting)
|
||||
script_write_input (buf, key);
|
||||
if (istream_replay)
|
||||
screen_write_input (buf, key);
|
||||
|
||||
/* Return terminating key */
|
||||
|
||||
return key;
|
||||
|
||||
}/* stream_read_input */
|
|
@ -1,193 +0,0 @@
|
|||
/* table.c - Table handling opcodes
|
||||
* Copyright (c) 1995-1997 Stefan Jokisch
|
||||
*
|
||||
* This file is part of Frotz.
|
||||
*
|
||||
* Frotz 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.
|
||||
*
|
||||
* Frotz 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
|
||||
*/
|
||||
|
||||
#include "frotz.h"
|
||||
|
||||
/*
|
||||
* z_copy_table, copy a table or fill it with zeroes.
|
||||
*
|
||||
* zargs[0] = address of table
|
||||
* zargs[1] = destination address or 0 for fill
|
||||
* zargs[2] = size of table
|
||||
*
|
||||
* Note: Copying is safe even when source and destination overlap; but
|
||||
* if zargs[1] is negative the table _must_ be copied forwards.
|
||||
*
|
||||
*/
|
||||
|
||||
void z_copy_table (void)
|
||||
{
|
||||
zword addr;
|
||||
zword size = zargs[2];
|
||||
zbyte value;
|
||||
int i;
|
||||
|
||||
if (zargs[1] == 0) /* zero table */
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
storeb ((zword) (zargs[0] + i), 0);
|
||||
|
||||
else if ((short) size < 0 || zargs[0] > zargs[1]) /* copy forwards */
|
||||
|
||||
for (i = 0; i < (((short) size < 0) ? - (short) size : size); i++) {
|
||||
addr = zargs[0] + i;
|
||||
LOW_BYTE (addr, value)
|
||||
storeb ((zword) (zargs[1] + i), value);
|
||||
}
|
||||
|
||||
else /* copy backwards */
|
||||
|
||||
for (i = size - 1; i >= 0; i--) {
|
||||
addr = zargs[0] + i;
|
||||
LOW_BYTE (addr, value)
|
||||
storeb ((zword) (zargs[1] + i), value);
|
||||
}
|
||||
|
||||
}/* z_copy_table */
|
||||
|
||||
/*
|
||||
* z_loadb, store a value from a table of bytes.
|
||||
*
|
||||
* zargs[0] = address of table
|
||||
* zargs[1] = index of table entry to store
|
||||
*
|
||||
*/
|
||||
|
||||
void z_loadb (void)
|
||||
{
|
||||
zword addr = zargs[0] + zargs[1];
|
||||
zbyte value;
|
||||
|
||||
LOW_BYTE (addr, value)
|
||||
|
||||
store (value);
|
||||
|
||||
}/* z_loadb */
|
||||
|
||||
/*
|
||||
* z_loadw, store a value from a table of words.
|
||||
*
|
||||
* zargs[0] = address of table
|
||||
* zargs[1] = index of table entry to store
|
||||
*
|
||||
*/
|
||||
|
||||
void z_loadw (void)
|
||||
{
|
||||
zword addr = zargs[0] + 2 * zargs[1];
|
||||
zword value;
|
||||
|
||||
LOW_WORD (addr, value)
|
||||
|
||||
store (value);
|
||||
|
||||
}/* z_loadw */
|
||||
|
||||
/*
|
||||
* z_scan_table, find and store the address of a target within a table.
|
||||
*
|
||||
* zargs[0] = target value to be searched for
|
||||
* zargs[1] = address of table
|
||||
* zargs[2] = number of table entries to check value against
|
||||
* zargs[3] = type of table (optional, defaults to 0x82)
|
||||
*
|
||||
* Note: The table is a word array if bit 7 of zargs[3] is set; otherwise
|
||||
* it's a byte array. The lower bits hold the address step.
|
||||
*
|
||||
*/
|
||||
|
||||
void z_scan_table (void)
|
||||
{
|
||||
zword addr = zargs[1];
|
||||
int i;
|
||||
|
||||
/* Supply default arguments */
|
||||
|
||||
if (zargc < 4)
|
||||
zargs[3] = 0x82;
|
||||
|
||||
/* Scan byte or word array */
|
||||
|
||||
for (i = 0; i < zargs[2]; i++) {
|
||||
|
||||
if (zargs[3] & 0x80) { /* scan word array */
|
||||
|
||||
zword wvalue;
|
||||
|
||||
LOW_WORD (addr, wvalue)
|
||||
|
||||
if (wvalue == zargs[0])
|
||||
goto finished;
|
||||
|
||||
} else { /* scan byte array */
|
||||
|
||||
zbyte bvalue;
|
||||
|
||||
LOW_BYTE (addr, bvalue)
|
||||
|
||||
if (bvalue == zargs[0])
|
||||
goto finished;
|
||||
|
||||
}
|
||||
|
||||
addr += zargs[3] & 0x7f;
|
||||
|
||||
}
|
||||
|
||||
addr = 0;
|
||||
|
||||
finished:
|
||||
|
||||
store (addr);
|
||||
branch (addr);
|
||||
|
||||
}/* z_scan_table */
|
||||
|
||||
/*
|
||||
* z_storeb, write a byte into a table of bytes.
|
||||
*
|
||||
* zargs[0] = address of table
|
||||
* zargs[1] = index of table entry
|
||||
* zargs[2] = value to be written
|
||||
*
|
||||
*/
|
||||
|
||||
void z_storeb (void)
|
||||
{
|
||||
|
||||
storeb ((zword) (zargs[0] + zargs[1]), zargs[2]);
|
||||
|
||||
}/* z_storeb */
|
||||
|
||||
/*
|
||||
* z_storew, write a word into a table of words.
|
||||
*
|
||||
* zargs[0] = address of table
|
||||
* zargs[1] = index of table entry
|
||||
* zargs[2] = value to be written
|
||||
*
|
||||
*/
|
||||
|
||||
void z_storew (void)
|
||||
{
|
||||
|
||||
storew ((zword) (zargs[0] + 2 * zargs[1]), zargs[2]);
|
||||
|
||||
}/* z_storew */
|
File diff suppressed because it is too large
Load diff
|
@ -1,304 +0,0 @@
|
|||
/* variable.c - Variable and stack related opcodes
|
||||
* Copyright (c) 1995-1997 Stefan Jokisch
|
||||
*
|
||||
* This file is part of Frotz.
|
||||
*
|
||||
* Frotz 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.
|
||||
*
|
||||
* Frotz 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
|
||||
*/
|
||||
|
||||
#include "frotz.h"
|
||||
|
||||
/*
|
||||
* z_dec, decrement a variable.
|
||||
*
|
||||
* zargs[0] = variable to decrement
|
||||
*
|
||||
*/
|
||||
|
||||
void z_dec (void)
|
||||
{
|
||||
zword value;
|
||||
|
||||
if (zargs[0] == 0)
|
||||
(*sp)--;
|
||||
else if (zargs[0] < 16)
|
||||
(*(fp - zargs[0]))--;
|
||||
else {
|
||||
zword addr = h_globals + 2 * (zargs[0] - 16);
|
||||
LOW_WORD (addr, value)
|
||||
value--;
|
||||
SET_WORD (addr, value)
|
||||
}
|
||||
|
||||
}/* z_dec */
|
||||
|
||||
/*
|
||||
* z_dec_chk, decrement a variable and branch if now less than value.
|
||||
*
|
||||
* zargs[0] = variable to decrement
|
||||
* zargs[1] = value to check variable against
|
||||
*
|
||||
*/
|
||||
|
||||
void z_dec_chk (void)
|
||||
{
|
||||
zword value;
|
||||
|
||||
if (zargs[0] == 0)
|
||||
value = --(*sp);
|
||||
else if (zargs[0] < 16)
|
||||
value = --(*(fp - zargs[0]));
|
||||
else {
|
||||
zword addr = h_globals + 2 * (zargs[0] - 16);
|
||||
LOW_WORD (addr, value)
|
||||
value--;
|
||||
SET_WORD (addr, value)
|
||||
}
|
||||
|
||||
branch ((short) value < (short) zargs[1]);
|
||||
|
||||
}/* z_dec_chk */
|
||||
|
||||
/*
|
||||
* z_inc, increment a variable.
|
||||
*
|
||||
* zargs[0] = variable to increment
|
||||
*
|
||||
*/
|
||||
|
||||
void z_inc (void)
|
||||
{
|
||||
zword value;
|
||||
|
||||
if (zargs[0] == 0)
|
||||
(*sp)++;
|
||||
else if (zargs[0] < 16)
|
||||
(*(fp - zargs[0]))++;
|
||||
else {
|
||||
zword addr = h_globals + 2 * (zargs[0] - 16);
|
||||
LOW_WORD (addr, value)
|
||||
value++;
|
||||
SET_WORD (addr, value)
|
||||
}
|
||||
|
||||
}/* z_inc */
|
||||
|
||||
/*
|
||||
* z_inc_chk, increment a variable and branch if now greater than value.
|
||||
*
|
||||
* zargs[0] = variable to increment
|
||||
* zargs[1] = value to check variable against
|
||||
*
|
||||
*/
|
||||
|
||||
void z_inc_chk (void)
|
||||
{
|
||||
zword value;
|
||||
|
||||
if (zargs[0] == 0)
|
||||
value = ++(*sp);
|
||||
else if (zargs[0] < 16)
|
||||
value = ++(*(fp - zargs[0]));
|
||||
else {
|
||||
zword addr = h_globals + 2 * (zargs[0] - 16);
|
||||
LOW_WORD (addr, value)
|
||||
value++;
|
||||
SET_WORD (addr, value)
|
||||
}
|
||||
|
||||
branch ((short) value > (short) zargs[1]);
|
||||
|
||||
}/* z_inc_chk */
|
||||
|
||||
/*
|
||||
* z_load, store the value of a variable.
|
||||
*
|
||||
* zargs[0] = variable to store
|
||||
*
|
||||
*/
|
||||
|
||||
void z_load (void)
|
||||
{
|
||||
zword value;
|
||||
|
||||
if (zargs[0] == 0)
|
||||
value = *sp;
|
||||
else if (zargs[0] < 16)
|
||||
value = *(fp - zargs[0]);
|
||||
else {
|
||||
zword addr = h_globals + 2 * (zargs[0] - 16);
|
||||
LOW_WORD (addr, value)
|
||||
}
|
||||
|
||||
store (value);
|
||||
|
||||
}/* z_load */
|
||||
|
||||
/*
|
||||
* z_pop, pop a value off the game stack and discard it.
|
||||
*
|
||||
* no zargs used
|
||||
*
|
||||
*/
|
||||
|
||||
void z_pop (void)
|
||||
{
|
||||
|
||||
sp++;
|
||||
|
||||
}/* z_pop */
|
||||
|
||||
/*
|
||||
* z_pop_stack, pop n values off the game or user stack and discard them.
|
||||
*
|
||||
* zargs[0] = number of values to discard
|
||||
* zargs[1] = address of user stack (optional)
|
||||
*
|
||||
*/
|
||||
|
||||
void z_pop_stack (void)
|
||||
{
|
||||
|
||||
if (zargc == 2) { /* it's a user stack */
|
||||
|
||||
zword size;
|
||||
zword addr = zargs[1];
|
||||
|
||||
LOW_WORD (addr, size)
|
||||
|
||||
size += zargs[0];
|
||||
storew (addr, size);
|
||||
|
||||
} else sp += zargs[0]; /* it's the game stack */
|
||||
|
||||
}/* z_pop_stack */
|
||||
|
||||
/*
|
||||
* z_pull, pop a value off...
|
||||
*
|
||||
* a) ...the game or a user stack and store it (V6)
|
||||
*
|
||||
* zargs[0] = address of user stack (optional)
|
||||
*
|
||||
* b) ...the game stack and write it to a variable (other than V6)
|
||||
*
|
||||
* zargs[0] = variable to write value to
|
||||
*
|
||||
*/
|
||||
|
||||
void z_pull (void)
|
||||
{
|
||||
zword value;
|
||||
|
||||
if (h_version != V6) { /* not a V6 game, pop stack and write */
|
||||
|
||||
value = *sp++;
|
||||
|
||||
if (zargs[0] == 0)
|
||||
*sp = value;
|
||||
else if (zargs[0] < 16)
|
||||
*(fp - zargs[0]) = value;
|
||||
else {
|
||||
zword addr = h_globals + 2 * (zargs[0] - 16);
|
||||
SET_WORD (addr, value)
|
||||
}
|
||||
|
||||
} else { /* it's V6, but is there a user stack? */
|
||||
|
||||
if (zargc == 1) { /* it's a user stack */
|
||||
|
||||
zword size;
|
||||
zword addr = zargs[0];
|
||||
|
||||
LOW_WORD (addr, size)
|
||||
|
||||
size++;
|
||||
storew (addr, size);
|
||||
|
||||
addr += 2 * size;
|
||||
LOW_WORD (addr, value)
|
||||
|
||||
} else value = *sp++; /* it's the game stack */
|
||||
|
||||
store (value);
|
||||
|
||||
}
|
||||
|
||||
}/* z_pull */
|
||||
|
||||
/*
|
||||
* z_push, push a value onto the game stack.
|
||||
*
|
||||
* zargs[0] = value to push onto the stack
|
||||
*
|
||||
*/
|
||||
|
||||
void z_push (void)
|
||||
{
|
||||
|
||||
*--sp = zargs[0];
|
||||
|
||||
}/* z_push */
|
||||
|
||||
/*
|
||||
* z_push_stack, push a value onto a user stack then branch if successful.
|
||||
*
|
||||
* zargs[0] = value to push onto the stack
|
||||
* zargs[1] = address of user stack
|
||||
*
|
||||
*/
|
||||
|
||||
void z_push_stack (void)
|
||||
{
|
||||
zword size;
|
||||
zword addr = zargs[1];
|
||||
|
||||
LOW_WORD (addr, size)
|
||||
|
||||
if (size != 0) {
|
||||
|
||||
storew ((zword) (addr + 2 * size), zargs[0]);
|
||||
|
||||
size--;
|
||||
storew (addr, size);
|
||||
|
||||
}
|
||||
|
||||
branch (size);
|
||||
|
||||
}/* z_push_stack */
|
||||
|
||||
/*
|
||||
* z_store, write a value to a variable.
|
||||
*
|
||||
* zargs[0] = variable to be written to
|
||||
* zargs[1] = value to write
|
||||
*
|
||||
*/
|
||||
|
||||
void z_store (void)
|
||||
{
|
||||
zword value = zargs[1];
|
||||
|
||||
if (zargs[0] == 0)
|
||||
*sp = value;
|
||||
else if (zargs[0] < 16)
|
||||
*(fp - zargs[0]) = value;
|
||||
else {
|
||||
zword addr = h_globals + 2 * (zargs[0] - 16);
|
||||
SET_WORD (addr, value)
|
||||
}
|
||||
|
||||
}/* z_store */
|
|
@ -1,42 +0,0 @@
|
|||
/* dumb-frotz.h
|
||||
* $Id: dumb-frotz.h,v 1.1.1.1 2002/03/26 22:38:34 feedle Exp $
|
||||
* Frotz os functions for a standard C library and a dumb terminal.
|
||||
* Now you can finally play Zork Zero on your Teletype.
|
||||
*
|
||||
* Copyright 1997, 1998 Alembic Petrofsky <alembic@petrofsky.berkeley.ca.us>.
|
||||
* Any use permitted provided this notice stays intact.
|
||||
*/
|
||||
#include "../common/frotz.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
|
||||
#define VERSION "1.0"
|
||||
|
||||
/* from ../common/setup.h */
|
||||
extern f_setup_t f_setup;
|
||||
|
||||
/* From input.c. */
|
||||
bool is_terminator (zchar);
|
||||
|
||||
/* dumb-input.c */
|
||||
bool dumb_handle_setting(const char *setting, bool show_cursor, bool startup);
|
||||
void dumb_init_input(void);
|
||||
|
||||
/* dumb-output.c */
|
||||
void dumb_init_output(void);
|
||||
bool dumb_output_handle_setting(const char *setting, bool show_cursor,
|
||||
bool startup);
|
||||
void dumb_show_screen(bool show_cursor);
|
||||
void dumb_show_prompt(bool show_cursor, char line_type);
|
||||
void dumb_dump_screen(void);
|
||||
void dumb_display_user_input(char *);
|
||||
void dumb_discard_old_input(int num_chars);
|
||||
void dumb_elide_more_prompt(void);
|
||||
void dumb_set_picture_cell(int row, int col, char c);
|
||||
|
||||
/* dumb-pic.c */
|
||||
void dumb_init_pictures(char *graphics_filename);
|
|
@ -1,234 +0,0 @@
|
|||
/* dumb-init.c
|
||||
* $Id: dumb-init.c,v 1.1.1.1 2002/03/26 22:38:34 feedle Exp $
|
||||
*
|
||||
* Copyright 1997,1998 Alva Petrofsky <alva@petrofsky.berkeley.ca.us>.
|
||||
* Any use permitted provided this notice stays intact.
|
||||
*/
|
||||
|
||||
#include "dumb_frotz.h"
|
||||
|
||||
f_setup_t f_setup;
|
||||
|
||||
#define INFORMATION "\
|
||||
An interpreter for all Infocom and other Z-Machine games.\n\
|
||||
Complies with standard 1.0 of Graham Nelson's specification.\n\
|
||||
\n\
|
||||
Syntax: dfrotz [options] story-file\n\
|
||||
-a watch attribute setting \t -Q use old-style save format\n\
|
||||
-A watch attribute testing \t -R xxx do runtime setting \\xxx\n\
|
||||
-h # screen height \t before starting (can be used repeatedly)\n\
|
||||
-i ignore fatal errors \t -s # random number seed value\n\
|
||||
-I # interpreter number \t -S # transscript width\n\
|
||||
-o watch object movement \t -t set Tandy bit\n\
|
||||
-O watch object locating \t -u # slots for multiple undo\n\
|
||||
-p plain ASCII output only \t -w # screen width\n\
|
||||
-P alter piracy opcode \t -x expand abbreviations g/x/z"
|
||||
|
||||
/*
|
||||
static char usage[] = "\
|
||||
\n\
|
||||
FROTZ V2.32 - interpreter for all Infocom games. Complies with standard\n\
|
||||
1.0 of Graham Nelson's specification. Written by Stefan Jokisch in 1995-7.\n\
|
||||
\n\
|
||||
DUMB-FROTZ V2.32R1 - port for all platforms. Somewhat complies with standard\n\
|
||||
9899 of ISO's specification. Written by Alembic Petrofsky in 1997-8.\n\
|
||||
\n\
|
||||
Syntax: frotz [options] story-file [graphics-file]\n\
|
||||
\n\
|
||||
-a watch attribute setting\n\
|
||||
-A watch attribute testing\n\
|
||||
-h # screen height\n\
|
||||
-i ignore runtime errors\n\
|
||||
-I # interpreter number to report to game\n\
|
||||
-o watch object movement\n\
|
||||
-O watch object locating\n\
|
||||
-p alter piracy opcode\n\
|
||||
-P transliterate latin1 to plain ASCII\n\
|
||||
-R xxx do runtime setting \\xxx before starting\n\
|
||||
(this option can be used multiple times)\n\
|
||||
-s # random number seed value\n\
|
||||
-S # transscript width\n\
|
||||
-t set Tandy bit\n\
|
||||
-u # slots for multiple undo\n\
|
||||
-w # screen width\n\
|
||||
-x expand abbreviations g/x/z\n\
|
||||
\n\
|
||||
While running, enter \"\\help\" to list the runtime escape sequences.\n\
|
||||
";
|
||||
*/
|
||||
|
||||
|
||||
/* A unix-like getopt, but with the names changed to avoid any problems. */
|
||||
static int zoptind = 1;
|
||||
static int zoptopt = 0;
|
||||
static char *zoptarg = NULL;
|
||||
static int zgetopt (int argc, char *argv[], const char *options)
|
||||
{
|
||||
static pos = 1;
|
||||
const char *p;
|
||||
if (zoptind >= argc || argv[zoptind][0] != '-' || argv[zoptind][1] == 0)
|
||||
return EOF;
|
||||
zoptopt = argv[zoptind][pos++];
|
||||
zoptarg = NULL;
|
||||
if (argv[zoptind][pos] == 0)
|
||||
{ pos = 1; zoptind++; }
|
||||
p = strchr (options, zoptopt);
|
||||
if (zoptopt == ':' || p == NULL) {
|
||||
fputs ("illegal option -- ", stderr);
|
||||
goto error;
|
||||
} else if (p[1] == ':')
|
||||
if (zoptind >= argc) {
|
||||
fputs ("option requires an argument -- ", stderr);
|
||||
goto error;
|
||||
} else {
|
||||
zoptarg = argv[zoptind];
|
||||
if (pos != 1)
|
||||
zoptarg += pos;
|
||||
pos = 1; zoptind++;
|
||||
}
|
||||
return zoptopt;
|
||||
error:
|
||||
fputc (zoptopt, stderr);
|
||||
fputc ('\n', stderr);
|
||||
return '?';
|
||||
}/* zgetopt */
|
||||
|
||||
static int user_screen_width = 75;
|
||||
static int user_screen_height = 24;
|
||||
static int user_interpreter_number = -1;
|
||||
static int user_random_seed = -1;
|
||||
static int user_tandy_bit = 0;
|
||||
static char *graphics_filename = NULL;
|
||||
static bool plain_ascii = FALSE;
|
||||
|
||||
void os_process_arguments(int argc, char *argv[])
|
||||
{
|
||||
int c;
|
||||
|
||||
/* Parse the options */
|
||||
do {
|
||||
c = zgetopt(argc, argv, "aAh:iI:oOpPQs:R:S:tu:w:xZ:");
|
||||
switch(c) {
|
||||
case 'a': f_setup.attribute_assignment = 1; break;
|
||||
case 'A': f_setup.attribute_testing = 1; break;
|
||||
case 'h': user_screen_height = atoi(zoptarg); break;
|
||||
case 'i': f_setup.ignore_errors = 1; break;
|
||||
case 'I': f_setup.interpreter_number = atoi(zoptarg); break;
|
||||
case 'o': f_setup.object_movement = 1; break;
|
||||
case 'O': f_setup.object_locating = 1; break;
|
||||
case 'P': f_setup.piracy = 1; break;
|
||||
case 'p': plain_ascii = 1; break;
|
||||
case 'Q': f_setup.save_quetzal = 0; break;
|
||||
case 'R': dumb_handle_setting(zoptarg, FALSE, TRUE); break;
|
||||
case 's': user_random_seed = atoi(zoptarg); break;
|
||||
case 'S': f_setup.script_cols = atoi(zoptarg); break;
|
||||
case 't': user_tandy_bit = 1; break;
|
||||
case 'u': f_setup.undo_slots = atoi(zoptarg); break;
|
||||
case 'w': user_screen_width = atoi(zoptarg); break;
|
||||
case 'x': f_setup.expand_abbreviations = 1; break;
|
||||
case 'Z': f_setup.err_report_mode = atoi(zoptarg);
|
||||
if ((f_setup.err_report_mode < ERR_REPORT_NEVER) ||
|
||||
(f_setup.err_report_mode > ERR_REPORT_FATAL))
|
||||
f_setup.err_report_mode = ERR_DEFAULT_REPORT_MODE;
|
||||
break;
|
||||
}
|
||||
} while (c != EOF);
|
||||
|
||||
if (((argc - zoptind) != 1) && ((argc - zoptind) != 2)) {
|
||||
printf("FROTZ V%s\tdumb interface.\n", VERSION);
|
||||
puts(INFORMATION);
|
||||
printf("\t-Z # error checking mode (default = %d)\n"
|
||||
"\t %d = don't report errors %d = report first error\n"
|
||||
"\t %d = report all errors %d = exit after any error\n\n",
|
||||
ERR_DEFAULT_REPORT_MODE, ERR_REPORT_NEVER,
|
||||
ERR_REPORT_ONCE, ERR_REPORT_ALWAYS, ERR_REPORT_FATAL);
|
||||
exit(1);
|
||||
}
|
||||
/*
|
||||
if (((argc - zoptind) != 1) && ((argc - zoptind) != 2)) {
|
||||
puts(usage);
|
||||
exit(1);
|
||||
}
|
||||
*/
|
||||
story_name = argv[zoptind++];
|
||||
if (zoptind < argc)
|
||||
graphics_filename = argv[zoptind++];
|
||||
|
||||
}
|
||||
|
||||
void os_init_screen(void)
|
||||
{
|
||||
if (h_version == V3 && user_tandy_bit)
|
||||
h_config |= CONFIG_TANDY;
|
||||
|
||||
if (h_version >= V5 && f_setup.undo_slots == 0)
|
||||
h_flags &= ~UNDO_FLAG;
|
||||
|
||||
h_screen_rows = user_screen_height;
|
||||
h_screen_cols = user_screen_width;
|
||||
|
||||
if (user_interpreter_number > 0)
|
||||
h_interpreter_number = user_interpreter_number;
|
||||
else {
|
||||
/* Use ms-dos for v6 (because that's what most people have the
|
||||
* graphics files for), but don't use it for v5 (or Beyond Zork
|
||||
* will try to use funky characters). */
|
||||
h_interpreter_number = h_version == 6 ? INTERP_MSDOS : INTERP_DEC_20;
|
||||
}
|
||||
h_interpreter_version = 'F';
|
||||
|
||||
dumb_init_input();
|
||||
dumb_init_output();
|
||||
dumb_init_pictures(graphics_filename);
|
||||
}
|
||||
|
||||
int os_random_seed (void)
|
||||
{
|
||||
if (user_random_seed == -1)
|
||||
/* Use the epoch as seed value */
|
||||
return (time(0) & 0x7fff);
|
||||
else return user_random_seed;
|
||||
}
|
||||
|
||||
void os_restart_game (int stage) {}
|
||||
|
||||
void os_fatal (const char *s)
|
||||
{
|
||||
fprintf(stderr, "\nFatal error: %s\n", s);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
FILE *os_path_open(const char *name, const char *mode)
|
||||
{
|
||||
FILE *fp;
|
||||
char buf[FILENAME_MAX + 1];
|
||||
char *p;
|
||||
|
||||
/* Let's see if the file is in the currect directory */
|
||||
/* or if the user gave us a full path. */
|
||||
if ((fp = fopen(name, mode))) {
|
||||
return fp;
|
||||
}
|
||||
/* Sorry, but dumb frotz is too dumb to care about searching paths. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void os_init_setup(void)
|
||||
{
|
||||
f_setup.attribute_assignment = 0;
|
||||
f_setup.attribute_testing = 0;
|
||||
f_setup.context_lines = 0;
|
||||
f_setup.object_locating = 0;
|
||||
f_setup.object_movement = 0;
|
||||
f_setup.left_margin = 0;
|
||||
f_setup.right_margin = 0;
|
||||
f_setup.ignore_errors = 0;
|
||||
f_setup.piracy = 0;
|
||||
f_setup.undo_slots = MAX_UNDO_SLOTS;
|
||||
f_setup.expand_abbreviations = 0;
|
||||
f_setup.script_cols = 80;
|
||||
f_setup.save_quetzal = 1;
|
||||
f_setup.sound = 1;
|
||||
f_setup.err_report_mode = ERR_DEFAULT_REPORT_MODE;
|
||||
|
||||
}
|
|
@ -1,430 +0,0 @@
|
|||
/* dumb-input.c
|
||||
* $Id: dumb-input.c,v 1.1.1.1 2002/03/26 22:38:34 feedle Exp $
|
||||
* Copyright 1997,1998 Alpine Petrofsky <alpine@petrofsky.berkeley.ca.us>.
|
||||
* Any use permitted provided this notice stays intact.
|
||||
*/
|
||||
|
||||
#include "dumb_frotz.h"
|
||||
f_setup_t f_setup;
|
||||
|
||||
static char runtime_usage[] =
|
||||
"DUMB-FROTZ runtime help:\n"
|
||||
" General Commands:\n"
|
||||
" \\help Show this message.\n"
|
||||
" \\set Show the current values of runtime settings.\n"
|
||||
" \\s Show the current contents of the whole screen.\n"
|
||||
" \\d Discard the part of the input before the cursor.\n"
|
||||
" \\wN Advance clock N/10 seconds, possibly causing the current\n"
|
||||
" and subsequent inputs to timeout.\n"
|
||||
" \\w Advance clock by the amount of real time since this input\n"
|
||||
" started (times the current speed factor).\n"
|
||||
" \\t Advance clock just enough to timeout the current input\n"
|
||||
" Reverse-Video Display Method Settings:\n"
|
||||
" \\rn none \\rc CAPS \\rd doublestrike \\ru underline\n"
|
||||
" \\rbC show rv blanks as char C (orthogonal to above modes)\n"
|
||||
" Output Compression Settings:\n"
|
||||
" \\cn none: show whole screen before every input.\n"
|
||||
" \\cm max: show only lines that have new nonblank characters.\n"
|
||||
" \\cs spans: like max, but emit a blank line between each span of\n"
|
||||
" screen lines shown.\n"
|
||||
" \\chN Hide top N lines (orthogonal to above modes).\n"
|
||||
" Misc Settings:\n"
|
||||
" \\sfX Set speed factor to X. (0 = never timeout automatically).\n"
|
||||
" \\mp Toggle use of MORE prompts\n"
|
||||
" \\ln Toggle display of line numbers.\n"
|
||||
" \\lt Toggle display of the line type identification chars.\n"
|
||||
" \\vb Toggle visual bell.\n"
|
||||
" \\pb Toggle display of picture outline boxes.\n"
|
||||
" (Toggle commands can be followed by a 1 or 0 to set value ON or OFF.)\n"
|
||||
" Character Escapes:\n"
|
||||
" \\\\ backslash \\# backspace \\[ escape \\_ return\n"
|
||||
" \\< \\> \\^ \\. cursor motion \\1 ..\\0 f1..f10\n"
|
||||
" \\D ..\\X Standard Frotz hotkeys. Use \\H (help) to see the list.\n"
|
||||
" Line Type Identification Characters:\n"
|
||||
" Input lines:\n"
|
||||
" untimed timed\n"
|
||||
" > T A regular line-oriented input\n"
|
||||
" ) t A single-character input\n"
|
||||
" } D A line input with some input before the cursor.\n"
|
||||
" (Use \\d to discard it.)\n"
|
||||
" Output lines:\n"
|
||||
" ] Output line that contains the cursor.\n"
|
||||
" . A blank line emitted as part of span compression.\n"
|
||||
" (blank) Any other output line.\n"
|
||||
;
|
||||
|
||||
static float speed = 1;
|
||||
static bool do_more_prompts = FALSE;
|
||||
|
||||
enum input_type {
|
||||
INPUT_CHAR,
|
||||
INPUT_LINE,
|
||||
INPUT_LINE_CONTINUED,
|
||||
};
|
||||
|
||||
/* get a character. Exit with no fuss on EOF. */
|
||||
static int xgetchar(void)
|
||||
{
|
||||
int c = getchar();
|
||||
if (c == EOF) {
|
||||
if (feof(stdin)) {
|
||||
fprintf(stderr, "\nEOT\n");
|
||||
exit(0);
|
||||
}
|
||||
os_fatal(strerror(errno));
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Read one line, including the newline, into s. Safely avoids buffer
|
||||
* overruns (but that's kind of pointless because there are several
|
||||
* other places where I'm not so careful). */
|
||||
static void getline_(char *s)
|
||||
{
|
||||
int c;
|
||||
char *p;
|
||||
fflush(stdout);
|
||||
p = s;
|
||||
while (p < s + INPUT_BUFFER_SIZE - 1)
|
||||
if ((*p++ = xgetchar()) == '\n') {
|
||||
*p = '\0';
|
||||
return;
|
||||
}
|
||||
p[-1] = '\n';
|
||||
p[0] = '\0';
|
||||
while ((c = xgetchar()) != '\n')
|
||||
;
|
||||
printf("Line too long, truncated to %s\n", s - INPUT_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
/* Translate in place all the escape characters in s. */
|
||||
static void translate_special_chars(char *s)
|
||||
{
|
||||
char *src = s, *dest = s;
|
||||
while (*src)
|
||||
switch(*src++) {
|
||||
default: *dest++ = src[-1]; break;
|
||||
case '\n': *dest++ = ZC_RETURN; break;
|
||||
case '\\':
|
||||
switch (*src++) {
|
||||
case '\n': *dest++ = ZC_RETURN; break;
|
||||
case '\\': *dest++ = '\\'; break;
|
||||
case '?': *dest++ = ZC_BACKSPACE; break;
|
||||
case '[': *dest++ = ZC_ESCAPE; break;
|
||||
case '_': *dest++ = ZC_RETURN; break;
|
||||
case '^': *dest++ = ZC_ARROW_UP; break;
|
||||
case '.': *dest++ = ZC_ARROW_DOWN; break;
|
||||
case '<': *dest++ = ZC_ARROW_LEFT; break;
|
||||
case '>': *dest++ = ZC_ARROW_RIGHT; break;
|
||||
case 'R': *dest++ = ZC_HKEY_RECORD; break;
|
||||
case 'P': *dest++ = ZC_HKEY_PLAYBACK; break;
|
||||
case 'S': *dest++ = ZC_HKEY_SEED; break;
|
||||
case 'U': *dest++ = ZC_HKEY_UNDO; break;
|
||||
case 'N': *dest++ = ZC_HKEY_RESTART; break;
|
||||
case 'X': *dest++ = ZC_HKEY_QUIT; break;
|
||||
case 'D': *dest++ = ZC_HKEY_DEBUG; break;
|
||||
case 'H': *dest++ = ZC_HKEY_HELP; break;
|
||||
case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
*dest++ = ZC_FKEY_MIN + src[-1] - '0' - 1; break;
|
||||
case '0': *dest++ = ZC_FKEY_MIN + 9; break;
|
||||
default:
|
||||
fprintf(stderr, "DUMB-FROTZ: unknown escape char: %c\n", src[-1]);
|
||||
fprintf(stderr, "Enter \\help to see the list\n");
|
||||
}
|
||||
}
|
||||
*dest = '\0';
|
||||
}
|
||||
|
||||
|
||||
/* The time in tenths of seconds that the user is ahead of z time. */
|
||||
static int time_ahead = 0;
|
||||
|
||||
/* Called from os_read_key and os_read_line if they have input from
|
||||
* a previous call to dumb_read_line.
|
||||
* Returns TRUE if we should timeout rather than use the read-ahead.
|
||||
* (because the user is further ahead than the timeout). */
|
||||
static bool check_timeout(int timeout)
|
||||
{
|
||||
if ((timeout == 0) || (timeout > time_ahead))
|
||||
time_ahead = 0;
|
||||
else
|
||||
time_ahead -= timeout;
|
||||
return time_ahead != 0;
|
||||
}
|
||||
|
||||
/* If val is '0' or '1', set *var accordingly, otherwise toggle it. */
|
||||
static void toggle(bool *var, char val)
|
||||
{
|
||||
*var = val == '1' || (val != '0' && !*var);
|
||||
}
|
||||
|
||||
/* Handle input-related user settings and call dumb_output_handle_setting. */
|
||||
bool dumb_handle_setting(const char *setting, bool show_cursor, bool startup)
|
||||
{
|
||||
if (!strncmp(setting, "sf", 2)) {
|
||||
speed = atof(&setting[2]);
|
||||
printf("Speed Factor %g\n", speed);
|
||||
} else if (!strncmp(setting, "mp", 2)) {
|
||||
toggle(&do_more_prompts, setting[2]);
|
||||
printf("More prompts %s\n", do_more_prompts ? "ON" : "OFF");
|
||||
} else {
|
||||
if (!strcmp(setting, "set")) {
|
||||
printf("Speed Factor %g\n", speed);
|
||||
printf("More Prompts %s\n", do_more_prompts ? "ON" : "OFF");
|
||||
}
|
||||
return dumb_output_handle_setting(setting, show_cursor, startup);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Read a line, processing commands (lines that start with a backslash
|
||||
* (that isn't the start of a special character)), and write the
|
||||
* first non-command to s.
|
||||
* Return true if timed-out. */
|
||||
static bool dumb_read_line(char *s, char *prompt, bool show_cursor,
|
||||
int timeout, enum input_type type,
|
||||
zchar *continued_line_chars)
|
||||
{
|
||||
time_t start_time;
|
||||
|
||||
if (timeout) {
|
||||
if (time_ahead >= timeout) {
|
||||
time_ahead -= timeout;
|
||||
return TRUE;
|
||||
}
|
||||
timeout -= time_ahead;
|
||||
start_time = time(0);
|
||||
}
|
||||
time_ahead = 0;
|
||||
|
||||
dumb_show_screen(show_cursor);
|
||||
for (;;) {
|
||||
char *command;
|
||||
if (prompt)
|
||||
fputs(prompt, stdout);
|
||||
else
|
||||
dumb_show_prompt(show_cursor, (timeout ? "tTD" : ")>}")[type]);
|
||||
getline_(s);
|
||||
if ((s[0] != '\\') || ((s[1] != '\0') && !islower(s[1]))) {
|
||||
/* Is not a command line. */
|
||||
translate_special_chars(s);
|
||||
if (timeout) {
|
||||
int elapsed = (time(0) - start_time) * 10 * speed;
|
||||
if (elapsed > timeout) {
|
||||
time_ahead = elapsed - timeout;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
/* Commands. */
|
||||
|
||||
/* Remove the \ and the terminating newline. */
|
||||
command = s + 1;
|
||||
command[strlen(command) - 1] = '\0';
|
||||
|
||||
if (!strcmp(command, "t")) {
|
||||
if (timeout) {
|
||||
time_ahead = 0;
|
||||
s[0] = '\0';
|
||||
return TRUE;
|
||||
}
|
||||
} else if (*command == 'w') {
|
||||
if (timeout) {
|
||||
int elapsed = atoi(&command[1]);
|
||||
time_t now = time(0);
|
||||
if (elapsed == 0)
|
||||
elapsed = (now - start_time) * 10 * speed;
|
||||
if (elapsed >= timeout) {
|
||||
time_ahead = elapsed - timeout;
|
||||
s[0] = '\0';
|
||||
return TRUE;
|
||||
}
|
||||
timeout -= elapsed;
|
||||
start_time = now;
|
||||
}
|
||||
} else if (!strcmp(command, "d")) {
|
||||
if (type != INPUT_LINE_CONTINUED)
|
||||
fprintf(stderr, "DUMB-FROTZ: No input to discard\n");
|
||||
else {
|
||||
dumb_discard_old_input(strlen(continued_line_chars));
|
||||
continued_line_chars[0] = '\0';
|
||||
type = INPUT_LINE;
|
||||
}
|
||||
} else if (!strcmp(command, "help")) {
|
||||
if (!do_more_prompts)
|
||||
fputs(runtime_usage, stdout);
|
||||
else {
|
||||
char *current_page, *next_page;
|
||||
current_page = next_page = runtime_usage;
|
||||
for (;;) {
|
||||
int i;
|
||||
for (i = 0; (i < h_screen_rows - 2) && *next_page; i++)
|
||||
next_page = strchr(next_page, '\n') + 1;
|
||||
printf("%.*s", next_page - current_page, current_page);
|
||||
current_page = next_page;
|
||||
if (!*current_page)
|
||||
break;
|
||||
printf("HELP: Type <return> for more, or q <return> to stop: ");
|
||||
getline_(s);
|
||||
if (!strcmp(s, "q\n"))
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (!strcmp(command, "s")) {
|
||||
dumb_dump_screen();
|
||||
} else if (!dumb_handle_setting(command, show_cursor, FALSE)) {
|
||||
fprintf(stderr, "DUMB-FROTZ: unknown command: %s\n", s);
|
||||
fprintf(stderr, "Enter \\help to see the list of commands\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Read a line that is not part of z-machine input (more prompts and
|
||||
* filename requests). */
|
||||
static void dumb_read_misc_line(char *s, char *prompt)
|
||||
{
|
||||
dumb_read_line(s, prompt, 0, 0, 0, 0);
|
||||
/* Remove terminating newline */
|
||||
s[strlen(s) - 1] = '\0';
|
||||
}
|
||||
|
||||
/* For allowing the user to input in a single line keys to be returned
|
||||
* for several consecutive calls to read_char, with no screen update
|
||||
* in between. Useful for traversing menus. */
|
||||
static char read_key_buffer[INPUT_BUFFER_SIZE];
|
||||
|
||||
/* Similar. Useful for using function key abbreviations. */
|
||||
static char read_line_buffer[INPUT_BUFFER_SIZE];
|
||||
|
||||
zchar os_read_key (int timeout, bool show_cursor)
|
||||
{
|
||||
char c;
|
||||
int timed_out;
|
||||
|
||||
/* Discard any keys read for line input. */
|
||||
read_line_buffer[0] = '\0';
|
||||
|
||||
if (read_key_buffer[0] == '\0') {
|
||||
timed_out = dumb_read_line(read_key_buffer, NULL, show_cursor, timeout,
|
||||
INPUT_CHAR, NULL);
|
||||
/* An empty input line is reported as a single CR.
|
||||
* If there's anything else in the line, we report only the line's
|
||||
* contents and not the terminating CR. */
|
||||
if (strlen(read_key_buffer) > 1)
|
||||
read_key_buffer[strlen(read_key_buffer) - 1] = '\0';
|
||||
} else
|
||||
timed_out = check_timeout(timeout);
|
||||
|
||||
if (timed_out)
|
||||
return ZC_TIME_OUT;
|
||||
|
||||
c = read_key_buffer[0];
|
||||
memmove(read_key_buffer, read_key_buffer + 1, strlen(read_key_buffer));
|
||||
|
||||
/* TODO: error messages for invalid special chars. */
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
zchar os_read_line (int max, zchar *buf, int timeout, int width, int continued)
|
||||
{
|
||||
char *p;
|
||||
int terminator;
|
||||
static bool timed_out_last_time;
|
||||
int timed_out;
|
||||
|
||||
/* Discard any keys read for single key input. */
|
||||
read_key_buffer[0] = '\0';
|
||||
|
||||
/* After timing out, discard any further input unless we're continuing. */
|
||||
if (timed_out_last_time && !continued)
|
||||
read_line_buffer[0] = '\0';
|
||||
|
||||
if (read_line_buffer[0] == '\0')
|
||||
timed_out = dumb_read_line(read_line_buffer, NULL, TRUE, timeout,
|
||||
buf[0] ? INPUT_LINE_CONTINUED : INPUT_LINE,
|
||||
buf);
|
||||
else
|
||||
timed_out = check_timeout(timeout);
|
||||
|
||||
if (timed_out) {
|
||||
timed_out_last_time = TRUE;
|
||||
return ZC_TIME_OUT;
|
||||
}
|
||||
|
||||
/* find the terminating character. */
|
||||
for (p = read_line_buffer;; p++) {
|
||||
if (is_terminator(*p)) {
|
||||
terminator = *p;
|
||||
*p++ = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Truncate to width and max. */
|
||||
|
||||
/* copy to screen */
|
||||
dumb_display_user_input(read_line_buffer);
|
||||
|
||||
/* copy to the buffer and save the rest for next time. */
|
||||
strcat(buf, read_line_buffer);
|
||||
p = read_line_buffer + strlen(read_line_buffer) + 1;
|
||||
memmove(read_line_buffer, p, strlen(p) + 1);
|
||||
|
||||
/* If there was just a newline after the terminating character,
|
||||
* don't save it. */
|
||||
if ((read_line_buffer[0] == '\r') && (read_line_buffer[1] == '\0'))
|
||||
read_line_buffer[0] = '\0';
|
||||
|
||||
timed_out_last_time = FALSE;
|
||||
return terminator;
|
||||
}
|
||||
|
||||
int os_read_file_name (char *file_name, const char *default_name, int flag)
|
||||
{
|
||||
char buf[INPUT_BUFFER_SIZE], prompt[INPUT_BUFFER_SIZE];
|
||||
FILE *fp;
|
||||
|
||||
sprintf(prompt, "Please enter a filename [%s]: ", default_name);
|
||||
dumb_read_misc_line(buf, prompt);
|
||||
if (strlen(buf) > MAX_FILE_NAME) {
|
||||
printf("Filename too long\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
strcpy (file_name, buf[0] ? buf : default_name);
|
||||
|
||||
/* Warn if overwriting a file. */
|
||||
// if ((flag == FILE_SAVE || flag == FILE_SAVE_AUX || flag == FILE_RECORD)
|
||||
// && ((fp = fopen(file_name, "rb")) != NULL)) {
|
||||
// fclose (fp);
|
||||
// dumb_read_misc_line(buf, "Overwrite existing file? ");
|
||||
// return(tolower(buf[0]) == 'y');
|
||||
// }
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void os_more_prompt (void)
|
||||
{
|
||||
if (do_more_prompts) {
|
||||
char buf[INPUT_BUFFER_SIZE];
|
||||
dumb_read_misc_line(buf, "***MORE***");
|
||||
} else
|
||||
dumb_elide_more_prompt();
|
||||
}
|
||||
|
||||
void dumb_init_input(void)
|
||||
{
|
||||
if ((h_version >= V4) && (speed != 0))
|
||||
h_config |= CONFIG_TIMEDINPUT;
|
||||
|
||||
if (h_version >= V5)
|
||||
h_flags &= ~(MOUSE_FLAG | MENU_FLAG);
|
||||
}
|
||||
|
||||
zword os_read_mouse(void)
|
||||
{
|
||||
/* NOT IMPLEMENTED */
|
||||
}
|
|
@ -1,535 +0,0 @@
|
|||
/* dumb-output.c
|
||||
* $Id: dumb-output.c,v 1.2 2002/03/26 22:52:31 feedle Exp $
|
||||
*
|
||||
* Copyright 1997,1998 Alfresco Petrofsky <alfresco@petrofsky.berkeley.edu>.
|
||||
* Any use permitted provided this notice stays intact.
|
||||
*/
|
||||
|
||||
#include "dumb_frotz.h"
|
||||
|
||||
f_setup_t f_setup;
|
||||
|
||||
static bool show_line_numbers = FALSE;
|
||||
static bool show_line_types = -1;
|
||||
static bool show_pictures = TRUE;
|
||||
static bool visual_bell = TRUE;
|
||||
static bool plain_ascii = FALSE;
|
||||
|
||||
static char latin1_to_ascii[] =
|
||||
" ! c L >o< Y | S '' C a << not - R _ "
|
||||
"^0 +/- ^2 ^3 ' my P . , ^1 o >> 1/4 1/2 3/4 ? "
|
||||
"A A A A Ae A AE C E E E E I I I I "
|
||||
"Th N O O O O Oe * O U U U Ue Y Th ss "
|
||||
"a a a a ae a ae c e e e e i i i i "
|
||||
"th n o o o o oe : o u u u ue y th y "
|
||||
;
|
||||
|
||||
/* h_screen_rows * h_screen_cols */
|
||||
static int screen_cells;
|
||||
|
||||
/* The in-memory state of the screen. */
|
||||
/* Each cell contains a style in the upper byte and a char in the lower. */
|
||||
typedef unsigned short cell;
|
||||
static cell *screen_data;
|
||||
|
||||
static cell make_cell(int style, char c) {return (style << 8) | (0xff & c);}
|
||||
static char cell_char(cell c) {return c & 0xff;}
|
||||
static int cell_style(cell c) {return c >> 8;}
|
||||
|
||||
|
||||
/* A cell's style is REVERSE_STYLE, normal (0), or PICTURE_STYLE.
|
||||
* PICTURE_STYLE means the character is part of an ascii image outline
|
||||
* box. (This just buys us the ability to turn box display on and off
|
||||
* with immediate effect. No, not very useful, but I wanted to give
|
||||
* the rv bit some company in that huge byte I allocated for it.) */
|
||||
#define PICTURE_STYLE 16
|
||||
|
||||
static int current_style = 0;
|
||||
|
||||
/* Which cells have changed (1 byte per cell). */
|
||||
static char *screen_changes;
|
||||
|
||||
static int cursor_row = 0, cursor_col = 0;
|
||||
|
||||
/* Compression styles. */
|
||||
static enum {
|
||||
COMPRESSION_NONE, COMPRESSION_SPANS, COMPRESSION_MAX,
|
||||
} compression_mode = COMPRESSION_SPANS;
|
||||
static char *compression_names[] = {"NONE", "SPANS", "MAX"};
|
||||
static int hide_lines = 0;
|
||||
|
||||
/* Reverse-video display styles. */
|
||||
static enum {
|
||||
RV_NONE, RV_DOUBLESTRIKE, RV_UNDERLINE, RV_CAPS,
|
||||
} rv_mode = RV_NONE;
|
||||
static char *rv_names[] = {"NONE", "DOUBLESTRIKE", "UNDERLINE", "CAPS"};
|
||||
static char rv_blank_char = ' ';
|
||||
|
||||
static cell *dumb_row(int r) {return screen_data + r * h_screen_cols;}
|
||||
|
||||
static char *dumb_changes_row(int r)
|
||||
{
|
||||
return screen_changes + r * h_screen_cols;
|
||||
}
|
||||
|
||||
int os_char_width (zchar z)
|
||||
{
|
||||
if (plain_ascii && z >= ZC_LATIN1_MIN && z <= ZC_LATIN1_MAX) {
|
||||
char *p = latin1_to_ascii + 4 * (z - ZC_LATIN1_MIN);
|
||||
return strchr(p, ' ') - p;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int os_string_width (const zchar *s)
|
||||
{
|
||||
int width = 0;
|
||||
zchar c;
|
||||
|
||||
while ((c = *s++) != 0)
|
||||
if (c == ZC_NEW_STYLE || c == ZC_NEW_FONT)
|
||||
s++;
|
||||
else
|
||||
width += os_char_width(c);
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
void os_set_cursor(int row, int col)
|
||||
{
|
||||
cursor_row = row - 1; cursor_col = col - 1;
|
||||
if (cursor_row >= h_screen_rows)
|
||||
cursor_row = h_screen_rows - 1;
|
||||
}
|
||||
|
||||
/* Set a cell and update screen_changes. */
|
||||
static void dumb_set_cell(int row, int col, cell c)
|
||||
{
|
||||
dumb_changes_row(row)[col] = (c != dumb_row(row)[col]);
|
||||
dumb_row(row)[col] = c;
|
||||
}
|
||||
|
||||
void dumb_set_picture_cell(int row, int col, char c)
|
||||
{
|
||||
dumb_set_cell(row, col, make_cell(PICTURE_STYLE, c));
|
||||
}
|
||||
|
||||
/* Copy a cell and copy its changedness state.
|
||||
* This is used for scrolling. */
|
||||
static void dumb_copy_cell(int dest_row, int dest_col,
|
||||
int src_row, int src_col)
|
||||
{
|
||||
dumb_row(dest_row)[dest_col] = dumb_row(src_row)[src_col];
|
||||
dumb_changes_row(dest_row)[dest_col] = dumb_changes_row(src_row)[src_col];
|
||||
}
|
||||
|
||||
void os_set_text_style(int x)
|
||||
{
|
||||
current_style = x & REVERSE_STYLE;
|
||||
}
|
||||
|
||||
/* put a character in the cell at the cursor and advance the cursor. */
|
||||
static void dumb_display_char(char c)
|
||||
{
|
||||
dumb_set_cell(cursor_row, cursor_col, make_cell(current_style, c));
|
||||
if (++cursor_col == h_screen_cols)
|
||||
if (cursor_row == h_screen_rows - 1)
|
||||
cursor_col--;
|
||||
else {
|
||||
cursor_row++;
|
||||
cursor_col = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void dumb_display_user_input(char *s)
|
||||
{
|
||||
/* copy to screen without marking it as a change. */
|
||||
while (*s)
|
||||
dumb_row(cursor_row)[cursor_col++] = make_cell(0, *s++);
|
||||
}
|
||||
|
||||
void dumb_discard_old_input(int num_chars)
|
||||
{
|
||||
/* Weird discard stuff. Grep spec for 'pain in my butt'. */
|
||||
/* The old characters should be on the screen just before the cursor.
|
||||
* Erase them. */
|
||||
cursor_col -= num_chars;
|
||||
if (cursor_col < 0)
|
||||
cursor_col = 0;
|
||||
os_erase_area(cursor_row + 1, cursor_col + 1,
|
||||
cursor_row + 1, cursor_col + num_chars);
|
||||
}
|
||||
|
||||
void os_display_char (zchar c)
|
||||
{
|
||||
if (c >= ZC_LATIN1_MIN && c <= ZC_LATIN1_MAX) {
|
||||
if (plain_ascii) {
|
||||
char *ptr = latin1_to_ascii + 4 * (c - ZC_LATIN1_MIN);
|
||||
do
|
||||
dumb_display_char(*ptr++);
|
||||
while (*ptr != ' ');
|
||||
} else
|
||||
dumb_display_char(c);
|
||||
} else if (c >= 32 && c <= 126) {
|
||||
dumb_display_char(c);
|
||||
} else if (c == ZC_GAP) {
|
||||
dumb_display_char(' '); dumb_display_char(' ');
|
||||
} else if (c == ZC_INDENT) {
|
||||
dumb_display_char(' '); dumb_display_char(' '); dumb_display_char(' ');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Haxor your boxor? */
|
||||
void os_display_string (const zchar *s)
|
||||
{
|
||||
zchar c;
|
||||
|
||||
while ((c = *s++) != 0)
|
||||
if (c == ZC_NEW_FONT)
|
||||
s++;
|
||||
else if (c == ZC_NEW_STYLE)
|
||||
os_set_text_style(*s++);
|
||||
else {
|
||||
os_display_char (c);
|
||||
}
|
||||
}
|
||||
|
||||
void os_erase_area (int top, int left, int bottom, int right)
|
||||
{
|
||||
int row, col;
|
||||
top--; left--; bottom--; right--;
|
||||
for (row = top; row <= bottom; row++)
|
||||
for (col = left; col <= right; col++)
|
||||
dumb_set_cell(row, col, make_cell(current_style, ' '));
|
||||
}
|
||||
|
||||
void os_scroll_area (int top, int left, int bottom, int right, int units)
|
||||
{
|
||||
int row, col;
|
||||
top--; left--; bottom--; right--;
|
||||
if (units > 0) {
|
||||
for (row = top; row <= bottom - units; row++)
|
||||
for (col = left; col <= right; col++)
|
||||
dumb_copy_cell(row, col, row + units, col);
|
||||
os_erase_area(bottom - units + 2, left + 1, bottom + 1, right + 1);
|
||||
} else if (units < 0) {
|
||||
for (row = bottom; row >= top - units; row--)
|
||||
for (col = left; col <= right; col++)
|
||||
dumb_copy_cell(row, col, row + units, col);
|
||||
os_erase_area(top + 1, left + 1, top - units, right + 1);
|
||||
}
|
||||
}
|
||||
|
||||
int os_font_data(int font, int *height, int *width)
|
||||
{
|
||||
if (font == TEXT_FONT) {
|
||||
*height = 1; *width = 1; return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void os_set_colour (int x, int y) {}
|
||||
void os_set_font (int x) {}
|
||||
|
||||
/* Print a cell to stdout. */
|
||||
static void show_cell(cell cel)
|
||||
{
|
||||
char c = cell_char(cel);
|
||||
switch (cell_style(cel)) {
|
||||
case 0:
|
||||
putchar(c);
|
||||
break;
|
||||
case PICTURE_STYLE:
|
||||
putchar(show_pictures ? c : ' ');
|
||||
break;
|
||||
case REVERSE_STYLE:
|
||||
if (c == ' ')
|
||||
putchar(rv_blank_char);
|
||||
else
|
||||
switch (rv_mode) {
|
||||
case RV_NONE: putchar(c); break;
|
||||
case RV_CAPS: putchar(toupper(c)); break;
|
||||
case RV_UNDERLINE: putchar('_'); putchar('\b'); putchar(c); break;
|
||||
case RV_DOUBLESTRIKE: putchar(c); putchar('\b'); putchar(c); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool will_print_blank(cell c)
|
||||
{
|
||||
return (((cell_style(c) == PICTURE_STYLE) && !show_pictures)
|
||||
|| ((cell_char(c) == ' ')
|
||||
&& ((cell_style(c) != REVERSE_STYLE) || (rv_blank_char == ' '))));
|
||||
}
|
||||
|
||||
static void show_line_prefix(int row, char c)
|
||||
{
|
||||
if (show_line_numbers)
|
||||
printf((row == -1) ? ".." : "%02d", (row + 1) % 100);
|
||||
if (show_line_types)
|
||||
putchar(c);
|
||||
/* Add a separator char (unless there's nothing to separate). */
|
||||
if (show_line_numbers || show_line_types)
|
||||
putchar(' ');
|
||||
}
|
||||
|
||||
/* Print a row to stdout. */
|
||||
static void show_row(int r)
|
||||
{
|
||||
if (r == -1) {
|
||||
show_line_prefix(-1, '.');
|
||||
} else {
|
||||
int c, last;
|
||||
show_line_prefix(r, (r == cursor_row) ? ']' : ' ');
|
||||
/* Don't print spaces at end of line. */
|
||||
/* (Saves bandwidth and printhead wear.) */
|
||||
/* TODO: compress spaces to tabs. */
|
||||
for (last = h_screen_cols - 1; last >= 0; last--)
|
||||
if (!will_print_blank(dumb_row(r)[last]))
|
||||
break;
|
||||
for (c = 0; c <= last; c++)
|
||||
show_cell(dumb_row(r)[c]);
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
/* Print the part of the cursor row before the cursor. */
|
||||
void dumb_show_prompt(bool show_cursor, char line_type)
|
||||
{
|
||||
int i;
|
||||
show_line_prefix(show_cursor ? cursor_row : -1, line_type);
|
||||
if (show_cursor)
|
||||
for (i = 0; i < cursor_col; i++)
|
||||
show_cell(dumb_row(cursor_row)[i]);
|
||||
}
|
||||
|
||||
static void mark_all_unchanged(void)
|
||||
{
|
||||
memset(screen_changes, 0, screen_cells);
|
||||
}
|
||||
|
||||
/* Check if a cell is a blank or will display as one.
|
||||
* (Used to help decide if contents are worth printing.) */
|
||||
static bool is_blank(cell c)
|
||||
{
|
||||
return ((cell_char(c) == ' ')
|
||||
|| ((cell_style(c) == PICTURE_STYLE) && !show_pictures));
|
||||
}
|
||||
|
||||
/* Show the current screen contents, or what's changed since the last
|
||||
* call.
|
||||
*
|
||||
* If compressing, and show_cursor is true, and the cursor is past the
|
||||
* last nonblank character on the last line that would be shown, then
|
||||
* don't show that line (because it will be redundant with the prompt
|
||||
* line just below it). */
|
||||
void dumb_show_screen(bool show_cursor)
|
||||
{
|
||||
int r, c, first, last;
|
||||
char changed_rows[0x100];
|
||||
|
||||
/* Easy case */
|
||||
if (compression_mode == COMPRESSION_NONE) {
|
||||
for (r = hide_lines; r < h_screen_rows; r++)
|
||||
show_row(r);
|
||||
mark_all_unchanged();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check which rows changed, and where the first and last change is. */
|
||||
first = last = -1;
|
||||
memset(changed_rows, 0, h_screen_rows);
|
||||
for (r = hide_lines; r < h_screen_rows; r++) {
|
||||
for (c = 0; c < h_screen_cols; c++)
|
||||
if (dumb_changes_row(r)[c] && !is_blank(dumb_row(r)[c]))
|
||||
break;
|
||||
changed_rows[r] = (c != h_screen_cols);
|
||||
if (changed_rows[r]) {
|
||||
first = (first != -1) ? first : r;
|
||||
last = r;
|
||||
}
|
||||
}
|
||||
|
||||
if (first == -1)
|
||||
return;
|
||||
|
||||
/* The show_cursor rule described above */
|
||||
if (show_cursor && (cursor_row == last)) {
|
||||
for (c = cursor_col; c < h_screen_cols; c++)
|
||||
if (!is_blank(dumb_row(last)[c]))
|
||||
break;
|
||||
if (c == h_screen_cols)
|
||||
last--;
|
||||
}
|
||||
|
||||
/* Display the appropriate rows. */
|
||||
if (compression_mode == COMPRESSION_MAX) {
|
||||
for (r = first; r <= last; r++)
|
||||
if (changed_rows[r])
|
||||
show_row(r);
|
||||
} else {
|
||||
/* COMPRESSION_SPANS */
|
||||
for (r = first; r <= last; r++) {
|
||||
if (changed_rows[r] || changed_rows[r + 1])
|
||||
show_row(r);
|
||||
else {
|
||||
while (!changed_rows[r + 1])
|
||||
r++;
|
||||
show_row(-1);
|
||||
}
|
||||
}
|
||||
if (show_cursor && (cursor_row > last + 1))
|
||||
show_row((cursor_row == last + 2) ? (last + 1) : -1);
|
||||
}
|
||||
|
||||
mark_all_unchanged();
|
||||
}
|
||||
|
||||
/* Unconditionally show whole screen. For \s user command. */
|
||||
void dumb_dump_screen(void)
|
||||
{
|
||||
int r;
|
||||
for (r = 0; r < h_screen_height; r++)
|
||||
show_row(r);
|
||||
}
|
||||
|
||||
/* Called when it's time for a more prompt but user has them turned off. */
|
||||
void dumb_elide_more_prompt(void)
|
||||
{
|
||||
dumb_show_screen(FALSE);
|
||||
if (compression_mode == COMPRESSION_SPANS && hide_lines == 0) {
|
||||
show_row(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void os_reset_screen(void)
|
||||
{
|
||||
dumb_show_screen(FALSE);
|
||||
}
|
||||
|
||||
void os_beep (int volume)
|
||||
{
|
||||
if (visual_bell)
|
||||
printf("[%s-PITCHED BEEP]\n", (volume == 1) ? "HIGH" : "LOW");
|
||||
else
|
||||
putchar('\a'); /* so much for dumb. */
|
||||
}
|
||||
|
||||
|
||||
/* To make the common code happy */
|
||||
|
||||
void os_prepare_sample (int a) {}
|
||||
void os_finish_with_sample (int a) {}
|
||||
void os_start_sample (int a, int b, int c, zword d) {}
|
||||
void os_stop_sample (int a) {}
|
||||
|
||||
|
||||
/* if val is '0' or '1', set *var accordingly, else toggle it. */
|
||||
static void toggle(bool *var, char val)
|
||||
{
|
||||
*var = val == '1' || (val != '0' && !*var);
|
||||
}
|
||||
|
||||
bool dumb_output_handle_setting(const char *setting, bool show_cursor,
|
||||
bool startup)
|
||||
{
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
if (!strncmp(setting, "pb", 2)) {
|
||||
toggle(&show_pictures, setting[2]);
|
||||
printf("Picture outlines display %s\n", show_pictures ? "ON" : "OFF");
|
||||
if (startup)
|
||||
return TRUE;
|
||||
for (i = 0; i < screen_cells; i++)
|
||||
screen_changes[i] = (cell_style(screen_data[i]) == PICTURE_STYLE);
|
||||
dumb_show_screen(show_cursor);
|
||||
|
||||
} else if (!strncmp(setting, "vb", 2)) {
|
||||
toggle(&visual_bell, setting[2]);
|
||||
printf("Visual bell %s\n", visual_bell ? "ON" : "OFF");
|
||||
os_beep(1); os_beep(2);
|
||||
|
||||
} else if (!strncmp(setting, "ln", 2)) {
|
||||
toggle(&show_line_numbers, setting[2]);
|
||||
printf("Line numbering %s\n", show_line_numbers ? "ON" : "OFF");
|
||||
|
||||
} else if (!strncmp(setting, "lt", 2)) {
|
||||
toggle(&show_line_types, setting[2]);
|
||||
printf("Line-type display %s\n", show_line_types ? "ON" : "OFF");
|
||||
|
||||
} else if (*setting == 'c') {
|
||||
switch (setting[1]) {
|
||||
case 'm': compression_mode = COMPRESSION_MAX; break;
|
||||
case 's': compression_mode = COMPRESSION_SPANS; break;
|
||||
case 'n': compression_mode = COMPRESSION_NONE; break;
|
||||
case 'h': hide_lines = atoi(&setting[2]); break;
|
||||
default: return FALSE;
|
||||
}
|
||||
printf("Compression mode %s, hiding top %d lines\n",
|
||||
compression_names[compression_mode], hide_lines);
|
||||
|
||||
} else if (*setting == 'r') {
|
||||
switch (setting[1]) {
|
||||
case 'n': rv_mode = RV_NONE; break;
|
||||
case 'o': rv_mode = RV_DOUBLESTRIKE; break;
|
||||
case 'u': rv_mode = RV_UNDERLINE; break;
|
||||
case 'c': rv_mode = RV_CAPS; break;
|
||||
case 'b': rv_blank_char = setting[2] ? setting[2] : ' '; break;
|
||||
default: return FALSE;
|
||||
}
|
||||
printf("Reverse-video mode %s, blanks reverse to '%c': ",
|
||||
rv_names[rv_mode], rv_blank_char);
|
||||
for (p = "sample reverse text"; *p; p++)
|
||||
show_cell(make_cell(REVERSE_STYLE, *p));
|
||||
putchar('\n');
|
||||
for (i = 0; i < screen_cells; i++)
|
||||
screen_changes[i] = (cell_style(screen_data[i]) == REVERSE_STYLE);
|
||||
dumb_show_screen(show_cursor);
|
||||
|
||||
} else if (!strcmp(setting, "set")) {
|
||||
printf("Compression Mode %s, hiding top %d lines\n",
|
||||
compression_names[compression_mode], hide_lines);
|
||||
printf("Picture Boxes display %s\n", show_pictures ? "ON" : "OFF");
|
||||
printf("Visual Bell %s\n", visual_bell ? "ON" : "OFF");
|
||||
os_beep(1); os_beep(2);
|
||||
printf("Line Numbering %s\n", show_line_numbers ? "ON" : "OFF");
|
||||
printf("Line-Type display %s\n", show_line_types ? "ON" : "OFF");
|
||||
printf("Reverse-Video mode %s, Blanks reverse to '%c': ",
|
||||
rv_names[rv_mode], rv_blank_char);
|
||||
for (p = "sample reverse text"; *p; p++)
|
||||
show_cell(make_cell(REVERSE_STYLE, *p));
|
||||
putchar('\n');
|
||||
} else
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void dumb_init_output(void)
|
||||
{
|
||||
if (h_version == V3) {
|
||||
h_config |= CONFIG_SPLITSCREEN;
|
||||
h_flags &= ~OLD_SOUND_FLAG;
|
||||
}
|
||||
|
||||
if (h_version >= V5) {
|
||||
h_flags &= ~SOUND_FLAG;
|
||||
}
|
||||
|
||||
h_screen_height = h_screen_rows;
|
||||
h_screen_width = h_screen_cols;
|
||||
screen_cells = h_screen_rows * h_screen_cols;
|
||||
|
||||
h_font_width = 1; h_font_height = 1;
|
||||
|
||||
if (show_line_types == -1)
|
||||
show_line_types = h_version > 3;
|
||||
|
||||
screen_data = malloc(screen_cells * sizeof(cell));
|
||||
screen_changes = malloc(screen_cells);
|
||||
os_erase_area(1, 1, h_screen_rows, h_screen_cols);
|
||||
memset(screen_changes, 0, screen_cells);
|
||||
}
|
|
@ -1,153 +0,0 @@
|
|||
/* dumb-pic.c
|
||||
* $Id: dumb-pic.c,v 1.1.1.1 2002/03/26 22:38:34 feedle Exp $
|
||||
*
|
||||
* Copyright 1997,1998 Alcibiades Petrofsky
|
||||
* <alcibiades@petrofsky.berkeley.ca.us>.
|
||||
* Any use permitted provided this notice stays intact.
|
||||
*/
|
||||
#include "dumb_frotz.h"
|
||||
|
||||
f_setup_t f_setup;
|
||||
|
||||
#define PIC_FILE_HEADER_FLAGS 1
|
||||
#define PIC_FILE_HEADER_NUM_IMAGES 4
|
||||
#define PIC_FILE_HEADER_ENTRY_SIZE 8
|
||||
#define PIC_FILE_HEADER_VERSION 14
|
||||
|
||||
#define PIC_HEADER_NUMBER 0
|
||||
#define PIC_HEADER_WIDTH 2
|
||||
#define PIC_HEADER_HEIGHT 4
|
||||
|
||||
static struct {
|
||||
int z_num;
|
||||
int width;
|
||||
int height;
|
||||
int orig_width;
|
||||
int orig_height;
|
||||
} *pict_info;
|
||||
static int num_pictures = 0;
|
||||
|
||||
static unsigned char lookupb(unsigned char *p, int n) {return p[n];}
|
||||
static unsigned short lookupw(unsigned char *p, int n)
|
||||
{
|
||||
return (p[n + 1] << 8) | p[n];
|
||||
}
|
||||
|
||||
void dumb_init_pictures (char *filename)
|
||||
{
|
||||
FILE *file = NULL;
|
||||
int success = FALSE;
|
||||
unsigned char gheader[16];
|
||||
unsigned char *raw_info = NULL;
|
||||
int i, entry_size, flags;
|
||||
float x_scaler, y_scaler;
|
||||
|
||||
do {
|
||||
if ((h_version != V6)
|
||||
|| !filename
|
||||
|| ((file = fopen (filename, "rb")) == NULL)
|
||||
|| (fread(&gheader, sizeof (gheader), 1, file) != 1))
|
||||
break;
|
||||
|
||||
num_pictures = lookupw(gheader, PIC_FILE_HEADER_NUM_IMAGES);
|
||||
entry_size = lookupb(gheader, PIC_FILE_HEADER_ENTRY_SIZE);
|
||||
flags = lookupb(gheader, PIC_FILE_HEADER_FLAGS);
|
||||
|
||||
raw_info = malloc(num_pictures * entry_size);
|
||||
|
||||
if (fread(raw_info, num_pictures * entry_size, 1, file) != 1)
|
||||
break;
|
||||
|
||||
pict_info = malloc((num_pictures + 1) * sizeof(*pict_info));
|
||||
pict_info[0].z_num = 0;
|
||||
pict_info[0].height = num_pictures;
|
||||
pict_info[0].width = lookupw(gheader, PIC_FILE_HEADER_VERSION);
|
||||
|
||||
y_scaler = h_screen_rows / 200.0;
|
||||
x_scaler = h_screen_cols / ((flags & 0x08) ? 640.0 : 320.0);
|
||||
|
||||
/* Copy and scale. */
|
||||
for (i = 1; i <= num_pictures; i++) {
|
||||
unsigned char *p = raw_info + entry_size * (i - 1);
|
||||
pict_info[i].z_num = lookupw(p, PIC_HEADER_NUMBER);
|
||||
pict_info[i].orig_height = lookupw(p, PIC_HEADER_HEIGHT);
|
||||
pict_info[i].orig_width = lookupw(p, PIC_HEADER_WIDTH);
|
||||
pict_info[i].height = pict_info[i].orig_height * y_scaler + .5;
|
||||
pict_info[i].width = pict_info[i].orig_width * x_scaler + .5;
|
||||
}
|
||||
success = TRUE;
|
||||
} while (0);
|
||||
if (file)
|
||||
fclose(file);
|
||||
if (raw_info)
|
||||
free(raw_info);
|
||||
if (success)
|
||||
h_config |= CONFIG_PICTURES;
|
||||
else
|
||||
{
|
||||
h_flags &= ~GRAPHICS_FLAG;
|
||||
if (filename)
|
||||
fprintf(stderr, "Warning: could not read graphics file %s\n", filename);
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert a Z picture number to an index into pict_info. */
|
||||
static int z_num_to_index(int n)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i <= num_pictures; i++)
|
||||
if (pict_info[i].z_num == n)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool os_picture_data(int num, int *height, int *width)
|
||||
{
|
||||
int index;
|
||||
|
||||
*height = 0;
|
||||
*width = 0;
|
||||
|
||||
if (!pict_info)
|
||||
return FALSE;
|
||||
|
||||
if ((index = z_num_to_index(num)) == -1)
|
||||
return FALSE;
|
||||
|
||||
*height = pict_info[index].height;
|
||||
*width = pict_info[index].width;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void os_draw_picture (int num, int row, int col)
|
||||
{
|
||||
int width, height, r, c;
|
||||
if (!os_picture_data(num, &height, &width) || !width || !height)
|
||||
return;
|
||||
col--, row--;
|
||||
/* Draw corners */
|
||||
dumb_set_picture_cell(row, col, '+');
|
||||
dumb_set_picture_cell(row, col + width - 1, '+');
|
||||
dumb_set_picture_cell(row + height - 1, col, '+');
|
||||
dumb_set_picture_cell(row + height - 1, col + width - 1, '+');
|
||||
/* sides */
|
||||
for (c = col + 1; c < col + width - 1; c++) {
|
||||
dumb_set_picture_cell(row, c, '-');
|
||||
dumb_set_picture_cell(row + height - 1, c, '-');
|
||||
}
|
||||
for (r = row + 1; r < row + height - 1; r++) {
|
||||
dumb_set_picture_cell(r, col, '|');
|
||||
dumb_set_picture_cell(r, col + width - 1, '|');
|
||||
}
|
||||
/* body, but for last line */
|
||||
for (r = row + 1; r < row + height - 2; r++)
|
||||
for (c = col + 1; c < col + width - 1; c++)
|
||||
dumb_set_picture_cell(r, c, ':');
|
||||
/* Last line of body, including picture number. */
|
||||
if (height >= 3)
|
||||
for (c = col + width - 2; c > col; c--, (num /= 10))
|
||||
dumb_set_picture_cell(row + height - 2, c, num ? (num % 10 + '0') : ':');
|
||||
}
|
||||
|
||||
int os_peek_colour (void) {return BLACK_COLOUR; }
|
|
@ -1,358 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008-2009 J-P Nurmi jpnurmi@gmail.com
|
||||
*
|
||||
* This example is free, and not covered by LGPL license. There is no
|
||||
* restriction applied to their modification, redistribution, using and so on.
|
||||
* You can study them, modify them, use them in your own program - either
|
||||
* completely or partially. By using it you may give me some credits in your
|
||||
* program, but you don't have to.
|
||||
*/
|
||||
|
||||
#include "transport/Config.h"
|
||||
#include "transport/NetworkPlugin.h"
|
||||
#include "Swiften/Swiften.h"
|
||||
#include "Swiften/SwiftenCompat.h"
|
||||
#include <boost/filesystem.hpp>
|
||||
#include "unistd.h"
|
||||
#include "signal.h"
|
||||
#include "sys/wait.h"
|
||||
#include "sys/signal.h"
|
||||
Swift::SimpleEventLoop *loop_;
|
||||
|
||||
using namespace boost::program_options;
|
||||
using namespace Transport;
|
||||
|
||||
class FrotzNetworkPlugin;
|
||||
FrotzNetworkPlugin * np = NULL;
|
||||
|
||||
#define PARENT_READ p.readpipe[0]
|
||||
#define CHILD_WRITE p.readpipe[1]
|
||||
#define CHILD_READ p.writepipe[0]
|
||||
#define PARENT_WRITE p.writepipe[1]
|
||||
|
||||
typedef struct dfrotz_ {
|
||||
pid_t pid;
|
||||
std::string game;
|
||||
int readpipe[2];
|
||||
int writepipe[2];
|
||||
} dfrotz;
|
||||
|
||||
using namespace boost::filesystem;
|
||||
|
||||
static const char *howtoplay = "To move around, just type the direction you want to go. Directions can be\n"
|
||||
"abbreviated: NORTH to N, SOUTH to S, EAST to E, WEST to W, NORTHEAST to\n"
|
||||
"NE, NORTHWEST to NW, SOUTHEAST to SE, SOUTHWEST to SW, UP to U, and DOWN\n"
|
||||
"to D. IN and OUT will also work in certain places.\n"
|
||||
"\n"
|
||||
"There are many differnet kinds of sentences used in Interactive Fiction.\n"
|
||||
"Here are some examples:\n"
|
||||
"\n"
|
||||
"> WALK TO THE NORTH\n"
|
||||
"> WEST\n"
|
||||
"> NE\n"
|
||||
"> DOWN\n"
|
||||
"> TAKE THE BIRDCAGE\n"
|
||||
"> READ ABOUT DIMWIT FLATHEAD\n"
|
||||
"> LOOK UP MEGABOZ IN THE ENCYCLOPEDIA\n"
|
||||
"> LIE DOWN IN THE PINK SOFA\n"
|
||||
"> EXAMINE THE SHINY COIN\n"
|
||||
"> PUT THE RUSTY KEY IN THE CARDBOARD BOX\n"
|
||||
"> SHOW MY BOW TIE TO THE BOUNCER\n"
|
||||
"> HIT THE CRAWLING CRAB WITH THE GIANT NUTCRACKER\n"
|
||||
"> ASK THE COWARDLY KING ABOUT THE CROWN JEWELS\n"
|
||||
"\n"
|
||||
"You can use multiple objects with certain verbs if you separate them by\n"
|
||||
"the word \"AND\" or by a comma. Here are some examples:\n"
|
||||
"\n"
|
||||
"> TAKE THE BOOK AND THE FROG\n"
|
||||
"> DROP THE JAR OF PEANUT BUTTER, THE SPOON, AND THE LEMMING FOOD\n"
|
||||
"> PUT THE EGG AND THE PENCIL IN THE CABINET\n"
|
||||
"\n"
|
||||
"You can include several inputs on one line if you separate them by the\n"
|
||||
"word \"THEN\" or by a period. Each input will be handled in order, as\n"
|
||||
"though you had typed them individually at seperate prompts. For example,\n"
|
||||
"you could type all of the following at once, before pressing the ENTER (or\n"
|
||||
"RETURN) key:\n"
|
||||
"\n"
|
||||
"> TURN ON THE LIGHT. TAKE THE BOOK THEN READ ABOUT THE JESTER IN THE BOOK\n"
|
||||
"\n"
|
||||
"If the story doesn't understand one of the sentences on your input line,\n"
|
||||
"or if an unusual event occurs, it will ignore the rest of your input line.\n"
|
||||
"\n"
|
||||
"The words \"IT\" and \"ALL\" can be very useful. For example:\n"
|
||||
"\n"
|
||||
"> EXAMINE THE APPLE. TAKE IT. EAT IT\n"
|
||||
"> CLOSE THE HEAVY METAL DOOR. LOCK IT\n"
|
||||
"> PICK UP THE GREEN BOOT. SMELL IT. PUT IT ON.\n"
|
||||
"> TAKE ALL\n"
|
||||
"> TAKE ALL THE TOOLS\n"
|
||||
"> DROP ALL THE TOOLS EXCEPT THE WRENCH AND MINIATURE HAMMER\n"
|
||||
"> TAKE ALL FROM THE CARTON\n"
|
||||
"> GIVE ALL BUT THE RUBY SLIPPERS TO THE WICKED WITCH\n"
|
||||
"\n"
|
||||
"The word \"ALL\" refers to every visible object except those inside\n"
|
||||
"something else. If there were an apple on the ground and an orange inside\n"
|
||||
"a cabinet, \"TAKE ALL\" would take the apple but not the orange.\n"
|
||||
"\n"
|
||||
"There are three kinds of questions you can ask: \"WHERE IS (something)\",\n"
|
||||
"\"WHAT IS (something)\", and \"WHO IS (someone)\". For example:\n"
|
||||
"\n"
|
||||
"> WHO IS LORD DIMWIT?\n"
|
||||
"> WHAT IS A GRUE?\n"
|
||||
"> WHERE IS EVERYBODY?\n"
|
||||
"\n"
|
||||
"When you meet intelligent creatures, you can talk to them by typing their\n"
|
||||
"name, then a comma, then whatever you want to say to them. Here are some\n"
|
||||
"examples:\n"
|
||||
"\n"
|
||||
"> JESTER, HELLO\n"
|
||||
"> GUSTAR WOOMAX, TELL ME ABOUT THE COCONUT\n"
|
||||
"> UNCLE OTTO, GIVE ME YOUR WALLET\n"
|
||||
"> HORSE, WHERE IS YOUR SADDLE?\n"
|
||||
"> BOY, RUN HOME THEN CALL THE POLICE\n"
|
||||
"> MIGHTY WIZARD, TAKE THIS POISONED APPLE. EAT IT\n"
|
||||
"\n"
|
||||
"Notice that in the last two examples, you are giving the characters more\n"
|
||||
"than one command on the same input line. Keep in mind, however, that many\n"
|
||||
"creatures don't care for idle chatter; your actions will speak louder than\n"
|
||||
"your words. \n";
|
||||
|
||||
|
||||
static void start_dfrotz(dfrotz &p, const std::string &game) {
|
||||
// p.writepipe[0] = -1;
|
||||
|
||||
if (pipe(p.readpipe) < 0 || pipe(p.writepipe) < 0) {
|
||||
}
|
||||
|
||||
std::cout << "dfrotz -p " << game << "\n";
|
||||
|
||||
if ((p.pid = fork()) < 0) {
|
||||
/* FATAL: cannot fork child */
|
||||
}
|
||||
else if (p.pid == 0) {
|
||||
close(PARENT_WRITE);
|
||||
close(PARENT_READ);
|
||||
|
||||
dup2(CHILD_READ, 0); close(CHILD_READ);
|
||||
dup2(CHILD_WRITE, 1); close(CHILD_WRITE);
|
||||
|
||||
execlp("dfrotz", "-p", game.c_str(), NULL);
|
||||
|
||||
}
|
||||
else {
|
||||
close(CHILD_READ);
|
||||
close(CHILD_WRITE);
|
||||
}
|
||||
}
|
||||
|
||||
class FrotzNetworkPlugin : public NetworkPlugin {
|
||||
public:
|
||||
Swift::BoostNetworkFactories *m_factories;
|
||||
Swift::BoostIOServiceThread m_boostIOServiceThread;
|
||||
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Connection> m_conn;
|
||||
|
||||
FrotzNetworkPlugin(Config *config, Swift::SimpleEventLoop *loop, const std::string &host, int port) : NetworkPlugin() {
|
||||
this->config = config;
|
||||
m_factories = new Swift::BoostNetworkFactories(loop);
|
||||
m_conn = m_factories->getConnectionFactory()->createConnection();
|
||||
m_conn->onDataRead.connect(boost::bind(&FrotzNetworkPlugin::_handleDataRead, this, _1));
|
||||
m_conn->connect(Swift::HostAddressPort(SWIFT_HOSTADDRESS(host), port));
|
||||
// m_conn->onConnectFinished.connect(boost::bind(&FrotzNetworkPlugin::_handleConnected, this, _1));
|
||||
// m_conn->onDisconnected.connect(boost::bind(&FrotzNetworkPlugin::handleDisconnected, this));
|
||||
}
|
||||
|
||||
void sendData(const std::string &string) {
|
||||
m_conn->write(Swift::createSafeByteArray(string));
|
||||
}
|
||||
|
||||
void _handleDataRead(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::SafeByteArray> data) {
|
||||
std::string d(data->begin(), data->end());
|
||||
handleDataRead(d);
|
||||
}
|
||||
|
||||
void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
|
||||
np->handleConnected(user);
|
||||
std::vector<std::string> groups;
|
||||
groups.push_back("ZCode");
|
||||
np->handleBuddyChanged(user, "zcode", "ZCode", groups, pbnetwork::STATUS_ONLINE);
|
||||
// sleep(1);
|
||||
// np->handleMessage(np->m_user, "zork", first_msg);
|
||||
}
|
||||
|
||||
void handleLogoutRequest(const std::string &user, const std::string &legacyName) {
|
||||
if (games.find(user) != games.end()) {
|
||||
kill(games[user].pid, SIGTERM);
|
||||
games.erase(user);
|
||||
}
|
||||
// exit(0);
|
||||
}
|
||||
|
||||
void readMessage(const std::string &user) {
|
||||
static char buf[15000];
|
||||
buf[0] = 0;
|
||||
int repeated = 0;
|
||||
while (strlen(buf) == 0) {
|
||||
ssize_t len = read(games[user].readpipe[0], buf, 15000);
|
||||
if (len > 0) {
|
||||
buf[len] = 0;
|
||||
}
|
||||
usleep(1000);
|
||||
repeated++;
|
||||
if (repeated > 30)
|
||||
return;
|
||||
}
|
||||
np->handleMessage(user, "zcode", buf);
|
||||
|
||||
std::string msg = "save\n";
|
||||
write(games[user].writepipe[1], msg.c_str(), msg.size());
|
||||
|
||||
msg = user + "_" + games[user].game + ".save\n";
|
||||
write(games[user].writepipe[1], msg.c_str(), msg.size());
|
||||
ignoreMessage(user);
|
||||
}
|
||||
|
||||
void ignoreMessage(const std::string &user) {
|
||||
usleep(1000000);
|
||||
static char buf[15000];
|
||||
buf[0] = 0;
|
||||
int repeated = 0;
|
||||
while (strlen(buf) == 0) {
|
||||
ssize_t len = read(games[user].readpipe[0], buf, 15000);
|
||||
if (len > 0) {
|
||||
buf[len] = 0;
|
||||
}
|
||||
usleep(1000);
|
||||
repeated++;
|
||||
if (repeated > 30)
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << "ignoring: " << buf << "\n";
|
||||
}
|
||||
|
||||
std::vector<std::string> getGames() {
|
||||
std::vector<std::string> games;
|
||||
path p(".");
|
||||
directory_iterator end_itr;
|
||||
for (directory_iterator itr(p); itr != end_itr; ++itr) {
|
||||
if (extension(itr->path()) == ".z5") {
|
||||
#if BOOST_FILESYSTEM_VERSION == 3
|
||||
games.push_back(itr->path().filename().string());
|
||||
#else
|
||||
games.push_back(itr->path().leaf());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return games;
|
||||
}
|
||||
|
||||
void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "", const std::string &id = "") {
|
||||
std::cout << "aaa\n";
|
||||
if (message.find("start") == 0) {
|
||||
std::string game = message.substr(6);
|
||||
std::vector<std::string> lst = getGames();
|
||||
if (std::find(lst.begin(), lst.end(), game) == lst.end()) {
|
||||
np->handleMessage(user, "zcode", "Unknown game");
|
||||
return;
|
||||
}
|
||||
np->handleMessage(user, "zcode", "Starting the game");
|
||||
|
||||
dfrotz d;
|
||||
d.game = game;
|
||||
start_dfrotz(d, game);
|
||||
games[user] = d;
|
||||
fcntl(games[user].readpipe[0], F_SETFL, O_NONBLOCK);
|
||||
|
||||
if (boost::filesystem::exists(user + "_" + games[user].game + ".save")) {
|
||||
|
||||
std::string msg = "restore\n";
|
||||
write(games[user].writepipe[1], msg.c_str(), msg.size());
|
||||
|
||||
msg = user + "_" + games[user].game + ".save\n";
|
||||
write(games[user].writepipe[1], msg.c_str(), msg.size());
|
||||
|
||||
ignoreMessage(user);
|
||||
|
||||
msg = "l\n";
|
||||
write(games[user].writepipe[1], msg.c_str(), msg.size());
|
||||
}
|
||||
|
||||
readMessage(user);
|
||||
}
|
||||
else if (message == "stop" && games.find(user) != games.end()) {
|
||||
kill(games[user].pid, SIGTERM);
|
||||
games.erase(user);
|
||||
np->handleMessage(user, "zcode", "Game stopped");
|
||||
}
|
||||
else if (message == "howtoplay") {
|
||||
np->handleMessage(user, "zcode", howtoplay);
|
||||
}
|
||||
else if (games.find(user) != games.end()) {
|
||||
std::string msg = message + "\n";
|
||||
write(games[user].writepipe[1], msg.c_str(), msg.size());
|
||||
readMessage(user);
|
||||
}
|
||||
else {
|
||||
std::string games;
|
||||
BOOST_FOREACH(const std::string &game, getGames()) {
|
||||
games += game + "\n";
|
||||
}
|
||||
np->handleMessage(user, "zcode", "Games are saved/loaded automatically. Use \"restart\" to restart existing game. Emulator commands are:\nstart <game>\nstop\nhowtoplay\n\nList of games:\n" + games);
|
||||
}
|
||||
}
|
||||
|
||||
void handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password) {
|
||||
}
|
||||
|
||||
void handleLeaveRoomRequest(const std::string &user, const std::string &room) {
|
||||
}
|
||||
|
||||
std::map<std::string, dfrotz> games;
|
||||
std::string first_msg;
|
||||
private:
|
||||
|
||||
Config *config;
|
||||
};
|
||||
|
||||
static void spectrum_sigchld_handler(int sig)
|
||||
{
|
||||
int status;
|
||||
pid_t pid;
|
||||
|
||||
do {
|
||||
pid = waitpid(-1, &status, WNOHANG);
|
||||
} while (pid != 0 && pid != (pid_t)-1);
|
||||
|
||||
if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
|
||||
char errmsg[BUFSIZ];
|
||||
snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
|
||||
perror(errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char* argv[]) {
|
||||
std::string host;
|
||||
int port;
|
||||
|
||||
if (signal(SIGCHLD, spectrum_sigchld_handler) == SIG_ERR) {
|
||||
std::cout << "SIGCHLD handler can't be set\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string error;
|
||||
Config *cfg = Config::createFromArgs(argc, argv, error, host, port);
|
||||
if (cfg == NULL) {
|
||||
std::cerr << error;
|
||||
return 1;
|
||||
}
|
||||
|
||||
Swift::SimpleEventLoop eventLoop;
|
||||
loop_ = &eventLoop;
|
||||
np = new FrotzNetworkPlugin(cfg, &eventLoop, host, port);
|
||||
loop_->run();
|
||||
|
||||
delete cfg;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
cmake_minimum_required(VERSION 2.6)
|
||||
FILE(GLOB SRC *.cpp)
|
||||
FILE(GLOB HEADERS *.h)
|
||||
QT4_WRAP_CPP(SRC ${HEADERS} OPTIONS -DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED)
|
||||
ADD_EXECUTABLE(spectrum2_libcommuni_backend ${SRC})
|
||||
|
||||
if (NOT WIN32)
|
||||
target_link_libraries(spectrum2_libcommuni_backend ${IRC_LIBRARY} Qt4::QtNetwork Qt4::QtCore transport pthread)
|
||||
else ()
|
||||
target_link_libraries(spectrum2_libcommuni_backend ${IRC_LIBRARY} Qt4::QtNetwork Qt4::QtCore transport)
|
||||
endif()
|
||||
INSTALL(TARGETS spectrum2_libcommuni_backend RUNTIME DESTINATION bin)
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
#include <QtCore>
|
||||
#include <iostream>
|
||||
#include <IrcCommand>
|
||||
#include <IrcMessage>
|
||||
|
||||
namespace CommuniBackport {
|
||||
|
||||
bool parseColors(const QString& message, int pos, int* len, int* fg = 0, int* bg = 0)
|
||||
{
|
||||
// fg(,bg)
|
||||
*len = 0;
|
||||
if (fg)
|
||||
*fg = -1;
|
||||
if (bg)
|
||||
*bg = -1;
|
||||
QRegExp rx(QLatin1String("(\\d{1,2})(?:,(\\d{1,2}))?"));
|
||||
int idx = rx.indexIn(message, pos);
|
||||
if (idx == pos) {
|
||||
*len = rx.matchedLength();
|
||||
if (fg)
|
||||
*fg = rx.cap(1).toInt();
|
||||
if (bg) {
|
||||
bool ok = false;
|
||||
int tmp = rx.cap(2).toInt(&ok);
|
||||
if (ok)
|
||||
*bg = tmp;
|
||||
}
|
||||
}
|
||||
return *len > 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
Converts \a text to plain text. This function parses the text and
|
||||
strips away IRC-style formatting like colors, bold and underline.
|
||||
|
||||
\sa toHtml()
|
||||
*/
|
||||
void toPlainText(QString& processed)
|
||||
{
|
||||
|
||||
int pos = 0;
|
||||
int len = 0;
|
||||
while (pos < processed.size()) {
|
||||
switch (processed.at(pos).unicode()) {
|
||||
case '\x02': // bold
|
||||
case '\x0f': // none
|
||||
case '\x13': // strike-through
|
||||
case '\x15': // underline
|
||||
case '\x16': // inverse
|
||||
case '\x1d': // italic
|
||||
case '\x1f': // underline
|
||||
processed.remove(pos, 1);
|
||||
break;
|
||||
|
||||
case '\x03': // color
|
||||
if (parseColors(processed, pos + 1, &len))
|
||||
processed.remove(pos, len + 1);
|
||||
else
|
||||
processed.remove(pos, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
++pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,301 +0,0 @@
|
|||
/**
|
||||
* XMPP - libpurple transport
|
||||
*
|
||||
* Copyright (C) 2013, Jan Kaluza <hanzz.k@gmail.com>
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
#include <IrcCommand>
|
||||
#include <IrcMessage>
|
||||
#include "ircnetworkplugin.h"
|
||||
#include "transport/Logging.h"
|
||||
|
||||
DEFINE_LOGGER(logger, "IRCNetworkPlugin");
|
||||
|
||||
#define FROM_UTF8(WHAT) QString::fromUtf8((WHAT).c_str(), (WHAT).size())
|
||||
#define TO_UTF8(WHAT) std::string((WHAT).toUtf8().data(), (WHAT).toUtf8().size())
|
||||
|
||||
IRCNetworkPlugin::IRCNetworkPlugin(Config *config, Swift::QtEventLoop *loop, const std::string &host, int port) {
|
||||
m_config = config;
|
||||
m_currentServer = 0;
|
||||
m_firstPing = true;
|
||||
|
||||
m_socket = new QTcpSocket();
|
||||
m_socket->connectToHost(FROM_UTF8(host), port);
|
||||
connect(m_socket, SIGNAL(readyRead()), this, SLOT(readData()));
|
||||
|
||||
std::string server = CONFIG_STRING_DEFAULTED(m_config, "service.irc_server", "");
|
||||
if (!server.empty()) {
|
||||
m_servers.push_back(server);
|
||||
}
|
||||
else {
|
||||
std::list<std::string> list;
|
||||
list = CONFIG_LIST_DEFAULTED(m_config, "service.irc_server", list);
|
||||
m_servers.insert(m_servers.begin(), list.begin(), list.end());
|
||||
}
|
||||
|
||||
if (CONFIG_HAS_KEY(m_config, "service.irc_identify")) {
|
||||
m_identify = CONFIG_STRING(m_config, "service.irc_identify");
|
||||
}
|
||||
else {
|
||||
m_identify = "NickServ identify $name $password";
|
||||
}
|
||||
}
|
||||
|
||||
void IRCNetworkPlugin::tryNextServer() {
|
||||
if (!m_servers.empty()) {
|
||||
int nextServer = (m_currentServer + 1) % m_servers.size();
|
||||
LOG4CXX_INFO(logger, "Server " << m_servers[m_currentServer] << " disconnected user. Next server to try will be " << m_servers[nextServer]);
|
||||
m_currentServer = nextServer;
|
||||
}
|
||||
}
|
||||
|
||||
void IRCNetworkPlugin::readData() {
|
||||
size_t availableBytes = m_socket->bytesAvailable();
|
||||
if (availableBytes == 0)
|
||||
return;
|
||||
|
||||
if (m_firstPing) {
|
||||
m_firstPing = false;
|
||||
|
||||
NetworkPlugin::PluginConfig cfg;
|
||||
cfg.setNeedRegistration(false);
|
||||
cfg.setSupportMUC(true);
|
||||
cfg.disableJIDEscaping();
|
||||
sendConfig(cfg);
|
||||
}
|
||||
|
||||
std::string d = std::string(m_socket->readAll().data(), availableBytes);
|
||||
handleDataRead(d);
|
||||
}
|
||||
|
||||
void IRCNetworkPlugin::sendData(const std::string &string) {
|
||||
m_socket->write(string.c_str(), string.size());
|
||||
}
|
||||
|
||||
MyIrcSession *IRCNetworkPlugin::createSession(const std::string &user, const std::string &hostname, const std::string &nickname, const std::string &password, const std::string &suffix) {
|
||||
MyIrcSession *session = new MyIrcSession(user, this, suffix);
|
||||
session->setUserName(FROM_UTF8(nickname));
|
||||
session->setNickName(FROM_UTF8(nickname));
|
||||
session->setRealName(FROM_UTF8(nickname));
|
||||
// session->setEncoding("UTF8");
|
||||
|
||||
std::vector<std::string> hostname_parts;
|
||||
boost::split(hostname_parts, hostname, boost::is_any_of(":/"));
|
||||
if (hostname_parts.size() == 2 && !hostname_parts[0].empty() && !hostname_parts[1].empty()) { // hostname was splitted
|
||||
session->setHost(FROM_UTF8(hostname_parts[0])); // real hostname
|
||||
int port = atoi(hostname_parts[1].c_str()); // user port
|
||||
if (hostname_parts[1][0] == '+' || port == 6697) { // use SSL
|
||||
port = (port < 1 || port > 65535) ? 6697 : port; // default to standard SSL port
|
||||
session->setSecure(true);
|
||||
} else { // use TCP
|
||||
port = (port < 1 || port > 65535) ? 6667 : port; // default to standart TCP port
|
||||
}
|
||||
session->setPort(port);
|
||||
} else { // hostname was not splitted: default to old behaviour
|
||||
session->setHost(FROM_UTF8(hostname));
|
||||
session->setPort(6667);
|
||||
}
|
||||
|
||||
if (!password.empty()) {
|
||||
std::string identify = m_identify;
|
||||
boost::replace_all(identify, "$password", password);
|
||||
boost::replace_all(identify, "$name", nickname);
|
||||
if (CONFIG_BOOL_DEFAULTED(m_config, "service.irc_send_pass", false)) {
|
||||
session->setPassword(FROM_UTF8(password)); // use IRC PASS
|
||||
} else {
|
||||
session->setIdentify(identify); // use identify supplied
|
||||
}
|
||||
}
|
||||
|
||||
session->createBufferModel();
|
||||
LOG4CXX_INFO(logger, user << ": Connecting " << hostname << " as " << nickname << ", port=" << session->port() << ", suffix=" << suffix);
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
void IRCNetworkPlugin::handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
|
||||
if (!m_servers.empty()) {
|
||||
// legacy name is user's nickname
|
||||
if (m_sessions[user] != NULL) {
|
||||
LOG4CXX_WARN(logger, user << ": Already logged in.");
|
||||
return;
|
||||
}
|
||||
|
||||
m_sessions[user] = createSession(user, m_servers[m_currentServer], legacyName, password, "");
|
||||
m_sessions[user]->open();
|
||||
}
|
||||
else {
|
||||
// We are waiting for first room join to connect user to IRC network, because we don't know which
|
||||
// network he chooses...
|
||||
LOG4CXX_INFO(logger, user << ": Ready for connections");
|
||||
handleConnected(user);
|
||||
}
|
||||
}
|
||||
|
||||
void IRCNetworkPlugin::handleVCardRequest(const std::string &user, const std::string &legacyName, unsigned int id) {
|
||||
handleVCard(user, id, legacyName, "", "", "");
|
||||
}
|
||||
|
||||
void IRCNetworkPlugin::handleLogoutRequest(const std::string &user, const std::string &legacyName) {
|
||||
if (m_sessions[user] == NULL) {
|
||||
LOG4CXX_WARN(logger, user << ": Already disconnected.");
|
||||
return;
|
||||
}
|
||||
LOG4CXX_INFO(logger, user << ": Disconnecting.");
|
||||
m_sessions[user]->close();
|
||||
m_sessions[user]->deleteLater();
|
||||
m_sessions.erase(user);
|
||||
}
|
||||
|
||||
std::string IRCNetworkPlugin::getSessionName(const std::string &user, const std::string &legacyName) {
|
||||
std::string u = user;
|
||||
if (!CONFIG_BOOL(m_config, "service.server_mode") && m_servers.empty()) {
|
||||
u = user + legacyName.substr(legacyName.find("@") + 1);
|
||||
if (u.find("/") != std::string::npos) {
|
||||
u = u.substr(0, u.find("/"));
|
||||
}
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
std::string IRCNetworkPlugin::getTargetName(const std::string &legacyName) {
|
||||
std::string r = legacyName;
|
||||
if (legacyName.find("/") == std::string::npos) {
|
||||
r = legacyName.substr(0, r.find("@"));
|
||||
}
|
||||
else {
|
||||
r = legacyName.substr(legacyName.find("/") + 1);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void IRCNetworkPlugin::handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &/*xhtml*/, const std::string &/*id*/) {
|
||||
std::string session = getSessionName(user, legacyName);
|
||||
if (m_sessions[session] == NULL) {
|
||||
LOG4CXX_WARN(logger, user << ": Session name: " << session << ", No session for user");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string target = getTargetName(legacyName);
|
||||
// We are sending PM message. On XMPP side, user is sending PM using the particular channel,
|
||||
// for example #room@irc.freenode.org/hanzz. On IRC side, we are forwarding this message
|
||||
// just to "hanzz". Therefore we have to somewhere store, that message from "hanzz" should
|
||||
// be mapped to #room@irc.freenode.org/hanzz.
|
||||
if (legacyName.find("/") != std::string::npos) {
|
||||
m_sessions[session]->addPM(target, legacyName.substr(0, legacyName.find("@")));
|
||||
}
|
||||
|
||||
LOG4CXX_INFO(logger, user << ": Session name: " << session << ", message to " << target);
|
||||
|
||||
if (message.find("/me") == 0) {
|
||||
m_sessions[session]->sendCommand(IrcCommand::createCtcpAction(FROM_UTF8(target), FROM_UTF8(message.substr(4))));
|
||||
}
|
||||
else if (message.find("/whois") == 0 || message.find(".whois") == 0) {
|
||||
m_sessions[session]->sendWhoisCommand(target, message.substr(7));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
m_sessions[session]->sendCommand(IrcCommand::createMessage(FROM_UTF8(target), FROM_UTF8(message)));
|
||||
}
|
||||
|
||||
if (target.find("#") == 0) {
|
||||
handleMessage(user, legacyName, message, TO_UTF8(m_sessions[session]->nickName()));
|
||||
}
|
||||
}
|
||||
|
||||
void IRCNetworkPlugin::handleRoomSubjectChangedRequest(const std::string &user, const std::string &room, const std::string &message) {
|
||||
std::string session = getSessionName(user, room);
|
||||
if (m_sessions[session] == NULL) {
|
||||
LOG4CXX_WARN(logger, user << ": Session name: " << session << ", No session for user");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string target = getTargetName(room);
|
||||
m_sessions[session]->sendCommand(IrcCommand::createTopic(FROM_UTF8(target), FROM_UTF8(message)));
|
||||
}
|
||||
|
||||
void IRCNetworkPlugin::handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password) {
|
||||
std::string session = getSessionName(user, room);
|
||||
std::string target = getTargetName(room);
|
||||
|
||||
LOG4CXX_INFO(logger, user << ": Session name: " << session << ", Joining room " << target);
|
||||
bool createdSession = false;
|
||||
if (m_sessions[session] == NULL) {
|
||||
if (m_servers.empty()) {
|
||||
// in gateway mode we want to login this user to network according to legacyName
|
||||
if (room.find("@") != std::string::npos) {
|
||||
// suffix is %irc.freenode.net to let MyIrcSession return #room%irc.freenode.net
|
||||
m_sessions[session] = createSession(user, room.substr(room.find("@") + 1), nickname, "", room.substr(room.find("@")));
|
||||
createdSession = true;
|
||||
}
|
||||
else {
|
||||
LOG4CXX_WARN(logger, user << ": There's no proper server defined in room to which this user wants to join: " << room);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG4CXX_WARN(logger, user << ": Join room requested for unconnected user");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_sessions[session]->sendCommand(IrcCommand::createJoin(FROM_UTF8(target), FROM_UTF8(password)));
|
||||
m_sessions[session]->rooms += 1;
|
||||
|
||||
if (createdSession) {
|
||||
m_sessions[session]->open();
|
||||
}
|
||||
|
||||
// update nickname, because we have nickname per session, no nickname per room.
|
||||
if (nickname != TO_UTF8(m_sessions[session]->nickName())) {
|
||||
handleRoomNicknameChanged(user, room, TO_UTF8(m_sessions[session]->nickName()));
|
||||
handleParticipantChanged(user, nickname, room, 0, pbnetwork::STATUS_ONLINE, "", TO_UTF8(m_sessions[session]->nickName()));
|
||||
}
|
||||
}
|
||||
|
||||
void IRCNetworkPlugin::handleLeaveRoomRequest(const std::string &user, const std::string &room) {
|
||||
std::string session = getSessionName(user, room);
|
||||
std::string target = getTargetName(room);
|
||||
|
||||
LOG4CXX_INFO(logger, user << ": Session name: " << session << ", Leaving room " << target);
|
||||
if (m_sessions[session] == NULL)
|
||||
return;
|
||||
|
||||
m_sessions[session]->sendCommand(IrcCommand::createPart(FROM_UTF8(target)));
|
||||
m_sessions[session]->rooms -= 1;
|
||||
|
||||
if (m_sessions[session]->rooms <= 0 && m_servers.empty()) {
|
||||
LOG4CXX_INFO(logger, user << ": Session name: " << session << ", User is not in any room, disconnecting from network");
|
||||
m_sessions[session]->close();
|
||||
m_sessions[session]->deleteLater();
|
||||
m_sessions.erase(session);
|
||||
}
|
||||
}
|
||||
|
||||
void IRCNetworkPlugin::handleStatusChangeRequest(const std::string &user, int status, const std::string &statusMessage) {
|
||||
if (m_sessions[user] == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (status == pbnetwork::STATUS_AWAY) {
|
||||
LOG4CXX_INFO(logger, user << ": User is now away.");
|
||||
m_sessions[user]->sendCommand(IrcCommand::createAway(statusMessage.empty() ? "Away" : FROM_UTF8(statusMessage)));
|
||||
}
|
||||
else {
|
||||
LOG4CXX_INFO(logger, user << ": User is not away anymore.");
|
||||
m_sessions[user]->sendCommand(IrcCommand::createAway(""));
|
||||
}
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
/**
|
||||
* XMPP - libpurple transport
|
||||
*
|
||||
* Copyright (C) 2013, Jan Kaluza <hanzz.k@gmail.com>
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef Q_MOC_RUN
|
||||
#include "session.h"
|
||||
#include <QtCore>
|
||||
#include <QtNetwork>
|
||||
#include "transport/Config.h"
|
||||
#include "transport/NetworkPlugin.h"
|
||||
#include "Swiften/EventLoop/Qt/QtEventLoop.h"
|
||||
#endif
|
||||
|
||||
class IRCNetworkPlugin : public QObject, public NetworkPlugin {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
IRCNetworkPlugin(Config *config, Swift::QtEventLoop *loop, const std::string &host, int port);
|
||||
|
||||
void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password);
|
||||
|
||||
void handleLogoutRequest(const std::string &user, const std::string &legacyName);
|
||||
|
||||
void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &/*xhtml*/, const std::string &/*id*/);
|
||||
|
||||
void handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password);
|
||||
|
||||
void handleLeaveRoomRequest(const std::string &user, const std::string &room);
|
||||
|
||||
void handleRoomSubjectChangedRequest(const std::string &user, const std::string &room, const std::string &message);
|
||||
|
||||
void handleVCardRequest(const std::string &user, const std::string &legacyName, unsigned int id);
|
||||
|
||||
void handleStatusChangeRequest(const std::string &user, int status, const std::string &statusMessage);
|
||||
|
||||
void tryNextServer();
|
||||
|
||||
Config *getConfig() {
|
||||
return m_config;
|
||||
}
|
||||
|
||||
public slots:
|
||||
void readData();
|
||||
void sendData(const std::string &string);
|
||||
|
||||
private:
|
||||
MyIrcSession *createSession(const std::string &user, const std::string &hostname, const std::string &nickname, const std::string &password, const std::string &suffix = "");
|
||||
std::string getSessionName(const std::string &user, const std::string &legacyName);
|
||||
std::string getTargetName(const std::string &legacyName);
|
||||
|
||||
private:
|
||||
Config *m_config;
|
||||
QTcpSocket *m_socket;
|
||||
std::map<std::string, MyIrcSession *> m_sessions;
|
||||
std::vector<std::string> m_servers;
|
||||
int m_currentServer;
|
||||
std::string m_identify;
|
||||
bool m_firstPing;
|
||||
};
|
|
@ -1,53 +0,0 @@
|
|||
/**
|
||||
* XMPP - libpurple transport
|
||||
*
|
||||
* Copyright (C) 2013, Jan Kaluza <hanzz.k@gmail.com>
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
#include <QtCore>
|
||||
#include <QtNetwork>
|
||||
#include "transport/Config.h"
|
||||
#include "transport/NetworkPlugin.h"
|
||||
#include "transport/Logging.h"
|
||||
#include "Swiften/EventLoop/Qt/QtEventLoop.h"
|
||||
#include "ircnetworkplugin.h"
|
||||
|
||||
using namespace boost::program_options;
|
||||
using namespace Transport;
|
||||
|
||||
NetworkPlugin * np = NULL;
|
||||
|
||||
int main (int argc, char* argv[]) {
|
||||
std::string host;
|
||||
int port;
|
||||
|
||||
std::string error;
|
||||
Config *cfg = Config::createFromArgs(argc, argv, error, host, port);
|
||||
if (cfg == NULL) {
|
||||
std::cerr << error;
|
||||
return 1;
|
||||
}
|
||||
|
||||
Logging::initBackendLogging(cfg);
|
||||
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
Swift::QtEventLoop eventLoop;
|
||||
|
||||
|
||||
np = new IRCNetworkPlugin(cfg, &eventLoop, host, port);
|
||||
return app.exec();
|
||||
}
|
|
@ -1,586 +0,0 @@
|
|||
/**
|
||||
* XMPP - libpurple transport
|
||||
*
|
||||
* Copyright (C) 2013, Jan Kaluza <hanzz.k@gmail.com>
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
|
||||
#include "session.h"
|
||||
#include <QtCore>
|
||||
#include <iostream>
|
||||
#include <IrcCommand>
|
||||
#include <IrcMessage>
|
||||
#include <IrcUser>
|
||||
#include <IrcChannel>
|
||||
#include "backports.h"
|
||||
|
||||
#include "ircnetworkplugin.h"
|
||||
|
||||
#define FROM_UTF8(WHAT) QString::fromUtf8((WHAT).c_str(), (WHAT).size())
|
||||
#define TO_UTF8(WHAT) std::string((WHAT).toUtf8().data(), (WHAT).toUtf8().size())
|
||||
|
||||
#include "transport/Logging.h"
|
||||
|
||||
DEFINE_LOGGER(logger, "IRCConnection");
|
||||
|
||||
MyIrcSession::MyIrcSession(const std::string &user, IRCNetworkPlugin *np, const std::string &suffix, QObject* parent) : IrcConnection(parent)
|
||||
{
|
||||
m_np = np;
|
||||
m_user = user;
|
||||
m_suffix = suffix;
|
||||
m_connected = false;
|
||||
rooms = 0;
|
||||
m_bufferModel = NULL;
|
||||
|
||||
connect(this, SIGNAL(disconnected()), SLOT(on_disconnected()));
|
||||
connect(this, SIGNAL(socketError(QAbstractSocket::SocketError)), SLOT(on_socketError(QAbstractSocket::SocketError)));
|
||||
connect(this, SIGNAL(connected()), SLOT(on_connected()));
|
||||
|
||||
m_awayTimer = new QTimer(this);
|
||||
connect(m_awayTimer, SIGNAL(timeout()), this, SLOT(awayTimeout()));
|
||||
m_awayTimer->start(1 * 1000);
|
||||
}
|
||||
|
||||
MyIrcSession::~MyIrcSession() {
|
||||
delete m_awayTimer;
|
||||
}
|
||||
|
||||
void MyIrcSession::createBufferModel() {
|
||||
m_bufferModel = new IrcBufferModel(this);
|
||||
connect(m_bufferModel, SIGNAL(added(IrcBuffer*)), this, SLOT(onBufferAdded(IrcBuffer*)));
|
||||
connect(m_bufferModel, SIGNAL(removed(IrcBuffer*)), this, SLOT(onBufferRemoved(IrcBuffer*)));
|
||||
|
||||
// keep the command parser aware of the context
|
||||
// connect(m_bufferModel, SIGNAL(channelsChanged(QStringList)), parser, SLOT(setChannels(QStringList)));
|
||||
|
||||
// create a server buffer for non-targeted messages...
|
||||
IrcBuffer* serverBuffer = m_bufferModel->add(host());
|
||||
// ...and connect it to IrcBufferModel::messageIgnored()
|
||||
// TODO: Make this configurable, so users can show the MOTD and other stuff as in normal
|
||||
// IRC client.
|
||||
connect(m_bufferModel, SIGNAL(messageIgnored(IrcMessage*)), serverBuffer, SLOT(receiveMessage(IrcMessage*)));
|
||||
}
|
||||
|
||||
void MyIrcSession::onBufferAdded(IrcBuffer* buffer) {
|
||||
LOG4CXX_INFO(logger, m_user << ": Created IrcBuffer " << TO_UTF8(buffer->name()));
|
||||
|
||||
connect(buffer, SIGNAL(messageReceived(IrcMessage*)), this, SLOT(onMessageReceived(IrcMessage*)));
|
||||
|
||||
if (buffer->isChannel()) {
|
||||
QVariantMap userData;
|
||||
userData["awayCycle"] = boost::lexical_cast<int>(CONFIG_STRING_DEFAULTED(m_np->getConfig(), "service.irc_away_timeout", "60")) + m_userModels.size();
|
||||
userData["awayTick"] = 0;
|
||||
buffer->setUserData(userData);
|
||||
}
|
||||
|
||||
// create a model for buffer users
|
||||
IrcUserModel* userModel = new IrcUserModel(buffer);
|
||||
connect(userModel, SIGNAL(added(IrcUser*)), this, SLOT(onIrcUserAdded(IrcUser*)));
|
||||
connect(userModel, SIGNAL(removed(IrcUser*)), this, SLOT(onIrcUserRemoved(IrcUser*)));
|
||||
m_userModels.insert(buffer, userModel);
|
||||
}
|
||||
|
||||
void MyIrcSession::onBufferRemoved(IrcBuffer* buffer) {
|
||||
LOG4CXX_INFO(logger, m_user << ": Removed IrcBuffer " << TO_UTF8(buffer->name()));
|
||||
// the buffer specific models and documents are no longer needed
|
||||
delete m_userModels.take(buffer);
|
||||
}
|
||||
|
||||
bool MyIrcSession::hasIrcUser(const std::string &channel_, const std::string &name) {
|
||||
std::string channel = channel_;
|
||||
if (channel[0] != '#') {
|
||||
channel = "#" + channel;
|
||||
}
|
||||
|
||||
IrcBuffer *buffer = m_bufferModel->find(FROM_UTF8(channel));
|
||||
if (!buffer) {
|
||||
LOG4CXX_ERROR(logger, m_user << ": Cannot find IrcBuffer '" << channel << "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
IrcUserModel *userModel = m_userModels.value(buffer);
|
||||
if (!userModel) {
|
||||
LOG4CXX_ERROR(logger, m_user << ": Cannot find UserModel for IrcBuffer " << channel);
|
||||
return false;
|
||||
}
|
||||
|
||||
return userModel->contains(FROM_UTF8(name));
|
||||
}
|
||||
|
||||
void MyIrcSession::sendUserToFrontend(IrcUser *user, pbnetwork::StatusType statusType, const std::string &statusMessage, const std::string &newNick) {
|
||||
std::string target = "#" + TO_UTF8(user->channel()->name().toLower()) + m_suffix;
|
||||
int op = user->mode() == "o";
|
||||
|
||||
if (statusType != pbnetwork::STATUS_NONE) {
|
||||
if (user->isAway()) {
|
||||
statusType = pbnetwork::STATUS_AWAY;
|
||||
}
|
||||
if (newNick.empty()) {
|
||||
LOG4CXX_INFO(logger, m_user << ": IrcUser connected: " << target << "/" << TO_UTF8(user->name()));
|
||||
}
|
||||
else {
|
||||
LOG4CXX_INFO(logger, m_user << ": IrcUser changed nickname: " << target << "/" << TO_UTF8(user->name()) << ", newNick=" << newNick);
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG4CXX_INFO(logger, m_user << ": IrcUser disconnected: " << target << "/" << TO_UTF8(user->name()));
|
||||
}
|
||||
|
||||
m_np->handleParticipantChanged(m_user, TO_UTF8(user->name()), target, op, statusType, statusMessage, newNick);
|
||||
}
|
||||
|
||||
void MyIrcSession::onIrcUserChanged(bool dummy) {
|
||||
IrcUser *user = dynamic_cast<IrcUser *>(QObject::sender());
|
||||
if (!user) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG4CXX_INFO(logger, m_user << ": IrcUser " << TO_UTF8(user->name()) << " changed.");
|
||||
sendUserToFrontend(user, pbnetwork::STATUS_ONLINE);
|
||||
}
|
||||
|
||||
void MyIrcSession::onIrcUserChanged(const QString &) {
|
||||
onIrcUserChanged(false);
|
||||
}
|
||||
|
||||
void MyIrcSession::onIrcUserAdded(IrcUser *user) {
|
||||
sendUserToFrontend(user, pbnetwork::STATUS_ONLINE);
|
||||
connect(user, SIGNAL(modeChanged(const QString&)), this, SLOT(onIrcUserChanged(const QString&)));
|
||||
connect(user, SIGNAL(awayChanged(bool)), this, SLOT(onIrcUserChanged(bool)));
|
||||
|
||||
}
|
||||
|
||||
void MyIrcSession::onIrcUserRemoved(IrcUser *user) {
|
||||
sendUserToFrontend(user, pbnetwork::STATUS_NONE);
|
||||
disconnect(user, SIGNAL(modeChanged(const QString&)), this, SLOT(onIrcUserChanged(const QString&)));
|
||||
disconnect(user, SIGNAL(awayChanged(bool)), this, SLOT(onIrcUserChanged(bool)));
|
||||
}
|
||||
|
||||
void MyIrcSession::on_connected() {
|
||||
m_connected = true;
|
||||
if (m_suffix.empty()) {
|
||||
m_np->handleConnected(m_user);
|
||||
}
|
||||
|
||||
if (getIdentify().find(" ") != std::string::npos) {
|
||||
std::string to = getIdentify().substr(0, getIdentify().find(" "));
|
||||
std::string what = getIdentify().substr(getIdentify().find(" ") + 1);
|
||||
LOG4CXX_INFO(logger, m_user << ": Sending IDENTIFY message to " << to);
|
||||
sendCommand(IrcCommand::createMessage(FROM_UTF8(to), FROM_UTF8(what)));
|
||||
}
|
||||
}
|
||||
|
||||
void MyIrcSession::addPM(const std::string &name, const std::string &room) {
|
||||
LOG4CXX_INFO(logger, m_user << ": Adding PM conversation " << name << " " << room);
|
||||
m_pms[name] = room;
|
||||
}
|
||||
|
||||
void MyIrcSession::on_socketError(QAbstractSocket::SocketError error) {
|
||||
std::string reason;
|
||||
switch(error) {
|
||||
case QAbstractSocket::ConnectionRefusedError: reason = "The connection was refused by the peer (or timed out)."; break;
|
||||
case QAbstractSocket::RemoteHostClosedError: reason = "The remote host closed the connection."; break;
|
||||
case QAbstractSocket::HostNotFoundError: reason = "The host address was not found."; break;
|
||||
case QAbstractSocket::SocketAccessError: reason = "The socket operation failed because the application lacked the required privileges."; break;
|
||||
case QAbstractSocket::SocketResourceError: reason = "The local system ran out of resources."; break;
|
||||
case QAbstractSocket::SocketTimeoutError: reason = "The socket operation timed out."; break;
|
||||
case QAbstractSocket::DatagramTooLargeError: reason = "The datagram was larger than the operating system's limit."; break;
|
||||
case QAbstractSocket::NetworkError: reason = "An error occurred with the network."; break;
|
||||
case QAbstractSocket::SslHandshakeFailedError: reason = "The SSL/TLS handshake failed, so the connection was closed"; break;
|
||||
case QAbstractSocket::UnknownSocketError: reason = "An unidentified error occurred."; break;
|
||||
default: reason= "Unknown error."; break;
|
||||
};
|
||||
|
||||
if (!m_suffix.empty()) {
|
||||
foreach (IrcBuffer *buffer, m_bufferModel->buffers()) {
|
||||
if (!buffer->isChannel()) {
|
||||
continue;
|
||||
}
|
||||
m_np->handleParticipantChanged(m_user, TO_UTF8(nickName()), TO_UTF8(buffer->title()) + m_suffix, pbnetwork::PARTICIPANT_FLAG_ROOM_NOT_FOUND, pbnetwork::STATUS_NONE, reason);
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_np->handleDisconnected(m_user, 0, reason);
|
||||
m_np->tryNextServer();
|
||||
}
|
||||
LOG4CXX_INFO(logger, m_user << ": Disconnected from IRC network: " << reason);
|
||||
m_connected = false;
|
||||
}
|
||||
|
||||
void MyIrcSession::on_disconnected() {
|
||||
if (m_suffix.empty()) {
|
||||
m_np->handleDisconnected(m_user, 0, "");
|
||||
m_np->tryNextServer();
|
||||
}
|
||||
m_connected = false;
|
||||
}
|
||||
|
||||
void MyIrcSession::correctNickname(std::string &nick) {
|
||||
if (nick.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch(nick.at(0)) {
|
||||
case '@':
|
||||
case '+':
|
||||
case '~':
|
||||
case '&':
|
||||
case '%':
|
||||
nick.erase(0, 1);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
IrcUser *MyIrcSession::getIrcUser(IrcBuffer *buffer, std::string &nick) {
|
||||
correctNickname(nick);
|
||||
IrcUserModel *userModel = m_userModels.value(buffer);
|
||||
if (!userModel) {
|
||||
LOG4CXX_ERROR(logger, m_user << ": Cannot find UserModel for IrcBuffer " << TO_UTF8(buffer->name()));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return userModel->find(FROM_UTF8(nick));
|
||||
}
|
||||
|
||||
IrcUser *MyIrcSession::getIrcUser(IrcBuffer *buffer, IrcMessage *message) {
|
||||
std::string nick = TO_UTF8(message->nick());
|
||||
return getIrcUser(buffer, nick);
|
||||
}
|
||||
|
||||
void MyIrcSession::on_parted(IrcMessage *message) {
|
||||
// TODO: We currently use onIrcUserRemoved, but this does not allow sending
|
||||
// part/quit message. We should use this method instead and write version
|
||||
// of sendUserToFrontend which takes nickname instead of IrcUser just for
|
||||
// part/quit messages.
|
||||
// IrcPartMessage *m = (IrcPartMessage *) message;
|
||||
// IrcBuffer *buffer = dynamic_cast<IrcBuffer *>(QObject::sender());
|
||||
// IrcUser *user = getIrcUser(buffer, message);
|
||||
// if (!user) {
|
||||
// LOG4CXX_ERROR(logger, m_user << ": Part: IrcUser " << TO_UTF8(message->nick()) << " not in channel " << TO_UTF8(buffer->name()));
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// sendUserToFrontend(user, pbnetwork::STATUS_NONE, TO_UTF8(m->reason()));
|
||||
}
|
||||
|
||||
void MyIrcSession::on_quit(IrcMessage *message) {
|
||||
// TODO: We currently use onIrcUserRemoved, but this does not allow sending
|
||||
// part/quit message. We should use this method instead and write version
|
||||
// of sendUserToFrontend which takes nickname instead of IrcUser just for
|
||||
// part/quit messages.
|
||||
// IrcQuitMessage *m = (IrcQuitMessage *) message;
|
||||
// IrcBuffer *buffer = dynamic_cast<IrcBuffer *>(QObject::sender());
|
||||
// IrcUser *user = getIrcUser(buffer, message);
|
||||
// if (!user) {
|
||||
// LOG4CXX_ERROR(logger, m_user << ": Quit: IrcUser " << TO_UTF8(message->nick()) << " not in channel " << TO_UTF8(buffer->name()));
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// sendUserToFrontend(user, pbnetwork::STATUS_NONE, TO_UTF8(m->reason()));
|
||||
}
|
||||
|
||||
void MyIrcSession::on_nickChanged(IrcMessage *message) {
|
||||
IrcNickMessage *m = (IrcNickMessage *) message;
|
||||
IrcBuffer *buffer = dynamic_cast<IrcBuffer *>(QObject::sender());
|
||||
IrcUser *user = getIrcUser(buffer, message);
|
||||
if (!user) {
|
||||
LOG4CXX_ERROR(logger, m_user << ": NickChanged: IrcUser " << TO_UTF8(message->nick()) << " not in channel " << TO_UTF8(buffer->name()));
|
||||
return;
|
||||
}
|
||||
|
||||
sendUserToFrontend(user, pbnetwork::STATUS_ONLINE, "", TO_UTF8(m->newNick()));
|
||||
}
|
||||
|
||||
void MyIrcSession::on_topicChanged(IrcMessage *message) {
|
||||
IrcTopicMessage *m = (IrcTopicMessage *) message;
|
||||
|
||||
std::string nickname = TO_UTF8(m->nick());
|
||||
correctNickname(nickname);
|
||||
|
||||
LOG4CXX_INFO(logger, m_user << ": " << nickname << " topic changed to " << TO_UTF8(m->topic()));
|
||||
m_np->handleSubject(m_user, TO_UTF8(m->channel().toLower()) + m_suffix, TO_UTF8(m->topic()), nickname);
|
||||
}
|
||||
|
||||
void MyIrcSession::sendWhoisCommand(const std::string &channel, const std::string &to) {
|
||||
m_whois[to] = channel;
|
||||
sendCommand(IrcCommand::createWhois(FROM_UTF8(to)));
|
||||
}
|
||||
|
||||
void MyIrcSession::on_whoisMessageReceived(IrcMessage *message) {
|
||||
IrcWhoisMessage *m = (IrcWhoisMessage *) message;
|
||||
std::string nickname = TO_UTF8(m->nick());
|
||||
if (m_whois.find(nickname) == m_whois.end()) {
|
||||
LOG4CXX_INFO(logger, "Whois response received with unexpected nickname " << nickname);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string msg = "";
|
||||
msg += nickname + " is connected to " + TO_UTF8(m->server()) + " (" + TO_UTF8(m->realName()) + ")\n";
|
||||
msg += nickname + " is a user on channels: " + TO_UTF8(m->channels().join(", "));
|
||||
|
||||
sendMessageToFrontend(m_whois[nickname], "whois", msg);
|
||||
m_whois.erase(nickname);
|
||||
}
|
||||
|
||||
void MyIrcSession::on_namesMessageReceived(IrcMessage *message) {
|
||||
LOG4CXX_INFO(logger, m_user << ": NAMES received");
|
||||
IrcBuffer *buffer = dynamic_cast<IrcBuffer *>(QObject::sender());
|
||||
IrcUserModel *userModel = m_userModels.value(buffer);
|
||||
if (!userModel) {
|
||||
LOG4CXX_ERROR(logger, m_user << ": Cannot find UserModel for IrcBuffer " << TO_UTF8(buffer->name()));
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (IrcUser *user, userModel->users()) {
|
||||
sendUserToFrontend(user, pbnetwork::STATUS_ONLINE);
|
||||
}
|
||||
|
||||
LOG4CXX_INFO(logger, m_user << "Asking /who for channel " << TO_UTF8(buffer->name()));
|
||||
sendCommand(IrcCommand::createWho(buffer->name()));
|
||||
}
|
||||
|
||||
void MyIrcSession::sendMessageToFrontend(const std::string &channel, const std::string &nick, const std::string &msg) {
|
||||
QString html = "";//msg;
|
||||
// CommuniBackport::toPlainText(msg);
|
||||
|
||||
// TODO: Communi produces invalid html now...
|
||||
// if (html == msg) {
|
||||
// html = "";
|
||||
// }
|
||||
// else {
|
||||
// html = IrcUtil::messageToHtml(html);
|
||||
// }
|
||||
|
||||
std::string nickname = nick;
|
||||
if (channel.find("#") == 0) {
|
||||
correctNickname(nickname);
|
||||
m_np->handleMessage(m_user, channel + m_suffix, msg, nickname, TO_UTF8(html));
|
||||
}
|
||||
else {
|
||||
correctNickname(nickname);
|
||||
if (m_pms.find(nickname) != m_pms.end()) {
|
||||
std::string room = m_pms[nickname].substr(0, m_pms[nickname].find("/"));
|
||||
room = room.substr(0, room.find("@"));
|
||||
if (hasIrcUser(room, nickname)) {
|
||||
m_np->handleMessage(m_user, room + m_suffix, msg, nickname, TO_UTF8(html), "", false, true);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
nickname = nickname + m_suffix;
|
||||
}
|
||||
}
|
||||
else {
|
||||
foreach (IrcBuffer *buffer, m_bufferModel->buffers()) {
|
||||
std::string room = "#" + TO_UTF8(buffer->name());
|
||||
IrcUserModel *userModel = m_userModels.value(buffer);
|
||||
if (!userModel) {
|
||||
LOG4CXX_ERROR(logger, m_user << ": Cannot find UserModel for IrcBuffer " << TO_UTF8(buffer->name()));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!userModel->contains(FROM_UTF8(nickname))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
addPM(nickname, room + "/" + nickname);
|
||||
m_np->handleMessage(m_user, room + m_suffix, msg, nickname, TO_UTF8(html), "", false, true);
|
||||
return;
|
||||
}
|
||||
|
||||
nickname = nickname + m_suffix;
|
||||
}
|
||||
|
||||
m_np->handleMessage(m_user, nickname, msg, "", TO_UTF8(html));
|
||||
}
|
||||
}
|
||||
|
||||
void MyIrcSession::on_messageReceived(IrcMessage *message) {
|
||||
IrcPrivateMessage *m = (IrcPrivateMessage *) message;
|
||||
if (m->isRequest()) {
|
||||
QString request = m->content().split(" ", QString::SkipEmptyParts).value(0).toUpper();
|
||||
if (request == "PING" || request == "TIME" || request == "VERSION") {
|
||||
LOG4CXX_INFO(logger, m_user << ": " << TO_UTF8(request) << " received and has been answered");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::string msg = TO_UTF8(m->content());
|
||||
if (m->isAction()) {
|
||||
msg = "/me " + msg;
|
||||
}
|
||||
|
||||
std::string target = TO_UTF8(m->target().toLower());
|
||||
std::string nickname = TO_UTF8(m->nick());
|
||||
sendMessageToFrontend(target, nickname, msg);
|
||||
}
|
||||
|
||||
void MyIrcSession::on_numericMessageReceived(IrcMessage *message) {
|
||||
QString channel;
|
||||
QStringList members;
|
||||
std::string nick;
|
||||
|
||||
IrcNumericMessage *m = (IrcNumericMessage *) message;
|
||||
QStringList parameters = m->parameters();
|
||||
switch (m->code()) {
|
||||
case Irc::RPL_TOPIC:
|
||||
m_topicData = TO_UTF8(parameters[2]);
|
||||
break;
|
||||
case Irc::RPL_TOPICWHOTIME:
|
||||
nick = TO_UTF8(parameters[2]);
|
||||
if (nick.find("!") != std::string::npos) {
|
||||
nick = nick.substr(0, nick.find("!"));
|
||||
}
|
||||
if (nick.find("/") != std::string::npos) {
|
||||
nick = nick.substr(0, nick.find("/"));
|
||||
}
|
||||
m_np->handleSubject(m_user, TO_UTF8(parameters[1].toLower()) + m_suffix, m_topicData, nick);
|
||||
break;
|
||||
case Irc::ERR_NOSUCHNICK:
|
||||
case Irc::ERR_NOSUCHSERVER:
|
||||
nick = TO_UTF8(parameters[1]);
|
||||
if (m_whois.find(nick) != m_whois.end()) {
|
||||
sendMessageToFrontend(m_whois[nick], "whois", nick + ": No such client");
|
||||
m_whois.erase(nick);
|
||||
}
|
||||
break;
|
||||
case Irc::ERR_ERRONEUSNICKNAME:
|
||||
m_np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_INVALID_USERNAME, "Erroneous Nickname");
|
||||
break;
|
||||
case Irc::ERR_NICKNAMEINUSE:
|
||||
case Irc::ERR_NICKCOLLISION:
|
||||
foreach (IrcBuffer *buffer, m_bufferModel->buffers()) {
|
||||
if (!buffer->isChannel()) {
|
||||
continue;
|
||||
}
|
||||
m_np->handleRoomNicknameChanged(m_user, TO_UTF8(buffer->title()) + m_suffix, TO_UTF8(nickName() + "_"));
|
||||
m_np->handleParticipantChanged(m_user, TO_UTF8(nickName()), TO_UTF8(buffer->title()) + m_suffix, 0, pbnetwork::STATUS_ONLINE, "", TO_UTF8(nickName() + "_"));
|
||||
}
|
||||
setNickName(nickName() + "_");
|
||||
open();
|
||||
// for(AutoJoinMap::iterator it = m_autoJoin.begin(); it != m_autoJoin.end(); it++) {
|
||||
// m_np->handleParticipantChanged(m_user, TO_UTF8(nickName()), it->second->getChannel() + m_suffix, pbnetwork::PARTICIPANT_FLAG_CONFLICT);
|
||||
// }
|
||||
// if (m_suffix.empty()) {
|
||||
// m_np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_INVALID_USERNAME, "Nickname is already in use");
|
||||
// }
|
||||
break;
|
||||
// foreach (IrcBuffer *buffer, m_bufferModel->buffers()) {
|
||||
// if (!buffer->isChannel()) {
|
||||
// continue;
|
||||
// }
|
||||
// m_np->handleParticipantChanged(m_user, TO_UTF8(nickName()), TO_UTF8(buffer->title()) + m_suffix, pbnetwork::PARTICIPANT_FLAG_CONFLICT);
|
||||
// }
|
||||
// m_np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_INVALID_USERNAME, "Nickname collision KILL");
|
||||
// break;
|
||||
case Irc::ERR_PASSWDMISMATCH:
|
||||
foreach (IrcBuffer *buffer, m_bufferModel->buffers()) {
|
||||
if (!buffer->isChannel()) {
|
||||
continue;
|
||||
}
|
||||
m_np->handleParticipantChanged(m_user, TO_UTF8(nickName()), TO_UTF8(buffer->title()) + m_suffix, pbnetwork::PARTICIPANT_FLAG_NOT_AUTHORIZED);
|
||||
}
|
||||
if (m_suffix.empty()) {
|
||||
m_np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_INVALID_USERNAME, "Password incorrect");
|
||||
}
|
||||
case 321:
|
||||
m_rooms.clear();
|
||||
m_names.clear();
|
||||
break;
|
||||
case 322:
|
||||
m_rooms.push_back(TO_UTF8(parameters[1]));
|
||||
m_names.push_back(TO_UTF8(parameters[1]));
|
||||
break;
|
||||
case 323:
|
||||
m_np->handleRoomList("", m_rooms, m_names);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (m->code() >= 400 && m->code() < 500) {
|
||||
LOG4CXX_INFO(logger, m_user << ": Error message received: " << message->toData().data());
|
||||
}
|
||||
else {
|
||||
LOG4CXX_INFO(logger, m_user << ": Numeric message received: " << message->toData().data());
|
||||
}
|
||||
}
|
||||
|
||||
void MyIrcSession::awayTimeout() {
|
||||
foreach (IrcBuffer *buffer, m_bufferModel->buffers()) {
|
||||
if (!buffer->isChannel()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QVariantMap userData = buffer->userData();
|
||||
int awayCycle = userData["awayCycle"].toInt();
|
||||
int awayTick = userData["awayTick"].toInt();
|
||||
|
||||
if (awayTick == awayCycle) {
|
||||
LOG4CXX_INFO(logger, m_user << ": The time has come. Asking /who " << TO_UTF8(buffer->title()) << " again to get current away states.");
|
||||
sendCommand(IrcCommand::createWho(buffer->title()));
|
||||
awayTick = 0;
|
||||
}
|
||||
awayTick++;
|
||||
|
||||
userData["awayCycle"] = awayCycle;
|
||||
userData["awayTick"] = awayTick;
|
||||
buffer->setUserData(userData);
|
||||
}
|
||||
}
|
||||
|
||||
void MyIrcSession::on_noticeMessageReceived(IrcMessage *message) {
|
||||
IrcNoticeMessage *m = (IrcNoticeMessage *) message;
|
||||
LOG4CXX_INFO(logger, m_user << ": NOTICE " << TO_UTF8(m->content()));
|
||||
|
||||
std::string msg = TO_UTF8(m->content());
|
||||
std::string target = TO_UTF8(m->target().toLower());
|
||||
std::string nickname = TO_UTF8(m->nick());
|
||||
sendMessageToFrontend(target, nickname, msg);
|
||||
}
|
||||
|
||||
void MyIrcSession::onMessageReceived(IrcMessage *message) {
|
||||
switch (message->type()) {
|
||||
case IrcMessage::Part:
|
||||
on_parted(message);
|
||||
break;
|
||||
case IrcMessage::Quit:
|
||||
on_quit(message);
|
||||
break;
|
||||
case IrcMessage::Nick:
|
||||
on_nickChanged(message);
|
||||
break;
|
||||
case IrcMessage::Topic:
|
||||
on_topicChanged(message);
|
||||
break;
|
||||
case IrcMessage::Private:
|
||||
on_messageReceived(message);
|
||||
break;
|
||||
case IrcMessage::Numeric:
|
||||
on_numericMessageReceived(message);
|
||||
break;
|
||||
case IrcMessage::Notice:
|
||||
on_noticeMessageReceived(message);
|
||||
break;
|
||||
case IrcMessage::Whois:
|
||||
on_whoisMessageReceived(message);
|
||||
break;
|
||||
case IrcMessage::Names:
|
||||
on_namesMessageReceived(message);
|
||||
break;
|
||||
default:break;
|
||||
}
|
||||
}
|
|
@ -1,119 +0,0 @@
|
|||
/**
|
||||
* XMPP - libpurple transport
|
||||
*
|
||||
* Copyright (C) 2013, Jan Kaluza <hanzz.k@gmail.com>
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SESSION_H
|
||||
#define SESSION_H
|
||||
|
||||
#ifndef Q_MOC_RUN
|
||||
#include <IrcConnection>
|
||||
#include <IrcBufferModel>
|
||||
#include <IrcBuffer>
|
||||
#include <IrcUserModel>
|
||||
#include <transport/NetworkPlugin.h>
|
||||
#include "Swiften/Swiften.h"
|
||||
#include <boost/smart_ptr/make_shared.hpp>
|
||||
#include <QTimer>
|
||||
#endif
|
||||
|
||||
using namespace Transport;
|
||||
|
||||
class IRCNetworkPlugin;
|
||||
|
||||
class MyIrcSession : public IrcConnection
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MyIrcSession(const std::string &user, IRCNetworkPlugin *np, const std::string &suffix = "", QObject* parent = 0);
|
||||
virtual ~MyIrcSession();
|
||||
|
||||
void createBufferModel();
|
||||
|
||||
// We are sending PM message. On XMPP side, user is sending PM using the particular channel,
|
||||
// for example #room@irc.freenode.org/hanzz. On IRC side, we are forwarding this message
|
||||
// just to "hanzz". Therefore we have to somewhere store, that message from "hanzz" should
|
||||
// be mapped to #room@irc.freenode.org/hanzz.
|
||||
void addPM(const std::string &name, const std::string &room);
|
||||
|
||||
void setIdentify(const std::string &identify) {
|
||||
m_identify = identify;
|
||||
}
|
||||
|
||||
const std::string &getIdentify() {
|
||||
return m_identify;
|
||||
}
|
||||
|
||||
bool hasIrcUser(const std::string &channel, const std::string &name);
|
||||
|
||||
void correctNickname(std::string &nick);
|
||||
IrcUser *getIrcUser(IrcBuffer *buffer, IrcMessage *message);
|
||||
IrcUser *getIrcUser(IrcBuffer *buffer, std::string &nick);
|
||||
|
||||
void sendWhoisCommand(const std::string &channel, const std::string &to);
|
||||
void sendMessageToFrontend(const std::string &channel, const std::string &nickname, const std::string &msg);
|
||||
void sendUserToFrontend(IrcUser *user, pbnetwork::StatusType statusType, const std::string &statusMessage = "", const std::string &newNick = "");
|
||||
|
||||
void on_joined(IrcMessage *message);
|
||||
void on_parted(IrcMessage *message);
|
||||
void on_quit(IrcMessage *message);
|
||||
void on_nickChanged(IrcMessage *message);
|
||||
void on_topicChanged(IrcMessage *message);
|
||||
void on_messageReceived(IrcMessage *message);
|
||||
void on_numericMessageReceived(IrcMessage *message);
|
||||
void on_noticeMessageReceived(IrcMessage *message);
|
||||
void on_whoisMessageReceived(IrcMessage *message);
|
||||
void on_namesMessageReceived(IrcMessage *message);
|
||||
|
||||
int rooms;
|
||||
|
||||
protected Q_SLOTS:
|
||||
void on_connected();
|
||||
void on_disconnected();
|
||||
void on_socketError(QAbstractSocket::SocketError error);
|
||||
|
||||
void onBufferAdded(IrcBuffer* buffer);
|
||||
void onBufferRemoved(IrcBuffer* buffer);
|
||||
|
||||
void onIrcUserAdded(IrcUser *user);
|
||||
void onIrcUserChanged(const QString &);
|
||||
void onIrcUserChanged(bool);
|
||||
void onIrcUserRemoved(IrcUser *user);
|
||||
|
||||
void onMessageReceived(IrcMessage* message);
|
||||
void awayTimeout();
|
||||
|
||||
|
||||
protected:
|
||||
IRCNetworkPlugin *m_np;
|
||||
IrcBufferModel *m_bufferModel;
|
||||
std::string m_user;
|
||||
std::string m_identify;
|
||||
std::string m_topicData;
|
||||
bool m_connected;
|
||||
std::list<std::string> m_rooms;
|
||||
std::list<std::string> m_names;
|
||||
std::map<std::string, std::string> m_pms;
|
||||
QTimer *m_awayTimer;
|
||||
std::string m_suffix;
|
||||
std::map<std::string, std::string> m_whois;
|
||||
QHash<IrcBuffer*, IrcUserModel*> m_userModels;
|
||||
};
|
||||
|
||||
#endif // SESSION_H
|
|
@ -1,17 +0,0 @@
|
|||
cmake_minimum_required(VERSION 2.6)
|
||||
FILE(GLOB SRC *.cpp)
|
||||
|
||||
ADD_EXECUTABLE(spectrum2_libpurple_backend ${SRC})
|
||||
|
||||
if(MSVC)
|
||||
target_link_libraries(spectrum2_libpurple_backend transport ${PURPLE_LIBRARY} ${GLIB2_LIBRARIES} ${LIBXML2_LIBRARIES} ${EVENT_LIBRARIES} transport-plugin ${PROTOBUF_LIBRARY})
|
||||
else()
|
||||
if (NOT WIN32)
|
||||
target_link_libraries(spectrum2_libpurple_backend transport ${PURPLE_LIBRARY} ${GLIB2_LIBRARIES} ${EVENT_LIBRARIES} transport-plugin pthread)
|
||||
else()
|
||||
target_link_libraries(spectrum2_libpurple_backend transport ${PURPLE_LIBRARY} ${GLIB2_LIBRARIES} ${EVENT_LIBRARIES} transport-plugin)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
INSTALL(TARGETS spectrum2_libpurple_backend RUNTIME DESTINATION bin)
|
||||
|
|
@ -1,251 +0,0 @@
|
|||
import sys
|
||||
import os
|
||||
|
||||
# intialize for methods used in libpurple macros
|
||||
methods = ["purple_connection_get_state(", "purple_conversation_get_im_data(",
|
||||
"purple_conversation_get_chat_data(", "purple_blist_node_get_type("]
|
||||
macros = ["PURPLE_CONV_IM", "PURPLE_CONV_CHAT", "PURPLE_BLIST_NODE_IS_BUDDY", "PURPLE_CONNECTION_IS_CONNECTED"]
|
||||
definitions = []
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
print "Usage:", sys.argv[0], "<path_to_libpurple_dir_containing_libpurple_headers>"
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def handle_file(cpp):
|
||||
global methods
|
||||
global macros
|
||||
sys.stdout.write("getting used methods in " + cpp + ": ")
|
||||
sys.stdout.flush()
|
||||
|
||||
counter = 0
|
||||
|
||||
new_file = ""
|
||||
f = open(cpp, "r")
|
||||
for line in f.readlines():
|
||||
new_line = ""
|
||||
index = 0
|
||||
while index < len(line):
|
||||
new_line += line[index]
|
||||
if line[index:].startswith("purple_") or line[index:].startswith("wpurple_") or line[index:].startswith("serv_"):
|
||||
if line[index:].find("=") != -1 and line[index:].find("=") < line[index:].find("("):
|
||||
index += 1
|
||||
continue
|
||||
if line[index-1] == "_" or line[index:].find("(") == -1 or line[index:].startswith("purple_commands_init") or line[index:].startswith("serv_addr"):
|
||||
index += 1
|
||||
continue
|
||||
m = line[index:line[index:].find("(")+index]
|
||||
index += len(m)
|
||||
if m.find("_wrapped") != -1:
|
||||
new_line += m[1:] + "("
|
||||
m = m.replace("_wrapped", "")
|
||||
else:
|
||||
new_line += m[1:] + "_wrapped("
|
||||
if not m + "(" in methods and len(m) != 0:
|
||||
methods += [m + "("]
|
||||
counter += 1
|
||||
index += 1
|
||||
|
||||
for x in macros:
|
||||
if new_line.find(x + "_WRAPPED") == -1:
|
||||
new_line = new_line.replace(x, x + "_WRAPPED")
|
||||
new_file += new_line
|
||||
f.close()
|
||||
|
||||
print counter, "new methods found"
|
||||
return new_file
|
||||
|
||||
def handle_header(header, method):
|
||||
global definitions
|
||||
|
||||
f = open(os.path.join(sys.argv[1], header), "r")
|
||||
|
||||
lines = f.readlines()
|
||||
for i in range(len(lines)):
|
||||
line = lines[i]
|
||||
if line.find(method) != -1:
|
||||
if line.startswith(method):
|
||||
line = lines[i-1][:-1] + line
|
||||
m = line[:-1]
|
||||
l = unicode(m).strip()
|
||||
if l.endswith(")"):
|
||||
continue
|
||||
|
||||
if m.find("/*") > m.find(";"):
|
||||
m = m[:m.find("/*")]
|
||||
m.rstrip()
|
||||
if len(m) != 0:
|
||||
while m[-1] == " ":
|
||||
m = m[:-1]
|
||||
|
||||
index = i;
|
||||
while not m.endswith(";"):
|
||||
index += 1
|
||||
m += " " + lines[index][:-1].lstrip()
|
||||
|
||||
l = unicode(m).strip()
|
||||
if (l.startswith("#") or l.startswith("*") or l.startswith("/*") or l.count("***") != 0 or l.count("&&") != 0
|
||||
or l.endswith(")")):
|
||||
continue;
|
||||
|
||||
m = m.replace("G_GNUC_NULL_TERMINATE", "")
|
||||
|
||||
if not m in definitions:
|
||||
print "found", method[:-1], "in", header
|
||||
definitions += [m]
|
||||
break
|
||||
f.close()
|
||||
|
||||
def get_raw_args(d):
|
||||
return d[d.find("(")+1:-2]
|
||||
|
||||
def get_args(d):
|
||||
x = d[d.find("(")+1:-2]
|
||||
x = x.split(",")
|
||||
|
||||
args = []
|
||||
for arg in x:
|
||||
y = arg.split(" ")
|
||||
if len(y) == 1:
|
||||
continue
|
||||
args += [y[-1].replace("*", "")]
|
||||
|
||||
return args
|
||||
|
||||
def get_name(d):
|
||||
x = d[:d.find("(")+1].lstrip()
|
||||
if x.find("wpurple_") != -1:
|
||||
return x[x.find("wpurple_"):]
|
||||
if x.find("serv_") != -1:
|
||||
return x[x.find("serv_"):]
|
||||
return x[x.find("purple_"):]
|
||||
|
||||
def get_rtype(d):
|
||||
if d.find("wpurple_") != -1:
|
||||
return d[:d.find("wpurple_")].lstrip()
|
||||
if d.find("serv_") != -1:
|
||||
return d[:d.find("serv_")].lstrip()
|
||||
return d[:d.find("purple_")].lstrip()
|
||||
|
||||
def output():
|
||||
global definitions
|
||||
|
||||
header = open("purple_defs.h", "w")
|
||||
print >> header, "#pragma once"
|
||||
print >> header, "#if PURPLE_RUNTIME"
|
||||
|
||||
print >> header, """
|
||||
#include <Windows.h>
|
||||
#include <purple.h>
|
||||
|
||||
#define PURPLE_BLIST_NODE_IS_CHAT_WRAPPED(n) (purple_blist_node_get_type_wrapped(n) == PURPLE_BLIST_CHAT_NODE)
|
||||
#define PURPLE_BLIST_NODE_IS_BUDDY_WRAPPED(n) (purple_blist_node_get_type_wrapped(n) == PURPLE_BLIST_BUDDY_NODE)
|
||||
#define PURPLE_BLIST_NODE_IS_CONTACT_WRAPPED(n) (purple_blist_node_get_type_wrapped(n) == PURPLE_BLIST_CONTACT_NODE)
|
||||
#define PURPLE_BLIST_NODE_IS_GROUP_WRAPPED(n) (purple_blist_node_get_type_wrapped(n) == PURPLE_BLIST_GROUP_NODE)
|
||||
|
||||
#define PURPLE_CONV_IM_WRAPPED(c) (purple_conversation_get_im_data_wrapped(c))
|
||||
#define PURPLE_CONV_CHAT_WRAPPED(c) (purple_conversation_get_chat_data_wrapped(c))
|
||||
|
||||
#define PURPLE_CONNECTION_IS_CONNECTED_WRAPPED(gc) \
|
||||
(purple_connection_get_state_wrapped(gc) == PURPLE_CONNECTED)
|
||||
"""
|
||||
|
||||
for d in definitions:
|
||||
#typedef void (_cdecl * purple_util_set_user_wrapped_func)(const char *dir);
|
||||
print >> header, "typedef", get_rtype(d), "(_cdecl *", get_name(d)[:-1] + "_wrapped_fnc)(" + get_raw_args(d) + ");"
|
||||
#extern purple_util_set_user_wrapped_func purple_util_set_user_wrapped;
|
||||
print >> header, "extern", get_name(d)[:-1] + "_wrapped_fnc", get_name(d)[:-1] + "_wrapped;"
|
||||
print >> header, ""
|
||||
|
||||
print >> header, ""
|
||||
print >> header, "#else"
|
||||
print >> header, ""
|
||||
|
||||
print >> header, """
|
||||
#define PURPLE_BLIST_NODE_IS_CHAT_WRAPPED PURPLE_BLIST_NODE_IS_CHAT
|
||||
#define PURPLE_BLIST_NODE_IS_BUDDY_WRAPPED PURPLE_BLIST_NODE_IS_BUDDY
|
||||
#define PURPLE_BLIST_NODE_IS_CONTACT_WRAPPED PURPLE_BLIST_NODE_IS_CONTACT
|
||||
#define PURPLE_BLIST_NODE_IS_GROUP_WRAPPED PURPLE_BLIST_NODE_IS_GROUP
|
||||
|
||||
#define PURPLE_CONV_IM_WRAPPED PURPLE_CONV_IM
|
||||
#define PURPLE_CONV_CHAT_WRAPPED PURPLE_CONV_CHAT
|
||||
|
||||
#define PURPLE_CONNECTION_IS_CONNECTED_WRAPPED PURPLE_CONNECTION_IS_CONNECTED
|
||||
"""
|
||||
|
||||
for d in definitions:
|
||||
#define purple_util_set_user_wrapped purple_util_set_user
|
||||
print >> header, "#define", get_name(d)[:-1] + "_wrapped", get_name(d)[:-1]
|
||||
|
||||
print >> header, "#endif"
|
||||
print >> header, ""
|
||||
print >> header, "bool resolvePurpleFunctions();"
|
||||
print >> header, ""
|
||||
|
||||
|
||||
cpp = open("purple_defs.cpp", "w")
|
||||
print >> cpp, "#include \"purple_defs.h\""
|
||||
print >> cpp, ""
|
||||
print >> cpp, "#if PURPLE_RUNTIME"
|
||||
print >> cpp, "static HMODULE f_hPurple = NULL;"
|
||||
for d in definitions:
|
||||
#purple_util_set_user_wrapped_fnc purple_util_set_user_wrapped = NULL;
|
||||
print >> cpp, get_name(d)[:-1] + "_wrapped_fnc", get_name(d)[:-1] + "_wrapped = NULL;"
|
||||
|
||||
print >> cpp, "#endif"
|
||||
|
||||
print >> cpp, "bool resolvePurpleFunctions() {"
|
||||
print >> cpp, "#if PURPLE_RUNTIME"
|
||||
print >> cpp, "\tf_hPurple = LoadLibrary(L\"libpurple.dll\");"
|
||||
print >> cpp, "\tif (!f_hPurple)"
|
||||
print >> cpp, "\t\t\treturn false;"
|
||||
for d in definitions:
|
||||
#purple_util_set_user_wrapped = (purple_util_set_user_wrapped_func)GetProcAddress(f_hPurple, "purple_util_set_user_dir");
|
||||
print >> cpp, "\t" + get_name(d)[:-1] + "_wrapped = (" + get_name(d)[:-1] + "_wrapped_fnc)GetProcAddress(f_hPurple, \"" + get_name(d)[:-1] + "\");"
|
||||
#if (!purple_util_set_user_wrapped)
|
||||
print >> cpp, "\tif (!" + get_name(d)[:-1] + "_wrapped)"
|
||||
print >> cpp, "\t\treturn false;"
|
||||
print >> cpp, ""
|
||||
print >> cpp, "#endif"
|
||||
|
||||
print >> cpp, "\treturn true;"
|
||||
print >> cpp, "}"
|
||||
print >> cpp, ""
|
||||
|
||||
cpp.close()
|
||||
header.close()
|
||||
|
||||
|
||||
for f in os.listdir("."):
|
||||
if not f.endswith(".cpp") or f.startswith("purple_defs"):
|
||||
continue
|
||||
new_file = handle_file(f)
|
||||
|
||||
print "updating", f
|
||||
fd = open(f, "w")
|
||||
fd.write(new_file)
|
||||
fd.close()
|
||||
|
||||
for f in os.listdir(sys.argv[1]):
|
||||
if not f.endswith(".h"):
|
||||
continue
|
||||
for m in methods:
|
||||
handle_header(f, m)
|
||||
|
||||
sys.argv[1] = sys.argv[1] + "/win32"
|
||||
for f in os.listdir(sys.argv[1]):
|
||||
if not f.endswith(".h"):
|
||||
continue
|
||||
for m in methods:
|
||||
handle_header(f, m)
|
||||
|
||||
for m in methods:
|
||||
found = False
|
||||
for d in definitions:
|
||||
if d.find(m[:-1]) != -1:
|
||||
found = True
|
||||
break
|
||||
if not found:
|
||||
print "NOT FOUND:", m
|
||||
|
||||
output()
|
|
@ -1,265 +0,0 @@
|
|||
/**
|
||||
* XMPP - libpurple transport
|
||||
*
|
||||
* Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
|
||||
#include "geventloop.h"
|
||||
#ifdef _WIN32
|
||||
#include "win32/win32dep.h"
|
||||
#undef read
|
||||
#undef write
|
||||
#endif
|
||||
#ifdef WITH_LIBEVENT
|
||||
#include "event.h"
|
||||
#endif
|
||||
|
||||
#include "purple_defs.h"
|
||||
|
||||
#include "transport/Logging.h"
|
||||
|
||||
DEFINE_LOGGER(logger, "EventLoop");
|
||||
|
||||
typedef struct _PurpleIOClosure {
|
||||
PurpleInputFunction function;
|
||||
guint result;
|
||||
gpointer data;
|
||||
#ifdef WITH_LIBEVENT
|
||||
GSourceFunc function2;
|
||||
struct timeval timeout;
|
||||
struct event evfifo;
|
||||
#endif
|
||||
} PurpleIOClosure;
|
||||
|
||||
static gboolean io_invoke(GIOChannel *source,
|
||||
GIOCondition condition,
|
||||
gpointer data)
|
||||
{
|
||||
PurpleIOClosure *closure = (PurpleIOClosure* )data;
|
||||
PurpleInputCondition purple_cond = (PurpleInputCondition)0;
|
||||
|
||||
int tmp = 0;
|
||||
if (condition & READ_COND)
|
||||
{
|
||||
tmp |= PURPLE_INPUT_READ;
|
||||
purple_cond = (PurpleInputCondition)tmp;
|
||||
}
|
||||
if (condition & WRITE_COND)
|
||||
{
|
||||
tmp |= PURPLE_INPUT_WRITE;
|
||||
purple_cond = (PurpleInputCondition)tmp;
|
||||
}
|
||||
|
||||
closure->function(closure->data, g_io_channel_unix_get_fd(source), purple_cond);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void io_destroy(gpointer data)
|
||||
{
|
||||
g_free(data);
|
||||
}
|
||||
|
||||
static guint input_add(gint fd,
|
||||
PurpleInputCondition condition,
|
||||
PurpleInputFunction function,
|
||||
gpointer data)
|
||||
{
|
||||
PurpleIOClosure *closure = g_new0(PurpleIOClosure, 1);
|
||||
GIOChannel *channel;
|
||||
GIOCondition cond = (GIOCondition)0;
|
||||
closure->function = function;
|
||||
closure->data = data;
|
||||
|
||||
int tmp = 0;
|
||||
if (condition & PURPLE_INPUT_READ)
|
||||
{
|
||||
tmp |= READ_COND;
|
||||
cond = (GIOCondition)tmp;
|
||||
}
|
||||
if (condition & PURPLE_INPUT_WRITE)
|
||||
{
|
||||
tmp |= WRITE_COND;
|
||||
cond = (GIOCondition)tmp;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
channel = wpurple_g_io_channel_win32_new_socket_wrapped(fd);
|
||||
#else
|
||||
channel = g_io_channel_unix_new(fd);
|
||||
#endif
|
||||
closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond,
|
||||
io_invoke, closure, io_destroy);
|
||||
|
||||
g_io_channel_unref(channel);
|
||||
return closure->result;
|
||||
}
|
||||
|
||||
static PurpleEventLoopUiOps eventLoopOps =
|
||||
{
|
||||
g_timeout_add,
|
||||
g_source_remove,
|
||||
input_add,
|
||||
g_source_remove,
|
||||
NULL,
|
||||
#if GLIB_CHECK_VERSION(2,14,0)
|
||||
g_timeout_add_seconds,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
#ifdef WITH_LIBEVENT
|
||||
|
||||
static GHashTable *events = NULL;
|
||||
static unsigned long id = 0;
|
||||
|
||||
static void event_io_destroy(gpointer data)
|
||||
{
|
||||
PurpleIOClosure *closure = (PurpleIOClosure* )data;
|
||||
event_del(&closure->evfifo);
|
||||
g_free(data);
|
||||
}
|
||||
|
||||
static void event_io_invoke(int fd, short event, void *data)
|
||||
{
|
||||
PurpleIOClosure *closure = (PurpleIOClosure* )data;
|
||||
PurpleInputCondition purple_cond = (PurpleInputCondition)0;
|
||||
int tmp = 0;
|
||||
if (event & EV_READ)
|
||||
{
|
||||
tmp |= PURPLE_INPUT_READ;
|
||||
purple_cond = (PurpleInputCondition)tmp;
|
||||
}
|
||||
if (event & EV_WRITE)
|
||||
{
|
||||
tmp |= PURPLE_INPUT_WRITE;
|
||||
purple_cond = (PurpleInputCondition)tmp;
|
||||
}
|
||||
if (event & EV_TIMEOUT)
|
||||
{
|
||||
// tmp |= PURPLE_INPUT_WRITE;
|
||||
// purple_cond = (PurpleInputCondition)tmp;
|
||||
LOG4CXX_INFO(logger, "before timer callback " << closure->function2);
|
||||
if (closure->function2(closure->data))
|
||||
evtimer_add(&closure->evfifo, &closure->timeout);
|
||||
LOG4CXX_INFO(logger, "after timer callback" << closure->function2);
|
||||
// else
|
||||
// event_io_destroy(data);
|
||||
return;
|
||||
}
|
||||
LOG4CXX_INFO(logger, "before callback " << closure->function);
|
||||
closure->function(closure->data, fd, purple_cond);
|
||||
LOG4CXX_INFO(logger, "after callback" << closure->function);
|
||||
}
|
||||
|
||||
static gboolean event_input_remove(guint handle)
|
||||
{
|
||||
PurpleIOClosure *closure = (PurpleIOClosure *) g_hash_table_lookup(events, &handle);
|
||||
if (closure)
|
||||
event_io_destroy(closure);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static guint event_input_add(gint fd,
|
||||
PurpleInputCondition condition,
|
||||
PurpleInputFunction function,
|
||||
gpointer data)
|
||||
{
|
||||
PurpleIOClosure *closure = g_new0(PurpleIOClosure, 1);
|
||||
GIOChannel *channel;
|
||||
GIOCondition cond = (GIOCondition)0;
|
||||
closure->function = function;
|
||||
closure->data = data;
|
||||
|
||||
int tmp = EV_PERSIST;
|
||||
if (condition & PURPLE_INPUT_READ)
|
||||
{
|
||||
tmp |= EV_READ;
|
||||
}
|
||||
if (condition & PURPLE_INPUT_WRITE)
|
||||
{
|
||||
tmp |= EV_WRITE;
|
||||
}
|
||||
|
||||
event_set(&closure->evfifo, fd, tmp, event_io_invoke, closure);
|
||||
event_add(&closure->evfifo, NULL);
|
||||
|
||||
int *f = (int *) g_malloc(sizeof(int));
|
||||
*f = id;
|
||||
id++;
|
||||
g_hash_table_replace(events, f, closure);
|
||||
|
||||
return *f;
|
||||
}
|
||||
|
||||
static guint event_timeout_add (guint interval, GSourceFunc function, gpointer data) {
|
||||
struct timeval timeout;
|
||||
PurpleIOClosure *closure = g_new0(PurpleIOClosure, 1);
|
||||
closure->function2 = function;
|
||||
closure->data = data;
|
||||
|
||||
timeout.tv_sec = interval/1000;
|
||||
timeout.tv_usec = (interval%1000)*1000;
|
||||
evtimer_set(&closure->evfifo, event_io_invoke, closure);
|
||||
evtimer_add(&closure->evfifo, &timeout);
|
||||
closure->timeout = timeout;
|
||||
|
||||
guint *f = (guint *) g_malloc(sizeof(guint));
|
||||
*f = id;
|
||||
id++;
|
||||
g_hash_table_replace(events, f, closure);
|
||||
return *f;
|
||||
}
|
||||
|
||||
static PurpleEventLoopUiOps libEventLoopOps =
|
||||
{
|
||||
event_timeout_add,
|
||||
event_input_remove,
|
||||
event_input_add,
|
||||
event_input_remove,
|
||||
NULL,
|
||||
// #if GLIB_CHECK_VERSION(2,14,0)
|
||||
// g_timeout_add_seconds,
|
||||
// #else
|
||||
NULL,
|
||||
// #endif
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
#endif /* WITH_LIBEVENT*/
|
||||
|
||||
PurpleEventLoopUiOps * getEventLoopUiOps(bool libev){
|
||||
#ifdef WITH_LIBEVENT
|
||||
if (libev) {
|
||||
event_init();
|
||||
events = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL);
|
||||
return &libEventLoopOps;
|
||||
}
|
||||
else {
|
||||
return &eventLoopOps;
|
||||
}
|
||||
#endif
|
||||
return &eventLoopOps;
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
/**
|
||||
* XMPP - libpurple transport
|
||||
*
|
||||
* Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _HI_EVENTLOOP_H
|
||||
#define _HI_EVENTLOOP_H
|
||||
|
||||
#include <glib.h>
|
||||
#include "purple.h"
|
||||
#include "eventloop.h"
|
||||
|
||||
#define READ_COND (G_IO_IN | G_IO_HUP | G_IO_ERR)
|
||||
#define WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL)
|
||||
|
||||
PurpleEventLoopUiOps * getEventLoopUiOps(bool libev);
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -1,739 +0,0 @@
|
|||
#include "purple_defs.h"
|
||||
|
||||
#if PURPLE_RUNTIME
|
||||
static HMODULE f_hPurple = NULL;
|
||||
purple_account_set_bool_wrapped_fnc purple_account_set_bool_wrapped = NULL;
|
||||
purple_account_get_protocol_id_wrapped_fnc purple_account_get_protocol_id_wrapped = NULL;
|
||||
purple_account_set_int_wrapped_fnc purple_account_set_int_wrapped = NULL;
|
||||
purple_account_set_string_wrapped_fnc purple_account_set_string_wrapped = NULL;
|
||||
purple_account_get_username_wrapped_fnc purple_account_get_username_wrapped = NULL;
|
||||
purple_account_set_username_wrapped_fnc purple_account_set_username_wrapped = NULL;
|
||||
purple_account_set_proxy_info_wrapped_fnc purple_account_set_proxy_info_wrapped = NULL;
|
||||
purple_accounts_find_wrapped_fnc purple_accounts_find_wrapped = NULL;
|
||||
purple_account_new_wrapped_fnc purple_account_new_wrapped = NULL;
|
||||
purple_accounts_add_wrapped_fnc purple_accounts_add_wrapped = NULL;
|
||||
purple_account_get_password_wrapped_fnc purple_account_get_password_wrapped = NULL;
|
||||
purple_account_set_password_wrapped_fnc purple_account_set_password_wrapped = NULL;
|
||||
purple_account_set_enabled_wrapped_fnc purple_account_set_enabled_wrapped = NULL;
|
||||
purple_account_set_privacy_type_wrapped_fnc purple_account_set_privacy_type_wrapped = NULL;
|
||||
purple_account_get_status_type_with_primitive_wrapped_fnc purple_account_get_status_type_with_primitive_wrapped = NULL;
|
||||
purple_account_set_status_wrapped_fnc purple_account_set_status_wrapped = NULL;
|
||||
purple_account_get_int_wrapped_fnc purple_account_get_int_wrapped = NULL;
|
||||
purple_account_disconnect_wrapped_fnc purple_account_disconnect_wrapped = NULL;
|
||||
purple_accounts_delete_wrapped_fnc purple_accounts_delete_wrapped = NULL;
|
||||
purple_account_get_connection_wrapped_fnc purple_account_get_connection_wrapped = NULL;
|
||||
purple_account_set_alias_wrapped_fnc purple_account_set_alias_wrapped = NULL;
|
||||
purple_account_set_public_alias_wrapped_fnc purple_account_set_public_alias_wrapped = NULL;
|
||||
purple_account_remove_buddy_wrapped_fnc purple_account_remove_buddy_wrapped = NULL;
|
||||
purple_account_add_buddy_wrapped_fnc purple_account_add_buddy_wrapped = NULL;
|
||||
purple_account_get_name_for_display_wrapped_fnc purple_account_get_name_for_display_wrapped = NULL;
|
||||
purple_accounts_set_ui_ops_wrapped_fnc purple_accounts_set_ui_ops_wrapped = NULL;
|
||||
purple_account_option_get_type_wrapped_fnc purple_account_option_get_type_wrapped = NULL;
|
||||
purple_account_option_get_setting_wrapped_fnc purple_account_option_get_setting_wrapped = NULL;
|
||||
purple_blist_node_get_type_wrapped_fnc purple_blist_node_get_type_wrapped = NULL;
|
||||
purple_buddy_get_alias_wrapped_fnc purple_buddy_get_alias_wrapped = NULL;
|
||||
purple_buddy_get_server_alias_wrapped_fnc purple_buddy_get_server_alias_wrapped = NULL;
|
||||
purple_find_buddy_wrapped_fnc purple_find_buddy_wrapped = NULL;
|
||||
purple_buddy_get_group_wrapped_fnc purple_buddy_get_group_wrapped = NULL;
|
||||
purple_blist_remove_buddy_wrapped_fnc purple_blist_remove_buddy_wrapped = NULL;
|
||||
purple_blist_alias_buddy_wrapped_fnc purple_blist_alias_buddy_wrapped = NULL;
|
||||
purple_blist_server_alias_buddy_wrapped_fnc purple_blist_server_alias_buddy_wrapped = NULL;
|
||||
purple_find_group_wrapped_fnc purple_find_group_wrapped = NULL;
|
||||
purple_group_new_wrapped_fnc purple_group_new_wrapped = NULL;
|
||||
purple_blist_add_contact_wrapped_fnc purple_blist_add_contact_wrapped = NULL;
|
||||
purple_buddy_get_contact_wrapped_fnc purple_buddy_get_contact_wrapped = NULL;
|
||||
purple_buddy_new_wrapped_fnc purple_buddy_new_wrapped = NULL;
|
||||
purple_blist_add_buddy_wrapped_fnc purple_blist_add_buddy_wrapped = NULL;
|
||||
purple_blist_find_chat_wrapped_fnc purple_blist_find_chat_wrapped = NULL;
|
||||
purple_chat_get_components_wrapped_fnc purple_chat_get_components_wrapped = NULL;
|
||||
purple_buddy_get_presence_wrapped_fnc purple_buddy_get_presence_wrapped = NULL;
|
||||
purple_buddy_get_account_wrapped_fnc purple_buddy_get_account_wrapped = NULL;
|
||||
purple_buddy_get_name_wrapped_fnc purple_buddy_get_name_wrapped = NULL;
|
||||
purple_find_buddies_wrapped_fnc purple_find_buddies_wrapped = NULL;
|
||||
purple_group_get_name_wrapped_fnc purple_group_get_name_wrapped = NULL;
|
||||
purple_blist_set_ui_ops_wrapped_fnc purple_blist_set_ui_ops_wrapped = NULL;
|
||||
purple_set_blist_wrapped_fnc purple_set_blist_wrapped = NULL;
|
||||
purple_blist_new_wrapped_fnc purple_blist_new_wrapped = NULL;
|
||||
purple_blist_load_wrapped_fnc purple_blist_load_wrapped = NULL;
|
||||
purple_blist_get_handle_wrapped_fnc purple_blist_get_handle_wrapped = NULL;
|
||||
purple_buddy_icons_set_account_icon_wrapped_fnc purple_buddy_icons_set_account_icon_wrapped = NULL;
|
||||
purple_buddy_icons_find_wrapped_fnc purple_buddy_icons_find_wrapped = NULL;
|
||||
purple_buddy_icon_get_full_path_wrapped_fnc purple_buddy_icon_get_full_path_wrapped = NULL;
|
||||
purple_buddy_icon_unref_wrapped_fnc purple_buddy_icon_unref_wrapped = NULL;
|
||||
purple_buddy_icons_find_account_icon_wrapped_fnc purple_buddy_icons_find_account_icon_wrapped = NULL;
|
||||
purple_buddy_icon_get_data_wrapped_fnc purple_buddy_icon_get_data_wrapped = NULL;
|
||||
purple_certificate_add_ca_search_path_wrapped_fnc purple_certificate_add_ca_search_path_wrapped = NULL;
|
||||
purple_connection_get_state_wrapped_fnc purple_connection_get_state_wrapped = NULL;
|
||||
purple_connection_get_account_wrapped_fnc purple_connection_get_account_wrapped = NULL;
|
||||
purple_connection_get_display_name_wrapped_fnc purple_connection_get_display_name_wrapped = NULL;
|
||||
purple_connections_set_ui_ops_wrapped_fnc purple_connections_set_ui_ops_wrapped = NULL;
|
||||
purple_connections_get_handle_wrapped_fnc purple_connections_get_handle_wrapped = NULL;
|
||||
purple_conversation_get_im_data_wrapped_fnc purple_conversation_get_im_data_wrapped = NULL;
|
||||
purple_conversation_get_chat_data_wrapped_fnc purple_conversation_get_chat_data_wrapped = NULL;
|
||||
purple_find_conversation_with_account_wrapped_fnc purple_find_conversation_with_account_wrapped = NULL;
|
||||
purple_conversation_new_wrapped_fnc purple_conversation_new_wrapped = NULL;
|
||||
purple_conversation_get_type_wrapped_fnc purple_conversation_get_type_wrapped = NULL;
|
||||
purple_conv_im_send_wrapped_fnc purple_conv_im_send_wrapped = NULL;
|
||||
purple_conv_chat_send_wrapped_fnc purple_conv_chat_send_wrapped = NULL;
|
||||
purple_conversation_destroy_wrapped_fnc purple_conversation_destroy_wrapped = NULL;
|
||||
purple_conversation_get_account_wrapped_fnc purple_conversation_get_account_wrapped = NULL;
|
||||
purple_conversation_get_name_wrapped_fnc purple_conversation_get_name_wrapped = NULL;
|
||||
purple_conversations_set_ui_ops_wrapped_fnc purple_conversations_set_ui_ops_wrapped = NULL;
|
||||
purple_conversations_get_handle_wrapped_fnc purple_conversations_get_handle_wrapped = NULL;
|
||||
purple_core_set_ui_ops_wrapped_fnc purple_core_set_ui_ops_wrapped = NULL;
|
||||
purple_core_init_wrapped_fnc purple_core_init_wrapped = NULL;
|
||||
purple_debug_set_ui_ops_wrapped_fnc purple_debug_set_ui_ops_wrapped = NULL;
|
||||
purple_debug_set_verbose_wrapped_fnc purple_debug_set_verbose_wrapped = NULL;
|
||||
purple_dnsquery_set_ui_ops_wrapped_fnc purple_dnsquery_set_ui_ops_wrapped = NULL;
|
||||
purple_timeout_remove_wrapped_fnc purple_timeout_remove_wrapped = NULL;
|
||||
purple_input_add_wrapped_fnc purple_input_add_wrapped = NULL;
|
||||
purple_timeout_add_wrapped_fnc purple_timeout_add_wrapped = NULL;
|
||||
purple_timeout_add_seconds_wrapped_fnc purple_timeout_add_seconds_wrapped = NULL;
|
||||
purple_eventloop_set_ui_ops_wrapped_fnc purple_eventloop_set_ui_ops_wrapped = NULL;
|
||||
purple_input_remove_wrapped_fnc purple_input_remove_wrapped = NULL;
|
||||
purple_xfer_ui_ready_wrapped_fnc purple_xfer_ui_ready_wrapped = NULL;
|
||||
purple_xfer_request_accepted_wrapped_fnc purple_xfer_request_accepted_wrapped = NULL;
|
||||
purple_xfer_request_denied_wrapped_fnc purple_xfer_request_denied_wrapped = NULL;
|
||||
purple_xfer_get_account_wrapped_fnc purple_xfer_get_account_wrapped = NULL;
|
||||
purple_xfer_get_filename_wrapped_fnc purple_xfer_get_filename_wrapped = NULL;
|
||||
purple_xfer_get_size_wrapped_fnc purple_xfer_get_size_wrapped = NULL;
|
||||
purple_xfer_unref_wrapped_fnc purple_xfer_unref_wrapped = NULL;
|
||||
purple_xfer_ref_wrapped_fnc purple_xfer_ref_wrapped = NULL;
|
||||
purple_xfers_set_ui_ops_wrapped_fnc purple_xfers_set_ui_ops_wrapped = NULL;
|
||||
purple_xfers_get_handle_wrapped_fnc purple_xfers_get_handle_wrapped = NULL;
|
||||
purple_roomlist_set_ui_ops_wrapped_fnc purple_roomlist_set_ui_ops_wrapped = NULL;
|
||||
purple_roomlist_get_list_wrapped_fnc purple_roomlist_get_list_wrapped = NULL;
|
||||
purple_imgstore_get_data_wrapped_fnc purple_imgstore_get_data_wrapped = NULL;
|
||||
purple_imgstore_get_size_wrapped_fnc purple_imgstore_get_size_wrapped = NULL;
|
||||
purple_imgstore_unref_wrapped_fnc purple_imgstore_unref_wrapped = NULL;
|
||||
purple_notify_user_info_new_wrapped_fnc purple_notify_user_info_new_wrapped = NULL;
|
||||
purple_notify_user_info_destroy_wrapped_fnc purple_notify_user_info_destroy_wrapped = NULL;
|
||||
purple_notify_user_info_get_entries_wrapped_fnc purple_notify_user_info_get_entries_wrapped = NULL;
|
||||
purple_notify_user_info_entry_get_label_wrapped_fnc purple_notify_user_info_entry_get_label_wrapped = NULL;
|
||||
purple_notify_user_info_entry_get_value_wrapped_fnc purple_notify_user_info_entry_get_value_wrapped = NULL;
|
||||
purple_notify_set_ui_ops_wrapped_fnc purple_notify_set_ui_ops_wrapped = NULL;
|
||||
purple_plugins_add_search_path_wrapped_fnc purple_plugins_add_search_path_wrapped = NULL;
|
||||
purple_plugin_action_free_wrapped_fnc purple_plugin_action_free_wrapped = NULL;
|
||||
purple_prefs_load_wrapped_fnc purple_prefs_load_wrapped = NULL;
|
||||
purple_prefs_set_bool_wrapped_fnc purple_prefs_set_bool_wrapped = NULL;
|
||||
purple_prefs_set_string_wrapped_fnc purple_prefs_set_string_wrapped = NULL;
|
||||
purple_privacy_deny_wrapped_fnc purple_privacy_deny_wrapped = NULL;
|
||||
purple_privacy_allow_wrapped_fnc purple_privacy_allow_wrapped = NULL;
|
||||
purple_privacy_check_wrapped_fnc purple_privacy_check_wrapped = NULL;
|
||||
purple_proxy_info_new_wrapped_fnc purple_proxy_info_new_wrapped = NULL;
|
||||
purple_proxy_info_set_type_wrapped_fnc purple_proxy_info_set_type_wrapped = NULL;
|
||||
purple_proxy_info_set_host_wrapped_fnc purple_proxy_info_set_host_wrapped = NULL;
|
||||
purple_proxy_info_set_port_wrapped_fnc purple_proxy_info_set_port_wrapped = NULL;
|
||||
purple_proxy_info_set_username_wrapped_fnc purple_proxy_info_set_username_wrapped = NULL;
|
||||
purple_proxy_info_set_password_wrapped_fnc purple_proxy_info_set_password_wrapped = NULL;
|
||||
purple_find_prpl_wrapped_fnc purple_find_prpl_wrapped = NULL;
|
||||
purple_prpl_send_attention_wrapped_fnc purple_prpl_send_attention_wrapped = NULL;
|
||||
purple_request_set_ui_ops_wrapped_fnc purple_request_set_ui_ops_wrapped = NULL;
|
||||
serv_get_info_wrapped_fnc serv_get_info_wrapped = NULL;
|
||||
serv_alias_buddy_wrapped_fnc serv_alias_buddy_wrapped = NULL;
|
||||
serv_send_typing_wrapped_fnc serv_send_typing_wrapped = NULL;
|
||||
serv_join_chat_wrapped_fnc serv_join_chat_wrapped = NULL;
|
||||
purple_signal_connect_wrapped_fnc purple_signal_connect_wrapped = NULL;
|
||||
purple_status_type_get_id_wrapped_fnc purple_status_type_get_id_wrapped = NULL;
|
||||
purple_presence_get_active_status_wrapped_fnc purple_presence_get_active_status_wrapped = NULL;
|
||||
purple_status_type_get_primitive_wrapped_fnc purple_status_type_get_primitive_wrapped = NULL;
|
||||
purple_status_get_type_wrapped_fnc purple_status_get_type_wrapped = NULL;
|
||||
purple_status_get_attr_string_wrapped_fnc purple_status_get_attr_string_wrapped = NULL;
|
||||
purple_markup_escape_text_wrapped_fnc purple_markup_escape_text_wrapped = NULL;
|
||||
purple_markup_strip_html_wrapped_fnc purple_markup_strip_html_wrapped = NULL;
|
||||
purple_strdup_withhtml_wrapped_fnc purple_strdup_withhtml_wrapped = NULL;
|
||||
purple_markup_html_to_xhtml_wrapped_fnc purple_markup_html_to_xhtml_wrapped = NULL;
|
||||
purple_normalize_wrapped_fnc purple_normalize_wrapped = NULL;
|
||||
purple_utf8_try_convert_wrapped_fnc purple_utf8_try_convert_wrapped = NULL;
|
||||
purple_util_set_user_dir_wrapped_fnc purple_util_set_user_dir_wrapped = NULL;
|
||||
wpurple_g_io_channel_win32_new_socket_wrapped_fnc wpurple_g_io_channel_win32_new_socket_wrapped = NULL;
|
||||
#endif
|
||||
bool resolvePurpleFunctions() {
|
||||
#if PURPLE_RUNTIME
|
||||
f_hPurple = LoadLibrary(L"libpurple.dll");
|
||||
if (!f_hPurple)
|
||||
return false;
|
||||
purple_account_set_bool_wrapped = (purple_account_set_bool_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_set_bool");
|
||||
if (!purple_account_set_bool_wrapped)
|
||||
return false;
|
||||
|
||||
purple_account_get_protocol_id_wrapped = (purple_account_get_protocol_id_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_get_protocol_id");
|
||||
if (!purple_account_get_protocol_id_wrapped)
|
||||
return false;
|
||||
|
||||
purple_account_set_int_wrapped = (purple_account_set_int_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_set_int");
|
||||
if (!purple_account_set_int_wrapped)
|
||||
return false;
|
||||
|
||||
purple_account_set_string_wrapped = (purple_account_set_string_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_set_string");
|
||||
if (!purple_account_set_string_wrapped)
|
||||
return false;
|
||||
|
||||
purple_account_get_username_wrapped = (purple_account_get_username_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_get_username");
|
||||
if (!purple_account_get_username_wrapped)
|
||||
return false;
|
||||
|
||||
purple_account_set_username_wrapped = (purple_account_set_username_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_set_username");
|
||||
if (!purple_account_set_username_wrapped)
|
||||
return false;
|
||||
|
||||
purple_account_set_proxy_info_wrapped = (purple_account_set_proxy_info_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_set_proxy_info");
|
||||
if (!purple_account_set_proxy_info_wrapped)
|
||||
return false;
|
||||
|
||||
purple_accounts_find_wrapped = (purple_accounts_find_wrapped_fnc)GetProcAddress(f_hPurple, "purple_accounts_find");
|
||||
if (!purple_accounts_find_wrapped)
|
||||
return false;
|
||||
|
||||
purple_account_new_wrapped = (purple_account_new_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_new");
|
||||
if (!purple_account_new_wrapped)
|
||||
return false;
|
||||
|
||||
purple_accounts_add_wrapped = (purple_accounts_add_wrapped_fnc)GetProcAddress(f_hPurple, "purple_accounts_add");
|
||||
if (!purple_accounts_add_wrapped)
|
||||
return false;
|
||||
|
||||
purple_account_get_password_wrapped = (purple_account_get_password_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_get_password");
|
||||
if (!purple_account_get_password_wrapped)
|
||||
return false;
|
||||
|
||||
purple_account_set_password_wrapped = (purple_account_set_password_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_set_password");
|
||||
if (!purple_account_set_password_wrapped)
|
||||
return false;
|
||||
|
||||
purple_account_set_enabled_wrapped = (purple_account_set_enabled_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_set_enabled");
|
||||
if (!purple_account_set_enabled_wrapped)
|
||||
return false;
|
||||
|
||||
purple_account_set_privacy_type_wrapped = (purple_account_set_privacy_type_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_set_privacy_type");
|
||||
if (!purple_account_set_privacy_type_wrapped)
|
||||
return false;
|
||||
|
||||
purple_account_get_status_type_with_primitive_wrapped = (purple_account_get_status_type_with_primitive_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_get_status_type_with_primitive");
|
||||
if (!purple_account_get_status_type_with_primitive_wrapped)
|
||||
return false;
|
||||
|
||||
purple_account_set_status_wrapped = (purple_account_set_status_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_set_status");
|
||||
if (!purple_account_set_status_wrapped)
|
||||
return false;
|
||||
|
||||
purple_account_get_int_wrapped = (purple_account_get_int_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_get_int");
|
||||
if (!purple_account_get_int_wrapped)
|
||||
return false;
|
||||
|
||||
purple_account_disconnect_wrapped = (purple_account_disconnect_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_disconnect");
|
||||
if (!purple_account_disconnect_wrapped)
|
||||
return false;
|
||||
|
||||
purple_accounts_delete_wrapped = (purple_accounts_delete_wrapped_fnc)GetProcAddress(f_hPurple, "purple_accounts_delete");
|
||||
if (!purple_accounts_delete_wrapped)
|
||||
return false;
|
||||
|
||||
purple_account_get_connection_wrapped = (purple_account_get_connection_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_get_connection");
|
||||
if (!purple_account_get_connection_wrapped)
|
||||
return false;
|
||||
|
||||
purple_account_set_alias_wrapped = (purple_account_set_alias_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_set_alias");
|
||||
if (!purple_account_set_alias_wrapped)
|
||||
return false;
|
||||
|
||||
purple_account_set_public_alias_wrapped = (purple_account_set_public_alias_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_set_public_alias");
|
||||
if (!purple_account_set_public_alias_wrapped)
|
||||
return false;
|
||||
|
||||
purple_account_remove_buddy_wrapped = (purple_account_remove_buddy_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_remove_buddy");
|
||||
if (!purple_account_remove_buddy_wrapped)
|
||||
return false;
|
||||
|
||||
purple_account_add_buddy_wrapped = (purple_account_add_buddy_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_add_buddy");
|
||||
if (!purple_account_add_buddy_wrapped)
|
||||
return false;
|
||||
|
||||
purple_account_get_name_for_display_wrapped = (purple_account_get_name_for_display_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_get_name_for_display");
|
||||
if (!purple_account_get_name_for_display_wrapped)
|
||||
return false;
|
||||
|
||||
purple_accounts_set_ui_ops_wrapped = (purple_accounts_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_accounts_set_ui_ops");
|
||||
if (!purple_accounts_set_ui_ops_wrapped)
|
||||
return false;
|
||||
|
||||
purple_account_option_get_type_wrapped = (purple_account_option_get_type_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_option_get_type");
|
||||
if (!purple_account_option_get_type_wrapped)
|
||||
return false;
|
||||
|
||||
purple_account_option_get_setting_wrapped = (purple_account_option_get_setting_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_option_get_setting");
|
||||
if (!purple_account_option_get_setting_wrapped)
|
||||
return false;
|
||||
|
||||
purple_blist_node_get_type_wrapped = (purple_blist_node_get_type_wrapped_fnc)GetProcAddress(f_hPurple, "purple_blist_node_get_type");
|
||||
if (!purple_blist_node_get_type_wrapped)
|
||||
return false;
|
||||
|
||||
purple_buddy_get_alias_wrapped = (purple_buddy_get_alias_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_get_alias");
|
||||
if (!purple_buddy_get_alias_wrapped)
|
||||
return false;
|
||||
|
||||
purple_buddy_get_server_alias_wrapped = (purple_buddy_get_server_alias_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_get_server_alias");
|
||||
if (!purple_buddy_get_server_alias_wrapped)
|
||||
return false;
|
||||
|
||||
purple_find_buddy_wrapped = (purple_find_buddy_wrapped_fnc)GetProcAddress(f_hPurple, "purple_find_buddy");
|
||||
if (!purple_find_buddy_wrapped)
|
||||
return false;
|
||||
|
||||
purple_buddy_get_group_wrapped = (purple_buddy_get_group_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_get_group");
|
||||
if (!purple_buddy_get_group_wrapped)
|
||||
return false;
|
||||
|
||||
purple_blist_remove_buddy_wrapped = (purple_blist_remove_buddy_wrapped_fnc)GetProcAddress(f_hPurple, "purple_blist_remove_buddy");
|
||||
if (!purple_blist_remove_buddy_wrapped)
|
||||
return false;
|
||||
|
||||
purple_blist_alias_buddy_wrapped = (purple_blist_alias_buddy_wrapped_fnc)GetProcAddress(f_hPurple, "purple_blist_alias_buddy");
|
||||
if (!purple_blist_alias_buddy_wrapped)
|
||||
return false;
|
||||
|
||||
purple_blist_server_alias_buddy_wrapped = (purple_blist_server_alias_buddy_wrapped_fnc)GetProcAddress(f_hPurple, "purple_blist_server_alias_buddy");
|
||||
if (!purple_blist_server_alias_buddy_wrapped)
|
||||
return false;
|
||||
|
||||
purple_find_group_wrapped = (purple_find_group_wrapped_fnc)GetProcAddress(f_hPurple, "purple_find_group");
|
||||
if (!purple_find_group_wrapped)
|
||||
return false;
|
||||
|
||||
purple_group_new_wrapped = (purple_group_new_wrapped_fnc)GetProcAddress(f_hPurple, "purple_group_new");
|
||||
if (!purple_group_new_wrapped)
|
||||
return false;
|
||||
|
||||
purple_blist_add_contact_wrapped = (purple_blist_add_contact_wrapped_fnc)GetProcAddress(f_hPurple, "purple_blist_add_contact");
|
||||
if (!purple_blist_add_contact_wrapped)
|
||||
return false;
|
||||
|
||||
purple_buddy_get_contact_wrapped = (purple_buddy_get_contact_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_get_contact");
|
||||
if (!purple_buddy_get_contact_wrapped)
|
||||
return false;
|
||||
|
||||
purple_buddy_new_wrapped = (purple_buddy_new_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_new");
|
||||
if (!purple_buddy_new_wrapped)
|
||||
return false;
|
||||
|
||||
purple_blist_add_buddy_wrapped = (purple_blist_add_buddy_wrapped_fnc)GetProcAddress(f_hPurple, "purple_blist_add_buddy");
|
||||
if (!purple_blist_add_buddy_wrapped)
|
||||
return false;
|
||||
|
||||
purple_blist_find_chat_wrapped = (purple_blist_find_chat_wrapped_fnc)GetProcAddress(f_hPurple, "purple_blist_find_chat");
|
||||
if (!purple_blist_find_chat_wrapped)
|
||||
return false;
|
||||
|
||||
purple_chat_get_components_wrapped = (purple_chat_get_components_wrapped_fnc)GetProcAddress(f_hPurple, "purple_chat_get_components");
|
||||
if (!purple_chat_get_components_wrapped)
|
||||
return false;
|
||||
|
||||
purple_buddy_get_presence_wrapped = (purple_buddy_get_presence_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_get_presence");
|
||||
if (!purple_buddy_get_presence_wrapped)
|
||||
return false;
|
||||
|
||||
purple_buddy_get_account_wrapped = (purple_buddy_get_account_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_get_account");
|
||||
if (!purple_buddy_get_account_wrapped)
|
||||
return false;
|
||||
|
||||
purple_buddy_get_name_wrapped = (purple_buddy_get_name_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_get_name");
|
||||
if (!purple_buddy_get_name_wrapped)
|
||||
return false;
|
||||
|
||||
purple_find_buddies_wrapped = (purple_find_buddies_wrapped_fnc)GetProcAddress(f_hPurple, "purple_find_buddies");
|
||||
if (!purple_find_buddies_wrapped)
|
||||
return false;
|
||||
|
||||
purple_group_get_name_wrapped = (purple_group_get_name_wrapped_fnc)GetProcAddress(f_hPurple, "purple_group_get_name");
|
||||
if (!purple_group_get_name_wrapped)
|
||||
return false;
|
||||
|
||||
purple_blist_set_ui_ops_wrapped = (purple_blist_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_blist_set_ui_ops");
|
||||
if (!purple_blist_set_ui_ops_wrapped)
|
||||
return false;
|
||||
|
||||
purple_set_blist_wrapped = (purple_set_blist_wrapped_fnc)GetProcAddress(f_hPurple, "purple_set_blist");
|
||||
if (!purple_set_blist_wrapped)
|
||||
return false;
|
||||
|
||||
purple_blist_new_wrapped = (purple_blist_new_wrapped_fnc)GetProcAddress(f_hPurple, "purple_blist_new");
|
||||
if (!purple_blist_new_wrapped)
|
||||
return false;
|
||||
|
||||
purple_blist_load_wrapped = (purple_blist_load_wrapped_fnc)GetProcAddress(f_hPurple, "purple_blist_load");
|
||||
if (!purple_blist_load_wrapped)
|
||||
return false;
|
||||
|
||||
purple_blist_get_handle_wrapped = (purple_blist_get_handle_wrapped_fnc)GetProcAddress(f_hPurple, "purple_blist_get_handle");
|
||||
if (!purple_blist_get_handle_wrapped)
|
||||
return false;
|
||||
|
||||
purple_buddy_icons_set_account_icon_wrapped = (purple_buddy_icons_set_account_icon_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_icons_set_account_icon");
|
||||
if (!purple_buddy_icons_set_account_icon_wrapped)
|
||||
return false;
|
||||
|
||||
purple_buddy_icons_find_wrapped = (purple_buddy_icons_find_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_icons_find");
|
||||
if (!purple_buddy_icons_find_wrapped)
|
||||
return false;
|
||||
|
||||
purple_buddy_icon_get_full_path_wrapped = (purple_buddy_icon_get_full_path_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_icon_get_full_path");
|
||||
if (!purple_buddy_icon_get_full_path_wrapped)
|
||||
return false;
|
||||
|
||||
purple_buddy_icon_unref_wrapped = (purple_buddy_icon_unref_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_icon_unref");
|
||||
if (!purple_buddy_icon_unref_wrapped)
|
||||
return false;
|
||||
|
||||
purple_buddy_icons_find_account_icon_wrapped = (purple_buddy_icons_find_account_icon_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_icons_find_account_icon");
|
||||
if (!purple_buddy_icons_find_account_icon_wrapped)
|
||||
return false;
|
||||
|
||||
purple_buddy_icon_get_data_wrapped = (purple_buddy_icon_get_data_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_icon_get_data");
|
||||
if (!purple_buddy_icon_get_data_wrapped)
|
||||
return false;
|
||||
|
||||
purple_certificate_add_ca_search_path_wrapped = (purple_certificate_add_ca_search_path_wrapped_fnc)GetProcAddress(f_hPurple, "purple_certificate_add_ca_search_path");
|
||||
if (!purple_certificate_add_ca_search_path_wrapped)
|
||||
return false;
|
||||
|
||||
purple_connection_get_state_wrapped = (purple_connection_get_state_wrapped_fnc)GetProcAddress(f_hPurple, "purple_connection_get_state");
|
||||
if (!purple_connection_get_state_wrapped)
|
||||
return false;
|
||||
|
||||
purple_connection_get_account_wrapped = (purple_connection_get_account_wrapped_fnc)GetProcAddress(f_hPurple, "purple_connection_get_account");
|
||||
if (!purple_connection_get_account_wrapped)
|
||||
return false;
|
||||
|
||||
purple_connection_get_display_name_wrapped = (purple_connection_get_display_name_wrapped_fnc)GetProcAddress(f_hPurple, "purple_connection_get_display_name");
|
||||
if (!purple_connection_get_display_name_wrapped)
|
||||
return false;
|
||||
|
||||
purple_connections_set_ui_ops_wrapped = (purple_connections_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_connections_set_ui_ops");
|
||||
if (!purple_connections_set_ui_ops_wrapped)
|
||||
return false;
|
||||
|
||||
purple_connections_get_handle_wrapped = (purple_connections_get_handle_wrapped_fnc)GetProcAddress(f_hPurple, "purple_connections_get_handle");
|
||||
if (!purple_connections_get_handle_wrapped)
|
||||
return false;
|
||||
|
||||
purple_conversation_get_im_data_wrapped = (purple_conversation_get_im_data_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversation_get_im_data");
|
||||
if (!purple_conversation_get_im_data_wrapped)
|
||||
return false;
|
||||
|
||||
purple_conversation_get_chat_data_wrapped = (purple_conversation_get_chat_data_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversation_get_chat_data");
|
||||
if (!purple_conversation_get_chat_data_wrapped)
|
||||
return false;
|
||||
|
||||
purple_find_conversation_with_account_wrapped = (purple_find_conversation_with_account_wrapped_fnc)GetProcAddress(f_hPurple, "purple_find_conversation_with_account");
|
||||
if (!purple_find_conversation_with_account_wrapped)
|
||||
return false;
|
||||
|
||||
purple_conversation_new_wrapped = (purple_conversation_new_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversation_new");
|
||||
if (!purple_conversation_new_wrapped)
|
||||
return false;
|
||||
|
||||
purple_conversation_get_type_wrapped = (purple_conversation_get_type_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversation_get_type");
|
||||
if (!purple_conversation_get_type_wrapped)
|
||||
return false;
|
||||
|
||||
purple_conv_im_send_wrapped = (purple_conv_im_send_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conv_im_send");
|
||||
if (!purple_conv_im_send_wrapped)
|
||||
return false;
|
||||
|
||||
purple_conv_chat_send_wrapped = (purple_conv_chat_send_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conv_chat_send");
|
||||
if (!purple_conv_chat_send_wrapped)
|
||||
return false;
|
||||
|
||||
purple_conversation_destroy_wrapped = (purple_conversation_destroy_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversation_destroy");
|
||||
if (!purple_conversation_destroy_wrapped)
|
||||
return false;
|
||||
|
||||
purple_conversation_get_account_wrapped = (purple_conversation_get_account_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversation_get_account");
|
||||
if (!purple_conversation_get_account_wrapped)
|
||||
return false;
|
||||
|
||||
purple_conversation_get_name_wrapped = (purple_conversation_get_name_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversation_get_name");
|
||||
if (!purple_conversation_get_name_wrapped)
|
||||
return false;
|
||||
|
||||
purple_conversations_set_ui_ops_wrapped = (purple_conversations_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversations_set_ui_ops");
|
||||
if (!purple_conversations_set_ui_ops_wrapped)
|
||||
return false;
|
||||
|
||||
purple_conversations_get_handle_wrapped = (purple_conversations_get_handle_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversations_get_handle");
|
||||
if (!purple_conversations_get_handle_wrapped)
|
||||
return false;
|
||||
|
||||
purple_core_set_ui_ops_wrapped = (purple_core_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_core_set_ui_ops");
|
||||
if (!purple_core_set_ui_ops_wrapped)
|
||||
return false;
|
||||
|
||||
purple_core_init_wrapped = (purple_core_init_wrapped_fnc)GetProcAddress(f_hPurple, "purple_core_init");
|
||||
if (!purple_core_init_wrapped)
|
||||
return false;
|
||||
|
||||
purple_debug_set_ui_ops_wrapped = (purple_debug_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_debug_set_ui_ops");
|
||||
if (!purple_debug_set_ui_ops_wrapped)
|
||||
return false;
|
||||
|
||||
purple_debug_set_verbose_wrapped = (purple_debug_set_verbose_wrapped_fnc)GetProcAddress(f_hPurple, "purple_debug_set_verbose");
|
||||
if (!purple_debug_set_verbose_wrapped)
|
||||
return false;
|
||||
|
||||
purple_dnsquery_set_ui_ops_wrapped = (purple_dnsquery_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_dnsquery_set_ui_ops");
|
||||
if (!purple_dnsquery_set_ui_ops_wrapped)
|
||||
return false;
|
||||
|
||||
purple_timeout_remove_wrapped = (purple_timeout_remove_wrapped_fnc)GetProcAddress(f_hPurple, "purple_timeout_remove");
|
||||
if (!purple_timeout_remove_wrapped)
|
||||
return false;
|
||||
|
||||
purple_input_add_wrapped = (purple_input_add_wrapped_fnc)GetProcAddress(f_hPurple, "purple_input_add");
|
||||
if (!purple_input_add_wrapped)
|
||||
return false;
|
||||
|
||||
purple_timeout_add_wrapped = (purple_timeout_add_wrapped_fnc)GetProcAddress(f_hPurple, "purple_timeout_add");
|
||||
if (!purple_timeout_add_wrapped)
|
||||
return false;
|
||||
|
||||
purple_timeout_add_seconds_wrapped = (purple_timeout_add_seconds_wrapped_fnc)GetProcAddress(f_hPurple, "purple_timeout_add_seconds");
|
||||
if (!purple_timeout_add_seconds_wrapped)
|
||||
return false;
|
||||
|
||||
purple_eventloop_set_ui_ops_wrapped = (purple_eventloop_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_eventloop_set_ui_ops");
|
||||
if (!purple_eventloop_set_ui_ops_wrapped)
|
||||
return false;
|
||||
|
||||
purple_input_remove_wrapped = (purple_input_remove_wrapped_fnc)GetProcAddress(f_hPurple, "purple_input_remove");
|
||||
if (!purple_input_remove_wrapped)
|
||||
return false;
|
||||
|
||||
purple_xfer_ui_ready_wrapped = (purple_xfer_ui_ready_wrapped_fnc)GetProcAddress(f_hPurple, "purple_xfer_ui_ready");
|
||||
if (!purple_xfer_ui_ready_wrapped)
|
||||
return false;
|
||||
|
||||
purple_xfer_request_accepted_wrapped = (purple_xfer_request_accepted_wrapped_fnc)GetProcAddress(f_hPurple, "purple_xfer_request_accepted");
|
||||
if (!purple_xfer_request_accepted_wrapped)
|
||||
return false;
|
||||
|
||||
purple_xfer_request_denied_wrapped = (purple_xfer_request_denied_wrapped_fnc)GetProcAddress(f_hPurple, "purple_xfer_request_denied");
|
||||
if (!purple_xfer_request_denied_wrapped)
|
||||
return false;
|
||||
|
||||
purple_xfer_get_account_wrapped = (purple_xfer_get_account_wrapped_fnc)GetProcAddress(f_hPurple, "purple_xfer_get_account");
|
||||
if (!purple_xfer_get_account_wrapped)
|
||||
return false;
|
||||
|
||||
purple_xfer_get_filename_wrapped = (purple_xfer_get_filename_wrapped_fnc)GetProcAddress(f_hPurple, "purple_xfer_get_filename");
|
||||
if (!purple_xfer_get_filename_wrapped)
|
||||
return false;
|
||||
|
||||
purple_xfer_get_size_wrapped = (purple_xfer_get_size_wrapped_fnc)GetProcAddress(f_hPurple, "purple_xfer_get_size");
|
||||
if (!purple_xfer_get_size_wrapped)
|
||||
return false;
|
||||
|
||||
purple_xfer_unref_wrapped = (purple_xfer_unref_wrapped_fnc)GetProcAddress(f_hPurple, "purple_xfer_unref");
|
||||
if (!purple_xfer_unref_wrapped)
|
||||
return false;
|
||||
|
||||
purple_xfer_ref_wrapped = (purple_xfer_ref_wrapped_fnc)GetProcAddress(f_hPurple, "purple_xfer_ref");
|
||||
if (!purple_xfer_ref_wrapped)
|
||||
return false;
|
||||
|
||||
purple_xfers_set_ui_ops_wrapped = (purple_xfers_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_xfers_set_ui_ops");
|
||||
if (!purple_xfers_set_ui_ops_wrapped)
|
||||
return false;
|
||||
|
||||
purple_xfers_get_handle_wrapped = (purple_xfers_get_handle_wrapped_fnc)GetProcAddress(f_hPurple, "purple_xfers_get_handle");
|
||||
if (!purple_xfers_get_handle_wrapped)
|
||||
return false;
|
||||
|
||||
purple_roomlist_set_ui_ops_wrapped = (purple_roomlist_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_roomlist_set_ui_ops");
|
||||
if (!purple_roomlist_set_ui_ops_wrapped)
|
||||
return false;
|
||||
|
||||
purple_roomlist_get_list_wrapped = (purple_roomlist_get_list_wrapped_fnc)GetProcAddress(f_hPurple, "purple_roomlist_get_list");
|
||||
if (!purple_roomlist_get_list_wrapped)
|
||||
return false;
|
||||
|
||||
purple_imgstore_get_data_wrapped = (purple_imgstore_get_data_wrapped_fnc)GetProcAddress(f_hPurple, "purple_imgstore_get_data");
|
||||
if (!purple_imgstore_get_data_wrapped)
|
||||
return false;
|
||||
|
||||
purple_imgstore_get_size_wrapped = (purple_imgstore_get_size_wrapped_fnc)GetProcAddress(f_hPurple, "purple_imgstore_get_size");
|
||||
if (!purple_imgstore_get_size_wrapped)
|
||||
return false;
|
||||
|
||||
purple_imgstore_unref_wrapped = (purple_imgstore_unref_wrapped_fnc)GetProcAddress(f_hPurple, "purple_imgstore_unref");
|
||||
if (!purple_imgstore_unref_wrapped)
|
||||
return false;
|
||||
|
||||
purple_notify_user_info_new_wrapped = (purple_notify_user_info_new_wrapped_fnc)GetProcAddress(f_hPurple, "purple_notify_user_info_new");
|
||||
if (!purple_notify_user_info_new_wrapped)
|
||||
return false;
|
||||
|
||||
purple_notify_user_info_destroy_wrapped = (purple_notify_user_info_destroy_wrapped_fnc)GetProcAddress(f_hPurple, "purple_notify_user_info_destroy");
|
||||
if (!purple_notify_user_info_destroy_wrapped)
|
||||
return false;
|
||||
|
||||
purple_notify_user_info_get_entries_wrapped = (purple_notify_user_info_get_entries_wrapped_fnc)GetProcAddress(f_hPurple, "purple_notify_user_info_get_entries");
|
||||
if (!purple_notify_user_info_get_entries_wrapped)
|
||||
return false;
|
||||
|
||||
purple_notify_user_info_entry_get_label_wrapped = (purple_notify_user_info_entry_get_label_wrapped_fnc)GetProcAddress(f_hPurple, "purple_notify_user_info_entry_get_label");
|
||||
if (!purple_notify_user_info_entry_get_label_wrapped)
|
||||
return false;
|
||||
|
||||
purple_notify_user_info_entry_get_value_wrapped = (purple_notify_user_info_entry_get_value_wrapped_fnc)GetProcAddress(f_hPurple, "purple_notify_user_info_entry_get_value");
|
||||
if (!purple_notify_user_info_entry_get_value_wrapped)
|
||||
return false;
|
||||
|
||||
purple_notify_set_ui_ops_wrapped = (purple_notify_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_notify_set_ui_ops");
|
||||
if (!purple_notify_set_ui_ops_wrapped)
|
||||
return false;
|
||||
|
||||
purple_plugins_add_search_path_wrapped = (purple_plugins_add_search_path_wrapped_fnc)GetProcAddress(f_hPurple, "purple_plugins_add_search_path");
|
||||
if (!purple_plugins_add_search_path_wrapped)
|
||||
return false;
|
||||
|
||||
purple_plugin_action_free_wrapped = (purple_plugin_action_free_wrapped_fnc)GetProcAddress(f_hPurple, "purple_plugin_action_free");
|
||||
if (!purple_plugin_action_free_wrapped)
|
||||
return false;
|
||||
|
||||
purple_prefs_load_wrapped = (purple_prefs_load_wrapped_fnc)GetProcAddress(f_hPurple, "purple_prefs_load");
|
||||
if (!purple_prefs_load_wrapped)
|
||||
return false;
|
||||
|
||||
purple_prefs_set_bool_wrapped = (purple_prefs_set_bool_wrapped_fnc)GetProcAddress(f_hPurple, "purple_prefs_set_bool");
|
||||
if (!purple_prefs_set_bool_wrapped)
|
||||
return false;
|
||||
|
||||
purple_prefs_set_string_wrapped = (purple_prefs_set_string_wrapped_fnc)GetProcAddress(f_hPurple, "purple_prefs_set_string");
|
||||
if (!purple_prefs_set_string_wrapped)
|
||||
return false;
|
||||
|
||||
purple_privacy_deny_wrapped = (purple_privacy_deny_wrapped_fnc)GetProcAddress(f_hPurple, "purple_privacy_deny");
|
||||
if (!purple_privacy_deny_wrapped)
|
||||
return false;
|
||||
|
||||
purple_privacy_allow_wrapped = (purple_privacy_allow_wrapped_fnc)GetProcAddress(f_hPurple, "purple_privacy_allow");
|
||||
if (!purple_privacy_allow_wrapped)
|
||||
return false;
|
||||
|
||||
purple_privacy_check_wrapped = (purple_privacy_check_wrapped_fnc)GetProcAddress(f_hPurple, "purple_privacy_check");
|
||||
if (!purple_privacy_check_wrapped)
|
||||
return false;
|
||||
|
||||
purple_proxy_info_new_wrapped = (purple_proxy_info_new_wrapped_fnc)GetProcAddress(f_hPurple, "purple_proxy_info_new");
|
||||
if (!purple_proxy_info_new_wrapped)
|
||||
return false;
|
||||
|
||||
purple_proxy_info_set_type_wrapped = (purple_proxy_info_set_type_wrapped_fnc)GetProcAddress(f_hPurple, "purple_proxy_info_set_type");
|
||||
if (!purple_proxy_info_set_type_wrapped)
|
||||
return false;
|
||||
|
||||
purple_proxy_info_set_host_wrapped = (purple_proxy_info_set_host_wrapped_fnc)GetProcAddress(f_hPurple, "purple_proxy_info_set_host");
|
||||
if (!purple_proxy_info_set_host_wrapped)
|
||||
return false;
|
||||
|
||||
purple_proxy_info_set_port_wrapped = (purple_proxy_info_set_port_wrapped_fnc)GetProcAddress(f_hPurple, "purple_proxy_info_set_port");
|
||||
if (!purple_proxy_info_set_port_wrapped)
|
||||
return false;
|
||||
|
||||
purple_proxy_info_set_username_wrapped = (purple_proxy_info_set_username_wrapped_fnc)GetProcAddress(f_hPurple, "purple_proxy_info_set_username");
|
||||
if (!purple_proxy_info_set_username_wrapped)
|
||||
return false;
|
||||
|
||||
purple_proxy_info_set_password_wrapped = (purple_proxy_info_set_password_wrapped_fnc)GetProcAddress(f_hPurple, "purple_proxy_info_set_password");
|
||||
if (!purple_proxy_info_set_password_wrapped)
|
||||
return false;
|
||||
|
||||
purple_find_prpl_wrapped = (purple_find_prpl_wrapped_fnc)GetProcAddress(f_hPurple, "purple_find_prpl");
|
||||
if (!purple_find_prpl_wrapped)
|
||||
return false;
|
||||
|
||||
purple_prpl_send_attention_wrapped = (purple_prpl_send_attention_wrapped_fnc)GetProcAddress(f_hPurple, "purple_prpl_send_attention");
|
||||
if (!purple_prpl_send_attention_wrapped)
|
||||
return false;
|
||||
|
||||
purple_request_set_ui_ops_wrapped = (purple_request_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_request_set_ui_ops");
|
||||
if (!purple_request_set_ui_ops_wrapped)
|
||||
return false;
|
||||
|
||||
serv_get_info_wrapped = (serv_get_info_wrapped_fnc)GetProcAddress(f_hPurple, "serv_get_info");
|
||||
if (!serv_get_info_wrapped)
|
||||
return false;
|
||||
|
||||
serv_alias_buddy_wrapped = (serv_alias_buddy_wrapped_fnc)GetProcAddress(f_hPurple, "serv_alias_buddy");
|
||||
if (!serv_alias_buddy_wrapped)
|
||||
return false;
|
||||
|
||||
serv_send_typing_wrapped = (serv_send_typing_wrapped_fnc)GetProcAddress(f_hPurple, "serv_send_typing");
|
||||
if (!serv_send_typing_wrapped)
|
||||
return false;
|
||||
|
||||
serv_join_chat_wrapped = (serv_join_chat_wrapped_fnc)GetProcAddress(f_hPurple, "serv_join_chat");
|
||||
if (!serv_join_chat_wrapped)
|
||||
return false;
|
||||
|
||||
purple_signal_connect_wrapped = (purple_signal_connect_wrapped_fnc)GetProcAddress(f_hPurple, "purple_signal_connect");
|
||||
if (!purple_signal_connect_wrapped)
|
||||
return false;
|
||||
|
||||
purple_status_type_get_id_wrapped = (purple_status_type_get_id_wrapped_fnc)GetProcAddress(f_hPurple, "purple_status_type_get_id");
|
||||
if (!purple_status_type_get_id_wrapped)
|
||||
return false;
|
||||
|
||||
purple_presence_get_active_status_wrapped = (purple_presence_get_active_status_wrapped_fnc)GetProcAddress(f_hPurple, "purple_presence_get_active_status");
|
||||
if (!purple_presence_get_active_status_wrapped)
|
||||
return false;
|
||||
|
||||
purple_status_type_get_primitive_wrapped = (purple_status_type_get_primitive_wrapped_fnc)GetProcAddress(f_hPurple, "purple_status_type_get_primitive");
|
||||
if (!purple_status_type_get_primitive_wrapped)
|
||||
return false;
|
||||
|
||||
purple_status_get_type_wrapped = (purple_status_get_type_wrapped_fnc)GetProcAddress(f_hPurple, "purple_status_get_type");
|
||||
if (!purple_status_get_type_wrapped)
|
||||
return false;
|
||||
|
||||
purple_status_get_attr_string_wrapped = (purple_status_get_attr_string_wrapped_fnc)GetProcAddress(f_hPurple, "purple_status_get_attr_string");
|
||||
if (!purple_status_get_attr_string_wrapped)
|
||||
return false;
|
||||
|
||||
purple_markup_escape_text_wrapped = (purple_markup_escape_text_wrapped_fnc)GetProcAddress(f_hPurple, "purple_markup_escape_text");
|
||||
if (!purple_markup_escape_text_wrapped)
|
||||
return false;
|
||||
|
||||
purple_markup_strip_html_wrapped = (purple_markup_strip_html_wrapped_fnc)GetProcAddress(f_hPurple, "purple_markup_strip_html");
|
||||
if (!purple_markup_strip_html_wrapped)
|
||||
return false;
|
||||
|
||||
purple_strdup_withhtml_wrapped = (purple_strdup_withhtml_wrapped_fnc)GetProcAddress(f_hPurple, "purple_strdup_withhtml");
|
||||
if (!purple_strdup_withhtml_wrapped)
|
||||
return false;
|
||||
|
||||
purple_markup_html_to_xhtml_wrapped = (purple_markup_html_to_xhtml_wrapped_fnc)GetProcAddress(f_hPurple, "purple_markup_html_to_xhtml");
|
||||
if (!purple_markup_html_to_xhtml_wrapped)
|
||||
return false;
|
||||
|
||||
purple_normalize_wrapped = (purple_normalize_wrapped_fnc)GetProcAddress(f_hPurple, "purple_normalize");
|
||||
if (!purple_normalize_wrapped)
|
||||
return false;
|
||||
|
||||
purple_utf8_try_convert_wrapped = (purple_utf8_try_convert_wrapped_fnc)GetProcAddress(f_hPurple, "purple_utf8_try_convert");
|
||||
if (!purple_utf8_try_convert_wrapped)
|
||||
return false;
|
||||
|
||||
purple_util_set_user_dir_wrapped = (purple_util_set_user_dir_wrapped_fnc)GetProcAddress(f_hPurple, "purple_util_set_user_dir");
|
||||
if (!purple_util_set_user_dir_wrapped)
|
||||
return false;
|
||||
|
||||
wpurple_g_io_channel_win32_new_socket_wrapped = (wpurple_g_io_channel_win32_new_socket_wrapped_fnc)GetProcAddress(f_hPurple, "wpurple_g_io_channel_win32_new_socket");
|
||||
if (!wpurple_g_io_channel_win32_new_socket_wrapped)
|
||||
return false;
|
||||
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1,622 +0,0 @@
|
|||
#pragma once
|
||||
#if PURPLE_RUNTIME
|
||||
|
||||
#include <Windows.h>
|
||||
#include <purple.h>
|
||||
|
||||
#define PURPLE_BLIST_NODE_IS_CHAT_WRAPPED(n) (purple_blist_node_get_type_wrapped(n) == PURPLE_BLIST_CHAT_NODE)
|
||||
#define PURPLE_BLIST_NODE_IS_BUDDY_WRAPPED(n) (purple_blist_node_get_type_wrapped(n) == PURPLE_BLIST_BUDDY_NODE)
|
||||
#define PURPLE_BLIST_NODE_IS_CONTACT_WRAPPED(n) (purple_blist_node_get_type_wrapped(n) == PURPLE_BLIST_CONTACT_NODE)
|
||||
#define PURPLE_BLIST_NODE_IS_GROUP_WRAPPED(n) (purple_blist_node_get_type_wrapped(n) == PURPLE_BLIST_GROUP_NODE)
|
||||
|
||||
#define PURPLE_CONV_IM_WRAPPED(c) (purple_conversation_get_im_data_wrapped(c))
|
||||
#define PURPLE_CONV_CHAT_WRAPPED(c) (purple_conversation_get_chat_data_wrapped(c))
|
||||
|
||||
#define PURPLE_CONNECTION_IS_CONNECTED_WRAPPED(gc) (purple_connection_get_state_wrapped(gc) == PURPLE_CONNECTED)
|
||||
|
||||
typedef void (_cdecl * purple_account_set_bool_wrapped_fnc)(PurpleAccount *account, const char *name, gboolean value);
|
||||
extern purple_account_set_bool_wrapped_fnc purple_account_set_bool_wrapped;
|
||||
|
||||
typedef const char * (_cdecl * purple_account_get_protocol_id_wrapped_fnc)(const PurpleAccount *account);
|
||||
extern purple_account_get_protocol_id_wrapped_fnc purple_account_get_protocol_id_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_account_set_int_wrapped_fnc)(PurpleAccount *account, const char *name, int value);
|
||||
extern purple_account_set_int_wrapped_fnc purple_account_set_int_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_account_set_string_wrapped_fnc)(PurpleAccount *account, const char *name, const char *value);
|
||||
extern purple_account_set_string_wrapped_fnc purple_account_set_string_wrapped;
|
||||
|
||||
typedef const char * (_cdecl * purple_account_get_username_wrapped_fnc)(const PurpleAccount *account);
|
||||
extern purple_account_get_username_wrapped_fnc purple_account_get_username_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_account_set_username_wrapped_fnc)(PurpleAccount *account, const char *username);
|
||||
extern purple_account_set_username_wrapped_fnc purple_account_set_username_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_account_set_proxy_info_wrapped_fnc)(PurpleAccount *account, PurpleProxyInfo *info);
|
||||
extern purple_account_set_proxy_info_wrapped_fnc purple_account_set_proxy_info_wrapped;
|
||||
|
||||
typedef PurpleAccount * (_cdecl * purple_accounts_find_wrapped_fnc)(const char *name, const char *protocol);
|
||||
extern purple_accounts_find_wrapped_fnc purple_accounts_find_wrapped;
|
||||
|
||||
typedef PurpleAccount * (_cdecl * purple_account_new_wrapped_fnc)(const char *username, const char *protocol_id);
|
||||
extern purple_account_new_wrapped_fnc purple_account_new_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_accounts_add_wrapped_fnc)(PurpleAccount *account);
|
||||
extern purple_accounts_add_wrapped_fnc purple_accounts_add_wrapped;
|
||||
|
||||
typedef const char * (_cdecl * purple_account_get_password_wrapped_fnc)(const PurpleAccount *account);
|
||||
extern purple_account_get_password_wrapped_fnc purple_account_get_password_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_account_set_password_wrapped_fnc)(PurpleAccount *account, const char *password);
|
||||
extern purple_account_set_password_wrapped_fnc purple_account_set_password_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_account_set_enabled_wrapped_fnc)(PurpleAccount *account, const char *ui, gboolean value);
|
||||
extern purple_account_set_enabled_wrapped_fnc purple_account_set_enabled_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_account_set_privacy_type_wrapped_fnc)(PurpleAccount *account, PurplePrivacyType privacy_type);
|
||||
extern purple_account_set_privacy_type_wrapped_fnc purple_account_set_privacy_type_wrapped;
|
||||
|
||||
typedef PurpleStatusType * (_cdecl * purple_account_get_status_type_with_primitive_wrapped_fnc)( const PurpleAccount *account, PurpleStatusPrimitive primitive);
|
||||
extern purple_account_get_status_type_with_primitive_wrapped_fnc purple_account_get_status_type_with_primitive_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_account_set_status_wrapped_fnc)(PurpleAccount *account, const char *status_id, gboolean active, ...);
|
||||
extern purple_account_set_status_wrapped_fnc purple_account_set_status_wrapped;
|
||||
|
||||
typedef int (_cdecl * purple_account_get_int_wrapped_fnc)(const PurpleAccount *account, const char *name, int default_value);
|
||||
extern purple_account_get_int_wrapped_fnc purple_account_get_int_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_account_disconnect_wrapped_fnc)(PurpleAccount *account);
|
||||
extern purple_account_disconnect_wrapped_fnc purple_account_disconnect_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_accounts_delete_wrapped_fnc)(PurpleAccount *account);
|
||||
extern purple_accounts_delete_wrapped_fnc purple_accounts_delete_wrapped;
|
||||
|
||||
typedef PurpleConnection * (_cdecl * purple_account_get_connection_wrapped_fnc)(const PurpleAccount *account);
|
||||
extern purple_account_get_connection_wrapped_fnc purple_account_get_connection_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_account_set_alias_wrapped_fnc)(PurpleAccount *account, const char *alias);
|
||||
extern purple_account_set_alias_wrapped_fnc purple_account_set_alias_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_account_set_public_alias_wrapped_fnc)(PurpleAccount *account, const char *alias, PurpleSetPublicAliasSuccessCallback success_cb, PurpleSetPublicAliasFailureCallback failure_cb);
|
||||
extern purple_account_set_public_alias_wrapped_fnc purple_account_set_public_alias_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_account_remove_buddy_wrapped_fnc)(PurpleAccount *account, PurpleBuddy *buddy, PurpleGroup *group);
|
||||
extern purple_account_remove_buddy_wrapped_fnc purple_account_remove_buddy_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_account_add_buddy_wrapped_fnc)(PurpleAccount *account, PurpleBuddy *buddy);
|
||||
extern purple_account_add_buddy_wrapped_fnc purple_account_add_buddy_wrapped;
|
||||
|
||||
typedef const gchar * (_cdecl * purple_account_get_name_for_display_wrapped_fnc)(const PurpleAccount *account);
|
||||
extern purple_account_get_name_for_display_wrapped_fnc purple_account_get_name_for_display_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_accounts_set_ui_ops_wrapped_fnc)(PurpleAccountUiOps *ops);
|
||||
extern purple_accounts_set_ui_ops_wrapped_fnc purple_accounts_set_ui_ops_wrapped;
|
||||
|
||||
typedef PurplePrefType (_cdecl * purple_account_option_get_type_wrapped_fnc)(const PurpleAccountOption *option);
|
||||
extern purple_account_option_get_type_wrapped_fnc purple_account_option_get_type_wrapped;
|
||||
|
||||
typedef const char * (_cdecl * purple_account_option_get_setting_wrapped_fnc)(const PurpleAccountOption *option);
|
||||
extern purple_account_option_get_setting_wrapped_fnc purple_account_option_get_setting_wrapped;
|
||||
|
||||
typedef PurpleBlistNodeType (_cdecl * purple_blist_node_get_type_wrapped_fnc)(PurpleBlistNode *node);
|
||||
extern purple_blist_node_get_type_wrapped_fnc purple_blist_node_get_type_wrapped;
|
||||
|
||||
typedef const char * (_cdecl * purple_buddy_get_alias_wrapped_fnc)(PurpleBuddy *buddy);
|
||||
extern purple_buddy_get_alias_wrapped_fnc purple_buddy_get_alias_wrapped;
|
||||
|
||||
typedef const char * (_cdecl * purple_buddy_get_server_alias_wrapped_fnc)(PurpleBuddy *buddy);
|
||||
extern purple_buddy_get_server_alias_wrapped_fnc purple_buddy_get_server_alias_wrapped;
|
||||
|
||||
typedef PurpleBuddy * (_cdecl * purple_find_buddy_wrapped_fnc)(PurpleAccount *account, const char *name);
|
||||
extern purple_find_buddy_wrapped_fnc purple_find_buddy_wrapped;
|
||||
|
||||
typedef PurpleGroup * (_cdecl * purple_buddy_get_group_wrapped_fnc)(PurpleBuddy *buddy);
|
||||
extern purple_buddy_get_group_wrapped_fnc purple_buddy_get_group_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_blist_remove_buddy_wrapped_fnc)(PurpleBuddy *buddy);
|
||||
extern purple_blist_remove_buddy_wrapped_fnc purple_blist_remove_buddy_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_blist_alias_buddy_wrapped_fnc)(PurpleBuddy *buddy, const char *alias);
|
||||
extern purple_blist_alias_buddy_wrapped_fnc purple_blist_alias_buddy_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_blist_server_alias_buddy_wrapped_fnc)(PurpleBuddy *buddy, const char *alias);
|
||||
extern purple_blist_server_alias_buddy_wrapped_fnc purple_blist_server_alias_buddy_wrapped;
|
||||
|
||||
typedef PurpleGroup * (_cdecl * purple_find_group_wrapped_fnc)(const char *name);
|
||||
extern purple_find_group_wrapped_fnc purple_find_group_wrapped;
|
||||
|
||||
typedef PurpleGroup * (_cdecl * purple_group_new_wrapped_fnc)(const char *name);
|
||||
extern purple_group_new_wrapped_fnc purple_group_new_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_blist_add_contact_wrapped_fnc)(PurpleContact *contact, PurpleGroup *group, PurpleBlistNode *node);
|
||||
extern purple_blist_add_contact_wrapped_fnc purple_blist_add_contact_wrapped;
|
||||
|
||||
typedef PurpleContact * (_cdecl * purple_buddy_get_contact_wrapped_fnc)(PurpleBuddy *buddy);
|
||||
extern purple_buddy_get_contact_wrapped_fnc purple_buddy_get_contact_wrapped;
|
||||
|
||||
typedef PurpleBuddy * (_cdecl * purple_buddy_new_wrapped_fnc)(PurpleAccount *account, const char *name, const char *alias);
|
||||
extern purple_buddy_new_wrapped_fnc purple_buddy_new_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_blist_add_buddy_wrapped_fnc)(PurpleBuddy *buddy, PurpleContact *contact, PurpleGroup *group, PurpleBlistNode *node);
|
||||
extern purple_blist_add_buddy_wrapped_fnc purple_blist_add_buddy_wrapped;
|
||||
|
||||
typedef PurpleChat * (_cdecl * purple_blist_find_chat_wrapped_fnc)(PurpleAccount *account, const char *name);
|
||||
extern purple_blist_find_chat_wrapped_fnc purple_blist_find_chat_wrapped;
|
||||
|
||||
typedef GHashTable * (_cdecl * purple_chat_get_components_wrapped_fnc)(PurpleChat *chat);
|
||||
extern purple_chat_get_components_wrapped_fnc purple_chat_get_components_wrapped;
|
||||
|
||||
typedef PurplePresence * (_cdecl * purple_buddy_get_presence_wrapped_fnc)(const PurpleBuddy *buddy);
|
||||
extern purple_buddy_get_presence_wrapped_fnc purple_buddy_get_presence_wrapped;
|
||||
|
||||
typedef PurpleAccount * (_cdecl * purple_buddy_get_account_wrapped_fnc)(const PurpleBuddy *buddy);
|
||||
extern purple_buddy_get_account_wrapped_fnc purple_buddy_get_account_wrapped;
|
||||
|
||||
typedef const char * (_cdecl * purple_buddy_get_name_wrapped_fnc)(const PurpleBuddy *buddy);
|
||||
extern purple_buddy_get_name_wrapped_fnc purple_buddy_get_name_wrapped;
|
||||
|
||||
typedef GSList * (_cdecl * purple_find_buddies_wrapped_fnc)(PurpleAccount *account, const char *name);
|
||||
extern purple_find_buddies_wrapped_fnc purple_find_buddies_wrapped;
|
||||
|
||||
typedef const char * (_cdecl * purple_group_get_name_wrapped_fnc)(PurpleGroup *group);
|
||||
extern purple_group_get_name_wrapped_fnc purple_group_get_name_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_blist_set_ui_ops_wrapped_fnc)(PurpleBlistUiOps *ops);
|
||||
extern purple_blist_set_ui_ops_wrapped_fnc purple_blist_set_ui_ops_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_set_blist_wrapped_fnc)(PurpleBuddyList *blist);
|
||||
extern purple_set_blist_wrapped_fnc purple_set_blist_wrapped;
|
||||
|
||||
typedef PurpleBuddyList * (_cdecl * purple_blist_new_wrapped_fnc)(void);
|
||||
extern purple_blist_new_wrapped_fnc purple_blist_new_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_blist_load_wrapped_fnc)(void);
|
||||
extern purple_blist_load_wrapped_fnc purple_blist_load_wrapped;
|
||||
|
||||
typedef void * (_cdecl * purple_blist_get_handle_wrapped_fnc)(void);
|
||||
extern purple_blist_get_handle_wrapped_fnc purple_blist_get_handle_wrapped;
|
||||
|
||||
typedef PurpleStoredImage * (_cdecl * purple_buddy_icons_set_account_icon_wrapped_fnc)(PurpleAccount *account, guchar *icon_data, size_t icon_len);
|
||||
extern purple_buddy_icons_set_account_icon_wrapped_fnc purple_buddy_icons_set_account_icon_wrapped;
|
||||
|
||||
typedef PurpleBuddyIcon * (_cdecl * purple_buddy_icons_find_wrapped_fnc)(PurpleAccount *account, const char *username);
|
||||
extern purple_buddy_icons_find_wrapped_fnc purple_buddy_icons_find_wrapped;
|
||||
|
||||
typedef char * (_cdecl * purple_buddy_icon_get_full_path_wrapped_fnc)(PurpleBuddyIcon *icon);
|
||||
extern purple_buddy_icon_get_full_path_wrapped_fnc purple_buddy_icon_get_full_path_wrapped;
|
||||
|
||||
typedef PurpleBuddyIcon * (_cdecl * purple_buddy_icon_unref_wrapped_fnc)(PurpleBuddyIcon *icon);
|
||||
extern purple_buddy_icon_unref_wrapped_fnc purple_buddy_icon_unref_wrapped;
|
||||
|
||||
typedef PurpleStoredImage * (_cdecl * purple_buddy_icons_find_account_icon_wrapped_fnc)(PurpleAccount *account);
|
||||
extern purple_buddy_icons_find_account_icon_wrapped_fnc purple_buddy_icons_find_account_icon_wrapped;
|
||||
|
||||
typedef gconstpointer (_cdecl * purple_buddy_icon_get_data_wrapped_fnc)(const PurpleBuddyIcon *icon, size_t *len);
|
||||
extern purple_buddy_icon_get_data_wrapped_fnc purple_buddy_icon_get_data_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_certificate_add_ca_search_path_wrapped_fnc)(const char *path);
|
||||
extern purple_certificate_add_ca_search_path_wrapped_fnc purple_certificate_add_ca_search_path_wrapped;
|
||||
|
||||
typedef PurpleConnectionState (_cdecl * purple_connection_get_state_wrapped_fnc)(const PurpleConnection *gc);
|
||||
extern purple_connection_get_state_wrapped_fnc purple_connection_get_state_wrapped;
|
||||
|
||||
typedef PurpleAccount * (_cdecl * purple_connection_get_account_wrapped_fnc)(const PurpleConnection *gc);
|
||||
extern purple_connection_get_account_wrapped_fnc purple_connection_get_account_wrapped;
|
||||
|
||||
typedef const char * (_cdecl * purple_connection_get_display_name_wrapped_fnc)(const PurpleConnection *gc);
|
||||
extern purple_connection_get_display_name_wrapped_fnc purple_connection_get_display_name_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_connections_set_ui_ops_wrapped_fnc)(PurpleConnectionUiOps *ops);
|
||||
extern purple_connections_set_ui_ops_wrapped_fnc purple_connections_set_ui_ops_wrapped;
|
||||
|
||||
typedef void * (_cdecl * purple_connections_get_handle_wrapped_fnc)(void);
|
||||
extern purple_connections_get_handle_wrapped_fnc purple_connections_get_handle_wrapped;
|
||||
|
||||
typedef PurpleConvIm * (_cdecl * purple_conversation_get_im_data_wrapped_fnc)(const PurpleConversation *conv);
|
||||
extern purple_conversation_get_im_data_wrapped_fnc purple_conversation_get_im_data_wrapped;
|
||||
|
||||
typedef PurpleConvChat * (_cdecl * purple_conversation_get_chat_data_wrapped_fnc)(const PurpleConversation *conv);
|
||||
extern purple_conversation_get_chat_data_wrapped_fnc purple_conversation_get_chat_data_wrapped;
|
||||
|
||||
typedef PurpleConversation * (_cdecl * purple_find_conversation_with_account_wrapped_fnc)( PurpleConversationType type, const char *name, const PurpleAccount *account);
|
||||
extern purple_find_conversation_with_account_wrapped_fnc purple_find_conversation_with_account_wrapped;
|
||||
|
||||
typedef PurpleConversation * (_cdecl * purple_conversation_new_wrapped_fnc)(PurpleConversationType type, PurpleAccount *account, const char *name);
|
||||
extern purple_conversation_new_wrapped_fnc purple_conversation_new_wrapped;
|
||||
|
||||
typedef PurpleConversationType (_cdecl * purple_conversation_get_type_wrapped_fnc)(const PurpleConversation *conv);
|
||||
extern purple_conversation_get_type_wrapped_fnc purple_conversation_get_type_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_conversation_set_data_wrapped_func)(const PurpleConversation *conv, const char *key, gpointer data);
|
||||
extern purple_conversation_set_data_wrapped_func purple_conversation_set_data_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_conversation_update_wrapped_func)(const PurpleConversation *conv, PurpleConversationUpdateType type);
|
||||
extern purple_conversation_update_wrapped_func purple_conversation_update_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_conv_im_send_wrapped_fnc)(PurpleConvIm *im, const char *message);
|
||||
extern purple_conv_im_send_wrapped_fnc purple_conv_im_send_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_conv_chat_send_wrapped_fnc)(PurpleConvChat *chat, const char *message);
|
||||
extern purple_conv_chat_send_wrapped_fnc purple_conv_chat_send_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_conversation_destroy_wrapped_fnc)(PurpleConversation *conv);
|
||||
extern purple_conversation_destroy_wrapped_fnc purple_conversation_destroy_wrapped;
|
||||
|
||||
typedef PurpleAccount * (_cdecl * purple_conversation_get_account_wrapped_fnc)(const PurpleConversation *conv);
|
||||
extern purple_conversation_get_account_wrapped_fnc purple_conversation_get_account_wrapped;
|
||||
|
||||
typedef const char * (_cdecl * purple_conversation_get_name_wrapped_fnc)(const PurpleConversation *conv);
|
||||
extern purple_conversation_get_name_wrapped_fnc purple_conversation_get_name_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_conversations_set_ui_ops_wrapped_fnc)(PurpleConversationUiOps *ops);
|
||||
extern purple_conversations_set_ui_ops_wrapped_fnc purple_conversations_set_ui_ops_wrapped;
|
||||
|
||||
typedef void * (_cdecl * purple_conversations_get_handle_wrapped_fnc)(void);
|
||||
extern purple_conversations_get_handle_wrapped_fnc purple_conversations_get_handle_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_core_set_ui_ops_wrapped_fnc)(PurpleCoreUiOps *ops);
|
||||
extern purple_core_set_ui_ops_wrapped_fnc purple_core_set_ui_ops_wrapped;
|
||||
|
||||
typedef gboolean (_cdecl * purple_core_init_wrapped_fnc)(const char *ui);
|
||||
extern purple_core_init_wrapped_fnc purple_core_init_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_debug_set_ui_ops_wrapped_fnc)(PurpleDebugUiOps *ops);
|
||||
extern purple_debug_set_ui_ops_wrapped_fnc purple_debug_set_ui_ops_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_debug_set_verbose_wrapped_fnc)(gboolean verbose);
|
||||
extern purple_debug_set_verbose_wrapped_fnc purple_debug_set_verbose_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_dnsquery_set_ui_ops_wrapped_fnc)(PurpleDnsQueryUiOps *ops);
|
||||
extern purple_dnsquery_set_ui_ops_wrapped_fnc purple_dnsquery_set_ui_ops_wrapped;
|
||||
|
||||
typedef gboolean (_cdecl * purple_timeout_remove_wrapped_fnc)(guint handle);
|
||||
extern purple_timeout_remove_wrapped_fnc purple_timeout_remove_wrapped;
|
||||
|
||||
typedef guint (_cdecl * purple_input_add_wrapped_fnc)(int fd, PurpleInputCondition cond, PurpleInputFunction func, gpointer user_data);
|
||||
extern purple_input_add_wrapped_fnc purple_input_add_wrapped;
|
||||
|
||||
typedef guint (_cdecl * purple_timeout_add_wrapped_fnc)(guint interval, GSourceFunc function, gpointer data);
|
||||
extern purple_timeout_add_wrapped_fnc purple_timeout_add_wrapped;
|
||||
|
||||
typedef guint (_cdecl * purple_timeout_add_seconds_wrapped_fnc)(guint interval, GSourceFunc function, gpointer data);
|
||||
extern purple_timeout_add_seconds_wrapped_fnc purple_timeout_add_seconds_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_eventloop_set_ui_ops_wrapped_fnc)(PurpleEventLoopUiOps *ops);
|
||||
extern purple_eventloop_set_ui_ops_wrapped_fnc purple_eventloop_set_ui_ops_wrapped;
|
||||
|
||||
typedef gboolean (_cdecl * purple_input_remove_wrapped_fnc)(guint handle);
|
||||
extern purple_input_remove_wrapped_fnc purple_input_remove_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_xfer_ui_ready_wrapped_fnc)(PurpleXfer *xfer);
|
||||
extern purple_xfer_ui_ready_wrapped_fnc purple_xfer_ui_ready_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_xfer_request_accepted_wrapped_fnc)(PurpleXfer *xfer, const char *filename);
|
||||
extern purple_xfer_request_accepted_wrapped_fnc purple_xfer_request_accepted_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_xfer_request_denied_wrapped_fnc)(PurpleXfer *xfer);
|
||||
extern purple_xfer_request_denied_wrapped_fnc purple_xfer_request_denied_wrapped;
|
||||
|
||||
typedef PurpleAccount * (_cdecl * purple_xfer_get_account_wrapped_fnc)(const PurpleXfer *xfer);
|
||||
extern purple_xfer_get_account_wrapped_fnc purple_xfer_get_account_wrapped;
|
||||
|
||||
typedef const char * (_cdecl * purple_xfer_get_filename_wrapped_fnc)(const PurpleXfer *xfer);
|
||||
extern purple_xfer_get_filename_wrapped_fnc purple_xfer_get_filename_wrapped;
|
||||
|
||||
typedef size_t (_cdecl * purple_xfer_get_size_wrapped_fnc)(const PurpleXfer *xfer);
|
||||
extern purple_xfer_get_size_wrapped_fnc purple_xfer_get_size_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_xfer_unref_wrapped_fnc)(PurpleXfer *xfer);
|
||||
extern purple_xfer_unref_wrapped_fnc purple_xfer_unref_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_xfer_ref_wrapped_fnc)(PurpleXfer *xfer);
|
||||
extern purple_xfer_ref_wrapped_fnc purple_xfer_ref_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_xfers_set_ui_ops_wrapped_fnc)(PurpleXferUiOps *ops);
|
||||
extern purple_xfers_set_ui_ops_wrapped_fnc purple_xfers_set_ui_ops_wrapped;
|
||||
|
||||
typedef void * (_cdecl * purple_xfers_get_handle_wrapped_fnc)(void);
|
||||
extern purple_xfers_get_handle_wrapped_fnc purple_xfers_get_handle_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_roomlist_set_ui_ops_wrapped_fnc)(PurpleRoomlistUiOps *ops);
|
||||
extern purple_roomlist_set_ui_ops_wrapped_fnc purple_roomlist_set_ui_ops_wrapped;
|
||||
|
||||
typedef PurpleRoomlist * (_cdecl * purple_roomlist_get_list_wrapped_fnc)(PurpleConnection *con);
|
||||
extern purple_roomlist_get_list_wrapped_fnc purple_roomlist_get_list_wrapped;
|
||||
|
||||
typedef gconstpointer (_cdecl * purple_imgstore_get_data_wrapped_fnc)(PurpleStoredImage *img);
|
||||
extern purple_imgstore_get_data_wrapped_fnc purple_imgstore_get_data_wrapped;
|
||||
|
||||
typedef size_t (_cdecl * purple_imgstore_get_size_wrapped_fnc)(PurpleStoredImage *img);
|
||||
extern purple_imgstore_get_size_wrapped_fnc purple_imgstore_get_size_wrapped;
|
||||
|
||||
typedef PurpleStoredImage * (_cdecl * purple_imgstore_unref_wrapped_fnc)(PurpleStoredImage *img);
|
||||
extern purple_imgstore_unref_wrapped_fnc purple_imgstore_unref_wrapped;
|
||||
|
||||
typedef PurpleNotifyUserInfo * (_cdecl * purple_notify_user_info_new_wrapped_fnc)(void);
|
||||
extern purple_notify_user_info_new_wrapped_fnc purple_notify_user_info_new_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_notify_user_info_destroy_wrapped_fnc)(PurpleNotifyUserInfo *user_info);
|
||||
extern purple_notify_user_info_destroy_wrapped_fnc purple_notify_user_info_destroy_wrapped;
|
||||
|
||||
typedef GList * (_cdecl * purple_notify_user_info_get_entries_wrapped_fnc)(PurpleNotifyUserInfo *user_info);
|
||||
extern purple_notify_user_info_get_entries_wrapped_fnc purple_notify_user_info_get_entries_wrapped;
|
||||
|
||||
typedef const gchar * (_cdecl * purple_notify_user_info_entry_get_label_wrapped_fnc)(PurpleNotifyUserInfoEntry *user_info_entry);
|
||||
extern purple_notify_user_info_entry_get_label_wrapped_fnc purple_notify_user_info_entry_get_label_wrapped;
|
||||
|
||||
typedef const gchar * (_cdecl * purple_notify_user_info_entry_get_value_wrapped_fnc)(PurpleNotifyUserInfoEntry *user_info_entry);
|
||||
extern purple_notify_user_info_entry_get_value_wrapped_fnc purple_notify_user_info_entry_get_value_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_notify_set_ui_ops_wrapped_fnc)(PurpleNotifyUiOps *ops);
|
||||
extern purple_notify_set_ui_ops_wrapped_fnc purple_notify_set_ui_ops_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_plugins_add_search_path_wrapped_fnc)(const char *path);
|
||||
extern purple_plugins_add_search_path_wrapped_fnc purple_plugins_add_search_path_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_plugin_action_free_wrapped_fnc)(PurplePluginAction *action);
|
||||
extern purple_plugin_action_free_wrapped_fnc purple_plugin_action_free_wrapped;
|
||||
|
||||
typedef gboolean (_cdecl * purple_prefs_load_wrapped_fnc)(void);
|
||||
extern purple_prefs_load_wrapped_fnc purple_prefs_load_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_prefs_set_bool_wrapped_fnc)(const char *name, gboolean value);
|
||||
extern purple_prefs_set_bool_wrapped_fnc purple_prefs_set_bool_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_prefs_set_string_wrapped_fnc)(const char *name, const char *value);
|
||||
extern purple_prefs_set_string_wrapped_fnc purple_prefs_set_string_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_privacy_deny_wrapped_fnc)(PurpleAccount *account, const char *who, gboolean local, gboolean restore);
|
||||
extern purple_privacy_deny_wrapped_fnc purple_privacy_deny_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_privacy_allow_wrapped_fnc)(PurpleAccount *account, const char *who, gboolean local, gboolean restore);
|
||||
extern purple_privacy_allow_wrapped_fnc purple_privacy_allow_wrapped;
|
||||
|
||||
typedef gboolean (_cdecl * purple_privacy_check_wrapped_fnc)(PurpleAccount *account, const char *who);
|
||||
extern purple_privacy_check_wrapped_fnc purple_privacy_check_wrapped;
|
||||
|
||||
typedef PurpleProxyInfo * (_cdecl * purple_proxy_info_new_wrapped_fnc)(void);
|
||||
extern purple_proxy_info_new_wrapped_fnc purple_proxy_info_new_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_proxy_info_set_type_wrapped_fnc)(PurpleProxyInfo *info, PurpleProxyType type);
|
||||
extern purple_proxy_info_set_type_wrapped_fnc purple_proxy_info_set_type_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_proxy_info_set_host_wrapped_fnc)(PurpleProxyInfo *info, const char *host);
|
||||
extern purple_proxy_info_set_host_wrapped_fnc purple_proxy_info_set_host_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_proxy_info_set_port_wrapped_fnc)(PurpleProxyInfo *info, int port);
|
||||
extern purple_proxy_info_set_port_wrapped_fnc purple_proxy_info_set_port_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_proxy_info_set_username_wrapped_fnc)(PurpleProxyInfo *info, const char *username);
|
||||
extern purple_proxy_info_set_username_wrapped_fnc purple_proxy_info_set_username_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_proxy_info_set_password_wrapped_fnc)(PurpleProxyInfo *info, const char *password);
|
||||
extern purple_proxy_info_set_password_wrapped_fnc purple_proxy_info_set_password_wrapped;
|
||||
|
||||
typedef PurplePlugin * (_cdecl * purple_find_prpl_wrapped_fnc)(const char *id);
|
||||
extern purple_find_prpl_wrapped_fnc purple_find_prpl_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_prpl_send_attention_wrapped_fnc)(PurpleConnection *gc, const char *who, guint type_code);
|
||||
extern purple_prpl_send_attention_wrapped_fnc purple_prpl_send_attention_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_request_set_ui_ops_wrapped_fnc)(PurpleRequestUiOps *ops);
|
||||
extern purple_request_set_ui_ops_wrapped_fnc purple_request_set_ui_ops_wrapped;
|
||||
|
||||
typedef void (_cdecl * serv_get_info_wrapped_fnc)(PurpleConnection *, const char *);
|
||||
extern serv_get_info_wrapped_fnc serv_get_info_wrapped;
|
||||
|
||||
typedef void (_cdecl * serv_alias_buddy_wrapped_fnc)(PurpleBuddy *);
|
||||
extern serv_alias_buddy_wrapped_fnc serv_alias_buddy_wrapped;
|
||||
|
||||
typedef unsigned int (_cdecl * serv_send_typing_wrapped_fnc)(PurpleConnection *gc, const char *name, PurpleTypingState state);
|
||||
extern serv_send_typing_wrapped_fnc serv_send_typing_wrapped;
|
||||
|
||||
typedef void (_cdecl * serv_join_chat_wrapped_fnc)(PurpleConnection *, GHashTable *data);
|
||||
extern serv_join_chat_wrapped_fnc serv_join_chat_wrapped;
|
||||
|
||||
typedef gulong (_cdecl * purple_signal_connect_wrapped_fnc)(void *instance, const char *signal, void *handle, PurpleCallback func, void *data);
|
||||
extern purple_signal_connect_wrapped_fnc purple_signal_connect_wrapped;
|
||||
|
||||
typedef const char * (_cdecl * purple_status_type_get_id_wrapped_fnc)(const PurpleStatusType *status_type);
|
||||
extern purple_status_type_get_id_wrapped_fnc purple_status_type_get_id_wrapped;
|
||||
|
||||
typedef PurpleStatus * (_cdecl * purple_presence_get_active_status_wrapped_fnc)(const PurplePresence *presence);
|
||||
extern purple_presence_get_active_status_wrapped_fnc purple_presence_get_active_status_wrapped;
|
||||
|
||||
typedef PurpleStatusPrimitive (_cdecl * purple_status_type_get_primitive_wrapped_fnc)( const PurpleStatusType *status_type);
|
||||
extern purple_status_type_get_primitive_wrapped_fnc purple_status_type_get_primitive_wrapped;
|
||||
|
||||
typedef PurpleStatusType * (_cdecl * purple_status_get_type_wrapped_fnc)(const PurpleStatus *status);
|
||||
extern purple_status_get_type_wrapped_fnc purple_status_get_type_wrapped;
|
||||
|
||||
typedef const char * (_cdecl * purple_status_get_attr_string_wrapped_fnc)(const PurpleStatus *status, const char *id);
|
||||
extern purple_status_get_attr_string_wrapped_fnc purple_status_get_attr_string_wrapped;
|
||||
|
||||
typedef gchar * (_cdecl * purple_markup_escape_text_wrapped_fnc)(const gchar *text, gssize length);
|
||||
extern purple_markup_escape_text_wrapped_fnc purple_markup_escape_text_wrapped;
|
||||
|
||||
typedef char * (_cdecl * purple_markup_strip_html_wrapped_fnc)(const char *str);
|
||||
extern purple_markup_strip_html_wrapped_fnc purple_markup_strip_html_wrapped;
|
||||
|
||||
typedef gchar * (_cdecl * purple_strdup_withhtml_wrapped_fnc)(const gchar *src);
|
||||
extern purple_strdup_withhtml_wrapped_fnc purple_strdup_withhtml_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_markup_html_to_xhtml_wrapped_fnc)(const char *html, char **dest_xhtml, char **dest_plain);
|
||||
extern purple_markup_html_to_xhtml_wrapped_fnc purple_markup_html_to_xhtml_wrapped;
|
||||
|
||||
typedef const char * (_cdecl * purple_normalize_wrapped_fnc)(const PurpleAccount *account, const char *str);
|
||||
extern purple_normalize_wrapped_fnc purple_normalize_wrapped;
|
||||
|
||||
typedef gchar * (_cdecl * purple_utf8_try_convert_wrapped_fnc)(const char *str);
|
||||
extern purple_utf8_try_convert_wrapped_fnc purple_utf8_try_convert_wrapped;
|
||||
|
||||
typedef void (_cdecl * purple_util_set_user_dir_wrapped_fnc)(const char *dir);
|
||||
extern purple_util_set_user_dir_wrapped_fnc purple_util_set_user_dir_wrapped;
|
||||
|
||||
typedef GIOChannel * (_cdecl * wpurple_g_io_channel_win32_new_socket_wrapped_fnc)(int socket);
|
||||
extern wpurple_g_io_channel_win32_new_socket_wrapped_fnc wpurple_g_io_channel_win32_new_socket_wrapped;
|
||||
|
||||
|
||||
#else
|
||||
|
||||
|
||||
#define PURPLE_BLIST_NODE_IS_CHAT_WRAPPED PURPLE_BLIST_NODE_IS_CHAT
|
||||
#define PURPLE_BLIST_NODE_IS_BUDDY_WRAPPED PURPLE_BLIST_NODE_IS_BUDDY
|
||||
#define PURPLE_BLIST_NODE_IS_CONTACT_WRAPPED PURPLE_BLIST_NODE_IS_CONTACT
|
||||
#define PURPLE_BLIST_NODE_IS_GROUP_WRAPPED PURPLE_BLIST_NODE_IS_GROUP
|
||||
|
||||
#define PURPLE_CONV_IM_WRAPPED PURPLE_CONV_IM
|
||||
#define PURPLE_CONV_CHAT_WRAPPED PURPLE_CONV_CHAT
|
||||
|
||||
#define PURPLE_CONNECTION_IS_CONNECTED_WRAPPED PURPLE_CONNECTION_IS_CONNECTED
|
||||
|
||||
#define purple_account_set_bool_wrapped purple_account_set_bool
|
||||
#define purple_account_get_protocol_id_wrapped purple_account_get_protocol_id
|
||||
#define purple_account_set_int_wrapped purple_account_set_int
|
||||
#define purple_account_set_string_wrapped purple_account_set_string
|
||||
#define purple_account_get_username_wrapped purple_account_get_username
|
||||
#define purple_account_set_username_wrapped purple_account_set_username
|
||||
#define purple_account_set_proxy_info_wrapped purple_account_set_proxy_info
|
||||
#define purple_accounts_find_wrapped purple_accounts_find
|
||||
#define purple_account_new_wrapped purple_account_new
|
||||
#define purple_accounts_add_wrapped purple_accounts_add
|
||||
#define purple_account_get_password_wrapped purple_account_get_password
|
||||
#define purple_account_set_password_wrapped purple_account_set_password
|
||||
#define purple_account_set_enabled_wrapped purple_account_set_enabled
|
||||
#define purple_account_set_privacy_type_wrapped purple_account_set_privacy_type
|
||||
#define purple_account_get_status_type_with_primitive_wrapped purple_account_get_status_type_with_primitive
|
||||
#define purple_account_set_status_wrapped purple_account_set_status
|
||||
#define purple_account_get_int_wrapped purple_account_get_int
|
||||
#define purple_account_disconnect_wrapped purple_account_disconnect
|
||||
#define purple_accounts_delete_wrapped purple_accounts_delete
|
||||
#define purple_account_get_connection_wrapped purple_account_get_connection
|
||||
#define purple_account_set_alias_wrapped purple_account_set_alias
|
||||
#define purple_account_set_public_alias_wrapped purple_account_set_public_alias
|
||||
#define purple_account_remove_buddy_wrapped purple_account_remove_buddy
|
||||
#define purple_account_add_buddy_wrapped purple_account_add_buddy
|
||||
#define purple_account_get_name_for_display_wrapped purple_account_get_name_for_display
|
||||
#define purple_accounts_set_ui_ops_wrapped purple_accounts_set_ui_ops
|
||||
#define purple_account_option_get_type_wrapped purple_account_option_get_type
|
||||
#define purple_account_option_get_setting_wrapped purple_account_option_get_setting
|
||||
#define purple_blist_node_get_type_wrapped purple_blist_node_get_type
|
||||
#define purple_buddy_get_alias_wrapped purple_buddy_get_alias
|
||||
#define purple_buddy_get_server_alias_wrapped purple_buddy_get_server_alias
|
||||
#define purple_find_buddy_wrapped purple_find_buddy
|
||||
#define purple_buddy_get_group_wrapped purple_buddy_get_group
|
||||
#define purple_blist_remove_buddy_wrapped purple_blist_remove_buddy
|
||||
#define purple_blist_alias_buddy_wrapped purple_blist_alias_buddy
|
||||
#define purple_blist_server_alias_buddy_wrapped purple_blist_server_alias_buddy
|
||||
#define purple_find_group_wrapped purple_find_group
|
||||
#define purple_group_new_wrapped purple_group_new
|
||||
#define purple_blist_add_contact_wrapped purple_blist_add_contact
|
||||
#define purple_buddy_get_contact_wrapped purple_buddy_get_contact
|
||||
#define purple_buddy_new_wrapped purple_buddy_new
|
||||
#define purple_blist_add_buddy_wrapped purple_blist_add_buddy
|
||||
#define purple_blist_find_chat_wrapped purple_blist_find_chat
|
||||
#define purple_chat_get_components_wrapped purple_chat_get_components
|
||||
#define purple_buddy_get_presence_wrapped purple_buddy_get_presence
|
||||
#define purple_buddy_get_account_wrapped purple_buddy_get_account
|
||||
#define purple_buddy_get_name_wrapped purple_buddy_get_name
|
||||
#define purple_find_buddies_wrapped purple_find_buddies
|
||||
#define purple_group_get_name_wrapped purple_group_get_name
|
||||
#define purple_blist_set_ui_ops_wrapped purple_blist_set_ui_ops
|
||||
#define purple_set_blist_wrapped purple_set_blist
|
||||
#define purple_blist_new_wrapped purple_blist_new
|
||||
#define purple_blist_load_wrapped purple_blist_load
|
||||
#define purple_blist_get_handle_wrapped purple_blist_get_handle
|
||||
#define purple_buddy_icons_set_account_icon_wrapped purple_buddy_icons_set_account_icon
|
||||
#define purple_buddy_icons_find_wrapped purple_buddy_icons_find
|
||||
#define purple_buddy_icon_get_full_path_wrapped purple_buddy_icon_get_full_path
|
||||
#define purple_buddy_icon_unref_wrapped purple_buddy_icon_unref
|
||||
#define purple_buddy_icons_find_account_icon_wrapped purple_buddy_icons_find_account_icon
|
||||
#define purple_buddy_icon_get_data_wrapped purple_buddy_icon_get_data
|
||||
#define purple_certificate_add_ca_search_path_wrapped purple_certificate_add_ca_search_path
|
||||
#define purple_connection_get_state_wrapped purple_connection_get_state
|
||||
#define purple_connection_get_account_wrapped purple_connection_get_account
|
||||
#define purple_connection_get_display_name_wrapped purple_connection_get_display_name
|
||||
#define purple_connections_set_ui_ops_wrapped purple_connections_set_ui_ops
|
||||
#define purple_connections_get_handle_wrapped purple_connections_get_handle
|
||||
#define purple_conversation_get_im_data_wrapped purple_conversation_get_im_data
|
||||
#define purple_conversation_get_chat_data_wrapped purple_conversation_get_chat_data
|
||||
#define purple_find_conversation_with_account_wrapped purple_find_conversation_with_account
|
||||
#define purple_conversation_new_wrapped purple_conversation_new
|
||||
#define purple_conversation_get_type_wrapped purple_conversation_get_type
|
||||
#define purple_conversation_set_data_wrapped purple_conversation_set_data
|
||||
#define purple_conversation_update_wrapped purple_conversation_update
|
||||
#define purple_conv_im_send_wrapped purple_conv_im_send
|
||||
#define purple_conv_chat_send_wrapped purple_conv_chat_send
|
||||
#define purple_conversation_destroy_wrapped purple_conversation_destroy
|
||||
#define purple_conversation_get_account_wrapped purple_conversation_get_account
|
||||
#define purple_conversation_get_name_wrapped purple_conversation_get_name
|
||||
#define purple_conversations_set_ui_ops_wrapped purple_conversations_set_ui_ops
|
||||
#define purple_conversations_get_handle_wrapped purple_conversations_get_handle
|
||||
#define purple_core_set_ui_ops_wrapped purple_core_set_ui_ops
|
||||
#define purple_core_init_wrapped purple_core_init
|
||||
#define purple_debug_set_ui_ops_wrapped purple_debug_set_ui_ops
|
||||
#define purple_debug_set_verbose_wrapped purple_debug_set_verbose
|
||||
#define purple_dnsquery_set_ui_ops_wrapped purple_dnsquery_set_ui_ops
|
||||
#define purple_timeout_remove_wrapped purple_timeout_remove
|
||||
#define purple_input_add_wrapped purple_input_add
|
||||
#define purple_timeout_add_wrapped purple_timeout_add
|
||||
#define purple_timeout_add_seconds_wrapped purple_timeout_add_seconds
|
||||
#define purple_eventloop_set_ui_ops_wrapped purple_eventloop_set_ui_ops
|
||||
#define purple_input_remove_wrapped purple_input_remove
|
||||
#define purple_xfer_ui_ready_wrapped purple_xfer_ui_ready
|
||||
#define purple_xfer_request_accepted_wrapped purple_xfer_request_accepted
|
||||
#define purple_xfer_request_denied_wrapped purple_xfer_request_denied
|
||||
#define purple_xfer_get_account_wrapped purple_xfer_get_account
|
||||
#define purple_xfer_get_filename_wrapped purple_xfer_get_filename
|
||||
#define purple_xfer_get_size_wrapped purple_xfer_get_size
|
||||
#define purple_xfer_unref_wrapped purple_xfer_unref
|
||||
#define purple_xfer_ref_wrapped purple_xfer_ref
|
||||
#define purple_xfers_set_ui_ops_wrapped purple_xfers_set_ui_ops
|
||||
#define purple_xfers_get_handle_wrapped purple_xfers_get_handle
|
||||
#define purple_roomlist_set_ui_ops_wrapped purple_roomlist_set_ui_ops
|
||||
#define purple_roomlist_get_list_wrapped purple_roomlist_get_list
|
||||
#define purple_imgstore_get_data_wrapped purple_imgstore_get_data
|
||||
#define purple_imgstore_get_size_wrapped purple_imgstore_get_size
|
||||
#define purple_imgstore_unref_wrapped purple_imgstore_unref
|
||||
#define purple_notify_user_info_new_wrapped purple_notify_user_info_new
|
||||
#define purple_notify_user_info_destroy_wrapped purple_notify_user_info_destroy
|
||||
#define purple_notify_user_info_get_entries_wrapped purple_notify_user_info_get_entries
|
||||
#define purple_notify_user_info_entry_get_label_wrapped purple_notify_user_info_entry_get_label
|
||||
#define purple_notify_user_info_entry_get_value_wrapped purple_notify_user_info_entry_get_value
|
||||
#define purple_notify_set_ui_ops_wrapped purple_notify_set_ui_ops
|
||||
#define purple_plugins_add_search_path_wrapped purple_plugins_add_search_path
|
||||
#define purple_plugin_action_free_wrapped purple_plugin_action_free
|
||||
#define purple_prefs_load_wrapped purple_prefs_load
|
||||
#define purple_prefs_set_bool_wrapped purple_prefs_set_bool
|
||||
#define purple_prefs_set_string_wrapped purple_prefs_set_string
|
||||
#define purple_privacy_deny_wrapped purple_privacy_deny
|
||||
#define purple_privacy_allow_wrapped purple_privacy_allow
|
||||
#define purple_privacy_check_wrapped purple_privacy_check
|
||||
#define purple_proxy_info_new_wrapped purple_proxy_info_new
|
||||
#define purple_proxy_info_set_type_wrapped purple_proxy_info_set_type
|
||||
#define purple_proxy_info_set_host_wrapped purple_proxy_info_set_host
|
||||
#define purple_proxy_info_set_port_wrapped purple_proxy_info_set_port
|
||||
#define purple_proxy_info_set_username_wrapped purple_proxy_info_set_username
|
||||
#define purple_proxy_info_set_password_wrapped purple_proxy_info_set_password
|
||||
#define purple_find_prpl_wrapped purple_find_prpl
|
||||
#define purple_prpl_send_attention_wrapped purple_prpl_send_attention
|
||||
#define purple_request_set_ui_ops_wrapped purple_request_set_ui_ops
|
||||
#define serv_get_info_wrapped serv_get_info
|
||||
#define serv_alias_buddy_wrapped serv_alias_buddy
|
||||
#define serv_send_typing_wrapped serv_send_typing
|
||||
#define serv_join_chat_wrapped serv_join_chat
|
||||
#define purple_signal_connect_wrapped purple_signal_connect
|
||||
#define purple_status_type_get_id_wrapped purple_status_type_get_id
|
||||
#define purple_presence_get_active_status_wrapped purple_presence_get_active_status
|
||||
#define purple_status_type_get_primitive_wrapped purple_status_type_get_primitive
|
||||
#define purple_status_get_type_wrapped purple_status_get_type
|
||||
#define purple_status_get_attr_string_wrapped purple_status_get_attr_string
|
||||
#define purple_markup_escape_text_wrapped purple_markup_escape_text
|
||||
#define purple_markup_strip_html_wrapped purple_markup_strip_html
|
||||
#define purple_strdup_withhtml_wrapped purple_strdup_withhtml
|
||||
#define purple_markup_html_to_xhtml_wrapped purple_markup_html_to_xhtml
|
||||
#define purple_normalize_wrapped purple_normalize
|
||||
#define purple_utf8_try_convert_wrapped purple_utf8_try_convert
|
||||
#define purple_util_set_user_dir_wrapped purple_util_set_user_dir
|
||||
#define wpurple_g_io_channel_win32_new_socket_wrapped wpurple_g_io_channel_win32_new_socket
|
||||
#endif
|
||||
|
||||
bool resolvePurpleFunctions();
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
[service]
|
||||
jid = icq.localhost
|
||||
password = secret
|
||||
server = 127.0.0.1
|
||||
port = 5347
|
||||
protocol=prpl-jabber
|
||||
#server_mode=1
|
||||
|
||||
[database]
|
||||
database = test.sql
|
||||
prefix=icq
|
|
@ -1,197 +0,0 @@
|
|||
/**
|
||||
* libtransport -- C++ library for easy XMPP Transports development
|
||||
*
|
||||
* Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
|
||||
// win32/libc_interface.h defines its own socket(), read() and so on.
|
||||
// We don't want to use it here.
|
||||
#define _LIBC_INTERFACE_H_ 1
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#include "glib.h"
|
||||
#include "purple.h"
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "errno.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include "sys/wait.h"
|
||||
#include "sys/signal.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#else
|
||||
#include <process.h>
|
||||
#define getpid _getpid
|
||||
#define ssize_t SSIZE_T
|
||||
#include "win32/win32dep.h"
|
||||
#define close closesocket
|
||||
#endif
|
||||
|
||||
#include "purple_defs.h"
|
||||
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
|
||||
using std::vector;
|
||||
|
||||
static GHashTable *ui_info = NULL;
|
||||
|
||||
void execute_purple_plugin_action(PurpleConnection *gc, const std::string &name) {
|
||||
PurplePlugin *plugin = gc && PURPLE_CONNECTION_IS_CONNECTED_WRAPPED(gc) ? gc->prpl : NULL;
|
||||
if (plugin && PURPLE_PLUGIN_HAS_ACTIONS(plugin)) {
|
||||
PurplePluginAction *action = NULL;
|
||||
GList *actions, *l;
|
||||
|
||||
actions = PURPLE_PLUGIN_ACTIONS(plugin, gc);
|
||||
|
||||
for (l = actions; l != NULL; l = l->next) {
|
||||
if (l->data) {
|
||||
action = (PurplePluginAction *) l->data;
|
||||
action->plugin = plugin;
|
||||
action->context = gc;
|
||||
if ((std::string) action->label == name) {
|
||||
action->callback(action);
|
||||
}
|
||||
purple_plugin_action_free_wrapped(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GHashTable *spectrum_ui_get_info(void)
|
||||
{
|
||||
if(NULL == ui_info) {
|
||||
ui_info = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
|
||||
g_hash_table_insert(ui_info, g_strdup("name"), g_strdup("Spectrum"));
|
||||
g_hash_table_insert(ui_info, g_strdup("version"), g_strdup("0.5"));
|
||||
g_hash_table_insert(ui_info, g_strdup("website"), g_strdup("http://spectrum.im"));
|
||||
g_hash_table_insert(ui_info, g_strdup("dev_website"), g_strdup("http://spectrum.im"));
|
||||
g_hash_table_insert(ui_info, g_strdup("client_type"), g_strdup("pc"));
|
||||
|
||||
/*
|
||||
* This is the client key for "Pidgin." It is owned by the AIM
|
||||
* account "markdoliner." Please don't use this key for other
|
||||
* applications. You can either not specify a client key, in
|
||||
* which case the default "libpurple" key will be used, or you
|
||||
* can register for your own client key at
|
||||
* http://developer.aim.com/manageKeys.jsp
|
||||
*/
|
||||
g_hash_table_insert(ui_info, g_strdup("prpl-aim-clientkey"), g_strdup("ma1cSASNCKFtrdv9"));
|
||||
g_hash_table_insert(ui_info, g_strdup("prpl-icq-clientkey"), g_strdup("ma1cSASNCKFtrdv9"));
|
||||
|
||||
/*
|
||||
* This is the distid for Pidgin, given to us by AOL. Please
|
||||
* don't use this for other applications. You can just not
|
||||
* specify a distid and libpurple will use a default.
|
||||
*/
|
||||
g_hash_table_insert(ui_info, g_strdup("prpl-aim-distid"), GINT_TO_POINTER(1550));
|
||||
g_hash_table_insert(ui_info, g_strdup("prpl-icq-distid"), GINT_TO_POINTER(1550));
|
||||
}
|
||||
|
||||
return ui_info;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
void spectrum_sigchld_handler(int sig)
|
||||
{
|
||||
int status;
|
||||
pid_t pid;
|
||||
|
||||
do {
|
||||
pid = waitpid(-1, &status, WNOHANG);
|
||||
} while (pid != 0 && pid != (pid_t)-1);
|
||||
|
||||
if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
|
||||
char errmsg[BUFSIZ];
|
||||
snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
|
||||
perror(errmsg);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int create_socket(const char *host, int portno) {
|
||||
struct sockaddr_in stSockAddr;
|
||||
int SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
|
||||
if (-1 == SocketFD) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
hostent *hos;
|
||||
if ((hos = gethostbyname(host)) == NULL) {
|
||||
// strerror() will not work for gethostbyname() and hstrerror()
|
||||
// is supposedly obsolete
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(&stSockAddr, 0, sizeof(stSockAddr));
|
||||
|
||||
stSockAddr.sin_family = AF_INET;
|
||||
stSockAddr.sin_port = htons(portno);
|
||||
memcpy(&(stSockAddr.sin_addr.s_addr), hos->h_addr, hos->h_length);
|
||||
|
||||
if (-1 == connect(SocketFD, (struct sockaddr *)&stSockAddr, sizeof(stSockAddr))) {
|
||||
close(SocketFD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return SocketFD;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
std::wstring utf8ToUtf16(const std::string& str)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (str.empty())
|
||||
return L"";
|
||||
|
||||
// First request the size of the required UTF-16 buffer
|
||||
int numRequiredBytes = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), boost::numeric_cast<int>(str.size()), NULL, 0);
|
||||
if (!numRequiredBytes)
|
||||
return L"";
|
||||
|
||||
// Allocate memory for the UTF-16 string
|
||||
std::vector<wchar_t> utf16Str(numRequiredBytes);
|
||||
|
||||
int numConverted = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), boost::numeric_cast<int>(str.size()), &utf16Str[0], numRequiredBytes);
|
||||
if (!numConverted)
|
||||
return L"";
|
||||
|
||||
std::wstring wstr(&utf16Str[0], numConverted);
|
||||
return wstr;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// I don't believe libtransport is exception-safe so we'll just return an empty string instead
|
||||
return L"";
|
||||
}
|
||||
}
|
||||
#endif // _WIN32
|
|
@ -1,37 +0,0 @@
|
|||
/**
|
||||
* libtransport -- C++ library for easy XMPP Transports development
|
||||
*
|
||||
* Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "purple.h"
|
||||
#include <string>
|
||||
|
||||
#ifndef WIN32
|
||||
void spectrum_sigchld_handler(int sig);
|
||||
#endif
|
||||
|
||||
int create_socket(const char *host, int portno);
|
||||
GHashTable *spectrum_ui_get_info(void);
|
||||
|
||||
void execute_purple_plugin_action(PurpleConnection *gc, const std::string &name);
|
||||
|
||||
#ifdef _WIN32
|
||||
std::wstring utf8ToUtf16(const std::string& str);
|
||||
#endif
|
|
@ -1,10 +0,0 @@
|
|||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
FILE(GLOB SRC *.c *.cpp)
|
||||
|
||||
ADD_EXECUTABLE(spectrum2_smstools3_backend ${SRC})
|
||||
|
||||
target_link_libraries(spectrum2_smstools3_backend transport pthread ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
|
||||
|
||||
INSTALL(TARGETS spectrum2_smstools3_backend RUNTIME DESTINATION bin)
|
||||
|
|
@ -1,292 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008-2009 J-P Nurmi jpnurmi@gmail.com
|
||||
*
|
||||
* This example is free, and not covered by LGPL license. There is no
|
||||
* restriction applied to their modification, redistribution, using and so on.
|
||||
* You can study them, modify them, use them in your own program - either
|
||||
* completely or partially. By using it you may give me some credits in your
|
||||
* program, but you don't have to.
|
||||
*/
|
||||
|
||||
#include "transport/Config.h"
|
||||
#include "transport/Logging.h"
|
||||
#include "transport/NetworkPlugin.h"
|
||||
#include "transport/SQLite3Backend.h"
|
||||
#include "transport/MySQLBackend.h"
|
||||
#include "transport/PQXXBackend.h"
|
||||
#include "transport/StorageBackend.h"
|
||||
#include "Swiften/Swiften.h"
|
||||
#include "Swiften/SwiftenCompat.h"
|
||||
#include <boost/filesystem.hpp>
|
||||
#include "unistd.h"
|
||||
#include "signal.h"
|
||||
#include "sys/wait.h"
|
||||
#include "sys/signal.h"
|
||||
#include <fstream>
|
||||
#include <streambuf>
|
||||
|
||||
Swift::SimpleEventLoop *loop_;
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
using namespace boost::filesystem;
|
||||
|
||||
using namespace boost::program_options;
|
||||
using namespace Transport;
|
||||
|
||||
DEFINE_LOGGER(logger, "SMSNetworkPlugin");
|
||||
|
||||
#define INTERNAL_USER "/sms@backend@internal@user"
|
||||
|
||||
class SMSNetworkPlugin;
|
||||
SMSNetworkPlugin * np = NULL;
|
||||
|
||||
class SMSNetworkPlugin : public NetworkPlugin {
|
||||
public:
|
||||
Swift::BoostNetworkFactories *m_factories;
|
||||
Swift::BoostIOServiceThread m_boostIOServiceThread;
|
||||
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Connection> m_conn;
|
||||
Swift::Timer::ref m_timer;
|
||||
int m_internalUser;
|
||||
StorageBackend *storageBackend;
|
||||
|
||||
SMSNetworkPlugin(Config *config, Swift::SimpleEventLoop *loop, StorageBackend *storagebackend, const std::string &host, int port) : NetworkPlugin() {
|
||||
this->config = config;
|
||||
this->storageBackend = storagebackend;
|
||||
m_factories = new Swift::BoostNetworkFactories(loop);
|
||||
m_conn = m_factories->getConnectionFactory()->createConnection();
|
||||
m_conn->onDataRead.connect(boost::bind(&SMSNetworkPlugin::_handleDataRead, this, _1));
|
||||
m_conn->connect(Swift::HostAddressPort(SWIFT_HOSTADDRESS(host), port));
|
||||
// m_conn->onConnectFinished.connect(boost::bind(&FrotzNetworkPlugin::_handleConnected, this, _1));
|
||||
// m_conn->onDisconnected.connect(boost::bind(&FrotzNetworkPlugin::handleDisconnected, this));
|
||||
|
||||
LOG4CXX_INFO(logger, "Starting the plugin.");
|
||||
|
||||
m_timer = m_factories->getTimerFactory()->createTimer(5000);
|
||||
m_timer->onTick.connect(boost::bind(&SMSNetworkPlugin::handleSMSDir, this));
|
||||
m_timer->start();
|
||||
|
||||
// We're reusing our database model here. Buddies of user with JID INTERNAL_USER are there
|
||||
// to match received GSM messages from number N with the XMPP users who sent message to number N.
|
||||
// BuddyName = GSM number
|
||||
// Alias = XMPP user JID to which the messages from this number is sent to.
|
||||
// TODO: This should be per Modem!!!
|
||||
UserInfo info;
|
||||
info.jid = INTERNAL_USER;
|
||||
info.password = "";
|
||||
storageBackend->setUser(info);
|
||||
storageBackend->getUser(INTERNAL_USER, info);
|
||||
m_internalUser = info.id;
|
||||
}
|
||||
|
||||
|
||||
void handleSMS(const std::string &sms) {
|
||||
LOG4CXX_INFO(logger, "Handling SMS " << sms << ".");
|
||||
std::ifstream t(sms.c_str());
|
||||
std::string str;
|
||||
|
||||
t.seekg(0, std::ios::end);
|
||||
str.reserve(t.tellg());
|
||||
t.seekg(0, std::ios::beg);
|
||||
|
||||
str.assign((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
|
||||
|
||||
std::string from = "";
|
||||
std::string msg = "";
|
||||
while(str.find("\n") != std::string::npos) {
|
||||
std::string line = str.substr(0, str.find("\n"));
|
||||
if (line.find("From: ") == 0) {
|
||||
from = line.substr(strlen("From: "));
|
||||
}
|
||||
else if (line.empty()) {
|
||||
msg = str.substr(1);
|
||||
break;
|
||||
}
|
||||
str = str.substr(str.find("\n") + 1);
|
||||
}
|
||||
|
||||
std::list<BuddyInfo> roster;
|
||||
storageBackend->getBuddies(m_internalUser, roster);
|
||||
|
||||
std::string to;
|
||||
BOOST_FOREACH(BuddyInfo &b, roster) {
|
||||
if (b.legacyName == from) {
|
||||
to = b.alias;
|
||||
}
|
||||
}
|
||||
|
||||
if (to.empty()) {
|
||||
LOG4CXX_WARN(logger, "Received SMS from " << from << ", but this number is not associated with any XMPP user.");
|
||||
}
|
||||
|
||||
LOG4CXX_INFO(logger, "Forwarding SMS from " << from << " to " << to << ".");
|
||||
handleMessage(to, from, msg);
|
||||
}
|
||||
|
||||
void handleSMSDir() {
|
||||
std::string dir = "/var/spool/sms/incoming/";
|
||||
if (CONFIG_HAS_KEY(config, "backend.incoming_dir")) {
|
||||
dir = CONFIG_STRING(config, "backend.incoming_dir");
|
||||
}
|
||||
LOG4CXX_INFO(logger, "Checking directory " << dir << " for incoming SMS.");
|
||||
|
||||
path p(dir);
|
||||
directory_iterator end_itr;
|
||||
for (directory_iterator itr(p); itr != end_itr; ++itr) {
|
||||
|
||||
try {
|
||||
if (is_regular(itr->path())) {
|
||||
handleSMS(itr->path().string());
|
||||
remove(itr->path());
|
||||
}
|
||||
}
|
||||
catch (const filesystem_error& ex) {
|
||||
LOG4CXX_ERROR(logger, "Error when removing the SMS: " << ex.what() << ".");
|
||||
}
|
||||
}
|
||||
m_timer->start();
|
||||
}
|
||||
|
||||
void sendSMS(const std::string &to, const std::string &msg) {
|
||||
// TODO: Probably
|
||||
std::string data = "To: " + to + "\n";
|
||||
data += "\n";
|
||||
data += msg;
|
||||
|
||||
// generate random string here...
|
||||
std::string bucket = "abcdefghijklmnopqrstuvwxyz";
|
||||
std::string uuid;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
uuid += bucket[rand() % bucket.size()];
|
||||
}
|
||||
std::ofstream myfile;
|
||||
myfile.open (std::string("/var/spool/sms/outgoing/spectrum." + uuid).c_str());
|
||||
myfile << data;
|
||||
myfile.close();
|
||||
}
|
||||
|
||||
void sendData(const std::string &string) {
|
||||
m_conn->write(Swift::createSafeByteArray(string));
|
||||
}
|
||||
|
||||
void _handleDataRead(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::SafeByteArray> data) {
|
||||
std::string d(data->begin(), data->end());
|
||||
handleDataRead(d);
|
||||
}
|
||||
|
||||
void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
|
||||
UserInfo info;
|
||||
if (!storageBackend->getUser(user, info)) {
|
||||
handleDisconnected(user, 0, "Not registered user.");
|
||||
return;
|
||||
}
|
||||
std::list<BuddyInfo> roster;
|
||||
storageBackend->getBuddies(info.id, roster);
|
||||
|
||||
// Send available presence to every number in the roster.
|
||||
BOOST_FOREACH(BuddyInfo &b, roster) {
|
||||
handleBuddyChanged(user, b.legacyName, b.alias, b.groups, pbnetwork::STATUS_ONLINE);
|
||||
}
|
||||
|
||||
np->handleConnected(user);
|
||||
}
|
||||
|
||||
void handleLogoutRequest(const std::string &user, const std::string &legacyName) {
|
||||
}
|
||||
|
||||
void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "", const std::string &id = "") {
|
||||
// Remove trailing +, because smstools doesn't use it in "From: " field for received messages.
|
||||
std::string n = legacyName;
|
||||
if (n.find("+") == 0) {
|
||||
n = n.substr(1);
|
||||
}
|
||||
|
||||
// Create GSM Number - XMPP user pair to match the potential response and send it to the proper JID.
|
||||
BuddyInfo info;
|
||||
info.legacyName = n;
|
||||
info.alias = user;
|
||||
info.id = -1;
|
||||
info.subscription = "both";
|
||||
info.flags = 0;
|
||||
storageBackend->addBuddy(m_internalUser, info);
|
||||
|
||||
LOG4CXX_INFO(logger, "Sending SMS from " << user << " to " << n << ".");
|
||||
sendSMS(n, message);
|
||||
}
|
||||
|
||||
void handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password) {
|
||||
}
|
||||
|
||||
void handleLeaveRoomRequest(const std::string &user, const std::string &room) {
|
||||
}
|
||||
|
||||
void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups) {
|
||||
LOG4CXX_INFO(logger, user << ": Added buddy " << buddyName << ".");
|
||||
handleBuddyChanged(user, buddyName, alias, groups, pbnetwork::STATUS_ONLINE);
|
||||
}
|
||||
|
||||
void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
Config *config;
|
||||
};
|
||||
|
||||
static void spectrum_sigchld_handler(int sig)
|
||||
{
|
||||
int status;
|
||||
pid_t pid;
|
||||
|
||||
do {
|
||||
pid = waitpid(-1, &status, WNOHANG);
|
||||
} while (pid != 0 && pid != (pid_t)-1);
|
||||
|
||||
if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
|
||||
char errmsg[BUFSIZ];
|
||||
snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
|
||||
perror(errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char* argv[]) {
|
||||
std::string host;
|
||||
int port;
|
||||
|
||||
if (signal(SIGCHLD, spectrum_sigchld_handler) == SIG_ERR) {
|
||||
std::cout << "SIGCHLD handler can't be set\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string error;
|
||||
Config *cfg = Config::createFromArgs(argc, argv, error, host, port);
|
||||
if (cfg == NULL) {
|
||||
std::cerr << error;
|
||||
return 1;
|
||||
}
|
||||
|
||||
Logging::initBackendLogging(cfg);
|
||||
|
||||
StorageBackend *storageBackend = StorageBackend::createBackend(cfg, error);
|
||||
if (storageBackend == NULL) {
|
||||
if (!error.empty()) {
|
||||
std::cerr << error << "\n";
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
else if (!storageBackend->connect()) {
|
||||
std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
Swift::SimpleEventLoop eventLoop;
|
||||
loop_ = &eventLoop;
|
||||
np = new SMSNetworkPlugin(cfg, &eventLoop, storageBackend, host, port);
|
||||
loop_->run();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
FILE(GLOB SRC *.cpp)
|
||||
|
||||
ADD_EXECUTABLE(spectrum2_swiften_backend ${SRC})
|
||||
|
||||
IF (NOT WIN32)
|
||||
target_link_libraries(spectrum2_swiften_backend transport pthread ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
|
||||
else()
|
||||
target_link_libraries(spectrum2_swiften_backend transport ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
|
||||
endif()
|
||||
|
||||
INSTALL(TARGETS spectrum2_swiften_backend RUNTIME DESTINATION bin)
|
||||
|
|
@ -1,461 +0,0 @@
|
|||
// Transport includes
|
||||
#include "transport/Config.h"
|
||||
#include "transport/NetworkPlugin.h"
|
||||
#include "transport/Logging.h"
|
||||
|
||||
#include "boost/date_time/posix_time/posix_time.hpp"
|
||||
|
||||
// Swiften
|
||||
#include "Swiften/Swiften.h"
|
||||
#include "Swiften/SwiftenCompat.h"
|
||||
#include <Swiften/Version.h>
|
||||
#define HAVE_SWIFTEN_3 (SWIFTEN_VERSION >= 0x030000)
|
||||
|
||||
#ifndef WIN32
|
||||
// for signal handler
|
||||
#include "unistd.h"
|
||||
#include "signal.h"
|
||||
#include "sys/wait.h"
|
||||
#include "sys/signal.h"
|
||||
#endif
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
#ifndef __MACH__
|
||||
// malloc_trim
|
||||
#include "malloc.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Boost
|
||||
#include <boost/algorithm/string.hpp>
|
||||
using namespace boost::filesystem;
|
||||
using namespace boost::program_options;
|
||||
using namespace Transport;
|
||||
|
||||
DEFINE_LOGGER(logger, "Swiften");
|
||||
DEFINE_LOGGER(logger_xml, "backend.xml");
|
||||
|
||||
// eventloop
|
||||
Swift::SimpleEventLoop *loop_;
|
||||
|
||||
// Plugins
|
||||
class SwiftenPlugin;
|
||||
NetworkPlugin *np = NULL;
|
||||
Swift::XMPPSerializer *serializer;
|
||||
|
||||
class ForwardIQHandler : public Swift::IQHandler {
|
||||
public:
|
||||
std::map <std::string, std::string> m_id2resource;
|
||||
|
||||
ForwardIQHandler(NetworkPlugin *np, const std::string &user) {
|
||||
m_np = np;
|
||||
m_user = user;
|
||||
}
|
||||
|
||||
bool handleIQ(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::IQ> iq) {
|
||||
if (iq->getPayload<Swift::RosterPayload>() != NULL) {
|
||||
return false;
|
||||
}
|
||||
if (iq->getType() == Swift::IQ::Get) {
|
||||
m_id2resource[iq->getID()] = iq->getFrom().getResource();
|
||||
}
|
||||
|
||||
iq->setTo(m_user);
|
||||
std::string xml = safeByteArrayToString(serializer->serializeElement(iq));
|
||||
m_np->sendRawXML(xml);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
NetworkPlugin *m_np;
|
||||
std::string m_user;
|
||||
|
||||
};
|
||||
|
||||
class SwiftenPlugin : public NetworkPlugin, Swift::XMPPParserClient {
|
||||
public:
|
||||
Swift::BoostNetworkFactories *m_factories;
|
||||
Swift::BoostIOServiceThread m_boostIOServiceThread;
|
||||
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Connection> m_conn;
|
||||
bool m_firstPing;
|
||||
|
||||
Swift::FullPayloadSerializerCollection collection;
|
||||
Swift::XMPPParser *m_xmppParser;
|
||||
Swift::FullPayloadParserFactoryCollection m_collection2;
|
||||
|
||||
SwiftenPlugin(Config *config, Swift::SimpleEventLoop *loop, const std::string &host, int port) : NetworkPlugin() {
|
||||
this->config = config;
|
||||
m_firstPing = true;
|
||||
m_factories = new Swift::BoostNetworkFactories(loop);
|
||||
m_conn = m_factories->getConnectionFactory()->createConnection();
|
||||
m_conn->onDataRead.connect(boost::bind(&SwiftenPlugin::_handleDataRead, this, _1));
|
||||
m_conn->connect(Swift::HostAddressPort(SWIFT_HOSTADDRESS(host), port));
|
||||
#if HAVE_SWIFTEN_3
|
||||
serializer = new Swift::XMPPSerializer(&collection, Swift::ClientStreamType, false);
|
||||
#else
|
||||
serializer = new Swift::XMPPSerializer(&collection, Swift::ClientStreamType);
|
||||
#endif
|
||||
m_xmppParser = new Swift::XMPPParser(this, &m_collection2, m_factories->getXMLParserFactory());
|
||||
m_xmppParser->parse("<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='localhost' version='1.0'>");
|
||||
|
||||
LOG4CXX_INFO(logger, "Starting the plugin.");
|
||||
}
|
||||
|
||||
// NetworkPlugin uses this method to send the data to networkplugin server
|
||||
void sendData(const std::string &string) {
|
||||
m_conn->write(Swift::createSafeByteArray(string));
|
||||
}
|
||||
|
||||
// This method has to call handleDataRead with all received data from network plugin server
|
||||
void _handleDataRead(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::SafeByteArray> data) {
|
||||
if (m_firstPing) {
|
||||
m_firstPing = false;
|
||||
NetworkPlugin::PluginConfig cfg;
|
||||
cfg.setRawXML(true);
|
||||
cfg.setNeedRegistration(false);
|
||||
sendConfig(cfg);
|
||||
}
|
||||
std::string d(data->begin(), data->end());
|
||||
handleDataRead(d);
|
||||
}
|
||||
|
||||
void handleStreamStart(const Swift::ProtocolHeader&) {}
|
||||
#if HAVE_SWIFTEN_3
|
||||
void handleElement(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::ToplevelElement> element) {
|
||||
#else
|
||||
void handleElement(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Element> element) {
|
||||
#endif
|
||||
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Stanza> stanza = SWIFTEN_SHRPTR_NAMESPACE::dynamic_pointer_cast<Swift::Stanza>(element);
|
||||
if (!stanza) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string user = stanza->getFrom().toBare();
|
||||
|
||||
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Client> client = m_users[user];
|
||||
if (!client)
|
||||
return;
|
||||
|
||||
stanza->setFrom(client->getJID());
|
||||
|
||||
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Message> message = SWIFTEN_SHRPTR_NAMESPACE::dynamic_pointer_cast<Swift::Message>(stanza);
|
||||
if (message) {
|
||||
client->sendMessage(message);
|
||||
return;
|
||||
}
|
||||
|
||||
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Presence> presence = SWIFTEN_SHRPTR_NAMESPACE::dynamic_pointer_cast<Swift::Presence>(stanza);
|
||||
if (presence) {
|
||||
client->sendPresence(presence);
|
||||
return;
|
||||
}
|
||||
|
||||
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::IQ> iq = SWIFTEN_SHRPTR_NAMESPACE::dynamic_pointer_cast<Swift::IQ>(stanza);
|
||||
if (iq) {
|
||||
if (m_handlers[user]->m_id2resource.find(stanza->getID()) != m_handlers[user]->m_id2resource.end()) {
|
||||
std::string resource = m_handlers[user]->m_id2resource[stanza->getID()];
|
||||
if (resource.empty()) {
|
||||
iq->setTo(Swift::JID(iq->getTo().getNode(), iq->getTo().getDomain()));
|
||||
} else {
|
||||
iq->setTo(Swift::JID(iq->getTo().getNode(), iq->getTo().getDomain(), resource));
|
||||
}
|
||||
|
||||
m_handlers[user]->m_id2resource.erase(stanza->getID());
|
||||
}
|
||||
client->getIQRouter()->sendIQ(iq);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void handleStreamEnd() {}
|
||||
|
||||
void handleRawXML(const std::string &xml) {
|
||||
m_xmppParser->parse(xml);
|
||||
}
|
||||
|
||||
void handleSwiftDisconnected(const std::string &user, const boost::optional<Swift::ClientError> &error) {
|
||||
std::string message = "";
|
||||
bool reconnect = false;
|
||||
if (error) {
|
||||
switch(error->getType()) {
|
||||
case Swift::ClientError::UnknownError: message = ("Unknown Error"); reconnect = true; break;
|
||||
case Swift::ClientError::DomainNameResolveError: message = ("Unable to find server"); break;
|
||||
case Swift::ClientError::ConnectionError: message = ("Error connecting to server"); break;
|
||||
case Swift::ClientError::ConnectionReadError: message = ("Error while receiving server data"); reconnect = true; break;
|
||||
case Swift::ClientError::ConnectionWriteError: message = ("Error while sending data to the server"); reconnect = true; break;
|
||||
case Swift::ClientError::XMLError: message = ("Error parsing server data"); reconnect = true; break;
|
||||
case Swift::ClientError::AuthenticationFailedError: message = ("Login/password invalid"); break;
|
||||
case Swift::ClientError::CompressionFailedError: message = ("Error while compressing stream"); break;
|
||||
case Swift::ClientError::ServerVerificationFailedError: message = ("Server verification failed"); break;
|
||||
case Swift::ClientError::NoSupportedAuthMechanismsError: message = ("Authentication mechanisms not supported"); break;
|
||||
case Swift::ClientError::UnexpectedElementError: message = ("Unexpected response"); break;
|
||||
case Swift::ClientError::ResourceBindError: message = ("Error binding resource"); break;
|
||||
case Swift::ClientError::SessionStartError: message = ("Error starting session"); break;
|
||||
case Swift::ClientError::StreamError: message = ("Stream error"); break;
|
||||
case Swift::ClientError::TLSError: message = ("Encryption error"); break;
|
||||
case Swift::ClientError::ClientCertificateLoadError: message = ("Error loading certificate (Invalid password?)"); break;
|
||||
case Swift::ClientError::ClientCertificateError: message = ("Certificate not authorized"); break;
|
||||
|
||||
case Swift::ClientError::UnknownCertificateError: message = ("Unknown certificate"); break;
|
||||
case Swift::ClientError::CertificateExpiredError: message = ("Certificate has expired"); break;
|
||||
case Swift::ClientError::CertificateNotYetValidError: message = ("Certificate is not yet valid"); break;
|
||||
case Swift::ClientError::CertificateSelfSignedError: message = ("Certificate is self-signed"); break;
|
||||
case Swift::ClientError::CertificateRejectedError: message = ("Certificate has been rejected"); break;
|
||||
case Swift::ClientError::CertificateUntrustedError: message = ("Certificate is not trusted"); break;
|
||||
case Swift::ClientError::InvalidCertificatePurposeError: message = ("Certificate cannot be used for encrypting your connection"); break;
|
||||
case Swift::ClientError::CertificatePathLengthExceededError: message = ("Certificate path length constraint exceeded"); break;
|
||||
case Swift::ClientError::InvalidCertificateSignatureError: message = ("Invalid certificate signature"); break;
|
||||
case Swift::ClientError::InvalidCAError: message = ("Invalid Certificate Authority"); break;
|
||||
case Swift::ClientError::InvalidServerIdentityError: message = ("Certificate does not match the host identity"); break;
|
||||
}
|
||||
}
|
||||
LOG4CXX_INFO(logger, user << ": Disconnected " << message);
|
||||
handleDisconnected(user, reconnect ? 0 : 3, message);
|
||||
|
||||
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Client> client = m_users[user];
|
||||
if (client) {
|
||||
client->onConnected.disconnect(boost::bind(&SwiftenPlugin::handleSwiftConnected, this, user));
|
||||
client->onDisconnected.disconnect(boost::bind(&SwiftenPlugin::handleSwiftDisconnected, this, user, _1));
|
||||
client->onMessageReceived.disconnect(boost::bind(&SwiftenPlugin::handleSwiftMessageReceived, this, user, _1));
|
||||
m_users.erase(user);
|
||||
m_handlers.erase(user);
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
#ifndef __FreeBSD__
|
||||
#ifndef __MACH__
|
||||
// force returning of memory chunks allocated by libxml2 to kernel
|
||||
malloc_trim(0);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void handleSwiftConnected(const std::string &user) {
|
||||
LOG4CXX_INFO(logger, user << ": Connected to XMPP server.");
|
||||
handleConnected(user);
|
||||
m_users[user]->requestRoster();
|
||||
Swift::Presence::ref response = Swift::Presence::create();
|
||||
response->setFrom(m_users[user]->getJID());
|
||||
m_users[user]->sendPresence(response);
|
||||
}
|
||||
|
||||
void handleSwiftRosterReceived(const std::string &user) {
|
||||
Swift::PresenceOracle *oracle = m_users[user]->getPresenceOracle();
|
||||
BOOST_FOREACH(const Swift::XMPPRosterItem &item, m_users[user]->getRoster()->getItems()) {
|
||||
Swift::Presence::ref lastPresence = oracle->getLastPresence(item.getJID());
|
||||
pbnetwork::StatusType status = lastPresence ? ((pbnetwork::StatusType) lastPresence->getShow()) : pbnetwork::STATUS_NONE;
|
||||
handleBuddyChanged(user, item.getJID().toBare().toString(),
|
||||
item.getName(), item.getGroups(), status);
|
||||
}
|
||||
}
|
||||
|
||||
void handleSwiftPresenceChanged(const std::string &user, Swift::Presence::ref presence) {
|
||||
// SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Client> client = m_users[user];
|
||||
// if (client->getMUCRegistry()->isMUC(presence->getFrom().toBare())) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if (presence->getPayload<Swift::MUCUserPayload>() != NULL || presence->getPayload<Swift::MUCPayload>() != NULL) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// LOG4CXX_INFO(logger, user << ": " << presence->getFrom().toBare().toString() << " presence changed");
|
||||
//
|
||||
// std::string message = presence->getStatus();
|
||||
// std::string photo = "";
|
||||
//
|
||||
// SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::VCardUpdate> update = presence->getPayload<Swift::VCardUpdate>();
|
||||
// if (update) {
|
||||
// photo = update->getPhotoHash();
|
||||
// }
|
||||
//
|
||||
// boost::optional<Swift::XMPPRosterItem> item = m_users[user]->getRoster()->getItem(presence->getFrom());
|
||||
// if (item) {
|
||||
// handleBuddyChanged(user, presence->getFrom().toBare().toString(), item->getName(), item->getGroups(), (pbnetwork::StatusType) presence->getShow(), message, photo);
|
||||
// }
|
||||
// else {
|
||||
// std::vector<std::string> groups;
|
||||
// handleBuddyChanged(user, presence->getFrom().toBare().toString(), presence->getFrom().toBare(), groups, (pbnetwork::StatusType) presence->getShow(), message, photo);
|
||||
// }
|
||||
presence->setTo(user);
|
||||
std::string xml = safeByteArrayToString(serializer->serializeElement(presence));
|
||||
sendRawXML(xml);
|
||||
}
|
||||
|
||||
void handleSwiftMessageReceived(const std::string &user, Swift::Message::ref message) {
|
||||
message->setTo(user);
|
||||
std::string xml = safeByteArrayToString(serializer->serializeElement(message));
|
||||
sendRawXML(xml);
|
||||
}
|
||||
|
||||
void handleSwiftenDataRead(const Swift::SafeByteArray &data) {
|
||||
std::string d = safeByteArrayToString(data);
|
||||
if (!boost::starts_with(d, "<auth")) {
|
||||
LOG4CXX_INFO(logger_xml, "XML IN " << d);
|
||||
}
|
||||
}
|
||||
|
||||
void handleSwiftenDataWritten(const Swift::SafeByteArray &data) {
|
||||
LOG4CXX_INFO(logger_xml, "XML OUT " << safeByteArrayToString(data));
|
||||
}
|
||||
|
||||
void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
|
||||
LOG4CXX_INFO(logger, user << ": connecting as " << legacyName);
|
||||
Swift::JID jid(legacyName);
|
||||
if (legacyName.find("/") == std::string::npos) {
|
||||
jid = Swift::JID(legacyName + "/Spectrum");
|
||||
}
|
||||
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Client> client = SWIFTEN_SHRPTR_NAMESPACE::make_shared<Swift::Client>(jid, password, m_factories);
|
||||
m_users[user] = client;
|
||||
client->setAlwaysTrustCertificates();
|
||||
client->onConnected.connect(boost::bind(&SwiftenPlugin::handleSwiftConnected, this, user));
|
||||
client->onDisconnected.connect(boost::bind(&SwiftenPlugin::handleSwiftDisconnected, this, user, _1));
|
||||
client->onMessageReceived.connect(boost::bind(&SwiftenPlugin::handleSwiftMessageReceived, this, user, _1));
|
||||
client->getRoster()->onInitialRosterPopulated.connect(boost::bind(&SwiftenPlugin::handleSwiftRosterReceived, this, user));
|
||||
client->getPresenceOracle()->onPresenceChange.connect(boost::bind(&SwiftenPlugin::handleSwiftPresenceChanged, this, user, _1));
|
||||
client->onDataRead.connect(boost::bind(&SwiftenPlugin::handleSwiftenDataRead, this, _1));
|
||||
client->onDataWritten.connect(boost::bind(&SwiftenPlugin::handleSwiftenDataWritten, this, _1));
|
||||
client->getSubscriptionManager()->onPresenceSubscriptionRequest.connect(boost::bind(&SwiftenPlugin::handleSubscriptionRequest, this, user, _1, _2, _3));
|
||||
client->getSubscriptionManager()->onPresenceSubscriptionRevoked.connect(boost::bind(&SwiftenPlugin::handleSubscriptionRevoked, this, user, _1, _2));
|
||||
Swift::ClientOptions opt;
|
||||
opt.allowPLAINWithoutTLS = true;
|
||||
client->connect(opt);
|
||||
|
||||
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<ForwardIQHandler> handler = SWIFTEN_SHRPTR_NAMESPACE::make_shared<ForwardIQHandler>(this, user);
|
||||
client->getIQRouter()->addHandler(handler);
|
||||
m_handlers[user] = handler;
|
||||
}
|
||||
|
||||
void handleSubscriptionRequest(const std::string &user, const Swift::JID& jid, const std::string& message, Swift::Presence::ref presence) {
|
||||
handleSwiftPresenceChanged(user, presence);
|
||||
}
|
||||
|
||||
void handleSubscriptionRevoked(const std::string &user, const Swift::JID& jid, const std::string& message) {
|
||||
Swift::Presence::ref presence = Swift::Presence::create();
|
||||
presence->setTo(user);
|
||||
presence->setFrom(jid);
|
||||
presence->setType(Swift::Presence::Unsubscribe);
|
||||
handleSwiftPresenceChanged(user, presence);
|
||||
}
|
||||
|
||||
void handleLogoutRequest(const std::string &user, const std::string &legacyName) {
|
||||
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Client> client = m_users[user];
|
||||
if (client) {
|
||||
client->onConnected.disconnect(boost::bind(&SwiftenPlugin::handleSwiftConnected, this, user));
|
||||
// client->onDisconnected.disconnect(boost::bind(&SwiftenPlugin::handleSwiftDisconnected, this, user, _1));
|
||||
client->onMessageReceived.disconnect(boost::bind(&SwiftenPlugin::handleSwiftMessageReceived, this, user, _1));
|
||||
client->getRoster()->onInitialRosterPopulated.disconnect(boost::bind(&SwiftenPlugin::handleSwiftRosterReceived, this, user));
|
||||
client->getPresenceOracle()->onPresenceChange.disconnect(boost::bind(&SwiftenPlugin::handleSwiftPresenceChanged, this, user, _1));
|
||||
client->disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &msg, const std::string &xhtml = "", const std::string &id = "") {
|
||||
}
|
||||
|
||||
void handleVCardRequest(const std::string &user, const std::string &legacyName, unsigned int id) {
|
||||
}
|
||||
|
||||
void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups) {
|
||||
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Client> client = m_users[user];
|
||||
if (client) {
|
||||
LOG4CXX_INFO(logger, user << ": Added/Updated buddy " << buddyName << ".");
|
||||
if (!client->getRoster()->containsJID(buddyName) || client->getRoster()->getSubscriptionStateForJID(buddyName) != Swift::RosterItemPayload::Both) {
|
||||
Swift::RosterItemPayload item;
|
||||
item.setName(alias);
|
||||
item.setJID(buddyName);
|
||||
item.setGroups(groups);
|
||||
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::RosterPayload> roster(new Swift::RosterPayload());
|
||||
roster->addItem(item);
|
||||
Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(roster, client->getIQRouter());
|
||||
// request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster));
|
||||
request->send();
|
||||
client->getSubscriptionManager()->requestSubscription(buddyName);
|
||||
}
|
||||
else {
|
||||
Swift::JID contact(buddyName);
|
||||
Swift::RosterItemPayload item(contact, alias, client->getRoster()->getSubscriptionStateForJID(contact));
|
||||
item.setGroups(groups);
|
||||
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::RosterPayload> roster(new Swift::RosterPayload());
|
||||
roster->addItem(item);
|
||||
Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(roster, client->getIQRouter());
|
||||
// request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster));
|
||||
request->send();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups) {
|
||||
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Client> client = m_users[user];
|
||||
if (client) {
|
||||
Swift::RosterItemPayload item(buddyName, "", Swift::RosterItemPayload::Remove);
|
||||
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::RosterPayload> roster(new Swift::RosterPayload());
|
||||
roster->addItem(item);
|
||||
Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(roster, client->getIQRouter());
|
||||
// request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster));
|
||||
request->send();
|
||||
}
|
||||
}
|
||||
|
||||
void handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password) {
|
||||
|
||||
}
|
||||
|
||||
void handleLeaveRoomRequest(const std::string &user, const std::string &room) {
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
Config *config;
|
||||
std::map<std::string, SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Client> > m_users;
|
||||
std::map<std::string, SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<ForwardIQHandler> > m_handlers;
|
||||
};
|
||||
|
||||
#ifndef WIN32
|
||||
static void spectrum_sigchld_handler(int sig)
|
||||
{
|
||||
int status;
|
||||
pid_t pid;
|
||||
|
||||
do {
|
||||
pid = waitpid(-1, &status, WNOHANG);
|
||||
} while (pid != 0 && pid != (pid_t)-1);
|
||||
|
||||
if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
|
||||
char errmsg[BUFSIZ];
|
||||
snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
|
||||
perror(errmsg);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int main (int argc, char* argv[]) {
|
||||
std::string host;
|
||||
int port;
|
||||
|
||||
#ifndef WIN32
|
||||
if (signal(SIGCHLD, spectrum_sigchld_handler) == SIG_ERR) {
|
||||
std::cout << "SIGCHLD handler can't be set\n";
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string error;
|
||||
Config *cfg = Config::createFromArgs(argc, argv, error, host, port);
|
||||
if (cfg == NULL) {
|
||||
std::cerr << error;
|
||||
return 1;
|
||||
}
|
||||
|
||||
Logging::initBackendLogging(cfg);
|
||||
|
||||
Swift::SimpleEventLoop eventLoop;
|
||||
loop_ = &eventLoop;
|
||||
np = new SwiftenPlugin(cfg, &eventLoop, host, port);
|
||||
loop_->run();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
FILE(GLOB SRC *.c *.cpp)
|
||||
|
||||
ADD_EXECUTABLE(spectrum2_template_backend ${SRC})
|
||||
|
||||
if (CMAKE_COMPILER_IS_GNUCXX)
|
||||
if (NOT WIN32)
|
||||
target_link_libraries(spectrum2_template_backend transport pthread ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
|
||||
else()
|
||||
target_link_libraries(spectrum2_template_backend transport ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
|
||||
endif()
|
||||
else()
|
||||
target_link_libraries(spectrum2_template_backend transport ${PROTOBUF_LIBRARY} ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
|
||||
endif()
|
||||
|
||||
#INSTALL(TARGETS spectrum2_template_backend RUNTIME DESTINATION bin)
|
||||
|
|
@ -1 +0,0 @@
|
|||
This is just template for creating new generic spectrum2 backends. It does not do anything!
|
|
@ -1,68 +0,0 @@
|
|||
#include "plugin.h"
|
||||
|
||||
// Transport includes
|
||||
#include "transport/Config.h"
|
||||
#include "transport/NetworkPlugin.h"
|
||||
#include "transport/Logging.h"
|
||||
|
||||
// Swiften
|
||||
#include "Swiften/Swiften.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
// for signal handler
|
||||
#include "unistd.h"
|
||||
#include "signal.h"
|
||||
#include "sys/wait.h"
|
||||
#include "sys/signal.h"
|
||||
#endif
|
||||
// Boost
|
||||
#include <boost/algorithm/string.hpp>
|
||||
using namespace boost::filesystem;
|
||||
using namespace boost::program_options;
|
||||
using namespace Transport;
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
static void spectrum_sigchld_handler(int sig)
|
||||
{
|
||||
int status;
|
||||
pid_t pid;
|
||||
|
||||
do {
|
||||
pid = waitpid(-1, &status, WNOHANG);
|
||||
} while (pid != 0 && pid != (pid_t)-1);
|
||||
|
||||
if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
|
||||
char errmsg[BUFSIZ];
|
||||
snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
|
||||
perror(errmsg);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int main (int argc, char* argv[]) {
|
||||
std::string host;
|
||||
int port;
|
||||
|
||||
#ifndef _WIN32
|
||||
if (signal(SIGCHLD, spectrum_sigchld_handler) == SIG_ERR) {
|
||||
std::cout << "SIGCHLD handler can't be set\n";
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string error;
|
||||
Config *cfg = Config::createFromArgs(argc, argv, error, host, port);
|
||||
if (cfg == NULL) {
|
||||
std::cerr << error;
|
||||
return 1;
|
||||
}
|
||||
|
||||
Logging::initBackendLogging(cfg);
|
||||
|
||||
Swift::SimpleEventLoop eventLoop;
|
||||
Plugin p(cfg, &eventLoop, host, port);
|
||||
eventLoop.run();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
#include "plugin.h"
|
||||
// Transport includes
|
||||
#include "transport/Config.h"
|
||||
#include "transport/NetworkPlugin.h"
|
||||
#include "transport/Logging.h"
|
||||
|
||||
// Swiften
|
||||
#include "Swiften/Swiften.h"
|
||||
|
||||
// Boost
|
||||
#include <boost/algorithm/string.hpp>
|
||||
using namespace boost::filesystem;
|
||||
using namespace boost::program_options;
|
||||
using namespace Transport;
|
||||
|
||||
DEFINE_LOGGER(logger, "Backend Template");
|
||||
|
||||
Plugin::Plugin(Config *config, Swift::SimpleEventLoop *loop, const std::string &host, int port) : NetworkPlugin() {
|
||||
this->config = config;
|
||||
m_factories = new Swift::BoostNetworkFactories(loop);
|
||||
m_conn = m_factories->getConnectionFactory()->createConnection();
|
||||
m_conn->onDataRead.connect(boost::bind(&Plugin::_handleDataRead, this, _1));
|
||||
m_conn->connect(Swift::HostAddressPort(SWIFT_HOSTADDRESS(host), port));
|
||||
|
||||
LOG4CXX_INFO(logger, "Starting the plugin.");
|
||||
}
|
||||
|
||||
// NetworkPlugin uses this method to send the data to networkplugin server
|
||||
void Plugin::sendData(const std::string &string) {
|
||||
m_conn->write(Swift::createSafeByteArray(string));
|
||||
}
|
||||
|
||||
// This method has to call handleDataRead with all received data from network plugin server
|
||||
void Plugin::_handleDataRead(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::SafeByteArray> data) {
|
||||
std::string d(data->begin(), data->end());
|
||||
handleDataRead(d);
|
||||
}
|
||||
|
||||
void Plugin::handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
|
||||
handleConnected(user);
|
||||
LOG4CXX_INFO(logger, user << ": Added buddy - Echo.");
|
||||
handleBuddyChanged(user, "echo", "Echo", std::vector<std::string>(), pbnetwork::STATUS_ONLINE);
|
||||
}
|
||||
|
||||
void Plugin::handleLogoutRequest(const std::string &user, const std::string &legacyName) {
|
||||
}
|
||||
|
||||
void Plugin::handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml, const std::string &id) {
|
||||
LOG4CXX_INFO(logger, "Sending message from " << user << " to " << legacyName << ".");
|
||||
if (legacyName == "echo") {
|
||||
handleMessage(user, legacyName, message);
|
||||
}
|
||||
}
|
||||
|
||||
void Plugin::handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups) {
|
||||
LOG4CXX_INFO(logger, user << ": Added buddy " << buddyName << ".");
|
||||
handleBuddyChanged(user, buddyName, alias, groups, pbnetwork::STATUS_ONLINE);
|
||||
}
|
||||
|
||||
void Plugin::handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups) {
|
||||
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "Swiften/Swiften.h"
|
||||
#include "Swiften/SwiftenCompat.h"
|
||||
|
||||
#include "transport/Config.h"
|
||||
#include "transport/NetworkPlugin.h"
|
||||
|
||||
class Plugin : public Transport::NetworkPlugin {
|
||||
public:
|
||||
Plugin(Transport::Config *config, Swift::SimpleEventLoop *loop, const std::string &host, int port);
|
||||
|
||||
// NetworkPlugin uses this method to send the data to networkplugin server
|
||||
void sendData(const std::string &string);
|
||||
|
||||
void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password);
|
||||
|
||||
void handleLogoutRequest(const std::string &user, const std::string &legacyName);
|
||||
|
||||
void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "", const std::string &id = "");
|
||||
|
||||
void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups);
|
||||
|
||||
void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups);
|
||||
|
||||
private:
|
||||
// This method has to call handleDataRead with all received data from network plugin server
|
||||
void _handleDataRead(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::SafeByteArray> data);
|
||||
|
||||
private:
|
||||
Swift::BoostNetworkFactories *m_factories;
|
||||
Swift::BoostIOServiceThread m_boostIOServiceThread;
|
||||
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Connection> m_conn;
|
||||
Transport::Config *config;
|
||||
};
|
|
@ -1,103 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import asyncore, argparse, protocol_pb2, socket, logging
|
||||
from NetworkPlugin import NetworkPlugin
|
||||
|
||||
np = None
|
||||
|
||||
|
||||
logger = logging.getLogger('Template Backend')
|
||||
logger.setLevel(logging.DEBUG)
|
||||
ch = logging.StreamHandler()
|
||||
ch.setLevel(logging.DEBUG)
|
||||
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
||||
ch.setFormatter(formatter)
|
||||
logger.addHandler(ch)
|
||||
|
||||
|
||||
def handleTransportData(data):
|
||||
"""
|
||||
This function is called when data is received from the NetworkPlugin server
|
||||
"""
|
||||
np.handleDataRead(data)
|
||||
|
||||
|
||||
class SpectrumPlugin(NetworkPlugin):
|
||||
global logger
|
||||
def __init__(self, iochannel):
|
||||
NetworkPlugin.__init__(self)
|
||||
self.iochannel = iochannel
|
||||
logger.info("Starting plugin.")
|
||||
|
||||
def sendData(self, string):
|
||||
"""
|
||||
NetworkPlugin uses this method to send the data to networkplugin server
|
||||
"""
|
||||
self.iochannel.sendData(string)
|
||||
logger.info("Starting plugin.")
|
||||
|
||||
def handleLoginRequest(self, user, legacyName, password):
|
||||
self.handleConnected(user)
|
||||
logger.info("Added Echo Buddy")
|
||||
self.handleBuddyChanged(user, "echo", "Echo", [], protocol_pb2.STATUS_ONLINE)
|
||||
|
||||
def handleLogoutRequest(self, user, legacyName):
|
||||
pass
|
||||
|
||||
def handleMessageSendRequest(self, user, legacyName, message, xhtml = ""):
|
||||
logger.info("Message sent from " + user + ' to ' + legacyName)
|
||||
if(legacyName == "echo"):
|
||||
logger.info("Message Echoed: " + message)
|
||||
self.handleMessage(user, legacyName, message)
|
||||
|
||||
def handleBuddyUpdatedRequest(self, user, buddyName, alias, groups):
|
||||
logger.info("Added Buddy " + buddyName)
|
||||
self.handleBuddyChanged(user, buddyName, alias, groups, protocol_pb2.STATUS_ONLINE)
|
||||
|
||||
def handleBuddyRemovedRequest(self, user, buddyName, groups):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class IOChannel(asyncore.dispatcher):
|
||||
def __init__(self, host, port, readCallBack):
|
||||
asyncore.dispatcher.__init__(self)
|
||||
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.connect((host, port))
|
||||
self.handleReceivedData = readCallBack
|
||||
self.send_buffer = ""
|
||||
|
||||
def sendData(self, data):
|
||||
self.send_buffer += data
|
||||
|
||||
def handle_connect(self):
|
||||
pass
|
||||
|
||||
def handle_close(self):
|
||||
self.close()
|
||||
|
||||
def handle_read(self):
|
||||
data = self.recv(65536)
|
||||
self.handleReceivedData(data)
|
||||
|
||||
def handle_write(self):
|
||||
sent = self.send(self.send_buffer)
|
||||
self.send_buffer = self.send_buffer[sent:]
|
||||
|
||||
def writable(self):
|
||||
return (len(self.send_buffer) > 0)
|
||||
|
||||
def readable(self):
|
||||
return True
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--host', type=str, required=True)
|
||||
parser.add_argument('--port', type=int, required=True)
|
||||
parser.add_argument('config_file', type=str)
|
||||
|
||||
args = parser.parse_args()
|
||||
io = IOChannel(args.host, args.port, handleTransportData)
|
||||
np = SpectrumPlugin(io)
|
||||
asyncore.loop()
|
|
@ -1,15 +0,0 @@
|
|||
include_directories (${libtransport_SOURCE_DIR}/backends/twitter/libtwitcurl)
|
||||
FILE(GLOB SRC *.cpp libtwitcurl/*.cpp Requests/*.cpp)
|
||||
add_executable(spectrum2_twitter_backend ${SRC})
|
||||
|
||||
find_package(CURL)
|
||||
|
||||
if(CURL_FOUND)
|
||||
message(STATUS "Using curl ${CURL_VERSION_STRING}: ${CURL_INCLUDE_DIRS} ${CURL_LIBRARIES}")
|
||||
include_directories (${CURL_INCLUDE_DIRS})
|
||||
target_link_libraries(spectrum2_twitter_backend transport ${CURL_LIBRARIES} ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
|
||||
else()
|
||||
message(FATAL_ERROR "curl not found")
|
||||
endif()
|
||||
|
||||
INSTALL(TARGETS spectrum2_twitter_backend RUNTIME DESTINATION bin)
|
|
@ -1,72 +0,0 @@
|
|||
#include "HTTPRequest.h"
|
||||
DEFINE_LOGGER(logger, "HTTPRequest")
|
||||
|
||||
bool HTTPRequest::init()
|
||||
{
|
||||
curlhandle = curl_easy_init();
|
||||
if(curlhandle) {
|
||||
curlhandle = curl_easy_init();
|
||||
curl_easy_setopt(curlhandle, CURLOPT_PROXY, NULL);
|
||||
curl_easy_setopt(curlhandle, CURLOPT_PROXYUSERPWD, NULL);
|
||||
curl_easy_setopt(curlhandle, CURLOPT_PROXYAUTH, (long)CURLAUTH_ANY);
|
||||
return true;
|
||||
}
|
||||
LOG4CXX_ERROR(logger, "Couldn't Initialize curl!");
|
||||
return false;
|
||||
}
|
||||
|
||||
void HTTPRequest::setProxy(std::string IP, std::string port, std::string username, std::string password)
|
||||
{
|
||||
if(curlhandle) {
|
||||
std::string proxyIpPort = IP + ":" + port;
|
||||
curl_easy_setopt(curlhandle, CURLOPT_PROXY, proxyIpPort.c_str());
|
||||
if(username.length() && password.length()) {
|
||||
std::string proxyUserPass = username + ":" + password;
|
||||
curl_easy_setopt(curlhandle, CURLOPT_PROXYUSERPWD, proxyUserPass.c_str());
|
||||
}
|
||||
} else {
|
||||
LOG4CXX_ERROR(logger, "Trying to set proxy while CURL isn't initialized");
|
||||
}
|
||||
}
|
||||
|
||||
int HTTPRequest::curlCallBack(char* data, size_t size, size_t nmemb, HTTPRequest* obj)
|
||||
{
|
||||
int writtenSize = 0;
|
||||
if(obj && data) {
|
||||
obj->callbackdata.append(data, size*nmemb);
|
||||
writtenSize = (int)(size*nmemb);
|
||||
}
|
||||
return writtenSize;
|
||||
}
|
||||
|
||||
|
||||
bool HTTPRequest::GET(std::string url, std::string &data)
|
||||
{
|
||||
if(curlhandle) {
|
||||
curl_easy_setopt(curlhandle, CURLOPT_CUSTOMREQUEST, NULL);
|
||||
curl_easy_setopt(curlhandle, CURLOPT_ENCODING, "");
|
||||
|
||||
data = "";
|
||||
callbackdata = "";
|
||||
memset(curl_errorbuffer, 0, 1024);
|
||||
|
||||
curl_easy_setopt(curlhandle, CURLOPT_ERRORBUFFER, curl_errorbuffer);
|
||||
curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, curlCallBack);
|
||||
curl_easy_setopt(curlhandle, CURLOPT_WRITEDATA, this);
|
||||
|
||||
/* Set http request and url */
|
||||
curl_easy_setopt(curlhandle, CURLOPT_HTTPGET, 1);
|
||||
// curl_easy_setopt(curlhandle, CURLOPT_VERBOSE, 1);
|
||||
curl_easy_setopt(curlhandle, CURLOPT_URL, url.c_str());
|
||||
|
||||
/* Send http request and return status*/
|
||||
if(CURLE_OK == curl_easy_perform(curlhandle)) {
|
||||
data = callbackdata;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
LOG4CXX_ERROR(logger, "CURL not initialized!");
|
||||
strcpy(curl_errorbuffer, "CURL not initialized!");
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
#ifndef HTTPREQ_H
|
||||
#define HTTPREQ_H
|
||||
|
||||
#include "curl/curl.h"
|
||||
#include "transport/Logging.h"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string.h>
|
||||
|
||||
class HTTPRequest
|
||||
{
|
||||
CURL *curlhandle;
|
||||
char curl_errorbuffer[1024];
|
||||
std::string error;
|
||||
std::string callbackdata;
|
||||
|
||||
static int curlCallBack(char* data, size_t size, size_t nmemb, HTTPRequest *obj);
|
||||
|
||||
public:
|
||||
HTTPRequest() {
|
||||
curlhandle = NULL;
|
||||
}
|
||||
|
||||
~HTTPRequest() {
|
||||
if(curlhandle) {
|
||||
curl_easy_cleanup(curlhandle);
|
||||
curlhandle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool init();
|
||||
void setProxy(std::string, std::string, std::string, std::string);
|
||||
bool GET(std::string, std::string &);
|
||||
std::string getCurlError() {return std::string(curl_errorbuffer);}
|
||||
};
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue